diff options
author | Petr Machata <pmachata@redhat.com> | 2012-10-27 19:23:12 +0200 |
---|---|---|
committer | Petr Machata <pmachata@redhat.com> | 2012-10-27 19:23:12 +0200 |
commit | 165b566a50b2bd560af3bd9649e456915397066b (patch) | |
tree | 628db7a9bc75ef25d21f596dbea5ffe8bd1cb1bd | |
parent | 45de1a24740e813ac10b981684a9b46814ddb38c (diff) | |
download | ltrace-165b566a50b2bd560af3bd9649e456915397066b.tar.gz |
Add proc_find_symbol, use it to find corresponding symbols for clones
The code in breakpoint_clone was buggy--it looked through old_proc's
symbols. It was also needlessly verbose, proc_find_symbol uses library
key to find the right library. Instead use the new interface and call
it on new_proc to find the new symbol.
We also didn't relink symbols in stack elements of a cloned process in
process_clone. Use proc_find_symbol for this as well.
-rw-r--r-- | breakpoints.c | 33 | ||||
-rw-r--r-- | proc.c | 36 | ||||
-rw-r--r-- | proc.h | 8 |
3 files changed, 48 insertions, 29 deletions
diff --git a/breakpoints.c b/breakpoints.c index 450472a..d77fefc 100644 --- a/breakpoints.c +++ b/breakpoints.c @@ -155,41 +155,16 @@ breakpoint_destroy(struct breakpoint *bp) arch_breakpoint_destroy(bp); } -struct find_symbol_data { - struct library_symbol *old_libsym; - struct library_symbol *found_libsym; -}; - -static enum callback_status -find_sym_in_lib(struct Process *proc, struct library *lib, void *u) -{ - struct find_symbol_data *fs = u; - fs->found_libsym - = library_each_symbol(lib, NULL, library_symbol_equal_cb, - fs->old_libsym); - return fs->found_libsym != NULL ? CBS_STOP : CBS_CONT; -} - int breakpoint_clone(struct breakpoint *retp, struct Process *new_proc, struct breakpoint *bp, struct Process *old_proc) { - /* Find library and symbol that this breakpoint was linked to. */ - struct library_symbol *libsym = bp->libsym; - struct library *lib = NULL; - if (libsym != NULL) { - struct find_symbol_data f_data = { - .old_libsym = libsym, - }; - lib = proc_each_library(old_proc, NULL, - find_sym_in_lib, &f_data); - assert(lib != NULL); - libsym = f_data.found_libsym; + struct library_symbol *libsym = NULL; + if (bp->libsym != NULL) { + int rc = proc_find_symbol(new_proc, bp->libsym, NULL, &libsym); + assert(rc == 0); } - /* LIB and LIBSYM now hold the new library and symbol that - * correspond to the original breakpoint. Now we can do the - * clone itself. */ breakpoint_init_base(retp, new_proc, bp->addr, libsym); memcpy(retp->orig_value, bp->orig_value, sizeof(bp->orig_value)); retp->enabled = bp->enabled; @@ -420,6 +420,16 @@ process_clone(struct Process *retp, struct Process *proc, pid_t pid) } retp->callstack[i].arguments = nargs; } + + /* If it's not a syscall, we need to find the + * corresponding library symbol in the cloned + * library. */ + if (!elem->is_syscall && elem->c_un.libfunc != NULL) { + struct library_symbol *libfunc = elem->c_un.libfunc; + int rc = proc_find_symbol(retp, libfunc, + NULL, &elem->c_un.libfunc); + assert(rc == 0); + } } if (os_process_clone(retp, proc) < 0 @@ -949,3 +959,29 @@ proc_each_breakpoint(struct Process *proc, void *start, dict_apply_to_all(proc->breakpoints, &each_breakpoint_cb, &dd); return dd.end; } + +int +proc_find_symbol(struct Process *proc, struct library_symbol *sym, + struct library **retlib, struct library_symbol **retsym) +{ + struct library *lib = sym->lib; + assert(lib != NULL); + + struct library *flib + = proc_each_library(proc, NULL, library_with_key_cb, &lib->key); + if (flib == NULL) + return -1; + + struct library_symbol *fsym + = library_each_symbol(flib, NULL, library_symbol_named_cb, + (char *)sym->name); + if (fsym == NULL) + return -1; + + if (retlib != NULL) + *retlib = flib; + if (retsym != NULL) + *retsym = fsym; + + return 0; +} @@ -241,4 +241,12 @@ void *proc_each_breakpoint(struct Process *proc, void *start, * If tag is not found, return a negative value. */ int proc_find_dynamic_entry_addr(struct Process *proc, arch_addr_t src_addr, int d_tag, arch_addr_t *ret); + +/* Finds a symbol corresponding to LIBSYM in a process PROC. Returns + * 0 and sets *RETLIB and *RETSYM if the corresponding pointer is + * non-NULL. Returns a negative value when the symbols couldn't be + * found. */ +int proc_find_symbol(struct Process *proc, struct library_symbol *sym, + struct library **retlib, struct library_symbol **retsym); + #endif /* _PROC_H_ */ |