infrun.c:handle_inferior_event: Rework random signal checks.

Looking at the current random signal checks:

  if (ecs->event_thread->suspend.stop_signal == GDB_SIGNAL_TRAP)
    random_signal
      = !((bpstat_explains_signal (ecs->event_thread->control.stop_bpstat,
				   GDB_SIGNAL_TRAP)
	   != BPSTAT_SIGNAL_NO)
	  || stopped_by_watchpoint
	  || ecs->event_thread->control.trap_expected
	  || (ecs->event_thread->control.step_range_end
	      && (ecs->event_thread->control.step_resume_breakpoint
		  == NULL)));
  else
    {
      enum bpstat_signal_value sval;

      sval = bpstat_explains_signal (ecs->event_thread->control.stop_bpstat,
				     ecs->event_thread->suspend.stop_signal);
      random_signal = (sval == BPSTAT_SIGNAL_NO);

      if (sval == BPSTAT_SIGNAL_HIDE)
	ecs->event_thread->suspend.stop_signal = GDB_SIGNAL_0;
    }

We can observe:

  - the stepping checks bit:

          ...
	  || ecs->event_thread->control.trap_expected
	  || (ecs->event_thread->control.step_range_end
	      && (ecs->event_thread->control.step_resume_breakpoint
		  == NULL)));
          ...

    is just like currently_stepping:

     static int
     currently_stepping (struct thread_info *tp)
     {
       return ((tp->control.step_range_end
                && tp->control.step_resume_breakpoint == NULL)
               || tp->control.trap_expected
               || bpstat_should_step ());
     }

    except it misses the bpstat_should_step check (***).

    It's not really necessary to check bpstat_should_step in the
    random signal tests, because software watchpoints always end up in
    the bpstat list anyway, which means bpstat_explains_signal with
    GDB_SIGNAL_TRAP always returns at least BPSSTAT_SIGNAL_HIDE, but I
    think the code is clearer if we reuse currently_stepping.

    *** - bpstat_should_step checks to see if there's any software
    watchpoint in the breakpoint list, because we need to force the
    target to single-step all the way, to evaluate the watchpoint's
    value at each step.

  - we never hide GDB_SIGNAL_TRAP, even if the bpstat returns
    BPSTAT_SIGNAL_HIDE, which is actually the default for all
    breakpoints.  If we make the default be BPSTAT_SIGNAL_PASS, then
    we can merge the two bpstat_explains_signal paths.

gdb/
2013-11-14  Pedro Alves  <palves@redhat.com>

	* breakpoint.c (bpstat_explains_signal) <Moribund locations>:
	Return BPSTAT_SIGNAL_PASS instead of BPSTAT_SIGNAL_HIDE.
	(explains_signal_watchpoint): Return BPSTAT_SIGNAL_PASS instead of
	BPSTAT_SIGNAL_HIDE.
	(base_breakpoint_explains_signal): Return BPSTAT_SIGNAL_PASS
	instead of BPSTAT_SIGNAL_HIDE.
	* infrun.c (handle_inferior_event): Rework random signal checks.
This commit is contained in:
Pedro Alves
2013-11-14 19:43:26 +00:00
parent ce12b0125d
commit bac7d97b66
3 changed files with 28 additions and 23 deletions

View File

@@ -4238,7 +4238,7 @@ bpstat_explains_signal (bpstat bsp, enum gdb_signal sig)
/* A moribund location can never explain a signal other than
GDB_SIGNAL_TRAP. */
if (sig == GDB_SIGNAL_TRAP)
newval = BPSTAT_SIGNAL_HIDE;
newval = BPSTAT_SIGNAL_PASS;
else
newval = BPSTAT_SIGNAL_NO;
}
@@ -10779,7 +10779,7 @@ explains_signal_watchpoint (struct breakpoint *b, enum gdb_signal sig)
if (b->type == bp_watchpoint && sig != GDB_SIGNAL_TRAP)
return BPSTAT_SIGNAL_NO;
return BPSTAT_SIGNAL_HIDE;
return BPSTAT_SIGNAL_PASS;
}
/* The breakpoint_ops structure to be used in hardware watchpoints. */
@@ -12890,7 +12890,7 @@ base_breakpoint_decode_linespec (struct breakpoint *b, char **s,
static enum bpstat_signal_value
base_breakpoint_explains_signal (struct breakpoint *b, enum gdb_signal sig)
{
return BPSTAT_SIGNAL_HIDE;
return BPSTAT_SIGNAL_PASS;
}
/* The default "after_condition_true" method. */