/* Multi-process/thread control defs for GDB, the GNU debugger.
- Copyright (C) 1987, 1988, 1989, 1990, 1991, 1992, 1993, 1997, 1998, 1999,
- 2000, 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
+ Copyright (C) 1987-2015 Free Software Foundation, Inc.
Contributed by Lynx Real-Time Systems, Inc. Los Gatos, CA.
#include "frame.h"
#include "ui-out.h"
#include "inferior.h"
+#include "btrace.h"
+#include "common/vec.h"
+
+/* Frontend view of the thread state. Possible extensions: stepping,
+ finishing, until(ling),... */
+enum thread_state
+{
+ THREAD_STOPPED,
+ THREAD_RUNNING,
+ THREAD_EXITED,
+};
/* Inferior thread specific part of `struct infcall_control_state'.
/* Exception-resume breakpoint. */
struct breakpoint *exception_resume_breakpoint;
+ /* Breakpoints used for software single stepping. Plural, because
+ it may have multiple locations. E.g., if stepping over a
+ conditional branch instruction we can't decode the condition for,
+ we'll need to put a breakpoint at the branch destination, and
+ another at the instruction after the branch. */
+ struct breakpoint *single_step_breakpoints;
+
/* Range to single step within.
If this is nonzero, respond to a single-step signal by continuing
step for a single instruction (FIXME: it might clean up
wait_for_inferior in a minor way if this were changed to the
address of the instruction and that address plus one. But maybe
- not.). */
+ not). */
CORE_ADDR step_range_start; /* Inclusive */
CORE_ADDR step_range_end; /* Exclusive */
+ /* Function the thread was in as of last it started stepping. */
+ struct symbol *step_start_function;
+
+ /* If GDB issues a target step request, and this is nonzero, the
+ target should single-step this thread once, and then continue
+ single-stepping it without GDB core involvement as long as the
+ thread stops in the step range above. If this is zero, the
+ target should ignore the step range, and only issue one single
+ step. */
+ int may_range_step;
+
/* Stack frame address as of when stepping command was issued.
This is how we know when we step into a subroutine call, and how
to set the frame for the breakpoint used to step out. */
/* Chain containing status of breakpoint(s) the thread stopped
at. */
bpstat stop_bpstat;
+
+ /* The interpreter that issued the execution command. NULL if the
+ thread was resumed as a result of a command applied to some other
+ thread (e.g., "next" with scheduler-locking off). */
+ struct interp *command_interp;
+
+ /* Whether the command that started the thread was a stepping
+ command. This is used to decide whether "set scheduler-locking
+ step" behaves like "on" or "off". */
+ int stepping_command;
};
/* Inferior thread specific part of `struct infcall_suspend_state'.
struct thread_suspend_state
{
- /* Last signal that the inferior received (why it stopped). */
- enum target_signal stop_signal;
+ /* Last signal that the inferior received (why it stopped). When
+ the thread is resumed, this signal is delivered. Note: the
+ target should not check whether the signal is in pass state,
+ because the signal may have been explicitly passed with the
+ "signal" command, which overrides "handle nopass". If the signal
+ should be suppressed, the core will take care of clearing this
+ before the target is resumed. */
+ enum gdb_signal stop_signal;
};
+typedef struct value *value_ptr;
+DEF_VEC_P (value_ptr);
+typedef VEC (value_ptr) value_vec;
+
struct thread_info
{
struct thread_info *next;
kernel thread id, etc. */
int num; /* Convenient handle (GDB thread id) */
+ /* The name of the thread, as specified by the user. This is NULL
+ if the thread does not have a user-given name. */
+ char *name;
+
/* Non-zero means the thread is executing. Note: this is different
from saying that there is an active target and we are stopped at
a breakpoint, for instance. This is a real indicator whether the
thread is off and running. */
- /* This field is internal to thread.c. Never access it directly,
- use is_executing instead. */
- int executing_;
-
- /* Frontend view of the thread state. Note that the RUNNING/STOPPED
- states are different from EXECUTING. When the thread is stopped
- internally while handling an internal event, like a software
- single-step breakpoint, EXECUTING will be false, but running will
- still be true. As a possible future extension, this could turn
- into enum { stopped, exited, stepping, finishing, until(ling),
- running ... } */
- /* This field is internal to thread.c. Never access it directly,
- use is_running instead. */
- int state_;
+ int executing;
+
+ /* Frontend view of the thread state. Note that the THREAD_RUNNING/
+ THREAD_STOPPED states are different from EXECUTING. When the
+ thread is stopped internally while handling an internal event,
+ like a software single-step breakpoint, EXECUTING will be false,
+ but STATE will still be THREAD_RUNNING. */
+ enum thread_state state;
/* If this is > 0, then it means there's code out there that relies
on this thread being listed. Don't delete it from the lists even
SIGTRAP from a breakpoint SIGTRAP. */
CORE_ADDR prev_pc;
+ /* Did we set the thread stepping a breakpoint instruction? This is
+ used in conjunction with PREV_PC to decide whether to adjust the
+ PC. */
+ int stepped_breakpoint;
+
/* Should we step over breakpoint next time keep_going is called? */
int stepping_over_breakpoint;
+ /* Should we step over a watchpoint next time keep_going is called?
+ This is needed on targets with non-continuable, non-steppable
+ watchpoints. */
+ int stepping_over_watchpoint;
+
/* Set to TRUE if we should finish single-stepping over a breakpoint
- after hitting the current step-resume breakpoint. */
+ after hitting the current step-resume breakpoint. The context here
+ is that GDB is to do `next' or `step' while signal arrives.
+ When stepping over a breakpoint and signal arrives, GDB will attempt
+ to skip signal handler, so it inserts a step_resume_breakpoint at the
+ signal return address, and resume inferior.
+ step_after_step_resume_breakpoint is set to TRUE at this moment in
+ order to keep GDB in mind that there is still a breakpoint to step over
+ when GDB gets back SIGTRAP from step_resume_breakpoint. */
int step_after_step_resume_breakpoint;
- /* This is set TRUE when a catchpoint of a shared library event
- triggers. Since we don't wish to leave the inferior in the
- solib hook when we report the event, we step the inferior
- back to user code before stopping and reporting the event. */
- int stepping_through_solib_after_catch;
-
- /* When stepping_through_solib_after_catch is TRUE, this is a
- list of the catchpoints that should be reported as triggering
- when we finally do stop stepping. */
- bpstat stepping_through_solib_catchpoints;
-
/* Per-thread command support. */
/* Pointer to what is left to do for an execution command after the
int stop_requested;
/* The initiating frame of a nexting operation, used for deciding
- which exceptions to intercept. */
+ which exceptions to intercept. If it is null_frame_id no
+ bp_longjmp or bp_exception but longjmp has been caught just for
+ bp_longjmp_call_dummy. */
struct frame_id initiating_frame;
/* Private data used by the target vector implementation. */
- struct private_thread_info *private;
+ struct private_thread_info *priv;
/* Function that is called to free PRIVATE. If this is NULL, then
xfree will be called on PRIVATE. */
void (*private_dtor) (struct private_thread_info *);
+
+ /* Branch trace information for this thread. */
+ struct btrace_thread_info btrace;
+
+ /* Flag which indicates that the stack temporaries should be stored while
+ evaluating expressions. */
+ int stack_temporaries_enabled;
+
+ /* Values that are stored as temporaries on stack while evaluating
+ expressions. */
+ value_vec *stack_temporaries;
};
/* Create an empty thread list, or empty the existing one. */
exited, for example. */
extern void delete_thread_silent (ptid_t);
-/* Delete a step_resume_breakpoint from the thread database. */
+/* Delete a step_resume_breakpoint from the thread database. */
extern void delete_step_resume_breakpoint (struct thread_info *);
-/* Delete an exception_resume_breakpoint from the thread database. */
+/* Delete an exception_resume_breakpoint from the thread database. */
extern void delete_exception_resume_breakpoint (struct thread_info *);
+/* Delete the single-step breakpoints of thread TP, if any. */
+extern void delete_single_step_breakpoints (struct thread_info *tp);
+
+/* Check if the thread has software single stepping breakpoints
+ set. */
+extern int thread_has_single_step_breakpoints_set (struct thread_info *tp);
+
+/* Check whether the thread has software single stepping breakpoints
+ set at PC. */
+extern int thread_has_single_step_breakpoint_here (struct thread_info *tp,
+ struct address_space *aspace,
+ CORE_ADDR addr);
+
/* Translate the integer thread id (GDB's homegrown id, not the system's)
into a "pid" (which may be overloaded with extra thread information). */
extern ptid_t thread_id_to_pid (int);
returns the first thread in the list. */
struct thread_info *first_thread_of_process (int pid);
-/* Returns any thread of process PID. */
+/* Returns any thread of process PID, giving preference to the current
+ thread. */
extern struct thread_info *any_thread_of_process (int pid);
-/* Returns any non-exited thread of process PID, giving preference for
- already stopped threads. */
+/* Returns any non-exited thread of process PID, giving preference to
+ the current thread, and to not executing threads. */
extern struct thread_info *any_live_thread_of_process (int pid);
/* Change the ptid of thread OLD_PTID to NEW_PTID. */
typedef int (*thread_callback_func) (struct thread_info *, void *);
extern struct thread_info *iterate_over_threads (thread_callback_func, void *);
+/* Traverse all threads, except those that have THREAD_EXITED
+ state. */
+
+#define ALL_NON_EXITED_THREADS(T) \
+ for (T = thread_list; T; T = T->next) \
+ if ((T)->state != THREAD_EXITED)
+
+/* Traverse all threads, including those that have THREAD_EXITED
+ state. Allows deleting the currently iterated thread. */
+#define ALL_THREADS_SAFE(T, TMP) \
+ for ((T) = thread_list; \
+ (T) != NULL ? ((TMP) = (T)->next, 1): 0; \
+ (T) = (TMP))
+
extern int thread_count (void);
/* Switch from one thread to another. */
extern void switch_to_thread (ptid_t ptid);
/* Marks thread PTID is running, or stopped.
- If PIDGET (PTID) is -1, marks all threads. */
+ If PTID is minus_one_ptid, marks all threads. */
extern void set_running (ptid_t ptid, int running);
/* Marks or clears thread(s) PTID as having been requested to stop.
/* In the frontend's perpective, is this thread stopped? */
extern int is_stopped (ptid_t ptid);
-/* In the frontend's perpective is there any thread running? */
-extern int any_running (void);
-
-/* Marks thread PTID as executing, or not. If PIDGET (PTID) is -1,
+/* Marks thread PTID as executing, or not. If PTID is minus_one_ptid,
marks all threads.
Note that this is different from the running state. See the
- description of state_ and executing_ fields of struct
+ description of state and executing fields of struct
thread_info. */
extern void set_executing (ptid_t ptid, int executing);
/* Reports if thread PTID is executing. */
extern int is_executing (ptid_t ptid);
+/* True if any (known or unknown) thread is or may be executing. */
+extern int threads_are_executing (void);
+
/* Merge the executing property of thread PTID over to its thread
state property (frontend running/stopped view).
"executing" -> "running"
"exited" -> "exited"
- If PIDGET (PTID) is -1, go over all threads.
+ If PTID is minus_one_ptid, go over all threads.
Notifications are only emitted if the thread state did change. */
extern void finish_thread_state (ptid_t ptid);
/* Commands with a prefix of `thread'. */
extern struct cmd_list_element *thread_cmd_list;
+extern void thread_command (char *tidstr, int from_tty);
+
/* Print notices on thread events (attach, detach, etc.), set with
`set print thread-events'. */
extern int print_thread_events;
-extern void print_thread_info (struct ui_out *uiout, int thread,
+extern void print_thread_info (struct ui_out *uiout, char *threads,
int pid);
extern struct cleanup *make_cleanup_restore_current_thread (void);
extern void update_thread_list (void);
+/* Delete any thread the target says is no longer alive. */
+
+extern void prune_threads (void);
+
+/* Delete threads marked THREAD_EXITED. Unlike prune_threads, this
+ does not consult the target about whether the thread is alive right
+ now. */
+extern void delete_exited_threads (void);
+
+/* Return true if PC is in the stepping range of THREAD. */
+
+int pc_in_thread_step_range (CORE_ADDR pc, struct thread_info *thread);
+
+extern struct cleanup *enable_thread_stack_temporaries (ptid_t ptid);
+
+extern int thread_stack_temporaries_enabled_p (ptid_t ptid);
+
+extern void push_thread_stack_temporary (ptid_t ptid, struct value *v);
+
+extern struct value *get_last_thread_stack_temporary (ptid_t);
+
+extern int value_in_thread_stack_temporaries (struct value *, ptid_t);
+
+extern struct thread_info *thread_list;
+
#endif /* GDBTHREAD_H */