diff options
author | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-05-06 16:21:57 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-05-06 16:21:57 -0400 |
commit | 15700770ef7c5d12e2f1659d2ddbeb3f658d9f37 (patch) | |
tree | 7fa2f81c33c9efcb1a1568385beead75c5892cfb /scripts/mod/modpost.c | |
parent | 6de410c2b0cc055ae9ee640c84331f6a70878d9b (diff) | |
parent | 11de39e2fbbc592018e0a231d0ee773653dcc8d6 (diff) |
Merge git://git.kernel.org/pub/scm/linux/kernel/git/sam/kbuild
* git://git.kernel.org/pub/scm/linux/kernel/git/sam/kbuild: (38 commits)
kconfig: fix mconf segmentation fault
kbuild: enable use of code from a different dir
kconfig: error out if recursive dependencies are found
kbuild: scripts/basic/fixdep segfault on pathological string-o-death
kconfig: correct minor typo in Kconfig warning message.
kconfig: fix path to modules.txt in Kconfig help
usr/Kconfig: fix typo
kernel-doc: alphabetically-sorted entries in index.html of 'htmldocs'
kbuild: be more explicit on missing .config file
kbuild: clarify the creation of the LOCALVERSION_AUTO string.
kbuild: propagate errors from find in scripts/gen_initramfs_list.sh
kconfig: refer to qt3 if we cannot find qt libraries
kbuild: handle compressed cpio initramfs-es
kbuild: ignore section mismatch warning for references from .paravirtprobe to .init.text
kbuild: remove stale comment in modpost.c
kbuild/mkuboot.sh: allow spaces in CROSS_COMPILE
kbuild: fix make mrproper for Documentation/DocBook/man
kbuild: remove kconfig binaries during make mrproper
kconfig/menuconfig: do not hardcode '.config'
kbuild: override build timestamp & version
...
Diffstat (limited to 'scripts/mod/modpost.c')
-rw-r--r-- | scripts/mod/modpost.c | 141 |
1 files changed, 108 insertions, 33 deletions
diff --git a/scripts/mod/modpost.c b/scripts/mod/modpost.c index 78d659cbb36a..4ab36de45aa2 100644 --- a/scripts/mod/modpost.c +++ b/scripts/mod/modpost.c | |||
@@ -55,6 +55,17 @@ void warn(const char *fmt, ...) | |||
55 | va_end(arglist); | 55 | va_end(arglist); |
56 | } | 56 | } |
57 | 57 | ||
58 | void merror(const char *fmt, ...) | ||
59 | { | ||
60 | va_list arglist; | ||
61 | |||
62 | fprintf(stderr, "ERROR: "); | ||
63 | |||
64 | va_start(arglist, fmt); | ||
65 | vfprintf(stderr, fmt, arglist); | ||
66 | va_end(arglist); | ||
67 | } | ||
68 | |||
58 | static int is_vmlinux(const char *modname) | 69 | static int is_vmlinux(const char *modname) |
59 | { | 70 | { |
60 | const char *myname; | 71 | const char *myname; |
@@ -333,10 +344,10 @@ void release_file(void *file, unsigned long size) | |||
333 | munmap(file, size); | 344 | munmap(file, size); |
334 | } | 345 | } |
335 | 346 | ||
336 | static void parse_elf(struct elf_info *info, const char *filename) | 347 | static int parse_elf(struct elf_info *info, const char *filename) |
337 | { | 348 | { |
338 | unsigned int i; | 349 | unsigned int i; |
339 | Elf_Ehdr *hdr = info->hdr; | 350 | Elf_Ehdr *hdr; |
340 | Elf_Shdr *sechdrs; | 351 | Elf_Shdr *sechdrs; |
341 | Elf_Sym *sym; | 352 | Elf_Sym *sym; |
342 | 353 | ||
@@ -346,9 +357,18 @@ static void parse_elf(struct elf_info *info, const char *filename) | |||
346 | exit(1); | 357 | exit(1); |
347 | } | 358 | } |
348 | info->hdr = hdr; | 359 | info->hdr = hdr; |
349 | if (info->size < sizeof(*hdr)) | 360 | if (info->size < sizeof(*hdr)) { |
350 | goto truncated; | 361 | /* file too small, assume this is an empty .o file */ |
351 | 362 | return 0; | |
363 | } | ||
364 | /* Is this a valid ELF file? */ | ||
365 | if ((hdr->e_ident[EI_MAG0] != ELFMAG0) || | ||
366 | (hdr->e_ident[EI_MAG1] != ELFMAG1) || | ||
367 | (hdr->e_ident[EI_MAG2] != ELFMAG2) || | ||
368 | (hdr->e_ident[EI_MAG3] != ELFMAG3)) { | ||
369 | /* Not an ELF file - silently ignore it */ | ||
370 | return 0; | ||
371 | } | ||
352 | /* Fix endianness in ELF header */ | 372 | /* Fix endianness in ELF header */ |
353 | hdr->e_shoff = TO_NATIVE(hdr->e_shoff); | 373 | hdr->e_shoff = TO_NATIVE(hdr->e_shoff); |
354 | hdr->e_shstrndx = TO_NATIVE(hdr->e_shstrndx); | 374 | hdr->e_shstrndx = TO_NATIVE(hdr->e_shstrndx); |
@@ -371,8 +391,10 @@ static void parse_elf(struct elf_info *info, const char *filename) | |||
371 | = (void *)hdr + sechdrs[hdr->e_shstrndx].sh_offset; | 391 | = (void *)hdr + sechdrs[hdr->e_shstrndx].sh_offset; |
372 | const char *secname; | 392 | const char *secname; |
373 | 393 | ||
374 | if (sechdrs[i].sh_offset > info->size) | 394 | if (sechdrs[i].sh_offset > info->size) { |
375 | goto truncated; | 395 | fatal("%s is truncated. sechdrs[i].sh_offset=%u > sizeof(*hrd)=%ul\n", filename, (unsigned int)sechdrs[i].sh_offset, sizeof(*hdr)); |
396 | return 0; | ||
397 | } | ||
376 | secname = secstrings + sechdrs[i].sh_name; | 398 | secname = secstrings + sechdrs[i].sh_name; |
377 | if (strcmp(secname, ".modinfo") == 0) { | 399 | if (strcmp(secname, ".modinfo") == 0) { |
378 | info->modinfo = (void *)hdr + sechdrs[i].sh_offset; | 400 | info->modinfo = (void *)hdr + sechdrs[i].sh_offset; |
@@ -407,10 +429,7 @@ static void parse_elf(struct elf_info *info, const char *filename) | |||
407 | sym->st_value = TO_NATIVE(sym->st_value); | 429 | sym->st_value = TO_NATIVE(sym->st_value); |
408 | sym->st_size = TO_NATIVE(sym->st_size); | 430 | sym->st_size = TO_NATIVE(sym->st_size); |
409 | } | 431 | } |
410 | return; | 432 | return 1; |
411 | |||
412 | truncated: | ||
413 | fatal("%s is truncated.\n", filename); | ||
414 | } | 433 | } |
415 | 434 | ||
416 | static void parse_elf_finish(struct elf_info *info) | 435 | static void parse_elf_finish(struct elf_info *info) |
@@ -581,9 +600,17 @@ static int strrcmp(const char *s, const char *sub) | |||
581 | * the pattern is identified by: | 600 | * the pattern is identified by: |
582 | * tosec = .init.text | .exit.text | .init.data | 601 | * tosec = .init.text | .exit.text | .init.data |
583 | * fromsec = .data | 602 | * fromsec = .data |
584 | * atsym = *driver, *_template, *_sht, *_ops, *_probe, *probe_one | 603 | * atsym = *driver, *_template, *_sht, *_ops, *_probe, *probe_one, *_console |
585 | * | 604 | * |
586 | * Pattern 3: | 605 | * Pattern 3: |
606 | * Whitelist all references from .pci_fixup* section to .init.text | ||
607 | * This is part of the PCI init when built-in | ||
608 | * | ||
609 | * Pattern 4: | ||
610 | * Whitelist all refereces from .text.head to .init.data | ||
611 | * Whitelist all refereces from .text.head to .init.text | ||
612 | * | ||
613 | * Pattern 5: | ||
587 | * Some symbols belong to init section but still it is ok to reference | 614 | * Some symbols belong to init section but still it is ok to reference |
588 | * these from non-init sections as these symbols don't have any memory | 615 | * these from non-init sections as these symbols don't have any memory |
589 | * allocated for them and symbol address and value are same. So even | 616 | * allocated for them and symbol address and value are same. So even |
@@ -591,6 +618,30 @@ static int strrcmp(const char *s, const char *sub) | |||
591 | * For ex. symbols marking the init section boundaries. | 618 | * For ex. symbols marking the init section boundaries. |
592 | * This pattern is identified by | 619 | * This pattern is identified by |
593 | * refsymname = __init_begin, _sinittext, _einittext | 620 | * refsymname = __init_begin, _sinittext, _einittext |
621 | * | ||
622 | * Pattern 6: | ||
623 | * During the early init phase we have references from .init.text to | ||
624 | * .text we have an intended section mismatch - do not warn about it. | ||
625 | * See kernel_init() in init/main.c | ||
626 | * tosec = .init.text | ||
627 | * fromsec = .text | ||
628 | * atsym = kernel_init | ||
629 | * | ||
630 | * Pattern 7: | ||
631 | * Logos used in drivers/video/logo reside in __initdata but the | ||
632 | * funtion that references them are EXPORT_SYMBOL() so cannot be | ||
633 | * marker __init. So we whitelist them here. | ||
634 | * The pattern is: | ||
635 | * tosec = .init.data | ||
636 | * fromsec = .text* | ||
637 | * refsymname = logo_ | ||
638 | * | ||
639 | * Pattern 8: | ||
640 | * Symbols contained in .paravirtprobe may safely reference .init.text. | ||
641 | * The pattern is: | ||
642 | * tosec = .init.text | ||
643 | * fromsec = .paravirtprobe | ||
644 | * | ||
594 | **/ | 645 | **/ |
595 | static int secref_whitelist(const char *modname, const char *tosec, | 646 | static int secref_whitelist(const char *modname, const char *tosec, |
596 | const char *fromsec, const char *atsym, | 647 | const char *fromsec, const char *atsym, |
@@ -642,25 +693,39 @@ static int secref_whitelist(const char *modname, const char *tosec, | |||
642 | if (f1 && f2) | 693 | if (f1 && f2) |
643 | return 1; | 694 | return 1; |
644 | 695 | ||
645 | /* Whitelist all references from .pci_fixup section if vmlinux | 696 | /* Check for pattern 3 */ |
646 | * Whitelist all refereces from .text.head to .init.data if vmlinux | 697 | if ((strncmp(fromsec, ".pci_fixup", strlen(".pci_fixup")) == 0) && |
647 | * Whitelist all refereces from .text.head to .init.text if vmlinux | 698 | (strcmp(tosec, ".init.text") == 0)) |
648 | */ | 699 | return 1; |
649 | if (is_vmlinux(modname)) { | 700 | |
650 | if ((strcmp(fromsec, ".pci_fixup") == 0) && | 701 | /* Check for pattern 4 */ |
651 | (strcmp(tosec, ".init.text") == 0)) | 702 | if ((strcmp(fromsec, ".text.head") == 0) && |
703 | ((strcmp(tosec, ".init.data") == 0) || | ||
704 | (strcmp(tosec, ".init.text") == 0))) | ||
705 | return 1; | ||
706 | |||
707 | /* Check for pattern 5 */ | ||
708 | for (s = pat3refsym; *s; s++) | ||
709 | if (strcmp(refsymname, *s) == 0) | ||
710 | return 1; | ||
711 | |||
712 | /* Check for pattern 6 */ | ||
713 | if ((strcmp(tosec, ".init.text") == 0) && | ||
714 | (strcmp(fromsec, ".text") == 0) && | ||
715 | (strcmp(refsymname, "kernel_init") == 0)) | ||
652 | return 1; | 716 | return 1; |
653 | 717 | ||
654 | if ((strcmp(fromsec, ".text.head") == 0) && | 718 | /* Check for pattern 7 */ |
655 | ((strcmp(tosec, ".init.data") == 0) || | 719 | if ((strcmp(tosec, ".init.data") == 0) && |
656 | (strcmp(tosec, ".init.text") == 0))) | 720 | (strncmp(fromsec, ".text", strlen(".text")) == 0) && |
721 | (strncmp(refsymname, "logo_", strlen("logo_")) == 0)) | ||
722 | return 1; | ||
723 | |||
724 | /* Check for pattern 8 */ | ||
725 | if ((strcmp(tosec, ".init.text") == 0) && | ||
726 | (strcmp(fromsec, ".paravirtprobe") == 0)) | ||
657 | return 1; | 727 | return 1; |
658 | 728 | ||
659 | /* Check for pattern 3 */ | ||
660 | for (s = pat3refsym; *s; s++) | ||
661 | if (strcmp(refsymname, *s) == 0) | ||
662 | return 1; | ||
663 | } | ||
664 | return 0; | 729 | return 0; |
665 | } | 730 | } |
666 | 731 | ||
@@ -1090,7 +1155,8 @@ static void read_symbols(char *modname) | |||
1090 | struct elf_info info = { }; | 1155 | struct elf_info info = { }; |
1091 | Elf_Sym *sym; | 1156 | Elf_Sym *sym; |
1092 | 1157 | ||
1093 | parse_elf(&info, modname); | 1158 | if (!parse_elf(&info, modname)) |
1159 | return; | ||
1094 | 1160 | ||
1095 | mod = new_module(modname); | 1161 | mod = new_module(modname); |
1096 | 1162 | ||
@@ -1265,9 +1331,14 @@ static int add_versions(struct buffer *b, struct module *mod) | |||
1265 | exp = find_symbol(s->name); | 1331 | exp = find_symbol(s->name); |
1266 | if (!exp || exp->module == mod) { | 1332 | if (!exp || exp->module == mod) { |
1267 | if (have_vmlinux && !s->weak) { | 1333 | if (have_vmlinux && !s->weak) { |
1268 | warn("\"%s\" [%s.ko] undefined!\n", | 1334 | if (warn_unresolved) { |
1269 | s->name, mod->name); | 1335 | warn("\"%s\" [%s.ko] undefined!\n", |
1270 | err = warn_unresolved ? 0 : 1; | 1336 | s->name, mod->name); |
1337 | } else { | ||
1338 | merror("\"%s\" [%s.ko] undefined!\n", | ||
1339 | s->name, mod->name); | ||
1340 | err = 1; | ||
1341 | } | ||
1271 | } | 1342 | } |
1272 | continue; | 1343 | continue; |
1273 | } | 1344 | } |
@@ -1318,6 +1389,7 @@ static void add_depends(struct buffer *b, struct module *mod, | |||
1318 | buf_printf(b, "__attribute__((section(\".modinfo\"))) =\n"); | 1389 | buf_printf(b, "__attribute__((section(\".modinfo\"))) =\n"); |
1319 | buf_printf(b, "\"depends="); | 1390 | buf_printf(b, "\"depends="); |
1320 | for (s = mod->unres; s; s = s->next) { | 1391 | for (s = mod->unres; s; s = s->next) { |
1392 | const char *p; | ||
1321 | if (!s->module) | 1393 | if (!s->module) |
1322 | continue; | 1394 | continue; |
1323 | 1395 | ||
@@ -1325,8 +1397,11 @@ static void add_depends(struct buffer *b, struct module *mod, | |||
1325 | continue; | 1397 | continue; |
1326 | 1398 | ||
1327 | s->module->seen = 1; | 1399 | s->module->seen = 1; |
1328 | buf_printf(b, "%s%s", first ? "" : ",", | 1400 | if ((p = strrchr(s->module->name, '/')) != NULL) |
1329 | strrchr(s->module->name, '/') + 1); | 1401 | p++; |
1402 | else | ||
1403 | p = s->module->name; | ||
1404 | buf_printf(b, "%s%s", first ? "" : ",", p); | ||
1330 | first = 0; | 1405 | first = 0; |
1331 | } | 1406 | } |
1332 | buf_printf(b, "\";\n"); | 1407 | buf_printf(b, "\";\n"); |