Fix breakpoint cloning
diff --git a/breakpoint.h b/breakpoint.h
index 0509304..372c714 100644
--- a/breakpoint.h
+++ b/breakpoint.h
@@ -90,6 +90,13 @@
 int breakpoint_init(struct breakpoint *bp, struct Process *proc,
 		    target_address_t addr, struct library_symbol *libsym);
 
+/* Make a clone of breakpoint BP into the area of memory pointed to by
+ * RETP.  The original breakpoint was assigned to process OLD_PROC,
+ * the cloned breakpoint will be attached to process NEW_PROC.
+ * Returns 0 on success or a negative value on failure.  */
+int breakpoint_clone(struct breakpoint *retp, struct Process *new_proc,
+		     struct breakpoint *bp, struct Process *old_proc);
+
 /* Set callbacks.  If CBS is non-NULL, then BP->cbs shall be NULL.  */
 void breakpoint_set_callbacks(struct breakpoint *bp, struct bp_callbacks *cbs);
 
diff --git a/breakpoints.c b/breakpoints.c
index dd1a010..42ca582 100644
--- a/breakpoints.c
+++ b/breakpoints.c
@@ -66,8 +66,25 @@
 arch_breakpoint_destroy(struct breakpoint *sbp)
 {
 }
+
+int
+arch_breakpoint_clone(struct breakpoint *retp, struct breakpoint *sbp)
+{
+	return 0;
+}
 #endif
 
+static void
+breakpoint_init_base(struct breakpoint *bp, struct Process *proc,
+		     target_address_t addr, struct library_symbol *libsym)
+{
+	bp->cbs = NULL;
+	bp->addr = addr;
+	memset(bp->orig_value, 0, sizeof(bp->orig_value));
+	bp->enabled = 0;
+	bp->libsym = libsym;
+}
+
 /* On second thought, I don't think we need PROC.  All the translation
  * (arch_translate_address in particular) should be doable using
  * static lookups of various sections in the ELF file.  We shouldn't
@@ -76,11 +93,7 @@
 breakpoint_init(struct breakpoint *bp, struct Process *proc,
 		target_address_t addr, struct library_symbol *libsym)
 {
-	bp->cbs = NULL;
-	bp->addr = addr;
-	memset(bp->orig_value, 0, sizeof(bp->orig_value));
-	bp->enabled = 0;
-	bp->libsym = libsym;
+	breakpoint_init_base(bp, proc, addr, libsym);
 	return arch_breakpoint_init(proc, bp);
 }
 
@@ -97,11 +110,54 @@
 {
 	if (bp == NULL)
 		return;
-
-
 	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;
+	}
+
+	/* 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;
+	retp->debug_enabled = bp->debug_enabled;
+	if (arch_breakpoint_clone(retp, bp) < 0)
+		return -1;
+	breakpoint_set_callbacks(retp, bp->cbs);
+	return 0;
+}
+
 int
 breakpoint_turn_on(struct breakpoint *bp, struct Process *proc)
 {
diff --git a/common.h b/common.h
index eef3769..5c7ba09 100644
--- a/common.h
+++ b/common.h
@@ -235,6 +235,7 @@
 
 int arch_breakpoint_init(struct Process *proc, struct breakpoint *sbp);
 void arch_breakpoint_destroy(struct breakpoint *sbp);
+int arch_breakpoint_clone(struct breakpoint *retp, struct breakpoint *sbp);
 
 typedef void *target_address_t;
 /* This should extract entry point address and interpreter (dynamic
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;
+}
diff --git a/proc.h b/proc.h
index 2759380..8b77c31 100644
--- a/proc.h
+++ b/proc.h
@@ -200,4 +200,12 @@
 /* Remove BP from PROC.  */
 int proc_remove_breakpoint(struct Process *proc, struct breakpoint *bp);
 
+/* Iterate through the libraries of PROC.  See each_process for
+ * detailed description of the iteration interface.  */
+void *proc_each_breakpoint(struct Process *proc, void *start,
+			   enum callback_status (*cb)(struct Process *proc,
+						      struct breakpoint *bp,
+						      void *data),
+			   void *data);
+
 #endif /* _PROC_H_ */
diff --git a/sysdeps/linux-gnu/arm/breakpoint.c b/sysdeps/linux-gnu/arm/breakpoint.c
index d2c57d9..324ff07 100644
--- a/sysdeps/linux-gnu/arm/breakpoint.c
+++ b/sysdeps/linux-gnu/arm/breakpoint.c
@@ -86,10 +86,13 @@
 int
 arch_breakpoint_init(struct Process *proc, struct breakpoint *sbp)
 {
-	int thumb_mode = (int)addr & 1;
+	/* XXX That uintptr_t cast is there temporarily until
+	 * target_address_t becomes integral type.  */
+	int thumb_mode = ((uintptr_t)sbp->addr) & 1;
 	if (thumb_mode)
-		addr = (void *)((int)addr & ~1);
+		sbp->addr = (void *)((uintptr_t)sbp->addr & ~1);
 	sbp->arch.thumb_mode = thumb_mode | proc->thumb_mode;
+	/* XXX This doesn't seem like it belongs here.  */
 	proc->thumb_mode = 0;
 	return 0;
 }
@@ -98,3 +101,10 @@
 arch_breakpoint_destroy(struct breakpoint *sbp)
 {
 }
+
+int
+arch_breakpoint_clone(struct breakpoint *retp, struct breakpoint *sbp)
+{
+	retp->arch.thumb_mode = sbp->arch.thumb_mode;
+	return 0;
+}
diff --git a/sysdeps/linux-gnu/ppc/plt.c b/sysdeps/linux-gnu/ppc/plt.c
index 4aff818..3b03af8 100644
--- a/sysdeps/linux-gnu/ppc/plt.c
+++ b/sysdeps/linux-gnu/ppc/plt.c
@@ -548,3 +548,10 @@
 arch_breakpoint_destroy(struct breakpoint *bp)
 {
 }
+
+int
+arch_breakpoint_clone(struct breakpoint *retp, struct breakpoint *sbp)
+{
+	retp->arch = sbp->arch;
+	return 0;
+}