GDB (API)
/home/stan/gdb/src/gdb/inf-ttrace.c
Go to the documentation of this file.
00001 /* Low-level child interface to ttrace.
00002 
00003    Copyright (C) 2004-2013 Free Software Foundation, Inc.
00004 
00005    This file is part of GDB.
00006 
00007    This program is free software; you can redistribute it and/or modify
00008    it under the terms of the GNU General Public License as published by
00009    the Free Software Foundation; either version 3 of the License, or
00010    (at your option) any later version.
00011 
00012    This program is distributed in the hope that it will be useful,
00013    but WITHOUT ANY WARRANTY; without even the implied warranty of
00014    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015    GNU General Public License for more details.
00016 
00017    You should have received a copy of the GNU General Public License
00018    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
00019 
00020 #include "defs.h"
00021 
00022 /* The ttrace(2) system call didn't exist before HP-UX 10.30.  Don't
00023    try to compile this code unless we have it.  */
00024 #ifdef HAVE_TTRACE
00025 
00026 #include "command.h"
00027 #include "gdbcore.h"
00028 #include "gdbthread.h"
00029 #include "inferior.h"
00030 #include "terminal.h"
00031 #include "target.h"
00032 
00033 #include "gdb_assert.h"
00034 #include "gdb_string.h"
00035 #include <sys/mman.h>
00036 #include <sys/ttrace.h>
00037 #include <signal.h>
00038 
00039 #include "inf-child.h"
00040 #include "inf-ttrace.h"
00041 #include "common/filestuff.h"
00042 
00043 
00044 
00045 /* HP-UX uses a threading model where each user-space thread
00046    corresponds to a kernel thread.  These kernel threads are called
00047    lwps.  The ttrace(2) interface gives us almost full control over
00048    the threads, which makes it very easy to support them in GDB.  We
00049    identify the threads by process ID and lwp ID.  The ttrace(2) also
00050    provides us with a thread's user ID (in the `tts_user_tid' member
00051    of `ttstate_t') but we don't use that (yet) as it isn't necessary
00052    to uniquely label the thread.  */
00053 
00054 /* Number of active lwps.  */
00055 static int inf_ttrace_num_lwps;
00056 
00057 
00058 /* On HP-UX versions that have the ttrace(2) system call, we can
00059    implement "hardware" watchpoints by fiddling with the protection of
00060    pages in the address space that contain the variable being watched.
00061    In order to implement this, we keep a dictionary of pages for which
00062    we have changed the protection.  */
00063 
00064 struct inf_ttrace_page
00065 {
00066   CORE_ADDR addr;               /* Page address.  */
00067   int prot;                     /* Protection.  */
00068   int refcount;                 /* Reference count.  */
00069   struct inf_ttrace_page *next;
00070   struct inf_ttrace_page *prev;
00071 };
00072 
00073 struct inf_ttrace_page_dict
00074 {
00075   struct inf_ttrace_page buckets[128];
00076   int pagesize;                 /* Page size.  */
00077   int count;                    /* Number of pages in this dictionary.  */
00078 } inf_ttrace_page_dict;
00079 
00080 struct inf_ttrace_private_thread_info
00081 {
00082   int dying;
00083 };
00084 
00085 /* Number of lwps that are currently in a system call.  */
00086 static int inf_ttrace_num_lwps_in_syscall;
00087 
00088 /* Flag to indicate whether we should re-enable page protections after
00089    the next wait.  */
00090 static int inf_ttrace_reenable_page_protections;
00091 
00092 /* Enable system call events for process PID.  */
00093 
00094 static void
00095 inf_ttrace_enable_syscall_events (pid_t pid)
00096 {
00097   ttevent_t tte;
00098   ttstate_t tts;
00099 
00100   gdb_assert (inf_ttrace_num_lwps_in_syscall == 0);
00101 
00102   if (ttrace (TT_PROC_GET_EVENT_MASK, pid, 0,
00103               (uintptr_t)&tte, sizeof tte, 0) == -1)
00104     perror_with_name (("ttrace"));
00105 
00106   tte.tte_events |= (TTEVT_SYSCALL_ENTRY | TTEVT_SYSCALL_RETURN);
00107 
00108   if (ttrace (TT_PROC_SET_EVENT_MASK, pid, 0,
00109               (uintptr_t)&tte, sizeof tte, 0) == -1)
00110     perror_with_name (("ttrace"));
00111 
00112   if (ttrace (TT_PROC_GET_FIRST_LWP_STATE, pid, 0,
00113               (uintptr_t)&tts, sizeof tts, 0) == -1)
00114     perror_with_name (("ttrace"));
00115 
00116   if (tts.tts_flags & TTS_INSYSCALL)
00117     inf_ttrace_num_lwps_in_syscall++;
00118 
00119   /* FIXME: Handle multiple threads.  */
00120 }
00121 
00122 /* Disable system call events for process PID.  */
00123 
00124 static void
00125 inf_ttrace_disable_syscall_events (pid_t pid)
00126 {
00127   ttevent_t tte;
00128 
00129   gdb_assert (inf_ttrace_page_dict.count == 0);
00130 
00131   if (ttrace (TT_PROC_GET_EVENT_MASK, pid, 0,
00132               (uintptr_t)&tte, sizeof tte, 0) == -1)
00133     perror_with_name (("ttrace"));
00134 
00135   tte.tte_events &= ~(TTEVT_SYSCALL_ENTRY | TTEVT_SYSCALL_RETURN);
00136 
00137   if (ttrace (TT_PROC_SET_EVENT_MASK, pid, 0,
00138               (uintptr_t)&tte, sizeof tte, 0) == -1)
00139     perror_with_name (("ttrace"));
00140 
00141   inf_ttrace_num_lwps_in_syscall = 0;
00142 }
00143 
00144 /* Get information about the page at address ADDR for process PID from
00145    the dictionary.  */
00146 
00147 static struct inf_ttrace_page *
00148 inf_ttrace_get_page (pid_t pid, CORE_ADDR addr)
00149 {
00150   const int num_buckets = ARRAY_SIZE (inf_ttrace_page_dict.buckets);
00151   const int pagesize = inf_ttrace_page_dict.pagesize;
00152   int bucket;
00153   struct inf_ttrace_page *page;
00154 
00155   bucket = (addr / pagesize) % num_buckets;
00156   page = &inf_ttrace_page_dict.buckets[bucket];
00157   while (page)
00158     {
00159       if (page->addr == addr)
00160         break;
00161 
00162       page = page->next;
00163     }
00164 
00165   return page;
00166 }
00167 
00168 /* Add the page at address ADDR for process PID to the dictionary.  */
00169 
00170 static struct inf_ttrace_page *
00171 inf_ttrace_add_page (pid_t pid, CORE_ADDR addr)
00172 {
00173   const int num_buckets = ARRAY_SIZE (inf_ttrace_page_dict.buckets);
00174   const int pagesize = inf_ttrace_page_dict.pagesize;
00175   int bucket;
00176   struct inf_ttrace_page *page;
00177   struct inf_ttrace_page *prev = NULL;
00178 
00179   bucket = (addr / pagesize) % num_buckets;
00180   page = &inf_ttrace_page_dict.buckets[bucket];
00181   while (page)
00182     {
00183       if (page->addr == addr)
00184         break;
00185 
00186       prev = page;
00187       page = page->next;
00188     }
00189   
00190   if (!page)
00191     {
00192       int prot;
00193 
00194       if (ttrace (TT_PROC_GET_MPROTECT, pid, 0,
00195                   addr, 0, (uintptr_t)&prot) == -1)
00196         perror_with_name (("ttrace"));
00197       
00198       page = XMALLOC (struct inf_ttrace_page);
00199       page->addr = addr;
00200       page->prot = prot;
00201       page->refcount = 0;
00202       page->next = NULL;
00203 
00204       page->prev = prev;
00205       prev->next = page;
00206 
00207       inf_ttrace_page_dict.count++;
00208       if (inf_ttrace_page_dict.count == 1)
00209         inf_ttrace_enable_syscall_events (pid);
00210 
00211       if (inf_ttrace_num_lwps_in_syscall == 0)
00212         {
00213           if (ttrace (TT_PROC_SET_MPROTECT, pid, 0,
00214                       addr, pagesize, prot & ~PROT_WRITE) == -1)
00215             perror_with_name (("ttrace"));
00216         }
00217     }
00218 
00219   return page;
00220 }
00221 
00222 /* Insert the page at address ADDR of process PID to the dictionary.  */
00223 
00224 static void
00225 inf_ttrace_insert_page (pid_t pid, CORE_ADDR addr)
00226 {
00227   struct inf_ttrace_page *page;
00228 
00229   page = inf_ttrace_get_page (pid, addr);
00230   if (!page)
00231     page = inf_ttrace_add_page (pid, addr);
00232 
00233   page->refcount++;
00234 }
00235 
00236 /* Remove the page at address ADDR of process PID from the dictionary.  */
00237 
00238 static void
00239 inf_ttrace_remove_page (pid_t pid, CORE_ADDR addr)
00240 {
00241   const int pagesize = inf_ttrace_page_dict.pagesize;
00242   struct inf_ttrace_page *page;
00243 
00244   page = inf_ttrace_get_page (pid, addr);
00245   page->refcount--;
00246 
00247   gdb_assert (page->refcount >= 0);
00248 
00249   if (page->refcount == 0)
00250     {
00251       if (inf_ttrace_num_lwps_in_syscall == 0)
00252         {
00253           if (ttrace (TT_PROC_SET_MPROTECT, pid, 0,
00254                       addr, pagesize, page->prot) == -1)
00255             perror_with_name (("ttrace"));
00256         }
00257 
00258       inf_ttrace_page_dict.count--;
00259       if (inf_ttrace_page_dict.count == 0)
00260         inf_ttrace_disable_syscall_events (pid);
00261 
00262       page->prev->next = page->next;
00263       if (page->next)
00264         page->next->prev = page->prev;
00265 
00266       xfree (page);
00267     }
00268 }
00269 
00270 /* Mask the bits in PROT from the page protections that are currently
00271    in the dictionary for process PID.  */
00272 
00273 static void
00274 inf_ttrace_mask_page_protections (pid_t pid, int prot)
00275 {
00276   const int num_buckets = ARRAY_SIZE (inf_ttrace_page_dict.buckets);
00277   const int pagesize = inf_ttrace_page_dict.pagesize;
00278   int bucket;
00279 
00280   for (bucket = 0; bucket < num_buckets; bucket++)
00281     {
00282       struct inf_ttrace_page *page;
00283 
00284       page = inf_ttrace_page_dict.buckets[bucket].next;
00285       while (page)
00286         {
00287           if (ttrace (TT_PROC_SET_MPROTECT, pid, 0,
00288                       page->addr, pagesize, page->prot & ~prot) == -1)
00289             perror_with_name (("ttrace"));
00290 
00291           page = page->next;
00292         }
00293     }
00294 }
00295 
00296 /* Write-protect the pages in the dictionary for process PID.  */
00297 
00298 static void
00299 inf_ttrace_enable_page_protections (pid_t pid)
00300 {
00301   inf_ttrace_mask_page_protections (pid, PROT_WRITE);
00302 }
00303 
00304 /* Restore the protection of the pages in the dictionary for process
00305    PID.  */
00306 
00307 static void
00308 inf_ttrace_disable_page_protections (pid_t pid)
00309 {
00310   inf_ttrace_mask_page_protections (pid, 0);
00311 }
00312 
00313 /* Insert a "hardware" watchpoint for LEN bytes at address ADDR of
00314    type TYPE.  */
00315 
00316 static int
00317 inf_ttrace_insert_watchpoint (CORE_ADDR addr, int len, int type,
00318                               struct expression *cond)
00319 {
00320   const int pagesize = inf_ttrace_page_dict.pagesize;
00321   pid_t pid = ptid_get_pid (inferior_ptid);
00322   CORE_ADDR page_addr;
00323   int num_pages;
00324   int page;
00325 
00326   gdb_assert (type == hw_write);
00327 
00328   page_addr = (addr / pagesize) * pagesize;
00329   num_pages = (len + pagesize - 1) / pagesize;
00330 
00331   for (page = 0; page < num_pages; page++, page_addr += pagesize)
00332     inf_ttrace_insert_page (pid, page_addr);
00333 
00334   return 1;
00335 }
00336 
00337 /* Remove a "hardware" watchpoint for LEN bytes at address ADDR of
00338    type TYPE.  */
00339 
00340 static int
00341 inf_ttrace_remove_watchpoint (CORE_ADDR addr, int len, int type,
00342                               struct expression *cond)
00343 {
00344   const int pagesize = inf_ttrace_page_dict.pagesize;
00345   pid_t pid = ptid_get_pid (inferior_ptid);
00346   CORE_ADDR page_addr;
00347   int num_pages;
00348   int page;
00349 
00350   gdb_assert (type == hw_write);
00351 
00352   page_addr = (addr / pagesize) * pagesize;
00353   num_pages = (len + pagesize - 1) / pagesize;
00354 
00355   for (page = 0; page < num_pages; page++, page_addr += pagesize)
00356     inf_ttrace_remove_page (pid, page_addr);
00357 
00358   return 1;
00359 }
00360 
00361 static int
00362 inf_ttrace_can_use_hw_breakpoint (int type, int len, int ot)
00363 {
00364   return (type == bp_hardware_watchpoint);
00365 }
00366 
00367 static int
00368 inf_ttrace_region_ok_for_hw_watchpoint (CORE_ADDR addr, int len)
00369 {
00370   return 1;
00371 }
00372 
00373 /* Return non-zero if the current inferior was (potentially) stopped
00374    by hitting a "hardware" watchpoint.  */
00375 
00376 static int
00377 inf_ttrace_stopped_by_watchpoint (void)
00378 {
00379   pid_t pid = ptid_get_pid (inferior_ptid);
00380   lwpid_t lwpid = ptid_get_lwp (inferior_ptid);
00381   ttstate_t tts;
00382 
00383   if (inf_ttrace_page_dict.count > 0)
00384     {
00385       if (ttrace (TT_LWP_GET_STATE, pid, lwpid,
00386                   (uintptr_t)&tts, sizeof tts, 0) == -1)
00387         perror_with_name (("ttrace"));
00388 
00389       if (tts.tts_event == TTEVT_SIGNAL
00390           && tts.tts_u.tts_signal.tts_signo == SIGBUS)
00391         {
00392           const int pagesize = inf_ttrace_page_dict.pagesize;
00393           void *addr = tts.tts_u.tts_signal.tts_siginfo.si_addr;
00394           CORE_ADDR page_addr = ((uintptr_t)addr / pagesize) * pagesize;
00395 
00396           if (inf_ttrace_get_page (pid, page_addr))
00397             return 1;
00398         }
00399     }
00400 
00401   return 0;
00402 }
00403 
00404 
00405 /* When tracking a vfork(2), we cannot detach from the parent until
00406    after the child has called exec(3) or has exited.  If we are still
00407    attached to the parent, this variable will be set to the process ID
00408    of the parent.  Otherwise it will be set to zero.  */
00409 static pid_t inf_ttrace_vfork_ppid = -1;
00410 
00411 static int
00412 inf_ttrace_follow_fork (struct target_ops *ops, int follow_child,
00413                         int detach_fork)
00414 {
00415   pid_t pid, fpid;
00416   lwpid_t lwpid, flwpid;
00417   ttstate_t tts;
00418   struct thread_info *tp = inferior_thread ();
00419 
00420   gdb_assert (tp->pending_follow.kind == TARGET_WAITKIND_FORKED
00421               || tp->pending_follow.kind == TARGET_WAITKIND_VFORKED);
00422 
00423   pid = ptid_get_pid (inferior_ptid);
00424   lwpid = ptid_get_lwp (inferior_ptid);
00425 
00426   /* Get all important details that core GDB doesn't (and shouldn't)
00427      know about.  */
00428   if (ttrace (TT_LWP_GET_STATE, pid, lwpid,
00429               (uintptr_t)&tts, sizeof tts, 0) == -1)
00430     perror_with_name (("ttrace"));
00431 
00432   gdb_assert (tts.tts_event == TTEVT_FORK || tts.tts_event == TTEVT_VFORK);
00433 
00434   if (tts.tts_u.tts_fork.tts_isparent)
00435     {
00436       pid = tts.tts_pid;
00437       lwpid = tts.tts_lwpid;
00438       fpid = tts.tts_u.tts_fork.tts_fpid;
00439       flwpid = tts.tts_u.tts_fork.tts_flwpid;
00440     }
00441   else
00442     {
00443       pid = tts.tts_u.tts_fork.tts_fpid;
00444       lwpid = tts.tts_u.tts_fork.tts_flwpid;
00445       fpid = tts.tts_pid;
00446       flwpid = tts.tts_lwpid;
00447     }
00448 
00449   if (follow_child)
00450     {
00451       struct inferior *inf;
00452       struct inferior *parent_inf;
00453 
00454       parent_inf = find_inferior_pid (pid);
00455 
00456       inferior_ptid = ptid_build (fpid, flwpid, 0);
00457       inf = add_inferior (fpid);
00458       inf->attach_flag = parent_inf->attach_flag;
00459       inf->pspace = parent_inf->pspace;
00460       inf->aspace = parent_inf->aspace;
00461       copy_terminal_info (inf, parent_inf);
00462       detach_breakpoints (ptid_build (pid, lwpid, 0));
00463 
00464       target_terminal_ours ();
00465       fprintf_unfiltered (gdb_stdlog,
00466                           _("Attaching after fork to child process %ld.\n"),
00467                           (long)fpid);
00468     }
00469   else
00470     {
00471       inferior_ptid = ptid_build (pid, lwpid, 0);
00472       /* Detach any remaining breakpoints in the child.  In the case
00473          of fork events, we do not need to do this, because breakpoints
00474          should have already been removed earlier.  */
00475       if (tts.tts_event == TTEVT_VFORK)
00476         detach_breakpoints (ptid_build (fpid, flwpid, 0));
00477 
00478       target_terminal_ours ();
00479       fprintf_unfiltered (gdb_stdlog,
00480                           _("Detaching after fork from child process %ld.\n"),
00481                           (long)fpid);
00482     }
00483 
00484   if (tts.tts_event == TTEVT_VFORK)
00485     {
00486       gdb_assert (!tts.tts_u.tts_fork.tts_isparent);
00487 
00488       if (follow_child)
00489         {
00490           /* We can't detach from the parent yet.  */
00491           inf_ttrace_vfork_ppid = pid;
00492 
00493           reattach_breakpoints (fpid);
00494         }
00495       else
00496         {
00497           if (ttrace (TT_PROC_DETACH, fpid, 0, 0, 0, 0) == -1)
00498             perror_with_name (("ttrace"));
00499 
00500           /* Wait till we get the TTEVT_VFORK event in the parent.
00501              This indicates that the child has called exec(3) or has
00502              exited and that the parent is ready to be traced again.  */
00503           if (ttrace_wait (pid, lwpid, TTRACE_WAITOK, &tts, sizeof tts) == -1)
00504             perror_with_name (("ttrace_wait"));
00505           gdb_assert (tts.tts_event == TTEVT_VFORK);
00506           gdb_assert (tts.tts_u.tts_fork.tts_isparent);
00507 
00508           reattach_breakpoints (pid);
00509         }
00510     }
00511   else
00512     {
00513       gdb_assert (tts.tts_u.tts_fork.tts_isparent);
00514 
00515       if (follow_child)
00516         {
00517           if (ttrace (TT_PROC_DETACH, pid, 0, 0, 0, 0) == -1)
00518             perror_with_name (("ttrace"));
00519         }
00520       else
00521         {
00522           if (ttrace (TT_PROC_DETACH, fpid, 0, 0, 0, 0) == -1)
00523             perror_with_name (("ttrace"));
00524         }
00525     }
00526 
00527   if (follow_child)
00528     {
00529       struct thread_info *ti;
00530 
00531       /* The child will start out single-threaded.  */
00532       inf_ttrace_num_lwps = 1;
00533       inf_ttrace_num_lwps_in_syscall = 0;
00534 
00535       /* Delete parent.  */
00536       delete_thread_silent (ptid_build (pid, lwpid, 0));
00537       detach_inferior (pid);
00538 
00539       /* Add child thread.  inferior_ptid was already set above.  */
00540       ti = add_thread_silent (inferior_ptid);
00541       ti->private =
00542         xmalloc (sizeof (struct inf_ttrace_private_thread_info));
00543       memset (ti->private, 0,
00544               sizeof (struct inf_ttrace_private_thread_info));
00545     }
00546 
00547   return 0;
00548 }
00549 
00550 
00551 /* File descriptors for pipes used as semaphores during initial
00552    startup of an inferior.  */
00553 static int inf_ttrace_pfd1[2];
00554 static int inf_ttrace_pfd2[2];
00555 
00556 static void
00557 do_cleanup_pfds (void *dummy)
00558 {
00559   close (inf_ttrace_pfd1[0]);
00560   close (inf_ttrace_pfd1[1]);
00561   close (inf_ttrace_pfd2[0]);
00562   close (inf_ttrace_pfd2[1]);
00563 
00564   unmark_fd_no_cloexec (inf_ttrace_pfd1[0]);
00565   unmark_fd_no_cloexec (inf_ttrace_pfd1[1]);
00566   unmark_fd_no_cloexec (inf_ttrace_pfd2[0]);
00567   unmark_fd_no_cloexec (inf_ttrace_pfd2[1]);
00568 }
00569 
00570 static void
00571 inf_ttrace_prepare (void)
00572 {
00573   if (pipe (inf_ttrace_pfd1) == -1)
00574     perror_with_name (("pipe"));
00575 
00576   if (pipe (inf_ttrace_pfd2) == -1)
00577     {
00578       close (inf_ttrace_pfd1[0]);
00579       close (inf_ttrace_pfd2[0]);
00580       perror_with_name (("pipe"));
00581     }
00582 
00583   mark_fd_no_cloexec (inf_ttrace_pfd1[0]);
00584   mark_fd_no_cloexec (inf_ttrace_pfd1[1]);
00585   mark_fd_no_cloexec (inf_ttrace_pfd2[0]);
00586   mark_fd_no_cloexec (inf_ttrace_pfd2[1]);
00587 }
00588 
00589 /* Prepare to be traced.  */
00590 
00591 static void
00592 inf_ttrace_me (void)
00593 {
00594   struct cleanup *old_chain = make_cleanup (do_cleanup_pfds, 0);
00595   char c;
00596 
00597   /* "Trace me, Dr. Memory!"  */
00598   if (ttrace (TT_PROC_SETTRC, 0, 0, 0, TT_VERSION, 0) == -1)
00599     perror_with_name (("ttrace"));
00600 
00601   /* Tell our parent that we are ready to be traced.  */
00602   if (write (inf_ttrace_pfd1[1], &c, sizeof c) != sizeof c)
00603     perror_with_name (("write"));
00604 
00605   /* Wait until our parent has set the initial event mask.  */
00606   if (read (inf_ttrace_pfd2[0], &c, sizeof c) != sizeof c)
00607     perror_with_name (("read"));
00608 
00609   do_cleanups (old_chain);
00610 }
00611 
00612 /* Start tracing PID.  */
00613 
00614 static void
00615 inf_ttrace_him (struct target_ops *ops, int pid)
00616 {
00617   struct cleanup *old_chain = make_cleanup (do_cleanup_pfds, 0);
00618   ttevent_t tte;
00619   char c;
00620 
00621   /* Wait until our child is ready to be traced.  */
00622   if (read (inf_ttrace_pfd1[0], &c, sizeof c) != sizeof c)
00623     perror_with_name (("read"));
00624 
00625   /* Set the initial event mask.  */
00626   memset (&tte, 0, sizeof (tte));
00627   tte.tte_events |= TTEVT_EXEC | TTEVT_EXIT | TTEVT_FORK | TTEVT_VFORK;
00628   tte.tte_events |= TTEVT_LWP_CREATE | TTEVT_LWP_EXIT | TTEVT_LWP_TERMINATE;
00629 #ifdef TTEVT_BPT_SSTEP
00630   tte.tte_events |= TTEVT_BPT_SSTEP;
00631 #endif
00632   tte.tte_opts |= TTEO_PROC_INHERIT;
00633   if (ttrace (TT_PROC_SET_EVENT_MASK, pid, 0,
00634               (uintptr_t)&tte, sizeof tte, 0) == -1)
00635     perror_with_name (("ttrace"));
00636 
00637   /* Tell our child that we have set the initial event mask.  */
00638   if (write (inf_ttrace_pfd2[1], &c, sizeof c) != sizeof c)
00639     perror_with_name (("write"));
00640 
00641   do_cleanups (old_chain);
00642 
00643   push_target (ops);
00644 
00645   /* START_INFERIOR_TRAPS_EXPECTED is defined in inferior.h, and will
00646      be 1 or 2 depending on whether we're starting without or with a
00647      shell.  */
00648   startup_inferior (START_INFERIOR_TRAPS_EXPECTED);
00649 
00650   /* On some targets, there must be some explicit actions taken after
00651      the inferior has been started up.  */
00652   target_post_startup_inferior (pid_to_ptid (pid));
00653 }
00654 
00655 static void
00656 inf_ttrace_create_inferior (struct target_ops *ops, char *exec_file, 
00657                             char *allargs, char **env, int from_tty)
00658 {
00659   int pid;
00660 
00661   gdb_assert (inf_ttrace_num_lwps == 0);
00662   gdb_assert (inf_ttrace_num_lwps_in_syscall == 0);
00663   gdb_assert (inf_ttrace_page_dict.count == 0);
00664   gdb_assert (inf_ttrace_reenable_page_protections == 0);
00665   gdb_assert (inf_ttrace_vfork_ppid == -1);
00666 
00667   pid = fork_inferior (exec_file, allargs, env, inf_ttrace_me, NULL,
00668                        inf_ttrace_prepare, NULL, NULL);
00669 
00670   inf_ttrace_him (ops, pid);
00671 }
00672 
00673 static void
00674 inf_ttrace_mourn_inferior (struct target_ops *ops)
00675 {
00676   const int num_buckets = ARRAY_SIZE (inf_ttrace_page_dict.buckets);
00677   int bucket;
00678 
00679   inf_ttrace_num_lwps = 0;
00680   inf_ttrace_num_lwps_in_syscall = 0;
00681 
00682   for (bucket = 0; bucket < num_buckets; bucket++)
00683     {
00684       struct inf_ttrace_page *page;
00685       struct inf_ttrace_page *next;
00686 
00687       page = inf_ttrace_page_dict.buckets[bucket].next;
00688       while (page)
00689         {
00690           next = page->next;
00691           xfree (page);
00692           page = next;
00693         }
00694     }
00695   inf_ttrace_page_dict.count = 0;
00696 
00697   unpush_target (ops);
00698   generic_mourn_inferior ();
00699 }
00700 
00701 /* Assuming we just attached the debugger to a new inferior, create
00702    a new thread_info structure for each thread, and add it to our
00703    list of threads.  */
00704 
00705 static void
00706 inf_ttrace_create_threads_after_attach (int pid)
00707 {
00708   int status;
00709   ptid_t ptid;
00710   ttstate_t tts;
00711   struct thread_info *ti;
00712 
00713   status = ttrace (TT_PROC_GET_FIRST_LWP_STATE, pid, 0,
00714                    (uintptr_t) &tts, sizeof (ttstate_t), 0);
00715   if (status < 0)
00716     perror_with_name (_("TT_PROC_GET_FIRST_LWP_STATE ttrace call failed"));
00717   gdb_assert (tts.tts_pid == pid);
00718 
00719   /* Add the stopped thread.  */
00720   ptid = ptid_build (pid, tts.tts_lwpid, 0);
00721   ti = add_thread (ptid);
00722   ti->private = xzalloc (sizeof (struct inf_ttrace_private_thread_info));
00723   inf_ttrace_num_lwps++;
00724 
00725   /* We use the "first stopped thread" as the currently active thread.  */
00726   inferior_ptid = ptid;
00727 
00728   /* Iterative over all the remaining threads.  */
00729 
00730   for (;;)
00731     {
00732       ptid_t ptid;
00733 
00734       status = ttrace (TT_PROC_GET_NEXT_LWP_STATE, pid, 0,
00735                        (uintptr_t) &tts, sizeof (ttstate_t), 0);
00736       if (status < 0)
00737         perror_with_name (_("TT_PROC_GET_NEXT_LWP_STATE ttrace call failed"));
00738       if (status == 0)
00739         break;  /* End of list.  */
00740 
00741       ptid = ptid_build (tts.tts_pid, tts.tts_lwpid, 0);
00742       ti = add_thread (ptid);
00743       ti->private = xzalloc (sizeof (struct inf_ttrace_private_thread_info));
00744       inf_ttrace_num_lwps++;
00745     }
00746 }
00747 
00748 static void
00749 inf_ttrace_attach (struct target_ops *ops, char *args, int from_tty)
00750 {
00751   char *exec_file;
00752   pid_t pid;
00753   ttevent_t tte;
00754   struct inferior *inf;
00755 
00756   pid = parse_pid_to_attach (args);
00757 
00758   if (pid == getpid ())         /* Trying to masturbate?  */
00759     error (_("I refuse to debug myself!"));
00760 
00761   if (from_tty)
00762     {
00763       exec_file = get_exec_file (0);
00764 
00765       if (exec_file)
00766         printf_unfiltered (_("Attaching to program: %s, %s\n"), exec_file,
00767                            target_pid_to_str (pid_to_ptid (pid)));
00768       else
00769         printf_unfiltered (_("Attaching to %s\n"),
00770                            target_pid_to_str (pid_to_ptid (pid)));
00771 
00772       gdb_flush (gdb_stdout);
00773     }
00774 
00775   gdb_assert (inf_ttrace_num_lwps == 0);
00776   gdb_assert (inf_ttrace_num_lwps_in_syscall == 0);
00777   gdb_assert (inf_ttrace_vfork_ppid == -1);
00778 
00779   if (ttrace (TT_PROC_ATTACH, pid, 0, TT_KILL_ON_EXIT, TT_VERSION, 0) == -1)
00780     perror_with_name (("ttrace"));
00781 
00782   inf = current_inferior ();
00783   inferior_appeared (inf, pid);
00784   inf->attach_flag = 1;
00785 
00786   /* Set the initial event mask.  */
00787   memset (&tte, 0, sizeof (tte));
00788   tte.tte_events |= TTEVT_EXEC | TTEVT_EXIT | TTEVT_FORK | TTEVT_VFORK;
00789   tte.tte_events |= TTEVT_LWP_CREATE | TTEVT_LWP_EXIT | TTEVT_LWP_TERMINATE;
00790 #ifdef TTEVT_BPT_SSTEP
00791   tte.tte_events |= TTEVT_BPT_SSTEP;
00792 #endif
00793   tte.tte_opts |= TTEO_PROC_INHERIT;
00794   if (ttrace (TT_PROC_SET_EVENT_MASK, pid, 0,
00795               (uintptr_t)&tte, sizeof tte, 0) == -1)
00796     perror_with_name (("ttrace"));
00797 
00798   push_target (ops);
00799 
00800   inf_ttrace_create_threads_after_attach (pid);
00801 }
00802 
00803 static void
00804 inf_ttrace_detach (struct target_ops *ops, char *args, int from_tty)
00805 {
00806   pid_t pid = ptid_get_pid (inferior_ptid);
00807   int sig = 0;
00808 
00809   if (from_tty)
00810     {
00811       char *exec_file = get_exec_file (0);
00812       if (exec_file == 0)
00813         exec_file = "";
00814       printf_unfiltered (_("Detaching from program: %s, %s\n"), exec_file,
00815                          target_pid_to_str (pid_to_ptid (pid)));
00816       gdb_flush (gdb_stdout);
00817     }
00818   if (args)
00819     sig = atoi (args);
00820 
00821   /* ??? The HP-UX 11.0 ttrace(2) manual page doesn't mention that we
00822      can pass a signal number here.  Does this really work?  */
00823   if (ttrace (TT_PROC_DETACH, pid, 0, 0, sig, 0) == -1)
00824     perror_with_name (("ttrace"));
00825 
00826   if (inf_ttrace_vfork_ppid != -1)
00827     {
00828       if (ttrace (TT_PROC_DETACH, inf_ttrace_vfork_ppid, 0, 0, 0, 0) == -1)
00829         perror_with_name (("ttrace"));
00830       inf_ttrace_vfork_ppid = -1;
00831     }
00832 
00833   inf_ttrace_num_lwps = 0;
00834   inf_ttrace_num_lwps_in_syscall = 0;
00835 
00836   inferior_ptid = null_ptid;
00837   detach_inferior (pid);
00838 
00839   unpush_target (ops);
00840 }
00841 
00842 static void
00843 inf_ttrace_kill (struct target_ops *ops)
00844 {
00845   pid_t pid = ptid_get_pid (inferior_ptid);
00846 
00847   if (pid == 0)
00848     return;
00849 
00850   if (ttrace (TT_PROC_EXIT, pid, 0, 0, 0, 0) == -1)
00851     perror_with_name (("ttrace"));
00852   /* ??? Is it necessary to call ttrace_wait() here?  */
00853 
00854   if (inf_ttrace_vfork_ppid != -1)
00855     {
00856       if (ttrace (TT_PROC_DETACH, inf_ttrace_vfork_ppid, 0, 0, 0, 0) == -1)
00857         perror_with_name (("ttrace"));
00858       inf_ttrace_vfork_ppid = -1;
00859     }
00860 
00861   target_mourn_inferior ();
00862 }
00863 
00864 /* Check is a dying thread is dead by now, and delete it from GDBs
00865    thread list if so.  */
00866 static int
00867 inf_ttrace_delete_dead_threads_callback (struct thread_info *info, void *arg)
00868 {
00869   lwpid_t lwpid;
00870   struct inf_ttrace_private_thread_info *p;
00871 
00872   if (is_exited (info->ptid))
00873     return 0;
00874 
00875   lwpid = ptid_get_lwp (info->ptid);
00876   p = (struct inf_ttrace_private_thread_info *) info->private;
00877 
00878   /* Check if an lwp that was dying is still there or not.  */
00879   if (p->dying && (kill (lwpid, 0) == -1))
00880     /* It's gone now.  */
00881     delete_thread (info->ptid);
00882 
00883   return 0;
00884 }
00885 
00886 /* Resume the lwp pointed to by INFO, with REQUEST, and pass it signal
00887    SIG.  */
00888 
00889 static void
00890 inf_ttrace_resume_lwp (struct thread_info *info, ttreq_t request, int sig)
00891 {
00892   pid_t pid = ptid_get_pid (info->ptid);
00893   lwpid_t lwpid = ptid_get_lwp (info->ptid);
00894 
00895   if (ttrace (request, pid, lwpid, TT_NOPC, sig, 0) == -1)
00896     {
00897       struct inf_ttrace_private_thread_info *p
00898         = (struct inf_ttrace_private_thread_info *) info->private;
00899       if (p->dying && errno == EPROTO)
00900         /* This is expected, it means the dying lwp is really gone
00901            by now.  If ttrace had an event to inform the debugger
00902            the lwp is really gone, this wouldn't be needed.  */
00903         delete_thread (info->ptid);
00904       else
00905         /* This was really unexpected.  */
00906         perror_with_name (("ttrace"));
00907     }
00908 }
00909 
00910 /* Callback for iterate_over_threads.  */
00911 
00912 static int
00913 inf_ttrace_resume_callback (struct thread_info *info, void *arg)
00914 {
00915   if (!ptid_equal (info->ptid, inferior_ptid) && !is_exited (info->ptid))
00916     inf_ttrace_resume_lwp (info, TT_LWP_CONTINUE, 0);
00917 
00918   return 0;
00919 }
00920 
00921 static void
00922 inf_ttrace_resume (struct target_ops *ops,
00923                    ptid_t ptid, int step, enum gdb_signal signal)
00924 {
00925   int resume_all;
00926   ttreq_t request = step ? TT_LWP_SINGLE : TT_LWP_CONTINUE;
00927   int sig = gdb_signal_to_host (signal);
00928   struct thread_info *info;
00929 
00930   /* A specific PTID means `step only this process id'.  */
00931   resume_all = (ptid_equal (ptid, minus_one_ptid));
00932 
00933   /* If resuming all threads, it's the current thread that should be
00934      handled specially.  */
00935   if (resume_all)
00936     ptid = inferior_ptid;
00937 
00938   info = find_thread_ptid (ptid);
00939   inf_ttrace_resume_lwp (info, request, sig);
00940 
00941   if (resume_all)
00942     /* Let all the other threads run too.  */
00943     iterate_over_threads (inf_ttrace_resume_callback, NULL);
00944 }
00945 
00946 static ptid_t
00947 inf_ttrace_wait (struct target_ops *ops,
00948                  ptid_t ptid, struct target_waitstatus *ourstatus, int options)
00949 {
00950   pid_t pid = ptid_get_pid (ptid);
00951   lwpid_t lwpid = ptid_get_lwp (ptid);
00952   ttstate_t tts;
00953   struct thread_info *ti;
00954   ptid_t related_ptid;
00955 
00956   /* Until proven otherwise.  */
00957   ourstatus->kind = TARGET_WAITKIND_SPURIOUS;
00958 
00959   if (pid == -1)
00960     pid = lwpid = 0;
00961 
00962   gdb_assert (pid != 0 || lwpid == 0);
00963 
00964   do
00965     {
00966       set_sigint_trap ();
00967 
00968       if (ttrace_wait (pid, lwpid, TTRACE_WAITOK, &tts, sizeof tts) == -1)
00969         perror_with_name (("ttrace_wait"));
00970 
00971       if (tts.tts_event == TTEVT_VFORK && tts.tts_u.tts_fork.tts_isparent)
00972         {
00973           if (inf_ttrace_vfork_ppid != -1)
00974             {
00975               gdb_assert (inf_ttrace_vfork_ppid == tts.tts_pid);
00976 
00977               if (ttrace (TT_PROC_DETACH, tts.tts_pid, 0, 0, 0, 0) == -1)
00978                 perror_with_name (("ttrace"));
00979               inf_ttrace_vfork_ppid = -1;
00980             }
00981 
00982           tts.tts_event = TTEVT_NONE;
00983         }
00984 
00985       clear_sigint_trap ();
00986     }
00987   while (tts.tts_event == TTEVT_NONE);
00988 
00989   /* Now that we've waited, we can re-enable the page protections.  */
00990   if (inf_ttrace_reenable_page_protections)
00991     {
00992       gdb_assert (inf_ttrace_num_lwps_in_syscall == 0);
00993       inf_ttrace_enable_page_protections (tts.tts_pid);
00994       inf_ttrace_reenable_page_protections = 0;
00995     }
00996 
00997   ptid = ptid_build (tts.tts_pid, tts.tts_lwpid, 0);
00998 
00999   if (inf_ttrace_num_lwps == 0)
01000     {
01001       struct thread_info *ti;
01002 
01003       inf_ttrace_num_lwps = 1;
01004 
01005       /* This is the earliest we hear about the lwp member of
01006          INFERIOR_PTID, after an attach or fork_inferior.  */
01007       gdb_assert (ptid_get_lwp (inferior_ptid) == 0);
01008 
01009       /* We haven't set the private member on the main thread yet.  Do
01010          it now.  */
01011       ti = find_thread_ptid (inferior_ptid);
01012       gdb_assert (ti != NULL && ti->private == NULL);
01013       ti->private =
01014         xmalloc (sizeof (struct inf_ttrace_private_thread_info));
01015       memset (ti->private, 0,
01016               sizeof (struct inf_ttrace_private_thread_info));
01017 
01018       /* Notify the core that this ptid changed.  This changes
01019          inferior_ptid as well.  */
01020       thread_change_ptid (inferior_ptid, ptid);
01021     }
01022 
01023   switch (tts.tts_event)
01024     {
01025 #ifdef TTEVT_BPT_SSTEP
01026     case TTEVT_BPT_SSTEP:
01027       /* Make it look like a breakpoint.  */
01028       ourstatus->kind = TARGET_WAITKIND_STOPPED;
01029       ourstatus->value.sig = GDB_SIGNAL_TRAP;
01030       break;
01031 #endif
01032 
01033     case TTEVT_EXEC:
01034       ourstatus->kind = TARGET_WAITKIND_EXECD;
01035       ourstatus->value.execd_pathname =
01036         xmalloc (tts.tts_u.tts_exec.tts_pathlen + 1);
01037       if (ttrace (TT_PROC_GET_PATHNAME, tts.tts_pid, 0,
01038                   (uintptr_t)ourstatus->value.execd_pathname,
01039                   tts.tts_u.tts_exec.tts_pathlen, 0) == -1)
01040         perror_with_name (("ttrace"));
01041       ourstatus->value.execd_pathname[tts.tts_u.tts_exec.tts_pathlen] = 0;
01042 
01043       /* At this point, all inserted breakpoints are gone.  Doing this
01044          as soon as we detect an exec prevents the badness of deleting
01045          a breakpoint writing the current "shadow contents" to lift
01046          the bp.  That shadow is NOT valid after an exec.  */
01047       mark_breakpoints_out ();
01048       break;
01049 
01050     case TTEVT_EXIT:
01051       store_waitstatus (ourstatus, tts.tts_u.tts_exit.tts_exitcode);
01052       inf_ttrace_num_lwps = 0;
01053       break;
01054 
01055     case TTEVT_FORK:
01056       related_ptid = ptid_build (tts.tts_u.tts_fork.tts_fpid,
01057                                  tts.tts_u.tts_fork.tts_flwpid, 0);
01058 
01059       ourstatus->kind = TARGET_WAITKIND_FORKED;
01060       ourstatus->value.related_pid = related_ptid;
01061 
01062       /* Make sure the other end of the fork is stopped too.  */
01063       if (ttrace_wait (tts.tts_u.tts_fork.tts_fpid,
01064                        tts.tts_u.tts_fork.tts_flwpid,
01065                        TTRACE_WAITOK, &tts, sizeof tts) == -1)
01066         perror_with_name (("ttrace_wait"));
01067 
01068       gdb_assert (tts.tts_event == TTEVT_FORK);
01069       if (tts.tts_u.tts_fork.tts_isparent)
01070         {
01071           related_ptid = ptid_build (tts.tts_u.tts_fork.tts_fpid,
01072                                      tts.tts_u.tts_fork.tts_flwpid, 0);
01073           ptid = ptid_build (tts.tts_pid, tts.tts_lwpid, 0);
01074           ourstatus->value.related_pid = related_ptid;
01075         }
01076       break;
01077 
01078     case TTEVT_VFORK:
01079       gdb_assert (!tts.tts_u.tts_fork.tts_isparent);
01080 
01081       related_ptid = ptid_build (tts.tts_u.tts_fork.tts_fpid,
01082                                  tts.tts_u.tts_fork.tts_flwpid, 0);
01083 
01084       ourstatus->kind = TARGET_WAITKIND_VFORKED;
01085       ourstatus->value.related_pid = related_ptid;
01086 
01087       /* HACK: To avoid touching the parent during the vfork, switch
01088          away from it.  */
01089       inferior_ptid = ptid;
01090       break;
01091 
01092     case TTEVT_LWP_CREATE:
01093       lwpid = tts.tts_u.tts_thread.tts_target_lwpid;
01094       ptid = ptid_build (tts.tts_pid, lwpid, 0);
01095       ti = add_thread (ptid);
01096       ti->private =
01097         xmalloc (sizeof (struct inf_ttrace_private_thread_info));
01098       memset (ti->private, 0,
01099               sizeof (struct inf_ttrace_private_thread_info));
01100       inf_ttrace_num_lwps++;
01101       ptid = ptid_build (tts.tts_pid, tts.tts_lwpid, 0);
01102       /* Let the lwp_create-caller thread continue.  */
01103       ttrace (TT_LWP_CONTINUE, ptid_get_pid (ptid),
01104               ptid_get_lwp (ptid), TT_NOPC, 0, 0);
01105       /* Return without stopping the whole process.  */
01106       ourstatus->kind = TARGET_WAITKIND_IGNORE;
01107       return ptid;
01108 
01109     case TTEVT_LWP_EXIT:
01110       if (print_thread_events)
01111         printf_unfiltered (_("[%s exited]\n"), target_pid_to_str (ptid));
01112       ti = find_thread_ptid (ptid);
01113       gdb_assert (ti != NULL);
01114       ((struct inf_ttrace_private_thread_info *)ti->private)->dying = 1;
01115       inf_ttrace_num_lwps--;
01116       /* Let the thread really exit.  */
01117       ttrace (TT_LWP_CONTINUE, ptid_get_pid (ptid),
01118               ptid_get_lwp (ptid), TT_NOPC, 0, 0);
01119       /* Return without stopping the whole process.  */
01120       ourstatus->kind = TARGET_WAITKIND_IGNORE;
01121       return ptid;
01122 
01123     case TTEVT_LWP_TERMINATE:
01124       lwpid = tts.tts_u.tts_thread.tts_target_lwpid;
01125       ptid = ptid_build (tts.tts_pid, lwpid, 0);
01126       if (print_thread_events)
01127         printf_unfiltered(_("[%s has been terminated]\n"),
01128                           target_pid_to_str (ptid));
01129       ti = find_thread_ptid (ptid);
01130       gdb_assert (ti != NULL);
01131       ((struct inf_ttrace_private_thread_info *)ti->private)->dying = 1;
01132       inf_ttrace_num_lwps--;
01133 
01134       /* Resume the lwp_terminate-caller thread.  */
01135       ptid = ptid_build (tts.tts_pid, tts.tts_lwpid, 0);
01136       ttrace (TT_LWP_CONTINUE, ptid_get_pid (ptid),
01137               ptid_get_lwp (ptid), TT_NOPC, 0, 0);
01138       /* Return without stopping the whole process.  */
01139       ourstatus->kind = TARGET_WAITKIND_IGNORE;
01140       return ptid;
01141 
01142     case TTEVT_SIGNAL:
01143       ourstatus->kind = TARGET_WAITKIND_STOPPED;
01144       ourstatus->value.sig =
01145         gdb_signal_from_host (tts.tts_u.tts_signal.tts_signo);
01146       break;
01147 
01148     case TTEVT_SYSCALL_ENTRY:
01149       gdb_assert (inf_ttrace_reenable_page_protections == 0);
01150       inf_ttrace_num_lwps_in_syscall++;
01151       if (inf_ttrace_num_lwps_in_syscall == 1)
01152         {
01153           /* A thread has just entered a system call.  Disable any
01154              page protections as the kernel can't deal with them.  */
01155           inf_ttrace_disable_page_protections (tts.tts_pid);
01156         }
01157       ourstatus->kind = TARGET_WAITKIND_SYSCALL_ENTRY;
01158       ourstatus->value.syscall_number = tts.tts_scno;
01159       break;
01160 
01161     case TTEVT_SYSCALL_RETURN:
01162       if (inf_ttrace_num_lwps_in_syscall > 0)
01163         {
01164           /* If the last thread has just left the system call, this
01165              would be a logical place to re-enable the page
01166              protections, but that doesn't work.  We can't re-enable
01167              them until we've done another wait.  */
01168           inf_ttrace_reenable_page_protections = 
01169             (inf_ttrace_num_lwps_in_syscall == 1);
01170           inf_ttrace_num_lwps_in_syscall--;
01171         }
01172       ourstatus->kind = TARGET_WAITKIND_SYSCALL_RETURN;
01173       ourstatus->value.syscall_number = tts.tts_scno;
01174       break;
01175 
01176     default:
01177       gdb_assert (!"Unexpected ttrace event");
01178       break;
01179     }
01180 
01181   /* Make sure all threads within the process are stopped.  */
01182   if (ttrace (TT_PROC_STOP, tts.tts_pid, 0, 0, 0, 0) == -1)
01183     perror_with_name (("ttrace"));
01184 
01185   /* Now that the whole process is stopped, check if any dying thread
01186      is really dead by now.  If a dying thread is still alive, it will
01187      be stopped too, and will still show up in `info threads', tagged
01188      with "(Exiting)".  We could make `info threads' prune dead
01189      threads instead via inf_ttrace_thread_alive, but doing this here
01190      has the advantage that a frontend is notificed sooner of thread
01191      exits.  Note that a dying lwp is still alive, it still has to be
01192      resumed, like any other lwp.  */
01193   iterate_over_threads (inf_ttrace_delete_dead_threads_callback, NULL);
01194 
01195   return ptid;
01196 }
01197 
01198 /* Transfer LEN bytes from ADDR in the inferior's memory into READBUF,
01199    and transfer LEN bytes from WRITEBUF into the inferior's memory at
01200    ADDR.  Either READBUF or WRITEBUF may be null, in which case the
01201    corresponding transfer doesn't happen.  Return the number of bytes
01202    actually transferred (which may be zero if an error occurs).  */
01203 
01204 static LONGEST
01205 inf_ttrace_xfer_memory (CORE_ADDR addr, ULONGEST len,
01206                         void *readbuf, const void *writebuf)
01207 {
01208   pid_t pid = ptid_get_pid (inferior_ptid);
01209 
01210   /* HP-UX treats text space and data space differently.  GDB however,
01211      doesn't really know the difference.  Therefore we try both.  Try
01212      text space before data space though because when we're writing
01213      into text space the instruction cache might need to be flushed.  */
01214 
01215   if (readbuf
01216       && ttrace (TT_PROC_RDTEXT, pid, 0, addr, len, (uintptr_t)readbuf) == -1
01217       && ttrace (TT_PROC_RDDATA, pid, 0, addr, len, (uintptr_t)readbuf) == -1)
01218     return 0;
01219 
01220   if (writebuf
01221       && ttrace (TT_PROC_WRTEXT, pid, 0, addr, len, (uintptr_t)writebuf) == -1
01222       && ttrace (TT_PROC_WRDATA, pid, 0, addr, len, (uintptr_t)writebuf) == -1)
01223     return 0;
01224 
01225   return len;
01226 }
01227 
01228 static LONGEST
01229 inf_ttrace_xfer_partial (struct target_ops *ops, enum target_object object,
01230                          const char *annex, gdb_byte *readbuf,
01231                          const gdb_byte *writebuf,
01232                          ULONGEST offset, LONGEST len)
01233 {
01234   switch (object)
01235     {
01236     case TARGET_OBJECT_MEMORY:
01237       return inf_ttrace_xfer_memory (offset, len, readbuf, writebuf);
01238 
01239     case TARGET_OBJECT_UNWIND_TABLE:
01240       return -1;
01241 
01242     case TARGET_OBJECT_AUXV:
01243       return -1;
01244 
01245     case TARGET_OBJECT_WCOOKIE:
01246       return -1;
01247 
01248     default:
01249       return -1;
01250     }
01251 }
01252 
01253 /* Print status information about what we're accessing.  */
01254 
01255 static void
01256 inf_ttrace_files_info (struct target_ops *ignore)
01257 {
01258   struct inferior *inf = current_inferior ();
01259   printf_filtered (_("\tUsing the running image of %s %s.\n"),
01260                    inf->attach_flag ? "attached" : "child",
01261                    target_pid_to_str (inferior_ptid));
01262 }
01263 
01264 static int
01265 inf_ttrace_thread_alive (struct target_ops *ops, ptid_t ptid)
01266 {
01267   return 1;
01268 }
01269 
01270 /* Return a string describing the state of the thread specified by
01271    INFO.  */
01272 
01273 static char *
01274 inf_ttrace_extra_thread_info (struct thread_info *info)
01275 {
01276   struct inf_ttrace_private_thread_info* private =
01277     (struct inf_ttrace_private_thread_info *) info->private;
01278 
01279   if (private != NULL && private->dying)
01280     return "Exiting";
01281 
01282   return NULL;
01283 }
01284 
01285 static char *
01286 inf_ttrace_pid_to_str (struct target_ops *ops, ptid_t ptid)
01287 {
01288   pid_t pid = ptid_get_pid (ptid);
01289   lwpid_t lwpid = ptid_get_lwp (ptid);
01290   static char buf[128];
01291 
01292   if (lwpid == 0)
01293     xsnprintf (buf, sizeof buf, "process %ld",
01294                (long) pid);
01295   else
01296     xsnprintf (buf, sizeof buf, "process %ld, lwp %ld",
01297                (long) pid, (long) lwpid);
01298   return buf;
01299 }
01300 
01301 
01302 /* Implement the get_ada_task_ptid target_ops method.  */
01303 
01304 static ptid_t
01305 inf_ttrace_get_ada_task_ptid (long lwp, long thread)
01306 {
01307   return ptid_build (ptid_get_pid (inferior_ptid), lwp, 0);
01308 }
01309 
01310 
01311 struct target_ops *
01312 inf_ttrace_target (void)
01313 {
01314   struct target_ops *t = inf_child_target ();
01315 
01316   t->to_attach = inf_ttrace_attach;
01317   t->to_detach = inf_ttrace_detach;
01318   t->to_resume = inf_ttrace_resume;
01319   t->to_wait = inf_ttrace_wait;
01320   t->to_files_info = inf_ttrace_files_info;
01321   t->to_can_use_hw_breakpoint = inf_ttrace_can_use_hw_breakpoint;
01322   t->to_insert_watchpoint = inf_ttrace_insert_watchpoint;
01323   t->to_remove_watchpoint = inf_ttrace_remove_watchpoint;
01324   t->to_stopped_by_watchpoint = inf_ttrace_stopped_by_watchpoint;
01325   t->to_region_ok_for_hw_watchpoint =
01326     inf_ttrace_region_ok_for_hw_watchpoint;
01327   t->to_kill = inf_ttrace_kill;
01328   t->to_create_inferior = inf_ttrace_create_inferior;
01329   t->to_follow_fork = inf_ttrace_follow_fork;
01330   t->to_mourn_inferior = inf_ttrace_mourn_inferior;
01331   t->to_thread_alive = inf_ttrace_thread_alive;
01332   t->to_extra_thread_info = inf_ttrace_extra_thread_info;
01333   t->to_pid_to_str = inf_ttrace_pid_to_str;
01334   t->to_xfer_partial = inf_ttrace_xfer_partial;
01335   t->to_get_ada_task_ptid = inf_ttrace_get_ada_task_ptid;
01336 
01337   return t;
01338 }
01339 #endif
01340 
01341 
01342 /* Prevent warning from -Wmissing-prototypes.  */
01343 void _initialize_inf_ttrace (void);
01344 
01345 void
01346 _initialize_inf_ttrace (void)
01347 {
01348 #ifdef HAVE_TTRACE
01349   inf_ttrace_page_dict.pagesize = getpagesize();
01350 #endif
01351 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Defines