+/* Update BUF, which is LEN bytes read from the target address
+ MEMADDR, by replacing a memory breakpoint with its shadowed
+ contents.
+
+ If READBUF is not NULL, this buffer must not overlap with the of
+ the breakpoint location's shadow_contents buffer. Otherwise, a
+ failed assertion internal error will be raised. */
+
+static void
+one_breakpoint_xfer_memory (gdb_byte *readbuf, gdb_byte *writebuf,
+ const gdb_byte *writebuf_org,
+ ULONGEST memaddr, LONGEST len,
+ struct bp_target_info *target_info,
+ struct gdbarch *gdbarch)
+{
+ /* Now do full processing of the found relevant range of elements. */
+ CORE_ADDR bp_addr = 0;
+ int bp_size = 0;
+ int bptoffset = 0;
+
+ if (!breakpoint_address_match (target_info->placed_address_space, 0,
+ current_program_space->aspace, 0))
+ {
+ /* The breakpoint is inserted in a different address space. */
+ return;
+ }
+
+ /* Addresses and length of the part of the breakpoint that
+ we need to copy. */
+ bp_addr = target_info->placed_address;
+ bp_size = target_info->shadow_len;
+
+ if (bp_addr + bp_size <= memaddr)
+ {
+ /* The breakpoint is entirely before the chunk of memory we are
+ reading. */
+ return;
+ }
+
+ if (bp_addr >= memaddr + len)
+ {
+ /* The breakpoint is entirely after the chunk of memory we are
+ reading. */
+ return;
+ }
+
+ /* Offset within shadow_contents. */
+ if (bp_addr < memaddr)
+ {
+ /* Only copy the second part of the breakpoint. */
+ bp_size -= memaddr - bp_addr;
+ bptoffset = memaddr - bp_addr;
+ bp_addr = memaddr;
+ }
+
+ if (bp_addr + bp_size > memaddr + len)
+ {
+ /* Only copy the first part of the breakpoint. */
+ bp_size -= (bp_addr + bp_size) - (memaddr + len);
+ }
+
+ if (readbuf != NULL)
+ {
+ /* Verify that the readbuf buffer does not overlap with the
+ shadow_contents buffer. */
+ gdb_assert (target_info->shadow_contents >= readbuf + len
+ || readbuf >= (target_info->shadow_contents
+ + target_info->shadow_len));
+
+ /* Update the read buffer with this inserted breakpoint's
+ shadow. */
+ memcpy (readbuf + bp_addr - memaddr,
+ target_info->shadow_contents + bptoffset, bp_size);
+ }
+ else
+ {
+ const unsigned char *bp;
+ CORE_ADDR placed_address = target_info->placed_address;
+ int placed_size = target_info->placed_size;
+
+ /* Update the shadow with what we want to write to memory. */
+ memcpy (target_info->shadow_contents + bptoffset,
+ writebuf_org + bp_addr - memaddr, bp_size);
+
+ /* Determine appropriate breakpoint contents and size for this
+ address. */
+ bp = gdbarch_breakpoint_from_pc (gdbarch, &placed_address, &placed_size);
+
+ /* Update the final write buffer with this inserted
+ breakpoint's INSN. */
+ memcpy (writebuf + bp_addr - memaddr, bp + bptoffset, bp_size);
+ }
+}
+