From: Nick Alcock Date: Mon, 18 Jun 2012 15:57:59 +0000 (+0100) Subject: kallsyms: fix /proc/kallmodsyms population bugs X-Git-Tag: v4.1.12-92~313^2~147 X-Git-Url: https://www.infradead.org/git/?a=commitdiff_plain;h=bc08ead8ce57ebb1e99a08b2acc0a9c33e72f36b;p=users%2Fjedix%2Flinux-maple.git kallsyms: fix /proc/kallmodsyms population bugs scripts/kallsyms was failing to identify variables local to modules as being in those modules, which is unfortunate because a large number of DTrace module references are to data symbols. This is easily enough fixed by recording variable references as well as function references, which was all we were tracking before this. Alas, this breaks our heuristic that symbols whose names are seen more than once must be outside all modules, because external variable references can be seen multiple times inside a single module even when the thing they are a reference to is also inside that module. The fix to this is to differentiate between 'names seen in this module' and 'names seen in prior modules', recording newly-seen names in the former list and moving them en masse to the latter when we switch from scanning one module to scanning another. We can then define a symbol as being 'not in any module' iff it is seen while present in the names-seen-in-prior-modules list: a symbol that is seen repeatedly but only inside a single module's object file is still considered to be part of that module under this scheme. Signed-off-by: Nick Alcock --- diff --git a/scripts/kallsyms.c b/scripts/kallsyms.c index 8d65769555fc..b96f2328b470 100644 --- a/scripts/kallsyms.c +++ b/scripts/kallsyms.c @@ -805,6 +805,13 @@ static void read_module_symbols(unsigned int module_name, Dwarf_Die *tu = NULL; Dwarf_Addr junk; unsigned int *module_idx = NULL; + GHashTable *this_module_symbol_seen; + GHashTableIter copying_iter; + void *copying_name; + void *copying_dummy_value; + + this_module_symbol_seen = g_hash_table_new_full(g_str_hash, g_str_equal, + free, NULL); while ((tu = dwfl_nextcu(dwfl, tu, &junk)) != NULL) { Dwarf_Die toplevel; @@ -828,7 +835,8 @@ static void read_module_symbols(unsigned int module_name, } do { - if (dwarf_tag(&toplevel) == DW_TAG_subprogram) { + if ((dwarf_tag(&toplevel) == DW_TAG_subprogram) || + (dwarf_tag(&toplevel) == DW_TAG_variable)) { if (module_idx == NULL) { module_idx = malloc(sizeof(unsigned int)); if (module_idx == NULL) { @@ -839,24 +847,32 @@ static void read_module_symbols(unsigned int module_name, *module_idx = module_name; } /* - * If we have never seen this symbol before, we - * note that we have seen it, and track it in - * the symbol_to_module mapping. Otherwise, we - * *remove* it from that mapping, if it is - * present there. + * If we have never seen this symbol before + * outside of this module, we note that we have + * now seen it in this module, and track it in + * the symbol_to_module mapping. Otherwise, + * this symbol appears in multiple modules and + * is not a per-module symbol: *remove* it from + * that mapping, if it is present there. */ if (!g_hash_table_lookup_extended(module_symbol_seen, dwarf_diename(&toplevel), NULL, NULL)) { - g_hash_table_insert(module_symbol_seen, - strdup(dwarf_diename(&toplevel)), - NULL); - - g_hash_table_insert(symbol_to_module, - strdup(dwarf_diename(&toplevel)), - module_idx); + if (!g_hash_table_lookup_extended (symbol_to_module, + dwarf_diename(&toplevel), + NULL, NULL)) + g_hash_table_insert(symbol_to_module, + strdup(dwarf_diename(&toplevel)), + module_idx); + + if (!g_hash_table_lookup_extended (this_module_symbol_seen, + dwarf_diename(&toplevel), + NULL, NULL)) + g_hash_table_insert(this_module_symbol_seen, + strdup(dwarf_diename(&toplevel)), + NULL); } else { g_hash_table_remove(symbol_to_module, strdup(dwarf_diename(&toplevel))); @@ -871,6 +887,19 @@ static void read_module_symbols(unsigned int module_name, } } private_dwfl_free(dwfl); + + /* + * Work over all the symbols seen in this module and note that in future + * they are to be considered symbols that were seen in some other + * module. + */ + g_hash_table_iter_init(©ing_iter, this_module_symbol_seen); + while (g_hash_table_iter_next(©ing_iter, ©ing_name, + ©ing_dummy_value)) + g_hash_table_insert(module_symbol_seen, + strdup((char *) copying_name), NULL); + + g_hash_table_destroy(this_module_symbol_seen); } /*