diff options
Diffstat (limited to 'scripts/mod')
-rw-r--r-- | scripts/mod/file2alias.c | 21 | ||||
-rw-r--r-- | scripts/mod/modpost.c | 141 | ||||
-rw-r--r-- | scripts/mod/modpost.h | 1 | ||||
-rw-r--r-- | scripts/mod/sumversion.c | 5 |
4 files changed, 122 insertions, 46 deletions
diff --git a/scripts/mod/file2alias.c b/scripts/mod/file2alias.c index b2f73ffb40bd..ed1244dd58d0 100644 --- a/scripts/mod/file2alias.c +++ b/scripts/mod/file2alias.c | |||
@@ -37,7 +37,6 @@ typedef unsigned char __u8; | |||
37 | * even potentially has different endianness and word sizes, since | 37 | * even potentially has different endianness and word sizes, since |
38 | * we handle those differences explicitly below */ | 38 | * we handle those differences explicitly below */ |
39 | #include "../../include/linux/mod_devicetable.h" | 39 | #include "../../include/linux/mod_devicetable.h" |
40 | #include "../../include/linux/input.h" | ||
41 | 40 | ||
42 | #define ADD(str, sep, cond, field) \ | 41 | #define ADD(str, sep, cond, field) \ |
43 | do { \ | 42 | do { \ |
@@ -416,31 +415,33 @@ static int do_input_entry(const char *filename, struct input_device_id *id, | |||
416 | 415 | ||
417 | sprintf(alias + strlen(alias), "-e*"); | 416 | sprintf(alias + strlen(alias), "-e*"); |
418 | if (id->flags & INPUT_DEVICE_ID_MATCH_EVBIT) | 417 | if (id->flags & INPUT_DEVICE_ID_MATCH_EVBIT) |
419 | do_input(alias, id->evbit, 0, EV_MAX); | 418 | do_input(alias, id->evbit, 0, INPUT_DEVICE_ID_EV_MAX); |
420 | sprintf(alias + strlen(alias), "k*"); | 419 | sprintf(alias + strlen(alias), "k*"); |
421 | if (id->flags & INPUT_DEVICE_ID_MATCH_KEYBIT) | 420 | if (id->flags & INPUT_DEVICE_ID_MATCH_KEYBIT) |
422 | do_input(alias, id->keybit, KEY_MIN_INTERESTING, KEY_MAX); | 421 | do_input(alias, id->keybit, |
422 | INPUT_DEVICE_ID_KEY_MIN_INTERESTING, | ||
423 | INPUT_DEVICE_ID_KEY_MAX); | ||
423 | sprintf(alias + strlen(alias), "r*"); | 424 | sprintf(alias + strlen(alias), "r*"); |
424 | if (id->flags & INPUT_DEVICE_ID_MATCH_RELBIT) | 425 | if (id->flags & INPUT_DEVICE_ID_MATCH_RELBIT) |
425 | do_input(alias, id->relbit, 0, REL_MAX); | 426 | do_input(alias, id->relbit, 0, INPUT_DEVICE_ID_REL_MAX); |
426 | sprintf(alias + strlen(alias), "a*"); | 427 | sprintf(alias + strlen(alias), "a*"); |
427 | if (id->flags & INPUT_DEVICE_ID_MATCH_ABSBIT) | 428 | if (id->flags & INPUT_DEVICE_ID_MATCH_ABSBIT) |
428 | do_input(alias, id->absbit, 0, ABS_MAX); | 429 | do_input(alias, id->absbit, 0, INPUT_DEVICE_ID_ABS_MAX); |
429 | sprintf(alias + strlen(alias), "m*"); | 430 | sprintf(alias + strlen(alias), "m*"); |
430 | if (id->flags & INPUT_DEVICE_ID_MATCH_MSCIT) | 431 | if (id->flags & INPUT_DEVICE_ID_MATCH_MSCIT) |
431 | do_input(alias, id->mscbit, 0, MSC_MAX); | 432 | do_input(alias, id->mscbit, 0, INPUT_DEVICE_ID_MSC_MAX); |
432 | sprintf(alias + strlen(alias), "l*"); | 433 | sprintf(alias + strlen(alias), "l*"); |
433 | if (id->flags & INPUT_DEVICE_ID_MATCH_LEDBIT) | 434 | if (id->flags & INPUT_DEVICE_ID_MATCH_LEDBIT) |
434 | do_input(alias, id->ledbit, 0, LED_MAX); | 435 | do_input(alias, id->ledbit, 0, INPUT_DEVICE_ID_LED_MAX); |
435 | sprintf(alias + strlen(alias), "s*"); | 436 | sprintf(alias + strlen(alias), "s*"); |
436 | if (id->flags & INPUT_DEVICE_ID_MATCH_SNDBIT) | 437 | if (id->flags & INPUT_DEVICE_ID_MATCH_SNDBIT) |
437 | do_input(alias, id->sndbit, 0, SND_MAX); | 438 | do_input(alias, id->sndbit, 0, INPUT_DEVICE_ID_SND_MAX); |
438 | sprintf(alias + strlen(alias), "f*"); | 439 | sprintf(alias + strlen(alias), "f*"); |
439 | if (id->flags & INPUT_DEVICE_ID_MATCH_FFBIT) | 440 | if (id->flags & INPUT_DEVICE_ID_MATCH_FFBIT) |
440 | do_input(alias, id->ffbit, 0, FF_MAX); | 441 | do_input(alias, id->ffbit, 0, INPUT_DEVICE_ID_FF_MAX); |
441 | sprintf(alias + strlen(alias), "w*"); | 442 | sprintf(alias + strlen(alias), "w*"); |
442 | if (id->flags & INPUT_DEVICE_ID_MATCH_SWBIT) | 443 | if (id->flags & INPUT_DEVICE_ID_MATCH_SWBIT) |
443 | do_input(alias, id->swbit, 0, SW_MAX); | 444 | do_input(alias, id->swbit, 0, INPUT_DEVICE_ID_SW_MAX); |
444 | return 1; | 445 | return 1; |
445 | } | 446 | } |
446 | 447 | ||
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"); |
diff --git a/scripts/mod/modpost.h b/scripts/mod/modpost.h index d398c61e55ef..0858caa9c03f 100644 --- a/scripts/mod/modpost.h +++ b/scripts/mod/modpost.h | |||
@@ -145,3 +145,4 @@ void release_file(void *file, unsigned long size); | |||
145 | 145 | ||
146 | void fatal(const char *fmt, ...); | 146 | void fatal(const char *fmt, ...); |
147 | void warn(const char *fmt, ...); | 147 | void warn(const char *fmt, ...); |
148 | void merror(const char *fmt, ...); | ||
diff --git a/scripts/mod/sumversion.c b/scripts/mod/sumversion.c index 8a2875689e4d..6873d5af80d5 100644 --- a/scripts/mod/sumversion.c +++ b/scripts/mod/sumversion.c | |||
@@ -397,10 +397,9 @@ void get_src_version(const char *modname, char sum[], unsigned sumlen) | |||
397 | (int) strlen(basename) - 2, basename); | 397 | (int) strlen(basename) - 2, basename); |
398 | 398 | ||
399 | file = grab_file(filelist, &len); | 399 | file = grab_file(filelist, &len); |
400 | if (!file) { | 400 | if (!file) |
401 | warn("could not find versions for %s\n", filelist); | 401 | /* not a module or .mod file missing - ignore */ |
402 | return; | 402 | return; |
403 | } | ||
404 | 403 | ||
405 | sources = strchr(file, '\n'); | 404 | sources = strchr(file, '\n'); |
406 | if (!sources) { | 405 | if (!sources) { |