diff options
-rw-r--r-- | gdb/ChangeLog | 8 | ||||
-rw-r--r-- | gdb/breakpoint.c | 186 |
2 files changed, 125 insertions, 69 deletions
diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 880c37a..45a94a8 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,11 @@ +2014-04-10 Pedro Alves <palves@redhat.com> + + * breakpoint.c (single_step_breakpoints) + (single_step_gdbarch): Move up in the file. + (one_breakpoint_xfer_memory): New function, factored out from ... + (breakpoint_xfer_memory): ... here. Also process single-step + breakpoints. + 2014-04-09 Tristan Gingold <gingold@adacore.com> * darwin-nat.c (darwin_check_new_threads): Fix port leak, add diff --git a/gdb/breakpoint.c b/gdb/breakpoint.c index 19af9df..f777a4a 100644 --- a/gdb/breakpoint.c +++ b/gdb/breakpoint.c @@ -293,6 +293,12 @@ static struct breakpoint_ops bkpt_probe_breakpoint_ops; /* Dynamic printf class type. */ struct breakpoint_ops dprintf_breakpoint_ops; +/* One (or perhaps two) breakpoints used for software single + stepping. */ + +static void *single_step_breakpoints[2]; +static struct gdbarch *single_step_gdbarch[2]; + /* The style in which to perform a dynamic printf. This is a user option because different output options have different tradeoffs; if GDB does the printing, there is better error handling if there @@ -1409,6 +1415,100 @@ bp_location_has_shadow (struct bp_location *bl) return 1; } +/* 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); + } +} + /* Update BUF, which is LEN bytes read from the target address MEMADDR, by replacing any memory breakpoints with their shadowed contents. @@ -1435,6 +1535,7 @@ breakpoint_xfer_memory (gdb_byte *readbuf, gdb_byte *writebuf, /* Left boundary, right boundary and median element of our binary search. */ unsigned bc_l, bc_r, bc; + size_t i; /* Find BC_L which is a leftmost element which may affect BUF content. It is safe to report lower value but a failure to @@ -1508,74 +1609,27 @@ breakpoint_xfer_memory (gdb_byte *readbuf, gdb_byte *writebuf, if (!bp_location_has_shadow (bl)) continue; - if (!breakpoint_address_match (bl->target_info.placed_address_space, 0, - current_program_space->aspace, 0)) - continue; - - /* Addresses and length of the part of the breakpoint that - we need to copy. */ - bp_addr = bl->target_info.placed_address; - bp_size = bl->target_info.shadow_len; - - if (bp_addr + bp_size <= memaddr) - /* The breakpoint is entirely before the chunk of memory we - are reading. */ - continue; - if (bp_addr >= memaddr + len) - /* The breakpoint is entirely after the chunk of memory we are - reading. */ - continue; + one_breakpoint_xfer_memory (readbuf, writebuf, writebuf_org, + memaddr, len, &bl->target_info, bl->gdbarch); + } - /* 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; - } + /* Now process single-step breakpoints. These are not found in the + bp_location array. */ + for (i = 0; i < 2; i++) + { + struct bp_target_info *bp_tgt = single_step_breakpoints[i]; - if (bp_addr + bp_size > memaddr + len) - { - /* Only copy the first part of the breakpoint. */ - bp_size -= (bp_addr + bp_size) - (memaddr + len); - } + if (bp_tgt != NULL) + { + struct gdbarch *gdbarch = single_step_gdbarch[i]; - if (readbuf != NULL) - { - /* Verify that the readbuf buffer does not overlap with - the shadow_contents buffer. */ - gdb_assert (bl->target_info.shadow_contents >= readbuf + len - || readbuf >= (bl->target_info.shadow_contents - + bl->target_info.shadow_len)); - - /* Update the read buffer with this inserted breakpoint's - shadow. */ - memcpy (readbuf + bp_addr - memaddr, - bl->target_info.shadow_contents + bptoffset, bp_size); - } - else - { - struct gdbarch *gdbarch = bl->gdbarch; - const unsigned char *bp; - CORE_ADDR placed_address = bl->target_info.placed_address; - int placed_size = bl->target_info.placed_size; - - /* Update the shadow with what we want to write to memory. */ - memcpy (bl->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); - } - } + one_breakpoint_xfer_memory (readbuf, writebuf, writebuf_org, + memaddr, len, bp_tgt, gdbarch); + } + } } + /* Return true if BPT is either a software breakpoint or a hardware @@ -15036,12 +15090,6 @@ deprecated_remove_raw_breakpoint (struct gdbarch *gdbarch, void *bp) return ret; } -/* One (or perhaps two) breakpoints used for software single - stepping. */ - -static void *single_step_breakpoints[2]; -static struct gdbarch *single_step_gdbarch[2]; - /* Create and insert a breakpoint for software single step. */ void |