kbuild: warn when a moduled uses a symbol marked UNUSED

We now have infrastructure in place to mark an EXPORTed symbol
as unused. So the natural next step is to warn during buildtime when
a module uses a symbol marked UNUSED.

Signed-off-by: Sam Ravnborg <sam@ravnborg.org>

+64 -23
+62 -23
scripts/mod/modpost.c
··· 24 24 /* If we are modposting external module set to 1 */ 25 25 static int external_module = 0; 26 26 /* How a symbol is exported */ 27 - enum export {export_plain, export_gpl, export_gpl_future, export_unknown}; 27 + enum export { 28 + export_plain, export_unused, export_gpl, 29 + export_unused_gpl, export_gpl_future, export_unknown 30 + }; 28 31 29 32 void fatal(const char *fmt, ...) 30 33 { ··· 194 191 enum export export; 195 192 } export_list[] = { 196 193 { .str = "EXPORT_SYMBOL", .export = export_plain }, 194 + { .str = "EXPORT_UNUSED_SYMBOL", .export = export_unused }, 197 195 { .str = "EXPORT_SYMBOL_GPL", .export = export_gpl }, 196 + { .str = "EXPORT_UNUSED_SYMBOL_GPL", .export = export_unused_gpl }, 198 197 { .str = "EXPORT_SYMBOL_GPL_FUTURE", .export = export_gpl_future }, 199 198 { .str = "(unknown)", .export = export_unknown }, 200 199 }; ··· 223 218 { 224 219 if (sec == elf->export_sec) 225 220 return export_plain; 221 + else if (sec == elf->export_unused_sec) 222 + return export_unused; 226 223 else if (sec == elf->export_gpl_sec) 227 224 return export_gpl; 225 + else if (sec == elf->export_unused_gpl_sec) 226 + return export_unused_gpl; 228 227 else if (sec == elf->export_gpl_future_sec) 229 228 return export_gpl_future; 230 229 else ··· 377 368 info->modinfo_len = sechdrs[i].sh_size; 378 369 } else if (strcmp(secname, "__ksymtab") == 0) 379 370 info->export_sec = i; 371 + else if (strcmp(secname, "__ksymtab_unused") == 0) 372 + info->export_unused_sec = i; 380 373 else if (strcmp(secname, "__ksymtab_gpl") == 0) 381 374 info->export_gpl_sec = i; 375 + else if (strcmp(secname, "__ksymtab_unused_gpl") == 0) 376 + info->export_unused_gpl_sec = i; 382 377 else if (strcmp(secname, "__ksymtab_gpl_future") == 0) 383 378 info->export_gpl_future_sec = i; 384 379 ··· 1100 1087 buf->pos += len; 1101 1088 } 1102 1089 1103 - void check_license(struct module *mod) 1090 + static void check_for_gpl_usage(enum export exp, const char *m, const char *s) 1091 + { 1092 + const char *e = is_vmlinux(m) ?"":".ko"; 1093 + 1094 + switch (exp) { 1095 + case export_gpl: 1096 + fatal("modpost: GPL-incompatible module %s%s " 1097 + "uses GPL-only symbol '%s'\n", m, e, s); 1098 + break; 1099 + case export_unused_gpl: 1100 + fatal("modpost: GPL-incompatible module %s%s " 1101 + "uses GPL-only symbol marked UNUSED '%s'\n", m, e, s); 1102 + break; 1103 + case export_gpl_future: 1104 + warn("modpost: GPL-incompatible module %s%s " 1105 + "uses future GPL-only symbol '%s'\n", m, e, s); 1106 + break; 1107 + case export_plain: 1108 + case export_unused: 1109 + case export_unknown: 1110 + /* ignore */ 1111 + break; 1112 + } 1113 + } 1114 + 1115 + static void check_for_unused(enum export exp, const char* m, const char* s) 1116 + { 1117 + const char *e = is_vmlinux(m) ?"":".ko"; 1118 + 1119 + switch (exp) { 1120 + case export_unused: 1121 + case export_unused_gpl: 1122 + warn("modpost: module %s%s " 1123 + "uses symbol '%s' marked UNUSED\n", m, e, s); 1124 + break; 1125 + default: 1126 + /* ignore */ 1127 + break; 1128 + } 1129 + } 1130 + 1131 + static void check_exports(struct module *mod) 1104 1132 { 1105 1133 struct symbol *s, *exp; 1106 1134 1107 1135 for (s = mod->unres; s; s = s->next) { 1108 1136 const char *basename; 1109 - if (mod->gpl_compatible == 1) { 1110 - /* GPL-compatible modules may use all symbols */ 1111 - continue; 1112 - } 1113 1137 exp = find_symbol(s->name); 1114 1138 if (!exp || exp->module == mod) 1115 1139 continue; 1116 1140 basename = strrchr(mod->name, '/'); 1117 1141 if (basename) 1118 1142 basename++; 1119 - switch (exp->export) { 1120 - case export_gpl: 1121 - fatal("modpost: GPL-incompatible module %s " 1122 - "uses GPL-only symbol '%s'\n", 1123 - basename ? basename : mod->name, 1124 - exp->name); 1125 - break; 1126 - case export_gpl_future: 1127 - warn("modpost: GPL-incompatible module %s " 1128 - "uses future GPL-only symbol '%s'\n", 1129 - basename ? basename : mod->name, 1130 - exp->name); 1131 - break; 1132 - case export_plain: /* ignore */ break; 1133 - case export_unknown: /* ignore */ break; 1134 - } 1143 + else 1144 + basename = mod->name; 1145 + if (!mod->gpl_compatible) 1146 + check_for_gpl_usage(exp->export, basename, exp->name); 1147 + check_for_unused(exp->export, basename, exp->name); 1135 1148 } 1136 1149 } 1137 1150 ··· 1438 1399 for (mod = modules; mod; mod = mod->next) { 1439 1400 if (mod->skip) 1440 1401 continue; 1441 - check_license(mod); 1402 + check_exports(mod); 1442 1403 } 1443 1404 1444 1405 for (mod = modules; mod; mod = mod->next) {
+2
scripts/mod/modpost.h
··· 117 117 Elf_Sym *symtab_start; 118 118 Elf_Sym *symtab_stop; 119 119 Elf_Section export_sec; 120 + Elf_Section export_unused_sec; 120 121 Elf_Section export_gpl_sec; 122 + Elf_Section export_unused_gpl_sec; 121 123 Elf_Section export_gpl_future_sec; 122 124 const char *strtab; 123 125 char *modinfo;