DWARF parser now looks for exported types
[platform/upstream/ltrace.git] / proc.c
diff --git a/proc.c b/proc.c
index 11755b0..f08f947 100644 (file)
--- a/proc.c
+++ b/proc.c
@@ -1,6 +1,6 @@
 /*
  * This file is part of ltrace.
- * Copyright (C) 2011,2012,2013 Petr Machata, Red Hat Inc.
+ * Copyright (C) 2011,2012,2013,2014 Petr Machata, Red Hat Inc.
  * Copyright (C) 2010 Joe Damato
  * Copyright (C) 1998,2009 Juan Cespedes
  *
 #include <stdlib.h>
 #include <string.h>
 
-#if defined(HAVE_LIBUNWIND)
-#include <libunwind.h>
-#include <libunwind-ptrace.h>
-#endif /* defined(HAVE_LIBUNWIND) */
-
 #include "backend.h"
 #include "breakpoint.h"
 #include "debug.h"
@@ -41,6 +36,7 @@
 #include "options.h"
 #include "proc.h"
 #include "value_dict.h"
+#include "dwarf_prototypes.h"
 
 #ifndef OS_HAVE_PROCESS_DATA
 int
@@ -111,6 +107,11 @@ destroy_unwind(struct process *proc)
        if (proc->unwind_as != NULL)
                unw_destroy_addr_space(proc->unwind_as);
 #endif /* defined(HAVE_LIBUNWIND) */
+
+#if defined(HAVE_LIBDW)
+       if (proc->dwfl != NULL)
+               dwfl_end(proc->dwfl);
+#endif /* defined(HAVE_LIBDW) */
 }
 
 static int
@@ -172,6 +173,10 @@ process_bare_init(struct process *proc, const char *filename,
        }
 #endif /* defined(HAVE_LIBUNWIND) */
 
+#if defined(HAVE_LIBDW)
+       proc->dwfl = NULL; /* Initialize for leader only on first library.  */
+#endif /* defined(HAVE_LIBDW) */
+
        return 0;
 }
 
@@ -220,9 +225,11 @@ process_init(struct process *proc, const char *filename, pid_t pid)
                goto fail;
        }
 
-       if (proc->leader != proc)
-               return 0;
-       if (process_init_main(proc) < 0) {
+       if (proc->leader != proc) {
+               proc->e_machine = proc->leader->e_machine;
+               proc->e_class = proc->leader->e_class;
+               get_arch_dep(proc);
+       } else if (process_init_main(proc) < 0) {
                process_bare_destroy(proc, 0);
                goto fail;
        }
@@ -885,6 +892,64 @@ proc_add_library(struct process *proc, struct library *lib)
        debug(DEBUG_PROCESS, "added library %s@%p (%s) to %d",
              lib->soname, lib->base, lib->pathname, proc->pid);
 
+#if defined(HAVE_LIBDW)
+       Dwfl *dwfl = NULL;
+
+       /* Setup module tracking for libdwfl unwinding.  */
+       struct process *leader = proc->leader;
+       dwfl = leader->dwfl;
+       if (dwfl == NULL) {
+               static const Dwfl_Callbacks proc_callbacks = {
+                       .find_elf = dwfl_linux_proc_find_elf,
+                       .find_debuginfo = dwfl_standard_find_debuginfo
+               };
+               dwfl = dwfl_begin(&proc_callbacks);
+               if (dwfl == NULL)
+                       fprintf(stderr,
+                                       "Couldn't initialize libdwfl unwinding "
+                                       "for process %d: %s\n", leader->pid,
+                                       dwfl_errmsg (-1));
+       }
+
+       if (dwfl != NULL) {
+               dwfl_report_begin_add(dwfl);
+               if (dwfl_report_elf(dwfl, lib->soname,
+                                                       lib->pathname, -1,
+                                                       (GElf_Addr) lib->base,
+                                                       false) == 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) {
+                               int r = dwfl_linux_proc_attach(dwfl,
+                                                              leader->pid,
+                                                              true);
+                               if (r == 0)
+                                       leader->dwfl = dwfl;
+                               else {
+                                       const char *msg;
+                                       dwfl_end(dwfl);
+                                       if (r < 0)
+                                               msg = dwfl_errmsg(-1);
+                                       else
+                                               msg = strerror(r);
+                                       fprintf(stderr, "Couldn't initialize "
+                                               "libdwfl (for unwinding, prototype import) for "
+                                               "process %d: %s\n",
+                                               leader->pid, msg);
+                               }
+                       }
+               }
+       }
+
+       lib->dwfl = dwfl;
+
+#endif /* defined(HAVE_LIBDW) */
+
        /* Insert breakpoints for all active (non-latent) symbols.  */
        struct library_symbol *libsym = NULL;
        while ((libsym = library_each_symbol(lib, libsym,
@@ -1005,8 +1070,8 @@ each_breakpoint_cb(arch_addr_t *key, struct breakpoint **bpp, void *d)
        return data->cb(data->proc, *bpp, data->cb_data);
 }
 
-void *
-proc_each_breakpoint(struct process *proc, void *start,
+arch_addr_t *
+proc_each_breakpoint(struct process *proc, arch_addr_t *start,
                     enum callback_status (*cb)(struct process *proc,
                                                struct breakpoint *bp,
                                                void *data), void *data)