diff options
Diffstat (limited to 'scripts/mod/modpost.c')
-rw-r--r-- | scripts/mod/modpost.c | 159 |
1 files changed, 92 insertions, 67 deletions
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; |