diff options
Diffstat (limited to 'scripts/mod')
| -rw-r--r-- | scripts/mod/file2alias.c | 12 | ||||
| -rw-r--r-- | scripts/mod/modpost.c | 159 |
2 files changed, 104 insertions, 67 deletions
diff --git a/scripts/mod/file2alias.c b/scripts/mod/file2alias.c index f646381dc015..8a09021d8c59 100644 --- a/scripts/mod/file2alias.c +++ b/scripts/mod/file2alias.c | |||
| @@ -290,6 +290,14 @@ static int do_serio_entry(const char *filename, | |||
| 290 | return 1; | 290 | return 1; |
| 291 | } | 291 | } |
| 292 | 292 | ||
| 293 | /* looks like: "acpi:ACPI0003 or acpi:PNP0C0B" or "acpi:LNXVIDEO" */ | ||
| 294 | static int do_acpi_entry(const char *filename, | ||
| 295 | struct acpi_device_id *id, char *alias) | ||
| 296 | { | ||
| 297 | sprintf(alias, "acpi*:%s:", id->id); | ||
| 298 | return 1; | ||
| 299 | } | ||
| 300 | |||
| 293 | /* looks like: "pnp:dD" */ | 301 | /* looks like: "pnp:dD" */ |
| 294 | static int do_pnp_entry(const char *filename, | 302 | static int do_pnp_entry(const char *filename, |
| 295 | struct pnp_device_id *id, char *alias) | 303 | struct pnp_device_id *id, char *alias) |
| @@ -551,6 +559,10 @@ void handle_moddevtable(struct module *mod, struct elf_info *info, | |||
| 551 | do_table(symval, sym->st_size, | 559 | do_table(symval, sym->st_size, |
| 552 | sizeof(struct serio_device_id), "serio", | 560 | sizeof(struct serio_device_id), "serio", |
| 553 | do_serio_entry, mod); | 561 | do_serio_entry, mod); |
| 562 | else if (sym_is(symname, "__mod_acpi_device_table")) | ||
| 563 | do_table(symval, sym->st_size, | ||
| 564 | sizeof(struct acpi_device_id), "acpi", | ||
| 565 | do_acpi_entry, mod); | ||
| 554 | else if (sym_is(symname, "__mod_pnp_device_table")) | 566 | else if (sym_is(symname, "__mod_pnp_device_table")) |
| 555 | do_table(symval, sym->st_size, | 567 | do_table(symval, sym->st_size, |
| 556 | sizeof(struct pnp_device_id), "pnp", | 568 | sizeof(struct pnp_device_id), "pnp", |
diff --git a/scripts/mod/modpost.c b/scripts/mod/modpost.c index 5ab7914d30ef..ee58ded021d7 100644 --- a/scripts/mod/modpost.c +++ b/scripts/mod/modpost.c | |||
| @@ -23,6 +23,8 @@ int have_vmlinux = 0; | |||
| 23 | static int all_versions = 0; | 23 | static int all_versions = 0; |
| 24 | /* If we are modposting external module set to 1 */ | 24 | /* If we are modposting external module set to 1 */ |
| 25 | static int external_module = 0; | 25 | static int external_module = 0; |
| 26 | /* Warn about section mismatch in vmlinux if set to 1 */ | ||
| 27 | static int vmlinux_section_warnings = 1; | ||
| 26 | /* Only warn about unresolved symbols */ | 28 | /* Only warn about unresolved symbols */ |
| 27 | static int warn_unresolved = 0; | 29 | static int warn_unresolved = 0; |
| 28 | /* How a symbol is exported */ | 30 | /* How a symbol is exported */ |
| @@ -584,13 +586,61 @@ static int strrcmp(const char *s, const char *sub) | |||
| 584 | return memcmp(s + slen - sublen, sub, sublen); | 586 | return memcmp(s + slen - sublen, sub, sublen); |
| 585 | } | 587 | } |
| 586 | 588 | ||
| 589 | /* | ||
| 590 | * Functions used only during module init is marked __init and is stored in | ||
| 591 | * a .init.text section. Likewise data is marked __initdata and stored in | ||
| 592 | * a .init.data section. | ||
| 593 | * If this section is one of these sections return 1 | ||
| 594 | * See include/linux/init.h for the details | ||
| 595 | */ | ||
| 596 | static int init_section(const char *name) | ||
| 597 | { | ||
| 598 | if (strcmp(name, ".init") == 0) | ||
| 599 | return 1; | ||
| 600 | if (strncmp(name, ".init.", strlen(".init.")) == 0) | ||
| 601 | return 1; | ||
| 602 | return 0; | ||
| 603 | } | ||
| 604 | |||
| 605 | /* | ||
| 606 | * Functions used only during module exit is marked __exit and is stored in | ||
| 607 | * a .exit.text section. Likewise data is marked __exitdata and stored in | ||
| 608 | * a .exit.data section. | ||
| 609 | * If this section is one of these sections return 1 | ||
| 610 | * See include/linux/init.h for the details | ||
| 611 | **/ | ||
| 612 | static int exit_section(const char *name) | ||
| 613 | { | ||
| 614 | if (strcmp(name, ".exit.text") == 0) | ||
| 615 | return 1; | ||
| 616 | if (strcmp(name, ".exit.data") == 0) | ||
| 617 | return 1; | ||
| 618 | return 0; | ||
| 619 | |||
| 620 | } | ||
| 621 | |||
| 622 | /* | ||
| 623 | * Data sections are named like this: | ||
| 624 | * .data | .data.rel | .data.rel.* | ||
| 625 | * Return 1 if the specified section is a data section | ||
| 626 | */ | ||
| 627 | static int data_section(const char *name) | ||
| 628 | { | ||
| 629 | if ((strcmp(name, ".data") == 0) || | ||
| 630 | (strcmp(name, ".data.rel") == 0) || | ||
| 631 | (strncmp(name, ".data.rel.", strlen(".data.rel.")) == 0)) | ||
| 632 | return 1; | ||
| 633 | else | ||
| 634 | return 0; | ||
| 635 | } | ||
| 636 | |||
| 587 | /** | 637 | /** |
| 588 | * Whitelist to allow certain references to pass with no warning. | 638 | * Whitelist to allow certain references to pass with no warning. |
| 589 | * | 639 | * |
| 590 | * Pattern 0: | 640 | * Pattern 0: |
| 591 | * Do not warn if funtion/data are marked with __init_refok/__initdata_refok. | 641 | * Do not warn if funtion/data are marked with __init_refok/__initdata_refok. |
| 592 | * The pattern is identified by: | 642 | * The pattern is identified by: |
| 593 | * fromsec = .text.init.refok | .data.init.refok | 643 | * fromsec = .text.init.refok* | .data.init.refok* |
| 594 | * | 644 | * |
| 595 | * Pattern 1: | 645 | * Pattern 1: |
| 596 | * If a module parameter is declared __initdata and permissions=0 | 646 | * If a module parameter is declared __initdata and permissions=0 |
| @@ -608,8 +658,8 @@ static int strrcmp(const char *s, const char *sub) | |||
| 608 | * These functions may often be marked __init and we do not want to | 658 | * These functions may often be marked __init and we do not want to |
| 609 | * warn here. | 659 | * warn here. |
| 610 | * the pattern is identified by: | 660 | * the pattern is identified by: |
| 611 | * tosec = .init.text | .exit.text | .init.data | 661 | * tosec = init or exit section |
| 612 | * fromsec = .data | .data.rel | .data.rel.* | 662 | * fromsec = data section |
| 613 | * atsym = *driver, *_template, *_sht, *_ops, *_probe, *probe_one, *_console, *_timer | 663 | * atsym = *driver, *_template, *_sht, *_ops, *_probe, *probe_one, *_console, *_timer |
| 614 | * | 664 | * |
| 615 | * Pattern 3: | 665 | * Pattern 3: |
| @@ -625,12 +675,18 @@ static int strrcmp(const char *s, const char *sub) | |||
| 625 | * This pattern is identified by | 675 | * This pattern is identified by |
| 626 | * refsymname = __init_begin, _sinittext, _einittext | 676 | * refsymname = __init_begin, _sinittext, _einittext |
| 627 | * | 677 | * |
| 678 | * Pattern 5: | ||
| 679 | * Xtensa uses literal sections for constants that are accessed PC-relative. | ||
| 680 | * Literal sections may safely reference their text sections. | ||
| 681 | * (Note that the name for the literal section omits any trailing '.text') | ||
| 682 | * tosec = <section>[.text] | ||
| 683 | * fromsec = <section>.literal | ||
| 628 | **/ | 684 | **/ |
| 629 | static int secref_whitelist(const char *modname, const char *tosec, | 685 | static int secref_whitelist(const char *modname, const char *tosec, |
| 630 | const char *fromsec, const char *atsym, | 686 | const char *fromsec, const char *atsym, |
| 631 | const char *refsymname) | 687 | const char *refsymname) |
| 632 | { | 688 | { |
| 633 | int f1 = 1, f2 = 1; | 689 | int len; |
| 634 | const char **s; | 690 | const char **s; |
| 635 | const char *pat2sym[] = { | 691 | const char *pat2sym[] = { |
| 636 | "driver", | 692 | "driver", |
| @@ -652,36 +708,21 @@ static int secref_whitelist(const char *modname, const char *tosec, | |||
| 652 | }; | 708 | }; |
| 653 | 709 | ||
| 654 | /* Check for pattern 0 */ | 710 | /* Check for pattern 0 */ |
| 655 | if ((strcmp(fromsec, ".text.init.refok") == 0) || | 711 | if ((strncmp(fromsec, ".text.init.refok", strlen(".text.init.refok")) == 0) || |
| 656 | (strcmp(fromsec, ".data.init.refok") == 0)) | 712 | (strncmp(fromsec, ".data.init.refok", strlen(".data.init.refok")) == 0)) |
| 657 | return 1; | 713 | return 1; |
| 658 | 714 | ||
| 659 | /* Check for pattern 1 */ | 715 | /* Check for pattern 1 */ |
| 660 | if (strcmp(tosec, ".init.data") != 0) | 716 | if ((strcmp(tosec, ".init.data") == 0) && |
| 661 | f1 = 0; | 717 | (strncmp(fromsec, ".data", strlen(".data")) == 0) && |
| 662 | if (strncmp(fromsec, ".data", strlen(".data")) != 0) | 718 | (strncmp(atsym, "__param", strlen("__param")) == 0)) |
| 663 | f1 = 0; | 719 | return 1; |
| 664 | if (strncmp(atsym, "__param", strlen("__param")) != 0) | ||
| 665 | f1 = 0; | ||
| 666 | |||
| 667 | if (f1) | ||
| 668 | return f1; | ||
| 669 | 720 | ||
| 670 | /* Check for pattern 2 */ | 721 | /* Check for pattern 2 */ |
| 671 | if ((strcmp(tosec, ".init.text") != 0) && | 722 | if ((init_section(tosec) || exit_section(tosec)) && data_section(fromsec)) |
| 672 | (strcmp(tosec, ".exit.text") != 0) && | 723 | for (s = pat2sym; *s; s++) |
| 673 | (strcmp(tosec, ".init.data") != 0)) | 724 | if (strrcmp(atsym, *s) == 0) |
| 674 | f2 = 0; | 725 | return 1; |
| 675 | if ((strcmp(fromsec, ".data") != 0) && | ||
| 676 | (strcmp(fromsec, ".data.rel") != 0) && | ||
| 677 | (strncmp(fromsec, ".data.rel.", strlen(".data.rel.")) != 0)) | ||
| 678 | f2 = 0; | ||
| 679 | |||
| 680 | for (s = pat2sym; *s; s++) | ||
| 681 | if (strrcmp(atsym, *s) == 0) | ||
| 682 | f1 = 1; | ||
| 683 | if (f1 && f2) | ||
| 684 | return 1; | ||
| 685 | 726 | ||
| 686 | /* Check for pattern 3 */ | 727 | /* Check for pattern 3 */ |
| 687 | if ((strcmp(fromsec, ".text.head") == 0) && | 728 | if ((strcmp(fromsec, ".text.head") == 0) && |
| @@ -694,6 +735,15 @@ static int secref_whitelist(const char *modname, const char *tosec, | |||
| 694 | if (strcmp(refsymname, *s) == 0) | 735 | if (strcmp(refsymname, *s) == 0) |
| 695 | return 1; | 736 | return 1; |
| 696 | 737 | ||
| 738 | /* Check for pattern 5 */ | ||
| 739 | if (strrcmp(tosec, ".text") == 0) | ||
| 740 | len = strlen(tosec) - strlen(".text"); | ||
| 741 | else | ||
| 742 | len = strlen(tosec); | ||
| 743 | if ((strncmp(tosec, fromsec, len) == 0) && (strlen(fromsec) > len) && | ||
| 744 | (strcmp(fromsec + len, ".literal") == 0)) | ||
| 745 | return 1; | ||
| 746 | |||
| 697 | return 0; | 747 | return 0; |
| 698 | } | 748 | } |
| 699 | 749 | ||
| @@ -822,9 +872,9 @@ static void warn_sec_mismatch(const char *modname, const char *fromsec, | |||
| 822 | refsymname = elf->strtab + refsym->st_name; | 872 | refsymname = elf->strtab + refsym->st_name; |
| 823 | 873 | ||
| 824 | /* check whitelist - we may ignore it */ | 874 | /* check whitelist - we may ignore it */ |
| 825 | if (before && | 875 | if (secref_whitelist(modname, secname, fromsec, |
| 826 | secref_whitelist(modname, secname, fromsec, | 876 | before ? elf->strtab + before->st_name : "", |
| 827 | elf->strtab + before->st_name, refsymname)) | 877 | refsymname)) |
| 828 | return; | 878 | return; |
| 829 | 879 | ||
| 830 | if (before && after) { | 880 | if (before && after) { |
| @@ -1077,6 +1127,8 @@ static int initexit_section_ref_ok(const char *name) | |||
| 1077 | ".smp_locks", | 1127 | ".smp_locks", |
| 1078 | ".stab", | 1128 | ".stab", |
| 1079 | ".m68k_fixup", | 1129 | ".m68k_fixup", |
| 1130 | ".xt.prop", /* xtensa informational section */ | ||
| 1131 | ".xt.lit", /* xtensa informational section */ | ||
| 1080 | NULL | 1132 | NULL |
| 1081 | }; | 1133 | }; |
| 1082 | /* Start of section names */ | 1134 | /* Start of section names */ |
| @@ -1106,21 +1158,6 @@ static int initexit_section_ref_ok(const char *name) | |||
| 1106 | return 0; | 1158 | return 0; |
| 1107 | } | 1159 | } |
| 1108 | 1160 | ||
| 1109 | /** | ||
| 1110 | * Functions used only during module init is marked __init and is stored in | ||
| 1111 | * a .init.text section. Likewise data is marked __initdata and stored in | ||
| 1112 | * a .init.data section. | ||
| 1113 | * If this section is one of these sections return 1 | ||
| 1114 | * See include/linux/init.h for the details | ||
| 1115 | **/ | ||
| 1116 | static int init_section(const char *name) | ||
| 1117 | { | ||
| 1118 | if (strcmp(name, ".init") == 0) | ||
| 1119 | return 1; | ||
| 1120 | if (strncmp(name, ".init.", strlen(".init.")) == 0) | ||
| 1121 | return 1; | ||
| 1122 | return 0; | ||
| 1123 | } | ||
| 1124 | 1161 | ||
| 1125 | /* | 1162 | /* |
| 1126 | * Identify sections from which references to a .init section is OK. | 1163 | * Identify sections from which references to a .init section is OK. |
| @@ -1178,23 +1215,6 @@ static int init_section_ref_ok(const char *name) | |||
| 1178 | } | 1215 | } |
| 1179 | 1216 | ||
| 1180 | /* | 1217 | /* |
| 1181 | * Functions used only during module exit is marked __exit and is stored in | ||
| 1182 | * a .exit.text section. Likewise data is marked __exitdata and stored in | ||
| 1183 | * a .exit.data section. | ||
| 1184 | * If this section is one of these sections return 1 | ||
| 1185 | * See include/linux/init.h for the details | ||
| 1186 | **/ | ||
| 1187 | static int exit_section(const char *name) | ||
| 1188 | { | ||
| 1189 | if (strcmp(name, ".exit.text") == 0) | ||
| 1190 | return 1; | ||
| 1191 | if (strcmp(name, ".exit.data") == 0) | ||
| 1192 | return 1; | ||
| 1193 | return 0; | ||
| 1194 | |||
| 1195 | } | ||
| 1196 | |||
| 1197 | /* | ||
| 1198 | * Identify sections from which references to a .exit section is OK. | 1218 | * Identify sections from which references to a .exit section is OK. |
| 1199 | */ | 1219 | */ |
| 1200 | static int exit_section_ref_ok(const char *name) | 1220 | static int exit_section_ref_ok(const char *name) |
| @@ -1257,8 +1277,10 @@ static void read_symbols(char *modname) | |||
| 1257 | handle_modversions(mod, &info, sym, symname); | 1277 | handle_modversions(mod, &info, sym, symname); |
| 1258 | handle_moddevtable(mod, &info, sym, symname); | 1278 | handle_moddevtable(mod, &info, sym, symname); |
| 1259 | } | 1279 | } |
| 1260 | check_sec_ref(mod, modname, &info, init_section, init_section_ref_ok); | 1280 | if (is_vmlinux(modname) && vmlinux_section_warnings) { |
| 1261 | check_sec_ref(mod, modname, &info, exit_section, exit_section_ref_ok); | 1281 | check_sec_ref(mod, modname, &info, init_section, init_section_ref_ok); |
| 1282 | check_sec_ref(mod, modname, &info, exit_section, exit_section_ref_ok); | ||
| 1283 | } | ||
| 1262 | 1284 | ||
| 1263 | version = get_modinfo(info.modinfo, info.modinfo_len, "version"); | 1285 | version = get_modinfo(info.modinfo, info.modinfo_len, "version"); |
| 1264 | if (version) | 1286 | if (version) |
| @@ -1626,7 +1648,7 @@ int main(int argc, char **argv) | |||
| 1626 | int opt; | 1648 | int opt; |
| 1627 | int err; | 1649 | int err; |
| 1628 | 1650 | ||
| 1629 | while ((opt = getopt(argc, argv, "i:I:mo:aw")) != -1) { | 1651 | while ((opt = getopt(argc, argv, "i:I:mso:aw")) != -1) { |
| 1630 | switch(opt) { | 1652 | switch(opt) { |
| 1631 | case 'i': | 1653 | case 'i': |
| 1632 | kernel_read = optarg; | 1654 | kernel_read = optarg; |
| @@ -1644,6 +1666,9 @@ int main(int argc, char **argv) | |||
| 1644 | case 'a': | 1666 | case 'a': |
| 1645 | all_versions = 1; | 1667 | all_versions = 1; |
| 1646 | break; | 1668 | break; |
| 1669 | case 's': | ||
| 1670 | vmlinux_section_warnings = 0; | ||
| 1671 | break; | ||
| 1647 | case 'w': | 1672 | case 'w': |
| 1648 | warn_unresolved = 1; | 1673 | warn_unresolved = 1; |
| 1649 | break; | 1674 | break; |
