History

kbuild: add verbose option to Section mismatch reporting in modpost

If the config option CONFIG_SECTION_MISMATCH is not set and we see a Section mismatch present the following to the user: modpost: Found 1 section mismatch(es). To see additional details select "Enable full Section mismatch analysis" in the Kernel Hacking menu (CONFIG_SECTION_MISMATCH). If the option CONFIG_SECTION_MISMATCH is selected then be verbose in the Section mismatch reporting from mdopost. Sample outputs: WARNING: o-x86_64/vmlinux.o(.text+0x7396): Section mismatch in reference from the function discover_ebda() to the variable .init.data:ebda_addr The function discover_ebda() references the variable __initdata ebda_addr. This is often because discover_ebda lacks a __initdata annotation or the annotation of ebda_addr is wrong. WARNING: o-x86_64/vmlinux.o(.data+0x74d58): Section mismatch in reference from the variable pci_serial_quirks to the function .devexit.text:pci_plx9050_exit() The variable pci_serial_quirks references the function __devexit pci_plx9050_exit() If the reference is valid then annotate the variable with __exit* (see linux/init.h) or name the variable: *driver, *_template, *_timer, *_sht, *_ops, *_probe, *_probe_one, *_console, WARNING: o-x86_64/vmlinux.o(__ksymtab+0x630): Section mismatch in reference from the variable __ksymtab_arch_register_cpu to the function .cpuinit.text:arch_register_cpu() The symbol arch_register_cpu is exported and annotated __cpuinit Fix this by removing the __cpuinit annotation of arch_register_cpu or drop the export.

Sam Ravnborg committed 18 years ago

Commit 588ccd71 parent f5eaa323 files · +229 −29Browse files

Showing the changes to scripts (2 of 3 files). Show all

Unified · Split

2 files
  1. scripts/Makefile.modpost +1 −0
  2. scripts/mod/modpost.c +226 −29
scripts/Makefile.modpost+1−0
@@ -62,6 +62,7 @@ modpost = scripts/mod/modpost \ · 61 unmodified lines
62 $(if $(KBUILD_EXTMOD),-i,-o) $(kernelsymfile) \62 $(if $(KBUILD_EXTMOD),-i,-o) $(kernelsymfile) \
63 $(if $(KBUILD_EXTMOD),-I $(modulesymfile)) \63 $(if $(KBUILD_EXTMOD),-I $(modulesymfile)) \
64 $(if $(KBUILD_EXTMOD),-o $(modulesymfile)) \64 $(if $(KBUILD_EXTMOD),-o $(modulesymfile)) \
65 $(if $(CONFIG_DEBUG_SECTION_MISMATCH),,-S) \
65 $(if $(KBUILD_EXTMOD)$(KBUILD_MODPOST_WARN),-w)66 $(if $(KBUILD_EXTMOD)$(KBUILD_MODPOST_WARN),-w)
66 67
67quiet_cmd_modpost = MODPOST $(words $(filter-out vmlinux FORCE, $^)) modules68quiet_cmd_modpost = MODPOST $(words $(filter-out vmlinux FORCE, $^)) modules
scripts/mod/modpost.c+226−29
@@ -28,6 +28,9 @@ static int vmlinux_section_warnings = 1; · 27 unmodified lines
28/* Only warn about unresolved symbols */28/* Only warn about unresolved symbols */
29static int warn_unresolved = 0;29static int warn_unresolved = 0;
30/* How a symbol is exported */30/* How a symbol is exported */
31static int sec_mismatch_count = 0;
32static int sec_mismatch_verbose = 1;
33
31enum export {34enum export {
32 export_plain, export_unused, export_gpl,35 export_plain, export_unused, export_gpl,
33 export_unused_gpl, export_gpl_future, export_unknown36 export_unused_gpl, export_gpl_future, export_unknown
@@ -760,9 +763,23 @@ static const char *head_sections[] = { ".head.text*", NULL }; · 726 unmodified lines
760static const char *linker_symbols[] =763static const char *linker_symbols[] =
761 { "__init_begin", "_sinittext", "_einittext", NULL };764 { "__init_begin", "_sinittext", "_einittext", NULL };
762 765
766enum mismatch {
767 NO_MISMATCH,
768 TEXT_TO_INIT,
769 DATA_TO_INIT,
770 TEXT_TO_EXIT,
771 DATA_TO_EXIT,
772 XXXINIT_TO_INIT,
773 XXXEXIT_TO_EXIT,
774 INIT_TO_EXIT,
775 EXIT_TO_INIT,
776 EXPORT_TO_INIT_EXIT,
777};
778
763struct sectioncheck {779struct sectioncheck {
764 const char *fromsec[20];780 const char *fromsec[20];
765 const char *tosec[20];781 const char *tosec[20];
782 enum mismatch mismatch;
766};783};
767 784
768const struct sectioncheck sectioncheck[] = {785const struct sectioncheck sectioncheck[] = {
@@ -770,33 +787,54 @@ const struct sectioncheck sectioncheck[] = { · 1 unmodified line
770 * normal code and data787 * normal code and data
771 */788 */
772{789{
773 .fromsec = { TEXT_SECTIONS, DATA_SECTIONS, NULL },790 .fromsec = { TEXT_SECTIONS, NULL },
774 .tosec = { ALL_INIT_SECTIONS, ALL_EXIT_SECTIONS, NULL }791 .tosec = { ALL_INIT_SECTIONS, NULL },
792 .mismatch = TEXT_TO_INIT,
793},
794{
795 .fromsec = { DATA_SECTIONS, NULL },
796 .tosec = { ALL_INIT_SECTIONS, NULL },
797 .mismatch = DATA_TO_INIT,
798},
799{
800 .fromsec = { TEXT_SECTIONS, NULL },
801 .tosec = { ALL_EXIT_SECTIONS, NULL },
802 .mismatch = TEXT_TO_EXIT,
803},
804{
805 .fromsec = { DATA_SECTIONS, NULL },
806 .tosec = { ALL_EXIT_SECTIONS, NULL },
807 .mismatch = DATA_TO_EXIT,
775},808},
776/* Do not reference init code/data from devinit/cpuinit/meminit code/data */809/* Do not reference init code/data from devinit/cpuinit/meminit code/data */
777{810{
778 .fromsec = { DEV_INIT_SECTIONS, CPU_INIT_SECTIONS, MEM_INIT_SECTIONS, NULL },811 .fromsec = { DEV_INIT_SECTIONS, CPU_INIT_SECTIONS, MEM_INIT_SECTIONS, NULL },
779 .tosec = { INIT_SECTIONS, NULL }812 .tosec = { INIT_SECTIONS, NULL },
813 .mismatch = XXXINIT_TO_INIT,
780},814},
781/* Do not reference exit code/data from devexit/cpuexit/memexit code/data */815/* Do not reference exit code/data from devexit/cpuexit/memexit code/data */
782{816{
783 .fromsec = { DEV_EXIT_SECTIONS, CPU_EXIT_SECTIONS, MEM_EXIT_SECTIONS, NULL },817 .fromsec = { DEV_EXIT_SECTIONS, CPU_EXIT_SECTIONS, MEM_EXIT_SECTIONS, NULL },
784 .tosec = { EXIT_SECTIONS, NULL }818 .tosec = { EXIT_SECTIONS, NULL },
819 .mismatch = XXXEXIT_TO_EXIT,
785},820},
786/* Do not use exit code/data from init code */821/* Do not use exit code/data from init code */
787{822{
788 .fromsec = { ALL_INIT_SECTIONS, NULL },823 .fromsec = { ALL_INIT_SECTIONS, NULL },
789 .tosec = { ALL_EXIT_SECTIONS, NULL },824 .tosec = { ALL_EXIT_SECTIONS, NULL },
825 .mismatch = INIT_TO_EXIT,
790},826},
791/* Do not use init code/data from exit code */827/* Do not use init code/data from exit code */
792{828{
793 .fromsec = { ALL_EXIT_SECTIONS, NULL },829 .fromsec = { ALL_EXIT_SECTIONS, NULL },
794 .tosec = { ALL_INIT_SECTIONS, NULL }830 .tosec = { ALL_INIT_SECTIONS, NULL },
831 .mismatch = EXIT_TO_INIT,
795},832},
796/* Do not export init/exit functions or data */833/* Do not export init/exit functions or data */
797{834{
798 .fromsec = { "__ksymtab*", NULL },835 .fromsec = { "__ksymtab*", NULL },
799 .tosec = { ALL_INIT_SECTIONS, ALL_EXIT_SECTIONS, NULL }836 .tosec = { ALL_INIT_SECTIONS, ALL_EXIT_SECTIONS, NULL },
837 .mismatch = EXPORT_TO_INIT_EXIT
800}838}
801};839};
802 840
@@ -809,10 +847,10 @@ static int section_mismatch(const char *fromsec, const char *tosec) · 6 unmodified lines
809 for (i = 0; i < elems; i++) {847 for (i = 0; i < elems; i++) {
810 if (match(fromsec, check->fromsec) &&848 if (match(fromsec, check->fromsec) &&
811 match(tosec, check->tosec))849 match(tosec, check->tosec))
812 return 1;850 return check->mismatch;
813 check++;851 check++;
814 }852 }
815 return 0;853 return NO_MISMATCH;
816}854}
817 855
818/**856/**
@@ -988,48 +1026,198 @@ static Elf_Sym *find_elf_symbol2(struct elf_info *elf, Elf_Addr addr, · 169 unmodified lines
988 return near;1026 return near;
989}1027}
990 1028
1029/*
1030 * Convert a section name to the function/data attribute
1031 * .init.text => __init
1032 * .cpuinit.data => __cpudata
1033 * .memexitconst => __memconst
1034 * etc.
1035*/
1036static char *sec2annotation(const char *s)
1037{
1038 if (match(s, init_exit_sections)) {
1039 char *p = malloc(20);
1040 char *r = p;
1041
1042 *p++ = '_';
1043 *p++ = '_';
1044 if (*s == '.')
1045 s++;
1046 while (*s && *s != '.')
1047 *p++ = *s++;
1048 *p = '\0';
1049 if (*s == '.')
1050 s++;
1051 if (strstr(s, "rodata") != NULL)
1052 strcat(p, "const ");
1053 else if (strstr(s, "data") != NULL)
1054 strcat(p, "data ");
1055 else
1056 strcat(p, " ");
1057 return r; /* we leak her but we do not care */
1058 } else {
1059 return "";
1060 }
1061}
1062
1063static int is_function(Elf_Sym *sym)
1064{
1065 if (sym)
1066 return ELF_ST_TYPE(sym->st_info) == STT_FUNC;
1067 else
1068 return 0;
1069}
1070
991/*1071/*
992 * Print a warning about a section mismatch.1072 * Print a warning about a section mismatch.
993 * Try to find symbols near it so user can find it.1073 * Try to find symbols near it so user can find it.
994 * Check whitelist before warning - it may be a false positive.1074 * Check whitelist before warning - it may be a false positive.
995 */1075 */
996static void report_sec_mismatch(const char *modname,1076static void report_sec_mismatch(const char *modname, enum mismatch mismatch,
997 const char *fromsec,1077 const char *fromsec,
998 unsigned long long fromaddr,1078 unsigned long long fromaddr,
999 const char *fromsym,1079 const char *fromsym,
1000 const char *tosec, const char *tosym)1080 int from_is_func,
1001{1081 const char *tosec, const char *tosym,
1002 if (strlen(tosym)) {1082 int to_is_func)
1003 warn("%s(%s+0x%llx): Section mismatch: reference to %s:%s "1083{
1004 "in '%s'\n",1084 const char *from, *from_p;
1005 modname, fromsec, fromaddr,1085 const char *to, *to_p;
1006 tosec, tosym, fromsym);1086 from = from_is_func ? "function" : "variable";
1007 } else {1087 from_p = from_is_func ? "()" : "";
1008 warn("%s(%s+0x%llx): Section mismatch: reference to %s:%s\n",1088 to = to_is_func ? "function" : "variable";
1009 modname, fromsec, fromaddr,1089 to_p = to_is_func ? "()" : "";
1010 tosec, tosym);1090
1091 fprintf(stderr, "WARNING: %s(%s+0x%llx): Section mismatch in"
1092 " reference from the %s %s%s to the %s %s:%s%s\n",
1093 modname, fromsec, fromaddr, from, fromsym, from_p,
1094 to, tosec, tosym, to_p);
1095
1096 sec_mismatch_count++;
1097 if (!sec_mismatch_verbose)
1098 return;
1099
1100 switch (mismatch) {
1101 case TEXT_TO_INIT:
1102 fprintf(stderr,
1103 "The function %s %s() references\n"
1104 "the %s %s%s%s.\n"
1105 "This is often because %s lacks a %s\n"
1106 "annotation or the annotation of %s is wrong.\n",
1107 sec2annotation(fromsec), fromsym,
1108 to, sec2annotation(tosec), tosym, to_p,
1109 fromsym, sec2annotation(tosec), tosym);
1110 break;
1111 case DATA_TO_INIT: {
1112 const char **s = symbol_white_list;
1113 fprintf(stderr,
1114 "The variable %s references\n"
1115 "the %s %s%s%s\n"
1116 "If the reference is valid then annotate the\n"
1117 "variable with __init* (see linux/init.h) "
1118 "or name the variable:\n",
1119 fromsym, to, sec2annotation(tosec), tosym, to_p);
1120 while (*s)
1121 fprintf(stderr, "%s, ", *s++);
1122 fprintf(stderr, "\n");
1123 break;
1011 }1124 }
1125 case TEXT_TO_EXIT:
1126 fprintf(stderr,
1127 "The function %s() references a %s in an exit section.\n"
1128 "Often the %s %s%s has valid usage outside the exit section\n"
1129 "and the fix is to remove the %sannotation of %s.\n",
1130 fromsym, to, to, tosym, to_p, sec2annotation(tosec), tosym);
1131 break;
1132 case DATA_TO_EXIT: {
1133 const char **s = symbol_white_list;
1134 fprintf(stderr,
1135 "The variable %s references\n"
1136 "the %s %s%s%s\n"
1137 "If the reference is valid then annotate the\n"
1138 "variable with __exit* (see linux/init.h) or "
1139 "name the variable:\n",
1140 fromsym, to, sec2annotation(tosec), tosym, to_p);
1141 while (*s)
1142 fprintf(stderr, "%s, ", *s++);
1143 fprintf(stderr, "\n");
1144 break;
1145 }
1146 case XXXINIT_TO_INIT:
1147 case XXXEXIT_TO_EXIT:
1148 fprintf(stderr,
1149 "The %s %s%s%s references\n"
1150 "a %s %s%s%s.\n"
1151 "If %s is only used by %s then\n"
1152 "annotate %s with a matching annotation.\n",
1153 from, sec2annotation(fromsec), fromsym, from_p,
1154 to, sec2annotation(tosec), tosym, to_p,
1155 fromsym, tosym, fromsym);
1156 break;
1157 case INIT_TO_EXIT:
1158 fprintf(stderr,
1159 "The %s %s%s%s references\n"
1160 "a %s %s%s%s.\n"
1161 "This is often seen when error handling "
1162 "in the init function\n"
1163 "uses functionality in the exit path.\n"
1164 "The fix is often to remove the %sannotation of\n"
1165 "%s%s so it may be used outside an exit section.\n",
1166 from, sec2annotation(fromsec), fromsym, from_p,
1167 to, sec2annotation(tosec), tosym, to_p,
1168 sec2annotation(tosec), tosym, to_p);
1169 break;
1170 case EXIT_TO_INIT:
1171 fprintf(stderr,
1172 "The %s %s%s%s references\n"
1173 "a %s %s%s%s.\n"
1174 "This is often seen when error handling "
1175 "in the exit function\n"
1176 "uses functionality in the init path.\n"
1177 "The fix is often to remove the %sannotation of\n"
1178 "%s%s so it may be used outside an init section.\n",
1179 from, sec2annotation(fromsec), fromsym, from_p,
1180 to, sec2annotation(tosec), tosym, to_p,
1181 sec2annotation(tosec), tosym, to_p);
1182 break;
1183 case EXPORT_TO_INIT_EXIT:
1184 fprintf(stderr,
1185 "The symbol %s is exported and annotated %s\n"
1186 "Fix this by removing the %sannotation of %s "
1187 "or drop the export.\n",
1188 tosym, sec2annotation(tosec), sec2annotation(tosec), tosym);
1189 case NO_MISMATCH:
1190 /* To get warnings on missing members */
1191 break;
1192 }
1193 fprintf(stderr, "\n");
1012}1194}
1013 1195
1014static void check_section_mismatch(const char *modname, struct elf_info *elf,1196static void check_section_mismatch(const char *modname, struct elf_info *elf,
1015 Elf_Rela *r, Elf_Sym *sym, const char *fromsec)1197 Elf_Rela *r, Elf_Sym *sym, const char *fromsec)
1016{1198{
1017 const char *tosec;1199 const char *tosec;
1200 enum mismatch mismatch;
1018 1201
1019 tosec = sec_name(elf, sym->st_shndx);1202 tosec = sec_name(elf, sym->st_shndx);
1020 if (section_mismatch(fromsec, tosec)) {1203 mismatch = section_mismatch(fromsec, tosec);
1021 const char *fromsym;1204 if (mismatch != NO_MISMATCH) {
1205 Elf_Sym *to;
1206 Elf_Sym *from;
1022 const char *tosym;1207 const char *tosym;
1208 const char *fromsym;
1023 1209
1024 fromsym = sym_name(elf,1210 from = find_elf_symbol2(elf, r->r_offset, fromsec);
1025 find_elf_symbol2(elf, r->r_offset, fromsec));1211 fromsym = sym_name(elf, from);
1026 tosym = sym_name(elf,1212 to = find_elf_symbol(elf, r->r_addend, sym);
1027 find_elf_symbol(elf, r->r_addend, sym));1213 tosym = sym_name(elf, to);
1028 1214
1029 /* check whitelist - we may ignore it */1215 /* check whitelist - we may ignore it */
1030 if (secref_whitelist(fromsec, fromsym, tosec, tosym)) {1216 if (secref_whitelist(fromsec, fromsym, tosec, tosym)) {
1031 report_sec_mismatch(modname, fromsec, r->r_offset,1217 report_sec_mismatch(modname, mismatch,
1032 fromsym, tosec, tosym);1218 fromsec, r->r_offset, fromsym,
1219 is_function(from), tosec, tosym,
1220 is_function(to));
1033 }1221 }
1034 }1222 }
1035}1223}
@@ -1643,7 +1831,7 @@ int main(int argc, char **argv) · 607 unmodified lines
1643 int opt;1831 int opt;
1644 int err;1832 int err;
1645 1833
1646 while ((opt = getopt(argc, argv, "i:I:mso:aw")) != -1) {1834 while ((opt = getopt(argc, argv, "i:I:msSo:aw")) != -1) {
1647 switch (opt) {1835 switch (opt) {
1648 case 'i':1836 case 'i':
1649 kernel_read = optarg;1837 kernel_read = optarg;
@@ -1664,6 +1852,9 @@ int main(int argc, char **argv) · 14 unmodified lines
1664 case 's':1852 case 's':
1665 vmlinux_section_warnings = 0;1853 vmlinux_section_warnings = 0;
1666 break;1854 break;
1855 case 'S':
1856 sec_mismatch_verbose = 0;
1857 break;
1667 case 'w':1858 case 'w':
1668 warn_unresolved = 1;1859 warn_unresolved = 1;
1669 break;1860 break;
@@ -1708,6 +1899,12 @@ int main(int argc, char **argv) · 38 unmodified lines
1708 1899
1709 if (dump_write)1900 if (dump_write)
1710 write_dump(dump_write);1901 write_dump(dump_write);
1902 if (sec_mismatch_count && !sec_mismatch_verbose)
1903 fprintf(stderr, "modpost: Found %d section mismatch(es).\n"
1904 "To see additional details select \"Enable full "
1905 "Section mismatch analysis\"\n"
1906 "in the Kernel Hacking menu "
1907 "(CONFIG_SECTION_MISMATCH).\n", sec_mismatch_count);
1711 1908
1712 return err;1909 return err;
1713}1910}

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t