/* Low-level child interface to ttrace.
- Copyright 2004, 2005 Free Software Foundation, Inc.
+ Copyright (C) 2004, 2005, 2006, 2007 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;
}
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;
}
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? */
-
- 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 void
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,
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
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)
{
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)
{
{
/* 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;
#endif
case TTEVT_EXEC:
+ /* FIXME: kettenis/20051029: GDB doesn't really know how to deal
+ with TARGET_WAITKIND_EXECD events yet. So we make it look
+ like a SIGTRAP instead. */
+#if 0
ourstatus->kind = TARGET_WAITKIND_EXECD;
ourstatus->value.execd_pathname =
xmalloc (tts.tts_u.tts_exec.tts_pathlen + 1);
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;
+#else
+ ourstatus->kind = TARGET_WAITKIND_STOPPED;
+ ourstatus->value.sig = TARGET_SIGNAL_TRAP;
+#endif
break;
case TTEVT_EXIT:
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);
+ 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;
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);
+ 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;
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 *
{
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_follow_fork = inf_ttrace_follow_fork;
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;