diff options
author | Pedro Alves <palves@redhat.com> | 2013-11-14 19:43:27 +0000 |
---|---|---|
committer | Pedro Alves <palves@redhat.com> | 2013-11-14 19:51:50 +0000 |
commit | 4f5d7f635cd1dd81575edb35395272ee3d535502 (patch) | |
tree | 3c9cb5fa87c5d0122fb8d2bfe20840b672467fdb /gdb | |
parent | 47591c29add16c520c7bc2c7ace227deeb08f4a5 (diff) | |
download | gdb-4f5d7f635cd1dd81575edb35395272ee3d535502.zip gdb-4f5d7f635cd1dd81575edb35395272ee3d535502.tar.gz gdb-4f5d7f635cd1dd81575edb35395272ee3d535502.tar.bz2 |
infrun.c: Split handle_inferior_event further.
After the previous patches, we only ever reach the code after the
initial 'switch (ecs->ws.kind)' switch for TARGET_WAITKIND_STOPPED.
We can now factor out all that to its own function.
Unfortunately, stepped_after_stopped_by_watchpoint needed to move to
the ecs. I think that indicates a state machine bug -- no event other
than TARGET_WAITKIND_STOPPED indicates a single-step actually
finished. TARGET_WAITKIND_SYSCALL_XXX, TARGET_WAITKIND_FORK, etc. are
all events that are triggered from the kernel, _within_ a syscall,
IOW, from userspace's perspective, halfway through an instruction
being executed. This might actually matter for the syscall events, as
syscalls can change memory (and thus trigger watchpoints).
gdb/
2013-11-14 Pedro Alves <palves@redhat.com>
* infrun.c (struct execution_control_state)
<stepped_after_stopped_by_watchpoint>: New field.
(get_inferior_stop_soon): New function.
(handle_inferior_event): 'stepped_after_stopped_by_watchpoint' was
moved to struct execution_control_state -- adjust. Use
get_inferior_stop_soon. Split TARGET_WAITKIND_STOPPED handling to
new function.
(handle_signal_stop): New function, factored out from
handle_inferior_event.
Diffstat (limited to 'gdb')
-rw-r--r-- | gdb/ChangeLog | 12 | ||||
-rw-r--r-- | gdb/infrun.c | 59 |
2 files changed, 50 insertions, 21 deletions
diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 58e7f2e..5b9428d 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,5 +1,17 @@ 2013-11-14 Pedro Alves <palves@redhat.com> + * infrun.c (struct execution_control_state) + <stepped_after_stopped_by_watchpoint>: New field. + (get_inferior_stop_soon): New function. + (handle_inferior_event): 'stepped_after_stopped_by_watchpoint' was + moved to struct execution_control_state -- adjust. Use + get_inferior_stop_soon. Split TARGET_WAITKIND_STOPPED handling to + new function. + (handle_signal_stop): New function, factored out from + handle_inferior_event. + +2013-11-14 Pedro Alves <palves@redhat.com> + * break-catch-sig.c (signal_catchpoint_explains_signal): Adjust to return a boolean. * breakpoint.c (bpstat_explains_signal): Adjust to return a diff --git a/gdb/infrun.c b/gdb/infrun.c index 4d26e37..52bb064 100644 --- a/gdb/infrun.c +++ b/gdb/infrun.c @@ -2424,6 +2424,11 @@ struct execution_control_state CORE_ADDR stop_func_end; const char *stop_func_name; int wait_some_more; + + /* We were in infwait_step_watch_state or + infwait_nonstep_watch_state state, and the thread reported an + event. */ + int stepped_after_stopped_by_watchpoint; }; static void handle_inferior_event (struct execution_control_state *ecs); @@ -2432,6 +2437,7 @@ static void handle_step_into_function (struct gdbarch *gdbarch, struct execution_control_state *ecs); static void handle_step_into_function_backward (struct gdbarch *gdbarch, struct execution_control_state *ecs); +static void handle_signal_stop (struct execution_control_state *ecs); static void check_exception_resume (struct execution_control_state *, struct frame_info *); @@ -3132,6 +3138,18 @@ fill_in_stop_func (struct gdbarch *gdbarch, } } + +/* Return the STOP_SOON field of the inferior pointed at by PTID. */ + +static enum stop_kind +get_inferior_stop_soon (ptid_t ptid) +{ + struct inferior *inf = find_inferior_pid (ptid_get_pid (ptid)); + + gdb_assert (inf != NULL); + return inf->control.stop_soon; +} + /* Given an execution control state that has been freshly filled in by an event from the inferior, figure out what it means and take appropriate action. @@ -3148,12 +3166,7 @@ fill_in_stop_func (struct gdbarch *gdbarch, static void handle_inferior_event (struct execution_control_state *ecs) { - struct frame_info *frame; - struct gdbarch *gdbarch; - int stopped_by_watchpoint; - int stepped_after_stopped_by_watchpoint = 0; enum stop_kind stop_soon; - int random_signal; if (ecs->ws.kind == TARGET_WAITKIND_IGNORE) { @@ -3187,18 +3200,6 @@ handle_inferior_event (struct execution_control_state *ecs) return; } - if (ecs->ws.kind != TARGET_WAITKIND_EXITED - && ecs->ws.kind != TARGET_WAITKIND_SIGNALLED - && ecs->ws.kind != TARGET_WAITKIND_NO_RESUMED) - { - struct inferior *inf = find_inferior_pid (ptid_get_pid (ecs->ptid)); - - gdb_assert (inf); - stop_soon = inf->control.stop_soon; - } - else - stop_soon = NO_STOP_QUIETLY; - /* Cache the last pid/waitstatus. */ target_last_wait_ptid = ecs->ptid; target_last_waitstatus = ecs->ws; @@ -3295,7 +3296,7 @@ handle_inferior_event (struct execution_control_state *ecs) fprintf_unfiltered (gdb_stdlog, "infrun: infwait_step_watch_state\n"); - stepped_after_stopped_by_watchpoint = 1; + ecs->stepped_after_stopped_by_watchpoint = 1; break; case infwait_nonstep_watch_state: @@ -3307,7 +3308,7 @@ handle_inferior_event (struct execution_control_state *ecs) /* FIXME-maybe: is this cleaner than setting a flag? Does it handle things like signals arriving and other things happening in combination correctly? */ - stepped_after_stopped_by_watchpoint = 1; + ecs->stepped_after_stopped_by_watchpoint = 1; break; default: @@ -3330,6 +3331,8 @@ handle_inferior_event (struct execution_control_state *ecs) the beginning of an attach or remote session; we will query the full list of libraries once the connection is established. */ + + stop_soon = get_inferior_stop_soon (ecs->ptid); if (stop_soon == NO_STOP_QUIETLY) { struct regcache *regcache; @@ -3715,7 +3718,8 @@ Cannot fill $_exitsignal with the correct signal number.\n")); if (debug_infrun) fprintf_unfiltered (gdb_stdlog, "infrun: TARGET_WAITKIND_STOPPED\n"); ecs->event_thread->suspend.stop_signal = ecs->ws.value.sig; - break; + handle_signal_stop (ecs); + return; case TARGET_WAITKIND_NO_HISTORY: if (debug_infrun) @@ -3735,6 +3739,18 @@ Cannot fill $_exitsignal with the correct signal number.\n")); stop_stepping (ecs); return; } +} + +/* Come here when the program has stopped with a signal. */ + +static void +handle_signal_stop (struct execution_control_state *ecs) +{ + struct frame_info *frame; + struct gdbarch *gdbarch; + int stopped_by_watchpoint; + enum stop_kind stop_soon; + int random_signal; if (ecs->ws.kind == TARGET_WAITKIND_STOPPED) { @@ -4022,7 +4038,7 @@ Cannot fill $_exitsignal with the correct signal number.\n")); singlestep_breakpoints_inserted_p = 0; } - if (stepped_after_stopped_by_watchpoint) + if (ecs->stepped_after_stopped_by_watchpoint) stopped_by_watchpoint = 0; else stopped_by_watchpoint = watchpoints_triggered (&ecs->ws); @@ -4167,6 +4183,7 @@ Cannot fill $_exitsignal with the correct signal number.\n")); /* This is originated from start_remote(), start_inferior() and shared libraries hook functions. */ + stop_soon = get_inferior_stop_soon (ecs->ptid); if (stop_soon == STOP_QUIETLY || stop_soon == STOP_QUIETLY_REMOTE) { if (debug_infrun) |