| @@ -348,26 +348,38 @@ static enum export export_from_sec(struct elf_info *elf, unsigned int sec) · 347 unmodified lines |
| 348 | 348 | return export_unknown; |
| 349 | 349 | } |
| 350 | 350 | |
| 351 | | −static char *sym_extract_namespace(const char **symname) |
| 351 | +static const char *namespace_from_kstrtabns(struct elf_info *info, |
| 352 | + Elf_Sym *kstrtabns) |
| 352 | 353 | { |
| 353 | | − char *namespace = NULL; |
| 354 | | − char *ns_separator; |
| 354 | + char *value = info->ksymtab_strings + kstrtabns->st_value; |
| 355 | + return value[0] ? value : NULL; |
| 356 | +} |
| 357 | + |
| 358 | +static void sym_update_namespace(const char *symname, const char *namespace) |
| 359 | +{ |
| 360 | + struct symbol *s = find_symbol(symname); |
| 355 | 361 | |
| 356 | | − ns_separator = strchr(*symname, '.'); |
| 357 | | − if (ns_separator) { |
| 358 | | − namespace = NOFAIL(strndup(*symname, ns_separator - *symname)); |
| 359 | | − *symname = ns_separator + 1; |
| 362 | + /* |
| 363 | + * That symbol should have been created earlier and thus this is |
| 364 | + * actually an assertion. |
| 365 | + */ |
| 366 | + if (!s) { |
| 367 | + merror("Could not update namespace(%s) for symbol %s\n", |
| 368 | + namespace, symname); |
| 369 | + return; |
| 360 | 370 | } |
| 361 | 371 | |
| 362 | | − return namespace; |
| 372 | + free(s->namespace); |
| 373 | + s->namespace = |
| 374 | + namespace && namespace[0] ? NOFAIL(strdup(namespace)) : NULL; |
| 363 | 375 | } |
| 364 | 376 | |
| 365 | 377 | /** |
| 366 | 378 | * Add an exported symbol - it may have already been added without a |
| 367 | 379 | * CRC, in this case just update the CRC |
| 368 | 380 | **/ |
| 369 | | −static struct symbol *sym_add_exported(const char *name, const char *namespace, |
| 370 | | − struct module *mod, enum export export) |
| 381 | +static struct symbol *sym_add_exported(const char *name, struct module *mod, |
| 382 | + enum export export) |
| 371 | 383 | { |
| 372 | 384 | struct symbol *s = find_symbol(name); |
| 373 | 385 | |
| @@ -383,8 +395,6 @@ static struct symbol *sym_add_exported(const char *name, const char *namespace, · 9 unmodified lines |
| 383 | 395 | s->module = mod; |
| 384 | 396 | } |
| 385 | 397 | } |
| 386 | | − free(s->namespace); |
| 387 | | − s->namespace = namespace ? strdup(namespace) : NULL; |
| 388 | 398 | s->preloaded = 0; |
| 389 | 399 | s->vmlinux = is_vmlinux(mod->name); |
| 390 | 400 | s->kernel = 0; |
| @@ -583,6 +593,10 @@ static int parse_elf(struct elf_info *info, const char *filename) · 192 unmodified lines |
| 583 | 593 | info->export_unused_gpl_sec = i; |
| 584 | 594 | else if (strcmp(secname, "__ksymtab_gpl_future") == 0) |
| 585 | 595 | info->export_gpl_future_sec = i; |
| 596 | + else if (strcmp(secname, "__ksymtab_strings") == 0) |
| 597 | + info->ksymtab_strings = (void *)hdr + |
| 598 | + sechdrs[i].sh_offset - |
| 599 | + sechdrs[i].sh_addr; |
| 586 | 600 | |
| 587 | 601 | if (sechdrs[i].sh_type == SHT_SYMTAB) { |
| 588 | 602 | unsigned int sh_link_idx; |
| @@ -672,7 +686,6 @@ static void handle_modversions(struct module *mod, struct elf_info *info, · 83 unmodified lines |
| 672 | 686 | enum export export; |
| 673 | 687 | bool is_crc = false; |
| 674 | 688 | const char *name; |
| 675 | | − char *namespace; |
| 676 | 689 | |
| 677 | 690 | if ((!is_vmlinux(mod->name) || mod->is_dot_o) && |
| 678 | 691 | strstarts(symname, "__ksymtab")) |
| @@ -745,9 +758,7 @@ static void handle_modversions(struct module *mod, struct elf_info *info, · 66 unmodified lines |
| 745 | 758 | /* All exported symbols */ |
| 746 | 759 | if (strstarts(symname, "__ksymtab_")) { |
| 747 | 760 | name = symname + strlen("__ksymtab_"); |
| 748 | | − namespace = sym_extract_namespace(&name); |
| 749 | | − sym_add_exported(name, namespace, mod, export); |
| 750 | | − free(namespace); |
| 761 | + sym_add_exported(name, mod, export); |
| 751 | 762 | } |
| 752 | 763 | if (strcmp(symname, "init_module") == 0) |
| 753 | 764 | mod->has_init = 1; |
| @@ -2043,6 +2054,16 @@ static void read_symbols(const char *modname) · 1289 unmodified lines |
| 2043 | 2054 | handle_moddevtable(mod, &info, sym, symname); |
| 2044 | 2055 | } |
| 2045 | 2056 | |
| 2057 | + /* Apply symbol namespaces from __kstrtabns_<symbol> entries. */ |
| 2058 | + for (sym = info.symtab_start; sym < info.symtab_stop; sym++) { |
| 2059 | + symname = remove_dot(info.strtab + sym->st_name); |
| 2060 | + |
| 2061 | + if (strstarts(symname, "__kstrtabns_")) |
| 2062 | + sym_update_namespace(symname + strlen("__kstrtabns_"), |
| 2063 | + namespace_from_kstrtabns(&info, |
| 2064 | + sym)); |
| 2065 | + } |
| 2066 | + |
| 2046 | 2067 | // check for static EXPORT_SYMBOL_* functions && global vars |
| 2047 | 2068 | for (sym = info.symtab_start; sym < info.symtab_stop; sym++) { |
| 2048 | 2069 | unsigned char bind = ELF_ST_BIND(sym->st_info); |
| @@ -2196,7 +2217,7 @@ static int check_exports(struct module *mod) · 147 unmodified lines |
| 2196 | 2217 | else |
| 2197 | 2218 | basename = mod->name; |
| 2198 | 2219 | |
| 2199 | | − if (exp->namespace && exp->namespace[0]) { |
| 2220 | + if (exp->namespace) { |
| 2200 | 2221 | add_namespace(&mod->required_namespaces, |
| 2201 | 2222 | exp->namespace); |
| 2202 | 2223 | |
| @@ -2454,12 +2475,12 @@ static void read_dump(const char *fname, unsigned int kernel) · 251 unmodified lines |
| 2454 | 2475 | mod = new_module(modname); |
| 2455 | 2476 | mod->skip = 1; |
| 2456 | 2477 | } |
| 2457 | | − s = sym_add_exported(symname, namespace, mod, |
| 2458 | | − export_no(export)); |
| 2478 | + s = sym_add_exported(symname, mod, export_no(export)); |
| 2459 | 2479 | s->kernel = kernel; |
| 2460 | 2480 | s->preloaded = 1; |
| 2461 | 2481 | s->is_static = 0; |
| 2462 | 2482 | sym_update_crc(symname, mod, crc, export_no(export)); |
| 2483 | + sym_update_namespace(symname, namespace); |
| 2463 | 2484 | } |
| 2464 | 2485 | release_file(file, size); |
| 2465 | 2486 | return; |