/* Multi-process/thread control defs for GDB, the GNU debugger.
- Copyright (C) 1987-2014 Free Software Foundation, Inc.
+ Copyright (C) 1987-2015 Free Software Foundation, Inc.
Contributed by Lynx Real-Time Systems, Inc. Los Gatos, CA.
#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),... */
/* 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
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
int trap_expected;
/* Nonzero if the thread is being proceeded for a "finish" command
- or a similar situation when stop_registers should be saved. */
+ or a similar situation when return value should be printed. */
int proceed_to_finish;
/* Nonzero if the thread is being proceeded for an inferior function
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;
-};
-/* Inferior thread specific part of `struct infcall_suspend_state'.
+ /* 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 process counterpart is `struct inferior_suspend_state'. */
+/* Inferior thread specific part of `struct infcall_suspend_state'. */
struct thread_suspend_state
{
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;
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;
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. */
/* 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. */
/* 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);
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 ptid_get_pid (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);
-/* Marks thread PTID as executing, or not. If ptid_get_pid (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
"executing" -> "running"
"exited" -> "exited"
- If ptid_get_pid (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 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 */