/* Low-level child interface to ptrace.
Copyright (C) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1998,
- 1999, 2000, 2001, 2002, 2004, 2005, 2006, 2007, 2008, 2009
+ 1999, 2000, 2001, 2002, 2004, 2005, 2006, 2007, 2008, 2009, 2010
Free Software Foundation, Inc.
This file is part of GDB.
#include "command.h"
#include "inferior.h"
#include "inflow.h"
+#include "terminal.h"
#include "gdbcore.h"
#include "regcache.h"
{
pid_t pid, fpid;
ptrace_state_t pe;
- struct thread_info *last_tp = NULL;
- /* FIXME: kettenis/20050720: This stuff should really be passed as
- an argument by our caller. */
- {
- ptid_t ptid;
- struct target_waitstatus status;
-
- get_last_target_status (&ptid, &status);
- gdb_assert (status.kind == TARGET_WAITKIND_FORKED);
-
- pid = ptid_get_pid (ptid);
- last_tp = find_thread_pid (ptid);
- }
+ pid = ptid_get_pid (inferior_ptid);
if (ptrace (PT_GET_PROCESS_STATE, pid,
(PTRACE_TYPE_ARG3)&pe, sizeof pe) == -1)
if (follow_child)
{
- /* Copy user stepping state to the new inferior thread. */
- struct breakpoint *step_resume_breakpoint = last_tp->step_resume_breakpoint;
- CORE_ADDR step_range_start = last_tp->step_range_start;
- CORE_ADDR step_range_end = last_tp->step_range_end;
- struct frame_id step_frame_id = last_tp->step_frame_id;
- int attach_flag = find_inferior_pid (pid)->attach_flag;
- struct inferior *inf;
+ struct inferior *parent_inf, *child_inf;
struct thread_info *tp;
- /* Otherwise, deleting the parent would get rid of this
- breakpoint. */
- last_tp->step_resume_breakpoint = NULL;
+ parent_inf = find_inferior_pid (pid);
+
+ /* Add the child. */
+ child_inf = add_inferior (fpid);
+ child_inf->attach_flag = parent_inf->attach_flag;
+ copy_terminal_info (child_inf, parent_inf);
+ child_inf->pspace = parent_inf->pspace;
+ child_inf->aspace = parent_inf->aspace;
/* Before detaching from the parent, remove all breakpoints from
it. */
/* Delete the parent. */
detach_inferior (pid);
- /* Add the child. */
- inf = add_inferior (fpid);
- inf->attach_flag = attach_flag;
- tp = add_thread_silent (inferior_ptid);
-
- tp->step_resume_breakpoint = step_resume_breakpoint;
- tp->step_range_start = step_range_start;
- tp->step_range_end = step_range_end;
- tp->step_frame_id = step_frame_id;
-
- /* Reset breakpoints in the child as appropriate. */
- follow_inferior_reset_breakpoints ();
+ add_thread_silent (inferior_ptid);
}
else
{
- inferior_ptid = pid_to_ptid (pid);
-
/* Breakpoints have already been detached from the child by
infrun.c. */
if (ptrace (PT_DETACH, fpid, (PTRACE_TYPE_ARG3)1, 0) == -1)
perror_with_name (("ptrace"));
- detach_inferior (pid);
}
return 0;
{
int pid;
+ /* Do not change either targets above or the same target if already present.
+ The reason is the target stack is shared across multiple inferiors. */
+ int ops_already_pushed = target_is_pushed (ops);
+ struct cleanup *back_to = NULL;
+
+ if (! ops_already_pushed)
+ {
+ /* Clear possible core file with its process_stratum. */
+ push_target (ops);
+ back_to = make_cleanup_unpush_target (ops);
+ }
+
pid = fork_inferior (exec_file, allargs, env, inf_ptrace_me, NULL,
NULL, NULL);
- push_target (ops);
+ if (! ops_already_pushed)
+ discard_cleanups (back_to);
/* On some targets, there must be some explicit synchronization
between the parent and child processes after the debugger
only report its exit status to its original parent. */
waitpid (ptid_get_pid (inferior_ptid), &status, 0);
- unpush_target (ops);
generic_mourn_inferior ();
+
+ if (!have_inferiors ())
+ unpush_target (ops);
}
/* Attach to the process specified by ARGS. If FROM_TTY is non-zero,
{
char *exec_file;
pid_t pid;
- char *dummy;
struct inferior *inf;
- if (!args)
- error_no_arg (_("process-id to attach"));
+ /* Do not change either targets above or the same target if already present.
+ The reason is the target stack is shared across multiple inferiors. */
+ int ops_already_pushed = target_is_pushed (ops);
+ struct cleanup *back_to = NULL;
- dummy = args;
- pid = strtol (args, &dummy, 0);
- /* Some targets don't set errno on errors, grrr! */
- if (pid == 0 && args == dummy)
- error (_("Illegal process-id: %s."), args);
+ pid = parse_pid_to_attach (args);
if (pid == getpid ()) /* Trying to masturbate? */
error (_("I refuse to debug myself!"));
+ if (! ops_already_pushed)
+ {
+ /* target_pid_to_str already uses the target. Also clear possible core
+ file with its process_stratum. */
+ push_target (ops);
+ back_to = make_cleanup_unpush_target (ops);
+ }
+
if (from_tty)
{
exec_file = get_exec_file (0);
error (_("This system does not support attaching to a process"));
#endif
- inferior_ptid = pid_to_ptid (pid);
-
- inf = add_inferior (pid);
+ inf = current_inferior ();
+ inferior_appeared (inf, pid);
inf->attach_flag = 1;
+ inferior_ptid = pid_to_ptid (pid);
/* Always add a main thread. If some target extends the ptrace
target, it should decorate the ptid later with more info. */
add_thread_silent (inferior_ptid);
- push_target(ops);
+ if (! ops_already_pushed)
+ discard_cleanups (back_to);
}
#ifdef PT_GET_PROCESS_STATE
ptid_t ptid, int step, enum target_signal signal)
{
pid_t pid = ptid_get_pid (ptid);
- int request = PT_CONTINUE;
+ int request;
if (pid == -1)
/* Resume all threads. Traditionally ptrace() only supports
single-threaded processes, so simply resume the inferior. */
pid = ptid_get_pid (inferior_ptid);
+ if (catch_syscall_enabled () > 0)
+ request = PT_SYSCALL;
+ else
+ request = PT_CONTINUE;
+
if (step)
{
/* If this system does not support PT_STEP, a higher level
static ptid_t
inf_ptrace_wait (struct target_ops *ops,
- ptid_t ptid, struct target_waitstatus *ourstatus)
+ ptid_t ptid, struct target_waitstatus *ourstatus, int options)
{
pid_t pid;
int status, save_errno;