Making sure to not double-examine the same DWARF CU
authorDima Kogan <dima@secretsauce.net>
Wed, 21 May 2014 10:47:33 +0000 (03:47 -0700)
committerChanho Park <chanho61.park@samsung.com>
Fri, 22 Aug 2014 11:38:26 +0000 (20:38 +0900)
dwarf_prototypes.c
library.c
library.h
output.c
proc.c
proc.h

index 4860e4d..6094658 100644 (file)
@@ -979,7 +979,8 @@ static bool process_die_compileunit(struct protolib *plib, struct library *lib,
        return true;
 }
 
-static void import(struct protolib *plib, struct library *lib, Dwfl *dwfl)
+static void import(struct protolib *plib, struct library *lib,
+                  Dwfl_Module *dwfl_module)
 {
        // A map from DIE addresses (Dwarf_Off) to type structures (struct
        // arg_type_info*). This is created and filled in at the start of each
@@ -992,7 +993,7 @@ static void import(struct protolib *plib, struct library *lib, Dwfl *dwfl)
 
        Dwarf_Addr bias;
        Dwarf_Die *die = NULL;
-       while ((die = dwfl_nextcu(dwfl, die, &bias)) != NULL) {
+       while ((die = dwfl_module_nextcu(dwfl_module, die, &bias)) != NULL) {
                if (dwarf_tag(die) == DW_TAG_compile_unit)
                        process_die_compileunit(plib, lib,
                                                &type_dieoffset_hash, die);
@@ -1007,7 +1008,6 @@ static void import(struct protolib *plib, struct library *lib, Dwfl *dwfl)
 bool import_DWARF_prototypes(struct library *lib)
 {
        struct protolib *plib = lib->protolib;
-       Dwfl *dwfl = lib->dwfl;
 
        debug(DEBUG_FUNCTION, "Importing DWARF prototypes from '%s'",
              lib->soname);
@@ -1026,7 +1026,7 @@ bool import_DWARF_prototypes(struct library *lib)
                }
        }
 
-       import(plib, lib, dwfl);
+       import(plib, lib, lib->dwfl_module);
        lib->protolib = plib;
 
        return true;
index 13d8d45..3a22519 100644 (file)
--- a/library.c
+++ b/library.c
@@ -296,7 +296,7 @@ private_library_init(struct library *lib, enum library_type type)
        lib->type = type;
 
 #if defined(HAVE_LIBDW)
-       lib->dwfl = NULL;
+       lib->dwfl_module = NULL;
 #endif
 }
 
index 82dc048..4d649e0 100644 (file)
--- a/library.h
+++ b/library.h
@@ -176,7 +176,7 @@ struct library {
        struct os_library_data os;
 
 #if defined(HAVE_LIBDW)
-       Dwfl *dwfl;
+       Dwfl_Module *dwfl_module;
 #endif
 };
 
index 8d378ea..10faee2 100644 (file)
--- a/output.c
+++ b/output.c
@@ -216,7 +216,7 @@ library_get_prototype(struct library *lib, const char *name)
 #if defined(HAVE_LIBDW)
                // DWARF data fills in the gaps in the .conf files, so I don't
                // check for lib->protolib==NULL here
-               if (lib->dwfl != NULL &&
+               if (lib->dwfl_module != NULL &&
                    (filter_matches_library(options.plt_filter,    lib ) ||
                     filter_matches_library(options.static_filter, lib ) ||
                     filter_matches_library(options.export_filter, lib )))
diff --git a/proc.c b/proc.c
index 7c370a3..5385510 100644 (file)
--- a/proc.c
+++ b/proc.c
@@ -175,6 +175,7 @@ process_bare_init(struct process *proc, const char *filename,
 
 #if defined(HAVE_LIBDW)
        proc->dwfl = NULL; /* Initialize for leader only on first library.  */
+       proc->should_attach_dwfl = 1; /* should try to attach the DWFL data */
 #endif /* defined(HAVE_LIBDW) */
 
        return 0;
@@ -894,6 +895,7 @@ proc_add_library(struct process *proc, struct library *lib)
 
 #if defined(HAVE_LIBDW)
        Dwfl *dwfl = NULL;
+       Dwfl_Module *dwfl_module = NULL;
 
        /* Setup module tracking for libdwfl unwinding.  */
        struct process *leader = proc->leader;
@@ -913,24 +915,26 @@ proc_add_library(struct process *proc, struct library *lib)
 
        if (dwfl != NULL) {
                dwfl_report_begin_add(dwfl);
-               if (dwfl_report_elf(dwfl, lib->soname,
-                                   lib->pathname, -1,
-                                   (GElf_Addr) lib->base,
-                                   false) == NULL)
+               dwfl_module =
+                       dwfl_report_elf(dwfl, lib->soname,
+                                       lib->pathname, -1,
+                                       (GElf_Addr) lib->base,
+                                       false);
+               if (dwfl_module == NULL)
                        fprintf(stderr,
                                "dwfl_report_elf %s@%p (%s) %d: %s\n",
                                lib->soname, lib->base, lib->pathname,
                                proc->pid, dwfl_errmsg (-1));
+
                dwfl_report_end(dwfl, NULL, NULL);
 
                if (options.bt_depth > 0) {
-                       if (leader->dwfl == NULL) {
+                       if (proc->should_attach_dwfl) {
                                int r = dwfl_linux_proc_attach(dwfl,
                                                               leader->pid,
                                                               true);
-                               if (r == 0)
-                                       leader->dwfl = dwfl;
-                               else {
+                               proc->should_attach_dwfl = 0;
+                               if (r != 0) {
                                        const char *msg;
                                        dwfl_end(dwfl);
                                        if (r < 0)
@@ -946,7 +950,8 @@ proc_add_library(struct process *proc, struct library *lib)
                }
        }
 
-       lib->dwfl = dwfl;
+       lib->dwfl_module = dwfl_module;
+       leader->dwfl = dwfl;
 
 #endif /* defined(HAVE_LIBDW) */
 
diff --git a/proc.h b/proc.h
index 659c786..c1408be 100644 (file)
--- a/proc.h
+++ b/proc.h
@@ -121,6 +121,12 @@ struct process {
 #if defined(HAVE_LIBDW)
        /* Unwind info for leader, NULL for non-leader procs. */
        Dwfl *dwfl;
+
+       /* Whether we still need to attach the DWARF library to this process. We
+        * try only once, and never again, regardless of whether we succeeded or
+        * not. 0 = shouldn't attach */
+       int should_attach_dwfl;
+
 #endif /* defined(HAVE_LIBDW) */
 
 #if defined(HAVE_LIBUNWIND)