/*
* 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"
#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)
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
}
#endif /* defined(HAVE_LIBUNWIND) */
+#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;
}
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;
}
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;
}
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;
+ 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);
+ 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);
+ proc->should_attach_dwfl = 0;
+ if (r != 0) {
+ const char *msg;
+ dwfl_end(dwfl);
+ if (r < 0)
+ msg = dwfl_errmsg(-1);
+ else
+ msg = strerror(r);
+ fprintf(stderr, "Couldn't initialize "
+ "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. */
struct library_symbol *libsym = NULL;
while ((libsym = library_each_symbol(lib, libsym,
"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
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)