This is the mail archive of the gdb-patches@sourceware.cygnus.com mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

RFA: permanent breakpoints



Request for approval.  This contains changes mostly to breakpoint.c,
but also has a small change to the GDBTk files, and pa64solib.c.

Here are the internal changes necessary to support "permanent"
breakpoints: breakpoints that are hardwired into the inferior's code
by the programmer.  GDB just knows they're there, but doesn't try to
insert or remove them.

GDB needs this to communicate properly with the dynamic linker on
HP/UX on PA 2.0 in wide (64-bit) mode.

There is no user interface for this, which is lame, but the HP
contract doesn't need it, and I'm low on time.  If folks think it's
interesting, I could add one later, write docs and a NEWS entry, etc.


1999-09-11  Jim Blandy  <jimb@cris.red-bean.com>

	* breakpoint.c (breakpoint_here_p): Remove meaningless code,
	testing b->enable against shlib_disabled and call_disabled after
	we know it is enabled.

	Implement "permanent breakpoints" --- breakpoints that are
	hardwired into the inferior's code.  GDB knows they're there, but
	doesn't try to insert or remove them, etc.
	* breakpoint.h (enum enable): Add `permanent' enablement state.
	* breakpoint.c (breakpoint_is_permanent): New function.
	* breakpoint.h (breakpoint_is_permanent): Add declaration.
	* breakpoint.c (insert_breakpoints): Don't bother to insert
	permanent breakpoints...
	(remove_breakpoint): ... or remove them.
	(breakpoint_here_p): Handle `permanent' like `enabled'.
	(breakpoint_1): Extend bpenables to cover all the enablement states.
	(describe_other_breakpoints): Describe permanent breakpoints.
	(check_duplicates): If one of the breakpoints at ADDRESS is a
	permanent breakpoint, treat all the others as the duplicates, so
	we don't try to insert or remove any of them.  Verify that only
	the permanent breakpoint is actually inserted.
	(delete_breakpoint): Complain if we discover that another
	breakpoint was inserted at the same place as a permanent
	breakpoint.
	(disable_breakpoint): Fail silently if asked to disable a
	permanent breakpoint.
	(do_enable_breakpoint): Don't change a permanent breakpoint's
	enablement to ordinary `enabled'.  Leave it alone.
	* breakpoint.c (create_solib_event_breakpoint): Return the
	breakpoint object created.
	* breakpoint.h (create_solib_event_breakpoint): Fix declaration.
	* pa64solib.c (pa64_solib_create_inferior_hook): Make the dynamic
	linker's breakpoint in __dld_break a permanent breakpoint.
	* gdbtk-cmds.c (gdb_get_breakpoint_info): Report a permanent
	breakpoint as enabled.

Index: breakpoint.c
===================================================================
RCS file: /cvs/cvsfiles/devo/gdb/breakpoint.c,v
retrieving revision 1.241
diff -c -r1.241 breakpoint.c
*** breakpoint.c	1999/09/01 20:13:42	1.241
--- breakpoint.c	1999/09/12 05:06:44
***************
*** 676,682 ****
  
    ALL_BREAKPOINTS_SAFE (b, temp)
    {
!     if (b->type != bp_watchpoint
  	&& b->type != bp_hardware_watchpoint
  	&& b->type != bp_read_watchpoint
  	&& b->type != bp_access_watchpoint
--- 676,685 ----
  
    ALL_BREAKPOINTS_SAFE (b, temp)
    {
!     if (b->enable == permanent)
!       /* No need to do anything for a permanent breakpoint.  */
!       ;
!     else if (b->type != bp_watchpoint
  	&& b->type != bp_hardware_watchpoint
  	&& b->type != bp_read_watchpoint
  	&& b->type != bp_access_watchpoint
***************
*** 1136,1141 ****
--- 1139,1148 ----
  {
    int val;
  
+   if (b->enable == permanent)
+     /* We shouldn't touch permament breakpoints.  */
+     return;
+ 
    if (b->type == bp_none)
      warning ("attempted to remove apparently deleted breakpoint #%d?", 
  	     b->number);
***************
*** 1149,1155 ****
        && b->type != bp_catch_exec
        && b->type != bp_catch_catch
        && b->type != bp_catch_throw)
- 
      {
        if (b->type == bp_hardware_breakpoint)
  	val = target_remove_hw_breakpoint (b->address, b->shadow_contents);
--- 1156,1161 ----
***************
*** 1373,1381 ****
    register struct breakpoint *b;
  
    ALL_BREAKPOINTS (b)
!     if (b->enable == enabled
! 	&& b->enable != shlib_disabled
! 	&& b->enable != call_disabled
  	&& b->address == pc)	/* bp is enabled and matches pc */
      {
        if (overlay_debugging &&
--- 1379,1386 ----
    register struct breakpoint *b;
  
    ALL_BREAKPOINTS (b)
!     if ((b->enable == enabled
! 	 || b->enable == permanent)
  	&& b->address == pc)	/* bp is enabled and matches pc */
      {
        if (overlay_debugging &&
***************
*** 2863,2869 ****
  
    static char *bpdisps[] =
    {"del", "dstp", "dis", "keep"};
!   static char bpenables[] = "nyn";
    char wrap_indent[80];
    /* start-sanitize-flathead */
  #ifdef UI_OUT
--- 2868,2874 ----
  
    static char *bpdisps[] =
    {"del", "dstp", "dis", "keep"};
!   static char bpenables[] = "nynny";
    char wrap_indent[80];
    /* start-sanitize-flathead */
  #ifdef UI_OUT
***************
*** 3484,3491 ****
  	       b->number,
  	       ((b->enable == disabled || 
  		 b->enable == shlib_disabled || 
! 		 b->enable == call_disabled)
! 		? " (disabled)" : ""),
  	       (others > 1) ? "," : ((others == 1) ? " and" : ""));
  	  }
        printf_filtered ("also set at pc ");
--- 3489,3497 ----
  	       b->number,
  	       ((b->enable == disabled || 
  		 b->enable == shlib_disabled || 
! 		 b->enable == call_disabled) ? " (disabled)" 
! 		: b->enable == permanent ? " (permanent)"
! 		: ""),
  	       (others > 1) ? "," : ((others == 1) ? " and" : ""));
  	  }
        printf_filtered ("also set at pc ");
***************
*** 3512,3518 ****
  
  /* Rescan breakpoints at address ADDRESS,
     marking the first one as "first" and any others as "duplicates".
!    This is so that the bpt instruction is only inserted once.  */
  
  static void
  check_duplicates (address, section)
--- 3518,3526 ----
  
  /* Rescan breakpoints at address ADDRESS,
     marking the first one as "first" and any others as "duplicates".
!    This is so that the bpt instruction is only inserted once.
!    If we have a permanent breakpoint at ADDRESS, make that one
!    the official one, and the rest as duplicates.  */
  
  static void
  check_duplicates (address, section)
***************
*** 3521,3526 ****
--- 3529,3535 ----
  {
    register struct breakpoint *b;
    register int count = 0;
+   struct breakpoint *perm_bp = 0;
  
    if (address == 0)		/* Watchpoints are uninteresting */
      return;
***************
*** 3532,3540 ****
--- 3541,3584 ----
  	&& b->address == address
  	&& (overlay_debugging == 0 || b->section == section))
      {
+       /* Have we found a permanent breakpoint?  */
+       if (b->enable == permanent)
+ 	{
+ 	  perm_bp = b;
+ 	  break;
+ 	}
+ 	
        count++;
        b->duplicate = count > 1;
      }
+ 
+   /* If we found a permanent breakpoint at this address, go over the
+      list again and declare all the other breakpoints there to be the
+      duplicates.  */
+   if (perm_bp)
+     {
+       perm_bp->duplicate = 0;
+ 
+       /* Permanent breakpoint should always be inserted.  */
+       if (! perm_bp->inserted)
+ 	internal_error ("allegedly permanent breakpoint is not "
+ 			"actually inserted");
+ 
+       ALL_BREAKPOINTS (b)
+ 	if (b != perm_bp)
+ 	  {
+ 	    if (b->inserted)
+ 	      internal_error ("another breakpoint was inserted on top of "
+ 			      "a permanent breakpoint");
+ 
+ 	    if (b->enable != disabled
+ 		&& b->enable != shlib_disabled
+ 		&& b->enable != call_disabled
+ 		&& b->address == address
+ 		&& (overlay_debugging == 0 || b->section == section))
+ 	      b->duplicate = 1;
+ 	  }
+     }
  }
  
  /* Low level routine to set a breakpoint.
***************
*** 3597,3602 ****
--- 3641,3657 ----
    return b;
  }
  
+ 
+ /* Note that b is actually a permanent breakpoint.  */
+ void
+ breakpoint_is_permanent (struct breakpoint *b)
+ {
+   b->enable = permanent;
+ 
+   /* By definition, permanent breakpoints are already present in the code.  */
+   b->inserted = 1;
+ }
+ 
  #ifdef GET_LONGJMP_TARGET
  
  static void
***************
*** 3676,3682 ****
      delete_breakpoint (b);
  }
  
! void
  create_solib_event_breakpoint (address)
       CORE_ADDR address;
  {
--- 3731,3737 ----
      delete_breakpoint (b);
  }
  
! struct breakpoint *
  create_solib_event_breakpoint (address)
       CORE_ADDR address;
  {
***************
*** 3690,3695 ****
--- 3745,3752 ----
    b->number = internal_breakpoint_number--;
    b->disposition = donttouch;
    b->type = bp_shlib_event;
+ 
+   return b;
  }
  
  /* Disable any breakpoints that are on code in shared libraries.  Only
***************
*** 6325,6330 ****
--- 6382,6395 ----
  	{
  	  int val;
  
+ 	  /* We should never reach this point if there is a permanent
+ 	     breakpoint at the same address as the one being deleted.
+ 	     If there is a permanent breakpoint somewhere, it should
+ 	     always be the only one inserted.  */
+ 	  if (b->enable == permanent)
+ 	    internal_error ("another breakpoint was inserted on top of "
+ 			    "a permanent breakpoint");
+ 
  	  if (b->type == bp_hardware_breakpoint)
  	    val = target_insert_hw_breakpoint (b->address, b->shadow_contents);
  	  else
***************
*** 6773,6778 ****
--- 6838,6847 ----
    if (bpt->type == bp_watchpoint_scope)
      return;
  
+   /* You can't disable permanent breakpoints.  */
+   if (bpt->enable == permanent)
+     return;
+ 
    bpt->enable = disabled;
  
    check_duplicates (bpt->address, bpt->section);
***************
*** 6841,6847 ****
  	error ("Hardware breakpoints used exceeds limit.");
      }
  
!   bpt->enable = enabled;
    bpt->disposition = disposition;
    check_duplicates (bpt->address, bpt->section);
    breakpoints_changed ();
--- 6910,6917 ----
  	error ("Hardware breakpoints used exceeds limit.");
      }
  
!   if (bpt->enable != permanent)
!     bpt->enable = enabled;
    bpt->disposition = disposition;
    check_duplicates (bpt->address, bpt->section);
    breakpoints_changed ();
Index: breakpoint.h
===================================================================
RCS file: /cvs/cvsfiles/devo/gdb/breakpoint.h,v
retrieving revision 1.52
diff -c -r1.52 breakpoint.h
*** breakpoint.h	1999/08/29 00:06:42	1.52
--- breakpoint.h	1999/09/12 05:06:45
***************
*** 129,141 ****
      shlib_disabled,	/* The eventpoint's address is in an unloaded solib.
  			   The eventpoint will be automatically enabled 
  			   and reset when that solib is loaded. */
!     call_disabled	/* The eventpoint has been disabled while a call 
  			   into the inferior is "in flight", because some 
  			   eventpoints interfere with the implementation of 
  			   a call on some targets.  The eventpoint will be 
  			   automatically enabled and reset when the call 
  			   "lands" (either completes, or stops at another 
  			   eventpoint). */
    };
  
  
--- 129,146 ----
      shlib_disabled,	/* The eventpoint's address is in an unloaded solib.
  			   The eventpoint will be automatically enabled 
  			   and reset when that solib is loaded. */
!     call_disabled,	/* The eventpoint has been disabled while a call 
  			   into the inferior is "in flight", because some 
  			   eventpoints interfere with the implementation of 
  			   a call on some targets.  The eventpoint will be 
  			   automatically enabled and reset when the call 
  			   "lands" (either completes, or stops at another 
  			   eventpoint). */
+     permanent		/* There is a breakpoint instruction hard-wired into
+ 			   the target's code.  Don't try to write another
+ 			   breakpoint instruction on top of it, or restore
+ 			   its value.  Step over it using the architecture's
+ 			   SKIP_INSN macro.  */
    };
  
  
***************
*** 594,600 ****
  
  extern void enable_breakpoint PARAMS ((struct breakpoint *));
  
! extern void create_solib_event_breakpoint PARAMS ((CORE_ADDR));
  
  extern void remove_solib_event_breakpoints PARAMS ((void));
  
--- 599,607 ----
  
  extern void enable_breakpoint PARAMS ((struct breakpoint *));
  
! extern void breakpoint_is_permanent PARAMS ((struct breakpoint *));
! 
! extern struct breakpoint *create_solib_event_breakpoint PARAMS ((CORE_ADDR));
  
  extern void remove_solib_event_breakpoints PARAMS ((void));
  
Index: pa64solib.c
===================================================================
RCS file: /cvs/cvsfiles/devo/gdb/pa64solib.c,v
retrieving revision 2.3
diff -c -r2.3 pa64solib.c
*** pa64solib.c	1999/08/23 16:19:35	2.3
--- pa64solib.c	1999/09/12 05:06:46
***************
*** 621,627 ****
        sym_addr = load_addr + sym_addr + 4;
        
        /* Create the shared library breakpoint.  */
!       create_solib_event_breakpoint (sym_addr);
  
        /* We're done with the temporary bfd.  */
        bfd_close (tmp_bfd);
--- 621,637 ----
        sym_addr = load_addr + sym_addr + 4;
        
        /* Create the shared library breakpoint.  */
!       {
! 	struct breakpoint *b
! 	  = create_solib_event_breakpoint (sym_addr);
! 
! 	/* The breakpoint is actually hard-coded into the dynamic linker,
! 	   so we don't need to actually insert a breakpoint instruction
! 	   there.  In fact, the dynamic linker's code is immutable, even to
! 	   ttrace, so we shouldn't even try to do that.  For cases like
! 	   this, we have "permanent" breakpoints.  */
! 	breakpoint_is_permanent (b);
!       }
  
        /* We're done with the temporary bfd.  */
        bfd_close (tmp_bfd);
Index: gdbtk-cmds.c
===================================================================
RCS file: /cvs/cvsfiles/devo/gdb/gdbtk-cmds.c,v
retrieving revision 2.57
diff -c -r2.57 gdbtk-cmds.c
*** gdbtk-cmds.c	1999/09/03 10:15:31	2.57
--- gdbtk-cmds.c	1999/09/12 05:06:51
***************
*** 3968,3974 ****
    Tcl_ListObjAppendElement (NULL, result_ptr->obj_ptr,
  			    Tcl_NewStringObj (bptypes[b->type], -1));
    Tcl_ListObjAppendElement (NULL, result_ptr->obj_ptr,
! 			    Tcl_NewBooleanObj (b->enable == enabled));
    Tcl_ListObjAppendElement (NULL, result_ptr->obj_ptr,
  			    Tcl_NewStringObj (bpdisp[b->disposition], -1));
    Tcl_ListObjAppendElement (NULL, result_ptr->obj_ptr,
--- 3968,3975 ----
    Tcl_ListObjAppendElement (NULL, result_ptr->obj_ptr,
  			    Tcl_NewStringObj (bptypes[b->type], -1));
    Tcl_ListObjAppendElement (NULL, result_ptr->obj_ptr,
! 			    Tcl_NewBooleanObj (b->enable == enabled
! 					       || b->enable == permanent));
    Tcl_ListObjAppendElement (NULL, result_ptr->obj_ptr,
  			    Tcl_NewStringObj (bpdisp[b->disposition], -1));
    Tcl_ListObjAppendElement (NULL, result_ptr->obj_ptr,

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]