From 534b89a9f6a86a28300cd71619112c4bbca7c0ae Mon Sep 17 00:00:00 2001 From: Sam Ravnborg Date: Sat, 1 Jul 2006 10:10:19 +0200 Subject: kbuild: fix segv in modpost Parsing an old Modules.symvers file casued modpost to SEGV. Signed-off-by: Sam Ravnborg --- scripts/mod/modpost.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) (limited to 'scripts/mod/modpost.c') diff --git a/scripts/mod/modpost.c b/scripts/mod/modpost.c index 0dd16177642d..65411665e13c 100644 --- a/scripts/mod/modpost.c +++ b/scripts/mod/modpost.c @@ -205,6 +205,8 @@ static const char *export_str(enum export ex) static enum export export_no(const char * s) { int i; + if (!s) + return export_unknown; for (i = 0; export_list[i].export != export_unknown; i++) { if (strcmp(export_list[i].str, s) == 0) return export_list[i].export; @@ -1271,7 +1273,7 @@ static void write_if_changed(struct buffer *b, const char *fname) } /* parse Module.symvers file. line format: - * 0x12345678symbolmodule[export] + * 0x12345678symbolmodule[[export]something] **/ static void read_dump(const char *fname, unsigned int kernel) { @@ -1284,7 +1286,7 @@ static void read_dump(const char *fname, unsigned int kernel) return; while ((line = get_next_line(&pos, file, size))) { - char *symname, *modname, *d, *export; + char *symname, *modname, *d, *export, *end; unsigned int crc; struct module *mod; struct symbol *s; @@ -1297,7 +1299,8 @@ static void read_dump(const char *fname, unsigned int kernel) *modname++ = '\0'; if ((export = strchr(modname, '\t')) != NULL) *export++ = '\0'; - + if (export && ((end = strchr(export, '\t')) != NULL)) + *end = '\0'; crc = strtoul(line, &d, 16); if (*symname == '\0' || *modname == '\0' || *d != '\0') goto fail; -- cgit v1.2.2 From c96fca213737a5b4bc569e1d9a0ef6adeff661e9 Mon Sep 17 00:00:00 2001 From: Sam Ravnborg Date: Sat, 1 Jul 2006 11:44:23 +0200 Subject: 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 --- scripts/mod/modpost.c | 85 +++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 62 insertions(+), 23 deletions(-) (limited to 'scripts/mod/modpost.c') 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; /* If we are modposting external module set to 1 */ static int external_module = 0; /* How a symbol is exported */ -enum export {export_plain, export_gpl, export_gpl_future, export_unknown}; +enum export { + export_plain, export_unused, export_gpl, + export_unused_gpl, export_gpl_future, export_unknown +}; void fatal(const char *fmt, ...) { @@ -191,7 +194,9 @@ static struct { enum export export; } export_list[] = { { .str = "EXPORT_SYMBOL", .export = export_plain }, + { .str = "EXPORT_UNUSED_SYMBOL", .export = export_unused }, { .str = "EXPORT_SYMBOL_GPL", .export = export_gpl }, + { .str = "EXPORT_UNUSED_SYMBOL_GPL", .export = export_unused_gpl }, { .str = "EXPORT_SYMBOL_GPL_FUTURE", .export = export_gpl_future }, { .str = "(unknown)", .export = export_unknown }, }; @@ -218,8 +223,12 @@ static enum export export_from_sec(struct elf_info *elf, Elf_Section sec) { if (sec == elf->export_sec) return export_plain; + else if (sec == elf->export_unused_sec) + return export_unused; else if (sec == elf->export_gpl_sec) return export_gpl; + else if (sec == elf->export_unused_gpl_sec) + return export_unused_gpl; else if (sec == elf->export_gpl_future_sec) return export_gpl_future; else @@ -368,8 +377,12 @@ static void parse_elf(struct elf_info *info, const char *filename) info->modinfo_len = sechdrs[i].sh_size; } else if (strcmp(secname, "__ksymtab") == 0) info->export_sec = i; + else if (strcmp(secname, "__ksymtab_unused") == 0) + info->export_unused_sec = i; else if (strcmp(secname, "__ksymtab_gpl") == 0) info->export_gpl_sec = i; + else if (strcmp(secname, "__ksymtab_unused_gpl") == 0) + info->export_unused_gpl_sec = i; else if (strcmp(secname, "__ksymtab_gpl_future") == 0) info->export_gpl_future_sec = i; @@ -1087,38 +1100,64 @@ void buf_write(struct buffer *buf, const char *s, int len) buf->pos += len; } -void check_license(struct module *mod) +static void check_for_gpl_usage(enum export exp, const char *m, const char *s) +{ + const char *e = is_vmlinux(m) ?"":".ko"; + + switch (exp) { + case export_gpl: + fatal("modpost: GPL-incompatible module %s%s " + "uses GPL-only symbol '%s'\n", m, e, s); + break; + case export_unused_gpl: + fatal("modpost: GPL-incompatible module %s%s " + "uses GPL-only symbol marked UNUSED '%s'\n", m, e, s); + break; + case export_gpl_future: + warn("modpost: GPL-incompatible module %s%s " + "uses future GPL-only symbol '%s'\n", m, e, s); + break; + case export_plain: + case export_unused: + case export_unknown: + /* ignore */ + break; + } +} + +static void check_for_unused(enum export exp, const char* m, const char* s) +{ + const char *e = is_vmlinux(m) ?"":".ko"; + + switch (exp) { + case export_unused: + case export_unused_gpl: + warn("modpost: module %s%s " + "uses symbol '%s' marked UNUSED\n", m, e, s); + break; + default: + /* ignore */ + break; + } +} + +static void check_exports(struct module *mod) { struct symbol *s, *exp; for (s = mod->unres; s; s = s->next) { const char *basename; - if (mod->gpl_compatible == 1) { - /* GPL-compatible modules may use all symbols */ - continue; - } exp = find_symbol(s->name); if (!exp || exp->module == mod) continue; basename = strrchr(mod->name, '/'); if (basename) basename++; - switch (exp->export) { - case export_gpl: - fatal("modpost: GPL-incompatible module %s " - "uses GPL-only symbol '%s'\n", - basename ? basename : mod->name, - exp->name); - break; - case export_gpl_future: - warn("modpost: GPL-incompatible module %s " - "uses future GPL-only symbol '%s'\n", - basename ? basename : mod->name, - exp->name); - break; - case export_plain: /* ignore */ break; - case export_unknown: /* ignore */ break; - } + else + basename = mod->name; + if (!mod->gpl_compatible) + check_for_gpl_usage(exp->export, basename, exp->name); + check_for_unused(exp->export, basename, exp->name); } } @@ -1399,7 +1438,7 @@ int main(int argc, char **argv) for (mod = modules; mod; mod = mod->next) { if (mod->skip) continue; - check_license(mod); + check_exports(mod); } for (mod = modules; mod; mod = mod->next) { -- cgit v1.2.2