diff options
Diffstat (limited to 'scripts/mod/modpost.c')
-rw-r--r-- | scripts/mod/modpost.c | 114 |
1 files changed, 63 insertions, 51 deletions
diff --git a/scripts/mod/modpost.c b/scripts/mod/modpost.c index 0d998c54564d..0de2fb236640 100644 --- a/scripts/mod/modpost.c +++ b/scripts/mod/modpost.c @@ -1163,6 +1163,14 @@ static const struct sectioncheck *section_mismatch( * fromsec = text section * refsymname = *.constprop.* * + * Pattern 6: + * Hide section mismatch warnings for ELF local symbols. The goal + * is to eliminate false positive modpost warnings caused by + * compiler-generated ELF local symbol names such as ".LANCHOR1". + * Autogenerated symbol names bypass modpost's "Pattern 2" + * whitelisting, which relies on pattern-matching against symbol + * names to work. (One situation where gcc can autogenerate ELF + * local symbols is when "-fsection-anchors" is used.) **/ static int secref_whitelist(const struct sectioncheck *mismatch, const char *fromsec, const char *fromsym, @@ -1201,9 +1209,37 @@ static int secref_whitelist(const struct sectioncheck *mismatch, match(fromsym, optim_symbols)) return 0; + /* Check for pattern 6 */ + if (strstarts(fromsym, ".L")) + return 0; + return 1; } +static inline int is_arm_mapping_symbol(const char *str) +{ + return str[0] == '$' && strchr("axtd", str[1]) + && (str[2] == '\0' || str[2] == '.'); +} + +/* + * If there's no name there, ignore it; likewise, ignore it if it's + * one of the magic symbols emitted used by current ARM tools. + * + * Otherwise if find_symbols_between() returns those symbols, they'll + * fail the whitelist tests and cause lots of false alarms ... fixable + * only by merging __exit and __init sections into __text, bloating + * the kernel (which is especially evil on embedded platforms). + */ +static inline int is_valid_name(struct elf_info *elf, Elf_Sym *sym) +{ + const char *name = elf->strtab + sym->st_name; + + if (!name || !strlen(name)) + return 0; + return !is_arm_mapping_symbol(name); +} + /** * Find symbol based on relocation record info. * In some cases the symbol supplied is a valid symbol so @@ -1229,6 +1265,8 @@ static Elf_Sym *find_elf_symbol(struct elf_info *elf, Elf64_Sword addr, continue; if (ELF_ST_TYPE(sym->st_info) == STT_SECTION) continue; + if (!is_valid_name(elf, sym)) + continue; if (sym->st_value == addr) return sym; /* Find a symbol nearby - addr are maybe negative */ @@ -1247,30 +1285,6 @@ static Elf_Sym *find_elf_symbol(struct elf_info *elf, Elf64_Sword addr, return NULL; } -static inline int is_arm_mapping_symbol(const char *str) -{ - return str[0] == '$' && strchr("axtd", str[1]) - && (str[2] == '\0' || str[2] == '.'); -} - -/* - * If there's no name there, ignore it; likewise, ignore it if it's - * one of the magic symbols emitted used by current ARM tools. - * - * Otherwise if find_symbols_between() returns those symbols, they'll - * fail the whitelist tests and cause lots of false alarms ... fixable - * only by merging __exit and __init sections into __text, bloating - * the kernel (which is especially evil on embedded platforms). - */ -static inline int is_valid_name(struct elf_info *elf, Elf_Sym *sym) -{ - const char *name = elf->strtab + sym->st_name; - - if (!name || !strlen(name)) - return 0; - return !is_arm_mapping_symbol(name); -} - /* * Find symbols before or equal addr and after addr - in the section sec. * If we find two symbols with equal offset prefer one with a valid name. @@ -2083,15 +2097,27 @@ 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 (!exp || exp->module == mod) { + if (have_vmlinux && !s->weak) { + if (warn_unresolved) { + warn("\"%s\" [%s.ko] undefined!\n", + s->name, mod->name); + } else { + merror("\"%s\" [%s.ko] undefined!\n", + s->name, mod->name); + err = 1; + } + } continue; + } basename = strrchr(mod->name, '/'); if (basename) basename++; @@ -2101,6 +2127,8 @@ 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 int check_modname_len(struct module *mod) @@ -2178,19 +2206,8 @@ static int add_versions(struct buffer *b, struct module *mod) for (s = mod->unres; s; s = s->next) { exp = find_symbol(s->name); - if (!exp || exp->module == mod) { - if (have_vmlinux && !s->weak) { - if (warn_unresolved) { - warn("\"%s\" [%s.ko] undefined!\n", - s->name, mod->name); - } else { - merror("\"%s\" [%s.ko] undefined!\n", - s->name, mod->name); - err = 1; - } - } + if (!exp || exp->module == mod) continue; - } s->module = exp->module; s->crc_valid = exp->crc_valid; s->crc = exp->crc; @@ -2227,15 +2244,15 @@ static int add_versions(struct buffer *b, struct module *mod) return err; } -static void add_depends(struct buffer *b, struct module *mod, - struct module *modules) +static void add_depends(struct buffer *b, struct module *mod) { struct symbol *s; - struct module *m; int first = 1; - for (m = modules; m; m = m->next) - m->seen = is_vmlinux(m->name); + /* Clear ->seen flag of modules that own symbols needed by this. */ + for (s = mod->unres; s; s = s->next) + if (s->module) + s->module->seen = is_vmlinux(s->module->name); buf_printf(b, "\n"); buf_printf(b, "static const char __module_depends[]\n"); @@ -2416,7 +2433,7 @@ int main(int argc, char **argv) struct ext_sym_list *extsym_iter; struct ext_sym_list *extsym_start = NULL; - while ((opt = getopt(argc, argv, "i:I:e:mnsST:o:awM:K:E")) != -1) { + while ((opt = getopt(argc, argv, "i:I:e:mnsST:o:awE")) != -1) { switch (opt) { case 'i': kernel_read = optarg; @@ -2482,12 +2499,6 @@ int main(int argc, char **argv) if (files_source) read_symbols_from_files(files_source); - for (mod = modules; mod; mod = mod->next) { - if (mod->skip) - continue; - check_exports(mod); - } - err = 0; for (mod = modules; mod; mod = mod->next) { @@ -2499,12 +2510,13 @@ int main(int argc, char **argv) buf.pos = 0; 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); err |= add_versions(&buf, mod); - add_depends(&buf, mod, modules); + add_depends(&buf, mod); add_moddevtable(&buf, mod); add_srcversion(&buf, mod); |