コード例 #1
0
int
default_memory_insert_breakpoint (struct gdbarch *gdbarch,
				  struct bp_target_info *bp_tgt)
{
  int val;
  const unsigned char *bp;
  gdb_byte *readbuf;

  /* Determine appropriate breakpoint contents and size for this address.  */
  bp = gdbarch_breakpoint_from_pc
       (gdbarch, &bp_tgt->placed_address, &bp_tgt->placed_size);
  if (bp == NULL)
    error (_("Software breakpoints not implemented for this target."));

  /* Save the memory contents in the shadow_contents buffer and then
     write the breakpoint instruction.  */
  bp_tgt->shadow_len = bp_tgt->placed_size;
  readbuf = alloca (bp_tgt->placed_size);
  val = target_read_memory (bp_tgt->placed_address, readbuf,
			    bp_tgt->placed_size);
  if (val == 0)
    {
      memcpy (bp_tgt->shadow_contents, readbuf, bp_tgt->placed_size);
      val = target_write_raw_memory (bp_tgt->placed_address, bp,
				     bp_tgt->placed_size);
    }

  return val;
}
コード例 #2
0
ファイル: mem-break.c プロジェクト: peterdocter/toolchain-gdb
int
default_memory_insert_breakpoint (struct gdbarch *gdbarch,
				  struct bp_target_info *bp_tgt)
{
  int val;
  const unsigned char *bp;
  CORE_ADDR pc_addr;

  /* Determine appropriate breakpoint contents and size for this address.  */
  pc_addr = bp_tgt->requested_address ?
      bp_tgt->requested_address :
      bp_tgt->placed_address;
  bp = gdbarch_breakpoint_from_pc
       (gdbarch, &pc_addr, &bp_tgt->placed_size);
  if (bp == NULL)
    error (_("Software breakpoints not implemented for this target."));

  /* Save the memory contents.  */
  bp_tgt->shadow_len = bp_tgt->placed_size;
  val = target_read_memory (bp_tgt->placed_address, bp_tgt->shadow_contents,
			    bp_tgt->placed_size);

  /* Write the breakpoint.  */
  if (val == 0)
    val = target_write_memory (bp_tgt->placed_address, bp,
			       bp_tgt->placed_size);

  return val;
}
コード例 #3
0
/* ppc_linux_memory_remove_breakpoints attempts to remove a breakpoint
   in much the same fashion as memory_remove_breakpoint in mem-break.c,
   but is careful not to write back the previous contents if the code
   in question has changed in between inserting the breakpoint and
   removing it.

   Here is the problem that we're trying to solve...

   Once upon a time, before introducing this function to remove
   breakpoints from the inferior, setting a breakpoint on a shared
   library function prior to running the program would not work
   properly.  In order to understand the problem, it is first
   necessary to understand a little bit about dynamic linking on
   this platform.

   A call to a shared library function is accomplished via a bl
   (branch-and-link) instruction whose branch target is an entry
   in the procedure linkage table (PLT).  The PLT in the object
   file is uninitialized.  To gdb, prior to running the program, the
   entries in the PLT are all zeros.

   Once the program starts running, the shared libraries are loaded
   and the procedure linkage table is initialized, but the entries in
   the table are not (necessarily) resolved.  Once a function is
   actually called, the code in the PLT is hit and the function is
   resolved.  In order to better illustrate this, an example is in
   order; the following example is from the gdb testsuite.
	    
	We start the program shmain.

	    [kev@arroyo testsuite]$ ../gdb gdb.base/shmain
	    [...]

	We place two breakpoints, one on shr1 and the other on main.

	    (gdb) b shr1
	    Breakpoint 1 at 0x100409d4
	    (gdb) b main
	    Breakpoint 2 at 0x100006a0: file gdb.base/shmain.c, line 44.

	Examine the instruction (and the immediatly following instruction)
	upon which the breakpoint was placed.  Note that the PLT entry
	for shr1 contains zeros.

	    (gdb) x/2i 0x100409d4
	    0x100409d4 <shr1>:      .long 0x0
	    0x100409d8 <shr1+4>:    .long 0x0

	Now run 'til main.

	    (gdb) r
	    Starting program: gdb.base/shmain 
	    Breakpoint 1 at 0xffaf790: file gdb.base/shr1.c, line 19.

	    Breakpoint 2, main ()
		at gdb.base/shmain.c:44
	    44        g = 1;

	Examine the PLT again.  Note that the loading of the shared
	library has initialized the PLT to code which loads a constant
	(which I think is an index into the GOT) into r11 and then
	branchs a short distance to the code which actually does the
	resolving.

	    (gdb) x/2i 0x100409d4
	    0x100409d4 <shr1>:      li      r11,4
	    0x100409d8 <shr1+4>:    b       0x10040984 <sg+4>
	    (gdb) c
	    Continuing.

	    Breakpoint 1, shr1 (x=1)
		at gdb.base/shr1.c:19
	    19        l = 1;

	Now we've hit the breakpoint at shr1.  (The breakpoint was
	reset from the PLT entry to the actual shr1 function after the
	shared library was loaded.) Note that the PLT entry has been
	resolved to contain a branch that takes us directly to shr1.
	(The real one, not the PLT entry.)

	    (gdb) x/2i 0x100409d4
	    0x100409d4 <shr1>:      b       0xffaf76c <shr1>
	    0x100409d8 <shr1+4>:    b       0x10040984 <sg+4>

   The thing to note here is that the PLT entry for shr1 has been
   changed twice.

   Now the problem should be obvious.  GDB places a breakpoint (a
   trap instruction) on the zero value of the PLT entry for shr1.
   Later on, after the shared library had been loaded and the PLT
   initialized, GDB gets a signal indicating this fact and attempts
   (as it always does when it stops) to remove all the breakpoints.

   The breakpoint removal was causing the former contents (a zero
   word) to be written back to the now initialized PLT entry thus
   destroying a portion of the initialization that had occurred only a
   short time ago.  When execution continued, the zero word would be
   executed as an instruction an illegal instruction trap was
   generated instead.  (0 is not a legal instruction.)

   The fix for this problem was fairly straightforward.  The function
   memory_remove_breakpoint from mem-break.c was copied to this file,
   modified slightly, and renamed to ppc_linux_memory_remove_breakpoint.
   In tm-linux.h, MEMORY_REMOVE_BREAKPOINT is defined to call this new
   function.

   The differences between ppc_linux_memory_remove_breakpoint () and
   memory_remove_breakpoint () are minor.  All that the former does
   that the latter does not is check to make sure that the breakpoint
   location actually contains a breakpoint (trap instruction) prior
   to attempting to write back the old contents.  If it does contain
   a trap instruction, we allow the old contents to be written back.
   Otherwise, we silently do nothing.

   The big question is whether memory_remove_breakpoint () should be
   changed to have the same functionality.  The downside is that more
   traffic is generated for remote targets since we'll have an extra
   fetch of a memory word each time a breakpoint is removed.

   For the time being, we'll leave this self-modifying-code-friendly
   version in ppc-linux-tdep.c, but it ought to be migrated somewhere
   else in the event that some other platform has similar needs with
   regard to removing breakpoints in some potentially self modifying
   code.  */
static int
ppc_linux_memory_remove_breakpoint (struct gdbarch *gdbarch,
				    struct bp_target_info *bp_tgt)
{
  CORE_ADDR addr = bp_tgt->placed_address;
  const unsigned char *bp;
  int val;
  int bplen;
  gdb_byte old_contents[BREAKPOINT_MAX];
  struct cleanup *cleanup;

  /* Determine appropriate breakpoint contents and size for this address.  */
  bp = gdbarch_breakpoint_from_pc (gdbarch, &addr, &bplen);
  if (bp == NULL)
    error (_("Software breakpoints not implemented for this target."));

  /* Make sure we see the memory breakpoints.  */
  cleanup = make_show_memory_breakpoints_cleanup (1);
  val = target_read_memory (addr, old_contents, bplen);

  /* If our breakpoint is no longer at the address, this means that the
     program modified the code on us, so it is wrong to put back the
     old value.  */
  if (val == 0 && memcmp (bp, old_contents, bplen) == 0)
    val = target_write_raw_memory (addr, bp_tgt->shadow_contents, bplen);

  do_cleanups (cleanup);
  return val;
}
コード例 #4
0
ファイル: mem-break.c プロジェクト: jon-turney/binutils-gdb
int
memory_validate_breakpoint (struct gdbarch *gdbarch,
			    struct bp_target_info *bp_tgt)
{
  CORE_ADDR addr = bp_tgt->placed_address;
  const gdb_byte *bp;
  int val;
  int bplen;
  gdb_byte cur_contents[BREAKPOINT_MAX];

  /* Determine appropriate breakpoint contents and size for this
     address.  */
  bp = gdbarch_breakpoint_from_pc (gdbarch, &addr, &bplen);

  if (bp == NULL)
    return 0;

  /* Make sure we see the memory breakpoints.  */
  scoped_restore restore_memory
    = make_scoped_restore_show_memory_breakpoints (1);
  val = target_read_memory (addr, cur_contents, bplen);

  /* If our breakpoint is no longer at the address, this means that
     the program modified the code on us, so it is wrong to put back
     the old value.  */
  return (val == 0 && memcmp (bp, cur_contents, bplen) == 0);
}
コード例 #5
0
static int
microblaze_linux_memory_remove_breakpoint (struct gdbarch *gdbarch, 
					   struct bp_target_info *bp_tgt)
{
  CORE_ADDR addr = bp_tgt->reqstd_address;
  const gdb_byte *bp;
  int val;
  int bplen;
  gdb_byte old_contents[BREAKPOINT_MAX];

  /* Determine appropriate breakpoint contents and size for this address.  */
  bp = gdbarch_breakpoint_from_pc (gdbarch, &addr, &bplen);
  if (bp == NULL)
    error (_("Software breakpoints not implemented for this target."));

  val = target_read_memory (addr, old_contents, bplen);

  /* If our breakpoint is no longer at the address, this means that the
     program modified the code on us, so it is wrong to put back the
     old value.  */
  if (val == 0 && memcmp (bp, old_contents, bplen) == 0)
    val = target_write_raw_memory (addr, bp_tgt->shadow_contents, bplen);

  return val;
}
コード例 #6
0
ファイル: arch-utils.c プロジェクト: Manishearth/gdb
void
default_skip_permanent_breakpoint (struct regcache *regcache)
{
  struct gdbarch *gdbarch = get_regcache_arch (regcache);
  CORE_ADDR current_pc = regcache_read_pc (regcache);
  int bp_len;

  gdbarch_breakpoint_from_pc (gdbarch, &current_pc, &bp_len);
  current_pc += bp_len;
  regcache_write_pc (regcache, current_pc);
}
コード例 #7
0
CORE_ADDR
displaced_step_at_entry_point (struct gdbarch *gdbarch)
{
  CORE_ADDR addr;
  int bp_len;

  addr = entry_point_address ();

  /* Inferior calls also use the entry point as a breakpoint location.
     We don't want displaced stepping to interfere with those
     breakpoints, so leave space.  */
  gdbarch_breakpoint_from_pc (gdbarch, &addr, &bp_len);
  addr += bp_len * 2;

  return addr;
}
コード例 #8
0
static CORE_ADDR
amd64_dicos_push_dummy_code (struct gdbarch *gdbarch,
			     CORE_ADDR sp, CORE_ADDR funaddr,
			     struct value **args, int nargs,
			     struct type *value_type,
			     CORE_ADDR *real_pc, CORE_ADDR *bp_addr,
			     struct regcache *regcache)
{
  int bplen;
  CORE_ADDR bppc = sp;

  gdbarch_breakpoint_from_pc (gdbarch, &bppc, &bplen);
  *bp_addr = sp - bplen;
  *real_pc = funaddr;

  return *bp_addr;
}
コード例 #9
0
void
default_remote_breakpoint_from_pc (struct gdbarch *gdbarch, CORE_ADDR *pcptr,
				   int *kindptr)
{
  gdbarch_breakpoint_from_pc (gdbarch, pcptr, kindptr);
}