aboutsummaryrefslogtreecommitdiff
path: root/sysdeps
diff options
context:
space:
mode:
authorEdgar E. Iglesias <edgar@axis.com>2012-09-27 17:02:40 +0200
committerPetr Machata <pmachata@redhat.com>2012-09-27 17:46:10 +0200
commit3a1806db0ecaa4364e51b4822d66d05f4acd87a9 (patch)
treebef38703ee8c952765632f25d4be0d8f56389579 /sysdeps
parentaddae05da54ac16c55133e1c384d74e03346f634 (diff)
downloadltrace-3a1806db0ecaa4364e51b4822d66d05f4acd87a9.tar.gz
mipsel: Update breakpoints when functions return
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@axis.com>
Diffstat (limited to 'sysdeps')
-rw-r--r--sysdeps/linux-gnu/mipsel/arch.h1
-rw-r--r--sysdeps/linux-gnu/mipsel/plt.c45
2 files changed, 46 insertions, 0 deletions
diff --git a/sysdeps/linux-gnu/mipsel/arch.h b/sysdeps/linux-gnu/mipsel/arch.h
index d46136b..5f5a7dd 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 8778781..6e8dd9d 100644
--- a/sysdeps/linux-gnu/mipsel/plt.c
+++ b/sysdeps/linux-gnu/mipsel/plt.c
@@ -175,6 +175,51 @@ 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 != MIPS_PLT_UNRESOLVED)
+ return;
+
+ resolved_addr = sym2addr(proc, libsym);
+ libsym->arch.resolved_addr = (uintptr_t) resolved_addr;
+ libsym->arch.type = MIPS_PLT_RESOLVED;
+
+ if (libsym->arch.stub_addr == libsym->arch.resolved_addr) {
+ /* Prelinked symbol. No need to add new breakpoint. */
+ return;
+ }
+
+ bp = malloc(sizeof (*bp));
+ if (bp == NULL) {
+ fprintf(stderr, "Failed to allocate bp for %s\n",
+ libsym->name);
+ return;
+ }
+
+ 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_enable_breakpoint_sym(struct library_symbol *libsym, void *data)
{