1/* Low-level child interface to ttrace.
2
3   Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011
4   Free Software Foundation, Inc.
5
6   This file is part of GDB.
7
8   This program is free software; you can redistribute it and/or modify
9   it under the terms of the GNU General Public License as published by
10   the Free Software Foundation; either version 3 of the License, or
11   (at your option) any later version.
12
13   This program is distributed in the hope that it will be useful,
14   but WITHOUT ANY WARRANTY; without even the implied warranty of
15   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16   GNU General Public License for more details.
17
18   You should have received a copy of the GNU General Public License
19   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
20
21#include "defs.h"
22
23/* The ttrace(2) system call didn't exist before HP-UX 10.30.  Don't
24   try to compile this code unless we have it.  */
25#ifdef HAVE_TTRACE
26
27#include "command.h"
28#include "gdbcore.h"
29#include "gdbthread.h"
30#include "inferior.h"
31#include "terminal.h"
32#include "target.h"
33
34#include "gdb_assert.h"
35#include "gdb_string.h"
36#include <sys/mman.h>
37#include <sys/ttrace.h>
38#include <signal.h>
39
40#include "inf-child.h"
41#include "inf-ttrace.h"
42
43
44
45/* HP-UX uses a threading model where each user-space thread
46   corresponds to a kernel thread.  These kernel threads are called
47   lwps.  The ttrace(2) interface gives us almost full control over
48   the threads, which makes it very easy to support them in GDB.  We
49   identify the threads by process ID and lwp ID.  The ttrace(2) also
50   provides us with a thread's user ID (in the `tts_user_tid' member
51   of `ttstate_t') but we don't use that (yet) as it isn't necessary
52   to uniquely label the thread.  */
53
54/* Number of active lwps.  */
55static int inf_ttrace_num_lwps;
56
57
58/* On HP-UX versions that have the ttrace(2) system call, we can
59   implement "hardware" watchpoints by fiddling with the protection of
60   pages in the address space that contain the variable being watched.
61   In order to implement this, we keep a dictionary of pages for which
62   we have changed the protection.  */
63
64struct inf_ttrace_page
65{
66  CORE_ADDR addr;		/* Page address.  */
67  int prot;			/* Protection.  */
68  int refcount;			/* Reference count.  */
69  struct inf_ttrace_page *next;
70  struct inf_ttrace_page *prev;
71};
72
73struct inf_ttrace_page_dict
74{
75  struct inf_ttrace_page buckets[128];
76  int pagesize;			/* Page size.  */
77  int count;			/* Number of pages in this dictionary.  */
78} inf_ttrace_page_dict;
79
80struct inf_ttrace_private_thread_info
81{
82  int dying;
83};
84
85/* Number of lwps that are currently in a system call.  */
86static int inf_ttrace_num_lwps_in_syscall;
87
88/* Flag to indicate whether we should re-enable page protections after
89   the next wait.  */
90static int inf_ttrace_reenable_page_protections;
91
92/* Enable system call events for process PID.  */
93
94static void
95inf_ttrace_enable_syscall_events (pid_t pid)
96{
97  ttevent_t tte;
98  ttstate_t tts;
99
100  gdb_assert (inf_ttrace_num_lwps_in_syscall == 0);
101
102  if (ttrace (TT_PROC_GET_EVENT_MASK, pid, 0,
103	      (uintptr_t)&tte, sizeof tte, 0) == -1)
104    perror_with_name (("ttrace"));
105
106  tte.tte_events |= (TTEVT_SYSCALL_ENTRY | TTEVT_SYSCALL_RETURN);
107
108  if (ttrace (TT_PROC_SET_EVENT_MASK, pid, 0,
109	      (uintptr_t)&tte, sizeof tte, 0) == -1)
110    perror_with_name (("ttrace"));
111
112  if (ttrace (TT_PROC_GET_FIRST_LWP_STATE, pid, 0,
113	      (uintptr_t)&tts, sizeof tts, 0) == -1)
114    perror_with_name (("ttrace"));
115
116  if (tts.tts_flags & TTS_INSYSCALL)
117    inf_ttrace_num_lwps_in_syscall++;
118
119  /* FIXME: Handle multiple threads.  */
120}
121
122/* Disable system call events for process PID.  */
123
124static void
125inf_ttrace_disable_syscall_events (pid_t pid)
126{
127  ttevent_t tte;
128
129  gdb_assert (inf_ttrace_page_dict.count == 0);
130
131  if (ttrace (TT_PROC_GET_EVENT_MASK, pid, 0,
132	      (uintptr_t)&tte, sizeof tte, 0) == -1)
133    perror_with_name (("ttrace"));
134
135  tte.tte_events &= ~(TTEVT_SYSCALL_ENTRY | TTEVT_SYSCALL_RETURN);
136
137  if (ttrace (TT_PROC_SET_EVENT_MASK, pid, 0,
138	      (uintptr_t)&tte, sizeof tte, 0) == -1)
139    perror_with_name (("ttrace"));
140
141  inf_ttrace_num_lwps_in_syscall = 0;
142}
143
144/* Get information about the page at address ADDR for process PID from
145   the dictionary.  */
146
147static struct inf_ttrace_page *
148inf_ttrace_get_page (pid_t pid, CORE_ADDR addr)
149{
150  const int num_buckets = ARRAY_SIZE (inf_ttrace_page_dict.buckets);
151  const int pagesize = inf_ttrace_page_dict.pagesize;
152  int bucket;
153  struct inf_ttrace_page *page;
154
155  bucket = (addr / pagesize) % num_buckets;
156  page = &inf_ttrace_page_dict.buckets[bucket];
157  while (page)
158    {
159      if (page->addr == addr)
160	break;
161
162      page = page->next;
163    }
164
165  return page;
166}
167
168/* Add the page at address ADDR for process PID to the dictionary.  */
169
170static struct inf_ttrace_page *
171inf_ttrace_add_page (pid_t pid, CORE_ADDR addr)
172{
173  const int num_buckets = ARRAY_SIZE (inf_ttrace_page_dict.buckets);
174  const int pagesize = inf_ttrace_page_dict.pagesize;
175  int bucket;
176  struct inf_ttrace_page *page;
177  struct inf_ttrace_page *prev = NULL;
178
179  bucket = (addr / pagesize) % num_buckets;
180  page = &inf_ttrace_page_dict.buckets[bucket];
181  while (page)
182    {
183      if (page->addr == addr)
184	break;
185
186      prev = page;
187      page = page->next;
188    }
189
190  if (!page)
191    {
192      int prot;
193
194      if (ttrace (TT_PROC_GET_MPROTECT, pid, 0,
195		  addr, 0, (uintptr_t)&prot) == -1)
196	perror_with_name (("ttrace"));
197
198      page = XMALLOC (struct inf_ttrace_page);
199      page->addr = addr;
200      page->prot = prot;
201      page->refcount = 0;
202      page->next = NULL;
203
204      page->prev = prev;
205      prev->next = page;
206
207      inf_ttrace_page_dict.count++;
208      if (inf_ttrace_page_dict.count == 1)
209	inf_ttrace_enable_syscall_events (pid);
210
211      if (inf_ttrace_num_lwps_in_syscall == 0)
212	{
213	  if (ttrace (TT_PROC_SET_MPROTECT, pid, 0,
214		      addr, pagesize, prot & ~PROT_WRITE) == -1)
215	    perror_with_name (("ttrace"));
216	}
217    }
218
219  return page;
220}
221
222/* Insert the page at address ADDR of process PID to the dictionary.  */
223
224static void
225inf_ttrace_insert_page (pid_t pid, CORE_ADDR addr)
226{
227  struct inf_ttrace_page *page;
228
229  page = inf_ttrace_get_page (pid, addr);
230  if (!page)
231    page = inf_ttrace_add_page (pid, addr);
232
233  page->refcount++;
234}
235
236/* Remove the page at address ADDR of process PID from the dictionary.  */
237
238static void
239inf_ttrace_remove_page (pid_t pid, CORE_ADDR addr)
240{
241  const int pagesize = inf_ttrace_page_dict.pagesize;
242  struct inf_ttrace_page *page;
243
244  page = inf_ttrace_get_page (pid, addr);
245  page->refcount--;
246
247  gdb_assert (page->refcount >= 0);
248
249  if (page->refcount == 0)
250    {
251      if (inf_ttrace_num_lwps_in_syscall == 0)
252	{
253	  if (ttrace (TT_PROC_SET_MPROTECT, pid, 0,
254		      addr, pagesize, page->prot) == -1)
255	    perror_with_name (("ttrace"));
256	}
257
258      inf_ttrace_page_dict.count--;
259      if (inf_ttrace_page_dict.count == 0)
260	inf_ttrace_disable_syscall_events (pid);
261
262      page->prev->next = page->next;
263      if (page->next)
264	page->next->prev = page->prev;
265
266      xfree (page);
267    }
268}
269
270/* Mask the bits in PROT from the page protections that are currently
271   in the dictionary for process PID.  */
272
273static void
274inf_ttrace_mask_page_protections (pid_t pid, int prot)
275{
276  const int num_buckets = ARRAY_SIZE (inf_ttrace_page_dict.buckets);
277  const int pagesize = inf_ttrace_page_dict.pagesize;
278  int bucket;
279
280  for (bucket = 0; bucket < num_buckets; bucket++)
281    {
282      struct inf_ttrace_page *page;
283
284      page = inf_ttrace_page_dict.buckets[bucket].next;
285      while (page)
286	{
287	  if (ttrace (TT_PROC_SET_MPROTECT, pid, 0,
288		      page->addr, pagesize, page->prot & ~prot) == -1)
289	    perror_with_name (("ttrace"));
290
291	  page = page->next;
292	}
293    }
294}
295
296/* Write-protect the pages in the dictionary for process PID.  */
297
298static void
299inf_ttrace_enable_page_protections (pid_t pid)
300{
301  inf_ttrace_mask_page_protections (pid, PROT_WRITE);
302}
303
304/* Restore the protection of the pages in the dictionary for process
305   PID.  */
306
307static void
308inf_ttrace_disable_page_protections (pid_t pid)
309{
310  inf_ttrace_mask_page_protections (pid, 0);
311}
312
313/* Insert a "hardware" watchpoint for LEN bytes at address ADDR of
314   type TYPE.  */
315
316static int
317inf_ttrace_insert_watchpoint (CORE_ADDR addr, int len, int type,
318			      struct expression *cond)
319{
320  const int pagesize = inf_ttrace_page_dict.pagesize;
321  pid_t pid = ptid_get_pid (inferior_ptid);
322  CORE_ADDR page_addr;
323  int num_pages;
324  int page;
325
326  gdb_assert (type == hw_write);
327
328  page_addr = (addr / pagesize) * pagesize;
329  num_pages = (len + pagesize - 1) / pagesize;
330
331  for (page = 0; page < num_pages; page++, page_addr += pagesize)
332    inf_ttrace_insert_page (pid, page_addr);
333
334  return 1;
335}
336
337/* Remove a "hardware" watchpoint for LEN bytes at address ADDR of
338   type TYPE.  */
339
340static int
341inf_ttrace_remove_watchpoint (CORE_ADDR addr, int len, int type,
342			      struct expression *cond)
343{
344  const int pagesize = inf_ttrace_page_dict.pagesize;
345  pid_t pid = ptid_get_pid (inferior_ptid);
346  CORE_ADDR page_addr;
347  int num_pages;
348  int page;
349
350  gdb_assert (type == hw_write);
351
352  page_addr = (addr / pagesize) * pagesize;
353  num_pages = (len + pagesize - 1) / pagesize;
354
355  for (page = 0; page < num_pages; page++, page_addr += pagesize)
356    inf_ttrace_remove_page (pid, page_addr);
357
358  return 1;
359}
360
361static int
362inf_ttrace_can_use_hw_breakpoint (int type, int len, int ot)
363{
364  return (type == bp_hardware_watchpoint);
365}
366
367static int
368inf_ttrace_region_ok_for_hw_watchpoint (CORE_ADDR addr, int len)
369{
370  return 1;
371}
372
373/* Return non-zero if the current inferior was (potentially) stopped
374   by hitting a "hardware" watchpoint.  */
375
376static int
377inf_ttrace_stopped_by_watchpoint (void)
378{
379  pid_t pid = ptid_get_pid (inferior_ptid);
380  lwpid_t lwpid = ptid_get_lwp (inferior_ptid);
381  ttstate_t tts;
382
383  if (inf_ttrace_page_dict.count > 0)
384    {
385      if (ttrace (TT_LWP_GET_STATE, pid, lwpid,
386		  (uintptr_t)&tts, sizeof tts, 0) == -1)
387	perror_with_name (("ttrace"));
388
389      if (tts.tts_event == TTEVT_SIGNAL
390	  && tts.tts_u.tts_signal.tts_signo == SIGBUS)
391	{
392	  const int pagesize = inf_ttrace_page_dict.pagesize;
393	  void *addr = tts.tts_u.tts_signal.tts_siginfo.si_addr;
394	  CORE_ADDR page_addr = ((uintptr_t)addr / pagesize) * pagesize;
395
396	  if (inf_ttrace_get_page (pid, page_addr))
397	    return 1;
398	}
399    }
400
401  return 0;
402}
403
404
405/* When tracking a vfork(2), we cannot detach from the parent until
406   after the child has called exec(3) or has exited.  If we are still
407   attached to the parent, this variable will be set to the process ID
408   of the parent.  Otherwise it will be set to zero.  */
409static pid_t inf_ttrace_vfork_ppid = -1;
410
411static int
412inf_ttrace_follow_fork (struct target_ops *ops, int follow_child)
413{
414  pid_t pid, fpid;
415  lwpid_t lwpid, flwpid;
416  ttstate_t tts;
417  struct thread_info *tp = inferior_thread ();
418
419  gdb_assert (tp->pending_follow.kind == TARGET_WAITKIND_FORKED
420	      || tp->pending_follow.kind == TARGET_WAITKIND_VFORKED);
421
422  pid = ptid_get_pid (inferior_ptid);
423  lwpid = ptid_get_lwp (inferior_ptid);
424
425  /* Get all important details that core GDB doesn't (and shouldn't)
426     know about.  */
427  if (ttrace (TT_LWP_GET_STATE, pid, lwpid,
428	      (uintptr_t)&tts, sizeof tts, 0) == -1)
429    perror_with_name (("ttrace"));
430
431  gdb_assert (tts.tts_event == TTEVT_FORK || tts.tts_event == TTEVT_VFORK);
432
433  if (tts.tts_u.tts_fork.tts_isparent)
434    {
435      pid = tts.tts_pid;
436      lwpid = tts.tts_lwpid;
437      fpid = tts.tts_u.tts_fork.tts_fpid;
438      flwpid = tts.tts_u.tts_fork.tts_flwpid;
439    }
440  else
441    {
442      pid = tts.tts_u.tts_fork.tts_fpid;
443      lwpid = tts.tts_u.tts_fork.tts_flwpid;
444      fpid = tts.tts_pid;
445      flwpid = tts.tts_lwpid;
446    }
447
448  if (follow_child)
449    {
450      struct inferior *inf;
451      struct inferior *parent_inf;
452
453      parent_inf = find_inferior_pid (pid);
454
455      inferior_ptid = ptid_build (fpid, flwpid, 0);
456      inf = add_inferior (fpid);
457      inf->attach_flag = parent_inf->attach_flag;
458      inf->pspace = parent_inf->pspace;
459      inf->aspace = parent_inf->aspace;
460      copy_terminal_info (inf, parent_inf);
461      detach_breakpoints (pid);
462
463      target_terminal_ours ();
464      fprintf_unfiltered (gdb_stdlog,
465			  _("Attaching after fork to child process %ld.\n"),
466			  (long)fpid);
467    }
468  else
469    {
470      inferior_ptid = ptid_build (pid, lwpid, 0);
471      detach_breakpoints (fpid);
472
473      target_terminal_ours ();
474      fprintf_unfiltered (gdb_stdlog,
475			  _("Detaching after fork from child process %ld.\n"),
476			  (long)fpid);
477    }
478
479  if (tts.tts_event == TTEVT_VFORK)
480    {
481      gdb_assert (!tts.tts_u.tts_fork.tts_isparent);
482
483      if (follow_child)
484	{
485	  /* We can't detach from the parent yet.  */
486	  inf_ttrace_vfork_ppid = pid;
487
488	  reattach_breakpoints (fpid);
489	}
490      else
491	{
492	  if (ttrace (TT_PROC_DETACH, fpid, 0, 0, 0, 0) == -1)
493	    perror_with_name (("ttrace"));
494
495	  /* Wait till we get the TTEVT_VFORK event in the parent.
496	     This indicates that the child has called exec(3) or has
497	     exited and that the parent is ready to be traced again.  */
498	  if (ttrace_wait (pid, lwpid, TTRACE_WAITOK, &tts, sizeof tts) == -1)
499	    perror_with_name (("ttrace_wait"));
500	  gdb_assert (tts.tts_event == TTEVT_VFORK);
501	  gdb_assert (tts.tts_u.tts_fork.tts_isparent);
502
503	  reattach_breakpoints (pid);
504	}
505    }
506  else
507    {
508      gdb_assert (tts.tts_u.tts_fork.tts_isparent);
509
510      if (follow_child)
511	{
512	  if (ttrace (TT_PROC_DETACH, pid, 0, 0, 0, 0) == -1)
513	    perror_with_name (("ttrace"));
514	}
515      else
516	{
517	  if (ttrace (TT_PROC_DETACH, fpid, 0, 0, 0, 0) == -1)
518	    perror_with_name (("ttrace"));
519	}
520    }
521
522  if (follow_child)
523    {
524      struct thread_info *ti;
525
526      /* The child will start out single-threaded.  */
527      inf_ttrace_num_lwps = 1;
528      inf_ttrace_num_lwps_in_syscall = 0;
529
530      /* Delete parent.  */
531      delete_thread_silent (ptid_build (pid, lwpid, 0));
532      detach_inferior (pid);
533
534      /* Add child thread.  inferior_ptid was already set above.  */
535      ti = add_thread_silent (inferior_ptid);
536      ti->private =
537	xmalloc (sizeof (struct inf_ttrace_private_thread_info));
538      memset (ti->private, 0,
539	      sizeof (struct inf_ttrace_private_thread_info));
540    }
541
542  return 0;
543}
544
545
546/* File descriptors for pipes used as semaphores during initial
547   startup of an inferior.  */
548static int inf_ttrace_pfd1[2];
549static int inf_ttrace_pfd2[2];
550
551static void
552do_cleanup_pfds (void *dummy)
553{
554  close (inf_ttrace_pfd1[0]);
555  close (inf_ttrace_pfd1[1]);
556  close (inf_ttrace_pfd2[0]);
557  close (inf_ttrace_pfd2[1]);
558}
559
560static void
561inf_ttrace_prepare (void)
562{
563  if (pipe (inf_ttrace_pfd1) == -1)
564    perror_with_name (("pipe"));
565
566  if (pipe (inf_ttrace_pfd2) == -1)
567    {
568      close (inf_ttrace_pfd1[0]);
569      close (inf_ttrace_pfd2[0]);
570      perror_with_name (("pipe"));
571    }
572}
573
574/* Prepare to be traced.  */
575
576static void
577inf_ttrace_me (void)
578{
579  struct cleanup *old_chain = make_cleanup (do_cleanup_pfds, 0);
580  char c;
581
582  /* "Trace me, Dr. Memory!"  */
583  if (ttrace (TT_PROC_SETTRC, 0, 0, 0, TT_VERSION, 0) == -1)
584    perror_with_name (("ttrace"));
585
586  /* Tell our parent that we are ready to be traced.  */
587  if (write (inf_ttrace_pfd1[1], &c, sizeof c) != sizeof c)
588    perror_with_name (("write"));
589
590  /* Wait until our parent has set the initial event mask.  */
591  if (read (inf_ttrace_pfd2[0], &c, sizeof c) != sizeof c)
592    perror_with_name (("read"));
593
594  do_cleanups (old_chain);
595}
596
597/* Start tracing PID.  */
598
599static void
600inf_ttrace_him (struct target_ops *ops, int pid)
601{
602  struct cleanup *old_chain = make_cleanup (do_cleanup_pfds, 0);
603  ttevent_t tte;
604  char c;
605
606  /* Wait until our child is ready to be traced.  */
607  if (read (inf_ttrace_pfd1[0], &c, sizeof c) != sizeof c)
608    perror_with_name (("read"));
609
610  /* Set the initial event mask.  */
611  memset (&tte, 0, sizeof (tte));
612  tte.tte_events |= TTEVT_EXEC | TTEVT_EXIT | TTEVT_FORK | TTEVT_VFORK;
613  tte.tte_events |= TTEVT_LWP_CREATE | TTEVT_LWP_EXIT | TTEVT_LWP_TERMINATE;
614#ifdef TTEVT_BPT_SSTEP
615  tte.tte_events |= TTEVT_BPT_SSTEP;
616#endif
617  tte.tte_opts |= TTEO_PROC_INHERIT;
618  if (ttrace (TT_PROC_SET_EVENT_MASK, pid, 0,
619	      (uintptr_t)&tte, sizeof tte, 0) == -1)
620    perror_with_name (("ttrace"));
621
622  /* Tell our child that we have set the initial event mask.  */
623  if (write (inf_ttrace_pfd2[1], &c, sizeof c) != sizeof c)
624    perror_with_name (("write"));
625
626  do_cleanups (old_chain);
627
628  push_target (ops);
629
630  /* START_INFERIOR_TRAPS_EXPECTED is defined in inferior.h, and will
631     be 1 or 2 depending on whether we're starting without or with a
632     shell.  */
633  startup_inferior (START_INFERIOR_TRAPS_EXPECTED);
634
635  /* On some targets, there must be some explicit actions taken after
636     the inferior has been started up.  */
637  target_post_startup_inferior (pid_to_ptid (pid));
638}
639
640static void
641inf_ttrace_create_inferior (struct target_ops *ops, char *exec_file,
642			    char *allargs, char **env, int from_tty)
643{
644  int pid;
645
646  gdb_assert (inf_ttrace_num_lwps == 0);
647  gdb_assert (inf_ttrace_num_lwps_in_syscall == 0);
648  gdb_assert (inf_ttrace_page_dict.count == 0);
649  gdb_assert (inf_ttrace_reenable_page_protections == 0);
650  gdb_assert (inf_ttrace_vfork_ppid == -1);
651
652  pid = fork_inferior (exec_file, allargs, env, inf_ttrace_me, NULL,
653		       inf_ttrace_prepare, NULL);
654
655  inf_ttrace_him (ops, pid);
656}
657
658static void
659inf_ttrace_mourn_inferior (struct target_ops *ops)
660{
661  const int num_buckets = ARRAY_SIZE (inf_ttrace_page_dict.buckets);
662  int bucket;
663
664  inf_ttrace_num_lwps = 0;
665  inf_ttrace_num_lwps_in_syscall = 0;
666
667  for (bucket = 0; bucket < num_buckets; bucket++)
668    {
669      struct inf_ttrace_page *page;
670      struct inf_ttrace_page *next;
671
672      page = inf_ttrace_page_dict.buckets[bucket].next;
673      while (page)
674	{
675	  next = page->next;
676	  xfree (page);
677	  page = next;
678	}
679    }
680  inf_ttrace_page_dict.count = 0;
681
682  unpush_target (ops);
683  generic_mourn_inferior ();
684}
685
686/* Assuming we just attached the debugger to a new inferior, create
687   a new thread_info structure for each thread, and add it to our
688   list of threads.  */
689
690static void
691inf_ttrace_create_threads_after_attach (int pid)
692{
693  int status;
694  ptid_t ptid;
695  ttstate_t tts;
696  struct thread_info *ti;
697
698  status = ttrace (TT_PROC_GET_FIRST_LWP_STATE, pid, 0,
699		   (uintptr_t) &tts, sizeof (ttstate_t), 0);
700  if (status < 0)
701    perror_with_name (_("TT_PROC_GET_FIRST_LWP_STATE ttrace call failed"));
702  gdb_assert (tts.tts_pid == pid);
703
704  /* Add the stopped thread.  */
705  ptid = ptid_build (pid, tts.tts_lwpid, 0);
706  ti = add_thread (ptid);
707  ti->private = xzalloc (sizeof (struct inf_ttrace_private_thread_info));
708  inf_ttrace_num_lwps++;
709
710  /* We use the "first stopped thread" as the currently active thread.  */
711  inferior_ptid = ptid;
712
713  /* Iterative over all the remaining threads.  */
714
715  for (;;)
716    {
717      ptid_t ptid;
718
719      status = ttrace (TT_PROC_GET_NEXT_LWP_STATE, pid, 0,
720		       (uintptr_t) &tts, sizeof (ttstate_t), 0);
721      if (status < 0)
722	perror_with_name (_("TT_PROC_GET_NEXT_LWP_STATE ttrace call failed"));
723      if (status == 0)
724        break;  /* End of list.  */
725
726      ptid = ptid_build (tts.tts_pid, tts.tts_lwpid, 0);
727      ti = add_thread (ptid);
728      ti->private = xzalloc (sizeof (struct inf_ttrace_private_thread_info));
729      inf_ttrace_num_lwps++;
730    }
731}
732
733static void
734inf_ttrace_attach (struct target_ops *ops, char *args, int from_tty)
735{
736  char *exec_file;
737  pid_t pid;
738  ttevent_t tte;
739  struct inferior *inf;
740
741  pid = parse_pid_to_attach (args);
742
743  if (pid == getpid ())		/* Trying to masturbate?  */
744    error (_("I refuse to debug myself!"));
745
746  if (from_tty)
747    {
748      exec_file = get_exec_file (0);
749
750      if (exec_file)
751	printf_unfiltered (_("Attaching to program: %s, %s\n"), exec_file,
752			   target_pid_to_str (pid_to_ptid (pid)));
753      else
754	printf_unfiltered (_("Attaching to %s\n"),
755			   target_pid_to_str (pid_to_ptid (pid)));
756
757      gdb_flush (gdb_stdout);
758    }
759
760  gdb_assert (inf_ttrace_num_lwps == 0);
761  gdb_assert (inf_ttrace_num_lwps_in_syscall == 0);
762  gdb_assert (inf_ttrace_vfork_ppid == -1);
763
764  if (ttrace (TT_PROC_ATTACH, pid, 0, TT_KILL_ON_EXIT, TT_VERSION, 0) == -1)
765    perror_with_name (("ttrace"));
766
767  inf = current_inferior ();
768  inferior_appeared (inf, pid);
769  inf->attach_flag = 1;
770
771  /* Set the initial event mask.  */
772  memset (&tte, 0, sizeof (tte));
773  tte.tte_events |= TTEVT_EXEC | TTEVT_EXIT | TTEVT_FORK | TTEVT_VFORK;
774  tte.tte_events |= TTEVT_LWP_CREATE | TTEVT_LWP_EXIT | TTEVT_LWP_TERMINATE;
775#ifdef TTEVT_BPT_SSTEP
776  tte.tte_events |= TTEVT_BPT_SSTEP;
777#endif
778  tte.tte_opts |= TTEO_PROC_INHERIT;
779  if (ttrace (TT_PROC_SET_EVENT_MASK, pid, 0,
780	      (uintptr_t)&tte, sizeof tte, 0) == -1)
781    perror_with_name (("ttrace"));
782
783  push_target (ops);
784
785  inf_ttrace_create_threads_after_attach (pid);
786}
787
788static void
789inf_ttrace_detach (struct target_ops *ops, char *args, int from_tty)
790{
791  pid_t pid = ptid_get_pid (inferior_ptid);
792  int sig = 0;
793
794  if (from_tty)
795    {
796      char *exec_file = get_exec_file (0);
797      if (exec_file == 0)
798	exec_file = "";
799      printf_unfiltered (_("Detaching from program: %s, %s\n"), exec_file,
800			 target_pid_to_str (pid_to_ptid (pid)));
801      gdb_flush (gdb_stdout);
802    }
803  if (args)
804    sig = atoi (args);
805
806  /* ??? The HP-UX 11.0 ttrace(2) manual page doesn't mention that we
807     can pass a signal number here.  Does this really work?  */
808  if (ttrace (TT_PROC_DETACH, pid, 0, 0, sig, 0) == -1)
809    perror_with_name (("ttrace"));
810
811  if (inf_ttrace_vfork_ppid != -1)
812    {
813      if (ttrace (TT_PROC_DETACH, inf_ttrace_vfork_ppid, 0, 0, 0, 0) == -1)
814	perror_with_name (("ttrace"));
815      inf_ttrace_vfork_ppid = -1;
816    }
817
818  inf_ttrace_num_lwps = 0;
819  inf_ttrace_num_lwps_in_syscall = 0;
820
821  inferior_ptid = null_ptid;
822  detach_inferior (pid);
823
824  unpush_target (ops);
825}
826
827static void
828inf_ttrace_kill (struct target_ops *ops)
829{
830  pid_t pid = ptid_get_pid (inferior_ptid);
831
832  if (pid == 0)
833    return;
834
835  if (ttrace (TT_PROC_EXIT, pid, 0, 0, 0, 0) == -1)
836    perror_with_name (("ttrace"));
837  /* ??? Is it necessary to call ttrace_wait() here?  */
838
839  if (inf_ttrace_vfork_ppid != -1)
840    {
841      if (ttrace (TT_PROC_DETACH, inf_ttrace_vfork_ppid, 0, 0, 0, 0) == -1)
842	perror_with_name (("ttrace"));
843      inf_ttrace_vfork_ppid = -1;
844    }
845
846  target_mourn_inferior ();
847}
848
849/* Check is a dying thread is dead by now, and delete it from GDBs
850   thread list if so.  */
851static int
852inf_ttrace_delete_dead_threads_callback (struct thread_info *info, void *arg)
853{
854  lwpid_t lwpid;
855  struct inf_ttrace_private_thread_info *p;
856
857  if (is_exited (info->ptid))
858    return 0;
859
860  lwpid = ptid_get_lwp (info->ptid);
861  p = (struct inf_ttrace_private_thread_info *) info->private;
862
863  /* Check if an lwp that was dying is still there or not.  */
864  if (p->dying && (kill (lwpid, 0) == -1))
865    /* It's gone now.  */
866    delete_thread (info->ptid);
867
868  return 0;
869}
870
871/* Resume the lwp pointed to by INFO, with REQUEST, and pass it signal
872   SIG.  */
873
874static void
875inf_ttrace_resume_lwp (struct thread_info *info, ttreq_t request, int sig)
876{
877  pid_t pid = ptid_get_pid (info->ptid);
878  lwpid_t lwpid = ptid_get_lwp (info->ptid);
879
880  if (ttrace (request, pid, lwpid, TT_NOPC, sig, 0) == -1)
881    {
882      struct inf_ttrace_private_thread_info *p
883	= (struct inf_ttrace_private_thread_info *) info->private;
884      if (p->dying && errno == EPROTO)
885	/* This is expected, it means the dying lwp is really gone
886	   by now.  If ttrace had an event to inform the debugger
887	   the lwp is really gone, this wouldn't be needed.  */
888	delete_thread (info->ptid);
889      else
890	/* This was really unexpected.  */
891	perror_with_name (("ttrace"));
892    }
893}
894
895/* Callback for iterate_over_threads.  */
896
897static int
898inf_ttrace_resume_callback (struct thread_info *info, void *arg)
899{
900  if (!ptid_equal (info->ptid, inferior_ptid) && !is_exited (info->ptid))
901    inf_ttrace_resume_lwp (info, TT_LWP_CONTINUE, 0);
902
903  return 0;
904}
905
906static void
907inf_ttrace_resume (struct target_ops *ops,
908		   ptid_t ptid, int step, enum target_signal signal)
909{
910  int resume_all;
911  ttreq_t request = step ? TT_LWP_SINGLE : TT_LWP_CONTINUE;
912  int sig = target_signal_to_host (signal);
913  struct thread_info *info;
914
915  /* A specific PTID means `step only this process id'.  */
916  resume_all = (ptid_equal (ptid, minus_one_ptid));
917
918  /* If resuming all threads, it's the current thread that should be
919     handled specially.  */
920  if (resume_all)
921    ptid = inferior_ptid;
922
923  info = find_thread_ptid (ptid);
924  inf_ttrace_resume_lwp (info, request, sig);
925
926  if (resume_all)
927    /* Let all the other threads run too.  */
928    iterate_over_threads (inf_ttrace_resume_callback, NULL);
929}
930
931static ptid_t
932inf_ttrace_wait (struct target_ops *ops,
933		 ptid_t ptid, struct target_waitstatus *ourstatus, int options)
934{
935  pid_t pid = ptid_get_pid (ptid);
936  lwpid_t lwpid = ptid_get_lwp (ptid);
937  ttstate_t tts;
938  struct thread_info *ti;
939  ptid_t related_ptid;
940
941  /* Until proven otherwise.  */
942  ourstatus->kind = TARGET_WAITKIND_SPURIOUS;
943
944  if (pid == -1)
945    pid = lwpid = 0;
946
947  gdb_assert (pid != 0 || lwpid == 0);
948
949  do
950    {
951      set_sigint_trap ();
952
953      if (ttrace_wait (pid, lwpid, TTRACE_WAITOK, &tts, sizeof tts) == -1)
954	perror_with_name (("ttrace_wait"));
955
956      if (tts.tts_event == TTEVT_VFORK && tts.tts_u.tts_fork.tts_isparent)
957	{
958	  if (inf_ttrace_vfork_ppid != -1)
959	    {
960	      gdb_assert (inf_ttrace_vfork_ppid == tts.tts_pid);
961
962	      if (ttrace (TT_PROC_DETACH, tts.tts_pid, 0, 0, 0, 0) == -1)
963		perror_with_name (("ttrace"));
964	      inf_ttrace_vfork_ppid = -1;
965	    }
966
967	  tts.tts_event = TTEVT_NONE;
968	}
969
970      clear_sigint_trap ();
971    }
972  while (tts.tts_event == TTEVT_NONE);
973
974  /* Now that we've waited, we can re-enable the page protections.  */
975  if (inf_ttrace_reenable_page_protections)
976    {
977      gdb_assert (inf_ttrace_num_lwps_in_syscall == 0);
978      inf_ttrace_enable_page_protections (tts.tts_pid);
979      inf_ttrace_reenable_page_protections = 0;
980    }
981
982  ptid = ptid_build (tts.tts_pid, tts.tts_lwpid, 0);
983
984  if (inf_ttrace_num_lwps == 0)
985    {
986      struct thread_info *ti;
987
988      inf_ttrace_num_lwps = 1;
989
990      /* This is the earliest we hear about the lwp member of
991	 INFERIOR_PTID, after an attach or fork_inferior.  */
992      gdb_assert (ptid_get_lwp (inferior_ptid) == 0);
993
994      /* We haven't set the private member on the main thread yet.  Do
995	 it now.  */
996      ti = find_thread_ptid (inferior_ptid);
997      gdb_assert (ti != NULL && ti->private == NULL);
998      ti->private =
999	xmalloc (sizeof (struct inf_ttrace_private_thread_info));
1000      memset (ti->private, 0,
1001	      sizeof (struct inf_ttrace_private_thread_info));
1002
1003      /* Notify the core that this ptid changed.  This changes
1004	 inferior_ptid as well.  */
1005      thread_change_ptid (inferior_ptid, ptid);
1006    }
1007
1008  switch (tts.tts_event)
1009    {
1010#ifdef TTEVT_BPT_SSTEP
1011    case TTEVT_BPT_SSTEP:
1012      /* Make it look like a breakpoint.  */
1013      ourstatus->kind = TARGET_WAITKIND_STOPPED;
1014      ourstatus->value.sig = TARGET_SIGNAL_TRAP;
1015      break;
1016#endif
1017
1018    case TTEVT_EXEC:
1019      ourstatus->kind = TARGET_WAITKIND_EXECD;
1020      ourstatus->value.execd_pathname =
1021	xmalloc (tts.tts_u.tts_exec.tts_pathlen + 1);
1022      if (ttrace (TT_PROC_GET_PATHNAME, tts.tts_pid, 0,
1023		  (uintptr_t)ourstatus->value.execd_pathname,
1024		  tts.tts_u.tts_exec.tts_pathlen, 0) == -1)
1025	perror_with_name (("ttrace"));
1026      ourstatus->value.execd_pathname[tts.tts_u.tts_exec.tts_pathlen] = 0;
1027
1028      /* At this point, all inserted breakpoints are gone.  Doing this
1029	 as soon as we detect an exec prevents the badness of deleting
1030	 a breakpoint writing the current "shadow contents" to lift
1031	 the bp.  That shadow is NOT valid after an exec.  */
1032      mark_breakpoints_out ();
1033      break;
1034
1035    case TTEVT_EXIT:
1036      store_waitstatus (ourstatus, tts.tts_u.tts_exit.tts_exitcode);
1037      inf_ttrace_num_lwps = 0;
1038      break;
1039
1040    case TTEVT_FORK:
1041      related_ptid = ptid_build (tts.tts_u.tts_fork.tts_fpid,
1042				 tts.tts_u.tts_fork.tts_flwpid, 0);
1043
1044      ourstatus->kind = TARGET_WAITKIND_FORKED;
1045      ourstatus->value.related_pid = related_ptid;
1046
1047      /* Make sure the other end of the fork is stopped too.  */
1048      if (ttrace_wait (tts.tts_u.tts_fork.tts_fpid,
1049		       tts.tts_u.tts_fork.tts_flwpid,
1050		       TTRACE_WAITOK, &tts, sizeof tts) == -1)
1051	perror_with_name (("ttrace_wait"));
1052
1053      gdb_assert (tts.tts_event == TTEVT_FORK);
1054      if (tts.tts_u.tts_fork.tts_isparent)
1055	{
1056	  related_ptid = ptid_build (tts.tts_u.tts_fork.tts_fpid,
1057				     tts.tts_u.tts_fork.tts_flwpid, 0);
1058	  ptid = ptid_build (tts.tts_pid, tts.tts_lwpid, 0);
1059	  ourstatus->value.related_pid = related_ptid;
1060	}
1061      break;
1062
1063    case TTEVT_VFORK:
1064      gdb_assert (!tts.tts_u.tts_fork.tts_isparent);
1065
1066      related_ptid = ptid_build (tts.tts_u.tts_fork.tts_fpid,
1067				 tts.tts_u.tts_fork.tts_flwpid, 0);
1068
1069      ourstatus->kind = TARGET_WAITKIND_VFORKED;
1070      ourstatus->value.related_pid = related_ptid;
1071
1072      /* HACK: To avoid touching the parent during the vfork, switch
1073	 away from it.  */
1074      inferior_ptid = ptid;
1075      break;
1076
1077    case TTEVT_LWP_CREATE:
1078      lwpid = tts.tts_u.tts_thread.tts_target_lwpid;
1079      ptid = ptid_build (tts.tts_pid, lwpid, 0);
1080      ti = add_thread (ptid);
1081      ti->private =
1082	xmalloc (sizeof (struct inf_ttrace_private_thread_info));
1083      memset (ti->private, 0,
1084	      sizeof (struct inf_ttrace_private_thread_info));
1085      inf_ttrace_num_lwps++;
1086      ptid = ptid_build (tts.tts_pid, tts.tts_lwpid, 0);
1087      /* Let the lwp_create-caller thread continue.  */
1088      ttrace (TT_LWP_CONTINUE, ptid_get_pid (ptid),
1089              ptid_get_lwp (ptid), TT_NOPC, 0, 0);
1090      /* Return without stopping the whole process.  */
1091      ourstatus->kind = TARGET_WAITKIND_IGNORE;
1092      return ptid;
1093
1094    case TTEVT_LWP_EXIT:
1095      if (print_thread_events)
1096	printf_unfiltered (_("[%s exited]\n"), target_pid_to_str (ptid));
1097      ti = find_thread_ptid (ptid);
1098      gdb_assert (ti != NULL);
1099      ((struct inf_ttrace_private_thread_info *)ti->private)->dying = 1;
1100      inf_ttrace_num_lwps--;
1101      /* Let the thread really exit.  */
1102      ttrace (TT_LWP_CONTINUE, ptid_get_pid (ptid),
1103              ptid_get_lwp (ptid), TT_NOPC, 0, 0);
1104      /* Return without stopping the whole process.  */
1105      ourstatus->kind = TARGET_WAITKIND_IGNORE;
1106      return ptid;
1107
1108    case TTEVT_LWP_TERMINATE:
1109      lwpid = tts.tts_u.tts_thread.tts_target_lwpid;
1110      ptid = ptid_build (tts.tts_pid, lwpid, 0);
1111      if (print_thread_events)
1112	printf_unfiltered(_("[%s has been terminated]\n"),
1113			  target_pid_to_str (ptid));
1114      ti = find_thread_ptid (ptid);
1115      gdb_assert (ti != NULL);
1116      ((struct inf_ttrace_private_thread_info *)ti->private)->dying = 1;
1117      inf_ttrace_num_lwps--;
1118
1119      /* Resume the lwp_terminate-caller thread.  */
1120      ptid = ptid_build (tts.tts_pid, tts.tts_lwpid, 0);
1121      ttrace (TT_LWP_CONTINUE, ptid_get_pid (ptid),
1122              ptid_get_lwp (ptid), TT_NOPC, 0, 0);
1123      /* Return without stopping the whole process.  */
1124      ourstatus->kind = TARGET_WAITKIND_IGNORE;
1125      return ptid;
1126
1127    case TTEVT_SIGNAL:
1128      ourstatus->kind = TARGET_WAITKIND_STOPPED;
1129      ourstatus->value.sig =
1130	target_signal_from_host (tts.tts_u.tts_signal.tts_signo);
1131      break;
1132
1133    case TTEVT_SYSCALL_ENTRY:
1134      gdb_assert (inf_ttrace_reenable_page_protections == 0);
1135      inf_ttrace_num_lwps_in_syscall++;
1136      if (inf_ttrace_num_lwps_in_syscall == 1)
1137	{
1138	  /* A thread has just entered a system call.  Disable any
1139             page protections as the kernel can't deal with them.  */
1140	  inf_ttrace_disable_page_protections (tts.tts_pid);
1141	}
1142      ourstatus->kind = TARGET_WAITKIND_SYSCALL_ENTRY;
1143      ourstatus->value.syscall_number = tts.tts_scno;
1144      break;
1145
1146    case TTEVT_SYSCALL_RETURN:
1147      if (inf_ttrace_num_lwps_in_syscall > 0)
1148	{
1149	  /* If the last thread has just left the system call, this
1150	     would be a logical place to re-enable the page
1151	     protections, but that doesn't work.  We can't re-enable
1152	     them until we've done another wait.  */
1153	  inf_ttrace_reenable_page_protections =
1154	    (inf_ttrace_num_lwps_in_syscall == 1);
1155	  inf_ttrace_num_lwps_in_syscall--;
1156	}
1157      ourstatus->kind = TARGET_WAITKIND_SYSCALL_RETURN;
1158      ourstatus->value.syscall_number = tts.tts_scno;
1159      break;
1160
1161    default:
1162      gdb_assert (!"Unexpected ttrace event");
1163      break;
1164    }
1165
1166  /* Make sure all threads within the process are stopped.  */
1167  if (ttrace (TT_PROC_STOP, tts.tts_pid, 0, 0, 0, 0) == -1)
1168    perror_with_name (("ttrace"));
1169
1170  /* Now that the whole process is stopped, check if any dying thread
1171     is really dead by now.  If a dying thread is still alive, it will
1172     be stopped too, and will still show up in `info threads', tagged
1173     with "(Exiting)".  We could make `info threads' prune dead
1174     threads instead via inf_ttrace_thread_alive, but doing this here
1175     has the advantage that a frontend is notificed sooner of thread
1176     exits.  Note that a dying lwp is still alive, it still has to be
1177     resumed, like any other lwp.  */
1178  iterate_over_threads (inf_ttrace_delete_dead_threads_callback, NULL);
1179
1180  return ptid;
1181}
1182
1183/* Transfer LEN bytes from ADDR in the inferior's memory into READBUF,
1184   and transfer LEN bytes from WRITEBUF into the inferior's memory at
1185   ADDR.  Either READBUF or WRITEBUF may be null, in which case the
1186   corresponding transfer doesn't happen.  Return the number of bytes
1187   actually transferred (which may be zero if an error occurs).  */
1188
1189static LONGEST
1190inf_ttrace_xfer_memory (CORE_ADDR addr, ULONGEST len,
1191			void *readbuf, const void *writebuf)
1192{
1193  pid_t pid = ptid_get_pid (inferior_ptid);
1194
1195  /* HP-UX treats text space and data space differently.  GDB however,
1196     doesn't really know the difference.  Therefore we try both.  Try
1197     text space before data space though because when we're writing
1198     into text space the instruction cache might need to be flushed.  */
1199
1200  if (readbuf
1201      && ttrace (TT_PROC_RDTEXT, pid, 0, addr, len, (uintptr_t)readbuf) == -1
1202      && ttrace (TT_PROC_RDDATA, pid, 0, addr, len, (uintptr_t)readbuf) == -1)
1203    return 0;
1204
1205  if (writebuf
1206      && ttrace (TT_PROC_WRTEXT, pid, 0, addr, len, (uintptr_t)writebuf) == -1
1207      && ttrace (TT_PROC_WRDATA, pid, 0, addr, len, (uintptr_t)writebuf) == -1)
1208    return 0;
1209
1210  return len;
1211}
1212
1213static LONGEST
1214inf_ttrace_xfer_partial (struct target_ops *ops, enum target_object object,
1215			 const char *annex, gdb_byte *readbuf,
1216			 const gdb_byte *writebuf,
1217			 ULONGEST offset, LONGEST len)
1218{
1219  switch (object)
1220    {
1221    case TARGET_OBJECT_MEMORY:
1222      return inf_ttrace_xfer_memory (offset, len, readbuf, writebuf);
1223
1224    case TARGET_OBJECT_UNWIND_TABLE:
1225      return -1;
1226
1227    case TARGET_OBJECT_AUXV:
1228      return -1;
1229
1230    case TARGET_OBJECT_WCOOKIE:
1231      return -1;
1232
1233    default:
1234      return -1;
1235    }
1236}
1237
1238/* Print status information about what we're accessing.  */
1239
1240static void
1241inf_ttrace_files_info (struct target_ops *ignore)
1242{
1243  struct inferior *inf = current_inferior ();
1244  printf_filtered (_("\tUsing the running image of %s %s.\n"),
1245		   inf->attach_flag ? "attached" : "child",
1246		   target_pid_to_str (inferior_ptid));
1247}
1248
1249static int
1250inf_ttrace_thread_alive (struct target_ops *ops, ptid_t ptid)
1251{
1252  return 1;
1253}
1254
1255/* Return a string describing the state of the thread specified by
1256   INFO.  */
1257
1258static char *
1259inf_ttrace_extra_thread_info (struct thread_info *info)
1260{
1261  struct inf_ttrace_private_thread_info* private =
1262    (struct inf_ttrace_private_thread_info *) info->private;
1263
1264  if (private != NULL && private->dying)
1265    return "Exiting";
1266
1267  return NULL;
1268}
1269
1270static char *
1271inf_ttrace_pid_to_str (struct target_ops *ops, ptid_t ptid)
1272{
1273  pid_t pid = ptid_get_pid (ptid);
1274  lwpid_t lwpid = ptid_get_lwp (ptid);
1275  static char buf[128];
1276
1277  if (lwpid == 0)
1278    xsnprintf (buf, sizeof buf, "process %ld",
1279	       (long) pid);
1280  else
1281    xsnprintf (buf, sizeof buf, "process %ld, lwp %ld",
1282	       (long) pid, (long) lwpid);
1283  return buf;
1284}
1285
1286
1287/* Implement the get_ada_task_ptid target_ops method.  */
1288
1289static ptid_t
1290inf_ttrace_get_ada_task_ptid (long lwp, long thread)
1291{
1292  return ptid_build (ptid_get_pid (inferior_ptid), lwp, 0);
1293}
1294
1295
1296struct target_ops *
1297inf_ttrace_target (void)
1298{
1299  struct target_ops *t = inf_child_target ();
1300
1301  t->to_attach = inf_ttrace_attach;
1302  t->to_detach = inf_ttrace_detach;
1303  t->to_resume = inf_ttrace_resume;
1304  t->to_wait = inf_ttrace_wait;
1305  t->to_files_info = inf_ttrace_files_info;
1306  t->to_can_use_hw_breakpoint = inf_ttrace_can_use_hw_breakpoint;
1307  t->to_insert_watchpoint = inf_ttrace_insert_watchpoint;
1308  t->to_remove_watchpoint = inf_ttrace_remove_watchpoint;
1309  t->to_stopped_by_watchpoint = inf_ttrace_stopped_by_watchpoint;
1310  t->to_region_ok_for_hw_watchpoint =
1311    inf_ttrace_region_ok_for_hw_watchpoint;
1312  t->to_kill = inf_ttrace_kill;
1313  t->to_create_inferior = inf_ttrace_create_inferior;
1314  t->to_follow_fork = inf_ttrace_follow_fork;
1315  t->to_mourn_inferior = inf_ttrace_mourn_inferior;
1316  t->to_thread_alive = inf_ttrace_thread_alive;
1317  t->to_extra_thread_info = inf_ttrace_extra_thread_info;
1318  t->to_pid_to_str = inf_ttrace_pid_to_str;
1319  t->to_xfer_partial = inf_ttrace_xfer_partial;
1320  t->to_get_ada_task_ptid = inf_ttrace_get_ada_task_ptid;
1321
1322  return t;
1323}
1324#endif
1325
1326
1327/* Prevent warning from -Wmissing-prototypes.  */
1328void _initialize_hppa_hpux_nat (void);
1329
1330void
1331_initialize_inf_ttrace (void)
1332{
1333#ifdef HAVE_TTRACE
1334  inf_ttrace_page_dict.pagesize = getpagesize();
1335#endif
1336}
1337