diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2017-02-03 13:30:27 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2017-02-03 13:30:27 -0500 |
commit | 2cb54ce9ee92ae627bc1cef8bea236905910a86d (patch) | |
tree | 8cf38943b5acd64b25621d6eab72591c6a65ba1e | |
parent | 29905b52fad0854351f57bab867647e4982285bf (diff) | |
parent | 4b9eee96fcb361a5e16a8d2619825e8a048f81f7 (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/Kconfig | 1 | ||||
-rw-r--r-- | arch/powerpc/include/asm/module.h | 4 | ||||
-rw-r--r-- | arch/powerpc/kernel/module_64.c | 8 | ||||
-rw-r--r-- | include/asm-generic/export.h | 11 | ||||
-rw-r--r-- | include/linux/export.h | 17 | ||||
-rw-r--r-- | include/linux/module.h | 14 | ||||
-rw-r--r-- | init/Kconfig | 4 | ||||
-rw-r--r-- | kernel/module.c | 53 | ||||
-rw-r--r-- | scripts/Makefile.build | 2 | ||||
-rw-r--r-- | scripts/genksyms/genksyms.c | 19 | ||||
-rw-r--r-- | scripts/kallsyms.c | 12 | ||||
-rw-r--r-- | scripts/mod/modpost.c | 10 |
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 |
54 | KSYM(__kcrctab_\name): | 51 | KSYM(__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 | ||
524 | struct symsearch { | 524 | struct 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 | */ |
540 | const struct kernel_symbol *find_symbol(const char *name, | 540 | const 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 | ||
1990 | config MODULE_REL_CRCS | ||
1991 | bool | ||
1992 | depends on MODVERSIONS | ||
1993 | |||
1990 | config MODULE_SRCVERSION_ALL | 1994 | config 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[]; | |||
389 | extern const struct kernel_symbol __stop___ksymtab_gpl[]; | 389 | extern const struct kernel_symbol __stop___ksymtab_gpl[]; |
390 | extern const struct kernel_symbol __start___ksymtab_gpl_future[]; | 390 | extern const struct kernel_symbol __start___ksymtab_gpl_future[]; |
391 | extern const struct kernel_symbol __stop___ksymtab_gpl_future[]; | 391 | extern const struct kernel_symbol __stop___ksymtab_gpl_future[]; |
392 | extern const unsigned long __start___kcrctab[]; | 392 | extern const s32 __start___kcrctab[]; |
393 | extern const unsigned long __start___kcrctab_gpl[]; | 393 | extern const s32 __start___kcrctab_gpl[]; |
394 | extern const unsigned long __start___kcrctab_gpl_future[]; | 394 | extern const s32 __start___kcrctab_gpl_future[]; |
395 | #ifdef CONFIG_UNUSED_SYMBOLS | 395 | #ifdef CONFIG_UNUSED_SYMBOLS |
396 | extern const struct kernel_symbol __start___ksymtab_unused[]; | 396 | extern const struct kernel_symbol __start___ksymtab_unused[]; |
397 | extern const struct kernel_symbol __stop___ksymtab_unused[]; | 397 | extern const struct kernel_symbol __stop___ksymtab_unused[]; |
398 | extern const struct kernel_symbol __start___ksymtab_unused_gpl[]; | 398 | extern const struct kernel_symbol __start___ksymtab_unused_gpl[]; |
399 | extern const struct kernel_symbol __stop___ksymtab_unused_gpl[]; | 399 | extern const struct kernel_symbol __stop___ksymtab_unused_gpl[]; |
400 | extern const unsigned long __start___kcrctab_unused[]; | 400 | extern const s32 __start___kcrctab_unused[]; |
401 | extern const unsigned long __start___kcrctab_unused_gpl[]; | 401 | extern 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. */ |
564 | const struct kernel_symbol *find_symbol(const char *name, | 564 | const 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 | |
1253 | static unsigned long maybe_relocated(unsigned long crc, | 1253 | static 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 | ||
1263 | static int check_version(Elf_Shdr *sechdrs, | 1258 | static 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; | |||
44 | int in_source_file; | 44 | int in_source_file; |
45 | 45 | ||
46 | static int flag_debug, flag_dump_defs, flag_reference, flag_dump_types, | 46 | static int flag_debug, flag_dump_defs, flag_reference, flag_dump_types, |
47 | flag_preserve, flag_warnings; | 47 | flag_preserve, flag_warnings, flag_rel_crcs; |
48 | static const char *mod_prefix = ""; | 48 | static const char *mod_prefix = ""; |
49 | 49 | ||
50 | static int errors; | 50 | static 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 | ||
731 | static void genksyms_usage(void) | 734 | static 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 | } |