aboutsummaryrefslogtreecommitdiff
path: root/gdb/infrun.c
diff options
context:
space:
mode:
authorPedro Alves <palves@redhat.com>2008-10-15 19:15:34 +0000
committerPedro Alves <palves@redhat.com>2008-10-15 19:15:34 +0000
commit1c5cfe8615a947f26ef1569f3af3017bb1c63899 (patch)
tree67c00221d017a285eaf67bc17815044541a57d9f /gdb/infrun.c
parent41702f1b3391a34327b3fb4786b690583c1249b6 (diff)
downloadgdb-1c5cfe8615a947f26ef1569f3af3017bb1c63899.zip
gdb-1c5cfe8615a947f26ef1569f3af3017bb1c63899.tar.gz
gdb-1c5cfe8615a947f26ef1569f3af3017bb1c63899.tar.bz2
gdb/
* breakpoint.c (breakpoint_init_inferior): Clean up the moribund locations list. (moribund_breakpoint_here_p): Record the moribund location in the moribund_locations vector. * breakpoint.h (moribund_breakpoint_here_p): Declare. (displaced_step_fixup): Check if the breakpoint the thread was trying to step over has been removed since having been placed in the displaced stepping queue. (adjust_pc_after_break): In non-stop mode, check for a moribund breakpoint at the stop pc. (handle_inferior_event): Don't retire moribund breakpoints on TARGET_WAITKIND_IGNORE. gdb/testsuite/ * gdb.mi/mi-nsmoribund.exp, gdb.mi/nsmoribund.c: New test.
Diffstat (limited to 'gdb/infrun.c')
-rw-r--r--gdb/infrun.c84
1 files changed, 61 insertions, 23 deletions
diff --git a/gdb/infrun.c b/gdb/infrun.c
index f60f938..150bf4c 100644
--- a/gdb/infrun.c
+++ b/gdb/infrun.c
@@ -789,40 +789,71 @@ displaced_step_fixup (ptid_t event_ptid, enum target_signal signal)
do_cleanups (old_cleanups);
+ displaced_step_ptid = null_ptid;
+
/* Are there any pending displaced stepping requests? If so, run
one now. */
- if (displaced_step_request_queue)
+ while (displaced_step_request_queue)
{
struct displaced_step_request *head;
ptid_t ptid;
+ CORE_ADDR actual_pc;
head = displaced_step_request_queue;
ptid = head->ptid;
displaced_step_request_queue = head->next;
xfree (head);
- if (debug_displaced)
- fprintf_unfiltered (gdb_stdlog,
- "displaced: stepping queued %s now\n",
- target_pid_to_str (ptid));
-
- displaced_step_ptid = null_ptid;
- displaced_step_prepare (ptid);
context_switch (ptid);
- if (debug_displaced)
+ actual_pc = read_pc ();
+
+ if (breakpoint_here_p (actual_pc))
{
- struct regcache *resume_regcache = get_thread_regcache (ptid);
- CORE_ADDR actual_pc = regcache_read_pc (resume_regcache);
- gdb_byte buf[4];
-
- fprintf_unfiltered (gdb_stdlog, "displaced: run 0x%s: ",
- paddr_nz (actual_pc));
- read_memory (actual_pc, buf, sizeof (buf));
- displaced_step_dump_bytes (gdb_stdlog, buf, sizeof (buf));
+ if (debug_displaced)
+ fprintf_unfiltered (gdb_stdlog,
+ "displaced: stepping queued %s now\n",
+ target_pid_to_str (ptid));
+
+ displaced_step_prepare (ptid);
+
+ if (debug_displaced)
+ {
+ gdb_byte buf[4];
+
+ fprintf_unfiltered (gdb_stdlog, "displaced: run 0x%s: ",
+ paddr_nz (actual_pc));
+ read_memory (actual_pc, buf, sizeof (buf));
+ displaced_step_dump_bytes (gdb_stdlog, buf, sizeof (buf));
+ }
+
+ target_resume (ptid, 1, TARGET_SIGNAL_0);
+
+ /* Done, we're stepping a thread. */
+ break;
}
+ else
+ {
+ int step;
+ struct thread_info *tp = inferior_thread ();
+
+ /* The breakpoint we were sitting under has since been
+ removed. */
+ tp->trap_expected = 0;
+
+ /* Go back to what we were trying to do. */
+ step = currently_stepping (tp);
- target_resume (ptid, 1, TARGET_SIGNAL_0);
+ if (debug_displaced)
+ fprintf_unfiltered (gdb_stdlog, "breakpoint is gone %s: step(%d)\n",
+ target_pid_to_str (tp->ptid), step);
+
+ target_resume (ptid, step, TARGET_SIGNAL_0);
+ tp->stop_signal = TARGET_SIGNAL_0;
+
+ /* This request was discarded. See if there's any other
+ thread waiting for its turn. */
+ }
}
}
@@ -1798,9 +1829,16 @@ adjust_pc_after_break (struct execution_control_state *ecs)
breakpoint_pc = regcache_read_pc (regcache)
- gdbarch_decr_pc_after_break (gdbarch);
- /* Check whether there actually is a software breakpoint inserted
- at that location. */
- if (software_breakpoint_inserted_here_p (breakpoint_pc))
+ /* Check whether there actually is a software breakpoint inserted at
+ that location.
+
+ If in non-stop mode, a race condition is possible where we've
+ removed a breakpoint, but stop events for that breakpoint were
+ already queued and arrive later. To suppress those spurious
+ SIGTRAPs, we keep a list of such breakpoint locations for a bit,
+ and retire them after a number of stop events are reported. */
+ if (software_breakpoint_inserted_here_p (breakpoint_pc)
+ || (non_stop && moribund_breakpoint_here_p (breakpoint_pc)))
{
/* When using hardware single-step, a SIGTRAP is reported for both
a completed single-step and a software breakpoint. Need to
@@ -1873,8 +1911,6 @@ handle_inferior_event (struct execution_control_state *ecs)
else
stop_soon = NO_STOP_QUIETLY;
- breakpoint_retire_moribund ();
-
/* Cache the last pid/waitstatus. */
target_last_wait_ptid = ecs->ptid;
target_last_waitstatus = ecs->ws;
@@ -1902,6 +1938,8 @@ handle_inferior_event (struct execution_control_state *ecs)
if (ecs->ws.kind != TARGET_WAITKIND_IGNORE)
{
+ breakpoint_retire_moribund ();
+
/* Mark the non-executing threads accordingly. */
if (!non_stop
|| ecs->ws.kind == TARGET_WAITKIND_EXITED