2004-05-10 Andrew Cagney <cagney@redhat.com>

* infrun.c (check_sigtramp2): Delete function.
	(handle_inferior_event): When single stepping, and taking a
	signal, set a breakpoint at the signal return address.  Delete
	redundant calls to check_sigtramp2.
	(insert_step_resume_breakpoint): New function.
	(through_sigtramp_breakpoint, handle_inferior_event)
	(follow_exec, wait_for_inferior, fetch_inferior_event)
	(currently_stepping, keep_going): Delete most uses of
	through_sigtramp_breakpoint, not that it should be deleted.
	(delete_breakpoint_current_contents): Delete function.

Index: testsuite/ChangeLog
2004-05-10  Andrew Cagney  <cagney@redhat.com>

	* gdb.base/signals.exp (signal_tests_1): Simplify "continue to
	func1" and "next to 2nd alarm", kernel bug avoided.
This commit is contained in:
Andrew Cagney 2004-05-10 18:36:07 +00:00
parent 03f4cc205b
commit d303a6c766
4 changed files with 121 additions and 255 deletions

View File

@ -1,3 +1,16 @@
2004-05-10 Andrew Cagney <cagney@redhat.com>
* infrun.c (check_sigtramp2): Delete function.
(handle_inferior_event): When single stepping, and taking a
signal, set a breakpoint at the signal return address. Delete
redundant calls to check_sigtramp2.
(insert_step_resume_breakpoint): New function.
(through_sigtramp_breakpoint, handle_inferior_event)
(follow_exec, wait_for_inferior, fetch_inferior_event)
(currently_stepping, keep_going): Delete most uses of
through_sigtramp_breakpoint, not that it should be deleted.
(delete_breakpoint_current_contents): Delete function.
2004-05-10 Randolph Chung <tausq@debian.org>
* config/pa/linux.mt (TM_FILE): Use new tm-linux.h for hppa-linux

View File

@ -60,8 +60,6 @@ static void resume_cleanups (void *);
static int hook_stop_stub (void *);
static void delete_breakpoint_current_contents (void *);
static int restore_selected_frame (void *);
static void build_infrun (void);
@ -305,6 +303,8 @@ static int breakpoints_failed;
static int stop_print_frame;
static struct breakpoint *step_resume_breakpoint = NULL;
/* NOTE: cagney/2004-05-08: This variable needs to be garbage
collected, it isn't used. */
static struct breakpoint *through_sigtramp_breakpoint = NULL;
/* On some platforms (e.g., HP-UX), hardware watchpoints have bad
@ -423,9 +423,6 @@ follow_exec (int pid, char *execd_pathname)
step_range_start = 0;
step_range_end = 0;
/* If there was one, it's gone now. */
through_sigtramp_breakpoint = NULL;
/* What is this a.out's name? */
printf_unfiltered ("Executing new program: %s\n", execd_pathname);
@ -905,17 +902,6 @@ init_wait_for_inferior (void)
stepping_past_singlestep_breakpoint = 0;
}
static void
delete_breakpoint_current_contents (void *arg)
{
struct breakpoint **breakpointp = (struct breakpoint **) arg;
if (*breakpointp != NULL)
{
delete_breakpoint (*breakpointp);
*breakpointp = NULL;
}
}
/* This enum encodes possible reasons for doing a target_wait, so that
wfi can call target_wait in one place. (Ultimately the call will be
@ -984,9 +970,10 @@ void init_execution_control_state (struct execution_control_state *ecs);
static void handle_step_into_function (struct execution_control_state *ecs);
void handle_inferior_event (struct execution_control_state *ecs);
static void check_sigtramp2 (struct execution_control_state *ecs);
static void step_into_function (struct execution_control_state *ecs);
static void step_over_function (struct execution_control_state *ecs);
static void insert_step_resume_breakpoint (struct frame_info *step_frame,
struct execution_control_state *ecs);
static void stop_stepping (struct execution_control_state *ecs);
static void prepare_to_wait (struct execution_control_state *ecs);
static void keep_going (struct execution_control_state *ecs);
@ -1008,8 +995,6 @@ wait_for_inferior (void)
old_cleanups = make_cleanup (delete_step_resume_breakpoint,
&step_resume_breakpoint);
make_cleanup (delete_breakpoint_current_contents,
&through_sigtramp_breakpoint);
/* wfi still stays in a loop, so it's OK just to take the address of
a local to get the ecs pointer. */
@ -1070,8 +1055,6 @@ fetch_inferior_event (void *client_data)
{
old_cleanups = make_exec_cleanup (delete_step_resume_breakpoint,
&step_resume_breakpoint);
make_exec_cleanup (delete_breakpoint_current_contents,
&through_sigtramp_breakpoint);
/* Fill in with reasonable starting values. */
init_execution_control_state (async_ecs);
@ -1989,15 +1972,9 @@ handle_inferior_event (struct execution_control_state *ecs)
return;
}
/* Don't even think about breakpoints
if just proceeded over a breakpoint.
However, if we are trying to proceed over a breakpoint
and end up in sigtramp, then through_sigtramp_breakpoint
will be set and we should check whether we've hit the
step breakpoint. */
if (stop_signal == TARGET_SIGNAL_TRAP && trap_expected
&& through_sigtramp_breakpoint == NULL)
/* Don't even think about breakpoints if just proceeded over a
breakpoint. */
if (stop_signal == TARGET_SIGNAL_TRAP && trap_expected)
bpstat_clear (&stop_bpstat);
else
{
@ -2080,39 +2057,22 @@ process_event_stop_test:
if (signal_program[stop_signal] == 0)
stop_signal = TARGET_SIGNAL_0;
/* I'm not sure whether this needs to be check_sigtramp2 or
whether it could/should be keep_going.
if (step_range_end != 0
&& stop_signal != TARGET_SIGNAL_0
&& stop_pc >= step_range_start && stop_pc < step_range_end
&& frame_id_eq (get_frame_id (get_current_frame ()), step_frame_id))
{
/* The inferior is about to take a signal that will take it
out of the single step range. Set a breakpoint at the
current PC (which is presumably where the signal handler
will eventually return) and then allow the inferior to
run free.
This used to jump to step_over_function if we are stepping,
which is wrong.
Suppose the user does a `next' over a function call, and while
that call is in progress, the inferior receives a signal for
which GDB does not stop (i.e., signal_stop[SIG] is false). In
that case, when we reach this point, there is already a
step-resume breakpoint established, right where it should be:
immediately after the function call the user is "next"-ing
over. If we call step_over_function now, two bad things
happen:
- we'll create a new breakpoint, at wherever the current
frame's return address happens to be. That could be
anywhere, depending on what function call happens to be on
the top of the stack at that point. Point is, it's probably
not where we need it.
- the existing step-resume breakpoint (which is at the correct
address) will get orphaned: step_resume_breakpoint will point
to the new breakpoint, and the old step-resume breakpoint
will never be cleaned up.
The old behavior was meant to help HP-UX single-step out of
sigtramps. It would place the new breakpoint at prev_pc, which
was certainly wrong. I don't know the details there, so fixing
this probably breaks that. As with anything else, it's up to
the HP-UX maintainer to furnish a fix that doesn't break other
platforms. --JimB, 20 May 1999 */
check_sigtramp2 (ecs);
Note that this is only needed for a signal delivered
while in the single-step range. Nested signals aren't a
problem as they eventually all return. */
insert_step_resume_breakpoint (get_current_frame (), ecs);
}
keep_going (ecs);
return;
}
@ -2153,13 +2113,6 @@ process_event_stop_test:
{
delete_step_resume_breakpoint (&step_resume_breakpoint);
}
/* Not sure whether we need to blow this away too, but probably
it is like the step-resume breakpoint. */
if (through_sigtramp_breakpoint != NULL)
{
delete_breakpoint (through_sigtramp_breakpoint);
through_sigtramp_breakpoint = NULL;
}
#if 0
/* FIXME - Need to implement nested temporary breakpoints */
@ -2207,9 +2160,8 @@ process_event_stop_test:
case BPSTAT_WHAT_STOP_NOISY:
stop_print_frame = 1;
/* We are about to nuke the step_resume_breakpoint and
through_sigtramp_breakpoint via the cleanup chain, so
no need to worry about it here. */
/* We are about to nuke the step_resume_breakpointt via the
cleanup chain, so no need to worry about it here. */
stop_stepping (ecs);
return;
@ -2217,9 +2169,8 @@ process_event_stop_test:
case BPSTAT_WHAT_STOP_SILENT:
stop_print_frame = 0;
/* We are about to nuke the step_resume_breakpoint and
through_sigtramp_breakpoint via the cleanup chain, so
no need to worry about it here. */
/* We are about to nuke the step_resume_breakpoin via the
cleanup chain, so no need to worry about it here. */
stop_stepping (ecs);
return;
@ -2251,10 +2202,6 @@ process_event_stop_test:
break;
case BPSTAT_WHAT_THROUGH_SIGTRAMP:
if (through_sigtramp_breakpoint)
delete_breakpoint (through_sigtramp_breakpoint);
through_sigtramp_breakpoint = NULL;
/* If were waiting for a trap, hitting the step_resume_break
doesn't count as getting it. */
if (trap_expected)
@ -2398,9 +2345,6 @@ process_event_stop_test:
/* Having a step-resume breakpoint overrides anything
else having to do with stepping commands until
that breakpoint is reached. */
/* I'm not sure whether this needs to be check_sigtramp2 or
whether it could/should be keep_going. */
check_sigtramp2 (ecs);
keep_going (ecs);
return;
}
@ -2408,9 +2352,6 @@ process_event_stop_test:
if (step_range_end == 0)
{
/* Likewise if we aren't even stepping. */
/* I'm not sure whether this needs to be check_sigtramp2 or
whether it could/should be keep_going. */
check_sigtramp2 (ecs);
keep_going (ecs);
return;
}
@ -2422,9 +2363,6 @@ process_event_stop_test:
within it! */
if (stop_pc >= step_range_start && stop_pc < step_range_end)
{
/* We might be doing a BPSTAT_WHAT_SINGLE and getting a signal.
So definately need to check for sigtramp here. */
check_sigtramp2 (ecs);
keep_going (ecs);
return;
}
@ -2688,50 +2626,13 @@ process_event_stop_test:
static int
currently_stepping (struct execution_control_state *ecs)
{
return ((through_sigtramp_breakpoint == NULL
&& !ecs->handling_longjmp
return ((!ecs->handling_longjmp
&& ((step_range_end && step_resume_breakpoint == NULL)
|| trap_expected))
|| ecs->stepping_through_solib_after_catch
|| bpstat_should_step ());
}
static void
check_sigtramp2 (struct execution_control_state *ecs)
{
char *name;
struct symtab_and_line sr_sal;
/* Check that what has happened here is that we have just stepped
the inferior with a signal (because it is a signal which
shouldn't make us stop), thus stepping into sigtramp. */
if (!trap_expected)
return;
if (get_frame_type (get_current_frame ()) != SIGTRAMP_FRAME)
return;
/* So we need to set a step_resume_break_address breakpoint and
continue until we hit it, and then step. FIXME: This should be
more enduring than a step_resume breakpoint; we should know that
we will later need to keep going rather than re-hitting the
breakpoint here (see the testsuite, gdb.base/signals.exp where it
says "exceedingly difficult"). */
init_sal (&sr_sal); /* initialize to zeroes */
sr_sal.pc = prev_pc;
sr_sal.section = find_pc_overlay (sr_sal.pc);
/* We perhaps could set the frame if we kept track of what the frame
corresponding to prev_pc was. But we don't, so don't. */
through_sigtramp_breakpoint =
set_momentary_breakpoint (sr_sal, null_frame_id, bp_through_sigtramp);
if (breakpoints_inserted)
insert_breakpoints ();
ecs->remove_breakpoints_on_following_step = 1;
ecs->another_trap = 1;
}
/* Subroutine call with source code we should not step over. Do step
to the first line of code in it. */
@ -2809,6 +2710,38 @@ step_into_function (struct execution_control_state *ecs)
keep_going (ecs);
}
/* The inferior, as a result of a function call (has left) or signal
(about to leave) the single-step range. Set a momentary breakpoint
within the step range where the inferior is expected to later
return. */
static void
insert_step_resume_breakpoint (struct frame_info *step_frame,
struct execution_control_state *ecs)
{
struct symtab_and_line sr_sal;
/* This is only used within the step-resume range/frame. */
gdb_assert (frame_id_eq (step_frame_id, get_frame_id (step_frame)));
gdb_assert (step_range_end != 0);
gdb_assert (get_frame_pc (step_frame) >= step_range_start
&& get_frame_pc (step_frame) < step_range_end);
init_sal (&sr_sal); /* initialize to zeros */
sr_sal.pc = ADDR_BITS_REMOVE (get_frame_pc (step_frame));
sr_sal.section = find_pc_overlay (sr_sal.pc);
check_for_old_step_resume_breakpoint ();
step_resume_breakpoint
= set_momentary_breakpoint (sr_sal, get_frame_id (step_frame),
bp_step_resume);
if (breakpoints_inserted)
insert_breakpoints ();
}
/* We've just entered a callee, and we wish to resume until it returns
to the caller. Setting a step_resume breakpoint on the return
address will catch a return from the callee.
@ -2933,15 +2866,13 @@ keep_going (struct execution_control_state *ecs)
/* If we've just finished a special step resume and we don't
want to hit a breakpoint, pull em out. */
if (step_resume_breakpoint == NULL
&& through_sigtramp_breakpoint == NULL
&& ecs->remove_breakpoints_on_following_step)
{
ecs->remove_breakpoints_on_following_step = 0;
remove_breakpoints ();
breakpoints_inserted = 0;
}
else if (!breakpoints_inserted &&
(through_sigtramp_breakpoint != NULL || !ecs->another_trap))
else if (!breakpoints_inserted && !ecs->another_trap)
{
breakpoints_failed = insert_breakpoints ();
if (breakpoints_failed)

View File

@ -1,3 +1,8 @@
2004-05-10 Andrew Cagney <cagney@redhat.com>
* gdb.base/signals.exp (signal_tests_1): Simplify "continue to
func1" and "next to 2nd alarm", kernel bug avoided.
2004-05-10 Daniel Jacobowitz <dan@debian.org>
PR external/1568

View File

@ -60,102 +60,47 @@ proc signal_tests_1 {} {
# An alarm has been signaled, give the signal time to get delivered.
sleep 2
# i386 BSD currently fails the next test with a SIGTRAP.
setup_xfail "i*86-*-bsd*"
# But Dynix has a DECR_PC_AFTER_BREAK of zero, so the failure
# is shadowed by hitting the through_sigtramp_breakpoint.
clear_xfail "i*86-sequent-bsd*"
# Univel SVR4 i386 continues instead of stepping.
setup_xfail "i*86-univel-sysv4*"
# lynx fails with "next" acting like "continue"
setup_xfail "*-*-*lynx*"
# linux (aout versions) also fails with "next" acting like "continue"
# this is probably more dependant on the kernel version than on the
# object file format or utils. (sigh)
setup_xfail "i*86-pc-linuxaout-gnu" "i*86-pc-linuxoldld-gnu"
send_gdb "next\n"
gdb_expect {
-re "alarm .*$gdb_prompt $" { pass "next to 2nd alarm (1)" }
-re "Program received signal SIGTRAP.*first.*$gdb_prompt $" {
# NOTE: cagney/2004-05-09: The following is retained as an
# historical reference. Because signal delivery when doing a
# next has been changed to use a continue, and not a
# single-step, the kernel bug of a stuck trace-bit in the
# trampoline's saved PS register is avoided.
# This can happen on machines that have a trace flag
# in their PS register.
# The trace flag in the PS register will be set due to
# the `next' command.
# Before calling the signal handler, the PS register
# is pushed along with the context on the user stack.
# When the signal handler has finished, it reenters the
# the kernel via a sigreturn syscall, which restores the
# PS register along with the context.
# If the kernel erroneously does not clear the trace flag
# in the pushed context, gdb will receive a SIGTRAP from
# the set trace flag in the restored context after the
# signal handler has finished.
# This can happen on machines that have a trace flag in their
# PS register. The trace flag in the PS register will be set
# due to the `next' command. Before calling the signal
# handler, the PS register is pushed along with the context on
# the user stack. When the signal handler has finished, it
# reenters the the kernel via a sigreturn syscall, which
# restores the PS register along with the context. If the
# kernel erroneously does not clear the trace flag in the
# pushed context, gdb will receive a SIGTRAP from the set
# trace flag in the restored context after the signal handler
# has finished.
# I do not yet understand why the SIGTRAP does not occur
# after stepping the instruction at the restored PC on
# i386 BSDI 1.0 systems.
# I do not yet understand why the SIGTRAP does not occur after
# stepping the instruction at the restored PC on i386 BSDI 1.0
# systems.
# Note that the vax under Ultrix also exhibits
# this behaviour (it is uncovered by the `continue from
# a break in a signal handler' test below).
# With this test the failure is shadowed by hitting the
# through_sigtramp_breakpoint upon return from the signal
# handler.
# Note that the vax under Ultrix also exhibits this behaviour
# (it is uncovered by the `continue from a break in a signal
# handler' test below). With this test the failure is
# shadowed by hitting the through_sigtramp_breakpoint upon
# return from the signal handler.
# SVR4 and Linux based i*86 systems exhibit this behaviour as
# well (it is uncovered by the `continue from a break in a
# signal handler' test below). As these systems use procfs,
# where we tell the kernel not to tell gdb about `pass'
# signals, and the trace flag is cleared by the kernel before
# entering the sigtramp routine, GDB will not notice the
# execution of the signal handler. Upon return from the
# signal handler, GDB will receive a SIGTRAP from the set
# trace flag in the restored context. The SIGTRAP marks the
# end of a (albeit long winded) single step for GDB, causing
# this test to pass.
# SVR4 and Linux based i*86 systems exhibit this behaviour
# as well (it is uncovered by the `continue from a break
# in a signal handler' test below).
# As these systems use procfs, where we tell the kernel not
# to tell gdb about `pass' signals, and the trace flag is
# cleared by the kernel before entering the sigtramp
# routine, GDB will not notice the execution of the signal
# handler.
# Upon return from the signal handler, GDB will receive
# a SIGTRAP from the set trace flag in the restored context.
# The SIGTRAP marks the end of a (albeit long winded)
# single step for GDB, causing this test to pass.
fail "next to 2nd alarm (1) (probably kernel bug)"
gdb_test "next" "alarm.*" "next to 2nd alarm (1)"
}
-re "Program exited with code.*$gdb_prompt $" {
# This is apparently a bug in the UnixWare kernel (but
# has not been investigated beyond the
# resume/target_wait level, and has not been reported
# to Univel). If it steps when a signal is pending,
# it does a continue instead. I don't know whether
# there is a workaround.
# Perhaps this problem exists on other SVR4 systems;
# but (a) we have no reason to think so, and (b) if we
# put a wrong xfail here, we never get an XPASS to let
# us know that it was incorrect (and then if such a
# configuration regresses we have no way of knowing).
# Solaris is not a relevant data point either way
# because it lacks single stepping.
# fnf: I don't agree with the above philosophy. We
# can never be sure that any particular XFAIL is
# specified 100% correctly in that no systems with
# the bug are missed and all systems without the bug
# are excluded. If we include an XFAIL that isn't
# appropriate for a particular system, then when that
# system gets tested it will XPASS, and someone should
# investigate and fix the setup_xfail as appropriate,
# or more preferably, the actual bug. Each such case
# adds more data to narrowing down the scope of the
# problem and ultimately fixing it.
setup_xfail "i*86-*-sysv4*"
fail "'next' behaved as 'continue (known SVR4 bug)'"
return 0
}
-re ".*$gdb_prompt $" { fail "next to 2nd alarm (1)" }
timeout { fail "next to 2nd alarm (1); (timeout)" }
eof { fail "next to 2nd alarm (1); (eof)" }
}
gdb_test "next" "alarm .*" "next to 2nd alarm"
gdb_test "break handler" "Breakpoint \[0-9\]+ .*"
gdb_test "next" "\\+\\+count; /\\* second \\*/" \
@ -191,41 +136,13 @@ proc signal_tests_1 {} {
gdb_test "break func1" "Breakpoint \[0-9\]+ .*"
gdb_test "break func2" "Breakpoint \[0-9\]+ .*"
# Vax Ultrix and i386 BSD currently fail the next test with
# a SIGTRAP, but with different symptoms.
setup_xfail "vax-*-ultrix*"
setup_xfail "i*86-*-bsd*"
setup_xfail "i*86-*-freebsd*"
setup_xfail "i*86-pc-linux-gnu*"
setup_xfail "i*86-*-solaris2*"
send_gdb "continue\n"
gdb_expect {
-re "Breakpoint.*func1.*$gdb_prompt $" { pass "continue to func1" }
-re "Program received signal SIGTRAP.*second.*$gdb_prompt $" {
# NOTE: cagney/2004-05-09: Ref "next to 2nd alarm" above.
# Because signal delivery when doing a next has been changed
# to use a continue, and not a single-step, the kernel bug of
# a stuck trace-bit in the trampoline's saved PS register is
# avoided.
# See explanation for `next to 2nd alarm (1)' fail above.
# We did step into the signal handler, hit a breakpoint
# in the handler and continued from the breakpoint.
# The set trace flag in the restored context is causing
# the SIGTRAP, without stepping an instruction.
fail "continue to func1 (probably kernel bug)"
gdb_test "continue" "Breakpoint.*func1.*" \
"extra continue to func1"
}
-re "Program received signal SIGTRAP.*func1 ..;.*$gdb_prompt $" {
# On the vax under Ultrix the set trace flag in the restored
# context is causing the SIGTRAP, but after stepping one
# instruction, as expected.
fail "continue to func1 (probably kernel bug)"
gdb_test "continue" "Breakpoint.*func1.*" \
"extra continue to func1"
}
-re ".*$gdb_prompt $" { fail "continue to func1" }
default { fail "continue to func1" }
}
gdb_test "continue" "Breakpoint.*func1.*" "continue to func1"
setup_xfail "*-*-irix*"
send_gdb "signal SIGUSR1\n"