]> www.infradead.org Git - users/jedix/linux-maple.git/commitdiff
kallsyms: fix /proc/kallmodsyms population bugs
authorNick Alcock <nick.alcock@oracle.com>
Mon, 18 Jun 2012 15:57:59 +0000 (16:57 +0100)
committerNick Alcock <nick.alcock@oracle.com>
Mon, 29 Jun 2015 21:40:25 +0000 (22:40 +0100)
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 <nick.alcock@oracle.com>
scripts/kallsyms.c

index 8d65769555fc15110df38ee478dadee05df331d6..b96f2328b4704c081e0155d8b5298a6ded4d05bf 100644 (file)
@@ -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(&copying_iter, this_module_symbol_seen);
+       while (g_hash_table_iter_next(&copying_iter, &copying_name,
+                                     &copying_dummy_value))
+               g_hash_table_insert(module_symbol_seen,
+                                   strdup((char *) copying_name), NULL);
+
+       g_hash_table_destroy(this_module_symbol_seen);
 }
 
 /*