mirror of
				https://github.com/espressif/binutils-gdb.git
				synced 2025-11-04 06:37:06 +08:00 
			
		
		
		
	* linux-low.c (linux_wait_1): Avoid setting need_step_over is
there's a GDB breakpoint at stop_pc. Always report a trap to GDB if we could tell there's a GDB breakpoint at stop_pc. (need_step_over_p): Don't do a step over if we find a GDB breakpoint at the resume PC. * mem-break.c (struct raw_breakpoint): New. (enum bkpt_type): New type `gdb_breakpoint'. (struct breakpoint): Delete the `PC', `old_data' and `inserted' fields. New field `raw'. (find_raw_breakpoint_at): New. (set_raw_breakpoint_at): Handle refcounting. Create a raw breakpoint instead. (set_breakpoint_at): Adjust. (delete_raw_breakpoint): New. (release_breakpoint): New. (delete_breakpoint): Rename to... (delete_breakpoint_1): ... this. Add proc parameter. Use release_breakpoint. Return ENOENT. (delete_breakpoint): Reimplement. (find_breakpoint_at): Delete. (find_gdb_breakpoint_at): New. (delete_breakpoint_at): Delete. (set_gdb_breakpoint_at): New. (delete_gdb_breakpoint_at): New. (gdb_breakpoint_here): New. (set_reinsert_breakpoint): Use release_breakpoint. (uninsert_breakpoint): Rename to ... (uninsert_raw_breakpoint): ... this. (uninsert_breakpoints_at): Adjust to handle raw breakpoints. (reinsert_raw_breakpoint): Change parameter type to raw_breakpoint. (reinsert_breakpoints_at): Adjust to handle raw breakpoints instead. (check_breakpoints): Adjust. Use release_breakpoint. (breakpoint_here): Rewrite using find_raw_breakpoint_at. (breakpoint_inserted_here): Ditto. (check_mem_read): Adjust to iterate over raw breakpoints instead. Don't trust the breakpoint's shadow if it is not inserted. (check_mem_write): Adjust to iterate over raw breakpoints instead. (delete_all_breakpoints): Adjust. (free_all_breakpoints): Mark all breakpoints as uninserted, and use delete_breakpoint_1. * mem-break.h (breakpoints_supported): Delete declaration. (set_gdb_breakpoint_at): Declare. (gdb_breakpoint_here): Declare. (delete_breakpoint_at): Delete. (delete_gdb_breakpoint_at): Declare. * server.h (struct raw_breakpoint): Forward declare. (struct process_info): New field `raw_breakpoints'. * linux-x86-low.c (x86_insert_point, x86_remote_point): Handle Z0 breakpoints.
This commit is contained in:
		@ -1,3 +1,61 @@
 | 
			
		||||
2010-04-01  Pedro Alves  <pedro@codesourcery.com>
 | 
			
		||||
 | 
			
		||||
	* linux-low.c (linux_wait_1): Avoid setting need_step_over is
 | 
			
		||||
	there's a GDB breakpoint at stop_pc.  Always report a trap to GDB
 | 
			
		||||
	if we could tell there's a GDB breakpoint at stop_pc.
 | 
			
		||||
	(need_step_over_p): Don't do a step over if we find a GDB
 | 
			
		||||
	breakpoint at the resume PC.
 | 
			
		||||
 | 
			
		||||
	* mem-break.c (struct raw_breakpoint): New.
 | 
			
		||||
	(enum bkpt_type): New type `gdb_breakpoint'.
 | 
			
		||||
	(struct breakpoint): Delete the `PC', `old_data' and `inserted'
 | 
			
		||||
	fields.  New field `raw'.
 | 
			
		||||
	(find_raw_breakpoint_at): New.
 | 
			
		||||
	(set_raw_breakpoint_at): Handle refcounting.  Create a raw
 | 
			
		||||
	breakpoint instead.
 | 
			
		||||
	(set_breakpoint_at): Adjust.
 | 
			
		||||
	(delete_raw_breakpoint): New.
 | 
			
		||||
	(release_breakpoint): New.
 | 
			
		||||
	(delete_breakpoint): Rename to...
 | 
			
		||||
	(delete_breakpoint_1): ... this.  Add proc parameter.  Use
 | 
			
		||||
	release_breakpoint.  Return ENOENT.
 | 
			
		||||
	(delete_breakpoint): Reimplement.
 | 
			
		||||
	(find_breakpoint_at): Delete.
 | 
			
		||||
	(find_gdb_breakpoint_at): New.
 | 
			
		||||
	(delete_breakpoint_at): Delete.
 | 
			
		||||
	(set_gdb_breakpoint_at): New.
 | 
			
		||||
	(delete_gdb_breakpoint_at): New.
 | 
			
		||||
	(gdb_breakpoint_here): New.
 | 
			
		||||
	(set_reinsert_breakpoint): Use release_breakpoint.
 | 
			
		||||
	(uninsert_breakpoint): Rename to ...
 | 
			
		||||
	(uninsert_raw_breakpoint): ... this.
 | 
			
		||||
	(uninsert_breakpoints_at): Adjust to handle raw breakpoints.
 | 
			
		||||
	(reinsert_raw_breakpoint): Change parameter type to
 | 
			
		||||
	raw_breakpoint.
 | 
			
		||||
	(reinsert_breakpoints_at): Adjust to handle raw breakpoints
 | 
			
		||||
	instead.
 | 
			
		||||
	(check_breakpoints): Adjust.  Use release_breakpoint.
 | 
			
		||||
	(breakpoint_here): Rewrite using find_raw_breakpoint_at.
 | 
			
		||||
	(breakpoint_inserted_here): Ditto.
 | 
			
		||||
	(check_mem_read): Adjust to iterate over raw breakpoints instead.
 | 
			
		||||
	Don't trust the breakpoint's shadow if it is not inserted.
 | 
			
		||||
	(check_mem_write): Adjust to iterate over raw breakpoints instead.
 | 
			
		||||
	(delete_all_breakpoints): Adjust.
 | 
			
		||||
	(free_all_breakpoints): Mark all breakpoints as uninserted, and
 | 
			
		||||
	use delete_breakpoint_1.
 | 
			
		||||
 | 
			
		||||
	* mem-break.h (breakpoints_supported): Delete declaration.
 | 
			
		||||
	(set_gdb_breakpoint_at): Declare.
 | 
			
		||||
	(gdb_breakpoint_here): Declare.
 | 
			
		||||
	(delete_breakpoint_at): Delete.
 | 
			
		||||
	(delete_gdb_breakpoint_at): Declare.
 | 
			
		||||
 | 
			
		||||
	* server.h (struct raw_breakpoint): Forward declare.
 | 
			
		||||
	(struct process_info): New field `raw_breakpoints'.
 | 
			
		||||
 | 
			
		||||
	* linux-x86-low.c (x86_insert_point, x86_remote_point): Handle Z0
 | 
			
		||||
	breakpoints.
 | 
			
		||||
 | 
			
		||||
2010-03-24  Pedro Alves  <pedro@codesourcery.com>
 | 
			
		||||
 | 
			
		||||
	* linux-low.c (status_pending_p_callback): Fix comment.
 | 
			
		||||
 | 
			
		||||
@ -1740,7 +1740,8 @@ retry:
 | 
			
		||||
	  if (debug_threads)
 | 
			
		||||
	    fprintf (stderr, "Hit a gdbserver breakpoint.\n");
 | 
			
		||||
 | 
			
		||||
	  event_child->need_step_over = 1;
 | 
			
		||||
	  if (breakpoint_here (event_child->stop_pc))
 | 
			
		||||
	    event_child->need_step_over = 1;
 | 
			
		||||
	}
 | 
			
		||||
    }
 | 
			
		||||
  else
 | 
			
		||||
@ -1755,11 +1756,18 @@ retry:
 | 
			
		||||
 | 
			
		||||
  /* Check If GDB would be interested in this event.  If GDB wanted
 | 
			
		||||
     this thread to single step, we always want to report the SIGTRAP,
 | 
			
		||||
     and let GDB handle it.  */
 | 
			
		||||
     and let GDB handle it.  Watchpoints should always be reported.
 | 
			
		||||
     So should signals we can't explain.  A SIGTRAP we can't explain
 | 
			
		||||
     could be a GDB breakpoint --- we may or not support Z0
 | 
			
		||||
     breakpoints.  If we do, we're be able to handle GDB breakpoints
 | 
			
		||||
     on top of internal breakpoints, by handling the internal
 | 
			
		||||
     breakpoint and still reporting the event to GDB.  If we don't,
 | 
			
		||||
     we're out of luck, GDB won't see the breakpoint hit.  */
 | 
			
		||||
  report_to_gdb = (!maybe_internal_trap
 | 
			
		||||
		   || event_child->last_resume_kind == resume_step
 | 
			
		||||
		   || event_child->stopped_by_watchpoint
 | 
			
		||||
		   || (!step_over_finished && !bp_explains_trap));
 | 
			
		||||
		   || (!step_over_finished && !bp_explains_trap)
 | 
			
		||||
		   || gdb_breakpoint_here (event_child->stop_pc));
 | 
			
		||||
 | 
			
		||||
  /* We found no reason GDB would want us to stop.  We either hit one
 | 
			
		||||
     of our own breakpoints, or finished an internal step GDB
 | 
			
		||||
@ -1801,6 +1809,8 @@ retry:
 | 
			
		||||
	fprintf (stderr, "GDB wanted to single-step, reporting event.\n");
 | 
			
		||||
      if (event_child->stopped_by_watchpoint)
 | 
			
		||||
	fprintf (stderr, "Stopped by watchpoint.\n");
 | 
			
		||||
      if (gdb_breakpoint_here (event_child->stop_pc))
 | 
			
		||||
	fprintf (stderr, "Stopped by GDB breakpoint.\n");
 | 
			
		||||
      if (debug_threads)
 | 
			
		||||
	fprintf (stderr, "Hit a non-gdbserver trap event.\n");
 | 
			
		||||
    }
 | 
			
		||||
@ -2401,21 +2411,37 @@ need_step_over_p (struct inferior_list_entry *entry, void *dummy)
 | 
			
		||||
  saved_inferior = current_inferior;
 | 
			
		||||
  current_inferior = get_lwp_thread (lwp);
 | 
			
		||||
 | 
			
		||||
  /* We only step over our breakpoints.  */
 | 
			
		||||
  /* We can only step over breakpoints we know about.  */
 | 
			
		||||
  if (breakpoint_here (pc))
 | 
			
		||||
    {
 | 
			
		||||
      if (debug_threads)
 | 
			
		||||
	fprintf (stderr,
 | 
			
		||||
		 "Need step over [LWP %ld]? yes, found breakpoint at 0x%s\n",
 | 
			
		||||
		 lwpid_of (lwp), paddress (pc));
 | 
			
		||||
      /* Don't step over a breakpoint that GDB expects to hit
 | 
			
		||||
	 though.  */
 | 
			
		||||
      if (gdb_breakpoint_here (pc))
 | 
			
		||||
	{
 | 
			
		||||
	  if (debug_threads)
 | 
			
		||||
	    fprintf (stderr,
 | 
			
		||||
		     "Need step over [LWP %ld]? yes, but found"
 | 
			
		||||
		     " GDB breakpoint at 0x%s; skipping step over\n",
 | 
			
		||||
		     lwpid_of (lwp), paddress (pc));
 | 
			
		||||
 | 
			
		||||
      /* We've found an lwp that needs stepping over --- return 1 so
 | 
			
		||||
	 that find_inferior stops looking.  */
 | 
			
		||||
      current_inferior = saved_inferior;
 | 
			
		||||
	  current_inferior = saved_inferior;
 | 
			
		||||
	  return 0;
 | 
			
		||||
	}
 | 
			
		||||
      else
 | 
			
		||||
	{
 | 
			
		||||
	  if (debug_threads)
 | 
			
		||||
	    fprintf (stderr,
 | 
			
		||||
		     "Need step over [LWP %ld]? yes, found breakpoint at 0x%s\n",
 | 
			
		||||
		     lwpid_of (lwp), paddress (pc));
 | 
			
		||||
 | 
			
		||||
      /* If the step over is cancelled, this is set again.  */
 | 
			
		||||
      lwp->need_step_over = 0;
 | 
			
		||||
      return 1;
 | 
			
		||||
	  /* We've found an lwp that needs stepping over --- return 1 so
 | 
			
		||||
	     that find_inferior stops looking.  */
 | 
			
		||||
	  current_inferior = saved_inferior;
 | 
			
		||||
 | 
			
		||||
	  /* If the step over is cancelled, this is set again.  */
 | 
			
		||||
	  lwp->need_step_over = 0;
 | 
			
		||||
	  return 1;
 | 
			
		||||
	}
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  current_inferior = saved_inferior;
 | 
			
		||||
 | 
			
		||||
@ -431,6 +431,8 @@ x86_insert_point (char type, CORE_ADDR addr, int len)
 | 
			
		||||
  struct process_info *proc = current_process ();
 | 
			
		||||
  switch (type)
 | 
			
		||||
    {
 | 
			
		||||
    case '0':
 | 
			
		||||
      return set_gdb_breakpoint_at (addr);
 | 
			
		||||
    case '2':
 | 
			
		||||
    case '3':
 | 
			
		||||
    case '4':
 | 
			
		||||
@ -448,6 +450,8 @@ x86_remove_point (char type, CORE_ADDR addr, int len)
 | 
			
		||||
  struct process_info *proc = current_process ();
 | 
			
		||||
  switch (type)
 | 
			
		||||
    {
 | 
			
		||||
    case '0':
 | 
			
		||||
      return delete_gdb_breakpoint_at (addr);
 | 
			
		||||
    case '2':
 | 
			
		||||
    case '3':
 | 
			
		||||
    case '4':
 | 
			
		||||
 | 
			
		||||
@ -26,9 +26,53 @@ int breakpoint_len;
 | 
			
		||||
 | 
			
		||||
#define MAX_BREAKPOINT_LEN 8
 | 
			
		||||
 | 
			
		||||
/* GDB will never try to install multiple breakpoints at the same
 | 
			
		||||
   address.  But, we need to keep track of internal breakpoints too,
 | 
			
		||||
   and so we do need to be able to install multiple breakpoints at the
 | 
			
		||||
   same address transparently.  We keep track of two different, and
 | 
			
		||||
   closely related structures.  A raw breakpoint, which manages the
 | 
			
		||||
   low level, close to the metal aspect of a breakpoint.  It holds the
 | 
			
		||||
   breakpoint address, and a buffer holding a copy of the instructions
 | 
			
		||||
   that would be in memory had not been a breakpoint there (we call
 | 
			
		||||
   that the shadow memory of the breakpoint).  We occasionally need to
 | 
			
		||||
   temporarilly uninsert a breakpoint without the client knowing about
 | 
			
		||||
   it (e.g., to step over an internal breakpoint), so we keep an
 | 
			
		||||
   `inserted' state associated with this low level breakpoint
 | 
			
		||||
   structure.  There can only be one such object for a given address.
 | 
			
		||||
   Then, we have (a bit higher level) breakpoints.  This structure
 | 
			
		||||
   holds a callback to be called whenever a breakpoint is hit, a
 | 
			
		||||
   high-level type, and a link to a low level raw breakpoint.  There
 | 
			
		||||
   can be many high-level breakpoints at the same address, and all of
 | 
			
		||||
   them will point to the same raw breakpoint, which is reference
 | 
			
		||||
   counted.  */
 | 
			
		||||
 | 
			
		||||
/* The low level, physical, raw breakpoint.  */
 | 
			
		||||
struct raw_breakpoint
 | 
			
		||||
{
 | 
			
		||||
  struct raw_breakpoint *next;
 | 
			
		||||
 | 
			
		||||
  /* A reference count.  Each high level breakpoint referencing this
 | 
			
		||||
     raw breakpoint accounts for one reference.  */
 | 
			
		||||
  int refcount;
 | 
			
		||||
 | 
			
		||||
  /* The breakpoint's insertion address.  There can only be one raw
 | 
			
		||||
     breakpoint for a given PC.  */
 | 
			
		||||
  CORE_ADDR pc;
 | 
			
		||||
 | 
			
		||||
  /* The breakpoint's shadow memory.  */
 | 
			
		||||
  unsigned char old_data[MAX_BREAKPOINT_LEN];
 | 
			
		||||
 | 
			
		||||
  /* Non-zero if this breakpoint is currently inserted in the
 | 
			
		||||
     inferior.  */
 | 
			
		||||
  int inserted;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/* The type of a breakpoint.  */
 | 
			
		||||
enum bkpt_type
 | 
			
		||||
  {
 | 
			
		||||
    /* A GDB breakpoint, requested with a Z0 packet.  */
 | 
			
		||||
    gdb_breakpoint,
 | 
			
		||||
 | 
			
		||||
    /* A basic-software-single-step breakpoint.  */
 | 
			
		||||
    reinsert_breakpoint,
 | 
			
		||||
 | 
			
		||||
@ -37,38 +81,57 @@ enum bkpt_type
 | 
			
		||||
    other_breakpoint,
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
/* A high level (in gdbserver's perspective) breakpoint.  */
 | 
			
		||||
struct breakpoint
 | 
			
		||||
{
 | 
			
		||||
  struct breakpoint *next;
 | 
			
		||||
  CORE_ADDR pc;
 | 
			
		||||
  unsigned char old_data[MAX_BREAKPOINT_LEN];
 | 
			
		||||
 | 
			
		||||
  /* Non-zero if this breakpoint is currently inserted in the
 | 
			
		||||
     inferior.  */
 | 
			
		||||
  int inserted;
 | 
			
		||||
 | 
			
		||||
  /* The breakpoint's type.  */
 | 
			
		||||
  enum bkpt_type type;
 | 
			
		||||
 | 
			
		||||
  /* Link to this breakpoint's raw breakpoint.  This is always
 | 
			
		||||
     non-NULL.  */
 | 
			
		||||
  struct raw_breakpoint *raw;
 | 
			
		||||
 | 
			
		||||
  /* Function to call when we hit this breakpoint.  If it returns 1,
 | 
			
		||||
     the breakpoint shall be deleted; 0, it will be left inserted.  */
 | 
			
		||||
     the breakpoint shall be deleted; 0 or if this callback is NULL,
 | 
			
		||||
     it will be left inserted.  */
 | 
			
		||||
  int (*handler) (CORE_ADDR);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static void uninsert_breakpoint (struct breakpoint *bp);
 | 
			
		||||
static struct raw_breakpoint *
 | 
			
		||||
find_raw_breakpoint_at (CORE_ADDR where)
 | 
			
		||||
{
 | 
			
		||||
  struct process_info *proc = current_process ();
 | 
			
		||||
  struct raw_breakpoint *bp;
 | 
			
		||||
 | 
			
		||||
static struct breakpoint *
 | 
			
		||||
  for (bp = proc->raw_breakpoints; bp != NULL; bp = bp->next)
 | 
			
		||||
    if (bp->pc == where)
 | 
			
		||||
      return bp;
 | 
			
		||||
 | 
			
		||||
  return NULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static struct raw_breakpoint *
 | 
			
		||||
set_raw_breakpoint_at (CORE_ADDR where)
 | 
			
		||||
{
 | 
			
		||||
  struct process_info *proc = current_process ();
 | 
			
		||||
  struct breakpoint *bp;
 | 
			
		||||
  struct raw_breakpoint *bp;
 | 
			
		||||
  int err;
 | 
			
		||||
 | 
			
		||||
  if (breakpoint_data == NULL)
 | 
			
		||||
    error ("Target does not support breakpoints.");
 | 
			
		||||
 | 
			
		||||
  bp = find_raw_breakpoint_at (where);
 | 
			
		||||
  if (bp != NULL)
 | 
			
		||||
    {
 | 
			
		||||
      bp->refcount++;
 | 
			
		||||
      return bp;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  bp = xcalloc (1, sizeof (*bp));
 | 
			
		||||
  bp->pc = where;
 | 
			
		||||
  bp->refcount = 1;
 | 
			
		||||
 | 
			
		||||
  err = (*the_target->read_memory) (where, bp->old_data,
 | 
			
		||||
				    breakpoint_len);
 | 
			
		||||
@ -97,8 +160,8 @@ set_raw_breakpoint_at (CORE_ADDR where)
 | 
			
		||||
 | 
			
		||||
  /* Link the breakpoint in.  */
 | 
			
		||||
  bp->inserted = 1;
 | 
			
		||||
  bp->next = proc->breakpoints;
 | 
			
		||||
  proc->breakpoints = bp;
 | 
			
		||||
  bp->next = proc->raw_breakpoints;
 | 
			
		||||
  proc->raw_breakpoints = bp;
 | 
			
		||||
  return bp;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -107,10 +170,11 @@ set_breakpoint_at (CORE_ADDR where, int (*handler) (CORE_ADDR))
 | 
			
		||||
{
 | 
			
		||||
  struct process_info *proc = current_process ();
 | 
			
		||||
  struct breakpoint *bp;
 | 
			
		||||
  struct raw_breakpoint *raw;
 | 
			
		||||
 | 
			
		||||
  bp = set_raw_breakpoint_at (where);
 | 
			
		||||
  raw = set_raw_breakpoint_at (where);
 | 
			
		||||
 | 
			
		||||
  if (bp == NULL)
 | 
			
		||||
  if (raw == NULL)
 | 
			
		||||
    {
 | 
			
		||||
      /* warn? */
 | 
			
		||||
      return NULL;
 | 
			
		||||
@ -118,6 +182,8 @@ set_breakpoint_at (CORE_ADDR where, int (*handler) (CORE_ADDR))
 | 
			
		||||
 | 
			
		||||
  bp = xcalloc (1, sizeof (struct breakpoint));
 | 
			
		||||
  bp->type = other_breakpoint;
 | 
			
		||||
 | 
			
		||||
  bp->raw = raw;
 | 
			
		||||
  bp->handler = handler;
 | 
			
		||||
 | 
			
		||||
  bp->next = proc->breakpoints;
 | 
			
		||||
@ -126,11 +192,84 @@ set_breakpoint_at (CORE_ADDR where, int (*handler) (CORE_ADDR))
 | 
			
		||||
  return bp;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
delete_breakpoint (struct breakpoint *todel)
 | 
			
		||||
static int
 | 
			
		||||
delete_raw_breakpoint (struct process_info *proc, struct raw_breakpoint *todel)
 | 
			
		||||
{
 | 
			
		||||
  struct raw_breakpoint *bp, **bp_link;
 | 
			
		||||
  int ret;
 | 
			
		||||
 | 
			
		||||
  bp = proc->raw_breakpoints;
 | 
			
		||||
  bp_link = &proc->raw_breakpoints;
 | 
			
		||||
 | 
			
		||||
  while (bp)
 | 
			
		||||
    {
 | 
			
		||||
      if (bp == todel)
 | 
			
		||||
	{
 | 
			
		||||
	  if (bp->inserted)
 | 
			
		||||
	    {
 | 
			
		||||
	      struct raw_breakpoint *prev_bp_link = *bp_link;
 | 
			
		||||
 | 
			
		||||
	      *bp_link = bp->next;
 | 
			
		||||
 | 
			
		||||
	      ret = (*the_target->write_memory) (bp->pc, bp->old_data,
 | 
			
		||||
						 breakpoint_len);
 | 
			
		||||
	      if (ret != 0)
 | 
			
		||||
		{
 | 
			
		||||
		  /* Something went wrong, relink the breakpoint.  */
 | 
			
		||||
		  *bp_link = prev_bp_link;
 | 
			
		||||
 | 
			
		||||
		  if (debug_threads)
 | 
			
		||||
		    fprintf (stderr,
 | 
			
		||||
			     "Failed to uninsert raw breakpoint "
 | 
			
		||||
			     "at 0x%s (%s) while deleting it.\n",
 | 
			
		||||
			     paddress (bp->pc), strerror (ret));
 | 
			
		||||
		  return ret;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
	    }
 | 
			
		||||
	  else
 | 
			
		||||
	    *bp_link = bp->next;
 | 
			
		||||
 | 
			
		||||
	  free (bp);
 | 
			
		||||
	  return 0;
 | 
			
		||||
	}
 | 
			
		||||
      else
 | 
			
		||||
	{
 | 
			
		||||
	  bp_link = &bp->next;
 | 
			
		||||
	  bp = *bp_link;
 | 
			
		||||
	}
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  warning ("Could not find raw breakpoint in list.");
 | 
			
		||||
  return ENOENT;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int
 | 
			
		||||
release_breakpoint (struct process_info *proc, struct breakpoint *bp)
 | 
			
		||||
{
 | 
			
		||||
  int newrefcount;
 | 
			
		||||
  int ret;
 | 
			
		||||
 | 
			
		||||
  newrefcount = bp->raw->refcount - 1;
 | 
			
		||||
  if (newrefcount == 0)
 | 
			
		||||
    {
 | 
			
		||||
      ret = delete_raw_breakpoint (proc, bp->raw);
 | 
			
		||||
      if (ret != 0)
 | 
			
		||||
	return ret;
 | 
			
		||||
    }
 | 
			
		||||
  else
 | 
			
		||||
    bp->raw->refcount = newrefcount;
 | 
			
		||||
 | 
			
		||||
  free (bp);
 | 
			
		||||
 | 
			
		||||
  return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int
 | 
			
		||||
delete_breakpoint_1 (struct process_info *proc, struct breakpoint *todel)
 | 
			
		||||
{
 | 
			
		||||
  struct process_info *proc = current_process ();
 | 
			
		||||
  struct breakpoint *bp, **bp_link;
 | 
			
		||||
  int err;
 | 
			
		||||
 | 
			
		||||
  bp = proc->breakpoints;
 | 
			
		||||
  bp_link = &proc->breakpoints;
 | 
			
		||||
@ -141,9 +280,12 @@ delete_breakpoint (struct breakpoint *todel)
 | 
			
		||||
	{
 | 
			
		||||
	  *bp_link = bp->next;
 | 
			
		||||
 | 
			
		||||
	  uninsert_breakpoint (bp);
 | 
			
		||||
	  free (bp);
 | 
			
		||||
	  return;
 | 
			
		||||
	  err = release_breakpoint (proc, bp);
 | 
			
		||||
	  if (err != 0)
 | 
			
		||||
	    return err;
 | 
			
		||||
 | 
			
		||||
	  bp = *bp_link;
 | 
			
		||||
	  return 0;
 | 
			
		||||
	}
 | 
			
		||||
      else
 | 
			
		||||
	{
 | 
			
		||||
@ -153,30 +295,71 @@ delete_breakpoint (struct breakpoint *todel)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  warning ("Could not find breakpoint in list.");
 | 
			
		||||
  return ENOENT;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int
 | 
			
		||||
delete_breakpoint (struct breakpoint *todel)
 | 
			
		||||
{
 | 
			
		||||
  struct process_info *proc = current_process ();
 | 
			
		||||
  return delete_breakpoint_1 (proc, todel);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static struct breakpoint *
 | 
			
		||||
find_breakpoint_at (CORE_ADDR where)
 | 
			
		||||
find_gdb_breakpoint_at (CORE_ADDR where)
 | 
			
		||||
{
 | 
			
		||||
  struct process_info *proc = current_process ();
 | 
			
		||||
  struct breakpoint *bp = proc->breakpoints;
 | 
			
		||||
  struct breakpoint *bp;
 | 
			
		||||
 | 
			
		||||
  while (bp != NULL)
 | 
			
		||||
    {
 | 
			
		||||
      if (bp->pc == where)
 | 
			
		||||
	return bp;
 | 
			
		||||
      bp = bp->next;
 | 
			
		||||
    }
 | 
			
		||||
  for (bp = proc->breakpoints; bp != NULL; bp = bp->next)
 | 
			
		||||
    if (bp->type == gdb_breakpoint && bp->raw->pc == where)
 | 
			
		||||
      return bp;
 | 
			
		||||
 | 
			
		||||
  return NULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
delete_breakpoint_at (CORE_ADDR addr)
 | 
			
		||||
int
 | 
			
		||||
set_gdb_breakpoint_at (CORE_ADDR where)
 | 
			
		||||
{
 | 
			
		||||
  struct breakpoint *bp = find_breakpoint_at (addr);
 | 
			
		||||
  if (bp != NULL)
 | 
			
		||||
    delete_breakpoint (bp);
 | 
			
		||||
  struct breakpoint *bp;
 | 
			
		||||
 | 
			
		||||
  if (breakpoint_data == NULL)
 | 
			
		||||
    return 1;
 | 
			
		||||
 | 
			
		||||
  bp = set_breakpoint_at (where, NULL);
 | 
			
		||||
  if (bp == NULL)
 | 
			
		||||
    return -1;
 | 
			
		||||
 | 
			
		||||
  bp->type = gdb_breakpoint;
 | 
			
		||||
  return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int
 | 
			
		||||
delete_gdb_breakpoint_at (CORE_ADDR addr)
 | 
			
		||||
{
 | 
			
		||||
  struct breakpoint *bp;
 | 
			
		||||
  int err;
 | 
			
		||||
 | 
			
		||||
  if (breakpoint_data == NULL)
 | 
			
		||||
    return 1;
 | 
			
		||||
 | 
			
		||||
  bp = find_gdb_breakpoint_at (addr);
 | 
			
		||||
  if (bp == NULL)
 | 
			
		||||
    return -1;
 | 
			
		||||
 | 
			
		||||
  err = delete_breakpoint (bp);
 | 
			
		||||
  if (err)
 | 
			
		||||
    return -1;
 | 
			
		||||
 | 
			
		||||
  return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int
 | 
			
		||||
gdb_breakpoint_here (CORE_ADDR where)
 | 
			
		||||
{
 | 
			
		||||
  struct breakpoint *bp = find_gdb_breakpoint_at (where);
 | 
			
		||||
 | 
			
		||||
  return (bp != NULL);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
@ -185,7 +368,6 @@ set_reinsert_breakpoint (CORE_ADDR stop_at)
 | 
			
		||||
  struct breakpoint *bp;
 | 
			
		||||
 | 
			
		||||
  bp = set_breakpoint_at (stop_at, NULL);
 | 
			
		||||
 | 
			
		||||
  bp->type = reinsert_breakpoint;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -203,13 +385,7 @@ delete_reinsert_breakpoints (void)
 | 
			
		||||
      if (bp->type == reinsert_breakpoint)
 | 
			
		||||
	{
 | 
			
		||||
	  *bp_link = bp->next;
 | 
			
		||||
 | 
			
		||||
	  /* If something goes wrong, maybe this is a shared library
 | 
			
		||||
	     breakpoint, and the shared library has been unmapped.
 | 
			
		||||
	     Assume the breakpoint is gone anyway.  */
 | 
			
		||||
	  uninsert_breakpoint (bp);
 | 
			
		||||
	  free (bp);
 | 
			
		||||
 | 
			
		||||
	  release_breakpoint (proc, bp);
 | 
			
		||||
	  bp = *bp_link;
 | 
			
		||||
	}
 | 
			
		||||
      else
 | 
			
		||||
@ -221,7 +397,7 @@ delete_reinsert_breakpoints (void)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
uninsert_breakpoint (struct breakpoint *bp)
 | 
			
		||||
uninsert_raw_breakpoint (struct raw_breakpoint *bp)
 | 
			
		||||
{
 | 
			
		||||
  if (bp->inserted)
 | 
			
		||||
    {
 | 
			
		||||
@ -245,9 +421,9 @@ uninsert_breakpoint (struct breakpoint *bp)
 | 
			
		||||
void
 | 
			
		||||
uninsert_breakpoints_at (CORE_ADDR pc)
 | 
			
		||||
{
 | 
			
		||||
  struct breakpoint *bp;
 | 
			
		||||
  struct raw_breakpoint *bp;
 | 
			
		||||
 | 
			
		||||
  bp = find_breakpoint_at (pc);
 | 
			
		||||
  bp = find_raw_breakpoint_at (pc);
 | 
			
		||||
  if (bp == NULL)
 | 
			
		||||
    {
 | 
			
		||||
      /* This can happen when we remove all breakpoints while handling
 | 
			
		||||
@ -261,11 +437,11 @@ uninsert_breakpoints_at (CORE_ADDR pc)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  if (bp->inserted)
 | 
			
		||||
    uninsert_breakpoint (bp);
 | 
			
		||||
    uninsert_raw_breakpoint (bp);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
reinsert_raw_breakpoint (struct breakpoint *bp)
 | 
			
		||||
reinsert_raw_breakpoint (struct raw_breakpoint *bp)
 | 
			
		||||
{
 | 
			
		||||
  int err;
 | 
			
		||||
 | 
			
		||||
@ -285,16 +461,16 @@ reinsert_raw_breakpoint (struct breakpoint *bp)
 | 
			
		||||
void
 | 
			
		||||
reinsert_breakpoints_at (CORE_ADDR pc)
 | 
			
		||||
{
 | 
			
		||||
  struct breakpoint *bp;
 | 
			
		||||
  struct raw_breakpoint *bp;
 | 
			
		||||
 | 
			
		||||
  bp = find_breakpoint_at (pc);
 | 
			
		||||
  bp = find_raw_breakpoint_at (pc);
 | 
			
		||||
  if (bp == NULL)
 | 
			
		||||
    {
 | 
			
		||||
      /* This can happen when we remove all breakpoints while handling
 | 
			
		||||
	 a step-over.  */
 | 
			
		||||
      if (debug_threads)
 | 
			
		||||
	fprintf (stderr,
 | 
			
		||||
		 "Could not find breakpoint at 0x%s "
 | 
			
		||||
		 "Could not find raw breakpoint at 0x%s "
 | 
			
		||||
		 "in list (reinserting).\n",
 | 
			
		||||
		 paddress (pc));
 | 
			
		||||
      return;
 | 
			
		||||
@ -314,9 +490,9 @@ check_breakpoints (CORE_ADDR stop_pc)
 | 
			
		||||
 | 
			
		||||
  while (bp)
 | 
			
		||||
    {
 | 
			
		||||
      if (bp->pc == stop_pc)
 | 
			
		||||
      if (bp->raw->pc == stop_pc)
 | 
			
		||||
	{
 | 
			
		||||
	  if (!bp->inserted)
 | 
			
		||||
	  if (!bp->raw->inserted)
 | 
			
		||||
	    {
 | 
			
		||||
	      warning ("Hit a removed breakpoint?");
 | 
			
		||||
	      return;
 | 
			
		||||
@ -326,7 +502,7 @@ check_breakpoints (CORE_ADDR stop_pc)
 | 
			
		||||
	    {
 | 
			
		||||
	      *bp_link = bp->next;
 | 
			
		||||
 | 
			
		||||
	      delete_breakpoint (bp);
 | 
			
		||||
	      release_breakpoint (proc, bp);
 | 
			
		||||
 | 
			
		||||
	      bp = *bp_link;
 | 
			
		||||
	      continue;
 | 
			
		||||
@ -348,34 +524,24 @@ set_breakpoint_data (const unsigned char *bp_data, int bp_len)
 | 
			
		||||
int
 | 
			
		||||
breakpoint_here (CORE_ADDR addr)
 | 
			
		||||
{
 | 
			
		||||
  struct process_info *proc = current_process ();
 | 
			
		||||
  struct breakpoint *bp;
 | 
			
		||||
 | 
			
		||||
  for (bp = proc->breakpoints; bp != NULL; bp = bp->next)
 | 
			
		||||
    if (bp->pc == addr)
 | 
			
		||||
      return 1;
 | 
			
		||||
 | 
			
		||||
  return 0;
 | 
			
		||||
  return (find_raw_breakpoint_at (addr) != NULL);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int
 | 
			
		||||
breakpoint_inserted_here (CORE_ADDR addr)
 | 
			
		||||
{
 | 
			
		||||
  struct process_info *proc = current_process ();
 | 
			
		||||
  struct breakpoint *bp;
 | 
			
		||||
  struct raw_breakpoint *bp;
 | 
			
		||||
 | 
			
		||||
  for (bp = proc->breakpoints; bp != NULL; bp = bp->next)
 | 
			
		||||
    if (bp->pc == addr && bp->inserted)
 | 
			
		||||
      return 1;
 | 
			
		||||
  bp = find_raw_breakpoint_at (addr);
 | 
			
		||||
 | 
			
		||||
  return 0;
 | 
			
		||||
  return (bp != NULL && bp->inserted);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
check_mem_read (CORE_ADDR mem_addr, unsigned char *buf, int mem_len)
 | 
			
		||||
{
 | 
			
		||||
  struct process_info *proc = current_process ();
 | 
			
		||||
  struct breakpoint *bp = proc->breakpoints;
 | 
			
		||||
  struct raw_breakpoint *bp = proc->raw_breakpoints;
 | 
			
		||||
  CORE_ADDR mem_end = mem_addr + mem_len;
 | 
			
		||||
 | 
			
		||||
  for (; bp != NULL; bp = bp->next)
 | 
			
		||||
@ -401,7 +567,8 @@ check_mem_read (CORE_ADDR mem_addr, unsigned char *buf, int mem_len)
 | 
			
		||||
      copy_offset = start - bp->pc;
 | 
			
		||||
      buf_offset = start - mem_addr;
 | 
			
		||||
 | 
			
		||||
      memcpy (buf + buf_offset, bp->old_data + copy_offset, copy_len);
 | 
			
		||||
      if (bp->inserted)
 | 
			
		||||
	memcpy (buf + buf_offset, bp->old_data + copy_offset, copy_len);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -409,7 +576,7 @@ void
 | 
			
		||||
check_mem_write (CORE_ADDR mem_addr, unsigned char *buf, int mem_len)
 | 
			
		||||
{
 | 
			
		||||
  struct process_info *proc = current_process ();
 | 
			
		||||
  struct breakpoint *bp = proc->breakpoints;
 | 
			
		||||
  struct raw_breakpoint *bp = proc->raw_breakpoints;
 | 
			
		||||
  CORE_ADDR mem_end = mem_addr + mem_len;
 | 
			
		||||
 | 
			
		||||
  for (; bp != NULL; bp = bp->next)
 | 
			
		||||
@ -449,7 +616,7 @@ delete_all_breakpoints (void)
 | 
			
		||||
  struct process_info *proc = current_process ();
 | 
			
		||||
 | 
			
		||||
  while (proc->breakpoints)
 | 
			
		||||
    delete_breakpoint (proc->breakpoints);
 | 
			
		||||
    delete_breakpoint_1 (proc, proc->breakpoints);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Release all breakpoints, but do not try to un-insert them from the
 | 
			
		||||
@ -458,12 +625,15 @@ delete_all_breakpoints (void)
 | 
			
		||||
void
 | 
			
		||||
free_all_breakpoints (struct process_info *proc)
 | 
			
		||||
{
 | 
			
		||||
  struct breakpoint *bp;
 | 
			
		||||
  struct raw_breakpoint *raw_bp;
 | 
			
		||||
 | 
			
		||||
  for (raw_bp = proc->raw_breakpoints; raw_bp != NULL; raw_bp = raw_bp->next)
 | 
			
		||||
    raw_bp->inserted = 0;
 | 
			
		||||
 | 
			
		||||
  /* Note: use PROC explicitly instead of deferring to
 | 
			
		||||
     delete_all_breakpoints --- CURRENT_INFERIOR may already have been
 | 
			
		||||
     released when we get here.  There should be no call to
 | 
			
		||||
     current_process from here on.  */
 | 
			
		||||
  while (proc->breakpoints)
 | 
			
		||||
    {
 | 
			
		||||
      bp = proc->breakpoints;
 | 
			
		||||
      proc->breakpoints = bp->next;
 | 
			
		||||
      free (bp);
 | 
			
		||||
    }
 | 
			
		||||
    delete_breakpoint_1 (proc, proc->breakpoints);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -25,9 +25,10 @@
 | 
			
		||||
/* Breakpoints are opaque.  */
 | 
			
		||||
struct breakpoint;
 | 
			
		||||
 | 
			
		||||
/* Returns TRUE if breakpoints are supported on this target.  */
 | 
			
		||||
/* Create a new GDB breakpoint at WHERE.  Returns -1 if breakpoints
 | 
			
		||||
   are not supported on this target, 0 otherwise.  */
 | 
			
		||||
 | 
			
		||||
int breakpoints_supported (void);
 | 
			
		||||
int set_gdb_breakpoint_at (CORE_ADDR where);
 | 
			
		||||
 | 
			
		||||
/* Returns TRUE if there's any breakpoint at ADDR in our tables,
 | 
			
		||||
   inserted, or not.  */
 | 
			
		||||
@ -38,6 +39,10 @@ int breakpoint_here (CORE_ADDR addr);
 | 
			
		||||
 | 
			
		||||
int breakpoint_inserted_here (CORE_ADDR addr);
 | 
			
		||||
 | 
			
		||||
/* Returns TRUE if there's a GDB breakpoint set at ADDR.  */
 | 
			
		||||
 | 
			
		||||
int gdb_breakpoint_here (CORE_ADDR where);
 | 
			
		||||
 | 
			
		||||
/* Create a new breakpoint at WHERE, and call HANDLER when
 | 
			
		||||
   it is hit.  HANDLER should return 1 if the breakpoint
 | 
			
		||||
   should be deleted, 0 otherwise.  */
 | 
			
		||||
@ -45,10 +50,10 @@ int breakpoint_inserted_here (CORE_ADDR addr);
 | 
			
		||||
struct breakpoint *set_breakpoint_at (CORE_ADDR where,
 | 
			
		||||
				      int (*handler) (CORE_ADDR));
 | 
			
		||||
 | 
			
		||||
/* Delete a breakpoint previously inserted at ADDR with
 | 
			
		||||
   set_breakpoint_at.  */
 | 
			
		||||
/* Delete a GDB breakpoint previously inserted at ADDR with
 | 
			
		||||
   set_gdb_breakpoint_at.  */
 | 
			
		||||
 | 
			
		||||
void delete_breakpoint_at (CORE_ADDR addr);
 | 
			
		||||
int delete_gdb_breakpoint_at (CORE_ADDR addr);
 | 
			
		||||
 | 
			
		||||
/* Set a reinsert breakpoint at STOP_AT.  */
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -191,6 +191,7 @@ struct dll_info
 | 
			
		||||
 | 
			
		||||
struct sym_cache;
 | 
			
		||||
struct breakpoint;
 | 
			
		||||
struct raw_breakpoint;
 | 
			
		||||
struct process_info_private;
 | 
			
		||||
 | 
			
		||||
struct process_info
 | 
			
		||||
@ -209,6 +210,9 @@ struct process_info
 | 
			
		||||
  /* The list of memory breakpoints.  */
 | 
			
		||||
  struct breakpoint *breakpoints;
 | 
			
		||||
 | 
			
		||||
  /* The list of raw memory breakpoints.  */
 | 
			
		||||
  struct raw_breakpoint *raw_breakpoints;
 | 
			
		||||
 | 
			
		||||
  /* Private target data.  */
 | 
			
		||||
  struct process_info_private *private;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
		Reference in New Issue
	
	Block a user