aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2017-02-03 13:30:27 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2017-02-03 13:30:27 -0500
commit2cb54ce9ee92ae627bc1cef8bea236905910a86d (patch)
tree8cf38943b5acd64b25621d6eab72591c6a65ba1e
parent29905b52fad0854351f57bab867647e4982285bf (diff)
parent4b9eee96fcb361a5e16a8d2619825e8a048f81f7 (diff)
Merge branch 'modversions' (modversions fixes for powerpc from Ard)
Merge kcrctab entry fixes from Ard Biesheuvel: "This is a followup to [0] 'modversions: redefine kcrctab entries as relative CRC pointers', but since relative CRC pointers do not work in modules, and are actually only needed by powerpc with CONFIG_RELOCATABLE=y, I have made it a Kconfig selectable feature instead. First it introduces the MODULE_REL_CRCS Kconfig symbol, and adds the kbuild handling of it, i.e., modpost, genksyms and kallsyms. Then it switches all architectures to 32-bit CRC entries in kcrctab, where all architectures except powerpc with CONFIG_RELOCATABLE=y use absolute ELF symbol references as before" [0] http://marc.info/?l=linux-arch&m=148493613415294&w=2 * emailed patches from Ard Biesheuvel: module: unify absolute krctab definitions for 32-bit and 64-bit modversions: treat symbol CRCs as 32 bit quantities kbuild: modversions: add infrastructure for emitting relative CRCs
-rw-r--r--arch/powerpc/Kconfig1
-rw-r--r--arch/powerpc/include/asm/module.h4
-rw-r--r--arch/powerpc/kernel/module_64.c8
-rw-r--r--include/asm-generic/export.h11
-rw-r--r--include/linux/export.h17
-rw-r--r--include/linux/module.h14
-rw-r--r--init/Kconfig4
-rw-r--r--kernel/module.c53
-rw-r--r--scripts/Makefile.build2
-rw-r--r--scripts/genksyms/genksyms.c19
-rw-r--r--scripts/kallsyms.c12
-rw-r--r--scripts/mod/modpost.c10
12 files changed, 93 insertions, 62 deletions
diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig
index a8ee573fe610..db8a1ef6bfaf 100644
--- a/arch/powerpc/Kconfig
+++ b/arch/powerpc/Kconfig
@@ -484,6 +484,7 @@ config RELOCATABLE
484 bool "Build a relocatable kernel" 484 bool "Build a relocatable kernel"
485 depends on (PPC64 && !COMPILE_TEST) || (FLATMEM && (44x || FSL_BOOKE)) 485 depends on (PPC64 && !COMPILE_TEST) || (FLATMEM && (44x || FSL_BOOKE))
486 select NONSTATIC_KERNEL 486 select NONSTATIC_KERNEL
487 select MODULE_REL_CRCS if MODVERSIONS
487 help 488 help
488 This builds a kernel image that is capable of running at the 489 This builds a kernel image that is capable of running at the
489 location the kernel is loaded at. For ppc32, there is no any 490 location the kernel is loaded at. For ppc32, there is no any
diff --git a/arch/powerpc/include/asm/module.h b/arch/powerpc/include/asm/module.h
index cc12c61ef315..53885512b8d3 100644
--- a/arch/powerpc/include/asm/module.h
+++ b/arch/powerpc/include/asm/module.h
@@ -90,9 +90,5 @@ static inline int module_finalize_ftrace(struct module *mod, const Elf_Shdr *sec
90} 90}
91#endif 91#endif
92 92
93#if defined(CONFIG_MODVERSIONS) && defined(CONFIG_PPC64)
94#define ARCH_RELOCATES_KCRCTAB
95#define reloc_start PHYSICAL_START
96#endif
97#endif /* __KERNEL__ */ 93#endif /* __KERNEL__ */
98#endif /* _ASM_POWERPC_MODULE_H */ 94#endif /* _ASM_POWERPC_MODULE_H */
diff --git a/arch/powerpc/kernel/module_64.c b/arch/powerpc/kernel/module_64.c
index bb1807184bad..0b0f89685b67 100644
--- a/arch/powerpc/kernel/module_64.c
+++ b/arch/powerpc/kernel/module_64.c
@@ -286,14 +286,6 @@ static void dedotify_versions(struct modversion_info *vers,
286 for (end = (void *)vers + size; vers < end; vers++) 286 for (end = (void *)vers + size; vers < end; vers++)
287 if (vers->name[0] == '.') { 287 if (vers->name[0] == '.') {
288 memmove(vers->name, vers->name+1, strlen(vers->name)); 288 memmove(vers->name, vers->name+1, strlen(vers->name));
289#ifdef ARCH_RELOCATES_KCRCTAB
290 /* The TOC symbol has no CRC computed. To avoid CRC
291 * check failing, we must force it to the expected
292 * value (see CRC check in module.c).
293 */
294 if (!strcmp(vers->name, "TOC."))
295 vers->crc = -(unsigned long)reloc_start;
296#endif
297 } 289 }
298} 290}
299 291
diff --git a/include/asm-generic/export.h b/include/asm-generic/export.h
index 63554e9f6e0c..719db1968d81 100644
--- a/include/asm-generic/export.h
+++ b/include/asm-generic/export.h
@@ -9,18 +9,15 @@
9#ifndef KSYM_ALIGN 9#ifndef KSYM_ALIGN
10#define KSYM_ALIGN 8 10#define KSYM_ALIGN 8
11#endif 11#endif
12#ifndef KCRC_ALIGN
13#define KCRC_ALIGN 8
14#endif
15#else 12#else
16#define __put .long 13#define __put .long
17#ifndef KSYM_ALIGN 14#ifndef KSYM_ALIGN
18#define KSYM_ALIGN 4 15#define KSYM_ALIGN 4
19#endif 16#endif
17#endif
20#ifndef KCRC_ALIGN 18#ifndef KCRC_ALIGN
21#define KCRC_ALIGN 4 19#define KCRC_ALIGN 4
22#endif 20#endif
23#endif
24 21
25#ifdef CONFIG_HAVE_UNDERSCORE_SYMBOL_PREFIX 22#ifdef CONFIG_HAVE_UNDERSCORE_SYMBOL_PREFIX
26#define KSYM(name) _##name 23#define KSYM(name) _##name
@@ -52,7 +49,11 @@ KSYM(__kstrtab_\name):
52 .section ___kcrctab\sec+\name,"a" 49 .section ___kcrctab\sec+\name,"a"
53 .balign KCRC_ALIGN 50 .balign KCRC_ALIGN
54KSYM(__kcrctab_\name): 51KSYM(__kcrctab_\name):
55 __put KSYM(__crc_\name) 52#if defined(CONFIG_MODULE_REL_CRCS)
53 .long KSYM(__crc_\name) - .
54#else
55 .long KSYM(__crc_\name)
56#endif
56 .weak KSYM(__crc_\name) 57 .weak KSYM(__crc_\name)
57 .previous 58 .previous
58#endif 59#endif
diff --git a/include/linux/export.h b/include/linux/export.h
index 2a0f61fbc731..1a1dfdb2a5c6 100644
--- a/include/linux/export.h
+++ b/include/linux/export.h
@@ -43,12 +43,19 @@ extern struct module __this_module;
43#ifdef CONFIG_MODVERSIONS 43#ifdef CONFIG_MODVERSIONS
44/* Mark the CRC weak since genksyms apparently decides not to 44/* Mark the CRC weak since genksyms apparently decides not to
45 * generate a checksums for some symbols */ 45 * generate a checksums for some symbols */
46#if defined(CONFIG_MODULE_REL_CRCS)
46#define __CRC_SYMBOL(sym, sec) \ 47#define __CRC_SYMBOL(sym, sec) \
47 extern __visible void *__crc_##sym __attribute__((weak)); \ 48 asm(" .section \"___kcrctab" sec "+" #sym "\", \"a\" \n" \
48 static const unsigned long __kcrctab_##sym \ 49 " .weak " VMLINUX_SYMBOL_STR(__crc_##sym) " \n" \
49 __used \ 50 " .long " VMLINUX_SYMBOL_STR(__crc_##sym) " - . \n" \
50 __attribute__((section("___kcrctab" sec "+" #sym), used)) \ 51 " .previous \n");
51 = (unsigned long) &__crc_##sym; 52#else
53#define __CRC_SYMBOL(sym, sec) \
54 asm(" .section \"___kcrctab" sec "+" #sym "\", \"a\" \n" \
55 " .weak " VMLINUX_SYMBOL_STR(__crc_##sym) " \n" \
56 " .long " VMLINUX_SYMBOL_STR(__crc_##sym) " \n" \
57 " .previous \n");
58#endif
52#else 59#else
53#define __CRC_SYMBOL(sym, sec) 60#define __CRC_SYMBOL(sym, sec)
54#endif 61#endif
diff --git a/include/linux/module.h b/include/linux/module.h
index 7c84273d60b9..cc7cba219b20 100644
--- a/include/linux/module.h
+++ b/include/linux/module.h
@@ -346,7 +346,7 @@ struct module {
346 346
347 /* Exported symbols */ 347 /* Exported symbols */
348 const struct kernel_symbol *syms; 348 const struct kernel_symbol *syms;
349 const unsigned long *crcs; 349 const s32 *crcs;
350 unsigned int num_syms; 350 unsigned int num_syms;
351 351
352 /* Kernel parameters. */ 352 /* Kernel parameters. */
@@ -359,18 +359,18 @@ struct module {
359 /* GPL-only exported symbols. */ 359 /* GPL-only exported symbols. */
360 unsigned int num_gpl_syms; 360 unsigned int num_gpl_syms;
361 const struct kernel_symbol *gpl_syms; 361 const struct kernel_symbol *gpl_syms;
362 const unsigned long *gpl_crcs; 362 const s32 *gpl_crcs;
363 363
364#ifdef CONFIG_UNUSED_SYMBOLS 364#ifdef CONFIG_UNUSED_SYMBOLS
365 /* unused exported symbols. */ 365 /* unused exported symbols. */
366 const struct kernel_symbol *unused_syms; 366 const struct kernel_symbol *unused_syms;
367 const unsigned long *unused_crcs; 367 const s32 *unused_crcs;
368 unsigned int num_unused_syms; 368 unsigned int num_unused_syms;
369 369
370 /* GPL-only, unused exported symbols. */ 370 /* GPL-only, unused exported symbols. */
371 unsigned int num_unused_gpl_syms; 371 unsigned int num_unused_gpl_syms;
372 const struct kernel_symbol *unused_gpl_syms; 372 const struct kernel_symbol *unused_gpl_syms;
373 const unsigned long *unused_gpl_crcs; 373 const s32 *unused_gpl_crcs;
374#endif 374#endif
375 375
376#ifdef CONFIG_MODULE_SIG 376#ifdef CONFIG_MODULE_SIG
@@ -382,7 +382,7 @@ struct module {
382 382
383 /* symbols that will be GPL-only in the near future. */ 383 /* symbols that will be GPL-only in the near future. */
384 const struct kernel_symbol *gpl_future_syms; 384 const struct kernel_symbol *gpl_future_syms;
385 const unsigned long *gpl_future_crcs; 385 const s32 *gpl_future_crcs;
386 unsigned int num_gpl_future_syms; 386 unsigned int num_gpl_future_syms;
387 387
388 /* Exception table */ 388 /* Exception table */
@@ -523,7 +523,7 @@ struct module *find_module(const char *name);
523 523
524struct symsearch { 524struct symsearch {
525 const struct kernel_symbol *start, *stop; 525 const struct kernel_symbol *start, *stop;
526 const unsigned long *crcs; 526 const s32 *crcs;
527 enum { 527 enum {
528 NOT_GPL_ONLY, 528 NOT_GPL_ONLY,
529 GPL_ONLY, 529 GPL_ONLY,
@@ -539,7 +539,7 @@ struct symsearch {
539 */ 539 */
540const struct kernel_symbol *find_symbol(const char *name, 540const struct kernel_symbol *find_symbol(const char *name,
541 struct module **owner, 541 struct module **owner,
542 const unsigned long **crc, 542 const s32 **crc,
543 bool gplok, 543 bool gplok,
544 bool warn); 544 bool warn);
545 545
diff --git a/init/Kconfig b/init/Kconfig
index e1a937348a3e..4dd8bd232a1d 100644
--- a/init/Kconfig
+++ b/init/Kconfig
@@ -1987,6 +1987,10 @@ config MODVERSIONS
1987 make them incompatible with the kernel you are running. If 1987 make them incompatible with the kernel you are running. If
1988 unsure, say N. 1988 unsure, say N.
1989 1989
1990config MODULE_REL_CRCS
1991 bool
1992 depends on MODVERSIONS
1993
1990config MODULE_SRCVERSION_ALL 1994config MODULE_SRCVERSION_ALL
1991 bool "Source checksum for all modules" 1995 bool "Source checksum for all modules"
1992 help 1996 help
diff --git a/kernel/module.c b/kernel/module.c
index 38d4270925d4..3d8f126208e3 100644
--- a/kernel/module.c
+++ b/kernel/module.c
@@ -389,16 +389,16 @@ extern const struct kernel_symbol __start___ksymtab_gpl[];
389extern const struct kernel_symbol __stop___ksymtab_gpl[]; 389extern const struct kernel_symbol __stop___ksymtab_gpl[];
390extern const struct kernel_symbol __start___ksymtab_gpl_future[]; 390extern const struct kernel_symbol __start___ksymtab_gpl_future[];
391extern const struct kernel_symbol __stop___ksymtab_gpl_future[]; 391extern const struct kernel_symbol __stop___ksymtab_gpl_future[];
392extern const unsigned long __start___kcrctab[]; 392extern const s32 __start___kcrctab[];
393extern const unsigned long __start___kcrctab_gpl[]; 393extern const s32 __start___kcrctab_gpl[];
394extern const unsigned long __start___kcrctab_gpl_future[]; 394extern const s32 __start___kcrctab_gpl_future[];
395#ifdef CONFIG_UNUSED_SYMBOLS 395#ifdef CONFIG_UNUSED_SYMBOLS
396extern const struct kernel_symbol __start___ksymtab_unused[]; 396extern const struct kernel_symbol __start___ksymtab_unused[];
397extern const struct kernel_symbol __stop___ksymtab_unused[]; 397extern const struct kernel_symbol __stop___ksymtab_unused[];
398extern const struct kernel_symbol __start___ksymtab_unused_gpl[]; 398extern const struct kernel_symbol __start___ksymtab_unused_gpl[];
399extern const struct kernel_symbol __stop___ksymtab_unused_gpl[]; 399extern const struct kernel_symbol __stop___ksymtab_unused_gpl[];
400extern const unsigned long __start___kcrctab_unused[]; 400extern const s32 __start___kcrctab_unused[];
401extern const unsigned long __start___kcrctab_unused_gpl[]; 401extern const s32 __start___kcrctab_unused_gpl[];
402#endif 402#endif
403 403
404#ifndef CONFIG_MODVERSIONS 404#ifndef CONFIG_MODVERSIONS
@@ -497,7 +497,7 @@ struct find_symbol_arg {
497 497
498 /* Output */ 498 /* Output */
499 struct module *owner; 499 struct module *owner;
500 const unsigned long *crc; 500 const s32 *crc;
501 const struct kernel_symbol *sym; 501 const struct kernel_symbol *sym;
502}; 502};
503 503
@@ -563,7 +563,7 @@ static bool find_symbol_in_section(const struct symsearch *syms,
563 * (optional) module which owns it. Needs preempt disabled or module_mutex. */ 563 * (optional) module which owns it. Needs preempt disabled or module_mutex. */
564const struct kernel_symbol *find_symbol(const char *name, 564const struct kernel_symbol *find_symbol(const char *name,
565 struct module **owner, 565 struct module **owner,
566 const unsigned long **crc, 566 const s32 **crc,
567 bool gplok, 567 bool gplok,
568 bool warn) 568 bool warn)
569{ 569{
@@ -1249,23 +1249,17 @@ static int try_to_force_load(struct module *mod, const char *reason)
1249} 1249}
1250 1250
1251#ifdef CONFIG_MODVERSIONS 1251#ifdef CONFIG_MODVERSIONS
1252/* If the arch applies (non-zero) relocations to kernel kcrctab, unapply it. */ 1252
1253static unsigned long maybe_relocated(unsigned long crc, 1253static u32 resolve_rel_crc(const s32 *crc)
1254 const struct module *crc_owner)
1255{ 1254{
1256#ifdef ARCH_RELOCATES_KCRCTAB 1255 return *(u32 *)((void *)crc + *crc);
1257 if (crc_owner == NULL)
1258 return crc - (unsigned long)reloc_start;
1259#endif
1260 return crc;
1261} 1256}
1262 1257
1263static int check_version(Elf_Shdr *sechdrs, 1258static int check_version(Elf_Shdr *sechdrs,
1264 unsigned int versindex, 1259 unsigned int versindex,
1265 const char *symname, 1260 const char *symname,
1266 struct module *mod, 1261 struct module *mod,
1267 const unsigned long *crc, 1262 const s32 *crc)
1268 const struct module *crc_owner)
1269{ 1263{
1270 unsigned int i, num_versions; 1264 unsigned int i, num_versions;
1271 struct modversion_info *versions; 1265 struct modversion_info *versions;
@@ -1283,13 +1277,19 @@ static int check_version(Elf_Shdr *sechdrs,
1283 / sizeof(struct modversion_info); 1277 / sizeof(struct modversion_info);
1284 1278
1285 for (i = 0; i < num_versions; i++) { 1279 for (i = 0; i < num_versions; i++) {
1280 u32 crcval;
1281
1286 if (strcmp(versions[i].name, symname) != 0) 1282 if (strcmp(versions[i].name, symname) != 0)
1287 continue; 1283 continue;
1288 1284
1289 if (versions[i].crc == maybe_relocated(*crc, crc_owner)) 1285 if (IS_ENABLED(CONFIG_MODULE_REL_CRCS))
1286 crcval = resolve_rel_crc(crc);
1287 else
1288 crcval = *crc;
1289 if (versions[i].crc == crcval)
1290 return 1; 1290 return 1;
1291 pr_debug("Found checksum %lX vs module %lX\n", 1291 pr_debug("Found checksum %X vs module %lX\n",
1292 maybe_relocated(*crc, crc_owner), versions[i].crc); 1292 crcval, versions[i].crc);
1293 goto bad_version; 1293 goto bad_version;
1294 } 1294 }
1295 1295
@@ -1307,7 +1307,7 @@ static inline int check_modstruct_version(Elf_Shdr *sechdrs,
1307 unsigned int versindex, 1307 unsigned int versindex,
1308 struct module *mod) 1308 struct module *mod)
1309{ 1309{
1310 const unsigned long *crc; 1310 const s32 *crc;
1311 1311
1312 /* 1312 /*
1313 * Since this should be found in kernel (which can't be removed), no 1313 * Since this should be found in kernel (which can't be removed), no
@@ -1321,8 +1321,7 @@ static inline int check_modstruct_version(Elf_Shdr *sechdrs,
1321 } 1321 }
1322 preempt_enable(); 1322 preempt_enable();
1323 return check_version(sechdrs, versindex, 1323 return check_version(sechdrs, versindex,
1324 VMLINUX_SYMBOL_STR(module_layout), mod, crc, 1324 VMLINUX_SYMBOL_STR(module_layout), mod, crc);
1325 NULL);
1326} 1325}
1327 1326
1328/* First part is kernel version, which we ignore if module has crcs. */ 1327/* First part is kernel version, which we ignore if module has crcs. */
@@ -1340,8 +1339,7 @@ static inline int check_version(Elf_Shdr *sechdrs,
1340 unsigned int versindex, 1339 unsigned int versindex,
1341 const char *symname, 1340 const char *symname,
1342 struct module *mod, 1341 struct module *mod,
1343 const unsigned long *crc, 1342 const s32 *crc)
1344 const struct module *crc_owner)
1345{ 1343{
1346 return 1; 1344 return 1;
1347} 1345}
@@ -1368,7 +1366,7 @@ static const struct kernel_symbol *resolve_symbol(struct module *mod,
1368{ 1366{
1369 struct module *owner; 1367 struct module *owner;
1370 const struct kernel_symbol *sym; 1368 const struct kernel_symbol *sym;
1371 const unsigned long *crc; 1369 const s32 *crc;
1372 int err; 1370 int err;
1373 1371
1374 /* 1372 /*
@@ -1383,8 +1381,7 @@ static const struct kernel_symbol *resolve_symbol(struct module *mod,
1383 if (!sym) 1381 if (!sym)
1384 goto unlock; 1382 goto unlock;
1385 1383
1386 if (!check_version(info->sechdrs, info->index.vers, name, mod, crc, 1384 if (!check_version(info->sechdrs, info->index.vers, name, mod, crc)) {
1387 owner)) {
1388 sym = ERR_PTR(-EINVAL); 1385 sym = ERR_PTR(-EINVAL);
1389 goto getname; 1386 goto getname;
1390 } 1387 }
diff --git a/scripts/Makefile.build b/scripts/Makefile.build
index eadcd4d359d9..d883116ebaa4 100644
--- a/scripts/Makefile.build
+++ b/scripts/Makefile.build
@@ -164,6 +164,7 @@ cmd_gensymtypes_c = \
164 $(CPP) -D__GENKSYMS__ $(c_flags) $< | \ 164 $(CPP) -D__GENKSYMS__ $(c_flags) $< | \
165 $(GENKSYMS) $(if $(1), -T $(2)) \ 165 $(GENKSYMS) $(if $(1), -T $(2)) \
166 $(patsubst y,-s _,$(CONFIG_HAVE_UNDERSCORE_SYMBOL_PREFIX)) \ 166 $(patsubst y,-s _,$(CONFIG_HAVE_UNDERSCORE_SYMBOL_PREFIX)) \
167 $(patsubst y,-R,$(CONFIG_MODULE_REL_CRCS)) \
167 $(if $(KBUILD_PRESERVE),-p) \ 168 $(if $(KBUILD_PRESERVE),-p) \
168 -r $(firstword $(wildcard $(2:.symtypes=.symref) /dev/null)) 169 -r $(firstword $(wildcard $(2:.symtypes=.symref) /dev/null))
169 170
@@ -337,6 +338,7 @@ cmd_gensymtypes_S = \
337 $(CPP) -D__GENKSYMS__ $(c_flags) -xc - | \ 338 $(CPP) -D__GENKSYMS__ $(c_flags) -xc - | \
338 $(GENKSYMS) $(if $(1), -T $(2)) \ 339 $(GENKSYMS) $(if $(1), -T $(2)) \
339 $(patsubst y,-s _,$(CONFIG_HAVE_UNDERSCORE_SYMBOL_PREFIX)) \ 340 $(patsubst y,-s _,$(CONFIG_HAVE_UNDERSCORE_SYMBOL_PREFIX)) \
341 $(patsubst y,-R,$(CONFIG_MODULE_REL_CRCS)) \
340 $(if $(KBUILD_PRESERVE),-p) \ 342 $(if $(KBUILD_PRESERVE),-p) \
341 -r $(firstword $(wildcard $(2:.symtypes=.symref) /dev/null)) 343 -r $(firstword $(wildcard $(2:.symtypes=.symref) /dev/null))
342 344
diff --git a/scripts/genksyms/genksyms.c b/scripts/genksyms/genksyms.c
index 06121ce524a7..c9235d8340f1 100644
--- a/scripts/genksyms/genksyms.c
+++ b/scripts/genksyms/genksyms.c
@@ -44,7 +44,7 @@ char *cur_filename, *source_file;
44int in_source_file; 44int in_source_file;
45 45
46static int flag_debug, flag_dump_defs, flag_reference, flag_dump_types, 46static int flag_debug, flag_dump_defs, flag_reference, flag_dump_types,
47 flag_preserve, flag_warnings; 47 flag_preserve, flag_warnings, flag_rel_crcs;
48static const char *mod_prefix = ""; 48static const char *mod_prefix = "";
49 49
50static int errors; 50static int errors;
@@ -693,7 +693,10 @@ void export_symbol(const char *name)
693 fputs(">\n", debugfile); 693 fputs(">\n", debugfile);
694 694
695 /* Used as a linker script. */ 695 /* Used as a linker script. */
696 printf("%s__crc_%s = 0x%08lx ;\n", mod_prefix, name, crc); 696 printf(!flag_rel_crcs ? "%s__crc_%s = 0x%08lx;\n" :
697 "SECTIONS { .rodata : ALIGN(4) { "
698 "%s__crc_%s = .; LONG(0x%08lx); } }\n",
699 mod_prefix, name, crc);
697 } 700 }
698} 701}
699 702
@@ -730,7 +733,7 @@ void error_with_pos(const char *fmt, ...)
730 733
731static void genksyms_usage(void) 734static void genksyms_usage(void)
732{ 735{
733 fputs("Usage:\n" "genksyms [-adDTwqhV] > /path/to/.tmp_obj.ver\n" "\n" 736 fputs("Usage:\n" "genksyms [-adDTwqhVR] > /path/to/.tmp_obj.ver\n" "\n"
734#ifdef __GNU_LIBRARY__ 737#ifdef __GNU_LIBRARY__
735 " -s, --symbol-prefix Select symbol prefix\n" 738 " -s, --symbol-prefix Select symbol prefix\n"
736 " -d, --debug Increment the debug level (repeatable)\n" 739 " -d, --debug Increment the debug level (repeatable)\n"
@@ -742,6 +745,7 @@ static void genksyms_usage(void)
742 " -q, --quiet Disable warnings (default)\n" 745 " -q, --quiet Disable warnings (default)\n"
743 " -h, --help Print this message\n" 746 " -h, --help Print this message\n"
744 " -V, --version Print the release version\n" 747 " -V, --version Print the release version\n"
748 " -R, --relative-crc Emit section relative symbol CRCs\n"
745#else /* __GNU_LIBRARY__ */ 749#else /* __GNU_LIBRARY__ */
746 " -s Select symbol prefix\n" 750 " -s Select symbol prefix\n"
747 " -d Increment the debug level (repeatable)\n" 751 " -d Increment the debug level (repeatable)\n"
@@ -753,6 +757,7 @@ static void genksyms_usage(void)
753 " -q Disable warnings (default)\n" 757 " -q Disable warnings (default)\n"
754 " -h Print this message\n" 758 " -h Print this message\n"
755 " -V Print the release version\n" 759 " -V Print the release version\n"
760 " -R Emit section relative symbol CRCs\n"
756#endif /* __GNU_LIBRARY__ */ 761#endif /* __GNU_LIBRARY__ */
757 , stderr); 762 , stderr);
758} 763}
@@ -774,13 +779,14 @@ int main(int argc, char **argv)
774 {"preserve", 0, 0, 'p'}, 779 {"preserve", 0, 0, 'p'},
775 {"version", 0, 0, 'V'}, 780 {"version", 0, 0, 'V'},
776 {"help", 0, 0, 'h'}, 781 {"help", 0, 0, 'h'},
782 {"relative-crc", 0, 0, 'R'},
777 {0, 0, 0, 0} 783 {0, 0, 0, 0}
778 }; 784 };
779 785
780 while ((o = getopt_long(argc, argv, "s:dwqVDr:T:ph", 786 while ((o = getopt_long(argc, argv, "s:dwqVDr:T:phR",
781 &long_opts[0], NULL)) != EOF) 787 &long_opts[0], NULL)) != EOF)
782#else /* __GNU_LIBRARY__ */ 788#else /* __GNU_LIBRARY__ */
783 while ((o = getopt(argc, argv, "s:dwqVDr:T:ph")) != EOF) 789 while ((o = getopt(argc, argv, "s:dwqVDr:T:phR")) != EOF)
784#endif /* __GNU_LIBRARY__ */ 790#endif /* __GNU_LIBRARY__ */
785 switch (o) { 791 switch (o) {
786 case 's': 792 case 's':
@@ -823,6 +829,9 @@ int main(int argc, char **argv)
823 case 'h': 829 case 'h':
824 genksyms_usage(); 830 genksyms_usage();
825 return 0; 831 return 0;
832 case 'R':
833 flag_rel_crcs = 1;
834 break;
826 default: 835 default:
827 genksyms_usage(); 836 genksyms_usage();
828 return 1; 837 return 1;
diff --git a/scripts/kallsyms.c b/scripts/kallsyms.c
index 299b92ca1ae0..5d554419170b 100644
--- a/scripts/kallsyms.c
+++ b/scripts/kallsyms.c
@@ -219,6 +219,10 @@ static int symbol_valid(struct sym_entry *s)
219 "_SDA2_BASE_", /* ppc */ 219 "_SDA2_BASE_", /* ppc */
220 NULL }; 220 NULL };
221 221
222 static char *special_prefixes[] = {
223 "__crc_", /* modversions */
224 NULL };
225
222 static char *special_suffixes[] = { 226 static char *special_suffixes[] = {
223 "_veneer", /* arm */ 227 "_veneer", /* arm */
224 "_from_arm", /* arm */ 228 "_from_arm", /* arm */
@@ -259,6 +263,14 @@ static int symbol_valid(struct sym_entry *s)
259 if (strcmp(sym_name, special_symbols[i]) == 0) 263 if (strcmp(sym_name, special_symbols[i]) == 0)
260 return 0; 264 return 0;
261 265
266 for (i = 0; special_prefixes[i]; i++) {
267 int l = strlen(special_prefixes[i]);
268
269 if (l <= strlen(sym_name) &&
270 strncmp(sym_name, special_prefixes[i], l) == 0)
271 return 0;
272 }
273
262 for (i = 0; special_suffixes[i]; i++) { 274 for (i = 0; special_suffixes[i]; i++) {
263 int l = strlen(sym_name) - strlen(special_suffixes[i]); 275 int l = strlen(sym_name) - strlen(special_suffixes[i]);
264 276
diff --git a/scripts/mod/modpost.c b/scripts/mod/modpost.c
index 29c89a6bad3d..4dedd0d3d3a7 100644
--- a/scripts/mod/modpost.c
+++ b/scripts/mod/modpost.c
@@ -621,6 +621,16 @@ static void handle_modversions(struct module *mod, struct elf_info *info,
621 if (strncmp(symname, CRC_PFX, strlen(CRC_PFX)) == 0) { 621 if (strncmp(symname, CRC_PFX, strlen(CRC_PFX)) == 0) {
622 is_crc = true; 622 is_crc = true;
623 crc = (unsigned int) sym->st_value; 623 crc = (unsigned int) sym->st_value;
624 if (sym->st_shndx != SHN_UNDEF && sym->st_shndx != SHN_ABS) {
625 unsigned int *crcp;
626
627 /* symbol points to the CRC in the ELF object */
628 crcp = (void *)info->hdr + sym->st_value +
629 info->sechdrs[sym->st_shndx].sh_offset -
630 (info->hdr->e_type != ET_REL ?
631 info->sechdrs[sym->st_shndx].sh_addr : 0);
632 crc = *crcp;
633 }
624 sym_update_crc(symname + strlen(CRC_PFX), mod, crc, 634 sym_update_crc(symname + strlen(CRC_PFX), mod, crc,
625 export); 635 export);
626 } 636 }