aboutsummaryrefslogtreecommitdiffstats
path: root/scripts/mod
diff options
context:
space:
mode:
authorSam Ravnborg <sam@mars.ravnborg.org>2006-07-01 05:44:23 -0400
committerSam Ravnborg <sam@mars.ravnborg.org>2006-07-01 05:44:23 -0400
commitc96fca213737a5b4bc569e1d9a0ef6adeff661e9 (patch)
treed20a7d0550cf92040df1b2cf1c00199483d8f7f3 /scripts/mod
parent534b89a9f6a86a28300cd71619112c4bbca7c0ae (diff)
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>
Diffstat (limited to 'scripts/mod')
-rw-r--r--scripts/mod/modpost.c85
-rw-r--r--scripts/mod/modpost.h2
2 files changed, 64 insertions, 23 deletions
diff --git a/scripts/mod/modpost.c b/scripts/mod/modpost.c
index 65411665e13c..dfde0e87a765 100644
--- a/scripts/mod/modpost.c
+++ b/scripts/mod/modpost.c
@@ -24,7 +24,10 @@ 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 */
25static int external_module = 0; 25static int external_module = 0;
26/* How a symbol is exported */ 26/* How a symbol is exported */
27enum export {export_plain, export_gpl, export_gpl_future, export_unknown}; 27enum export {
28 export_plain, export_unused, export_gpl,
29 export_unused_gpl, export_gpl_future, export_unknown
30};
28 31
29void fatal(const char *fmt, ...) 32void fatal(const char *fmt, ...)
30{ 33{
@@ -191,7 +194,9 @@ static struct {
191 enum export export; 194 enum export export;
192} export_list[] = { 195} export_list[] = {
193 { .str = "EXPORT_SYMBOL", .export = export_plain }, 196 { .str = "EXPORT_SYMBOL", .export = export_plain },
197 { .str = "EXPORT_UNUSED_SYMBOL", .export = export_unused },
194 { .str = "EXPORT_SYMBOL_GPL", .export = export_gpl }, 198 { .str = "EXPORT_SYMBOL_GPL", .export = export_gpl },
199 { .str = "EXPORT_UNUSED_SYMBOL_GPL", .export = export_unused_gpl },
195 { .str = "EXPORT_SYMBOL_GPL_FUTURE", .export = export_gpl_future }, 200 { .str = "EXPORT_SYMBOL_GPL_FUTURE", .export = export_gpl_future },
196 { .str = "(unknown)", .export = export_unknown }, 201 { .str = "(unknown)", .export = export_unknown },
197}; 202};
@@ -218,8 +223,12 @@ static enum export export_from_sec(struct elf_info *elf, Elf_Section sec)
218{ 223{
219 if (sec == elf->export_sec) 224 if (sec == elf->export_sec)
220 return export_plain; 225 return export_plain;
226 else if (sec == elf->export_unused_sec)
227 return export_unused;
221 else if (sec == elf->export_gpl_sec) 228 else if (sec == elf->export_gpl_sec)
222 return export_gpl; 229 return export_gpl;
230 else if (sec == elf->export_unused_gpl_sec)
231 return export_unused_gpl;
223 else if (sec == elf->export_gpl_future_sec) 232 else if (sec == elf->export_gpl_future_sec)
224 return export_gpl_future; 233 return export_gpl_future;
225 else 234 else
@@ -368,8 +377,12 @@ static void parse_elf(struct elf_info *info, const char *filename)
368 info->modinfo_len = sechdrs[i].sh_size; 377 info->modinfo_len = sechdrs[i].sh_size;
369 } else if (strcmp(secname, "__ksymtab") == 0) 378 } else if (strcmp(secname, "__ksymtab") == 0)
370 info->export_sec = i; 379 info->export_sec = i;
380 else if (strcmp(secname, "__ksymtab_unused") == 0)
381 info->export_unused_sec = i;
371 else if (strcmp(secname, "__ksymtab_gpl") == 0) 382 else if (strcmp(secname, "__ksymtab_gpl") == 0)
372 info->export_gpl_sec = i; 383 info->export_gpl_sec = i;
384 else if (strcmp(secname, "__ksymtab_unused_gpl") == 0)
385 info->export_unused_gpl_sec = i;
373 else if (strcmp(secname, "__ksymtab_gpl_future") == 0) 386 else if (strcmp(secname, "__ksymtab_gpl_future") == 0)
374 info->export_gpl_future_sec = i; 387 info->export_gpl_future_sec = i;
375 388
@@ -1087,38 +1100,64 @@ void buf_write(struct buffer *buf, const char *s, int len)
1087 buf->pos += len; 1100 buf->pos += len;
1088} 1101}
1089 1102
1090void check_license(struct module *mod) 1103static void check_for_gpl_usage(enum export exp, const char *m, const char *s)
1104{
1105 const char *e = is_vmlinux(m) ?"":".ko";
1106
1107 switch (exp) {
1108 case export_gpl:
1109 fatal("modpost: GPL-incompatible module %s%s "
1110 "uses GPL-only symbol '%s'\n", m, e, s);
1111 break;
1112 case export_unused_gpl:
1113 fatal("modpost: GPL-incompatible module %s%s "
1114 "uses GPL-only symbol marked UNUSED '%s'\n", m, e, s);
1115 break;
1116 case export_gpl_future:
1117 warn("modpost: GPL-incompatible module %s%s "
1118 "uses future GPL-only symbol '%s'\n", m, e, s);
1119 break;
1120 case export_plain:
1121 case export_unused:
1122 case export_unknown:
1123 /* ignore */
1124 break;
1125 }
1126}
1127
1128static void check_for_unused(enum export exp, const char* m, const char* s)
1129{
1130 const char *e = is_vmlinux(m) ?"":".ko";
1131
1132 switch (exp) {
1133 case export_unused:
1134 case export_unused_gpl:
1135 warn("modpost: module %s%s "
1136 "uses symbol '%s' marked UNUSED\n", m, e, s);
1137 break;
1138 default:
1139 /* ignore */
1140 break;
1141 }
1142}
1143
1144static void check_exports(struct module *mod)
1091{ 1145{
1092 struct symbol *s, *exp; 1146 struct symbol *s, *exp;
1093 1147
1094 for (s = mod->unres; s; s = s->next) { 1148 for (s = mod->unres; s; s = s->next) {
1095 const char *basename; 1149 const char *basename;
1096 if (mod->gpl_compatible == 1) {
1097 /* GPL-compatible modules may use all symbols */
1098 continue;
1099 }
1100 exp = find_symbol(s->name); 1150 exp = find_symbol(s->name);
1101 if (!exp || exp->module == mod) 1151 if (!exp || exp->module == mod)
1102 continue; 1152 continue;
1103 basename = strrchr(mod->name, '/'); 1153 basename = strrchr(mod->name, '/');
1104 if (basename) 1154 if (basename)
1105 basename++; 1155 basename++;
1106 switch (exp->export) { 1156 else
1107 case export_gpl: 1157 basename = mod->name;
1108 fatal("modpost: GPL-incompatible module %s " 1158 if (!mod->gpl_compatible)
1109 "uses GPL-only symbol '%s'\n", 1159 check_for_gpl_usage(exp->export, basename, exp->name);
1110 basename ? basename : mod->name, 1160 check_for_unused(exp->export, basename, exp->name);
1111 exp->name);
1112 break;
1113 case export_gpl_future:
1114 warn("modpost: GPL-incompatible module %s "
1115 "uses future GPL-only symbol '%s'\n",
1116 basename ? basename : mod->name,
1117 exp->name);
1118 break;
1119 case export_plain: /* ignore */ break;
1120 case export_unknown: /* ignore */ break;
1121 }
1122 } 1161 }
1123} 1162}
1124 1163
@@ -1399,7 +1438,7 @@ int main(int argc, char **argv)
1399 for (mod = modules; mod; mod = mod->next) { 1438 for (mod = modules; mod; mod = mod->next) {
1400 if (mod->skip) 1439 if (mod->skip)
1401 continue; 1440 continue;
1402 check_license(mod); 1441 check_exports(mod);
1403 } 1442 }
1404 1443
1405 for (mod = modules; mod; mod = mod->next) { 1444 for (mod = modules; mod; mod = mod->next) {
diff --git a/scripts/mod/modpost.h b/scripts/mod/modpost.h
index 2b00c6062844..d398c61e55ef 100644
--- a/scripts/mod/modpost.h
+++ b/scripts/mod/modpost.h
@@ -117,7 +117,9 @@ struct elf_info {
117 Elf_Sym *symtab_start; 117 Elf_Sym *symtab_start;
118 Elf_Sym *symtab_stop; 118 Elf_Sym *symtab_stop;
119 Elf_Section export_sec; 119 Elf_Section export_sec;
120 Elf_Section export_unused_sec;
120 Elf_Section export_gpl_sec; 121 Elf_Section export_gpl_sec;
122 Elf_Section export_unused_gpl_sec;
121 Elf_Section export_gpl_future_sec; 123 Elf_Section export_gpl_future_sec;
122 const char *strtab; 124 const char *strtab;
123 char *modinfo; 125 char *modinfo;