/* Low-level child interface to ttrace.
- Copyright 2004 Free Software Foundation, Inc.
+ Copyright (C) 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
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 2 of the License, or
+ 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,
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, write to the Free Software
- Foundation, Inc., 59 Temple Place - Suite 330,
- Boston, MA 02111-1307, USA. */
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
#include "defs.h"
#include "gdbcore.h"
#include "gdbthread.h"
#include "inferior.h"
-#include "observer.h"
#include "target.h"
#include "gdb_assert.h"
int count; /* Number of pages in this dictionary. */
} inf_ttrace_page_dict;
+struct inf_ttrace_private_thread_info
+{
+ int dying;
+};
+
/* Number of lwps that are currently in a system call. */
static int inf_ttrace_num_lwps_in_syscall;
if (ttrace (TT_PROC_GET_EVENT_MASK, pid, 0,
(uintptr_t)&tte, sizeof tte, 0) == -1)
- perror_with_name ("ttrace");
+ perror_with_name (("ttrace"));
tte.tte_events |= (TTEVT_SYSCALL_ENTRY | TTEVT_SYSCALL_RETURN);
if (ttrace (TT_PROC_SET_EVENT_MASK, pid, 0,
(uintptr_t)&tte, sizeof tte, 0) == -1)
- perror_with_name ("ttrace");
+ perror_with_name (("ttrace"));
if (ttrace (TT_PROC_GET_FIRST_LWP_STATE, pid, 0,
(uintptr_t)&tts, sizeof tts, 0) == -1)
- perror_with_name ("ttrace");
+ perror_with_name (("ttrace"));
if (tts.tts_flags & TTS_INSYSCALL)
inf_ttrace_num_lwps_in_syscall++;
if (ttrace (TT_PROC_GET_EVENT_MASK, pid, 0,
(uintptr_t)&tte, sizeof tte, 0) == -1)
- perror_with_name ("ttrace");
+ perror_with_name (("ttrace"));
tte.tte_events &= ~(TTEVT_SYSCALL_ENTRY | TTEVT_SYSCALL_RETURN);
if (ttrace (TT_PROC_SET_EVENT_MASK, pid, 0,
(uintptr_t)&tte, sizeof tte, 0) == -1)
- perror_with_name ("ttrace");
+ perror_with_name (("ttrace"));
inf_ttrace_num_lwps_in_syscall = 0;
}
if (ttrace (TT_PROC_GET_MPROTECT, pid, 0,
addr, 0, (uintptr_t)&prot) == -1)
- perror_with_name ("ttrace");
+ perror_with_name (("ttrace"));
page = XMALLOC (struct inf_ttrace_page);
page->addr = addr;
{
if (ttrace (TT_PROC_SET_MPROTECT, pid, 0,
addr, pagesize, prot & ~PROT_WRITE) == -1)
- perror_with_name ("ttrace");
+ perror_with_name (("ttrace"));
}
}
{
if (ttrace (TT_PROC_SET_MPROTECT, pid, 0,
addr, pagesize, page->prot) == -1)
- perror_with_name ("ttrace");
+ perror_with_name (("ttrace"));
}
inf_ttrace_page_dict.count--;
{
if (ttrace (TT_PROC_SET_MPROTECT, pid, 0,
page->addr, pagesize, page->prot & ~prot) == -1)
- perror_with_name ("ttrace");
+ perror_with_name (("ttrace"));
page = page->next;
}
}
static int
-inf_ttrace_region_size_ok_for_hw_watchpoint (int len)
+inf_ttrace_region_ok_for_hw_watchpoint (CORE_ADDR addr, int len)
{
return 1;
}
{
if (ttrace (TT_LWP_GET_STATE, pid, lwpid,
(uintptr_t)&tts, sizeof tts, 0) == -1)
- perror_with_name ("ttrace");
+ perror_with_name (("ttrace"));
if (tts.tts_event == TTEVT_SIGNAL
&& tts.tts_u.tts_signal.tts_signo == SIGBUS)
}
\f
+/* When tracking a vfork(2), we cannot detach from the parent until
+ after the child has called exec(3) or has exited. If we are still
+ attached to the parent, this variable will be set to the process ID
+ of the parent. Otherwise it will be set to zero. */
+static pid_t inf_ttrace_vfork_ppid = -1;
+
+static int
+inf_ttrace_follow_fork (struct target_ops *ops, int follow_child)
+{
+ pid_t pid, fpid;
+ lwpid_t lwpid, flwpid;
+ ttstate_t tts;
+
+ /* 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
+ || status.kind == TARGET_WAITKIND_VFORKED);
+
+ pid = ptid_get_pid (ptid);
+ lwpid = ptid_get_lwp (ptid);
+ }
+
+ /* Get all important details that core GDB doesn't (and shouldn't)
+ know about. */
+ if (ttrace (TT_LWP_GET_STATE, pid, lwpid,
+ (uintptr_t)&tts, sizeof tts, 0) == -1)
+ perror_with_name (("ttrace"));
+
+ gdb_assert (tts.tts_event == TTEVT_FORK || tts.tts_event == TTEVT_VFORK);
+
+ if (tts.tts_u.tts_fork.tts_isparent)
+ {
+ pid = tts.tts_pid;
+ lwpid = tts.tts_lwpid;
+ fpid = tts.tts_u.tts_fork.tts_fpid;
+ flwpid = tts.tts_u.tts_fork.tts_flwpid;
+ }
+ else
+ {
+ pid = tts.tts_u.tts_fork.tts_fpid;
+ lwpid = tts.tts_u.tts_fork.tts_flwpid;
+ fpid = tts.tts_pid;
+ flwpid = tts.tts_lwpid;
+ }
+
+ if (follow_child)
+ {
+ inferior_ptid = ptid_build (fpid, flwpid, 0);
+ detach_breakpoints (pid);
+
+ target_terminal_ours ();
+ fprintf_unfiltered (gdb_stdlog, _("\
+Attaching after fork to child process %ld.\n"), (long)fpid);
+ }
+ else
+ {
+ inferior_ptid = ptid_build (pid, lwpid, 0);
+ detach_breakpoints (fpid);
+
+ target_terminal_ours ();
+ fprintf_unfiltered (gdb_stdlog, _("\
+Detaching after fork from child process %ld.\n"), (long)fpid);
+ }
+
+ if (tts.tts_event == TTEVT_VFORK)
+ {
+ gdb_assert (!tts.tts_u.tts_fork.tts_isparent);
+
+ if (follow_child)
+ {
+ /* We can't detach from the parent yet. */
+ inf_ttrace_vfork_ppid = pid;
+
+ reattach_breakpoints (fpid);
+ }
+ else
+ {
+ if (ttrace (TT_PROC_DETACH, fpid, 0, 0, 0, 0) == -1)
+ perror_with_name (("ttrace"));
+
+ /* Wait till we get the TTEVT_VFORK event in the parent.
+ This indicates that the child has called exec(3) or has
+ exited and that the parent is ready to be traced again. */
+ if (ttrace_wait (pid, lwpid, TTRACE_WAITOK, &tts, sizeof tts) == -1)
+ perror_with_name (("ttrace_wait"));
+ gdb_assert (tts.tts_event == TTEVT_VFORK);
+ gdb_assert (tts.tts_u.tts_fork.tts_isparent);
+
+ reattach_breakpoints (pid);
+ }
+ }
+ else
+ {
+ gdb_assert (tts.tts_u.tts_fork.tts_isparent);
+
+ if (follow_child)
+ {
+ if (ttrace (TT_PROC_DETACH, pid, 0, 0, 0, 0) == -1)
+ perror_with_name (("ttrace"));
+ }
+ else
+ {
+ if (ttrace (TT_PROC_DETACH, fpid, 0, 0, 0, 0) == -1)
+ perror_with_name (("ttrace"));
+ }
+ }
+
+ if (follow_child)
+ {
+ /* The child will start out single-threaded. */
+ inf_ttrace_num_lwps = 0;
+ inf_ttrace_num_lwps_in_syscall = 0;
+
+ /* Reset breakpoints in the child as appropriate. */
+ follow_inferior_reset_breakpoints ();
+ }
+
+ return 0;
+}
+\f
+
/* File descriptors for pipes used as semaphores during initial
startup of an inferior. */
static int inf_ttrace_pfd1[2];
inf_ttrace_prepare (void)
{
if (pipe (inf_ttrace_pfd1) == -1)
- perror_with_name ("pipe");
+ perror_with_name (("pipe"));
if (pipe (inf_ttrace_pfd2) == -1)
{
close (inf_ttrace_pfd1[0]);
close (inf_ttrace_pfd2[0]);
- perror_with_name ("pipe");
+ perror_with_name (("pipe"));
}
}
/* "Trace me, Dr. Memory!" */
if (ttrace (TT_PROC_SETTRC, 0, 0, 0, TT_VERSION, 0) == -1)
- perror_with_name ("ttrace");
+ perror_with_name (("ttrace"));
/* Tell our parent that we are ready to be traced. */
if (write (inf_ttrace_pfd1[1], &c, sizeof c) != sizeof c)
- perror_with_name ("write");
+ perror_with_name (("write"));
/* Wait until our parent has set the initial event mask. */
if (read (inf_ttrace_pfd2[0], &c, sizeof c) != sizeof c)
- perror_with_name ("read");
+ perror_with_name (("read"));
do_cleanups (old_chain);
}
/* Wait until our child is ready to be traced. */
if (read (inf_ttrace_pfd1[0], &c, sizeof c) != sizeof c)
- perror_with_name ("read");
+ perror_with_name (("read"));
/* Set the initial event mask. */
memset (&tte, 0, sizeof (tte));
- tte.tte_events |= TTEVT_EXEC | TTEVT_EXIT;
+ tte.tte_events |= TTEVT_EXEC | TTEVT_EXIT | TTEVT_FORK | TTEVT_VFORK;
tte.tte_events |= TTEVT_LWP_CREATE | TTEVT_LWP_EXIT | TTEVT_LWP_TERMINATE;
#ifdef TTEVT_BPT_SSTEP
tte.tte_events |= TTEVT_BPT_SSTEP;
#endif
- tte.tte_opts = TTEO_NOSTRCCHLD;
+ tte.tte_opts |= TTEO_PROC_INHERIT;
if (ttrace (TT_PROC_SET_EVENT_MASK, pid, 0,
(uintptr_t)&tte, sizeof tte, 0) == -1)
- perror_with_name ("ttrace");
+ perror_with_name (("ttrace"));
/* Tell our child that we have set the initial event mask. */
if (write (inf_ttrace_pfd2[1], &c, sizeof c) != sizeof c)
- perror_with_name ("write");
+ perror_with_name (("write"));
do_cleanups (old_chain);
gdb_assert (inf_ttrace_num_lwps_in_syscall == 0);
gdb_assert (inf_ttrace_page_dict.count == 0);
gdb_assert (inf_ttrace_reenable_page_protections == 0);
+ gdb_assert (inf_ttrace_vfork_ppid == -1);
fork_inferior (exec_file, allargs, env, inf_ttrace_me, inf_ttrace_him,
inf_ttrace_prepare, NULL);
-
- /* We are at the first instruction we care about. */
- observer_notify_inferior_created (¤t_target, from_tty);
-
- /* Pedal to the metal... */
- proceed ((CORE_ADDR) -1, TARGET_SIGNAL_0, 0);
-}
-
-static void
-inf_ttrace_kill_inferior (void)
-{
- pid_t pid = ptid_get_pid (inferior_ptid);
-
- if (pid == 0)
- return;
-
- if (ttrace (TT_PROC_EXIT, pid, 0, 0, 0, 0) == -1)
- perror_with_name ("ttrace");
- /* ??? Is it necessary to call ttrace_wait() here? */
- target_mourn_inferior ();
}
static void
ttevent_t tte;
if (!args)
- error_no_arg ("process-id to attach");
+ error_no_arg (_("process-id to attach"));
dummy = args;
pid = strtol (args, &dummy, 0);
if (from_tty)
{
- exec_file = (char *) get_exec_file (0);
+ exec_file = get_exec_file (0);
if (exec_file)
- printf_unfiltered ("Attaching to program: %s, %s\n", exec_file,
+ printf_unfiltered (_("Attaching to program: %s, %s\n"), exec_file,
target_pid_to_str (pid_to_ptid (pid)));
else
- printf_unfiltered ("Attaching to %s\n",
+ printf_unfiltered (_("Attaching to %s\n"),
target_pid_to_str (pid_to_ptid (pid)));
gdb_flush (gdb_stdout);
gdb_assert (inf_ttrace_num_lwps == 0);
gdb_assert (inf_ttrace_num_lwps_in_syscall == 0);
+ gdb_assert (inf_ttrace_vfork_ppid == -1);
if (ttrace (TT_PROC_ATTACH, pid, 0, TT_KILL_ON_EXIT, TT_VERSION, 0) == -1)
- perror_with_name ("ttrace");
+ perror_with_name (("ttrace"));
attach_flag = 1;
/* Set the initial event mask. */
memset (&tte, 0, sizeof (tte));
- tte.tte_events |= TTEVT_EXEC | TTEVT_EXIT;
+ tte.tte_events |= TTEVT_EXEC | TTEVT_EXIT | TTEVT_FORK | TTEVT_VFORK;
tte.tte_events |= TTEVT_LWP_CREATE | TTEVT_LWP_EXIT | TTEVT_LWP_TERMINATE;
#ifdef TTEVT_BPT_SSTEP
tte.tte_events |= TTEVT_BPT_SSTEP;
#endif
- tte.tte_opts = TTEO_NOSTRCCHLD;
+ tte.tte_opts |= TTEO_PROC_INHERIT;
if (ttrace (TT_PROC_SET_EVENT_MASK, pid, 0,
(uintptr_t)&tte, sizeof tte, 0) == -1)
- perror_with_name ("ttrace");
+ perror_with_name (("ttrace"));
inferior_ptid = pid_to_ptid (pid);
push_target (ttrace_ops_hack);
-
- /* Do this first, before anything has had a chance to query the
- inferior's symbol table or similar. */
- observer_notify_inferior_created (¤t_target, from_tty);
}
static void
inf_ttrace_detach (char *args, int from_tty)
{
- int sig = 0;
pid_t pid = ptid_get_pid (inferior_ptid);
+ int sig = 0;
if (from_tty)
{
char *exec_file = get_exec_file (0);
if (exec_file == 0)
exec_file = "";
- printf_unfiltered ("Detaching from program: %s, %s\n", exec_file,
+ printf_unfiltered (_("Detaching from program: %s, %s\n"), exec_file,
target_pid_to_str (pid_to_ptid (pid)));
gdb_flush (gdb_stdout);
}
/* ??? The HP-UX 11.0 ttrace(2) manual page doesn't mention that we
can pass a signal number here. Does this really work? */
if (ttrace (TT_PROC_DETACH, pid, 0, 0, sig, 0) == -1)
- perror_with_name ("ttrace");
+ perror_with_name (("ttrace"));
+
+ if (inf_ttrace_vfork_ppid != -1)
+ {
+ if (ttrace (TT_PROC_DETACH, inf_ttrace_vfork_ppid, 0, 0, 0, 0) == -1)
+ perror_with_name (("ttrace"));
+ inf_ttrace_vfork_ppid = -1;
+ }
inf_ttrace_num_lwps = 0;
inf_ttrace_num_lwps_in_syscall = 0;
inferior_ptid = null_ptid;
}
+static void
+inf_ttrace_kill (void)
+{
+ pid_t pid = ptid_get_pid (inferior_ptid);
+
+ if (pid == 0)
+ return;
+
+ if (ttrace (TT_PROC_EXIT, pid, 0, 0, 0, 0) == -1)
+ perror_with_name (("ttrace"));
+ /* ??? Is it necessary to call ttrace_wait() here? */
+
+ if (inf_ttrace_vfork_ppid != -1)
+ {
+ if (ttrace (TT_PROC_DETACH, inf_ttrace_vfork_ppid, 0, 0, 0, 0) == -1)
+ perror_with_name (("ttrace"));
+ inf_ttrace_vfork_ppid = -1;
+ }
+
+ target_mourn_inferior ();
+}
+
static int
inf_ttrace_resume_callback (struct thread_info *info, void *arg)
{
lwpid_t lwpid = ptid_get_lwp (info->ptid);
if (ttrace (TT_LWP_CONTINUE, pid, lwpid, TT_NOPC, 0, 0) == -1)
- perror_with_name ("ttrace");
+ perror_with_name (("ttrace"));
}
return 0;
}
+static int
+inf_ttrace_delete_dying_threads_callback (struct thread_info *info, void *arg)
+{
+ if (((struct inf_ttrace_private_thread_info *)info->private)->dying == 1)
+ delete_thread (info->ptid);
+ return 0;
+}
+
static void
inf_ttrace_resume (ptid_t ptid, int step, enum target_signal signal)
{
}
if (ttrace (request, pid, lwpid, TT_NOPC, sig, 0) == -1)
- perror_with_name ("ttrace");
+ perror_with_name (("ttrace"));
if (ptid_equal (ptid, minus_one_ptid) && inf_ttrace_num_lwps > 0)
{
/* Let all the other threads run too. */
iterate_over_threads (inf_ttrace_resume_callback, NULL);
+ iterate_over_threads (inf_ttrace_delete_dying_threads_callback, NULL);
}
}
pid_t pid = ptid_get_pid (ptid);
lwpid_t lwpid = ptid_get_lwp (ptid);
ttstate_t tts;
+ struct thread_info *ti;
/* Until proven otherwise. */
ourstatus->kind = TARGET_WAITKIND_SPURIOUS;
if (pid == -1)
- pid = 0;
+ pid = lwpid = 0;
- gdb_assert (lwpid == 0 || pid != 0);
+ gdb_assert (pid != 0 || lwpid == 0);
do
{
set_sigio_trap ();
if (ttrace_wait (pid, lwpid, TTRACE_WAITOK, &tts, sizeof tts) == -1)
- perror_with_name ("ttrace_wait");
+ perror_with_name (("ttrace_wait"));
+
+ if (tts.tts_event == TTEVT_VFORK && tts.tts_u.tts_fork.tts_isparent)
+ {
+ if (inf_ttrace_vfork_ppid != -1)
+ {
+ gdb_assert (inf_ttrace_vfork_ppid == tts.tts_pid);
+
+ if (ttrace (TT_PROC_DETACH, tts.tts_pid, 0, 0, 0, 0) == -1)
+ perror_with_name (("ttrace"));
+ inf_ttrace_vfork_ppid = -1;
+ }
+
+ tts.tts_event = TTEVT_NONE;
+ }
clear_sigio_trap ();
clear_sigint_trap ();
#endif
case TTEVT_EXEC:
- /* Make it look like a breakpoint. */
- ourstatus->kind = TARGET_WAITKIND_STOPPED;
- ourstatus->value.sig = TARGET_SIGNAL_TRAP;
+ ourstatus->kind = TARGET_WAITKIND_EXECD;
+ ourstatus->value.execd_pathname =
+ xmalloc (tts.tts_u.tts_exec.tts_pathlen + 1);
+ if (ttrace (TT_PROC_GET_PATHNAME, tts.tts_pid, 0,
+ (uintptr_t)ourstatus->value.execd_pathname,
+ tts.tts_u.tts_exec.tts_pathlen, 0) == -1)
+ perror_with_name (("ttrace"));
+ ourstatus->value.execd_pathname[tts.tts_u.tts_exec.tts_pathlen] = 0;
break;
case TTEVT_EXIT:
inf_ttrace_num_lwps = 0;
break;
+ case TTEVT_FORK:
+ ourstatus->kind = TARGET_WAITKIND_FORKED;
+ ourstatus->value.related_pid = tts.tts_u.tts_fork.tts_fpid;
+
+ /* Make sure the other end of the fork is stopped too. */
+ if (ttrace_wait (tts.tts_u.tts_fork.tts_fpid,
+ tts.tts_u.tts_fork.tts_flwpid,
+ TTRACE_WAITOK, &tts, sizeof tts) == -1)
+ perror_with_name (("ttrace_wait"));
+
+ gdb_assert (tts.tts_event == TTEVT_FORK);
+ if (tts.tts_u.tts_fork.tts_isparent)
+ {
+ ptid = ptid_build (tts.tts_pid, tts.tts_lwpid, 0);
+ ourstatus->value.related_pid = tts.tts_u.tts_fork.tts_fpid;
+ }
+ break;
+
+ case TTEVT_VFORK:
+ gdb_assert (!tts.tts_u.tts_fork.tts_isparent);
+
+ ourstatus->kind = TARGET_WAITKIND_VFORKED;
+ ourstatus->value.related_pid = tts.tts_u.tts_fork.tts_fpid;
+
+ /* HACK: To avoid touching the parent during the vfork, switch
+ away from it. */
+ inferior_ptid = ptid;
+ break;
+
case TTEVT_LWP_CREATE:
lwpid = tts.tts_u.tts_thread.tts_target_lwpid;
ptid = ptid_build (tts.tts_pid, lwpid, 0);
if (inf_ttrace_num_lwps == 0)
{
/* Now that we're going to be multi-threaded, add the
- origional thread to the list first. */
- add_thread (ptid_build (tts.tts_pid, tts.tts_lwpid, 0));
+ original thread to the list first. */
+ ti = add_thread (ptid_build (tts.tts_pid, tts.tts_lwpid, 0));
+ ti->private =
+ xmalloc (sizeof (struct inf_ttrace_private_thread_info));
+ memset (ti->private, 0,
+ sizeof (struct inf_ttrace_private_thread_info));
inf_ttrace_num_lwps++;
}
- printf_filtered ("[New %s]\n", target_pid_to_str (ptid));
- add_thread (ptid);
+ ti = add_thread (ptid);
+ ti->private =
+ xmalloc (sizeof (struct inf_ttrace_private_thread_info));
+ memset (ti->private, 0,
+ sizeof (struct inf_ttrace_private_thread_info));
inf_ttrace_num_lwps++;
ptid = ptid_build (tts.tts_pid, tts.tts_lwpid, 0);
break;
case TTEVT_LWP_EXIT:
- printf_filtered("[%s exited]\n", target_pid_to_str (ptid));
- delete_thread (ptid);
+ if (print_thread_events)
+ printf_unfiltered (_("[%s exited]\n"), target_pid_to_str (ptid));
+ ti = find_thread_pid (ptid);
+ gdb_assert (ti != NULL);
+ ((struct inf_ttrace_private_thread_info *)ti->private)->dying = 1;
inf_ttrace_num_lwps--;
+ ttrace (TT_LWP_CONTINUE, ptid_get_pid (ptid),
+ ptid_get_lwp (ptid), TT_NOPC, 0, 0);
/* If we don't return -1 here, core GDB will re-add the thread. */
ptid = minus_one_ptid;
break;
case TTEVT_LWP_TERMINATE:
lwpid = tts.tts_u.tts_thread.tts_target_lwpid;
ptid = ptid_build (tts.tts_pid, lwpid, 0);
- printf_filtered("[%s has been terminated]\n", target_pid_to_str (ptid));
- delete_thread (ptid);
+ printf_filtered(_("[%s has been terminated]\n"), target_pid_to_str (ptid));
+ ti = find_thread_pid (ptid);
+ gdb_assert (ti != NULL);
+ ((struct inf_ttrace_private_thread_info *)ti->private)->dying = 1;
inf_ttrace_num_lwps--;
ptid = ptid_build (tts.tts_pid, tts.tts_lwpid, 0);
break;
/* Make sure all threads within the process are stopped. */
if (ttrace (TT_PROC_STOP, tts.tts_pid, 0, 0, 0, 0) == -1)
- perror_with_name ("ttrace");
+ perror_with_name (("ttrace"));
/* HACK: Twiddle INFERIOR_PTID such that the initial thread of a
process isn't recognized as a new thread. */
static LONGEST
inf_ttrace_xfer_partial (struct target_ops *ops, enum target_object object,
- const char *annex, void *readbuf,
- const void *writebuf, ULONGEST offset, LONGEST len)
+ const char *annex, gdb_byte *readbuf,
+ const gdb_byte *writebuf, ULONGEST offset, LONGEST len)
{
switch (object)
{
static void
inf_ttrace_files_info (struct target_ops *ignore)
{
- printf_unfiltered ("\tUsing the running image of %s %s.\n",
- attach_flag ? "attached" : "child",
- target_pid_to_str (inferior_ptid));
+ printf_filtered (_("\tUsing the running image of %s %s.\n"),
+ attach_flag ? "attached" : "child",
+ target_pid_to_str (inferior_ptid));
}
static int
inf_ttrace_thread_alive (ptid_t ptid)
{
- return 1;
+ struct thread_info *ti;
+ ti = find_thread_pid (ptid);
+ return !(((struct inf_ttrace_private_thread_info *)ti->private)->dying);
}
static char *
{
pid_t pid = ptid_get_pid (ptid);
lwpid_t lwpid = ptid_get_lwp (ptid);
- static char buf[80];
+ static char buf[128];
- sprintf (buf, "process %ld, lwp %ld", (long)pid, (long)lwpid);
+ xsnprintf (buf, sizeof buf, "process %ld, lwp %ld",
+ (long)pid, (long)lwpid);
return buf;
}
{
struct target_ops *t = inf_child_target ();
- t->to_create_inferior = inf_ttrace_create_inferior;
- t->to_kill = inf_ttrace_kill_inferior;
- t->to_mourn_inferior = inf_ttrace_mourn_inferior;
t->to_attach = inf_ttrace_attach;
t->to_detach = inf_ttrace_detach;
t->to_resume = inf_ttrace_resume;
t->to_wait = inf_ttrace_wait;
- t->to_xfer_partial = inf_ttrace_xfer_partial;
t->to_files_info = inf_ttrace_files_info;
- t->to_thread_alive = inf_ttrace_thread_alive;
- t->to_pid_to_str = inf_ttrace_pid_to_str;
t->to_can_use_hw_breakpoint = inf_ttrace_can_use_hw_breakpoint;
- t->to_region_size_ok_for_hw_watchpoint =
- inf_ttrace_region_size_ok_for_hw_watchpoint;
t->to_insert_watchpoint = inf_ttrace_insert_watchpoint;
t->to_remove_watchpoint = inf_ttrace_remove_watchpoint;
t->to_stopped_by_watchpoint = inf_ttrace_stopped_by_watchpoint;
+ t->to_region_ok_for_hw_watchpoint =
+ inf_ttrace_region_ok_for_hw_watchpoint;
+ t->to_kill = inf_ttrace_kill;
+ t->to_create_inferior = inf_ttrace_create_inferior;
+ t->to_follow_fork = inf_ttrace_follow_fork;
+ t->to_mourn_inferior = inf_ttrace_mourn_inferior;
+ t->to_thread_alive = inf_ttrace_thread_alive;
+ t->to_pid_to_str = inf_ttrace_pid_to_str;
+ t->to_xfer_partial = inf_ttrace_xfer_partial;
ttrace_ops_hack = t;
return t;