From 4f5d7f635cd1dd81575edb35395272ee3d535502 Mon Sep 17 00:00:00 2001 From: Pedro Alves Date: Thu, 14 Nov 2013 19:43:27 +0000 Subject: [PATCH] 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 * infrun.c (struct execution_control_state) : 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. --- gdb/ChangeLog | 12 +++++++++++ gdb/infrun.c | 59 +++++++++++++++++++++++++++++++++------------------ 2 files changed, 50 insertions(+), 21 deletions(-) diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 58e7f2e48d6..5b9428d3f27 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,15 @@ +2013-11-14 Pedro Alves + + * infrun.c (struct execution_control_state) + : 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 * break-catch-sig.c (signal_catchpoint_explains_signal): Adjust to diff --git a/gdb/infrun.c b/gdb/infrun.c index 4d26e376841..52bb0643dcd 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) -- 2.30.2