[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