Fix bug in `expr_clone`
[platform/upstream/ltrace.git] / proc.c
diff --git a/proc.c b/proc.c
index 6f4f64e..bf2a172 100644 (file)
--- a/proc.c
+++ b/proc.c
 #include "proc.h"
 #include "value_dict.h"
 
+#if defined(HAVE_LIBDW)
+# include "dwarf_prototypes.h"
+#endif /* defined(HAVE_LIBDW) */
+
 #ifndef OS_HAVE_PROCESS_DATA
 int
 os_process_init(struct process *proc)
@@ -174,6 +178,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;
@@ -224,9 +229,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;
        }
@@ -863,20 +870,43 @@ proc_activate_delayed_symbol(struct process *proc,
        return breakpoint_for_symbol(libsym, proc);
 }
 
+
+struct activate_latent_in_context
+{
+       struct process *proc;
+       struct library_exported_names *exported_names;
+};
+static enum callback_status
+activate_latent_in_cb(struct library_symbol *libsym, void *data)
+{
+       struct activate_latent_in_context *ctx =
+               (struct activate_latent_in_context*)data;
+
+       if (libsym->latent &&
+           library_exported_names_contains(ctx->exported_names,
+                                           libsym->name) != 0)
+               proc_activate_latent_symbol(ctx->proc, libsym);
+
+       return CBS_CONT;
+}
+
 static enum callback_status
 activate_latent_in(struct process *proc, struct library *lib, void *data)
 {
-       struct library_exported_name *exported;
-       for (exported = data; exported != NULL; exported = exported->next) {
-               struct library_symbol *libsym = NULL;
-               while ((libsym = library_each_symbol(lib, libsym,
-                                                    library_symbol_named_cb,
-                                                    (void *)exported->name))
-                      != NULL)
-                       if (libsym->latent
-                           && proc_activate_latent_symbol(proc, libsym) < 0)
-                               return CBS_FAIL;
-       }
+       struct library_symbol *libsym = NULL;
+
+       struct library_exported_names *exported_names =
+               (struct library_exported_names*)data;
+
+       struct activate_latent_in_context ctx =
+               {.proc = proc,
+                .exported_names = exported_names};
+
+       if (library_each_symbol(lib, libsym,
+                               activate_latent_in_cb,
+                               &ctx) != NULL)
+               return CBS_FAIL;
+
        return CBS_CONT;
 }
 
@@ -890,42 +920,47 @@ proc_add_library(struct process *proc, struct library *lib)
              lib->soname, lib->base, lib->pathname, proc->pid);
 
 #if defined(HAVE_LIBDW)
-       if (options.bt_depth > 0) {
-               /* Setup module tracking for libdwfl unwinding.  */
-               struct process *leader = proc->leader;
-               Dwfl *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));
-               }
+       Dwfl *dwfl = NULL;
+       Dwfl_Module *dwfl_module = 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 (leader->dwfl == NULL) {
+       if (dwfl != NULL) {
+               dwfl_report_begin_add(dwfl);
+               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 (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)
@@ -933,13 +968,17 @@ proc_add_library(struct process *proc, struct library *lib)
                                        else
                                                msg = strerror(r);
                                        fprintf(stderr, "Couldn't initialize "
-                                               "libdwfl unwinding for "
-                                               "process %d: %s\n",
+                                               "libdwfl (unwinding, prototype "
+                                               "import) for process %d: %s\n",
                                                leader->pid, msg);
                                }
                        }
                }
        }
+
+       lib->dwfl_module = dwfl_module;
+       leader->dwfl = dwfl;
+
 #endif /* defined(HAVE_LIBDW) */
 
        /* Insert breakpoints for all active (non-latent) symbols.  */
@@ -951,15 +990,19 @@ proc_add_library(struct process *proc, struct library *lib)
                        "Couldn't insert breakpoint for %s to %d: %s.\n",
                        libsym->name, proc->pid, strerror(errno));
 
-       /* Look through export list of the new library and compare it
-        * with latent symbols of all libraries (including this
-        * library itself).  */
-       struct library *lib2 = NULL;
-       while ((lib2 = proc_each_library(proc, lib2, activate_latent_in,
-                                        lib->exported_names)) != NULL)
-               fprintf(stderr,
-                       "Couldn't activate latent symbols for %s in %d: %s.\n",
-                       lib2->soname, proc->pid, strerror(errno));
+       if (lib->should_activate_latent != 0) {
+               /* Look through export list of the new library and compare it
+                * with latent symbols of all libraries (including this
+                * library itself).  */
+               struct library *lib2 = NULL;
+
+               while ((lib2 = proc_each_library(proc, lib2, activate_latent_in,
+                                                &lib->exported_names)) != NULL)
+                       fprintf(stderr,
+                               "Couldn't activate latent symbols "
+                               "for %s in %d: %s.\n",
+                               lib2->soname, proc->pid, strerror(errno));
+       }
 }
 
 int