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