diff options
author | Edgar E. Iglesias <edgar@axis.com> | 2012-09-27 17:02:40 +0200 |
---|---|---|
committer | Petr Machata <pmachata@redhat.com> | 2012-09-27 17:46:10 +0200 |
commit | 3a1806db0ecaa4364e51b4822d66d05f4acd87a9 (patch) | |
tree | bef38703ee8c952765632f25d4be0d8f56389579 /sysdeps | |
parent | addae05da54ac16c55133e1c384d74e03346f634 (diff) | |
download | ltrace-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.h | 1 | ||||
-rw-r--r-- | sysdeps/linux-gnu/mipsel/plt.c | 45 |
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) { |