aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPetr Machata <pmachata@redhat.com>2012-10-27 19:23:12 +0200
committerPetr Machata <pmachata@redhat.com>2012-10-27 19:23:12 +0200
commit165b566a50b2bd560af3bd9649e456915397066b (patch)
tree628db7a9bc75ef25d21f596dbea5ffe8bd1cb1bd
parent45de1a24740e813ac10b981684a9b46814ddb38c (diff)
downloadltrace-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.c33
-rw-r--r--proc.c36
-rw-r--r--proc.h8
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;
diff --git a/proc.c b/proc.c
index e601e15..d12faef 100644
--- a/proc.c
+++ b/proc.c
@@ -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;
+}
diff --git a/proc.h b/proc.h
index ab8794b..68054b3 100644
--- a/proc.h
+++ b/proc.h
@@ -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_ */