mirror of
https://sourceware.org/git/binutils-gdb.git
synced 2024-12-01 05:55:23 +08:00
29f49a6a4f
* gdbthread.h (finish_thread_state, finish_thread_state_cleanup): Declare. * thread.c (finish_thread_state, finish_thread_state_cleanup): New. * infrun.c (wait_for_inferior, fetch_inferior_event): If an error is thrown while handling an event, finish the thread state. (normal_stop): Use finish_thread_state cleanup. * infcmd.c (run_command_1): If an error is thrown while starting the inferior, finish the thread state.
325 lines
12 KiB
C
325 lines
12 KiB
C
/* 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 Free Software Foundation, Inc.
|
|
Contributed by Lynx Real-Time Systems, Inc. Los Gatos, CA.
|
|
|
|
|
|
This file is part of GDB.
|
|
|
|
This program is free software; you can redistribute it and/or modify
|
|
it under the terms of the GNU General Public License as published by
|
|
the Free Software Foundation; either version 3 of the License, or
|
|
(at your option) any later version.
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with this program. If not, see <http://www.gnu.org/licenses/>. */
|
|
|
|
#ifndef GDBTHREAD_H
|
|
#define GDBTHREAD_H
|
|
|
|
struct symtab;
|
|
|
|
#include "breakpoint.h"
|
|
#include "frame.h"
|
|
#include "ui-out.h"
|
|
#include "inferior.h"
|
|
|
|
struct thread_info
|
|
{
|
|
struct thread_info *next;
|
|
ptid_t ptid; /* "Actual process id";
|
|
In fact, this may be overloaded with
|
|
kernel thread id, etc. */
|
|
int num; /* Convenient handle (GDB thread id) */
|
|
|
|
/* 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_;
|
|
|
|
/* 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
|
|
if we detect it exiting. */
|
|
int refcount;
|
|
|
|
/* User/external stepping state. */
|
|
|
|
/* Step-resume or longjmp-resume breakpoint. */
|
|
struct breakpoint *step_resume_breakpoint;
|
|
|
|
/* Range to single step within.
|
|
|
|
If this is nonzero, respond to a single-step signal by continuing
|
|
to step if the pc is in this range.
|
|
|
|
If step_range_start and step_range_end are both 1, it means to
|
|
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.). */
|
|
CORE_ADDR step_range_start; /* Inclusive */
|
|
CORE_ADDR step_range_end; /* Exclusive */
|
|
|
|
/* 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. */
|
|
struct frame_id step_frame_id;
|
|
int current_line;
|
|
struct symtab *current_symtab;
|
|
|
|
/* Internal stepping state. */
|
|
|
|
/* Record the pc of the thread the last time it stopped. This is
|
|
maintained by proceed and keep_going, and used in
|
|
adjust_pc_after_break to distinguish a hardware single-step
|
|
SIGTRAP from a breakpoint SIGTRAP. */
|
|
CORE_ADDR prev_pc;
|
|
|
|
/* Nonzero if we are presently stepping over a breakpoint.
|
|
|
|
If we hit a breakpoint or watchpoint, and then continue, we need
|
|
to single step the current thread with breakpoints disabled, to
|
|
avoid hitting the same breakpoint or watchpoint again. And we
|
|
should step just a single thread and keep other threads stopped,
|
|
so that other threads don't miss breakpoints while they are
|
|
removed.
|
|
|
|
So, this variable simultaneously means that we need to single
|
|
step the current thread, keep other threads stopped, and that
|
|
breakpoints should be removed while we step.
|
|
|
|
This variable is set either:
|
|
- in proceed, when we resume inferior on user's explicit request
|
|
- in keep_going, if handle_inferior_event decides we need to
|
|
step over breakpoint.
|
|
|
|
The variable is cleared in normal_stop. The proceed calls
|
|
wait_for_inferior, which calls handle_inferior_event in a loop,
|
|
and until wait_for_inferior exits, this variable is changed only
|
|
by keep_going. */
|
|
int trap_expected;
|
|
|
|
/* Should we step over breakpoint next time keep_going is called? */
|
|
int stepping_over_breakpoint;
|
|
|
|
/* Set to TRUE if we should finish single-stepping over a breakpoint
|
|
after hitting the current 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
|
|
target stops. Used only in asynchronous mode, by targets that
|
|
support async execution. Several execution commands use it. */
|
|
struct continuation *continuations;
|
|
|
|
/* Similar to the above, but used when a single execution command
|
|
requires several resume/stop iterations. Used by the step
|
|
command. */
|
|
struct continuation *intermediate_continuations;
|
|
|
|
/* Nonzero if the thread is being proceeded for a "finish" command
|
|
or a similar situation when stop_registers should be saved. */
|
|
int proceed_to_finish;
|
|
|
|
enum step_over_calls_kind step_over_calls;
|
|
|
|
/* Nonzero if stopped due to a step command. */
|
|
int stop_step;
|
|
|
|
/* If stepping, nonzero means step count is > 1 so don't print frame
|
|
next time inferior stops if it stops due to stepping. */
|
|
int step_multi;
|
|
|
|
/* Last signal that the inferior received (why it stopped). */
|
|
enum target_signal stop_signal;
|
|
|
|
/* Chain containing status of breakpoint(s) the thread stopped
|
|
at. */
|
|
bpstat stop_bpstat;
|
|
|
|
/* True if this thread has been explicitly requested to stop. */
|
|
int stop_requested;
|
|
|
|
/* Private data used by the target vector implementation. */
|
|
struct private_thread_info *private;
|
|
};
|
|
|
|
/* Create an empty thread list, or empty the existing one. */
|
|
extern void init_thread_list (void);
|
|
|
|
/* Add a thread to the thread list, print a message
|
|
that a new thread is found, and return the pointer to
|
|
the new thread. Caller my use this pointer to
|
|
initialize the private thread data. */
|
|
extern struct thread_info *add_thread (ptid_t ptid);
|
|
|
|
/* Same as add_thread, but does not print a message
|
|
about new thread. */
|
|
extern struct thread_info *add_thread_silent (ptid_t ptid);
|
|
|
|
/* Same as add_thread, and sets the private info. */
|
|
extern struct thread_info *add_thread_with_info (ptid_t ptid,
|
|
struct private_thread_info *);
|
|
|
|
/* Delete an existing thread list entry. */
|
|
extern void delete_thread (ptid_t);
|
|
|
|
/* Delete an existing thread list entry, and be quiet about it. Used
|
|
after the process this thread having belonged to having already
|
|
exited, for example. */
|
|
extern void delete_thread_silent (ptid_t);
|
|
|
|
/* Delete a step_resume_breakpoint from the thread database. */
|
|
extern void delete_step_resume_breakpoint (struct thread_info *);
|
|
|
|
/* 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);
|
|
|
|
/* Translate a 'pid' (which may be overloaded with extra thread information)
|
|
into the integer thread id (GDB's homegrown id, not the system's). */
|
|
extern int pid_to_thread_id (ptid_t ptid);
|
|
|
|
/* Boolean test for an already-known pid (which may be overloaded with
|
|
extra thread information). */
|
|
extern int in_thread_list (ptid_t ptid);
|
|
|
|
/* Boolean test for an already-known thread id (GDB's homegrown id,
|
|
not the system's). */
|
|
extern int valid_thread_id (int thread);
|
|
|
|
/* Search function to lookup a thread by 'pid'. */
|
|
extern struct thread_info *find_thread_pid (ptid_t ptid);
|
|
|
|
/* Find thread by GDB user-visible thread number. */
|
|
struct thread_info *find_thread_id (int num);
|
|
|
|
/* Change the ptid of thread OLD_PTID to NEW_PTID. */
|
|
void thread_change_ptid (ptid_t old_ptid, ptid_t new_ptid);
|
|
|
|
/* Iterator function to call a user-provided callback function
|
|
once for each known thread. */
|
|
typedef int (*thread_callback_func) (struct thread_info *, void *);
|
|
extern struct thread_info *iterate_over_threads (thread_callback_func, void *);
|
|
|
|
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. */
|
|
extern void set_running (ptid_t ptid, int running);
|
|
|
|
/* Marks or clears thread(s) PTID as having been requested to stop.
|
|
If PTID is MINUS_ONE_PTID, applies to all threads. If
|
|
ptid_is_pid(PTID) is true, applies to all threads of the process
|
|
pointed at by PTID. If STOP, then the THREAD_STOP_REQUESTED
|
|
observer is called with PTID as argument. */
|
|
extern void set_stop_requested (ptid_t ptid, int stop);
|
|
|
|
/* NOTE: Since the thread state is not a boolean, most times, you do
|
|
not want to check it with negation. If you really want to check if
|
|
the thread is stopped,
|
|
|
|
use (good):
|
|
|
|
if (is_stopped (ptid))
|
|
|
|
instead of (bad):
|
|
|
|
if (!is_running (ptid))
|
|
|
|
The latter also returns true on exited threads, most likelly not
|
|
what you want. */
|
|
|
|
/* Reports if in the frontend's perpective, thread PTID is running. */
|
|
extern int is_running (ptid_t ptid);
|
|
|
|
/* Is this thread listed, but known to have exited? We keep it listed
|
|
(but not visible) until it's safe to delete. */
|
|
extern int is_exited (ptid_t ptid);
|
|
|
|
/* 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 all threads.
|
|
|
|
Note that this is different from the running state. See the
|
|
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);
|
|
|
|
/* Merge the executing property of thread PTID over to its thread
|
|
state property (frontend running/stopped view).
|
|
|
|
"not executing" -> "stopped"
|
|
"executing" -> "running"
|
|
"exited" -> "exited"
|
|
|
|
If PIDGET (PTID) is -1, go over all threads.
|
|
|
|
Notifications are only emitted if the thread state did change. */
|
|
extern void finish_thread_state (ptid_t ptid);
|
|
|
|
/* Same as FINISH_THREAD_STATE, but with an interface suitable to be
|
|
registered as a cleanup. PTID_P points to the ptid_t that is
|
|
passed to FINISH_THREAD_STATE. */
|
|
extern void finish_thread_state_cleanup (void *ptid_p);
|
|
|
|
/* Commands with a prefix of `thread'. */
|
|
extern struct cmd_list_element *thread_cmd_list;
|
|
|
|
/* 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,
|
|
int pid);
|
|
|
|
extern struct cleanup *make_cleanup_restore_current_thread (void);
|
|
|
|
/* Returns a pointer into the thread_info corresponding to
|
|
INFERIOR_PTID. INFERIOR_PTID *must* be in the thread list. */
|
|
extern struct thread_info* inferior_thread (void);
|
|
|
|
#endif /* GDBTHREAD_H */
|