X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;f=gdb%2Finf-ttrace.c;h=680b89632f595332b1ed481ef58e6303227f6280;hb=5436304513349c5447b61f8b5ed6c38d77c5f0d9;hp=41393550573e638238ccca1b635bb44773508a35;hpb=5d426ff1d313c5f09f70a2c5e430b4d287ab232d;p=deliverable%2Fbinutils-gdb.git diff --git a/gdb/inf-ttrace.c b/gdb/inf-ttrace.c index 4139355057..680b89632f 100644 --- a/gdb/inf-ttrace.c +++ b/gdb/inf-ttrace.c @@ -1,12 +1,13 @@ /* Low-level child interface to ttrace. - Copyright 2004, 2005 Free Software Foundation, Inc. + Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009 + 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, @@ -15,9 +16,7 @@ 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 . */ #include "defs.h" @@ -29,13 +28,13 @@ #include "gdbcore.h" #include "gdbthread.h" #include "inferior.h" -#include "observer.h" #include "target.h" #include "gdb_assert.h" #include "gdb_string.h" #include #include +#include #include "inf-child.h" #include "inf-ttrace.h" @@ -79,6 +78,11 @@ struct inf_ttrace_page_dict 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; @@ -360,7 +364,7 @@ inf_ttrace_can_use_hw_breakpoint (int type, int len, int ot) } 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; } @@ -404,11 +408,15 @@ inf_ttrace_stopped_by_watchpoint (void) static pid_t inf_ttrace_vfork_ppid = -1; static int -inf_ttrace_follow_fork (int follow_child) +inf_ttrace_follow_fork (struct target_ops *ops, int follow_child) { pid_t pid, fpid; lwpid_t lwpid, flwpid; ttstate_t tts; + struct thread_info *last_tp = NULL; + struct breakpoint *step_resume_breakpoint = NULL; + CORE_ADDR step_range_start = 0, step_range_end = 0; + struct frame_id step_frame_id = null_frame_id; /* FIXME: kettenis/20050720: This stuff should really be passed as an argument by our caller. */ @@ -422,6 +430,7 @@ inf_ttrace_follow_fork (int follow_child) pid = ptid_get_pid (ptid); lwpid = ptid_get_lwp (ptid); + last_tp = find_thread_pid (ptid); } /* Get all important details that core GDB doesn't (and shouldn't) @@ -449,7 +458,18 @@ inf_ttrace_follow_fork (int follow_child) if (follow_child) { + /* Copy user stepping state to the new inferior thread. */ + step_resume_breakpoint = last_tp->step_resume_breakpoint; + step_range_start = last_tp->step_range_start; + step_range_end = last_tp->step_range_end; + step_frame_id = last_tp->step_frame_id; + + /* Otherwise, deleting the parent would get rid of this + breakpoint. */ + last_tp->step_resume_breakpoint = NULL; + inferior_ptid = ptid_build (fpid, flwpid, 0); + add_inferior (fpid); detach_breakpoints (pid); target_terminal_ours (); @@ -511,10 +531,28 @@ Detaching after fork from child process %ld.\n"), (long)fpid); if (follow_child) { + struct thread_info *ti; + /* The child will start out single-threaded. */ - inf_ttrace_num_lwps = 0; + inf_ttrace_num_lwps = 1; inf_ttrace_num_lwps_in_syscall = 0; + /* Delete parent. */ + delete_thread_silent (ptid_build (pid, lwpid, 0)); + detach_inferior (pid); + + /* Add child thread. inferior_ptid was already set above. */ + ti = add_thread_silent (inferior_ptid); + ti->private = + xmalloc (sizeof (struct inf_ttrace_private_thread_info)); + memset (ti->private, 0, + sizeof (struct inf_ttrace_private_thread_info)); + + ti->step_resume_breakpoint = step_resume_breakpoint; + ti->step_range_start = step_range_start; + ti->step_range_end = step_range_end; + ti->step_frame_id = step_frame_id; + /* Reset breakpoints in the child as appropriate. */ follow_inferior_reset_breakpoints (); } @@ -625,8 +663,8 @@ inf_ttrace_him (int pid) } static void -inf_ttrace_create_inferior (char *exec_file, char *allargs, char **env, - int from_tty) +inf_ttrace_create_inferior (struct target_ops *ops, char *exec_file, + char *allargs, char **env, int from_tty) { gdb_assert (inf_ttrace_num_lwps == 0); gdb_assert (inf_ttrace_num_lwps_in_syscall == 0); @@ -636,38 +674,10 @@ inf_ttrace_create_inferior (char *exec_file, char *allargs, char **env, 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 -inf_ttrace_mourn_inferior (void) +inf_ttrace_mourn_inferior (struct target_ops *ops) { const int num_buckets = ARRAY_SIZE (inf_ttrace_page_dict.buckets); int bucket; @@ -695,12 +705,13 @@ inf_ttrace_mourn_inferior (void) } static void -inf_ttrace_attach (char *args, int from_tty) +inf_ttrace_attach (struct target_ops *ops, char *args, int from_tty) { char *exec_file; pid_t pid; char *dummy; ttevent_t tte; + struct inferior *inf; if (!args) error_no_arg (_("process-id to attach")); @@ -715,7 +726,7 @@ inf_ttrace_attach (char *args, int from_tty) 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, @@ -733,7 +744,9 @@ inf_ttrace_attach (char *args, int from_tty) if (ttrace (TT_PROC_ATTACH, pid, 0, TT_KILL_ON_EXIT, TT_VERSION, 0) == -1) perror_with_name (("ttrace")); - attach_flag = 1; + + inf = add_inferior (pid); + inf->attach_flag = 1; /* Set the initial event mask. */ memset (&tte, 0, sizeof (tte)); @@ -747,16 +760,17 @@ inf_ttrace_attach (char *args, int from_tty) (uintptr_t)&tte, sizeof tte, 0) == -1) 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); + /* We'll bump inf_ttrace_num_lwps up and add the private data to the + thread as soon as we get to inf_ttrace_wait. At this point, we + don't have lwpid info yet. */ + inferior_ptid = pid_to_ptid (pid); + add_thread_silent (inferior_ptid); } static void -inf_ttrace_detach (char *args, int from_tty) +inf_ttrace_detach (struct target_ops *ops, char *args, int from_tty) { pid_t pid = ptid_get_pid (inferior_ptid); int sig = 0; @@ -788,21 +802,87 @@ inf_ttrace_detach (char *args, int from_tty) inf_ttrace_num_lwps = 0; inf_ttrace_num_lwps_in_syscall = 0; - unpush_target (ttrace_ops_hack); inferior_ptid = null_ptid; + detach_inferior (pid); + + unpush_target (ttrace_ops_hack); } -static int -inf_ttrace_resume_callback (struct thread_info *info, void *arg) +static void +inf_ttrace_kill (void) { - if (!ptid_equal (info->ptid, inferior_ptid)) + 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) { - pid_t pid = ptid_get_pid (info->ptid); - lwpid_t lwpid = ptid_get_lwp (info->ptid); + 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 (); +} + +/* Check is a dying thread is dead by now, and delete it from GDBs + thread list if so. */ +static int +inf_ttrace_delete_dead_threads_callback (struct thread_info *info, void *arg) +{ + lwpid_t lwpid; + struct inf_ttrace_private_thread_info *p; + + if (is_exited (info->ptid)) + return 0; + + lwpid = ptid_get_lwp (info->ptid); + p = (struct inf_ttrace_private_thread_info *) info->private; - if (ttrace (TT_LWP_CONTINUE, pid, lwpid, TT_NOPC, 0, 0) == -1) + /* Check if an lwp that was dying is still there or not. */ + if (p->dying && (kill (lwpid, 0) == -1)) + /* It's gone now. */ + delete_thread (info->ptid); + + return 0; +} + +/* Resume the lwp pointed to by INFO, with REQUEST, and pass it signal + SIG. */ + +static void +inf_ttrace_resume_lwp (struct thread_info *info, ttreq_t request, int sig) +{ + pid_t pid = ptid_get_pid (info->ptid); + lwpid_t lwpid = ptid_get_lwp (info->ptid); + + if (ttrace (request, pid, lwpid, TT_NOPC, sig, 0) == -1) + { + struct inf_ttrace_private_thread_info *p + = (struct inf_ttrace_private_thread_info *) info->private; + if (p->dying && errno == EPROTO) + /* This is expected, it means the dying lwp is really gone + by now. If ttrace had an event to inform the debugger + the lwp is really gone, this wouldn't be needed. */ + delete_thread (info->ptid); + else + /* This was really unexpected. */ perror_with_name (("ttrace")); } +} + +/* Callback for iterate_over_threads. */ + +static int +inf_ttrace_resume_callback (struct thread_info *info, void *arg) +{ + if (!ptid_equal (info->ptid, inferior_ptid) && !is_exited (info->ptid)) + inf_ttrace_resume_lwp (info, TT_LWP_CONTINUE, 0); return 0; } @@ -810,25 +890,25 @@ inf_ttrace_resume_callback (struct thread_info *info, void *arg) static void inf_ttrace_resume (ptid_t ptid, int step, enum target_signal signal) { - pid_t pid = ptid_get_pid (ptid); - lwpid_t lwpid = ptid_get_lwp (ptid); + int resume_all; ttreq_t request = step ? TT_LWP_SINGLE : TT_LWP_CONTINUE; int sig = target_signal_to_host (signal); + struct thread_info *info; - if (pid == -1) - { - pid = ptid_get_pid (inferior_ptid); - lwpid = ptid_get_lwp (inferior_ptid); - } + /* A specific PTID means `step only this process id'. */ + resume_all = (ptid_equal (ptid, minus_one_ptid)); - if (ttrace (request, pid, lwpid, TT_NOPC, sig, 0) == -1) - perror_with_name (("ttrace")); + /* If resuming all threads, it's the current thread that should be + handled specially. */ + if (resume_all) + ptid = inferior_ptid; - 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); - } + info = find_thread_pid (ptid); + inf_ttrace_resume_lwp (info, request, sig); + + if (resume_all) + /* Let all the other threads run too. */ + iterate_over_threads (inf_ttrace_resume_callback, NULL); } static ptid_t @@ -837,6 +917,8 @@ inf_ttrace_wait (ptid_t ptid, struct target_waitstatus *ourstatus) pid_t pid = ptid_get_pid (ptid); lwpid_t lwpid = ptid_get_lwp (ptid); ttstate_t tts; + struct thread_info *ti; + ptid_t related_ptid; /* Until proven otherwise. */ ourstatus->kind = TARGET_WAITKIND_SPURIOUS; @@ -849,7 +931,6 @@ inf_ttrace_wait (ptid_t ptid, struct target_waitstatus *ourstatus) do { set_sigint_trap (); - set_sigio_trap (); if (ttrace_wait (pid, lwpid, TTRACE_WAITOK, &tts, sizeof tts) == -1) perror_with_name (("ttrace_wait")); @@ -868,7 +949,6 @@ inf_ttrace_wait (ptid_t ptid, struct target_waitstatus *ourstatus) tts.tts_event = TTEVT_NONE; } - clear_sigio_trap (); clear_sigint_trap (); } while (tts.tts_event == TTEVT_NONE); @@ -883,6 +963,30 @@ inf_ttrace_wait (ptid_t ptid, struct target_waitstatus *ourstatus) ptid = ptid_build (tts.tts_pid, tts.tts_lwpid, 0); + if (inf_ttrace_num_lwps == 0) + { + struct thread_info *ti; + + inf_ttrace_num_lwps = 1; + + /* This is the earliest we hear about the lwp member of + INFERIOR_PTID, after an attach or fork_inferior. */ + gdb_assert (ptid_get_lwp (inferior_ptid) == 0); + + /* We haven't set the private member on the main thread yet. Do + it now. */ + ti = find_thread_pid (inferior_ptid); + gdb_assert (ti != NULL && ti->private == NULL); + ti->private = + xmalloc (sizeof (struct inf_ttrace_private_thread_info)); + memset (ti->private, 0, + sizeof (struct inf_ttrace_private_thread_info)); + + /* Notify the core that this ptid changed. This changes + inferior_ptid as well. */ + thread_change_ptid (inferior_ptid, ptid); + } + switch (tts.tts_event) { #ifdef TTEVT_BPT_SSTEP @@ -902,6 +1006,12 @@ inf_ttrace_wait (ptid_t ptid, struct target_waitstatus *ourstatus) 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; + + /* At this point, all inserted breakpoints are gone. Doing this + as soon as we detect an exec prevents the badness of deleting + a breakpoint writing the current "shadow contents" to lift + the bp. That shadow is NOT valid after an exec. */ + mark_breakpoints_out (); break; case TTEVT_EXIT: @@ -910,8 +1020,11 @@ inf_ttrace_wait (ptid_t ptid, struct target_waitstatus *ourstatus) break; case TTEVT_FORK: + related_ptid = ptid_build (tts.tts_u.tts_fork.tts_fpid, + tts.tts_u.tts_fork.tts_flwpid, 0); + ourstatus->kind = TARGET_WAITKIND_FORKED; - ourstatus->value.related_pid = tts.tts_u.tts_fork.tts_fpid; + ourstatus->value.related_pid = related_ptid; /* Make sure the other end of the fork is stopped too. */ if (ttrace_wait (tts.tts_u.tts_fork.tts_fpid, @@ -922,16 +1035,21 @@ inf_ttrace_wait (ptid_t ptid, struct target_waitstatus *ourstatus) gdb_assert (tts.tts_event == TTEVT_FORK); if (tts.tts_u.tts_fork.tts_isparent) { + related_ptid = ptid_build (tts.tts_u.tts_fork.tts_fpid, + tts.tts_u.tts_fork.tts_flwpid, 0); ptid = ptid_build (tts.tts_pid, tts.tts_lwpid, 0); - ourstatus->value.related_pid = tts.tts_u.tts_fork.tts_fpid; + ourstatus->value.related_pid = related_ptid; } break; case TTEVT_VFORK: gdb_assert (!tts.tts_u.tts_fork.tts_isparent); + related_ptid = ptid_build (tts.tts_u.tts_fork.tts_fpid, + tts.tts_u.tts_fork.tts_flwpid, 0); + ourstatus->kind = TARGET_WAITKIND_VFORKED; - ourstatus->value.related_pid = tts.tts_u.tts_fork.tts_fpid; + ourstatus->value.related_pid = related_ptid; /* HACK: To avoid touching the parent during the vfork, switch away from it. */ @@ -941,35 +1059,52 @@ inf_ttrace_wait (ptid_t ptid, struct target_waitstatus *ourstatus) 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)); - 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; + /* Let the lwp_create-caller thread continue. */ + ttrace (TT_LWP_CONTINUE, ptid_get_pid (ptid), + ptid_get_lwp (ptid), TT_NOPC, 0, 0); + /* Return without stopping the whole process. */ + ourstatus->kind = TARGET_WAITKIND_IGNORE; + return ptid; 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--; - /* If we don't return -1 here, core GDB will re-add the thread. */ - ptid = minus_one_ptid; - break; + /* Let the thread really exit. */ + ttrace (TT_LWP_CONTINUE, ptid_get_pid (ptid), + ptid_get_lwp (ptid), TT_NOPC, 0, 0); + /* Return without stopping the whole process. */ + ourstatus->kind = TARGET_WAITKIND_IGNORE; + return ptid; 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); + if (print_thread_events) + printf_unfiltered(_("[%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--; + + /* Resume the lwp_terminate-caller thread. */ ptid = ptid_build (tts.tts_pid, tts.tts_lwpid, 0); - break; + ttrace (TT_LWP_CONTINUE, ptid_get_pid (ptid), + ptid_get_lwp (ptid), TT_NOPC, 0, 0); + /* Return without stopping the whole process. */ + ourstatus->kind = TARGET_WAITKIND_IGNORE; + return ptid; case TTEVT_SIGNAL: ourstatus->kind = TARGET_WAITKIND_STOPPED; @@ -1014,10 +1149,15 @@ inf_ttrace_wait (ptid_t ptid, struct target_waitstatus *ourstatus) if (ttrace (TT_PROC_STOP, tts.tts_pid, 0, 0, 0, 0) == -1) perror_with_name (("ttrace")); - /* HACK: Twiddle INFERIOR_PTID such that the initial thread of a - process isn't recognized as a new thread. */ - if (ptid_get_lwp (inferior_ptid) == 0) - inferior_ptid = ptid; + /* Now that the whole process is stopped, check if any dying thread + is really dead by now. If a dying thread is still alive, it will + be stopped too, and will still show up in `info threads', tagged + with "(Exiting)". We could make `info threads' prune dead + threads instead via inf_ttrace_thread_alive, but doing this here + has the advantage that a frontend is notificed sooner of thread + exits. Note that a dying lwp is still alive, it still has to be + resumed, like any other lwp. */ + iterate_over_threads (inf_ttrace_delete_dead_threads_callback, NULL); return ptid; } @@ -1081,9 +1221,10 @@ inf_ttrace_xfer_partial (struct target_ops *ops, enum target_object 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)); + struct inferior *inf = current_inferior (); + printf_filtered (_("\tUsing the running image of %s %s.\n"), + inf->attach_flag ? "attached" : "child", + target_pid_to_str (inferior_ptid)); } static int @@ -1092,21 +1233,35 @@ inf_ttrace_thread_alive (ptid_t ptid) return 1; } +/* Return a string describing the state of the thread specified by + INFO. */ + static char * -inf_ttrace_pid_to_str (ptid_t ptid) +inf_ttrace_extra_thread_info (struct thread_info *info) { - if (inf_ttrace_num_lwps > 0) - { - pid_t pid = ptid_get_pid (ptid); - lwpid_t lwpid = ptid_get_lwp (ptid); - static char buf[128]; + struct inf_ttrace_private_thread_info* private = + (struct inf_ttrace_private_thread_info *) info->private; - xsnprintf (buf, sizeof buf, "process %ld, lwp %ld", - (long)pid, (long)lwpid); - return buf; - } + if (private != NULL && private->dying) + return "Exiting"; + + return NULL; +} + +static char * +inf_ttrace_pid_to_str (ptid_t ptid) +{ + pid_t pid = ptid_get_pid (ptid); + lwpid_t lwpid = ptid_get_lwp (ptid); + static char buf[128]; - return normal_pid_to_str (ptid); + if (lwpid == 0) + xsnprintf (buf, sizeof buf, "process %ld", + (long) pid); + else + xsnprintf (buf, sizeof buf, "process %ld, lwp %ld", + (long) pid, (long) lwpid); + return buf; } @@ -1115,24 +1270,25 @@ inf_ttrace_target (void) { 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_extra_thread_info = inf_ttrace_extra_thread_info; + t->to_pid_to_str = inf_ttrace_pid_to_str; + t->to_xfer_partial = inf_ttrace_xfer_partial; ttrace_ops_hack = t; return t;