* infrun.c (wait_for_inferior): When we hit a breakpoint for the
wrong thread, make sure to write the fixed PC value into the thread that stopped. Restart all threads after single stepping over a breakpoint for a different thread. * breakpoint.c (set_momentary_breakpoint): Make momentary breakpoints thread specific in a multi-threaded program. * lynx-nat.c (child_resume): Add some comments. Correctly choose between the single and multi-threaded step and continue ptrace calls. Some of the lynx-6100 single stepping fixes.
This commit is contained in:
parent
7523be3552
commit
48f4903f36
|
@ -1,3 +1,15 @@
|
||||||
|
Tue Jul 4 10:30:22 1995 Jeffrey A. Law <law@rtl.cygnus.com>
|
||||||
|
|
||||||
|
* infrun.c (wait_for_inferior): When we hit a breakpoint for the
|
||||||
|
wrong thread, make sure to write the fixed PC value into the thread
|
||||||
|
that stopped. Restart all threads after single stepping over a
|
||||||
|
breakpoint for a different thread.
|
||||||
|
* breakpoint.c (set_momentary_breakpoint): Make momentary
|
||||||
|
breakpoints thread specific in a multi-threaded program.
|
||||||
|
* lynx-nat.c (child_resume): Add some comments. Correctly
|
||||||
|
choose between the single and multi-threaded step and continue
|
||||||
|
ptrace calls.
|
||||||
|
|
||||||
Fri Jun 30 16:15:36 1995 Stan Shebs <shebs@andros.cygnus.com>
|
Fri Jun 30 16:15:36 1995 Stan Shebs <shebs@andros.cygnus.com>
|
||||||
|
|
||||||
* config/h8300/h8300.mt: Renamed from h8300hms.mt.
|
* config/h8300/h8300.mt: Renamed from h8300hms.mt.
|
||||||
|
|
84
gdb/infrun.c
84
gdb/infrun.c
|
@ -479,6 +479,8 @@ wait_for_inferior ()
|
||||||
else
|
else
|
||||||
pid = target_wait (-1, &w);
|
pid = target_wait (-1, &w);
|
||||||
|
|
||||||
|
have_waited:
|
||||||
|
|
||||||
flush_cached_frames ();
|
flush_cached_frames ();
|
||||||
|
|
||||||
/* If it's a new process, add it to the thread database */
|
/* If it's a new process, add it to the thread database */
|
||||||
|
@ -501,24 +503,6 @@ wait_for_inferior ()
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
stop_signal = w.value.sig;
|
|
||||||
|
|
||||||
stop_pc = read_pc_pid (pid);
|
|
||||||
|
|
||||||
if (STOPPED_BY_WATCHPOINT (w))
|
|
||||||
{
|
|
||||||
write_pc (stop_pc - DECR_PC_AFTER_BREAK);
|
|
||||||
|
|
||||||
remove_breakpoints ();
|
|
||||||
target_resume (pid, 1, TARGET_SIGNAL_0); /* Single step */
|
|
||||||
|
|
||||||
if (target_wait_hook)
|
|
||||||
target_wait_hook (pid, &w);
|
|
||||||
else
|
|
||||||
target_wait (pid, &w);
|
|
||||||
insert_breakpoints ();
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (w.kind)
|
switch (w.kind)
|
||||||
{
|
{
|
||||||
case TARGET_WAITKIND_LOADED:
|
case TARGET_WAITKIND_LOADED:
|
||||||
|
@ -587,6 +571,10 @@ wait_for_inferior ()
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
stop_signal = w.value.sig;
|
||||||
|
|
||||||
|
stop_pc = read_pc_pid (pid);
|
||||||
|
|
||||||
/* See if a thread hit a thread-specific breakpoint that was meant for
|
/* See if a thread hit a thread-specific breakpoint that was meant for
|
||||||
another thread. If so, then step that thread past the breakpoint,
|
another thread. If so, then step that thread past the breakpoint,
|
||||||
and continue it. */
|
and continue it. */
|
||||||
|
@ -599,7 +587,7 @@ wait_for_inferior ()
|
||||||
if (!breakpoint_thread_match (stop_pc - DECR_PC_AFTER_BREAK, pid))
|
if (!breakpoint_thread_match (stop_pc - DECR_PC_AFTER_BREAK, pid))
|
||||||
{
|
{
|
||||||
/* Saw a breakpoint, but it was hit by the wrong thread. Just continue. */
|
/* Saw a breakpoint, but it was hit by the wrong thread. Just continue. */
|
||||||
write_pc (stop_pc - DECR_PC_AFTER_BREAK);
|
write_pc_pid (stop_pc - DECR_PC_AFTER_BREAK, pid);
|
||||||
|
|
||||||
remove_breakpoints ();
|
remove_breakpoints ();
|
||||||
target_resume (pid, 1, TARGET_SIGNAL_0); /* Single step */
|
target_resume (pid, 1, TARGET_SIGNAL_0); /* Single step */
|
||||||
|
@ -611,7 +599,9 @@ wait_for_inferior ()
|
||||||
else
|
else
|
||||||
target_wait (pid, &w);
|
target_wait (pid, &w);
|
||||||
insert_breakpoints ();
|
insert_breakpoints ();
|
||||||
target_resume (pid, 0, TARGET_SIGNAL_0);
|
|
||||||
|
/* We need to restart all the threads now. */
|
||||||
|
target_resume (-1, 0, TARGET_SIGNAL_0);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -703,6 +693,60 @@ wait_for_inferior ()
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef HAVE_STEPPABLE_WATCHPOINT
|
||||||
|
/* It may not be necessary to disable the watchpoint to stop over
|
||||||
|
it. For example, the PA can (with some kernel cooperation)
|
||||||
|
single step over a watchpoint without disabling the watchpoint. */
|
||||||
|
if (STOPPED_BY_WATCHPOINT (w))
|
||||||
|
{
|
||||||
|
resume (1, 0);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef HAVE_NONSTEPPABLE_WATCHPOINT
|
||||||
|
/* It is far more common to need to disable a watchpoint
|
||||||
|
to step the inferior over it. FIXME. What else might
|
||||||
|
a debug register or page protection watchpoint scheme need
|
||||||
|
here? */
|
||||||
|
if (STOPPED_BY_WATCHPOINT (w))
|
||||||
|
{
|
||||||
|
/* At this point, we are stopped at an instruction which has attempted to write
|
||||||
|
to a piece of memory under control of a watchpoint. The instruction hasn't
|
||||||
|
actually executed yet. If we were to evaluate the watchpoint expression
|
||||||
|
now, we would get the old value, and therefore no change would seem to have
|
||||||
|
occurred.
|
||||||
|
|
||||||
|
In order to make watchpoints work `right', we really need to complete the
|
||||||
|
memory write, and then evaluate the watchpoint expression. The following
|
||||||
|
code does that by removing the watchpoint (actually, all watchpoints and
|
||||||
|
breakpoints), single-stepping the target, re-inserting watchpoints, and then
|
||||||
|
falling through to let normal single-step processing handle proceed. Since
|
||||||
|
this includes evaluating watchpoints, things will come to a stop in the
|
||||||
|
correct manner. */
|
||||||
|
|
||||||
|
write_pc (stop_pc - DECR_PC_AFTER_BREAK);
|
||||||
|
|
||||||
|
remove_breakpoints ();
|
||||||
|
target_resume (pid, 1, TARGET_SIGNAL_0); /* Single step */
|
||||||
|
|
||||||
|
if (target_wait_hook)
|
||||||
|
target_wait_hook (pid, &w);
|
||||||
|
else
|
||||||
|
target_wait (pid, &w);
|
||||||
|
insert_breakpoints ();
|
||||||
|
/* FIXME-maybe: is this cleaner than setting a flag? Does it
|
||||||
|
handle things like signals arriving and other things happening
|
||||||
|
in combination correctly? */
|
||||||
|
goto have_waited;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef HAVE_CONTINUABLE_WATCHPOINT
|
||||||
|
/* It may be possible to simply continue after a watchpoint. */
|
||||||
|
STOPPED_BY_WATCHPOINT (w);
|
||||||
|
#endif
|
||||||
|
|
||||||
stop_func_start = 0;
|
stop_func_start = 0;
|
||||||
stop_func_name = 0;
|
stop_func_name = 0;
|
||||||
/* Don't care about return value; stop_func_start and stop_func_name
|
/* Don't care about return value; stop_func_start and stop_func_name
|
||||||
|
|
|
@ -705,14 +705,16 @@ child_resume (pid, step, signal)
|
||||||
|
|
||||||
errno = 0;
|
errno = 0;
|
||||||
|
|
||||||
|
/* If pid == -1, then we want to step/continue all threads, else
|
||||||
|
we only want to step/continue a single thread. */
|
||||||
if (pid == -1)
|
if (pid == -1)
|
||||||
{
|
{
|
||||||
/* Resume all threads. */
|
|
||||||
|
|
||||||
pid = inferior_pid;
|
pid = inferior_pid;
|
||||||
|
func = step ? PTRACE_SINGLESTEP : PTRACE_CONT;
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
func = step ? PTRACE_SINGLESTEP_ONE : PTRACE_CONT_ONE;
|
||||||
|
|
||||||
func = step ? PTRACE_SINGLESTEP_ONE : PTRACE_CONT;
|
|
||||||
|
|
||||||
/* An address of (PTRACE_ARG3_TYPE)1 tells ptrace to continue from where
|
/* An address of (PTRACE_ARG3_TYPE)1 tells ptrace to continue from where
|
||||||
it was. (If GDB wanted it to start some other way, we have already
|
it was. (If GDB wanted it to start some other way, we have already
|
||||||
|
|
Loading…
Reference in New Issue