Mirror of the gdb-patches mailing list
 help / color / mirror / Atom feed
* RFC: Centralize DECR_PC_AFTER_BREAK handling from infrun
@ 2004-01-17 22:20 Daniel Jacobowitz
  2004-01-17 22:39 ` Andrew Cagney
                   ` (3 more replies)
  0 siblings, 4 replies; 13+ messages in thread
From: Daniel Jacobowitz @ 2004-01-17 22:20 UTC (permalink / raw)
  To: gdb-patches

The first, possibly most important step in cleaning up DECR_PC_AFTER_BREAK's
tentacles.  This changes handle_inferior_event to fix the PC immediately,
before doing anything else with it.  It removes the later decrements, but
doesn't remove all the later workarounds for possibly undecremented PC
values - that can come separately.

One case, HANDLE_NONSTEPPABLE_WATCHPOINTS and DECR_PC_AFTER_BREAK, is simply
removed.  There are no targets using this combination, and if one is added,
it's non-obvious whether a nonsteppable watchpoint really should be affected
by DECR_PC_AFTER_BREAK.

A future cleanup will change bpstat_stop_status to only take a CORE_ADDR
argument.  Also, I believe that both the tests for sigtramps and the use of
deprecated_frame_update_pc_hack can go now, but I don't want to mix that in
with this - esp. since I'm not sure how to test the former belief.

Tested i386-linux, which uses DECR_PC_AFTER_BREAK.  I'm not going to check
this in just yet; all comments and testing welcome.

-- 
Daniel Jacobowitz
MontaVista Software                         Debian GNU/Linux Developer

2004-01-17  Daniel Jacobowitz  <drow@mvista.com>

	* breakpoint.c (software_breakpoint_inserted_here_p): New function.
	(bpstat_stop_status): Don't decrement PC.
	* breakpoint.h (software_breakpoint_inserted_here_p): Add
	prototype.
	* infrun.c (adjust_pc_after_break): New function.
	(handle_inferior_event): Call it, early.  Remove later references
	to DECR_PC_AFTER_BREAK.
	(normal_stop): Add commentary.

Index: breakpoint.c
===================================================================
RCS file: /cvs/src/src/gdb/breakpoint.c,v
retrieving revision 1.149
diff -u -p -r1.149 breakpoint.c
--- breakpoint.c	17 Jan 2004 21:56:12 -0000	1.149
+++ breakpoint.c	17 Jan 2004 22:05:39 -0000
@@ -1721,6 +1721,37 @@ breakpoint_inserted_here_p (CORE_ADDR pc
   return 0;
 }
 
+/* This function returns non-zero iff there is a software breakpoint
+   inserted at PC.  */
+
+int
+software_breakpoint_inserted_here_p (CORE_ADDR pc)
+{
+  struct bp_location *bpt;
+  int any_breakpoint_here = 0;
+
+  ALL_BP_LOCATIONS (bpt)
+    {
+      if (bpt->loc_type != bp_loc_software_breakpoint)
+	continue;
+
+      if ((breakpoint_enabled (bpt->owner)
+	   || bpt->owner->enable_state == bp_permanent)
+	  && bpt->inserted
+	  && bpt->address == pc)	/* bp is enabled and matches pc */
+	{
+	  if (overlay_debugging 
+	      && section_is_overlay (bpt->section) 
+	      && !section_is_mapped (bpt->section))
+	    continue;		/* unmapped overlay -- can't be a match */
+	  else
+	    return 1;
+	}
+    }
+
+  return 0;
+}
+
 /* Return nonzero if FRAME is a dummy frame.  We can't use
    DEPRECATED_PC_IN_CALL_DUMMY because figuring out the saved SP would
    take too much time, at least using frame_register() on the 68k.
@@ -2578,13 +2609,7 @@ bpstat_stop_status (CORE_ADDR *pc, int n
   /* Pointer to the last thing in the chain currently.  */
   bpstat bs = root_bs;
 
-  /* Get the address where the breakpoint would have been.  The
-     "not_a_sw_breakpoint" argument is meant to distinguish between a
-     breakpoint trap event and a trace/singlestep trap event.  For a
-     trace/singlestep trap event, we would not want to subtract
-     DECR_PC_AFTER_BREAK from the PC. */
-
-  bp_addr = *pc - (not_a_sw_breakpoint ? 0 : DECR_PC_AFTER_BREAK);
+  bp_addr = *pc;
 
   ALL_BREAKPOINTS_SAFE (b, temp)
   {
@@ -2869,18 +2894,6 @@ bpstat_stop_status (CORE_ADDR *pc, int n
 
   bs->next = NULL;		/* Terminate the chain */
   bs = root_bs->next;		/* Re-grab the head of the chain */
-
-  if (real_breakpoint && bs)
-    {
-      if (bs->breakpoint_at->type != bp_hardware_breakpoint)
-	{
-	  if (DECR_PC_AFTER_BREAK != 0)
-	    {
-	      *pc = bp_addr;
-	      write_pc (bp_addr);
-	    }
-	}
-    }
 
   /* The value of a hardware watchpoint hasn't changed, but the
      intermediate memory locations we are watching may have.  */
Index: breakpoint.h
===================================================================
RCS file: /cvs/src/src/gdb/breakpoint.h,v
retrieving revision 1.26
diff -u -p -r1.26 breakpoint.h
--- breakpoint.h	6 Nov 2003 18:24:55 -0000	1.26
+++ breakpoint.h	17 Jan 2004 22:05:39 -0000
@@ -605,6 +605,8 @@ extern enum breakpoint_here breakpoint_h
 
 extern int breakpoint_inserted_here_p (CORE_ADDR);
 
+extern int software_breakpoint_inserted_here_p (CORE_ADDR);
+
 /* FIXME: cagney/2002-11-10: The current [generic] dummy-frame code
    implements a functional superset of this function.  The only reason
    it hasn't been removed is because some architectures still don't
Index: infrun.c
===================================================================
RCS file: /cvs/src/src/gdb/infrun.c,v
retrieving revision 1.128
diff -u -p -r1.128 infrun.c
--- infrun.c	17 Jan 2004 21:56:12 -0000	1.128
+++ infrun.c	17 Jan 2004 22:05:39 -0000
@@ -1316,6 +1316,59 @@ handle_step_into_function (struct execut
   return;
 }
 
+static void
+adjust_pc_after_break (struct execution_control_state *ecs)
+{
+  CORE_ADDR stop_pc;
+
+  /* If this target does not decrement the PC after breakpoints, then
+     we have nothing to do.  */
+  if (DECR_PC_AFTER_BREAK == 0)
+    return;
+
+  /* If we've hit a breakpoint, we'll be stopped with SIGTRAP.  */
+  if (ecs->ws.kind != TARGET_WAITKIND_STOPPED)
+    return;
+
+  if (ecs->ws.value.sig != TARGET_SIGNAL_TRAP)
+    return;
+
+  /* Find the location where (if we've hit a breakpoint) the breakpoint would
+     be.  */
+  stop_pc = read_pc_pid (ecs->ptid) - DECR_PC_AFTER_BREAK;
+
+  /* If we're software-single-stepping, then assume this is a breakpoint.
+     NOTE drow/2004-01-17: This doesn't check that the PC matches, or that
+     we're even in the right thread.  The software-single-step code needs
+     some modernization.
+
+     If we're not software-single-stepping, then we first check that there
+     is an enabled software breakpoint at this address.  If there is, and
+     we weren't using hardware-single-step, then we've hit the breakpoint.
+
+     If we were using hardware-single-step, we check prev_pc; if we just
+     stepped over an inserted software breakpoint, then we should decrement
+     the PC and eventually report hitting the breakpoint.  The prev_pc check
+     prevents us from decrementing the PC if we just stepped over a jump
+     instruction and landed on the instruction after a breakpoint.
+
+     The last bit checks that we didn't hit a breakpoint in a signal handler
+     without an intervening stop in sigtramp, which is detected by a new
+     stack pointer value below any usual function calling stack adjustments.
+
+     NOTE drow/2004-01-17: I'm not sure that this is necessary.  The check
+     predates checking for software single step at the same time.  Also,
+     if we've moved into a signal handler we should have seen the
+     signal.  */
+
+  if ((SOFTWARE_SINGLE_STEP_P () && singlestep_breakpoints_inserted_p)
+      || (software_breakpoint_inserted_here_p (stop_pc)
+	  && !(currently_stepping (ecs)
+	       && prev_pc != stop_pc
+	       && !(step_range_end && INNER_THAN (read_sp (), (step_sp - 16))))))
+    write_pc_pid (stop_pc, ecs->ptid);
+}
+
 /* Given an execution control state that has been freshly filled in
    by an event from the inferior, figure out what it means and take
    appropriate action.  */
@@ -1335,6 +1388,8 @@ handle_inferior_event (struct execution_
   target_last_wait_ptid = ecs->ptid;
   target_last_waitstatus = *ecs->wp;
 
+  adjust_pc_after_break (ecs);
+
   switch (ecs->infwait_state)
     {
     case infwait_thread_hop_state:
@@ -1688,19 +1743,15 @@ handle_inferior_event (struct execution_
       /* Check if a regular breakpoint has been hit before checking
          for a potential single step breakpoint. Otherwise, GDB will
          not see this breakpoint hit when stepping onto breakpoints.  */
-      if (breakpoints_inserted
-          && breakpoint_here_p (stop_pc - DECR_PC_AFTER_BREAK))
+      if (breakpoints_inserted && breakpoint_here_p (stop_pc))
 	{
 	  ecs->random_signal = 0;
-	  if (!breakpoint_thread_match (stop_pc - DECR_PC_AFTER_BREAK,
-					ecs->ptid))
+	  if (!breakpoint_thread_match (stop_pc, ecs->ptid))
 	    {
 	      int remove_status;
 
 	      /* Saw a breakpoint, but it was hit by the wrong thread.
 	         Just continue. */
-	      if (DECR_PC_AFTER_BREAK)
-		write_pc_pid (stop_pc - DECR_PC_AFTER_BREAK, ecs->ptid);
 
 	      remove_status = remove_breakpoints ();
 	      /* Did we fail to remove breakpoints?  If so, try
@@ -1713,7 +1764,7 @@ handle_inferior_event (struct execution_
 	      if (remove_status != 0)
 		{
 		  /* FIXME!  This is obviously non-portable! */
-		  write_pc_pid (stop_pc - DECR_PC_AFTER_BREAK + 4, ecs->ptid);
+		  write_pc_pid (stop_pc + 4, ecs->ptid);
 		  /* We need to restart all the threads now,
 		   * unles we're running in scheduler-locked mode. 
 		   * Use currently_stepping to determine whether to 
@@ -1747,17 +1798,6 @@ handle_inferior_event (struct execution_
 	}
       else if (SOFTWARE_SINGLE_STEP_P () && singlestep_breakpoints_inserted_p)
         {
-          /* Readjust the stop_pc as it is off by DECR_PC_AFTER_BREAK
-             compared to the value it would have if the system stepping
-             capability was used. This allows the rest of the code in
-             this function to use this address without having to worry
-             whether software single step is in use or not.  */
-          if (DECR_PC_AFTER_BREAK)
-            {
-              stop_pc -= DECR_PC_AFTER_BREAK;
-              write_pc_pid (stop_pc, ecs->ptid);
-            }
-
           sw_single_step_trap_p = 1;
           ecs->random_signal = 0;
         }
@@ -1889,9 +1929,6 @@ handle_inferior_event (struct execution_
          includes evaluating watchpoints, things will come to a
          stop in the correct manner.  */
 
-      if (DECR_PC_AFTER_BREAK)
-	write_pc (stop_pc - DECR_PC_AFTER_BREAK);
-
       remove_breakpoints ();
       registers_changed ();
       target_resume (ecs->ptid, 1, TARGET_SIGNAL_0);	/* Single step */
@@ -3101,6 +3138,7 @@ normal_stop (void)
       previous_inferior_ptid = inferior_ptid;
     }
 
+  /* NOTE drow/2004-01-17: Is this still necessary?  */
   /* Make sure that the current_frame's pc is correct.  This
      is a correction for setting up the frame info before doing
      DECR_PC_AFTER_BREAK */


^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: RFC: Centralize DECR_PC_AFTER_BREAK handling from infrun
  2004-01-17 22:20 RFC: Centralize DECR_PC_AFTER_BREAK handling from infrun Daniel Jacobowitz
@ 2004-01-17 22:39 ` Andrew Cagney
  2004-01-17 23:04   ` Daniel Jacobowitz
  2004-01-18  7:05 ` Eli Zaretskii
                   ` (2 subsequent siblings)
  3 siblings, 1 reply; 13+ messages in thread
From: Andrew Cagney @ 2004-01-17 22:39 UTC (permalink / raw)
  To: Daniel Jacobowitz; +Cc: gdb-patches

> The first, possibly most important step in cleaning up DECR_PC_AFTER_BREAK's
> tentacles.  This changes handle_inferior_event to fix the PC immediately,
> before doing anything else with it.  It removes the later decrements, but
> doesn't remove all the later workarounds for possibly undecremented PC
> values - that can come separately.
> 
> One case, HANDLE_NONSTEPPABLE_WATCHPOINTS and DECR_PC_AFTER_BREAK, is simply
> removed.  There are no targets using this combination, and if one is added,
> it's non-obvious whether a nonsteppable watchpoint really should be affected
> by DECR_PC_AFTER_BREAK.
> 
> A future cleanup will change bpstat_stop_status to only take a CORE_ADDR
> argument.  Also, I believe that both the tests for sigtramps and the use of
> deprecated_frame_update_pc_hack can go now, but I don't want to mix that in
> with this - esp. since I'm not sure how to test the former belief.

Build gdb with gcov and then run the testsuite, it will quickly point 
you at the "dead" code paths and hence how well it was really tested.

Otherwize, yow!

Andrew



^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: RFC: Centralize DECR_PC_AFTER_BREAK handling from infrun
  2004-01-17 22:39 ` Andrew Cagney
@ 2004-01-17 23:04   ` Daniel Jacobowitz
  0 siblings, 0 replies; 13+ messages in thread
From: Daniel Jacobowitz @ 2004-01-17 23:04 UTC (permalink / raw)
  To: gdb-patches

On Sat, Jan 17, 2004 at 05:38:41PM -0500, Andrew Cagney wrote:
> >The first, possibly most important step in cleaning up 
> >DECR_PC_AFTER_BREAK's
> >tentacles.  This changes handle_inferior_event to fix the PC immediately,
> >before doing anything else with it.  It removes the later decrements, but
> >doesn't remove all the later workarounds for possibly undecremented PC
> >values - that can come separately.
> >
> >One case, HANDLE_NONSTEPPABLE_WATCHPOINTS and DECR_PC_AFTER_BREAK, is 
> >simply
> >removed.  There are no targets using this combination, and if one is added,
> >it's non-obvious whether a nonsteppable watchpoint really should be 
> >affected
> >by DECR_PC_AFTER_BREAK.
> >
> >A future cleanup will change bpstat_stop_status to only take a CORE_ADDR
> >argument.  Also, I believe that both the tests for sigtramps and the use of
> >deprecated_frame_update_pc_hack can go now, but I don't want to mix that in
> >with this - esp. since I'm not sure how to test the former belief.
> 
> Build gdb with gcov and then run the testsuite, it will quickly point 
> you at the "dead" code paths and hence how well it was really tested.

Except, my hunch is it's related to some particular system's broken
PTRACE_SINGLESTEP :(  Well, if it doesn't show up on the systems I have
available I think I'll remove it anyway (after 6.1) - then if we need
to add it back we'll pick up a comment saying why it was necessary.

-- 
Daniel Jacobowitz
MontaVista Software                         Debian GNU/Linux Developer


^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: RFC: Centralize DECR_PC_AFTER_BREAK handling from infrun
  2004-01-17 22:20 RFC: Centralize DECR_PC_AFTER_BREAK handling from infrun Daniel Jacobowitz
  2004-01-17 22:39 ` Andrew Cagney
@ 2004-01-18  7:05 ` Eli Zaretskii
  2004-01-18 15:19   ` Daniel Jacobowitz
  2004-01-22 14:09 ` Andrew Cagney
  2004-01-31 19:19 ` Daniel Jacobowitz
  3 siblings, 1 reply; 13+ messages in thread
From: Eli Zaretskii @ 2004-01-18  7:05 UTC (permalink / raw)
  To: Daniel Jacobowitz; +Cc: gdb-patches

> Date: Sat, 17 Jan 2004 17:20:07 -0500
> From: Daniel Jacobowitz <drow@mvista.com>
> 
> One case, HANDLE_NONSTEPPABLE_WATCHPOINTS and DECR_PC_AFTER_BREAK, is simply
> removed.  There are no targets using this combination, and if one is added,
> it's non-obvious whether a nonsteppable watchpoint really should be affected
> by DECR_PC_AFTER_BREAK.

Right, but since we don't really know what that feature was about, I'd
suggest to leave a comment in adjust_pc_after_break that mentions
HANDLE_NONSTEPPABLE_WATCHPOINTS and that its support, if needed,
should be added.

> 	* breakpoint.c (software_breakpoint_inserted_here_p): New function.
> 	(bpstat_stop_status): Don't decrement PC.
> 	* breakpoint.h (software_breakpoint_inserted_here_p): Add
> 	prototype.
> 	* infrun.c (adjust_pc_after_break): New function.
> 	(handle_inferior_event): Call it, early.  Remove later references
> 	to DECR_PC_AFTER_BREAK.
> 	(normal_stop): Add commentary.

What happens if a location has both software and hardware
breakpoints?  Does the code still DTRT?

> +  /* If we've hit a breakpoint, we'll be stopped with SIGTRAP.  */
> +  if (ecs->ws.kind != TARGET_WAITKIND_STOPPED)
> +    return;
> +
> +  if (ecs->ws.value.sig != TARGET_SIGNAL_TRAP)
> +    return;

The original code didn't check these conditions, right?  So why add
them here?  (Also, the comment doesn't seem to describe the two
tests, only the second one.)


^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: RFC: Centralize DECR_PC_AFTER_BREAK handling from infrun
  2004-01-18  7:05 ` Eli Zaretskii
@ 2004-01-18 15:19   ` Daniel Jacobowitz
  2004-01-18 17:27     ` Eli Zaretskii
  2004-01-31 17:49     ` Daniel Jacobowitz
  0 siblings, 2 replies; 13+ messages in thread
From: Daniel Jacobowitz @ 2004-01-18 15:19 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: gdb-patches

On Sun, Jan 18, 2004 at 09:07:23AM +0200, Eli Zaretskii wrote:
> > Date: Sat, 17 Jan 2004 17:20:07 -0500
> > From: Daniel Jacobowitz <drow@mvista.com>
> > 
> > One case, HANDLE_NONSTEPPABLE_WATCHPOINTS and DECR_PC_AFTER_BREAK, is simply
> > removed.  There are no targets using this combination, and if one is added,
> > it's non-obvious whether a nonsteppable watchpoint really should be affected
> > by DECR_PC_AFTER_BREAK.
> 
> Right, but since we don't really know what that feature was about, I'd
> suggest to leave a comment in adjust_pc_after_break that mentions
> HANDLE_NONSTEPPABLE_WATCHPOINTS and that its support, if needed,
> should be added.

Well, we know what HANDLE_NONSTEPPABLE_WATCHPOINTS was about.  I'd be
curious to see whether any target ever used these two together, or if
the decrement was just added for consistency.  I'll add a comment.

> > 	* breakpoint.c (software_breakpoint_inserted_here_p): New function.
> > 	(bpstat_stop_status): Don't decrement PC.
> > 	* breakpoint.h (software_breakpoint_inserted_here_p): Add
> > 	prototype.
> > 	* infrun.c (adjust_pc_after_break): New function.
> > 	(handle_inferior_event): Call it, early.  Remove later references
> > 	to DECR_PC_AFTER_BREAK.
> > 	(normal_stop): Add commentary.
> 
> What happens if a location has both software and hardware
> breakpoints?  Does the code still DTRT?

Hmm, I am not sure.  What _is_ the right thing?  Decrement if the
software breakpoint was inserted, and do nothing if the hardware
breakpoint was inserted, and assume that both will not be inserted?

> > +  /* If we've hit a breakpoint, we'll be stopped with SIGTRAP.  */
> > +  if (ecs->ws.kind != TARGET_WAITKIND_STOPPED)
> > +    return;
> > +
> > +  if (ecs->ws.value.sig != TARGET_SIGNAL_TRAP)
> > +    return;
> 
> The original code didn't check these conditions, right?  So why add
> them here?  (Also, the comment doesn't seem to describe the two
> tests, only the second one.)

The comment does describe both tests; if != TARGET_WAITKIND_STOPPED,
then we aren't stopped by a signal.  The other waitkinds correspond to
things like exiting and catchpoints, and with the exception of some
complications in the FORKED/EXECD cases, stop_signal will not get set
to SIGTRAP.  Also, the original code did check these conditions, though
somewhat indirectly:

  if (stop_signal == TARGET_SIGNAL_TRAP)
    {
      /* Check if a regular breakpoint has been hit before checking
         for a potential single step breakpoint. Otherwise, GDB will
         not see this breakpoint hit when stepping onto breakpoints.  */

Oh, hum, that's for the first set (thread hit thread-specific BP for a
different thread).  The second thread does this:

  if (stop_signal == TARGET_SIGNAL_TRAP
      || (breakpoints_inserted &&
          (stop_signal == TARGET_SIGNAL_ILL
           || stop_signal == TARGET_SIGNAL_EMT))
      || stop_soon == STOP_QUIETLY
      || stop_soon == STOP_QUIETLY_NO_SIGSTOP)

The stop_soon's aren't relevant here, since they're handled before
DECR_PC_AFTER_BREAK, but the ILL/EMT are relevant.  They should be
added to adjust_pc_after_break - thanks!


-- 
Daniel Jacobowitz
MontaVista Software                         Debian GNU/Linux Developer


^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: RFC: Centralize DECR_PC_AFTER_BREAK handling from infrun
  2004-01-18 15:19   ` Daniel Jacobowitz
@ 2004-01-18 17:27     ` Eli Zaretskii
  2004-01-18 18:01       ` Andrew Cagney
  2004-01-31 17:51       ` Daniel Jacobowitz
  2004-01-31 17:49     ` Daniel Jacobowitz
  1 sibling, 2 replies; 13+ messages in thread
From: Eli Zaretskii @ 2004-01-18 17:27 UTC (permalink / raw)
  To: Daniel Jacobowitz; +Cc: gdb-patches

> Date: Sun, 18 Jan 2004 10:19:10 -0500
> From: Daniel Jacobowitz <drow@mvista.com>
> > 
> > What happens if a location has both software and hardware
> > breakpoints?  Does the code still DTRT?
> 
> Hmm, I am not sure.  What _is_ the right thing?

We should at least do no worse than the current code does--which is to
act as if only the first breakpoint (in the order stored in the
breakpoint data-base) were hit.  That is, if breakpoints #n and #m
both fire, the current GDB announces the one whose number is smaller
(because it walks thru the breakpoints in their numerical order).  It
doesn't seem to matter whether the breakpoints are of the software or
the hardware-assisted variety.

It would be nice if we could announce all breakpoints that break at
that point, but this might not be possible or very hard, I dunno.


^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: RFC: Centralize DECR_PC_AFTER_BREAK handling from infrun
  2004-01-18 17:27     ` Eli Zaretskii
@ 2004-01-18 18:01       ` Andrew Cagney
  2004-01-18 19:08         ` Eli Zaretskii
  2004-01-31 17:51       ` Daniel Jacobowitz
  1 sibling, 1 reply; 13+ messages in thread
From: Andrew Cagney @ 2004-01-18 18:01 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: Daniel Jacobowitz, gdb-patches

>> Date: Sun, 18 Jan 2004 10:19:10 -0500
>> From: Daniel Jacobowitz <drow@mvista.com>
> 
>> > 
>> > What happens if a location has both software and hardware
>> > breakpoints?  Does the code still DTRT?
> 
>> 
>> Hmm, I am not sure.  What _is_ the right thing?
> 
> 
> We should at least do no worse than the current code does--which is to
> act as if only the first breakpoint (in the order stored in the
> breakpoint data-base) were hit.  That is, if breakpoints #n and #m
> both fire, the current GDB announces the one whose number is smaller
> (because it walks thru the breakpoints in their numerical order).  It
> doesn't seem to matter whether the breakpoints are of the software or
> the hardware-assisted variety.
> 
> It would be nice if we could announce all breakpoints that break at
> that point, but this might not be possible or very hard, I dunno.

I'm not that sure that the current code is right though :-(  I recall 
comlaints about the current behavior - it should report all possible 
reasons for breaking and not just the first.

Andrew



^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: RFC: Centralize DECR_PC_AFTER_BREAK handling from infrun
  2004-01-18 18:01       ` Andrew Cagney
@ 2004-01-18 19:08         ` Eli Zaretskii
  0 siblings, 0 replies; 13+ messages in thread
From: Eli Zaretskii @ 2004-01-18 19:08 UTC (permalink / raw)
  To: Andrew Cagney; +Cc: drow, gdb-patches

> Date: Sun, 18 Jan 2004 13:00:52 -0500
> From: Andrew Cagney <cagney@gnu.org>
> > 
> > It would be nice if we could announce all breakpoints that break at
> > that point, but this might not be possible or very hard, I dunno.
> 
> I'm not that sure that the current code is right though :-(

Me neither.  That's why I think we should try to do better if it's
reasonable.  But we shouldn't make things worse, at the very least.

> I recall comlaints about the current behavior - it should report all
> possible reasons for breaking and not just the first.

Sure, and the commands bound to all breakpoints should certainly be
run, which we don't currently do.  That's a bug.


^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: RFC: Centralize DECR_PC_AFTER_BREAK handling from infrun
  2004-01-17 22:20 RFC: Centralize DECR_PC_AFTER_BREAK handling from infrun Daniel Jacobowitz
  2004-01-17 22:39 ` Andrew Cagney
  2004-01-18  7:05 ` Eli Zaretskii
@ 2004-01-22 14:09 ` Andrew Cagney
  2004-01-22 22:34   ` Daniel Jacobowitz
  2004-01-31 19:19 ` Daniel Jacobowitz
  3 siblings, 1 reply; 13+ messages in thread
From: Andrew Cagney @ 2004-01-22 14:09 UTC (permalink / raw)
  To: Daniel Jacobowitz; +Cc: gdb-patches

Is it possible to determine the need for the decrement based solely on 
the knowledge of how the thread was resumed (step, run, ...)?  In the 
remote case there isn't convenient access to the list of currently 
inserted breakpoints.

Andrew


^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: RFC: Centralize DECR_PC_AFTER_BREAK handling from infrun
  2004-01-22 14:09 ` Andrew Cagney
@ 2004-01-22 22:34   ` Daniel Jacobowitz
  0 siblings, 0 replies; 13+ messages in thread
From: Daniel Jacobowitz @ 2004-01-22 22:34 UTC (permalink / raw)
  To: gdb-patches

On Thu, Jan 22, 2004 at 09:09:09AM -0500, Andrew Cagney wrote:
> Is it possible to determine the need for the decrement based solely on 
> the knowledge of how the thread was resumed (step, run, ...)?  In the 
> remote case there isn't convenient access to the list of currently 
> inserted breakpoints.

Not sure what remote case you're referring to, can you give me an
example?

I'm not sure what the consequences of removing the
software_breakpoint_inserted_here_p test would be, but it'll be easier
to find out after I've reorganized.

-- 
Daniel Jacobowitz
MontaVista Software                         Debian GNU/Linux Developer


^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: RFC: Centralize DECR_PC_AFTER_BREAK handling from infrun
  2004-01-18 15:19   ` Daniel Jacobowitz
  2004-01-18 17:27     ` Eli Zaretskii
@ 2004-01-31 17:49     ` Daniel Jacobowitz
  1 sibling, 0 replies; 13+ messages in thread
From: Daniel Jacobowitz @ 2004-01-31 17:49 UTC (permalink / raw)
  To: Eli Zaretskii, gdb-patches

On Sun, Jan 18, 2004 at 10:19:10AM -0500, Daniel Jacobowitz wrote:
> > > +  /* If we've hit a breakpoint, we'll be stopped with SIGTRAP.  */
> > > +  if (ecs->ws.kind != TARGET_WAITKIND_STOPPED)
> > > +    return;
> > > +
> > > +  if (ecs->ws.value.sig != TARGET_SIGNAL_TRAP)
> > > +    return;
> > 
> > The original code didn't check these conditions, right?  So why add
> > them here?  (Also, the comment doesn't seem to describe the two
> > tests, only the second one.)
> 
> The comment does describe both tests; if != TARGET_WAITKIND_STOPPED,
> then we aren't stopped by a signal.  The other waitkinds correspond to
> things like exiting and catchpoints, and with the exception of some
> complications in the FORKED/EXECD cases, stop_signal will not get set
> to SIGTRAP.  Also, the original code did check these conditions, though
> somewhat indirectly:
> 
>   if (stop_signal == TARGET_SIGNAL_TRAP)
>     {
>       /* Check if a regular breakpoint has been hit before checking
>          for a potential single step breakpoint. Otherwise, GDB will
>          not see this breakpoint hit when stepping onto breakpoints.  */
> 
> Oh, hum, that's for the first set (thread hit thread-specific BP for a
> different thread).  The second thread does this:
> 
>   if (stop_signal == TARGET_SIGNAL_TRAP
>       || (breakpoints_inserted &&
>           (stop_signal == TARGET_SIGNAL_ILL
>            || stop_signal == TARGET_SIGNAL_EMT))
>       || stop_soon == STOP_QUIETLY
>       || stop_soon == STOP_QUIETLY_NO_SIGSTOP)
> 
> The stop_soon's aren't relevant here, since they're handled before
> DECR_PC_AFTER_BREAK, but the ILL/EMT are relevant.  They should be
> added to adjust_pc_after_break - thanks!

Actually, I'm not sure they should.  The question is, on an operating
system such that hitting a breakpoint causes SIGILL, should
DECR_PC_AFTER_BREAK be applied?  I don't have a machine such that
breakpoints cause SIGILL, but I tested  x86 and alpha (both
DECR_PC_AFTER_BREAK targets).  On x86 a SIGILL leaves the PC pointing
at the beginning of the illegal instruction, and on Alpha a SIGILL
leaves the PC pointing to the second instruction after the illegal one.
In neither case does that match the behavior of DECR_PC_AFTER_BREAK. 

So this will become a comment also.

-- 
Daniel Jacobowitz
MontaVista Software                         Debian GNU/Linux Developer


^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: RFC: Centralize DECR_PC_AFTER_BREAK handling from infrun
  2004-01-18 17:27     ` Eli Zaretskii
  2004-01-18 18:01       ` Andrew Cagney
@ 2004-01-31 17:51       ` Daniel Jacobowitz
  1 sibling, 0 replies; 13+ messages in thread
From: Daniel Jacobowitz @ 2004-01-31 17:51 UTC (permalink / raw)
  To: gdb-patches

On Sun, Jan 18, 2004 at 07:23:38PM +0200, Eli Zaretskii wrote:
> > Date: Sun, 18 Jan 2004 10:19:10 -0500
> > From: Daniel Jacobowitz <drow@mvista.com>
> > > 
> > > What happens if a location has both software and hardware
> > > breakpoints?  Does the code still DTRT?
> > 
> > Hmm, I am not sure.  What _is_ the right thing?
> 
> We should at least do no worse than the current code does--which is to
> act as if only the first breakpoint (in the order stored in the
> breakpoint data-base) were hit.  That is, if breakpoints #n and #m
> both fire, the current GDB announces the one whose number is smaller
> (because it walks thru the breakpoints in their numerical order).  It
> doesn't seem to matter whether the breakpoints are of the software or
> the hardware-assisted variety.
> 
> It would be nice if we could announce all breakpoints that break at
> that point, but this might not be possible or very hard, I dunno.

Behavior unchanged by this patch.  Only one of the breakpoints will be
inserted - the other will be marked as a duplicate - and only inserted
breakpoints are checked when figuring out whether a software breakpoint
was hit.

-- 
Daniel Jacobowitz
MontaVista Software                         Debian GNU/Linux Developer


^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: RFC: Centralize DECR_PC_AFTER_BREAK handling from infrun
  2004-01-17 22:20 RFC: Centralize DECR_PC_AFTER_BREAK handling from infrun Daniel Jacobowitz
                   ` (2 preceding siblings ...)
  2004-01-22 14:09 ` Andrew Cagney
@ 2004-01-31 19:19 ` Daniel Jacobowitz
  3 siblings, 0 replies; 13+ messages in thread
From: Daniel Jacobowitz @ 2004-01-31 19:19 UTC (permalink / raw)
  To: gdb-patches

On Sat, Jan 17, 2004 at 05:20:07PM -0500, Daniel Jacobowitz wrote:
> The first, possibly most important step in cleaning up DECR_PC_AFTER_BREAK's
> tentacles.  This changes handle_inferior_event to fix the PC immediately,
> before doing anything else with it.  It removes the later decrements, but
> doesn't remove all the later workarounds for possibly undecremented PC
> values - that can come separately.
> 
> One case, HANDLE_NONSTEPPABLE_WATCHPOINTS and DECR_PC_AFTER_BREAK, is simply
> removed.  There are no targets using this combination, and if one is added,
> it's non-obvious whether a nonsteppable watchpoint really should be affected
> by DECR_PC_AFTER_BREAK.
> 
> A future cleanup will change bpstat_stop_status to only take a CORE_ADDR
> argument.  Also, I believe that both the tests for sigtramps and the use of
> deprecated_frame_update_pc_hack can go now, but I don't want to mix that in
> with this - esp. since I'm not sure how to test the former belief.
> 
> Tested i386-linux, which uses DECR_PC_AFTER_BREAK.  I'm not going to check
> this in just yet; all comments and testing welcome.

I've checked in this version, with comment revisions (thanks Eli!) and
testing on AIX and Tru64 (thanks Joel!).  The latter convinced me that
something is seriously wrong on both of those targets, but the patch
had a non-deterministic affect on the existing failures.

-- 
Daniel Jacobowitz
MontaVista Software                         Debian GNU/Linux Developer

2004-01-31  Daniel Jacobowitz  <drow@mvista.com>

	* breakpoint.c (software_breakpoint_inserted_here_p): New function.
	(bpstat_stop_status): Don't decrement PC.
	* breakpoint.h (software_breakpoint_inserted_here_p): Add
	prototype.
	* infrun.c (adjust_pc_after_break): New function.
	(handle_inferior_event): Call it, early.  Remove later references
	to DECR_PC_AFTER_BREAK.
	(normal_stop): Add commentary.

Index: breakpoint.c
===================================================================
RCS file: /cvs/src/src/gdb/breakpoint.c,v
retrieving revision 1.152
diff -u -p -r1.152 breakpoint.c
--- breakpoint.c	28 Jan 2004 01:39:51 -0000	1.152
+++ breakpoint.c	31 Jan 2004 17:54:20 -0000
@@ -1717,6 +1717,37 @@ breakpoint_inserted_here_p (CORE_ADDR pc
   return 0;
 }
 
+/* This function returns non-zero iff there is a software breakpoint
+   inserted at PC.  */
+
+int
+software_breakpoint_inserted_here_p (CORE_ADDR pc)
+{
+  struct bp_location *bpt;
+  int any_breakpoint_here = 0;
+
+  ALL_BP_LOCATIONS (bpt)
+    {
+      if (bpt->loc_type != bp_loc_software_breakpoint)
+	continue;
+
+      if ((breakpoint_enabled (bpt->owner)
+	   || bpt->owner->enable_state == bp_permanent)
+	  && bpt->inserted
+	  && bpt->address == pc)	/* bp is enabled and matches pc */
+	{
+	  if (overlay_debugging 
+	      && section_is_overlay (bpt->section) 
+	      && !section_is_mapped (bpt->section))
+	    continue;		/* unmapped overlay -- can't be a match */
+	  else
+	    return 1;
+	}
+    }
+
+  return 0;
+}
+
 /* Return nonzero if FRAME is a dummy frame.  We can't use
    DEPRECATED_PC_IN_CALL_DUMMY because figuring out the saved SP would
    take too much time, at least using frame_register() on the 68k.
@@ -2571,13 +2602,7 @@ bpstat_stop_status (CORE_ADDR *pc, int n
   /* Pointer to the last thing in the chain currently.  */
   bpstat bs = root_bs;
 
-  /* Get the address where the breakpoint would have been.  The
-     "not_a_sw_breakpoint" argument is meant to distinguish between a
-     breakpoint trap event and a trace/singlestep trap event.  For a
-     trace/singlestep trap event, we would not want to subtract
-     DECR_PC_AFTER_BREAK from the PC. */
-
-  bp_addr = *pc - (not_a_sw_breakpoint ? 0 : DECR_PC_AFTER_BREAK);
+  bp_addr = *pc;
 
   ALL_BREAKPOINTS_SAFE (b, temp)
   {
@@ -2862,18 +2887,6 @@ bpstat_stop_status (CORE_ADDR *pc, int n
 
   bs->next = NULL;		/* Terminate the chain */
   bs = root_bs->next;		/* Re-grab the head of the chain */
-
-  if (real_breakpoint && bs)
-    {
-      if (bs->breakpoint_at->type != bp_hardware_breakpoint)
-	{
-	  if (DECR_PC_AFTER_BREAK != 0)
-	    {
-	      *pc = bp_addr;
-	      write_pc (bp_addr);
-	    }
-	}
-    }
 
   /* The value of a hardware watchpoint hasn't changed, but the
      intermediate memory locations we are watching may have.  */
Index: breakpoint.h
===================================================================
RCS file: /cvs/src/src/gdb/breakpoint.h,v
retrieving revision 1.26
diff -u -p -r1.26 breakpoint.h
--- breakpoint.h	6 Nov 2003 18:24:55 -0000	1.26
+++ breakpoint.h	31 Jan 2004 17:54:20 -0000
@@ -605,6 +605,8 @@ extern enum breakpoint_here breakpoint_h
 
 extern int breakpoint_inserted_here_p (CORE_ADDR);
 
+extern int software_breakpoint_inserted_here_p (CORE_ADDR);
+
 /* FIXME: cagney/2002-11-10: The current [generic] dummy-frame code
    implements a functional superset of this function.  The only reason
    it hasn't been removed is because some architectures still don't
Index: infrun.c
===================================================================
RCS file: /cvs/src/src/gdb/infrun.c,v
retrieving revision 1.131
diff -u -p -r1.131 infrun.c
--- infrun.c	21 Jan 2004 16:32:07 -0000	1.131
+++ infrun.c	31 Jan 2004 17:54:20 -0000
@@ -1313,6 +1313,74 @@ handle_step_into_function (struct execut
   return;
 }
 
+static void
+adjust_pc_after_break (struct execution_control_state *ecs)
+{
+  CORE_ADDR stop_pc;
+
+  /* If this target does not decrement the PC after breakpoints, then
+     we have nothing to do.  */
+  if (DECR_PC_AFTER_BREAK == 0)
+    return;
+
+  /* If we've hit a breakpoint, we'll normally be stopped with SIGTRAP.  If
+     we aren't, just return.
+     
+     NOTE drow/2004-01-31: On some targets, breakpoints may generate
+     different signals (SIGILL or SIGEMT for instance), but it is less
+     clear where the PC is pointing afterwards.  It may not match
+     DECR_PC_AFTER_BREAK.  I don't know any specific target that generates
+     these signals at breakpoints (the code has been in GDB since at least
+     1992) so I can not guess how to handle them here.
+     
+     In earlier versions of GDB, a target with HAVE_NONSTEPPABLE_WATCHPOINTS
+     would have the PC after hitting a watchpoint affected by
+     DECR_PC_AFTER_BREAK.  I haven't found any target with both of these set
+     in GDB history, and it seems unlikely to be correct, so
+     HAVE_NONSTEPPABLE_WATCHPOINTS is not checked here.  */
+
+  if (ecs->ws.kind != TARGET_WAITKIND_STOPPED)
+    return;
+
+  if (ecs->ws.value.sig != TARGET_SIGNAL_TRAP)
+    return;
+
+  /* Find the location where (if we've hit a breakpoint) the breakpoint would
+     be.  */
+  stop_pc = read_pc_pid (ecs->ptid) - DECR_PC_AFTER_BREAK;
+
+  /* If we're software-single-stepping, then assume this is a breakpoint.
+     NOTE drow/2004-01-17: This doesn't check that the PC matches, or that
+     we're even in the right thread.  The software-single-step code needs
+     some modernization.
+
+     If we're not software-single-stepping, then we first check that there
+     is an enabled software breakpoint at this address.  If there is, and
+     we weren't using hardware-single-step, then we've hit the breakpoint.
+
+     If we were using hardware-single-step, we check prev_pc; if we just
+     stepped over an inserted software breakpoint, then we should decrement
+     the PC and eventually report hitting the breakpoint.  The prev_pc check
+     prevents us from decrementing the PC if we just stepped over a jump
+     instruction and landed on the instruction after a breakpoint.
+
+     The last bit checks that we didn't hit a breakpoint in a signal handler
+     without an intervening stop in sigtramp, which is detected by a new
+     stack pointer value below any usual function calling stack adjustments.
+
+     NOTE drow/2004-01-17: I'm not sure that this is necessary.  The check
+     predates checking for software single step at the same time.  Also,
+     if we've moved into a signal handler we should have seen the
+     signal.  */
+
+  if ((SOFTWARE_SINGLE_STEP_P () && singlestep_breakpoints_inserted_p)
+      || (software_breakpoint_inserted_here_p (stop_pc)
+	  && !(currently_stepping (ecs)
+	       && prev_pc != stop_pc
+	       && !(step_range_end && INNER_THAN (read_sp (), (step_sp - 16))))))
+    write_pc_pid (stop_pc, ecs->ptid);
+}
+
 /* Given an execution control state that has been freshly filled in
    by an event from the inferior, figure out what it means and take
    appropriate action.  */
@@ -1332,6 +1400,8 @@ handle_inferior_event (struct execution_
   target_last_wait_ptid = ecs->ptid;
   target_last_waitstatus = *ecs->wp;
 
+  adjust_pc_after_break (ecs);
+
   switch (ecs->infwait_state)
     {
     case infwait_thread_hop_state:
@@ -1685,19 +1755,15 @@ handle_inferior_event (struct execution_
       /* Check if a regular breakpoint has been hit before checking
          for a potential single step breakpoint. Otherwise, GDB will
          not see this breakpoint hit when stepping onto breakpoints.  */
-      if (breakpoints_inserted
-          && breakpoint_here_p (stop_pc - DECR_PC_AFTER_BREAK))
+      if (breakpoints_inserted && breakpoint_here_p (stop_pc))
 	{
 	  ecs->random_signal = 0;
-	  if (!breakpoint_thread_match (stop_pc - DECR_PC_AFTER_BREAK,
-					ecs->ptid))
+	  if (!breakpoint_thread_match (stop_pc, ecs->ptid))
 	    {
 	      int remove_status;
 
 	      /* Saw a breakpoint, but it was hit by the wrong thread.
 	         Just continue. */
-	      if (DECR_PC_AFTER_BREAK)
-		write_pc_pid (stop_pc - DECR_PC_AFTER_BREAK, ecs->ptid);
 
 	      remove_status = remove_breakpoints ();
 	      /* Did we fail to remove breakpoints?  If so, try
@@ -1710,7 +1776,7 @@ handle_inferior_event (struct execution_
 	      if (remove_status != 0)
 		{
 		  /* FIXME!  This is obviously non-portable! */
-		  write_pc_pid (stop_pc - DECR_PC_AFTER_BREAK + 4, ecs->ptid);
+		  write_pc_pid (stop_pc + 4, ecs->ptid);
 		  /* We need to restart all the threads now,
 		   * unles we're running in scheduler-locked mode. 
 		   * Use currently_stepping to determine whether to 
@@ -1744,17 +1810,6 @@ handle_inferior_event (struct execution_
 	}
       else if (SOFTWARE_SINGLE_STEP_P () && singlestep_breakpoints_inserted_p)
         {
-          /* Readjust the stop_pc as it is off by DECR_PC_AFTER_BREAK
-             compared to the value it would have if the system stepping
-             capability was used. This allows the rest of the code in
-             this function to use this address without having to worry
-             whether software single step is in use or not.  */
-          if (DECR_PC_AFTER_BREAK)
-            {
-              stop_pc -= DECR_PC_AFTER_BREAK;
-              write_pc_pid (stop_pc, ecs->ptid);
-            }
-
           sw_single_step_trap_p = 1;
           ecs->random_signal = 0;
         }
@@ -1886,9 +1941,6 @@ handle_inferior_event (struct execution_
          includes evaluating watchpoints, things will come to a
          stop in the correct manner.  */
 
-      if (DECR_PC_AFTER_BREAK)
-	write_pc (stop_pc - DECR_PC_AFTER_BREAK);
-
       remove_breakpoints ();
       registers_changed ();
       target_resume (ecs->ptid, 1, TARGET_SIGNAL_0);	/* Single step */
@@ -3121,6 +3173,7 @@ normal_stop (void)
       previous_inferior_ptid = inferior_ptid;
     }
 
+  /* NOTE drow/2004-01-17: Is this still necessary?  */
   /* Make sure that the current_frame's pc is correct.  This
      is a correction for setting up the frame info before doing
      DECR_PC_AFTER_BREAK */


^ permalink raw reply	[flat|nested] 13+ messages in thread

end of thread, other threads:[~2004-01-31 19:19 UTC | newest]

Thread overview: 13+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2004-01-17 22:20 RFC: Centralize DECR_PC_AFTER_BREAK handling from infrun Daniel Jacobowitz
2004-01-17 22:39 ` Andrew Cagney
2004-01-17 23:04   ` Daniel Jacobowitz
2004-01-18  7:05 ` Eli Zaretskii
2004-01-18 15:19   ` Daniel Jacobowitz
2004-01-18 17:27     ` Eli Zaretskii
2004-01-18 18:01       ` Andrew Cagney
2004-01-18 19:08         ` Eli Zaretskii
2004-01-31 17:51       ` Daniel Jacobowitz
2004-01-31 17:49     ` Daniel Jacobowitz
2004-01-22 14:09 ` Andrew Cagney
2004-01-22 22:34   ` Daniel Jacobowitz
2004-01-31 19:19 ` Daniel Jacobowitz

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox