/* The method to call, if any, when a new thread is attached. */
static void (*linux_nat_new_thread) (struct lwp_info *);
+/* The method to call, if any, when a thread is destroyed. */
+static void (*linux_nat_delete_thread) (struct arch_lwp_info *);
+
/* The method to call, if any, when a new fork is attached. */
static linux_nat_new_fork_ftype *linux_nat_new_fork;
{
struct lwp_info *child_lp = NULL;
int status = W_STOPCODE (0);
- struct cleanup *old_chain;
int has_vforked;
ptid_t parent_ptid, child_ptid;
int parent_pid, child_pid;
child_pid = ptid_get_lwp (child_ptid);
/* We're already attached to the parent, by default. */
- old_chain = save_inferior_ptid ();
- inferior_ptid = child_ptid;
- child_lp = add_lwp (inferior_ptid);
+ child_lp = add_lwp (child_ptid);
child_lp->stopped = 1;
child_lp->last_resume_kind = resume_stop;
/* Detach new forked process? */
if (detach_fork)
{
- make_cleanup (delete_lwp_cleanup, child_lp);
+ struct cleanup *old_chain = make_cleanup (delete_lwp_cleanup,
+ child_lp);
if (linux_nat_prepare_to_resume != NULL)
linux_nat_prepare_to_resume (child_lp);
To work around this, single step the child process
once before detaching to clear the flags. */
+ /* Note that we consult the parent's architecture instead of
+ the child's because there's no inferior for the child at
+ this point. */
if (!gdbarch_software_single_step_p (target_thread_architecture
- (child_lp->ptid)))
+ (parent_ptid)))
{
linux_disable_event_reporting (child_pid);
if (ptrace (PTRACE_SINGLESTEP, child_pid, 0, 0) < 0)
ptrace (PTRACE_DETACH, child_pid, 0, signo);
}
- /* Resets value of inferior_ptid to parent ptid. */
do_cleanups (old_chain);
}
else
{
+ scoped_restore save_inferior_ptid
+ = make_scoped_restore (&inferior_ptid);
+ inferior_ptid = child_ptid;
+
/* Let the thread_db layer learn about this new process. */
check_for_thread_db ();
}
- do_cleanups (old_chain);
-
if (has_vforked)
{
struct lwp_info *parent_lp;
static void
lwp_free (struct lwp_info *lp)
{
- xfree (lp->arch_private);
+ /* Let the arch specific bits release arch_lwp_info. */
+ if (linux_nat_delete_thread != NULL)
+ linux_nat_delete_thread (lp->arch_private);
+ else
+ gdb_assert (lp->arch_private == NULL);
+
xfree (lp);
}
Returns a wait status for that LWP, to cache. */
static int
-linux_nat_post_attach_wait (ptid_t ptid, int first, int *signalled)
+linux_nat_post_attach_wait (ptid_t ptid, int *signalled)
{
pid_t new_pid, pid = ptid_get_lwp (ptid);
int status;
static void
linux_nat_create_inferior (struct target_ops *ops,
- char *exec_file, char *allargs, char **env,
- int from_tty)
+ const char *exec_file, const std::string &allargs,
+ char **env, int from_tty)
{
struct cleanup *restore_personality
= maybe_disable_address_space_randomization (disable_randomization);
/* Add the initial process as the first LWP to the list. */
lp = add_initial_lwp (ptid);
- status = linux_nat_post_attach_wait (lp->ptid, 1, &lp->signalled);
+ status = linux_nat_post_attach_wait (lp->ptid, &lp->signalled);
if (!WIFSTOPPED (status))
{
if (WIFEXITED (status))
{
int exit_code = WEXITSTATUS (status);
- target_terminal_ours ();
+ target_terminal::ours ();
target_mourn_inferior (inferior_ptid);
if (exit_code == 0)
error (_("Unable to attach: program exited normally."));
{
enum gdb_signal signo;
- target_terminal_ours ();
+ target_terminal::ours ();
target_mourn_inferior (inferior_ptid);
signo = gdb_signal_from_host (WTERMSIG (status));
inf_ptrace_detach_success (ops);
}
- delete_lwp (main_lwp->ptid);
}
/* Resume execution of the inferior process. If STEP is nonzero,
static int
check_stopped_by_watchpoint (struct lwp_info *lp)
{
- struct cleanup *old_chain;
-
if (linux_ops->to_stopped_by_watchpoint == NULL)
return 0;
- old_chain = save_inferior_ptid ();
+ scoped_restore save_inferior_ptid = make_scoped_restore (&inferior_ptid);
inferior_ptid = lp->ptid;
if (linux_ops->to_stopped_by_watchpoint (linux_ops))
lp->stopped_data_address_p = 0;
}
- do_cleanups (old_chain);
-
return lp->stop_reason == TARGET_STOPPED_BY_WATCHPOINT;
}
return;
regcache = get_thread_regcache (lp->ptid);
- gdbarch = get_regcache_arch (regcache);
+ gdbarch = regcache->arch ();
pc = regcache_read_pc (regcache);
sw_bp_pc = pc - gdbarch_decr_pc_after_break (gdbarch);
&& !USE_SIGTRAP_SIGINFO)
{
struct regcache *regcache = get_thread_regcache (lp->ptid);
- struct gdbarch *gdbarch = get_regcache_arch (regcache);
+ struct gdbarch *gdbarch = regcache->arch ();
int decr_pc = gdbarch_decr_pc_after_break (gdbarch);
if (decr_pc != 0)
else
{
struct regcache *regcache = get_thread_regcache (lp->ptid);
- struct gdbarch *gdbarch = get_regcache_arch (regcache);
+ struct gdbarch *gdbarch = regcache->arch ();
TRY
{
}
}
-static char *
+static const char *
linux_nat_pid_to_str (struct target_ops *ops, ptid_t ptid)
{
static char buf[64];
linux_proc_pending_signals (int pid, sigset_t *pending,
sigset_t *blocked, sigset_t *ignored)
{
- FILE *procfile;
char buffer[PATH_MAX], fname[PATH_MAX];
- struct cleanup *cleanup;
sigemptyset (pending);
sigemptyset (blocked);
sigemptyset (ignored);
xsnprintf (fname, sizeof fname, "/proc/%d/status", pid);
- procfile = gdb_fopen_cloexec (fname, "r");
+ gdb_file_up procfile = gdb_fopen_cloexec (fname, "r");
if (procfile == NULL)
error (_("Could not open %s"), fname);
- cleanup = make_cleanup_fclose (procfile);
- while (fgets (buffer, PATH_MAX, procfile) != NULL)
+ while (fgets (buffer, PATH_MAX, procfile.get ()) != NULL)
{
/* Normal queued signals are on the SigPnd line in the status
file. However, 2.6 kernels also have a "shared" pending
else if (startswith (buffer, "SigIgn:\t"))
add_line_to_sigset (buffer + 8, ignored);
}
-
- do_cleanups (cleanup);
}
static enum target_xfer_status
int pid = ptid_get_pid (inferior_ptid);
VEC(static_tracepoint_marker_p) *markers = NULL;
struct static_tracepoint_marker *marker = NULL;
- char *p = s;
+ const char *p = s;
ptid_t ptid = ptid_build (pid, 0, 0);
/* Pause all */
set_sigint_trap ();
}
-/* target_terminal_ours implementation.
+/* target_terminal::ours implementation.
This is a wrapper around child_terminal_ours to add async support (and
- implement the target_terminal_ours vs target_terminal_ours_for_output
+ implement the target_terminal::ours vs target_terminal::ours_for_output
distinction). child_terminal_ours is currently no different than
child_terminal_ours_for_output.
- We leave target_terminal_ours_for_output alone, leaving it to
+ We leave target_terminal::ours_for_output alone, leaving it to
child_terminal_ours_for_output. */
static void
linux_nat_new_thread = new_thread;
}
+/* Register a method to call whenever a new thread is attached. */
+void
+linux_nat_set_delete_thread (struct target_ops *t,
+ void (*delete_thread) (struct arch_lwp_info *))
+{
+ /* Save the pointer. We only support a single registered instance
+ of the GNU/Linux native target, so we do not need to map this to
+ T. */
+ linux_nat_delete_thread = delete_thread;
+}
+
/* See declaration in linux-nat.h. */
void
return inferior_ptid;
}
-/* Provide a prototype to silence -Wmissing-prototypes. */
-extern initialize_file_ftype _initialize_linux_nat;
-
void
_initialize_linux_nat (void)
{