forked from Imagelibrary/binutils-gdb
gdb/
2012-06-28 Jan Kratochvil <jan.kratochvil@redhat.com> Pedro Alves <palves@redhat.com> * gdbthread.h (ALL_THREADS): New macro. (thread_list): Declare. * infrun.c (handle_inferior_event) <spurious signal>: Don't keep going, but instead fall through to the stepping handling. * linux-nat.c (resume_lwp): New parameter 'signo'. Resume with the passed in signal. Adjust debug output. (resume_callback): Rename to ... (linux_nat_resume_callback): ... this. Pass the thread's last stop signal, if in "pass" state. (linux_nat_resume): Adjust to rename. (stop_wait_callback): New assertion. Don't respawn signals; instead let the LWP remain with SIGNALLED set. (linux_nat_wait_1): Remove flushing of pending SIGSTOPs. * remote.c (append_pending_thread_resumptions): New. (remote_vcont_resume): Call it. * target.h (target_resume): Extend comment. gdb/testsuite/ 2012-06-28 Jan Kratochvil <jan.kratochvil@redhat.com> Pedro Alves <palves@redhat.com> * gdb.threads/siginfo-threads.exp: New file. * gdb.threads/siginfo-threads.c: New file. * gdb.threads/sigstep-threads.exp: New file. * gdb.threads/sigstep-threads.c: New file.
This commit is contained in:
388
gdb/infrun.c
388
gdb/infrun.c
@@ -4363,227 +4363,227 @@ process_event_stop_test:
|
||||
(leaving the inferior at the step-resume-breakpoint without
|
||||
actually executing it). Either way continue until the
|
||||
breakpoint is really hit. */
|
||||
keep_going (ecs);
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Handle cases caused by hitting a breakpoint. */
|
||||
|
||||
/* Handle cases caused by hitting a breakpoint. */
|
||||
{
|
||||
CORE_ADDR jmp_buf_pc;
|
||||
struct bpstat_what what;
|
||||
CORE_ADDR jmp_buf_pc;
|
||||
struct bpstat_what what;
|
||||
|
||||
what = bpstat_what (ecs->event_thread->control.stop_bpstat);
|
||||
what = bpstat_what (ecs->event_thread->control.stop_bpstat);
|
||||
|
||||
if (what.call_dummy)
|
||||
{
|
||||
stop_stack_dummy = what.call_dummy;
|
||||
}
|
||||
|
||||
/* If we hit an internal event that triggers symbol changes, the
|
||||
current frame will be invalidated within bpstat_what (e.g., if
|
||||
we hit an internal solib event). Re-fetch it. */
|
||||
frame = get_current_frame ();
|
||||
gdbarch = get_frame_arch (frame);
|
||||
|
||||
switch (what.main_action)
|
||||
{
|
||||
case BPSTAT_WHAT_SET_LONGJMP_RESUME:
|
||||
/* If we hit the breakpoint at longjmp while stepping, we
|
||||
install a momentary breakpoint at the target of the
|
||||
jmp_buf. */
|
||||
|
||||
if (debug_infrun)
|
||||
fprintf_unfiltered (gdb_stdlog,
|
||||
"infrun: BPSTAT_WHAT_SET_LONGJMP_RESUME\n");
|
||||
|
||||
ecs->event_thread->stepping_over_breakpoint = 1;
|
||||
|
||||
if (what.is_longjmp)
|
||||
{
|
||||
struct value *arg_value;
|
||||
|
||||
/* If we set the longjmp breakpoint via a SystemTap probe,
|
||||
then use it to extract the arguments. The destination
|
||||
PC is the third argument to the probe. */
|
||||
arg_value = probe_safe_evaluate_at_pc (frame, 2);
|
||||
if (arg_value)
|
||||
jmp_buf_pc = value_as_address (arg_value);
|
||||
else if (!gdbarch_get_longjmp_target_p (gdbarch)
|
||||
|| !gdbarch_get_longjmp_target (gdbarch,
|
||||
frame, &jmp_buf_pc))
|
||||
{
|
||||
if (debug_infrun)
|
||||
fprintf_unfiltered (gdb_stdlog,
|
||||
"infrun: BPSTAT_WHAT_SET_LONGJMP_RESUME "
|
||||
"(!gdbarch_get_longjmp_target)\n");
|
||||
keep_going (ecs);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Insert a breakpoint at resume address. */
|
||||
insert_longjmp_resume_breakpoint (gdbarch, jmp_buf_pc);
|
||||
}
|
||||
else
|
||||
check_exception_resume (ecs, frame);
|
||||
keep_going (ecs);
|
||||
return;
|
||||
|
||||
case BPSTAT_WHAT_CLEAR_LONGJMP_RESUME:
|
||||
if (what.call_dummy)
|
||||
{
|
||||
struct frame_info *init_frame;
|
||||
stop_stack_dummy = what.call_dummy;
|
||||
}
|
||||
|
||||
/* There are several cases to consider.
|
||||
/* If we hit an internal event that triggers symbol changes, the
|
||||
current frame will be invalidated within bpstat_what (e.g.,
|
||||
if we hit an internal solib event). Re-fetch it. */
|
||||
frame = get_current_frame ();
|
||||
gdbarch = get_frame_arch (frame);
|
||||
|
||||
1. The initiating frame no longer exists. In this case
|
||||
we must stop, because the exception or longjmp has gone
|
||||
too far.
|
||||
|
||||
2. The initiating frame exists, and is the same as the
|
||||
current frame. We stop, because the exception or longjmp
|
||||
has been caught.
|
||||
|
||||
3. The initiating frame exists and is different from the
|
||||
current frame. This means the exception or longjmp has
|
||||
been caught beneath the initiating frame, so keep
|
||||
going.
|
||||
|
||||
4. longjmp breakpoint has been placed just to protect
|
||||
against stale dummy frames and user is not interested in
|
||||
stopping around longjmps. */
|
||||
switch (what.main_action)
|
||||
{
|
||||
case BPSTAT_WHAT_SET_LONGJMP_RESUME:
|
||||
/* If we hit the breakpoint at longjmp while stepping, we
|
||||
install a momentary breakpoint at the target of the
|
||||
jmp_buf. */
|
||||
|
||||
if (debug_infrun)
|
||||
fprintf_unfiltered (gdb_stdlog,
|
||||
"infrun: BPSTAT_WHAT_CLEAR_LONGJMP_RESUME\n");
|
||||
"infrun: BPSTAT_WHAT_SET_LONGJMP_RESUME\n");
|
||||
|
||||
gdb_assert (ecs->event_thread->control.exception_resume_breakpoint
|
||||
!= NULL);
|
||||
delete_exception_resume_breakpoint (ecs->event_thread);
|
||||
ecs->event_thread->stepping_over_breakpoint = 1;
|
||||
|
||||
if (what.is_longjmp)
|
||||
{
|
||||
check_longjmp_breakpoint_for_call_dummy (ecs->event_thread->num);
|
||||
struct value *arg_value;
|
||||
|
||||
if (!frame_id_p (ecs->event_thread->initiating_frame))
|
||||
/* If we set the longjmp breakpoint via a SystemTap
|
||||
probe, then use it to extract the arguments. The
|
||||
destination PC is the third argument to the
|
||||
probe. */
|
||||
arg_value = probe_safe_evaluate_at_pc (frame, 2);
|
||||
if (arg_value)
|
||||
jmp_buf_pc = value_as_address (arg_value);
|
||||
else if (!gdbarch_get_longjmp_target_p (gdbarch)
|
||||
|| !gdbarch_get_longjmp_target (gdbarch,
|
||||
frame, &jmp_buf_pc))
|
||||
{
|
||||
/* Case 4. */
|
||||
if (debug_infrun)
|
||||
fprintf_unfiltered (gdb_stdlog,
|
||||
"infrun: BPSTAT_WHAT_SET_LONGJMP_RESUME "
|
||||
"(!gdbarch_get_longjmp_target)\n");
|
||||
keep_going (ecs);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Insert a breakpoint at resume address. */
|
||||
insert_longjmp_resume_breakpoint (gdbarch, jmp_buf_pc);
|
||||
}
|
||||
else
|
||||
check_exception_resume (ecs, frame);
|
||||
keep_going (ecs);
|
||||
return;
|
||||
|
||||
init_frame = frame_find_by_id (ecs->event_thread->initiating_frame);
|
||||
case BPSTAT_WHAT_CLEAR_LONGJMP_RESUME:
|
||||
{
|
||||
struct frame_info *init_frame;
|
||||
|
||||
if (init_frame)
|
||||
{
|
||||
struct frame_id current_id
|
||||
= get_frame_id (get_current_frame ());
|
||||
if (frame_id_eq (current_id,
|
||||
ecs->event_thread->initiating_frame))
|
||||
{
|
||||
/* Case 2. Fall through. */
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Case 3. */
|
||||
keep_going (ecs);
|
||||
return;
|
||||
}
|
||||
}
|
||||
/* There are several cases to consider.
|
||||
|
||||
1. The initiating frame no longer exists. In this case
|
||||
we must stop, because the exception or longjmp has gone
|
||||
too far.
|
||||
|
||||
2. The initiating frame exists, and is the same as the
|
||||
current frame. We stop, because the exception or
|
||||
longjmp has been caught.
|
||||
|
||||
3. The initiating frame exists and is different from
|
||||
the current frame. This means the exception or longjmp
|
||||
has been caught beneath the initiating frame, so keep
|
||||
going.
|
||||
|
||||
4. longjmp breakpoint has been placed just to protect
|
||||
against stale dummy frames and user is not interested
|
||||
in stopping around longjmps. */
|
||||
|
||||
if (debug_infrun)
|
||||
fprintf_unfiltered (gdb_stdlog,
|
||||
"infrun: BPSTAT_WHAT_CLEAR_LONGJMP_RESUME\n");
|
||||
|
||||
gdb_assert (ecs->event_thread->control.exception_resume_breakpoint
|
||||
!= NULL);
|
||||
delete_exception_resume_breakpoint (ecs->event_thread);
|
||||
|
||||
if (what.is_longjmp)
|
||||
{
|
||||
check_longjmp_breakpoint_for_call_dummy (ecs->event_thread->num);
|
||||
|
||||
if (!frame_id_p (ecs->event_thread->initiating_frame))
|
||||
{
|
||||
/* Case 4. */
|
||||
keep_going (ecs);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
init_frame = frame_find_by_id (ecs->event_thread->initiating_frame);
|
||||
|
||||
if (init_frame)
|
||||
{
|
||||
struct frame_id current_id
|
||||
= get_frame_id (get_current_frame ());
|
||||
if (frame_id_eq (current_id,
|
||||
ecs->event_thread->initiating_frame))
|
||||
{
|
||||
/* Case 2. Fall through. */
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Case 3. */
|
||||
keep_going (ecs);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* For Cases 1 and 2, remove the step-resume breakpoint,
|
||||
if it exists. */
|
||||
delete_step_resume_breakpoint (ecs->event_thread);
|
||||
|
||||
ecs->event_thread->control.stop_step = 1;
|
||||
print_end_stepping_range_reason ();
|
||||
stop_stepping (ecs);
|
||||
}
|
||||
return;
|
||||
|
||||
case BPSTAT_WHAT_SINGLE:
|
||||
if (debug_infrun)
|
||||
fprintf_unfiltered (gdb_stdlog, "infrun: BPSTAT_WHAT_SINGLE\n");
|
||||
ecs->event_thread->stepping_over_breakpoint = 1;
|
||||
/* Still need to check other stuff, at least the case where
|
||||
we are stepping and step out of the right range. */
|
||||
break;
|
||||
|
||||
case BPSTAT_WHAT_STEP_RESUME:
|
||||
if (debug_infrun)
|
||||
fprintf_unfiltered (gdb_stdlog, "infrun: BPSTAT_WHAT_STEP_RESUME\n");
|
||||
|
||||
/* For Cases 1 and 2, remove the step-resume breakpoint,
|
||||
if it exists. */
|
||||
delete_step_resume_breakpoint (ecs->event_thread);
|
||||
if (ecs->event_thread->control.proceed_to_finish
|
||||
&& execution_direction == EXEC_REVERSE)
|
||||
{
|
||||
struct thread_info *tp = ecs->event_thread;
|
||||
|
||||
/* We are finishing a function in reverse, and just hit
|
||||
the step-resume breakpoint at the start address of
|
||||
the function, and we're almost there -- just need to
|
||||
back up by one more single-step, which should take us
|
||||
back to the function call. */
|
||||
tp->control.step_range_start = tp->control.step_range_end = 1;
|
||||
keep_going (ecs);
|
||||
return;
|
||||
}
|
||||
fill_in_stop_func (gdbarch, ecs);
|
||||
if (stop_pc == ecs->stop_func_start
|
||||
&& execution_direction == EXEC_REVERSE)
|
||||
{
|
||||
/* We are stepping over a function call in reverse, and
|
||||
just hit the step-resume breakpoint at the start
|
||||
address of the function. Go back to single-stepping,
|
||||
which should take us back to the function call. */
|
||||
ecs->event_thread->stepping_over_breakpoint = 1;
|
||||
keep_going (ecs);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
|
||||
case BPSTAT_WHAT_STOP_NOISY:
|
||||
if (debug_infrun)
|
||||
fprintf_unfiltered (gdb_stdlog, "infrun: BPSTAT_WHAT_STOP_NOISY\n");
|
||||
stop_print_frame = 1;
|
||||
|
||||
/* We are about to nuke the step_resume_breakpointt via the
|
||||
cleanup chain, so no need to worry about it here. */
|
||||
|
||||
ecs->event_thread->control.stop_step = 1;
|
||||
print_end_stepping_range_reason ();
|
||||
stop_stepping (ecs);
|
||||
return;
|
||||
|
||||
case BPSTAT_WHAT_STOP_SILENT:
|
||||
if (debug_infrun)
|
||||
fprintf_unfiltered (gdb_stdlog, "infrun: BPSTAT_WHAT_STOP_SILENT\n");
|
||||
stop_print_frame = 0;
|
||||
|
||||
/* 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;
|
||||
|
||||
case BPSTAT_WHAT_HP_STEP_RESUME:
|
||||
if (debug_infrun)
|
||||
fprintf_unfiltered (gdb_stdlog, "infrun: BPSTAT_WHAT_HP_STEP_RESUME\n");
|
||||
|
||||
delete_step_resume_breakpoint (ecs->event_thread);
|
||||
if (ecs->event_thread->step_after_step_resume_breakpoint)
|
||||
{
|
||||
/* Back when the step-resume breakpoint was inserted, we
|
||||
were trying to single-step off a breakpoint. Go back
|
||||
to doing that. */
|
||||
ecs->event_thread->step_after_step_resume_breakpoint = 0;
|
||||
ecs->event_thread->stepping_over_breakpoint = 1;
|
||||
keep_going (ecs);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
|
||||
case BPSTAT_WHAT_KEEP_CHECKING:
|
||||
break;
|
||||
}
|
||||
return;
|
||||
|
||||
case BPSTAT_WHAT_SINGLE:
|
||||
if (debug_infrun)
|
||||
fprintf_unfiltered (gdb_stdlog, "infrun: BPSTAT_WHAT_SINGLE\n");
|
||||
ecs->event_thread->stepping_over_breakpoint = 1;
|
||||
/* Still need to check other stuff, at least the case
|
||||
where we are stepping and step out of the right range. */
|
||||
break;
|
||||
|
||||
case BPSTAT_WHAT_STEP_RESUME:
|
||||
if (debug_infrun)
|
||||
fprintf_unfiltered (gdb_stdlog, "infrun: BPSTAT_WHAT_STEP_RESUME\n");
|
||||
|
||||
delete_step_resume_breakpoint (ecs->event_thread);
|
||||
if (ecs->event_thread->control.proceed_to_finish
|
||||
&& execution_direction == EXEC_REVERSE)
|
||||
{
|
||||
struct thread_info *tp = ecs->event_thread;
|
||||
|
||||
/* We are finishing a function in reverse, and just hit
|
||||
the step-resume breakpoint at the start address of the
|
||||
function, and we're almost there -- just need to back
|
||||
up by one more single-step, which should take us back
|
||||
to the function call. */
|
||||
tp->control.step_range_start = tp->control.step_range_end = 1;
|
||||
keep_going (ecs);
|
||||
return;
|
||||
}
|
||||
fill_in_stop_func (gdbarch, ecs);
|
||||
if (stop_pc == ecs->stop_func_start
|
||||
&& execution_direction == EXEC_REVERSE)
|
||||
{
|
||||
/* We are stepping over a function call in reverse, and
|
||||
just hit the step-resume breakpoint at the start
|
||||
address of the function. Go back to single-stepping,
|
||||
which should take us back to the function call. */
|
||||
ecs->event_thread->stepping_over_breakpoint = 1;
|
||||
keep_going (ecs);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
|
||||
case BPSTAT_WHAT_STOP_NOISY:
|
||||
if (debug_infrun)
|
||||
fprintf_unfiltered (gdb_stdlog, "infrun: BPSTAT_WHAT_STOP_NOISY\n");
|
||||
stop_print_frame = 1;
|
||||
|
||||
/* 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;
|
||||
|
||||
case BPSTAT_WHAT_STOP_SILENT:
|
||||
if (debug_infrun)
|
||||
fprintf_unfiltered (gdb_stdlog, "infrun: BPSTAT_WHAT_STOP_SILENT\n");
|
||||
stop_print_frame = 0;
|
||||
|
||||
/* 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;
|
||||
|
||||
case BPSTAT_WHAT_HP_STEP_RESUME:
|
||||
if (debug_infrun)
|
||||
fprintf_unfiltered (gdb_stdlog, "infrun: BPSTAT_WHAT_HP_STEP_RESUME\n");
|
||||
|
||||
delete_step_resume_breakpoint (ecs->event_thread);
|
||||
if (ecs->event_thread->step_after_step_resume_breakpoint)
|
||||
{
|
||||
/* Back when the step-resume breakpoint was inserted, we
|
||||
were trying to single-step off a breakpoint. Go back
|
||||
to doing that. */
|
||||
ecs->event_thread->step_after_step_resume_breakpoint = 0;
|
||||
ecs->event_thread->stepping_over_breakpoint = 1;
|
||||
keep_going (ecs);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
|
||||
case BPSTAT_WHAT_KEEP_CHECKING:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* We come here if we hit a breakpoint but should not
|
||||
stop for it. Possibly we also were stepping
|
||||
|
||||
Reference in New Issue
Block a user