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 | 155 | /* A list of all modules we processed */ |
| 156 | 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 | 160 | struct module *mod; |
| 161 | 161 | |
| 162 | 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 | 165 | return mod; |
| 165 | 166 | } |
| 166 | 167 | return NULL; |
| @@ -2030,10 +2031,10 @@ static void read_dump(const char *fname) · 1863 unmodified lines | ||
| 2030 | 2031 | continue; |
| 2031 | 2032 | } |
| 2032 | 2033 | |
| 2033 | − mod = find_module(modname); | |
| 2034 | + mod = find_module(fname, modname); | |
| 2034 | 2035 | if (!mod) { |
| 2035 | 2036 | mod = new_module(modname, strlen(modname)); |
| 2036 | − mod->from_dump = true; | |
| 2037 | + mod->dump_file = fname; | |
| 2037 | 2038 | } |
| 2038 | 2039 | s = sym_add_exported(symname, mod, gpl_only, namespace); |
| 2039 | 2040 | sym_set_crc(s, crc); |
| @@ -2052,7 +2053,7 @@ static void write_dump(const char *fname) · 12 unmodified lines | ||
| 2052 | 2053 | struct symbol *sym; |
| 2053 | 2054 | |
| 2054 | 2055 | list_for_each_entry(mod, &modules, list) { |
| 2055 | − if (mod->from_dump) | |
| 2056 | + if (mod->dump_file) | |
| 2056 | 2057 | continue; |
| 2057 | 2058 | list_for_each_entry(sym, &mod->exported_symbols, list) { |
| 2058 | 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 | 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 | 2081 | continue; |
| 2081 | 2082 | |
| 2082 | 2083 | buf_printf(&ns_deps_buf, "%s.ko:", mod->name); |
| @@ -2194,7 +2195,7 @@ int main(int argc, char **argv) · 111 unmodified lines | ||
| 2194 | 2195 | read_symbols_from_files(files_source); |
| 2195 | 2196 | |
| 2196 | 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 | 2199 | continue; |
| 2199 | 2200 | |
| 2200 | 2201 | check_modname_len(mod); |
| @@ -2205,7 +2206,7 @@ int main(int argc, char **argv) · 4 unmodified lines | ||
| 2205 | 2206 | handle_white_list_exports(unused_exports_white_list); |
| 2206 | 2207 | |
| 2207 | 2208 | list_for_each_entry(mod, &modules, list) { |
| 2208 | − if (mod->from_dump) | |
| 2209 | + if (mod->dump_file) | |
| 2209 | 2210 | continue; |
| 2210 | 2211 | |
| 2211 | 2212 | if (mod->is_vmlinux) |
| @@ -95,14 +95,15 @@ struct module_alias { · 94 unmodified lines | ||
| 95 | 95 | /** |
| 96 | 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 | 99 | * @aliases: list head for module_aliases |
| 99 | 100 | */ |
| 100 | 101 | struct module { |
| 101 | 102 | struct list_head list; |
| 102 | 103 | struct list_head exported_symbols; |
| 103 | 104 | struct list_head unresolved_symbols; |
| 105 | + const char *dump_file; | |
| 104 | 106 | bool is_gpl_compatible; |
| 105 | − bool from_dump; /* true if module was loaded from *.symvers */ | |
| 106 | 107 | bool is_vmlinux; |
| 107 | 108 | bool seen; |
| 108 | 109 | bool has_init; |