Browse Source

2011-12-06 Pedro Alves <pedro@codesourcery.com>

gdb/
	* breakpoint.c (breakpoint_restore_shadows): Rename to ...
	(breakpoint_xfer_memory): ... this.  Change prototype.  Handle
	memory writes too.
	* breakpoint.h (breakpoint_restore_shadows): Delete.
	(breakpoint_xfer_memory): Declare.
	* mem-break.c (default_memory_insert_breakpoint)
	(default_memory_remove_breakpoint): Use target_write_raw_memory.
	(memory_xfer_partial): Rename to ...
	(memory_xfer_partial_1): ... this.  Don't mask out breakpoints
	here.
	(memory_xfer_partial): New.
	(target_write_raw_memory): New.
	* target.h (target_write_raw_memory): New.

	gdb/testsuite/
	* gdb.base/break-always.exp: Test changing memory at addresses
	with breakpoints inserted.
gdb_7_4-branch
Pedro Alves 15 years ago
parent
commit
f0ba3972e9
  1. 16
      gdb/ChangeLog
  2. 32
      gdb/breakpoint.c
  3. 15
      gdb/breakpoint.h
  4. 8
      gdb/mem-break.c
  5. 80
      gdb/target.c
  6. 3
      gdb/target.h
  7. 5
      gdb/testsuite/ChangeLog
  8. 37
      gdb/testsuite/gdb.base/break-always.exp

16
gdb/ChangeLog

@ -1,3 +1,19 @@
2011-12-06 Pedro Alves <pedro@codesourcery.com>
* breakpoint.c (breakpoint_restore_shadows): Rename to ...
(breakpoint_xfer_memory): ... this. Change prototype. Handle
memory writes too.
* breakpoint.h (breakpoint_restore_shadows): Delete.
(breakpoint_xfer_memory): Declare.
* mem-break.c (default_memory_insert_breakpoint)
(default_memory_remove_breakpoint): Use target_write_raw_memory.
(memory_xfer_partial): Rename to ...
(memory_xfer_partial_1): ... this. Don't mask out breakpoints
here.
(memory_xfer_partial): New.
(target_write_raw_memory): New.
* target.h (target_write_raw_memory): New.
2011-12-06 Doug Evans <dje@google.com> 2011-12-06 Doug Evans <dje@google.com>
* linespec.c (decode_dollar): Avoid "may be used uninitialized" warning. * linespec.c (decode_dollar): Avoid "may be used uninitialized" warning.

32
gdb/breakpoint.c

@ -1049,7 +1049,9 @@ bp_location_has_shadow (struct bp_location *bl)
bl->address + bp_location_shadow_len_after_address_max <= memaddr */ bl->address + bp_location_shadow_len_after_address_max <= memaddr */
void void
breakpoint_restore_shadows (gdb_byte *buf, ULONGEST memaddr, LONGEST len) breakpoint_xfer_memory (gdb_byte *readbuf, gdb_byte *writebuf,
const gdb_byte *writebuf_org,
ULONGEST memaddr, LONGEST len)
{ {
/* Left boundary, right boundary and median element of our binary /* Left boundary, right boundary and median element of our binary
search. */ search. */
@ -1161,8 +1163,32 @@ breakpoint_restore_shadows (gdb_byte *buf, ULONGEST memaddr, LONGEST len)
bp_size -= (bp_addr + bp_size) - (memaddr + len); bp_size -= (bp_addr + bp_size) - (memaddr + len);
} }
memcpy (buf + bp_addr - memaddr, if (readbuf != NULL)
bl->target_info.shadow_contents + bptoffset, bp_size); {
/* 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;
unsigned 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);
}
} }
} }

15
gdb/breakpoint.h

@ -1296,10 +1296,17 @@ extern int deprecated_remove_raw_breakpoint (struct gdbarch *, void *);
target. */ target. */
int watchpoints_triggered (struct target_waitstatus *); int watchpoints_triggered (struct target_waitstatus *);
/* Update BUF, which is LEN bytes read from the target address MEMADDR, /* Helper for transparent breakpoint hiding for memory read and write
by replacing any memory breakpoints with their shadowed contents. */ routines.
void breakpoint_restore_shadows (gdb_byte *buf, ULONGEST memaddr,
LONGEST len); Update one of READBUF or WRITEBUF with either the shadows
(READBUF), or the breakpoint instructions (WRITEBUF) of inserted
breakpoints at the memory range defined by MEMADDR and extending
for LEN bytes. If writing, then WRITEBUF is a copy of WRITEBUF_ORG
on entry.*/
extern void breakpoint_xfer_memory (gdb_byte *readbuf, gdb_byte *writebuf,
const gdb_byte *writebuf_org,
ULONGEST memaddr, LONGEST len);
extern int breakpoints_always_inserted_mode (void); extern int breakpoints_always_inserted_mode (void);

8
gdb/mem-break.c

@ -60,8 +60,8 @@ default_memory_insert_breakpoint (struct gdbarch *gdbarch,
/* Write the breakpoint. */ /* Write the breakpoint. */
if (val == 0) if (val == 0)
val = target_write_memory (bp_tgt->placed_address, bp, val = target_write_raw_memory (bp_tgt->placed_address, bp,
bp_tgt->placed_size); bp_tgt->placed_size);
return val; return val;
} }
@ -71,8 +71,8 @@ int
default_memory_remove_breakpoint (struct gdbarch *gdbarch, default_memory_remove_breakpoint (struct gdbarch *gdbarch,
struct bp_target_info *bp_tgt) struct bp_target_info *bp_tgt)
{ {
return target_write_memory (bp_tgt->placed_address, bp_tgt->shadow_contents, return target_write_raw_memory (bp_tgt->placed_address, bp_tgt->shadow_contents,
bp_tgt->placed_size); bp_tgt->placed_size);
} }

80
gdb/target.c

@ -1388,19 +1388,15 @@ memory_xfer_live_readonly_partial (struct target_ops *ops,
For docs see target.h, to_xfer_partial. */ For docs see target.h, to_xfer_partial. */
static LONGEST static LONGEST
memory_xfer_partial (struct target_ops *ops, enum target_object object, memory_xfer_partial_1 (struct target_ops *ops, enum target_object object,
void *readbuf, const void *writebuf, ULONGEST memaddr, void *readbuf, const void *writebuf, ULONGEST memaddr,
LONGEST len) LONGEST len)
{ {
LONGEST res; LONGEST res;
int reg_len; int reg_len;
struct mem_region *region; struct mem_region *region;
struct inferior *inf; struct inferior *inf;
/* Zero length requests are ok and require no work. */
if (len == 0)
return 0;
/* For accesses to unmapped overlay sections, read directly from /* For accesses to unmapped overlay sections, read directly from
files. Must do this first, as MEMADDR may need adjustment. */ files. Must do this first, as MEMADDR may need adjustment. */
if (readbuf != NULL && overlay_debugging) if (readbuf != NULL && overlay_debugging)
@ -1551,11 +1547,7 @@ memory_xfer_partial (struct target_ops *ops, enum target_object object,
if (res <= 0) if (res <= 0)
return -1; return -1;
else else
{ return res;
if (readbuf && !show_memory_breakpoints)
breakpoint_restore_shadows (readbuf, memaddr, reg_len);
return res;
}
} }
/* If none of those methods found the memory we wanted, fall back /* If none of those methods found the memory we wanted, fall back
@ -1584,9 +1576,6 @@ memory_xfer_partial (struct target_ops *ops, enum target_object object,
} }
while (ops != NULL); while (ops != NULL);
if (res > 0 && readbuf != NULL && !show_memory_breakpoints)
breakpoint_restore_shadows (readbuf, memaddr, reg_len);
/* Make sure the cache gets updated no matter what - if we are writing /* Make sure the cache gets updated no matter what - if we are writing
to the stack. Even if this write is not tagged as such, we still need to the stack. Even if this write is not tagged as such, we still need
to update the cache. */ to update the cache. */
@ -1606,6 +1595,48 @@ memory_xfer_partial (struct target_ops *ops, enum target_object object,
return res; return res;
} }
/* Perform a partial memory transfer. For docs see target.h,
to_xfer_partial. */
static LONGEST
memory_xfer_partial (struct target_ops *ops, enum target_object object,
void *readbuf, const void *writebuf, ULONGEST memaddr,
LONGEST len)
{
int res;
/* Zero length requests are ok and require no work. */
if (len == 0)
return 0;
/* Fill in READBUF with breakpoint shadows, or WRITEBUF with
breakpoint insns, thus hiding out from higher layers whether
there are software breakpoints inserted in the code stream. */
if (readbuf != NULL)
{
res = memory_xfer_partial_1 (ops, object, readbuf, NULL, memaddr, len);
if (res > 0 && !show_memory_breakpoints)
breakpoint_xfer_memory (readbuf, NULL, NULL, memaddr, res);
}
else
{
void *buf;
struct cleanup *old_chain;
buf = xmalloc (len);
old_chain = make_cleanup (xfree, buf);
memcpy (buf, writebuf, len);
breakpoint_xfer_memory (NULL, buf, writebuf, memaddr, len);
res = memory_xfer_partial_1 (ops, object, NULL, buf, memaddr, len);
do_cleanups (old_chain);
}
return res;
}
static void static void
restore_show_memory_breakpoints (void *arg) restore_show_memory_breakpoints (void *arg)
{ {
@ -1761,6 +1792,25 @@ target_write_memory (CORE_ADDR memaddr, const gdb_byte *myaddr, int len)
return EIO; return EIO;
} }
/* Write LEN bytes from MYADDR to target raw memory at address
MEMADDR. Returns either 0 for success or an errno value if any
error occurs. If an error occurs, no guarantee is made about how
much data got written. Callers that can deal with partial writes
should call target_write. */
int
target_write_raw_memory (CORE_ADDR memaddr, const gdb_byte *myaddr, int len)
{
/* Dispatch to the topmost target, not the flattened current_target.
Memory accesses check target->to_has_(all_)memory, and the
flattened target doesn't inherit those. */
if (target_write (current_target.beneath, TARGET_OBJECT_RAW_MEMORY, NULL,
myaddr, memaddr, len) == len)
return 0;
else
return EIO;
}
/* Fetch the target's memory map. */ /* Fetch the target's memory map. */
VEC(mem_region_s) * VEC(mem_region_s) *

3
gdb/target.h

@ -941,6 +941,9 @@ extern int target_read_stack (CORE_ADDR memaddr, gdb_byte *myaddr, int len);
extern int target_write_memory (CORE_ADDR memaddr, const gdb_byte *myaddr, extern int target_write_memory (CORE_ADDR memaddr, const gdb_byte *myaddr,
int len); int len);
extern int target_write_raw_memory (CORE_ADDR memaddr, const gdb_byte *myaddr,
int len);
/* Fetches the target's memory map. If one is found it is sorted /* Fetches the target's memory map. If one is found it is sorted
and returned, after some consistency checking. Otherwise, NULL and returned, after some consistency checking. Otherwise, NULL
is returned. */ is returned. */

5
gdb/testsuite/ChangeLog

@ -1,3 +1,8 @@
2011-12-06 Pedro Alves <pedro@codesourcery.com>
* gdb.base/break-always.exp: Test changing memory at addresses
with breakpoints inserted.
2011-12-06 Joel Brobecker <brobecker@acacore.com> 2011-12-06 Joel Brobecker <brobecker@acacore.com>
* gdb.ada/fullname_bp.exp: Add tests for other valid linespecs * gdb.ada/fullname_bp.exp: Add tests for other valid linespecs

37
gdb/testsuite/gdb.base/break-always.exp

@ -49,7 +49,42 @@ gdb_test_no_output "enable 2" "enable 2.H"
gdb_test_no_output "disable 2" "disable 2.I" gdb_test_no_output "disable 2" "disable 2.I"
gdb_test "info breakpoints" "keep n.*keep n.*keep y.*keep n.*keep n.*" "before re-enable check breakpoint state" gdb_test "info breakpoints" "keep n.*keep n.*keep y.*keep n.*keep n.*" "before re-enable check breakpoint state"
gdb_test_no_output "enable" "re-enable all breakpoints" gdb_test_no_output "enable" "re-enable all breakpoints"
gdb_continue_to_breakpoint "bar" ".*break-always.c:$bar_location.*"
set bp_address 0
set test "set breakpoint on bar 2"
gdb_test_multiple "break bar" $test {
-re "Breakpoint 6 at ($hex).*$gdb_prompt $" {
set bp_address $expect_out(1,string)
pass $test
}
}
# Save the original INSN under the breakpoint.
gdb_test "p /x \$shadow = *(char *) $bp_address" \
" = $hex" \
"save shadow"
# Overwrite memory where the breakpoint is planted. GDB should update
# its memory breakpoint's shadows, to account for the new contents,
# and still leave the breakpoint insn planted. Try twice with
# different values, in case we happen to be writting exactly what was
# there already.
gdb_test "p /x *(char *) $bp_address = 0" \
" = 0x0" \
"write 0 to breakpoint's address"
gdb_test "p /x *(char *) $bp_address" \
" = 0x0" \
"read back 0 from the breakpoint's address"
gdb_test "p /x *(char *) $bp_address = 1" \
" = 0x1" \
"write 1 to breakpoint's address"
gdb_test "p /x *(char *) $bp_address" \
" = 0x1" \
"read back 1 from the breakpoint's address"
# Restore the original contents.
gdb_test "p /x *(char *) $bp_address = \$shadow" ""
# Run to breakpoint.
gdb_continue_to_breakpoint "bar" ".*break-always.c:$bar_location.*"

Loading…
Cancel
Save