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 | |
| 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')
| -rw-r--r-- | scripts/mod/modpost.c | 85 | ||||
| -rw-r--r-- | scripts/mod/modpost.h | 2 |
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 */ |
| 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) { |
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; |
