/* Target-struct-independent code to start (run) and stop an inferior
process.
- Copyright (C) 1986-2015 Free Software Foundation, Inc.
+ Copyright (C) 1986-2016 Free Software Foundation, Inc.
This file is part of GDB.
/* Detach new forked process? */
if (detach_fork)
{
- struct cleanup *old_chain;
-
/* Before detaching from the child, remove all breakpoints
from it. If we forked, then this has already been taken
care of by infrun.c. If we vforked however, any
/* The instruction being stepped over triggers a nonsteppable
watchpoint. If true, we'll skip inserting watchpoints. */
int nonsteppable_watchpoint_p;
+
+ /* The thread's global number. */
+ int thread;
};
/* The step-over info of the location that is being stepped over.
static void
set_step_over_info (struct address_space *aspace, CORE_ADDR address,
- int nonsteppable_watchpoint_p)
+ int nonsteppable_watchpoint_p,
+ int thread)
{
step_over_info.aspace = aspace;
step_over_info.address = address;
step_over_info.nonsteppable_watchpoint_p = nonsteppable_watchpoint_p;
+ step_over_info.thread = thread;
}
/* Called when we're not longer stepping over a breakpoint / an
step_over_info.aspace = NULL;
step_over_info.address = 0;
step_over_info.nonsteppable_watchpoint_p = 0;
+ step_over_info.thread = -1;
}
/* See infrun.h. */
/* See infrun.h. */
int
+thread_is_stepping_over_breakpoint (int thread)
+{
+ return (step_over_info.thread != -1
+ && thread == step_over_info.thread);
+}
+
+/* See infrun.h. */
+
+int
stepping_past_nonsteppable_watchpoint (void)
{
return step_over_info.nonsteppable_watchpoint_p;
{
struct displaced_step_inferior_state *displaced_state;
- if (ex.error != MEMORY_ERROR)
+ if (ex.error != MEMORY_ERROR
+ && ex.error != NOT_SUPPORTED_ERROR)
throw_exception (ex);
if (debug_infrun)
static void
infrun_thread_ptid_changed (ptid_t old_ptid, ptid_t new_ptid)
{
- struct displaced_step_request *it;
struct displaced_step_inferior_state *displaced;
if (ptid_equal (inferior_ptid, old_ptid))
stop_all_threads ();
set_step_over_info (get_regcache_aspace (regcache),
- regcache_read_pc (regcache), 0);
+ regcache_read_pc (regcache), 0, tp->global_num);
step = maybe_software_singlestep (gdbarch, pc);
static step_over_what
thread_still_needs_step_over (struct thread_info *tp)
{
- struct inferior *inf = find_inferior_ptid (tp->ptid);
step_over_what what = 0;
if (thread_still_needs_step_over_bp (tp))
{
enum gdb_signal sig;
struct regcache *regcache;
- struct address_space *aspace;
if (debug_infrun)
{
parent = ecs->ptid;
child = ecs->ws.value.related_pid;
+ /* At this point, the parent is marked running, and the
+ child is marked stopped. */
+
+ /* If not resuming the parent, mark it stopped. */
+ if (follow_child && !detach_fork && !non_stop && !sched_multi)
+ set_running (parent, 0);
+
+ /* If resuming the child, mark it running. */
+ if (follow_child || (!detach_fork && (non_stop || sched_multi)))
+ set_running (child, 1);
+
/* In non-stop mode, also resume the other branch. */
if (!detach_fork && (non_stop
|| (sched_multi && target_is_non_stop_p ())))
restart_threads (struct thread_info *event_thread)
{
struct thread_info *tp;
- struct thread_info *step_over = NULL;
/* In case the instruction just stepped spawned a new thread. */
update_thread_list ();
context_switch (ecs->ptid);
if (deprecated_context_hook)
- deprecated_context_hook (pid_to_thread_id (ecs->ptid));
+ deprecated_context_hook (ptid_to_global_thread_id (ecs->ptid));
}
/* At this point, get hold of the now-current thread's frame. */
keep_going_stepped_thread (struct thread_info *tp)
{
struct frame_info *frame;
- struct gdbarch *gdbarch;
struct execution_control_state ecss;
struct execution_control_state *ecs = &ecss;
stop_pc = regcache_read_pc (get_thread_regcache (tp->ptid));
frame = get_current_frame ();
- gdbarch = get_frame_arch (frame);
/* If the PC of the thread we were trying to single-step has
changed, then that thread has trapped or been signaled, but the
/* set_momentary_breakpoint_at_pc invalidates FRAME. */
frame = NULL;
- bp->thread = tp->num;
+ bp->thread = tp->global_num;
inferior_thread ()->control.exception_resume_breakpoint = bp;
}
}
bp = set_momentary_breakpoint_at_pc (get_frame_arch (frame),
handler, bp_exception_resume);
- bp->thread = tp->num;
+ bp->thread = tp->global_num;
inferior_thread ()->control.exception_resume_breakpoint = bp;
}
&& (remove_wps || !use_displaced_stepping (ecs->event_thread)))
{
set_step_over_info (get_regcache_aspace (regcache),
- regcache_read_pc (regcache), remove_wps);
+ regcache_read_pc (regcache), remove_wps,
+ ecs->event_thread->global_num);
}
else if (remove_wps)
- set_step_over_info (NULL, 0, remove_wps);
+ set_step_over_info (NULL, 0, remove_wps, -1);
/* If we now need to do an in-line step-over, we need to stop
all other threads. Note this must be done before
}
}
+/* Some targets/architectures can do extra processing/display of
+ segmentation faults. E.g., Intel MPX boundary faults.
+ Call the architecture dependent function to handle the fault. */
+
+static void
+handle_segmentation_fault (struct ui_out *uiout)
+{
+ struct regcache *regcache = get_current_regcache ();
+ struct gdbarch *gdbarch = get_regcache_arch (regcache);
+
+ if (gdbarch_handle_segmentation_fault_p (gdbarch))
+ gdbarch_handle_segmentation_fault (gdbarch, uiout);
+}
+
void
print_signal_received_reason (struct ui_out *uiout, enum gdb_signal siggnal)
{
+ struct thread_info *thr = inferior_thread ();
+
annotate_signal ();
- if (siggnal == GDB_SIGNAL_0 && !ui_out_is_mi_like_p (uiout))
+ if (ui_out_is_mi_like_p (uiout))
+ ;
+ else if (show_thread_that_caused_stop ())
{
- struct thread_info *t = inferior_thread ();
+ const char *name;
- ui_out_text (uiout, "\n[");
- ui_out_field_string (uiout, "thread-name",
- target_pid_to_str (t->ptid));
- ui_out_field_fmt (uiout, "thread-id", "] #%d", t->num);
- ui_out_text (uiout, " stopped");
+ ui_out_text (uiout, "\nThread ");
+ ui_out_field_fmt (uiout, "thread-id", "%s", print_thread_id (thr));
+
+ name = thr->name != NULL ? thr->name : target_thread_name (thr);
+ if (name != NULL)
+ {
+ ui_out_text (uiout, " \"");
+ ui_out_field_fmt (uiout, "name", "%s", name);
+ ui_out_text (uiout, "\"");
+ }
}
else
+ ui_out_text (uiout, "\nProgram");
+
+ if (siggnal == GDB_SIGNAL_0 && !ui_out_is_mi_like_p (uiout))
+ ui_out_text (uiout, " stopped");
+ else
{
- ui_out_text (uiout, "\nProgram received signal ");
+ ui_out_text (uiout, " received signal ");
annotate_signal_name ();
if (ui_out_is_mi_like_p (uiout))
ui_out_field_string
annotate_signal_string ();
ui_out_field_string (uiout, "signal-meaning",
gdb_signal_to_string (siggnal));
+
+ if (siggnal == GDB_SIGNAL_SEGV)
+ handle_segmentation_fault (uiout);
+
annotate_signal_string_end ();
}
ui_out_text (uiout, ".\n");
"to change these tables.\n"));
}
-/* Check if it makes sense to read $_siginfo from the current thread
- at this point. If not, throw an error. */
-
-static void
-validate_siginfo_access (void)
-{
- /* No current inferior, no siginfo. */
- if (ptid_equal (inferior_ptid, null_ptid))
- error (_("No thread selected."));
-
- /* Don't try to read from a dead thread. */
- if (is_exited (inferior_ptid))
- error (_("The current thread has terminated"));
-
- /* ... or from a spinning thread. */
- if (is_running (inferior_ptid))
- error (_("Selected thread is running."));
-}
-
/* The $_siginfo convenience variable is a bit special. We don't know
for sure the type of the value until we actually have a chance to
fetch the data. The type can change depending on gdbarch, so it is
{
LONGEST transferred;
- validate_siginfo_access ();
+ /* If we can access registers, so can we access $_siginfo. Likewise
+ vice versa. */
+ validate_registers_access ();
transferred =
target_read (¤t_target, TARGET_OBJECT_SIGNAL_INFO,
{
LONGEST transferred;
- validate_siginfo_access ();
+ /* If we can access registers, so can we access $_siginfo. Likewise
+ vice versa. */
+ validate_registers_access ();
transferred = target_write (¤t_target,
TARGET_OBJECT_SIGNAL_INFO,