diff options
author | Masahiro Yamada <yamada.masahiro@socionext.com> | 2019-11-15 02:42:24 +0900 |
---|---|---|
committer | Masahiro Yamada <yamada.masahiro@socionext.com> | 2019-11-23 15:46:38 +0900 |
commit | 1743694eb2357b47cd9951079f9ab0d728c916bf (patch) | |
tree | f67c68b27da8917a996c4d947f55224668134a48 | |
parent | 9bd2a099d7224281dd7756efa5c79df4f3fe8daf (diff) |
modpost: stop symbol preloading for modversion CRC
It is complicated to add mocked-up symbols for pre-handling CRC.
Handle CRC after all the export symbols in the relevant module
are registered.
Call handle_modversion() after the handle_symbol() iteration.
In some cases, I see atand-alone __crc_* without __ksymtab_*.
For example, ARCH=arm allyesconfig produces __crc_ccitt_veneer and
__crc_itu_t_veneer. I guess they come from crc_ccitt, crc_itu_t,
respectively. Since __*_veneer are auto-generated symbols, just
ignore them.
Signed-off-by: Masahiro Yamada <yamada.masahiro@socionext.com>
-rw-r--r-- | scripts/mod/modpost.c | 71 |
1 files changed, 39 insertions, 32 deletions
diff --git a/scripts/mod/modpost.c b/scripts/mod/modpost.c index 6735ae3da4c2..1c22cf7aa732 100644 --- a/scripts/mod/modpost.c +++ b/scripts/mod/modpost.c @@ -169,7 +169,7 @@ struct symbol { unsigned int vmlinux:1; /* 1 if symbol is defined in vmlinux */ unsigned int kernel:1; /* 1 if symbol is from kernel * (only for external modules) **/ - unsigned int preloaded:1; /* 1 if symbol from Module.symvers, or crc */ + unsigned int preloaded:1; /* 1 if symbol from Module.symvers */ unsigned int is_static:1; /* 1 if symbol is not global */ enum export export; /* Type of export */ char name[0]; @@ -410,16 +410,17 @@ static struct symbol *sym_add_exported(const char *name, struct module *mod, return s; } -static void sym_update_crc(const char *name, struct module *mod, - unsigned int crc, enum export export) +static void sym_set_crc(const char *name, unsigned int crc) { struct symbol *s = find_symbol(name); - if (!s) { - s = new_symbol(name, mod, export); - /* Don't complain when we find it later. */ - s->preloaded = 1; - } + /* + * Ignore stand-alone __crc_*, which might be auto-generated symbols + * such as __*_veneer in ARM ELF. + */ + if (!s) + return; + s->crc = crc; s->crc_valid = 1; } @@ -683,12 +684,34 @@ static int ignore_undef_symbol(struct elf_info *info, const char *symname) return 0; } +static void handle_modversion(const struct module *mod, + const struct elf_info *info, + const Elf_Sym *sym, const char *symname) +{ + unsigned int crc; + + if (sym->st_shndx == SHN_UNDEF) { + warn("EXPORT symbol \"%s\" [%s%s] version generation failed, symbol will not be versioned.\n", + symname, mod->name, is_vmlinux(mod->name) ? "":".ko"); + return; + } + + if (sym->st_shndx == SHN_ABS) { + crc = sym->st_value; + } else { + unsigned int *crcp; + + /* symbol points to the CRC in the ELF object */ + crcp = sym_get_data(info, sym); + crc = TO_NATIVE(*crcp); + } + sym_set_crc(symname, crc); +} + static void handle_symbol(struct module *mod, struct elf_info *info, const Elf_Sym *sym, const char *symname) { - unsigned int crc; enum export export; - bool is_crc = false; const char *name; if ((!is_vmlinux(mod->name) || mod->is_dot_o) && @@ -697,21 +720,6 @@ static void handle_symbol(struct module *mod, struct elf_info *info, else export = export_from_sec(info, get_secindex(info, sym)); - /* CRC'd symbol */ - if (strstarts(symname, "__crc_")) { - is_crc = true; - crc = (unsigned int) sym->st_value; - if (sym->st_shndx != SHN_UNDEF && sym->st_shndx != SHN_ABS) { - unsigned int *crcp; - - /* symbol points to the CRC in the ELF object */ - crcp = sym_get_data(info, sym); - crc = TO_NATIVE(*crcp); - } - sym_update_crc(symname + strlen("__crc_"), mod, crc, - export); - } - switch (sym->st_shndx) { case SHN_COMMON: if (strstarts(symname, "__gnu_lto_")) { @@ -746,11 +754,6 @@ static void handle_symbol(struct module *mod, struct elf_info *info, } #endif - if (is_crc) { - const char *e = is_vmlinux(mod->name) ?"":".ko"; - warn("EXPORT symbol \"%s\" [%s%s] version generation failed, symbol will not be versioned.\n", - symname + strlen("__crc_"), mod->name, e); - } mod->unres = alloc_symbol(symname, ELF_ST_BIND(sym->st_info) == STB_WEAK, mod->unres); @@ -2055,14 +2058,18 @@ static void read_symbols(const char *modname) handle_moddevtable(mod, &info, sym, symname); } - /* Apply symbol namespaces from __kstrtabns_<symbol> entries. */ for (sym = info.symtab_start; sym < info.symtab_stop; sym++) { symname = remove_dot(info.strtab + sym->st_name); + /* Apply symbol namespaces from __kstrtabns_<symbol> entries. */ if (strstarts(symname, "__kstrtabns_")) sym_update_namespace(symname + strlen("__kstrtabns_"), namespace_from_kstrtabns(&info, sym)); + + if (strstarts(symname, "__crc_")) + handle_modversion(mod, &info, sym, + symname + strlen("__crc_")); } // check for static EXPORT_SYMBOL_* functions && global vars @@ -2476,7 +2483,7 @@ static void read_dump(const char *fname, unsigned int kernel) s->kernel = kernel; s->preloaded = 1; s->is_static = 0; - sym_update_crc(symname, mod, crc, export_no(export)); + sym_set_crc(symname, crc); sym_update_namespace(symname, namespace); } release_file(file, size); |