* 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:
Jeff Law 1995-07-04 17:40:41 +00:00
parent 7523be3552
commit 48f4903f36
3 changed files with 81 additions and 23 deletions

View File

@ -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>
* config/h8300/h8300.mt: Renamed from h8300hms.mt.

View File

@ -479,6 +479,8 @@ wait_for_inferior ()
else
pid = target_wait (-1, &w);
have_waited:
flush_cached_frames ();
/* If it's a new process, add it to the thread database */
@ -501,24 +503,6 @@ wait_for_inferior ()
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)
{
case TARGET_WAITKIND_LOADED:
@ -587,6 +571,10 @@ wait_for_inferior ()
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
another thread. If so, then step that thread past the breakpoint,
and continue it. */
@ -599,7 +587,7 @@ wait_for_inferior ()
if (!breakpoint_thread_match (stop_pc - DECR_PC_AFTER_BREAK, pid))
{
/* 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 ();
target_resume (pid, 1, TARGET_SIGNAL_0); /* Single step */
@ -611,7 +599,9 @@ wait_for_inferior ()
else
target_wait (pid, &w);
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;
}
}
@ -703,6 +693,60 @@ wait_for_inferior ()
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_name = 0;
/* Don't care about return value; stop_func_start and stop_func_name

View File

@ -705,14 +705,16 @@ child_resume (pid, step, signal)
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)
{
/* Resume all threads. */
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
it was. (If GDB wanted it to start some other way, we have already