diff --git a/scripts/mod/modpost.c b/scripts/mod/modpost.c index 9c8c7511d..79aef50ed 100644 --- a/scripts/mod/modpost.c +++ b/scripts/mod/modpost.c @@ -17,6 +17,7 @@ #include #include #include +#include #include #include "modpost.h" #include "../../include/linux/license.h" @@ -29,20 +30,16 @@ static int have_vmlinux = 0; static int all_versions = 0; /* If we are modposting external module set to 1 */ static int external_module = 0; -#define MODULE_SCMVERSION_SIZE 64 -static char module_scmversion[MODULE_SCMVERSION_SIZE]; /* Only warn about unresolved symbols */ static int warn_unresolved = 0; /* How a symbol is exported */ static int sec_mismatch_count = 0; -static int sec_mismatch_warn_only = true; +static int sec_mismatch_fatal = 0; /* ignore missing files */ static int ignore_missing_files; /* If set to 1, only warn (instead of error) about missing ns imports */ static int allow_missing_ns_imports; -static bool error_occurred; - enum export { export_plain, export_unused, export_gpl, export_unused_gpl, export_gpl_future, export_unknown @@ -81,8 +78,14 @@ modpost_log(enum loglevel loglevel, const char *fmt, ...) if (loglevel == LOG_FATAL) exit(1); - if (loglevel == LOG_ERROR) - error_occurred = true; +} + +static inline bool strends(const char *str, const char *postfix) +{ + if (strlen(str) < strlen(postfix)) + return false; + + return strcmp(str + strlen(str) - strlen(postfix), postfix) == 0; } void *do_nofail(void *ptr, const char *expr) @@ -400,8 +403,8 @@ static void sym_update_namespace(const char *symname, const char *namespace) * actually an assertion. */ if (!s) { - error("Could not update namespace(%s) for symbol %s\n", - namespace, symname); + merror("Could not update namespace(%s) for symbol %s\n", + namespace, symname); return; } @@ -423,9 +426,10 @@ static struct symbol *sym_add_exported(const char *name, struct module *mod, s = new_symbol(name, mod, export); } else if (!external_module || s->module->is_vmlinux || s->module == mod) { - fatal("%s: '%s' exported twice. Previous export was in %s%s\n", - mod->name, name, s->module->name, - s->module->is_vmlinux ? "" : ".ko"); + warn("%s: '%s' exported twice. Previous export was in %s%s\n", + mod->name, name, s->module->name, + s->module->is_vmlinux ? "" : ".ko"); + return s; } s->module = mod; @@ -1267,7 +1271,8 @@ static int secref_whitelist(const struct sectioncheck *mismatch, static inline int is_arm_mapping_symbol(const char *str) { - return str[0] == '$' && strchr("axtd", str[1]) + return str[0] == '$' && + (str[1] == 'a' || str[1] == 'd' || str[1] == 't' || str[1] == 'x') && (str[2] == '\0' || str[2] == '.'); } @@ -1978,12 +1983,8 @@ static char *remove_dot(char *s) if (n && s[n]) { size_t m = strspn(s + n + 1, "0123456789"); - if (m && (s[n + m] == '.' || s[n + m] == 0)) + if (m && (s[n + m + 1] == '.' || s[n + m + 1] == 0)) s[n] = 0; - - /* strip trailing .lto */ - if (strends(s, ".lto")) - s[strlen(s) - 4] = '\0'; } return s; } @@ -2007,9 +2008,6 @@ static void read_symbols(const char *modname) /* strip trailing .o */ tmp = NOFAIL(strdup(modname)); tmp[strlen(tmp) - 2] = '\0'; - /* strip trailing .lto */ - if (strends(tmp, ".lto")) - tmp[strlen(tmp) - 4] = '\0'; mod = new_module(tmp); free(tmp); } @@ -2017,7 +2015,7 @@ static void read_symbols(const char *modname) if (!mod->is_vmlinux) { license = get_modinfo(&info, "license"); if (!license) - error("missing MODULE_LICENSE() in %s\n", modname); + warn("missing MODULE_LICENSE() in %s\n", modname); while (license) { if (license_is_gpl_compatible(license)) mod->gpl_compatible = 1; @@ -2144,11 +2142,11 @@ static void check_for_gpl_usage(enum export exp, const char *m, const char *s) { switch (exp) { case export_gpl: - error("GPL-incompatible module %s.ko uses GPL-only symbol '%s'\n", + fatal("GPL-incompatible module %s.ko uses GPL-only symbol '%s'\n", m, s); break; case export_unused_gpl: - error("GPL-incompatible module %s.ko uses GPL-only symbol marked UNUSED '%s'\n", + fatal("GPL-incompatible module %s.ko uses GPL-only symbol marked UNUSED '%s'\n", m, s); break; case export_gpl_future: @@ -2177,18 +2175,22 @@ static void check_for_unused(enum export exp, const char *m, const char *s) } } -static void check_exports(struct module *mod) +static int check_exports(struct module *mod) { struct symbol *s, *exp; + int err = 0; for (s = mod->unres; s; s = s->next) { const char *basename; exp = find_symbol(s->name); if (!exp || exp->module == mod) { - if (have_vmlinux && !s->weak) + if (have_vmlinux && !s->weak) { modpost_log(warn_unresolved ? LOG_WARN : LOG_ERROR, "\"%s\" [%s.ko] undefined!\n", s->name, mod->name); + if (!warn_unresolved) + err = 1; + } continue; } basename = strrchr(mod->name, '/'); @@ -2202,6 +2204,8 @@ static void check_exports(struct module *mod) modpost_log(allow_missing_ns_imports ? LOG_WARN : LOG_ERROR, "module %s uses symbol %s from namespace %s, but does not import it.\n", basename, exp->name, exp->namespace); + if (!allow_missing_ns_imports) + err = 1; add_namespace(&mod->missing_namespaces, exp->namespace); } @@ -2209,9 +2213,11 @@ static void check_exports(struct module *mod) check_for_gpl_usage(exp->export, basename, exp->name); check_for_unused(exp->export, basename, exp->name); } + + return err; } -static void check_modname_len(struct module *mod) +static int check_modname_len(struct module *mod) { const char *mod_name; @@ -2220,8 +2226,12 @@ static void check_modname_len(struct module *mod) mod_name = mod->name; else mod_name++; - if (strlen(mod_name) >= MODULE_NAME_LEN) - error("module name is too long [%s.ko]\n", mod->name); + if (strlen(mod_name) >= MODULE_NAME_LEN) { + merror("module name is too long [%s.ko]\n", mod->name); + return 1; + } + + return 0; } /** @@ -2263,20 +2273,6 @@ static void add_intree_flag(struct buffer *b, int is_intree) buf_printf(b, "\nMODULE_INFO(intree, \"Y\");\n"); } -/** - * add_scmversion() - Adds the MODULE_INFO macro for the scmversion. - * @b: Buffer to append to. - * - * This function fills in the module attribute `scmversion` for the kernel - * module. This is useful for determining a given module's SCM version on - * device via /sys/modules//scmversion and/or using the modinfo tool. - */ -static void add_scmversion(struct buffer *b) -{ - if (module_scmversion[0] != '\0') - buf_printf(b, "\nMODULE_INFO(scmversion, \"%s\");\n", module_scmversion); -} - /* Cannot check for assembler */ static void add_retpoline(struct buffer *b) { @@ -2294,9 +2290,10 @@ static void add_staging_flag(struct buffer *b, const char *name) /** * Record CRCs for unresolved symbols **/ -static void add_versions(struct buffer *b, struct module *mod) +static int add_versions(struct buffer *b, struct module *mod) { struct symbol *s, *exp; + int err = 0; for (s = mod->unres; s; s = s->next) { exp = find_symbol(s->name); @@ -2308,7 +2305,7 @@ static void add_versions(struct buffer *b, struct module *mod) } if (!modversions) - return; + return err; buf_printf(b, "\n"); buf_printf(b, "static const struct modversion_info ____versions[]\n"); @@ -2323,8 +2320,9 @@ static void add_versions(struct buffer *b, struct module *mod) continue; } if (strlen(s->name) >= MODULE_NAME_LEN) { - error("too long symbol \"%s\" [%s.ko]\n", - s->name, mod->name); + merror("too long symbol \"%s\" [%s.ko]\n", + s->name, mod->name); + err = 1; break; } buf_printf(b, "\t{ %#8x, \"%s\" },\n", @@ -2332,6 +2330,8 @@ static void add_versions(struct buffer *b, struct module *mod) } buf_printf(b, "};\n"); + + return err; } static void add_depends(struct buffer *b, struct module *mod) @@ -2542,11 +2542,12 @@ int main(int argc, char **argv) char *missing_namespace_deps = NULL; char *dump_write = NULL, *files_source = NULL; int opt; + int err; int n; struct dump_list *dump_read_start = NULL; struct dump_list **dump_read_iter = &dump_read_start; - while ((opt = getopt(argc, argv, "ei:mnT:o:awENd:v:")) != -1) { + while ((opt = getopt(argc, argv, "ei:mnT:o:awENd:")) != -1) { switch (opt) { case 'e': external_module = 1; @@ -2576,7 +2577,7 @@ int main(int argc, char **argv) warn_unresolved = 1; break; case 'E': - sec_mismatch_warn_only = false; + sec_mismatch_fatal = 1; break; case 'N': allow_missing_ns_imports = 1; @@ -2584,9 +2585,6 @@ int main(int argc, char **argv) case 'd': missing_namespace_deps = optarg; break; - case 'v': - strncpy(module_scmversion, optarg, sizeof(module_scmversion) - 1); - break; default: exit(1); } @@ -2614,6 +2612,8 @@ int main(int argc, char **argv) if (!have_vmlinux) warn("Symbol info of vmlinux is missing. Unresolved symbol check will be entirely skipped.\n"); + err = 0; + for (mod = modules; mod; mod = mod->next) { char fname[PATH_MAX]; @@ -2622,18 +2622,17 @@ int main(int argc, char **argv) buf.pos = 0; - check_modname_len(mod); - check_exports(mod); + err |= check_modname_len(mod); + err |= check_exports(mod); add_header(&buf, mod); add_intree_flag(&buf, !external_module); add_retpoline(&buf); add_staging_flag(&buf, mod->name); - add_versions(&buf, mod); + err |= add_versions(&buf, mod); add_depends(&buf, mod); add_moddevtable(&buf, mod); add_srcversion(&buf, mod); - add_scmversion(&buf); sprintf(fname, "%s.mod.c", mod->name); write_if_changed(&buf, fname); @@ -2644,21 +2643,21 @@ int main(int argc, char **argv) if (dump_write) write_dump(dump_write); - if (sec_mismatch_count && !sec_mismatch_warn_only) - error("Section mismatches detected.\n" + if (sec_mismatch_count && sec_mismatch_fatal) + fatal("Section mismatches detected.\n" "Set CONFIG_SECTION_MISMATCH_WARN_ONLY=y to allow them.\n"); for (n = 0; n < SYMBOL_HASH_SIZE; n++) { struct symbol *s; for (s = symbolhash[n]; s; s = s->next) { if (s->is_static) - error("\"%s\" [%s] is a static %s\n", - s->name, s->module->name, - export_str(s->export)); + warn("\"%s\" [%s] is a static %s\n", + s->name, s->module->name, + export_str(s->export)); } } free(buf.p); - return error_occurred ? 1 : 0; + return err; } diff --git a/scripts/mod/modpost.h b/scripts/mod/modpost.h index 1f76eea7c..3aa052722 100644 --- a/scripts/mod/modpost.h +++ b/scripts/mod/modpost.h @@ -2,7 +2,6 @@ #include #include #include -#include #include #include #include @@ -181,14 +180,6 @@ static inline unsigned int get_secindex(const struct elf_info *info, return info->symtab_shndx_start[sym - info->symtab_start]; } -static inline bool strends(const char *str, const char *postfix) -{ - if (strlen(str) < strlen(postfix)) - return false; - - return strcmp(str + strlen(str) - strlen(postfix), postfix) == 0; -} - /* file2alias.c */ extern unsigned int cross_build; void handle_moddevtable(struct module *mod, struct elf_info *info, @@ -210,19 +201,6 @@ enum loglevel { void modpost_log(enum loglevel loglevel, const char *fmt, ...); -/* - * warn - show the given message, then let modpost continue running, still - * allowing modpost to exit successfully. This should be used when - * we still allow to generate vmlinux and modules. - * - * error - show the given message, then let modpost continue running, but fail - * in the end. This should be used when we should stop building vmlinux - * or modules, but we can continue running modpost to catch as many - * issues as possible. - * - * fatal - show the given message, and bail out immediately. This should be - * used when there is no point to continue running modpost. - */ #define warn(fmt, args...) modpost_log(LOG_WARN, fmt, ##args) -#define error(fmt, args...) modpost_log(LOG_ERROR, fmt, ##args) +#define merror(fmt, args...) modpost_log(LOG_ERROR, fmt, ##args) #define fatal(fmt, args...) modpost_log(LOG_FATAL, fmt, ##args) diff --git a/scripts/mod/sumversion.c b/scripts/mod/sumversion.c index 760e6baa7..d587f40f1 100644 --- a/scripts/mod/sumversion.c +++ b/scripts/mod/sumversion.c @@ -391,14 +391,10 @@ void get_src_version(const char *modname, char sum[], unsigned sumlen) struct md4_ctx md; char *fname; char filelist[PATH_MAX + 1]; - int postfix_len = 1; - - if (strends(modname, ".lto.o")) - postfix_len = 5; /* objects for a module are listed in the first line of *.mod file. */ snprintf(filelist, sizeof(filelist), "%.*smod", - (int)strlen(modname) - postfix_len, modname); + (int)strlen(modname) - 1, modname); buf = read_text_file(filelist);