aboutsummaryrefslogtreecommitdiff
path: root/gdb
diff options
context:
space:
mode:
authorPedro Alves <palves@redhat.com>2013-11-14 19:43:27 +0000
committerPedro Alves <palves@redhat.com>2013-11-14 19:51:50 +0000
commit4f5d7f635cd1dd81575edb35395272ee3d535502 (patch)
tree3c9cb5fa87c5d0122fb8d2bfe20840b672467fdb /gdb
parent47591c29add16c520c7bc2c7ace227deeb08f4a5 (diff)
downloadgdb-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/ChangeLog12
-rw-r--r--gdb/infrun.c59
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)