Fix breakpoint cloning
diff --git a/proc.c b/proc.c
index b9f269f..79af573 100644
--- a/proc.c
+++ b/proc.c
@@ -114,51 +114,25 @@
int error;
};
-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;
-}
-
static void
clone_single_bp(void *key, void *value, void *u)
{
- target_address_t addr = (target_address_t)key;
struct breakpoint *bp = value;
struct clone_single_bp_data *data = u;
- /* Find library and symbol that this symbol 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(data->old_proc, NULL,
- find_sym_in_lib, &f_data);
- assert(lib != NULL);
- libsym = f_data.found_libsym;
- }
-
- /* LIB and LIBSYM now hold the new library and symbol that
- * correspond to the original breakpoint. Now we can do the
- * clone itself. */
+ data->error = 0;
struct breakpoint *clone = malloc(sizeof(*clone));
if (clone == NULL
- || breakpoint_init(clone, data->new_proc, addr, libsym) < 0) {
+ || breakpoint_clone(clone, data->new_proc,
+ bp, data->old_proc) < 0) {
+ fail:
+ free(clone);
data->error = -1;
- return;
}
- breakpoint_set_callbacks(clone, bp->cbs);
+ if (proc_add_breakpoint(data->new_proc->leader, clone) < 0) {
+ breakpoint_destroy(clone);
+ goto fail;
+ }
}
int
@@ -173,7 +147,7 @@
retp->tracesysgood = proc->tracesysgood;
/* For non-leader processes, that's all we need to do. */
- if (proc->leader != proc)
+ if (retp->leader != retp)
return 0;
/* Clone symbols first so that we can clone and relink
@@ -626,3 +600,53 @@
assert(!"Not yet implemented!");
abort();
}
+
+/* Dict doesn't support iteration restarts, so here's this contraption
+ * for now. XXX add restarts to dict. */
+struct each_breakpoint_data
+{
+ void *start;
+ void *end;
+ struct Process *proc;
+ enum callback_status (*cb)(struct Process *proc,
+ struct breakpoint *bp,
+ void *data);
+ void *cb_data;
+};
+
+static void
+each_breakpoint_cb(void *key, void *value, void *d)
+{
+ struct each_breakpoint_data *data = d;
+ if (data->end != NULL)
+ return;
+ if (data->start == key)
+ data->start = NULL;
+
+ if (data->start == NULL) {
+ switch (data->cb(data->proc, value, data->cb_data)) {
+ case CBS_FAIL:
+ /* XXX handle me */
+ case CBS_STOP:
+ data->end = key;
+ case CBS_CONT:
+ return;
+ }
+ }
+}
+
+void *
+proc_each_breakpoint(struct Process *proc, void *start,
+ enum callback_status (*cb)(struct Process *proc,
+ struct breakpoint *bp,
+ void *data), void *data)
+{
+ struct each_breakpoint_data dd = {
+ .start = start,
+ .proc = proc,
+ .cb = cb,
+ .cb_data = data,
+ };
+ dict_apply_to_all(proc->breakpoints, &each_breakpoint_cb, &dd);
+ return dd.end;
+}