From: "Edgar E. Iglesias" <[email protected]> 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 <[email protected]> --- backend.h | 4 +++ handle_event.c | 11 ++++++++- sysdeps/linux-gnu/mipsel/arch.h | 1 + sysdeps/linux-gnu/mipsel/plt.c | 45 +++++++++++++++++++++++++++++++++++++++ 4 files changed, 60 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 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) { -- 1.7.8.6 _______________________________________________ Ltrace-devel mailing list [email protected] http://lists.alioth.debian.org/cgi-bin/mailman/listinfo/ltrace-devel
