Since commit 13b25489b6f8 ("kbuild: change working directory to external module directory with M="), module paths are always relative to the top of the external module tree. The module paths recorded in Module.symvers are no longer globally unique when they are passed via KBUILD_EXTRA_SYMBOLS for building other external modules, which may result in false-positive "exported twice" errors. Such errors should not occur because external modules should be able to override in-tree modules. To address this, record the dump file path in struct module and check it when searching for a module.
Showing the changes to scripts (2 of 2 files). Show all
Unified · Split
| @@ -155,12 +155,13 @@ char *get_line(char **stringp) · 154 unmodified lines | |||
| 155 | /* A list of all modules we processed */ | 155 | /* A list of all modules we processed */ |
| 156 | LIST_HEAD(modules); | 156 | LIST_HEAD(modules); |
| 157 | 157 | ||
| 158 | static struct module *find_module(const char *modname) | 158 | static struct module *find_module(const char *filename, const char *modname) |
| 159 | { | 159 | { |
| 160 | struct module *mod; | 160 | struct module *mod; |
| 161 | 161 | ||
| 162 | list_for_each_entry(mod, &modules, list) { | 162 | list_for_each_entry(mod, &modules, list) { |
| 163 | if (strcmp(mod->name, modname) == 0) | 163 | if (!strcmp(mod->dump_file, filename) && |
| 164 | !strcmp(mod->name, modname)) | ||
| 164 | return mod; | 165 | return mod; |
| 165 | } | 166 | } |
| 166 | return NULL; | 167 | return NULL; |
| @@ -2030,10 +2031,10 @@ static void read_dump(const char *fname) · 1863 unmodified lines | |||
| 2030 | continue; | 2031 | continue; |
| 2031 | } | 2032 | } |
| 2032 | 2033 | ||
| 2033 | mod = find_module(modname); | 2034 | mod = find_module(fname, modname); |
| 2034 | if (!mod) { | 2035 | if (!mod) { |
| 2035 | mod = new_module(modname, strlen(modname)); | 2036 | mod = new_module(modname, strlen(modname)); |
| 2036 | mod->from_dump = true; | 2037 | mod->dump_file = fname; |
| 2037 | } | 2038 | } |
| 2038 | s = sym_add_exported(symname, mod, gpl_only, namespace); | 2039 | s = sym_add_exported(symname, mod, gpl_only, namespace); |
| 2039 | sym_set_crc(s, crc); | 2040 | sym_set_crc(s, crc); |
| @@ -2052,7 +2053,7 @@ static void write_dump(const char *fname) · 12 unmodified lines | |||
| 2052 | struct symbol *sym; | 2053 | struct symbol *sym; |
| 2053 | 2054 | ||
| 2054 | list_for_each_entry(mod, &modules, list) { | 2055 | list_for_each_entry(mod, &modules, list) { |
| 2055 | if (mod->from_dump) | 2056 | if (mod->dump_file) |
| 2056 | continue; | 2057 | continue; |
| 2057 | list_for_each_entry(sym, &mod->exported_symbols, list) { | 2058 | list_for_each_entry(sym, &mod->exported_symbols, list) { |
| 2058 | if (trim_unused_exports && !sym->used) | 2059 | if (trim_unused_exports && !sym->used) |
| @@ -2076,7 +2077,7 @@ static void write_namespace_deps_files(const char *fname) · 17 unmodified lines | |||
| 2076 | 2077 | ||
| 2077 | list_for_each_entry(mod, &modules, list) { | 2078 | list_for_each_entry(mod, &modules, list) { |
| 2078 | 2079 | ||
| 2079 | if (mod->from_dump || list_empty(&mod->missing_namespaces)) | 2080 | if (mod->dump_file || list_empty(&mod->missing_namespaces)) |
| 2080 | continue; | 2081 | continue; |
| 2081 | 2082 | ||
| 2082 | buf_printf(&ns_deps_buf, "%s.ko:", mod->name); | 2083 | buf_printf(&ns_deps_buf, "%s.ko:", mod->name); |
| @@ -2194,7 +2195,7 @@ int main(int argc, char **argv) · 111 unmodified lines | |||
| 2194 | read_symbols_from_files(files_source); | 2195 | read_symbols_from_files(files_source); |
| 2195 | 2196 | ||
| 2196 | list_for_each_entry(mod, &modules, list) { | 2197 | list_for_each_entry(mod, &modules, list) { |
| 2197 | if (mod->from_dump || mod->is_vmlinux) | 2198 | if (mod->dump_file || mod->is_vmlinux) |
| 2198 | continue; | 2199 | continue; |
| 2199 | 2200 | ||
| 2200 | check_modname_len(mod); | 2201 | check_modname_len(mod); |
| @@ -2205,7 +2206,7 @@ int main(int argc, char **argv) · 4 unmodified lines | |||
| 2205 | handle_white_list_exports(unused_exports_white_list); | 2206 | handle_white_list_exports(unused_exports_white_list); |
| 2206 | 2207 | ||
| 2207 | list_for_each_entry(mod, &modules, list) { | 2208 | list_for_each_entry(mod, &modules, list) { |
| 2208 | if (mod->from_dump) | 2209 | if (mod->dump_file) |
| 2209 | continue; | 2210 | continue; |
| 2210 | 2211 | ||
| 2211 | if (mod->is_vmlinux) | 2212 | if (mod->is_vmlinux) |
| @@ -95,14 +95,15 @@ struct module_alias { · 94 unmodified lines | |||
| 95 | /** | 95 | /** |
| 96 | * struct module - represent a module (vmlinux or *.ko) | 96 | * struct module - represent a module (vmlinux or *.ko) |
| 97 | * | 97 | * |
| 98 | * @dump_file: path to the .symvers file if loaded from a file | ||
| 98 | * @aliases: list head for module_aliases | 99 | * @aliases: list head for module_aliases |
| 99 | */ | 100 | */ |
| 100 | struct module { | 101 | struct module { |
| 101 | struct list_head list; | 102 | struct list_head list; |
| 102 | struct list_head exported_symbols; | 103 | struct list_head exported_symbols; |
| 103 | struct list_head unresolved_symbols; | 104 | struct list_head unresolved_symbols; |
| 105 | const char *dump_file; | ||
| 104 | bool is_gpl_compatible; | 106 | bool is_gpl_compatible; |
| 105 | bool from_dump; /* true if module was loaded from *.symvers */ | ||
| 106 | bool is_vmlinux; | 107 | bool is_vmlinux; |
| 107 | bool seen; | 108 | bool seen; |
| 108 | bool has_init; | 109 | bool has_init; |