+ return bp;
+}
+
+struct breakpoint *
+insert_breakpoint_at(struct process *proc, arch_addr_t addr,
+ struct library_symbol *libsym)
+{
+ debug(DEBUG_FUNCTION,
+ "insert_breakpoint_at(pid=%d, addr=%p, symbol=%s)",
+ proc->pid, addr, libsym ? libsym->name : "NULL");
+
+ assert(addr != 0);
+
+ struct breakpoint *bp = malloc(sizeof *bp);
+ if (bp == NULL || breakpoint_init(bp, proc, addr, libsym) < 0) {
+ free(bp);
+ return NULL;
+ }
+
+ /* N.B. (and XXX): BP->addr might differ from ADDR. On ARM
+ * this is a real possibility. The problem here is that to
+ * create a return breakpoint ltrace calls get_return_addr and
+ * then insert_breakpoint_at. So get_return_addr needs to
+ * encode all the information necessary for breakpoint_init
+ * into the address itself, so ADDR is potentially
+ * mangled. */
+
+ struct breakpoint *tmp = insert_breakpoint(proc, bp);
+ if (tmp != bp) {
+ breakpoint_destroy(bp);
+ free(bp);
+ }
+ return tmp;
+}
+
+struct breakpoint *
+insert_breakpoint(struct process *proc, struct breakpoint *bp)
+{
+ /* Only the group leader should be getting the breakpoints and
+ * thus have ->breakpoint initialized. */
+ struct process *leader = proc->leader;
+ assert(leader != NULL);
+ assert(leader->breakpoints != NULL);
+
+ /* XXX what we need to do instead is have a list of
+ * breakpoints that are enabled at this address. The
+ * following works if every breakpoint is the same and there's
+ * no extra data, but that doesn't hold anymore. For now it
+ * will suffice, about the only realistic case where we need
+ * to have more than one breakpoint per address is return from
+ * a recursive library call. */
+ struct breakpoint *ext_bp = bp;
+ if (DICT_FIND_VAL(leader->breakpoints, &bp->addr, &ext_bp) != 0) {
+ if (proc_add_breakpoint(leader, bp) < 0)
+ return NULL;
+ ext_bp = bp;
+ }
+
+ if (breakpoint_turn_on(ext_bp, proc) < 0) {
+ if (ext_bp != bp)
+ proc_remove_breakpoint(leader, bp);
+ return NULL;
+ }
+
+ return ext_bp;