[Ltrace-devel] [PATCH v2 8/8] mipsel: Update breakpoints when functions return
edgar.iglesias at gmail.com
edgar.iglesias at gmail.com
Thu Sep 27 10:07:40 UTC 2012
From: "Edgar E. Iglesias" <edgar at axis.com>
When functions return we check if the symbol went from
unresolved to resolved and if the resolved address
differs from the unresolved one. If so, we add a new
breakpoint at the resolved address.
This is not thread-safe.
Signed-off-by: Edgar E. Iglesias <edgar at axis.com>
---
backend.h | 4 ++++
handle_event.c | 11 ++++++++++-
sysdeps/linux-gnu/mipsel/arch.h | 1 +
sysdeps/linux-gnu/mipsel/plt.c | 39 +++++++++++++++++++++++++++++++++++++++
4 files changed, 54 insertions(+), 1 deletions(-)
diff --git a/backend.h b/backend.h
index e241eab..8b4e8fa 100644
--- a/backend.h
+++ b/backend.h
@@ -308,6 +308,10 @@ enum plt_status arch_elf_add_plt_entry(struct Process *proc, struct ltelf *lte,
* done with the process startup. */
void arch_dynlink_done(struct Process *proc);
+/* This callback needs to be implemented if arch.h defines
+ * ARCH_HAVE_SYMBOL_RET. It is called after a traced call returns. */
+void arch_symbol_ret(struct Process *proc, struct library_symbol *libsym);
+
/* If arch.h defines ARCH_HAVE_FETCH_ARG, the following callbacks have
* to be implemented: arch_fetch_arg_init, arch_fetch_arg_clone,
* arch_fetch_arg_done, arch_fetch_arg_next and arch_fetch_retval.
diff --git a/handle_event.c b/handle_event.c
index 384e868..5793d7f 100644
--- a/handle_event.c
+++ b/handle_event.c
@@ -573,6 +573,12 @@ output_right_tos(struct Process *proc)
output_right(LT_TOF_FUNCTIONR, proc, elem->c_un.libfunc);
}
+#ifndef ARCH_HAVE_SYMBOL_RET
+void arch_symbol_ret(struct Process *proc, struct library_symbol *libsym)
+{
+}
+#endif
+
static void
handle_breakpoint(Event *event)
{
@@ -606,6 +612,7 @@ handle_breakpoint(Event *event)
struct library_symbol *libsym =
event->proc->callstack[i].c_un.libfunc;
+ arch_symbol_ret(event->proc, libsym);
output_right_tos(event->proc);
callstack_pop(event->proc);
@@ -614,7 +621,7 @@ handle_breakpoint(Event *event)
* have the same return address, but were made
* for different symbols. This should only
* happen for entry point tracing, i.e. for -x
- * everywhere, or -x and -e on PPC64. */
+ * everywhere, or -x and -e on MIPS. */
while (event->proc->callstack_depth > 0) {
struct callstack_element *prev;
size_t d = event->proc->callstack_depth;
@@ -624,6 +631,8 @@ handle_breakpoint(Event *event)
|| prev->return_addr != brk_addr)
break;
+ arch_symbol_ret(event->proc,
+ prev->c_un.libfunc);
output_right_tos(event->proc);
callstack_pop(event->proc);
}
diff --git a/sysdeps/linux-gnu/mipsel/arch.h b/sysdeps/linux-gnu/mipsel/arch.h
index 23fe167..9144d83 100644
--- a/sysdeps/linux-gnu/mipsel/arch.h
+++ b/sysdeps/linux-gnu/mipsel/arch.h
@@ -43,6 +43,7 @@ struct arch_ltelf_data {
#define ARCH_HAVE_DYNLINK_DONE
#define ARCH_HAVE_ADD_PLT_ENTRY
#define ARCH_HAVE_ATOMIC_SINGLESTEP
+#define ARCH_HAVE_SYMBOL_RET
#define ARCH_HAVE_LIBRARY_SYMBOL_DATA
enum mips_plt_type
diff --git a/sysdeps/linux-gnu/mipsel/plt.c b/sysdeps/linux-gnu/mipsel/plt.c
index ed9e6da..35f0634 100644
--- a/sysdeps/linux-gnu/mipsel/plt.c
+++ b/sysdeps/linux-gnu/mipsel/plt.c
@@ -174,6 +174,45 @@ arch_elf_destroy(struct ltelf *lte)
{
}
+/* When functions return we check if the symbol needs an updated
+ breakpoint with the resolved address. */
+void arch_symbol_ret(struct Process *proc, struct library_symbol *libsym)
+{
+ struct breakpoint *bp;
+ arch_addr_t resolved_addr;
+
+ /* Only deal with unresolved symbols. */
+ if (libsym->arch.type != UNRESOLVED)
+ return;
+
+ resolved_addr = sym2addr(proc, libsym);
+ libsym->arch.resolved_addr = (uintptr_t) resolved_addr;
+ libsym->arch.type = RESOLVED;
+
+ if (libsym->arch.stub_addr == libsym->arch.resolved_addr) {
+ /* Prelinked symbol. No need to add new breakpoint. */
+ return;
+ }
+
+ bp = malloc(sizeof (*bp));
+ if (breakpoint_init(bp, proc, resolved_addr, libsym) < 0)
+ goto err;
+
+ if (proc_add_breakpoint(proc, bp) < 0) {
+ breakpoint_destroy(bp);
+ goto err;
+ }
+
+ if (breakpoint_turn_on(bp, proc) < 0) {
+ proc_remove_breakpoint(proc, bp);
+ breakpoint_destroy(bp);
+ goto err;
+ }
+ return;
+err:
+ free(bp);
+}
+
static enum callback_status
cb_each_sym(struct library_symbol *libsym, void *data)
{
--
1.7.8.6
More information about the Ltrace-devel
mailing list