diff options
author | Sam Ravnborg <sam@mars.ravnborg.org> | 2006-07-01 05:44:23 -0400 |
---|---|---|
committer | Sam Ravnborg <sam@mars.ravnborg.org> | 2006-07-01 05:44:23 -0400 |
commit | c96fca213737a5b4bc569e1d9a0ef6adeff661e9 (patch) | |
tree | d20a7d0550cf92040df1b2cf1c00199483d8f7f3 /scripts/mod/modpost.c | |
parent | 534b89a9f6a86a28300cd71619112c4bbca7c0ae (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/modpost.c')
-rw-r--r-- | scripts/mod/modpost.c | 85 |
1 files changed, 62 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 */ |
25 | static int external_module = 0; | 25 | static int external_module = 0; |
26 | /* How a symbol is exported */ | 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 | void fatal(const char *fmt, ...) | 32 | void 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 | ||
1090 | void check_license(struct module *mod) | 1103 | static 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 | |||
1128 | static 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 | |||
1144 | static 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) { |