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

Unified · Split

3 files
  1. lib/Kconfig.debug +2 −0
  2. scripts/Makefile.modpost +1 −0
  3. scripts/mod/modpost.c +226 −29
lib/Kconfig.debug+2−0
@@ -108,6 +108,8 @@ config DEBUG_SECTION_MISMATCH · 107 unmodified lines
108108 will tell where the mismatch happens much closer to the
109109 source. The drawback is that we will report the same
110110 mismatch at least twice.
111+ - Enable verbose reporting from modpost to help solving
112+ the section mismatches reported.
111113
112114 config DEBUG_KERNEL
113115 bool "Kernel debugging"
scripts/Makefile.modpost+1−0
@@ -62,6 +62,7 @@ modpost = scripts/mod/modpost \ · 61 unmodified lines
6262 $(if $(KBUILD_EXTMOD),-i,-o) $(kernelsymfile) \
6363 $(if $(KBUILD_EXTMOD),-I $(modulesymfile)) \
6464 $(if $(KBUILD_EXTMOD),-o $(modulesymfile)) \
65+ $(if $(CONFIG_DEBUG_SECTION_MISMATCH),,-S) \
6566 $(if $(KBUILD_EXTMOD)$(KBUILD_MODPOST_WARN),-w)
6667
6768 quiet_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
2828 /* Only warn about unresolved symbols */
2929 static int warn_unresolved = 0;
3030 /* How a symbol is exported */
31+static int sec_mismatch_count = 0;
32+static int sec_mismatch_verbose = 1;
33+
3134 enum export {
3235 export_plain, export_unused, export_gpl,
3336 export_unused_gpl, export_gpl_future, export_unknown
@@ -760,9 +763,23 @@ static const char *head_sections[] = { ".head.text*", NULL }; · 726 unmodified lines
760763 static const char *linker_symbols[] =
761764 { "__init_begin", "_sinittext", "_einittext", NULL };
762765
766+enum 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+
763779 struct sectioncheck {
764780 const char *fromsec[20];
765781 const char *tosec[20];
782+ enum mismatch mismatch;
766783 };
767784
768785 const struct sectioncheck sectioncheck[] = {
@@ -770,33 +787,54 @@ const struct sectioncheck sectioncheck[] = { · 1 unmodified line
770787 * normal code and data
771788 */
772789 {
773− .fromsec = { TEXT_SECTIONS, DATA_SECTIONS, NULL },
774− .tosec = { ALL_INIT_SECTIONS, ALL_EXIT_SECTIONS, NULL }
790+ .fromsec = { TEXT_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,
775808 },
776809 /* Do not reference init code/data from devinit/cpuinit/meminit code/data */
777810 {
778811 .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,
780814 },
781815 /* Do not reference exit code/data from devexit/cpuexit/memexit code/data */
782816 {
783817 .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,
785820 },
786821 /* Do not use exit code/data from init code */
787822 {
788823 .fromsec = { ALL_INIT_SECTIONS, NULL },
789824 .tosec = { ALL_EXIT_SECTIONS, NULL },
825+ .mismatch = INIT_TO_EXIT,
790826 },
791827 /* Do not use init code/data from exit code */
792828 {
793829 .fromsec = { ALL_EXIT_SECTIONS, NULL },
794− .tosec = { ALL_INIT_SECTIONS, NULL }
830+ .tosec = { ALL_INIT_SECTIONS, NULL },
831+ .mismatch = EXIT_TO_INIT,
795832 },
796833 /* Do not export init/exit functions or data */
797834 {
798835 .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
800838 }
801839 };
802840
@@ -809,10 +847,10 @@ static int section_mismatch(const char *fromsec, const char *tosec) · 6 unmodified lines
809847 for (i = 0; i < elems; i++) {
810848 if (match(fromsec, check->fromsec) &&
811849 match(tosec, check->tosec))
812− return 1;
850+ return check->mismatch;
813851 check++;
814852 }
815− return 0;
853+ return NO_MISMATCH;
816854 }
817855
818856 /**
@@ -988,48 +1026,198 @@ static Elf_Sym *find_elf_symbol2(struct elf_info *elf, Elf_Addr addr, · 169 unmodified lines
9881026 return near;
9891027 }
9901028
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+*/
1036+static 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+
1063+static 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+
9911071 /*
9921072 * Print a warning about a section mismatch.
9931073 * Try to find symbols near it so user can find it.
9941074 * Check whitelist before warning - it may be a false positive.
9951075 */
996−static void report_sec_mismatch(const char *modname,
1076+static void report_sec_mismatch(const char *modname, enum mismatch mismatch,
9971077 const char *fromsec,
9981078 unsigned long long fromaddr,
9991079 const char *fromsym,
1000− const char *tosec, const char *tosym)
1001−{
1002− if (strlen(tosym)) {
1003− warn("%s(%s+0x%llx): Section mismatch: reference to %s:%s "
1004− "in '%s'\n",
1005− modname, fromsec, fromaddr,
1006− tosec, tosym, fromsym);
1007− } else {
1008− warn("%s(%s+0x%llx): Section mismatch: reference to %s:%s\n",
1009− modname, fromsec, fromaddr,
1010− tosec, tosym);
1080+ int from_is_func,
1081+ const char *tosec, const char *tosym,
1082+ int to_is_func)
1083+{
1084+ const char *from, *from_p;
1085+ const char *to, *to_p;
1086+ from = from_is_func ? "function" : "variable";
1087+ from_p = from_is_func ? "()" : "";
1088+ to = to_is_func ? "function" : "variable";
1089+ to_p = to_is_func ? "()" : "";
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;
10111124 }
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");
10121194 }
10131195
10141196 static void check_section_mismatch(const char *modname, struct elf_info *elf,
10151197 Elf_Rela *r, Elf_Sym *sym, const char *fromsec)
10161198 {
10171199 const char *tosec;
1200+ enum mismatch mismatch;
10181201
10191202 tosec = sec_name(elf, sym->st_shndx);
1020− if (section_mismatch(fromsec, tosec)) {
1021− const char *fromsym;
1203+ mismatch = section_mismatch(fromsec, tosec);
1204+ if (mismatch != NO_MISMATCH) {
1205+ Elf_Sym *to;
1206+ Elf_Sym *from;
10221207 const char *tosym;
1208+ const char *fromsym;
10231209
1024− fromsym = sym_name(elf,
1025− find_elf_symbol2(elf, r->r_offset, fromsec));
1026− tosym = sym_name(elf,
1027− find_elf_symbol(elf, r->r_addend, sym));
1210+ from = find_elf_symbol2(elf, r->r_offset, fromsec);
1211+ fromsym = sym_name(elf, from);
1212+ to = find_elf_symbol(elf, r->r_addend, sym);
1213+ tosym = sym_name(elf, to);
10281214
10291215 /* check whitelist - we may ignore it */
10301216 if (secref_whitelist(fromsec, fromsym, tosec, tosym)) {
1031− report_sec_mismatch(modname, fromsec, r->r_offset,
1032− fromsym, tosec, tosym);
1217+ report_sec_mismatch(modname, mismatch,
1218+ fromsec, r->r_offset, fromsym,
1219+ is_function(from), tosec, tosym,
1220+ is_function(to));
10331221 }
10341222 }
10351223 }
@@ -1643,7 +1831,7 @@ int main(int argc, char **argv) · 607 unmodified lines
16431831 int opt;
16441832 int err;
16451833
1646− while ((opt = getopt(argc, argv, "i:I:mso:aw")) != -1) {
1834+ while ((opt = getopt(argc, argv, "i:I:msSo:aw")) != -1) {
16471835 switch (opt) {
16481836 case 'i':
16491837 kernel_read = optarg;
@@ -1664,6 +1852,9 @@ int main(int argc, char **argv) · 14 unmodified lines
16641852 case 's':
16651853 vmlinux_section_warnings = 0;
16661854 break;
1855+ case 'S':
1856+ sec_mismatch_verbose = 0;
1857+ break;
16671858 case 'w':
16681859 warn_unresolved = 1;
16691860 break;
@@ -1708,6 +1899,12 @@ int main(int argc, char **argv) · 38 unmodified lines
17081899
17091900 if (dump_write)
17101901 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);
17111908
17121909 return err;
17131910 }

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