/* Variables that describe the inferior process running under GDB:
Where it is, why it stopped, and how to step it.
- Copyright (C) 1986-2019 Free Software Foundation, Inc.
+ Copyright (C) 1986-2022 Free Software Foundation, Inc.
This file is part of GDB.
#if !defined (INFERIOR_H)
#define INFERIOR_H 1
+#include <exception>
+#include <list>
+
struct target_waitstatus;
struct frame_info;
struct ui_file;
struct ui_out;
struct terminal_info;
struct target_desc_info;
-struct continuation;
struct inferior;
struct thread_info;
#include "symfile-add-flags.h"
#include "gdbsupport/refcounted-object.h"
#include "gdbsupport/forward-scope-exit.h"
+#include "gdbsupport/gdb_unique_ptr.h"
+#include "gdbsupport/intrusive_list.h"
#include "gdbsupport/common-inferior.h"
#include "gdbthread.h"
+#include "process-stratum-target.h"
+#include "displaced-stepping.h"
+
+#include <unordered_map>
+
struct infcall_suspend_state;
struct infcall_control_state;
/* If we are restoring the inferior state due to an exception,
some error message will be printed. So, only warn the user
when we cannot restore during normal execution. */
- if (!std::uncaught_exception ())
+ bool unwinding;
+#if __cpp_lib_uncaught_exceptions
+ unwinding = std::uncaught_exceptions () > 0;
+#else
+ unwinding = std::uncaught_exception ();
+#endif
+ if (!unwinding)
warning (_("Failed to restore inferior state: %s"), e.what ());
}
}
extern void clear_sigint_trap (void);
-/* Set/get file name for default use for standard in/out in the inferior. */
-
-extern void set_inferior_io_terminal (const char *terminal_name);
-extern const char *get_inferior_io_terminal (void);
-
/* Collected pid, tid, etc. of the debugged inferior. When there's
no inferior, inferior_ptid.pid () will be 0. */
extern void child_terminal_info (struct target_ops *self, const char *, int);
-extern void info_terminal_command (char *, int);
-
extern void child_terminal_ours (struct target_ops *self);
extern void child_terminal_ours_for_output (struct target_ops *self);
STARTUP_INFERIOR. */
extern ptid_t gdb_startup_inferior (pid_t pid, int num_traps);
-extern char *construct_inferior_arguments (int, char **);
-
/* From infcmd.c */
/* Initial inferior setup. Determines the exec file is not yet known,
extern void setup_inferior (int from_tty);
-extern void post_create_inferior (struct target_ops *, int);
+extern void post_create_inferior (int from_tty);
extern void attach_command (const char *, int);
-extern const char *get_inferior_args (void);
-
-extern void set_inferior_args (const char *);
-
extern void set_inferior_args_vector (int, char **);
extern void registers_info (const char *, int);
extern void continue_1 (int all_threads);
-extern void interrupt_target_1 (int all_threads);
+extern void interrupt_target_1 (bool all_threads);
using delete_longjmp_breakpoint_cleanup
= FORWARD_SCOPE_EXIT (delete_longjmp_breakpoint);
extern void detach_command (const char *, int);
-extern void notice_new_inferior (struct thread_info *, int, int);
+extern void notice_new_inferior (struct thread_info *, bool, int);
+
+/* Return the value of the result of a function at the end of a 'finish'
+ command/BP. If the result's value cannot be retrieved, return NULL.
-extern struct value *get_return_value (struct value *function,
- struct type *value_type);
+ FUNC_SYMBOL is the symbol of the function being returned from. FUNCTION is
+ a value containing the address of the function. */
+
+extern struct value *get_return_value (struct symbol *func_symbol,
+ struct value *function);
/* Prepare for execution command. TARGET is the target that will run
the command. BACKGROUND determines whether this is a foreground
extern void prepare_execution_command (struct target_ops *target,
int background);
-/* Whether to start up the debuggee under a shell.
-
- If startup-with-shell is set, GDB's "run" will attempt to start up
- the debuggee under a shell.
-
- This is in order for argument-expansion to occur. E.g.,
-
- (gdb) run *
-
- The "*" gets expanded by the shell into a list of files.
-
- While this is a nice feature, it may be handy to bypass the shell
- in some cases. To disable this feature, do "set startup-with-shell
- false".
-
- The catch-exec traps expected during start-up will be one more if
- the target is started up with a shell. */
-extern int startup_with_shell;
-
/* Nonzero if stopped due to completion of a stack dummy routine. */
extern enum stop_stack_kind stop_stack_dummy;
/* Print notices on inferior events (attach, detach, etc.), set with
`set print inferior-events'. */
-extern int print_inferior_events;
+extern bool print_inferior_events;
/* Anything but NO_STOP_QUIETLY means we expect a trap and the caller
will handle it themselves. STOP_QUIETLY is used when running in
extern void set_current_inferior (inferior *);
+/* Switch inferior (and program space) to INF, and switch to no thread
+ selected. */
+extern void switch_to_inferior_no_thread (inferior *inf);
+
/* GDB represents the state of each program execution with an object
called an inferior. An inferior typically corresponds to a process
but is more general and applies also to targets that do not have a
listed exactly once in the inferior list, so placing an inferior in
the inferior list is an implicit, not counted strong reference. */
-class inferior : public refcounted_object
+class inferior : public refcounted_object,
+ public intrusive_list_node<inferior>
{
public:
explicit inferior (int pid);
/* Returns true if we can delete this inferior. */
bool deletable () const { return refcount () == 0; }
- /* Pointer to next inferior in singly-linked list of inferiors. */
- struct inferior *next = NULL;
+ /* Push T in this inferior's target stack. */
+ void push_target (struct target_ops *t)
+ { m_target_stack.push (t); }
- /* This inferior's thread list. */
- thread_info *thread_list = nullptr;
+ /* An overload that deletes the target on failure. */
+ void push_target (target_ops_up &&t)
+ {
+ m_target_stack.push (t.get ());
+ t.release ();
+ }
+
+ /* Unpush T from this inferior's target stack. */
+ int unpush_target (struct target_ops *t);
+
+ /* Returns true if T is pushed in this inferior's target stack. */
+ bool target_is_pushed (target_ops *t)
+ { return m_target_stack.is_pushed (t); }
+
+ /* Find the target beneath T in this inferior's target stack. */
+ target_ops *find_target_beneath (const target_ops *t)
+ { return m_target_stack.find_beneath (t); }
+
+ /* Return the target at the top of this inferior's target stack. */
+ target_ops *top_target ()
+ { return m_target_stack.top (); }
+
+ /* Return the target at process_stratum level in this inferior's
+ target stack. */
+ struct process_stratum_target *process_target ()
+ { return (process_stratum_target *) m_target_stack.at (process_stratum); }
+
+ /* Return the target at STRATUM in this inferior's target stack. */
+ target_ops *target_at (enum strata stratum)
+ { return m_target_stack.at (stratum); }
+
+ bool has_execution ()
+ { return target_has_execution (this); }
+
+ /* This inferior's thread list, sorted by creation order. */
+ intrusive_list<thread_info> thread_list;
+
+ /* A map of ptid_t to thread_info*, for average O(1) ptid_t lookup.
+ Exited threads do not appear in the map. */
+ std::unordered_map<ptid_t, thread_info *, hash_ptid> ptid_thread_map;
/* Returns a range adapter covering the inferior's threads,
including exited threads. Used like this:
{ .... }
*/
inf_threads_range threads ()
- { return inf_threads_range (this->thread_list); }
+ { return inf_threads_range (this->thread_list.begin ()); }
/* Returns a range adapter covering the inferior's non-exited
threads. Used like this:
{ .... }
*/
inf_non_exited_threads_range non_exited_threads ()
- { return inf_non_exited_threads_range (this->thread_list); }
+ { return inf_non_exited_threads_range (this->thread_list.begin ()); }
/* Like inferior::threads(), but returns a range adapter that can be
used with range-for, safely. I.e., it is safe to delete the
delete f;
*/
inline safe_inf_threads_range threads_safe ()
- { return safe_inf_threads_range (this->thread_list); }
+ { return safe_inf_threads_range (this->thread_list.begin ()); }
+
+ /* Delete all threads in the thread list. If SILENT, exit threads
+ silently. */
+ void clear_thread_list (bool silent);
+
+ /* Continuations-related methods. A continuation is an std::function
+ to be called to finish the execution of a command when running
+ GDB asynchronously. A continuation is executed after any thread
+ of this inferior stops. Continuations are used by the attach
+ command and the remote target when a new inferior is detected. */
+ void add_continuation (std::function<void ()> &&cont);
+ void do_all_continuations ();
+
+ /* Set/get file name for default use for standard in/out in the inferior.
+
+ On Unix systems, we try to make TERMINAL_NAME the inferior's controlling
+ terminal.
+
+ If TERMINAL_NAME is the empty string, then the inferior inherits GDB's
+ terminal (or GDBserver's if spawning a remote process). */
+ void set_tty (std::string terminal_name);
+ const std::string &tty ();
+
+ /* Set the argument string to use when running this inferior.
+
+ An empty string can be used to represent "no arguments". */
+ void set_args (std::string args)
+ {
+ m_args = std::move (args);
+ };
+
+ /* Get the argument string to use when running this inferior.
+
+ No arguments is represented by an empty string. */
+ const std::string &args () const
+ {
+ return m_args;
+ }
+
+ /* Set the inferior current working directory.
+
+ If CWD is empty, unset the directory. */
+ void set_cwd (std::string cwd)
+ {
+ m_cwd = std::move (cwd);
+ }
+
+ /* Get the inferior current working directory.
+
+ Return an empty string if the current working directory is not
+ specified. */
+ const std::string &cwd () const
+ {
+ return m_cwd;
+ }
/* Convenient handle (GDB inferior id). Unique across all
inferiors. */
/* The program space bound to this inferior. */
struct program_space *pspace = NULL;
- /* The arguments string to use when running. */
- char *args = NULL;
-
- /* The size of elements in argv. */
- int argc = 0;
-
- /* The vector version of arguments. If ARGC is nonzero,
- then we must compute ARGS from this (via the target).
- This is always coming from main's argv and therefore
- should never be freed. */
- char **argv = NULL;
-
- /* The current working directory that will be used when starting
- this inferior. */
- gdb::unique_xmalloc_ptr<char> cwd;
-
- /* The name of terminal device to use for I/O. */
- char *terminal = NULL;
-
/* The terminal state as set by the last target_terminal::terminal_*
call. */
target_terminal_state terminal_state = target_terminal_state::is_ours;
exits or execs. */
bool pending_detach = false;
- /* True if this inferior is a vfork parent waiting for a vfork child
- not under our control to be done with the shared memory region,
- either by exiting or execing. */
- bool waiting_for_vfork_done = false;
+ /* If non-nullptr, points to a thread that called vfork and is now waiting
+ for a vfork child not under our control to be done with the shared memory
+ region, either by exiting or execing. */
+ thread_info *thread_waiting_for_vfork_done = nullptr;
/* True if we're in the process of detaching from this inferior. */
bool detaching = false;
- /* What is left to do for an execution command after any thread of
- this inferior stops. For continuations associated with a
- specific thread, see `struct thread_info'. */
- continuation *continuations = NULL;
-
/* True if setup_inferior wasn't called for this inferior yet.
Until that is done, we must not access inferior memory or
registers, as we haven't determined the target
architecture/description. */
bool needs_setup = false;
+ /* True when we are reading the library list of the inferior during an
+ attach or handling a fork child. */
+ bool in_initial_library_scan = false;
+
/* Private data used by the target vector implementation. */
std::unique_ptr<private_inferior> priv;
/* Per inferior data-pointers required by other GDB modules. */
REGISTRY_FIELDS;
+
+private:
+ /* The inferior's target stack. */
+ target_stack m_target_stack;
+
+ /* The name of terminal device to use for I/O. */
+ std::string m_terminal;
+
+ /* The list of continuations. */
+ std::list<std::function<void ()>> m_continuations;
+
+ /* The arguments string to use when running. */
+ std::string m_args;
+
+ /* The current working directory that will be used when starting
+ this inferior. */
+ std::string m_cwd;
};
/* Keep a registry of per-inferior data-pointers required by other GDB
extern void inferior_appeared (struct inferior *inf, int pid);
-/* Get rid of all inferiors. */
-extern void discard_all_inferiors (void);
+/* Search function to lookup an inferior of TARG by target 'pid'. */
+extern struct inferior *find_inferior_pid (process_stratum_target *targ,
+ int pid);
-/* Search function to lookup an inferior by target 'pid'. */
-extern struct inferior *find_inferior_pid (int pid);
-
-/* Search function to lookup an inferior whose pid is equal to 'ptid.pid'. */
-extern struct inferior *find_inferior_ptid (ptid_t ptid);
+/* Search function to lookup an inferior of TARG whose pid is equal to
+ 'ptid.pid'. */
+extern struct inferior *find_inferior_ptid (process_stratum_target *targ,
+ ptid_t ptid);
/* Search function to lookup an inferior by GDB 'num'. */
extern struct inferior *find_inferior_id (int num);
extern struct inferior *
find_inferior_for_program_space (struct program_space *pspace);
-/* Inferior iterator function.
-
- Calls a callback function once for each inferior, so long as the
- callback function returns false. If the callback function returns
- true, the iteration will end and the current inferior will be
- returned. This can be useful for implementing a search for a
- inferior with arbitrary attributes, or for applying some operation
- to every inferior.
-
- It is safe to delete the iterated inferior from the callback. */
-extern struct inferior *iterate_over_inferiors (int (*) (struct inferior *,
- void *),
- void *);
-
/* Returns true if the inferior list is not empty. */
extern int have_inferiors (void);
-/* Returns the number of live inferiors (real live processes). */
-extern int number_of_live_inferiors (void);
+/* Returns the number of live inferiors running on PROC_TARGET (real
+ live processes with execution). */
+extern int number_of_live_inferiors (process_stratum_target *proc_target);
/* Returns true if there are any live inferiors in the inferior list
(not cores, not executables, real live processes). */
/* Traverse all inferiors. */
-extern struct inferior *inferior_list;
+extern intrusive_list<inferior> inferior_list;
/* Pull in the internals of the inferiors ranges and iterators. Must
be done after struct inferior is defined. */
inline all_inferiors_safe_range
all_inferiors_safe ()
{
- return {};
+ return all_inferiors_safe_range (nullptr, inferior_list);
}
/* Returns a range representing all inferiors, suitable to use with
*/
inline all_inferiors_range
-all_inferiors ()
+all_inferiors (process_stratum_target *proc_target = nullptr)
{
- return {};
+ return all_inferiors_range (proc_target, inferior_list);
}
/* Return a range that can be used to walk over all inferiors with PID
not zero, with range-for. */
inline all_non_exited_inferiors_range
-all_non_exited_inferiors ()
+all_non_exited_inferiors (process_stratum_target *proc_target = nullptr)
{
- return {};
+ return all_non_exited_inferiors_range (proc_target, inferior_list);
}
/* Prune away automatically added inferiors that aren't required
/* Print the current selected inferior. */
extern void print_selected_inferior (struct ui_out *uiout);
+/* Switch to inferior NEW_INF, a new inferior, and unless
+ NO_CONNECTION is true, push the process_stratum_target of ORG_INF
+ to NEW_INF. */
+
+extern void switch_to_inferior_and_push_target
+ (inferior *new_inf, bool no_connection, inferior *org_inf);
+
#endif /* !defined (INFERIOR_H) */