2006-07-13 Denis PILAT <denis.pilat@st.com>
[platform/upstream/binutils.git] / gdb / inf-ttrace.c
1 /* Low-level child interface to ttrace.
2
3    Copyright (C) 2004, 2005, 2006 Free Software Foundation, Inc.
4
5    This file is part of GDB.
6
7    This program is free software; you can redistribute it and/or modify
8    it under the terms of the GNU General Public License as published by
9    the Free Software Foundation; either version 2 of the License, or
10    (at your option) any later version.
11
12    This program is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15    GNU General Public License for more details.
16
17    You should have received a copy of the GNU General Public License
18    along with this program; if not, write to the Free Software
19    Foundation, Inc., 51 Franklin Street, Fifth Floor,
20    Boston, MA 02110-1301, USA.  */
21
22 #include "defs.h"
23
24 /* The ttrace(2) system call didn't exist before HP-UX 10.30.  Don't
25    try to compile this code unless we have it.  */
26 #ifdef HAVE_TTRACE
27
28 #include "command.h"
29 #include "gdbcore.h"
30 #include "gdbthread.h"
31 #include "inferior.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
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 /* Number of lwps that are currently in a system call.  */
82 static int inf_ttrace_num_lwps_in_syscall;
83
84 /* Flag to indicate whether we should re-enable page protections after
85    the next wait.  */
86 static int inf_ttrace_reenable_page_protections;
87
88 /* Enable system call events for process PID.  */
89
90 static void
91 inf_ttrace_enable_syscall_events (pid_t pid)
92 {
93   ttevent_t tte;
94   ttstate_t tts;
95
96   gdb_assert (inf_ttrace_num_lwps_in_syscall == 0);
97
98   if (ttrace (TT_PROC_GET_EVENT_MASK, pid, 0,
99               (uintptr_t)&tte, sizeof tte, 0) == -1)
100     perror_with_name (("ttrace"));
101
102   tte.tte_events |= (TTEVT_SYSCALL_ENTRY | TTEVT_SYSCALL_RETURN);
103
104   if (ttrace (TT_PROC_SET_EVENT_MASK, pid, 0,
105               (uintptr_t)&tte, sizeof tte, 0) == -1)
106     perror_with_name (("ttrace"));
107
108   if (ttrace (TT_PROC_GET_FIRST_LWP_STATE, pid, 0,
109               (uintptr_t)&tts, sizeof tts, 0) == -1)
110     perror_with_name (("ttrace"));
111
112   if (tts.tts_flags & TTS_INSYSCALL)
113     inf_ttrace_num_lwps_in_syscall++;
114
115   /* FIXME: Handle multiple threads.  */
116 }
117
118 /* Disable system call events for process PID.  */
119
120 static void
121 inf_ttrace_disable_syscall_events (pid_t pid)
122 {
123   ttevent_t tte;
124
125   gdb_assert (inf_ttrace_page_dict.count == 0);
126
127   if (ttrace (TT_PROC_GET_EVENT_MASK, pid, 0,
128               (uintptr_t)&tte, sizeof tte, 0) == -1)
129     perror_with_name (("ttrace"));
130
131   tte.tte_events &= ~(TTEVT_SYSCALL_ENTRY | TTEVT_SYSCALL_RETURN);
132
133   if (ttrace (TT_PROC_SET_EVENT_MASK, pid, 0,
134               (uintptr_t)&tte, sizeof tte, 0) == -1)
135     perror_with_name (("ttrace"));
136
137   inf_ttrace_num_lwps_in_syscall = 0;
138 }
139
140 /* Get information about the page at address ADDR for process PID from
141    the dictionary.  */
142
143 static struct inf_ttrace_page *
144 inf_ttrace_get_page (pid_t pid, CORE_ADDR addr)
145 {
146   const int num_buckets = ARRAY_SIZE (inf_ttrace_page_dict.buckets);
147   const int pagesize = inf_ttrace_page_dict.pagesize;
148   int bucket;
149   struct inf_ttrace_page *page;
150
151   bucket = (addr / pagesize) % num_buckets;
152   page = &inf_ttrace_page_dict.buckets[bucket];
153   while (page)
154     {
155       if (page->addr == addr)
156         break;
157
158       page = page->next;
159     }
160
161   return page;
162 }
163
164 /* Add the page at address ADDR for process PID to the dictionary.  */
165
166 static struct inf_ttrace_page *
167 inf_ttrace_add_page (pid_t pid, CORE_ADDR addr)
168 {
169   const int num_buckets = ARRAY_SIZE (inf_ttrace_page_dict.buckets);
170   const int pagesize = inf_ttrace_page_dict.pagesize;
171   int bucket;
172   struct inf_ttrace_page *page;
173   struct inf_ttrace_page *prev = NULL;
174
175   bucket = (addr / pagesize) % num_buckets;
176   page = &inf_ttrace_page_dict.buckets[bucket];
177   while (page)
178     {
179       if (page->addr == addr)
180         break;
181
182       prev = page;
183       page = page->next;
184     }
185   
186   if (!page)
187     {
188       int prot;
189
190       if (ttrace (TT_PROC_GET_MPROTECT, pid, 0,
191                   addr, 0, (uintptr_t)&prot) == -1)
192         perror_with_name (("ttrace"));
193       
194       page = XMALLOC (struct inf_ttrace_page);
195       page->addr = addr;
196       page->prot = prot;
197       page->refcount = 0;
198       page->next = NULL;
199
200       page->prev = prev;
201       prev->next = page;
202
203       inf_ttrace_page_dict.count++;
204       if (inf_ttrace_page_dict.count == 1)
205         inf_ttrace_enable_syscall_events (pid);
206
207       if (inf_ttrace_num_lwps_in_syscall == 0)
208         {
209           if (ttrace (TT_PROC_SET_MPROTECT, pid, 0,
210                       addr, pagesize, prot & ~PROT_WRITE) == -1)
211             perror_with_name (("ttrace"));
212         }
213     }
214
215   return page;
216 }
217
218 /* Insert the page at address ADDR of process PID to the dictionary.  */
219
220 static void
221 inf_ttrace_insert_page (pid_t pid, CORE_ADDR addr)
222 {
223   struct inf_ttrace_page *page;
224
225   page = inf_ttrace_get_page (pid, addr);
226   if (!page)
227     page = inf_ttrace_add_page (pid, addr);
228
229   page->refcount++;
230 }
231
232 /* Remove the page at address ADDR of process PID from the dictionary.  */
233
234 static void
235 inf_ttrace_remove_page (pid_t pid, CORE_ADDR addr)
236 {
237   const int pagesize = inf_ttrace_page_dict.pagesize;
238   struct inf_ttrace_page *page;
239
240   page = inf_ttrace_get_page (pid, addr);
241   page->refcount--;
242
243   gdb_assert (page->refcount >= 0);
244
245   if (page->refcount == 0)
246     {
247       if (inf_ttrace_num_lwps_in_syscall == 0)
248         {
249           if (ttrace (TT_PROC_SET_MPROTECT, pid, 0,
250                       addr, pagesize, page->prot) == -1)
251             perror_with_name (("ttrace"));
252         }
253
254       inf_ttrace_page_dict.count--;
255       if (inf_ttrace_page_dict.count == 0)
256         inf_ttrace_disable_syscall_events (pid);
257
258       page->prev->next = page->next;
259       if (page->next)
260         page->next->prev = page->prev;
261
262       xfree (page);
263     }
264 }
265
266 /* Mask the bits in PROT from the page protections that are currently
267    in the dictionary for process PID.  */
268
269 static void
270 inf_ttrace_mask_page_protections (pid_t pid, int prot)
271 {
272   const int num_buckets = ARRAY_SIZE (inf_ttrace_page_dict.buckets);
273   const int pagesize = inf_ttrace_page_dict.pagesize;
274   int bucket;
275
276   for (bucket = 0; bucket < num_buckets; bucket++)
277     {
278       struct inf_ttrace_page *page;
279
280       page = inf_ttrace_page_dict.buckets[bucket].next;
281       while (page)
282         {
283           if (ttrace (TT_PROC_SET_MPROTECT, pid, 0,
284                       page->addr, pagesize, page->prot & ~prot) == -1)
285             perror_with_name (("ttrace"));
286
287           page = page->next;
288         }
289     }
290 }
291
292 /* Write-protect the pages in the dictionary for process PID.  */
293
294 static void
295 inf_ttrace_enable_page_protections (pid_t pid)
296 {
297   inf_ttrace_mask_page_protections (pid, PROT_WRITE);
298 }
299
300 /* Restore the protection of the pages in the dictionary for process
301    PID.  */
302
303 static void
304 inf_ttrace_disable_page_protections (pid_t pid)
305 {
306   inf_ttrace_mask_page_protections (pid, 0);
307 }
308
309 /* Insert a "hardware" watchpoint for LEN bytes at address ADDR of
310    type TYPE.  */
311
312 static int
313 inf_ttrace_insert_watchpoint (CORE_ADDR addr, int len, int type)
314 {
315   const int pagesize = inf_ttrace_page_dict.pagesize;
316   pid_t pid = ptid_get_pid (inferior_ptid);
317   CORE_ADDR page_addr;
318   int num_pages;
319   int page;
320
321   gdb_assert (type == hw_write);
322
323   page_addr = (addr / pagesize) * pagesize;
324   num_pages = (len + pagesize - 1) / pagesize;
325
326   for (page = 0; page < num_pages; page++, page_addr += pagesize)
327     inf_ttrace_insert_page (pid, page_addr);
328
329   return 1;
330 }
331
332 /* Remove a "hardware" watchpoint for LEN bytes at address ADDR of
333    type TYPE.  */
334
335 static int
336 inf_ttrace_remove_watchpoint (CORE_ADDR addr, int len, int type)
337 {
338   const int pagesize = inf_ttrace_page_dict.pagesize;
339   pid_t pid = ptid_get_pid (inferior_ptid);
340   CORE_ADDR page_addr;
341   int num_pages;
342   int page;
343
344   gdb_assert (type == hw_write);
345
346   page_addr = (addr / pagesize) * pagesize;
347   num_pages = (len + pagesize - 1) / pagesize;
348
349   for (page = 0; page < num_pages; page++, page_addr += pagesize)
350     inf_ttrace_remove_page (pid, page_addr);
351
352   return 1;
353 }
354
355 static int
356 inf_ttrace_can_use_hw_breakpoint (int type, int len, int ot)
357 {
358   return (type == bp_hardware_watchpoint);
359 }
360
361 static int
362 inf_ttrace_region_ok_for_hw_watchpoint (CORE_ADDR addr, int len)
363 {
364   return 1;
365 }
366
367 /* Return non-zero if the current inferior was (potentially) stopped
368    by hitting a "hardware" watchpoint.  */
369
370 static int
371 inf_ttrace_stopped_by_watchpoint (void)
372 {
373   pid_t pid = ptid_get_pid (inferior_ptid);
374   lwpid_t lwpid = ptid_get_lwp (inferior_ptid);
375   ttstate_t tts;
376
377   if (inf_ttrace_page_dict.count > 0)
378     {
379       if (ttrace (TT_LWP_GET_STATE, pid, lwpid,
380                   (uintptr_t)&tts, sizeof tts, 0) == -1)
381         perror_with_name (("ttrace"));
382
383       if (tts.tts_event == TTEVT_SIGNAL
384           && tts.tts_u.tts_signal.tts_signo == SIGBUS)
385         {
386           const int pagesize = inf_ttrace_page_dict.pagesize;
387           void *addr = tts.tts_u.tts_signal.tts_siginfo.si_addr;
388           CORE_ADDR page_addr = ((uintptr_t)addr / pagesize) * pagesize;
389
390           if (inf_ttrace_get_page (pid, page_addr))
391             return 1;
392         }
393     }
394
395   return 0;
396 }
397 \f
398
399 /* When tracking a vfork(2), we cannot detach from the parent until
400    after the child has called exec(3) or has exited.  If we are still
401    attached to the parent, this variable will be set to the process ID
402    of the parent.  Otherwise it will be set to zero.  */
403 static pid_t inf_ttrace_vfork_ppid = -1;
404
405 static int
406 inf_ttrace_follow_fork (struct target_ops *ops, int follow_child)
407 {
408   pid_t pid, fpid;
409   lwpid_t lwpid, flwpid;
410   ttstate_t tts;
411
412   /* FIXME: kettenis/20050720: This stuff should really be passed as
413      an argument by our caller.  */
414   {
415     ptid_t ptid;
416     struct target_waitstatus status;
417
418     get_last_target_status (&ptid, &status);
419     gdb_assert (status.kind == TARGET_WAITKIND_FORKED
420                 || status.kind == TARGET_WAITKIND_VFORKED);
421
422     pid = ptid_get_pid (ptid);
423     lwpid = ptid_get_lwp (ptid);
424   }
425
426   /* Get all important details that core GDB doesn't (and shouldn't)
427      know about.  */
428   if (ttrace (TT_LWP_GET_STATE, pid, lwpid,
429               (uintptr_t)&tts, sizeof tts, 0) == -1)
430     perror_with_name (("ttrace"));
431
432   gdb_assert (tts.tts_event == TTEVT_FORK || tts.tts_event == TTEVT_VFORK);
433
434   if (tts.tts_u.tts_fork.tts_isparent)
435     {
436       pid = tts.tts_pid;
437       lwpid = tts.tts_lwpid;
438       fpid = tts.tts_u.tts_fork.tts_fpid;
439       flwpid = tts.tts_u.tts_fork.tts_flwpid;
440     }
441   else
442     {
443       pid = tts.tts_u.tts_fork.tts_fpid;
444       lwpid = tts.tts_u.tts_fork.tts_flwpid;
445       fpid = tts.tts_pid;
446       flwpid = tts.tts_lwpid;
447     }
448
449   if (follow_child)
450     {
451       inferior_ptid = ptid_build (fpid, flwpid, 0);
452       detach_breakpoints (pid);
453
454       target_terminal_ours ();
455       fprintf_unfiltered (gdb_stdlog, _("\
456 Attaching after fork to child process %ld.\n"), (long)fpid);
457     }
458   else
459     {
460       inferior_ptid = ptid_build (pid, lwpid, 0);
461       detach_breakpoints (fpid);
462
463       target_terminal_ours ();
464       fprintf_unfiltered (gdb_stdlog, _("\
465 Detaching after fork from child process %ld.\n"), (long)fpid);
466     }
467
468   if (tts.tts_event == TTEVT_VFORK)
469     {
470       gdb_assert (!tts.tts_u.tts_fork.tts_isparent);
471
472       if (follow_child)
473         {
474           /* We can't detach from the parent yet.  */
475           inf_ttrace_vfork_ppid = pid;
476
477           reattach_breakpoints (fpid);
478         }
479       else
480         {
481           if (ttrace (TT_PROC_DETACH, fpid, 0, 0, 0, 0) == -1)
482             perror_with_name (("ttrace"));
483
484           /* Wait till we get the TTEVT_VFORK event in the parent.
485              This indicates that the child has called exec(3) or has
486              exited and that the parent is ready to be traced again.  */
487           if (ttrace_wait (pid, lwpid, TTRACE_WAITOK, &tts, sizeof tts) == -1)
488             perror_with_name (("ttrace_wait"));
489           gdb_assert (tts.tts_event == TTEVT_VFORK);
490           gdb_assert (tts.tts_u.tts_fork.tts_isparent);
491
492           reattach_breakpoints (pid);
493         }
494     }
495   else
496     {
497       gdb_assert (tts.tts_u.tts_fork.tts_isparent);
498
499       if (follow_child)
500         {
501           if (ttrace (TT_PROC_DETACH, pid, 0, 0, 0, 0) == -1)
502             perror_with_name (("ttrace"));
503         }
504       else
505         {
506           if (ttrace (TT_PROC_DETACH, fpid, 0, 0, 0, 0) == -1)
507             perror_with_name (("ttrace"));
508         }
509     }
510
511   if (follow_child)
512     {
513       /* The child will start out single-threaded.  */
514       inf_ttrace_num_lwps = 0;
515       inf_ttrace_num_lwps_in_syscall = 0;
516
517       /* Reset breakpoints in the child as appropriate.  */
518       follow_inferior_reset_breakpoints ();
519     }
520
521   return 0;
522 }
523 \f
524
525 /* File descriptors for pipes used as semaphores during initial
526    startup of an inferior.  */
527 static int inf_ttrace_pfd1[2];
528 static int inf_ttrace_pfd2[2];
529
530 static void
531 do_cleanup_pfds (void *dummy)
532 {
533   close (inf_ttrace_pfd1[0]);
534   close (inf_ttrace_pfd1[1]);
535   close (inf_ttrace_pfd2[0]);
536   close (inf_ttrace_pfd2[1]);
537 }
538
539 static void
540 inf_ttrace_prepare (void)
541 {
542   if (pipe (inf_ttrace_pfd1) == -1)
543     perror_with_name (("pipe"));
544
545   if (pipe (inf_ttrace_pfd2) == -1)
546     {
547       close (inf_ttrace_pfd1[0]);
548       close (inf_ttrace_pfd2[0]);
549       perror_with_name (("pipe"));
550     }
551 }
552
553 /* Prepare to be traced.  */
554
555 static void
556 inf_ttrace_me (void)
557 {
558   struct cleanup *old_chain = make_cleanup (do_cleanup_pfds, 0);
559   char c;
560
561   /* "Trace me, Dr. Memory!"  */
562   if (ttrace (TT_PROC_SETTRC, 0, 0, 0, TT_VERSION, 0) == -1)
563     perror_with_name (("ttrace"));
564
565   /* Tell our parent that we are ready to be traced.  */
566   if (write (inf_ttrace_pfd1[1], &c, sizeof c) != sizeof c)
567     perror_with_name (("write"));
568
569   /* Wait until our parent has set the initial event mask.  */
570   if (read (inf_ttrace_pfd2[0], &c, sizeof c) != sizeof c)
571     perror_with_name (("read"));
572
573   do_cleanups (old_chain);
574 }
575
576 /* Start tracing PID.  */
577
578 static void
579 inf_ttrace_him (int pid)
580 {
581   struct cleanup *old_chain = make_cleanup (do_cleanup_pfds, 0);
582   ttevent_t tte;
583   char c;
584
585   /* Wait until our child is ready to be traced.  */
586   if (read (inf_ttrace_pfd1[0], &c, sizeof c) != sizeof c)
587     perror_with_name (("read"));
588
589   /* Set the initial event mask.  */
590   memset (&tte, 0, sizeof (tte));
591   tte.tte_events |= TTEVT_EXEC | TTEVT_EXIT | TTEVT_FORK | TTEVT_VFORK;
592   tte.tte_events |= TTEVT_LWP_CREATE | TTEVT_LWP_EXIT | TTEVT_LWP_TERMINATE;
593 #ifdef TTEVT_BPT_SSTEP
594   tte.tte_events |= TTEVT_BPT_SSTEP;
595 #endif
596   tte.tte_opts |= TTEO_PROC_INHERIT;
597   if (ttrace (TT_PROC_SET_EVENT_MASK, pid, 0,
598               (uintptr_t)&tte, sizeof tte, 0) == -1)
599     perror_with_name (("ttrace"));
600
601   /* Tell our child that we have set the initial event mask.  */
602   if (write (inf_ttrace_pfd2[1], &c, sizeof c) != sizeof c)
603     perror_with_name (("write"));
604
605   do_cleanups (old_chain);
606
607   push_target (ttrace_ops_hack);
608
609   /* On some targets, there must be some explicit synchronization
610      between the parent and child processes after the debugger forks,
611      and before the child execs the debuggee program.  This call
612      basically gives permission for the child to exec.  */
613
614   target_acknowledge_created_inferior (pid);
615
616   /* START_INFERIOR_TRAPS_EXPECTED is defined in inferior.h, and will
617      be 1 or 2 depending on whether we're starting without or with a
618      shell.  */
619   startup_inferior (START_INFERIOR_TRAPS_EXPECTED);
620
621   /* On some targets, there must be some explicit actions taken after
622      the inferior has been started up.  */
623   target_post_startup_inferior (pid_to_ptid (pid));
624 }
625
626 static void
627 inf_ttrace_create_inferior (char *exec_file, char *allargs, char **env,
628                             int from_tty)
629 {
630   gdb_assert (inf_ttrace_num_lwps == 0);
631   gdb_assert (inf_ttrace_num_lwps_in_syscall == 0);
632   gdb_assert (inf_ttrace_page_dict.count == 0);
633   gdb_assert (inf_ttrace_reenable_page_protections == 0);
634   gdb_assert (inf_ttrace_vfork_ppid == -1);
635
636   fork_inferior (exec_file, allargs, env, inf_ttrace_me, inf_ttrace_him,
637                  inf_ttrace_prepare, NULL);
638 }
639
640 static void
641 inf_ttrace_mourn_inferior (void)
642 {
643   const int num_buckets = ARRAY_SIZE (inf_ttrace_page_dict.buckets);
644   int bucket;
645
646   inf_ttrace_num_lwps = 0;
647   inf_ttrace_num_lwps_in_syscall = 0;
648
649   for (bucket = 0; bucket < num_buckets; bucket++)
650     {
651       struct inf_ttrace_page *page;
652       struct inf_ttrace_page *next;
653
654       page = inf_ttrace_page_dict.buckets[bucket].next;
655       while (page)
656         {
657           next = page->next;
658           xfree (page);
659           page = next;
660         }
661     }
662   inf_ttrace_page_dict.count = 0;
663
664   unpush_target (ttrace_ops_hack);
665   generic_mourn_inferior ();
666 }
667
668 static void
669 inf_ttrace_attach (char *args, int from_tty)
670 {
671   char *exec_file;
672   pid_t pid;
673   char *dummy;
674   ttevent_t tte;
675
676   if (!args)
677     error_no_arg (_("process-id to attach"));
678
679   dummy = args;
680   pid = strtol (args, &dummy, 0);
681   if (pid == 0 && args == dummy)
682     error (_("Illegal process-id: %s."), args);
683
684   if (pid == getpid ())         /* Trying to masturbate?  */
685     error (_("I refuse to debug myself!"));
686
687   if (from_tty)
688     {
689       exec_file = get_exec_file (0);
690
691       if (exec_file)
692         printf_unfiltered (_("Attaching to program: %s, %s\n"), exec_file,
693                            target_pid_to_str (pid_to_ptid (pid)));
694       else
695         printf_unfiltered (_("Attaching to %s\n"),
696                            target_pid_to_str (pid_to_ptid (pid)));
697
698       gdb_flush (gdb_stdout);
699     }
700
701   gdb_assert (inf_ttrace_num_lwps == 0);
702   gdb_assert (inf_ttrace_num_lwps_in_syscall == 0);
703   gdb_assert (inf_ttrace_vfork_ppid == -1);
704
705   if (ttrace (TT_PROC_ATTACH, pid, 0, TT_KILL_ON_EXIT, TT_VERSION, 0) == -1)
706     perror_with_name (("ttrace"));
707   attach_flag = 1;
708
709   /* Set the initial event mask.  */
710   memset (&tte, 0, sizeof (tte));
711   tte.tte_events |= TTEVT_EXEC | TTEVT_EXIT | TTEVT_FORK | TTEVT_VFORK;
712   tte.tte_events |= TTEVT_LWP_CREATE | TTEVT_LWP_EXIT | TTEVT_LWP_TERMINATE;
713 #ifdef TTEVT_BPT_SSTEP
714   tte.tte_events |= TTEVT_BPT_SSTEP;
715 #endif
716   tte.tte_opts |= TTEO_PROC_INHERIT;
717   if (ttrace (TT_PROC_SET_EVENT_MASK, pid, 0,
718               (uintptr_t)&tte, sizeof tte, 0) == -1)
719     perror_with_name (("ttrace"));
720
721   inferior_ptid = pid_to_ptid (pid);
722   push_target (ttrace_ops_hack);
723 }
724
725 static void
726 inf_ttrace_detach (char *args, int from_tty)
727 {
728   pid_t pid = ptid_get_pid (inferior_ptid);
729   int sig = 0;
730
731   if (from_tty)
732     {
733       char *exec_file = get_exec_file (0);
734       if (exec_file == 0)
735         exec_file = "";
736       printf_unfiltered (_("Detaching from program: %s, %s\n"), exec_file,
737                          target_pid_to_str (pid_to_ptid (pid)));
738       gdb_flush (gdb_stdout);
739     }
740   if (args)
741     sig = atoi (args);
742
743   /* ??? The HP-UX 11.0 ttrace(2) manual page doesn't mention that we
744      can pass a signal number here.  Does this really work?  */
745   if (ttrace (TT_PROC_DETACH, pid, 0, 0, sig, 0) == -1)
746     perror_with_name (("ttrace"));
747
748   if (inf_ttrace_vfork_ppid != -1)
749     {
750       if (ttrace (TT_PROC_DETACH, inf_ttrace_vfork_ppid, 0, 0, 0, 0) == -1)
751         perror_with_name (("ttrace"));
752       inf_ttrace_vfork_ppid = -1;
753     }
754
755   inf_ttrace_num_lwps = 0;
756   inf_ttrace_num_lwps_in_syscall = 0;
757
758   unpush_target (ttrace_ops_hack);
759   inferior_ptid = null_ptid;
760 }
761
762 static void
763 inf_ttrace_kill (void)
764 {
765   pid_t pid = ptid_get_pid (inferior_ptid);
766
767   if (pid == 0)
768     return;
769
770   if (ttrace (TT_PROC_EXIT, pid, 0, 0, 0, 0) == -1)
771     perror_with_name (("ttrace"));
772   /* ??? Is it necessary to call ttrace_wait() here?  */
773
774   if (inf_ttrace_vfork_ppid != -1)
775     {
776       if (ttrace (TT_PROC_DETACH, inf_ttrace_vfork_ppid, 0, 0, 0, 0) == -1)
777         perror_with_name (("ttrace"));
778       inf_ttrace_vfork_ppid = -1;
779     }
780
781   target_mourn_inferior ();
782 }
783
784 static int
785 inf_ttrace_resume_callback (struct thread_info *info, void *arg)
786 {
787   if (!ptid_equal (info->ptid, inferior_ptid))
788     {
789       pid_t pid = ptid_get_pid (info->ptid);
790       lwpid_t lwpid = ptid_get_lwp (info->ptid);
791
792       if (ttrace (TT_LWP_CONTINUE, pid, lwpid, TT_NOPC, 0, 0) == -1)
793         perror_with_name (("ttrace"));
794     }
795
796   return 0;
797 }
798
799 static void
800 inf_ttrace_resume (ptid_t ptid, int step, enum target_signal signal)
801 {
802   pid_t pid = ptid_get_pid (ptid);
803   lwpid_t lwpid = ptid_get_lwp (ptid);
804   ttreq_t request = step ? TT_LWP_SINGLE : TT_LWP_CONTINUE;
805   int sig = target_signal_to_host (signal);
806
807   if (pid == -1)
808     {
809       pid = ptid_get_pid (inferior_ptid);
810       lwpid = ptid_get_lwp (inferior_ptid);
811     }
812
813   if (ttrace (request, pid, lwpid, TT_NOPC, sig, 0) == -1)
814     perror_with_name (("ttrace"));
815
816   if (ptid_equal (ptid, minus_one_ptid) && inf_ttrace_num_lwps > 0)
817     {
818       /* Let all the other threads run too.  */
819       iterate_over_threads (inf_ttrace_resume_callback, NULL);
820     }
821 }
822
823 static ptid_t
824 inf_ttrace_wait (ptid_t ptid, struct target_waitstatus *ourstatus)
825 {
826   pid_t pid = ptid_get_pid (ptid);
827   lwpid_t lwpid = ptid_get_lwp (ptid);
828   ttstate_t tts;
829
830   /* Until proven otherwise.  */
831   ourstatus->kind = TARGET_WAITKIND_SPURIOUS;
832
833   if (pid == -1)
834     pid = lwpid = 0;
835
836   gdb_assert (pid != 0 || lwpid == 0);
837
838   do
839     {
840       set_sigint_trap ();
841       set_sigio_trap ();
842
843       if (ttrace_wait (pid, lwpid, TTRACE_WAITOK, &tts, sizeof tts) == -1)
844         perror_with_name (("ttrace_wait"));
845
846       if (tts.tts_event == TTEVT_VFORK && tts.tts_u.tts_fork.tts_isparent)
847         {
848           if (inf_ttrace_vfork_ppid != -1)
849             {
850               gdb_assert (inf_ttrace_vfork_ppid == tts.tts_pid);
851
852               if (ttrace (TT_PROC_DETACH, tts.tts_pid, 0, 0, 0, 0) == -1)
853                 perror_with_name (("ttrace"));
854               inf_ttrace_vfork_ppid = -1;
855             }
856
857           tts.tts_event = TTEVT_NONE;
858         }
859
860       clear_sigio_trap ();
861       clear_sigint_trap ();
862     }
863   while (tts.tts_event == TTEVT_NONE);
864
865   /* Now that we've waited, we can re-enable the page protections.  */
866   if (inf_ttrace_reenable_page_protections)
867     {
868       gdb_assert (inf_ttrace_num_lwps_in_syscall == 0);
869       inf_ttrace_enable_page_protections (tts.tts_pid);
870       inf_ttrace_reenable_page_protections = 0;
871     }
872
873   ptid = ptid_build (tts.tts_pid, tts.tts_lwpid, 0);
874
875   switch (tts.tts_event)
876     {
877 #ifdef TTEVT_BPT_SSTEP
878     case TTEVT_BPT_SSTEP:
879       /* Make it look like a breakpoint.  */
880       ourstatus->kind = TARGET_WAITKIND_STOPPED;
881       ourstatus->value.sig = TARGET_SIGNAL_TRAP;
882       break;
883 #endif
884
885     case TTEVT_EXEC:
886       /* FIXME: kettenis/20051029: GDB doesn't really know how to deal
887          with TARGET_WAITKIND_EXECD events yet.  So we make it look
888          like a SIGTRAP instead.  */
889 #if 0
890       ourstatus->kind = TARGET_WAITKIND_EXECD;
891       ourstatus->value.execd_pathname =
892         xmalloc (tts.tts_u.tts_exec.tts_pathlen + 1);
893       if (ttrace (TT_PROC_GET_PATHNAME, tts.tts_pid, 0,
894                   (uintptr_t)ourstatus->value.execd_pathname,
895                   tts.tts_u.tts_exec.tts_pathlen, 0) == -1)
896         perror_with_name (("ttrace"));
897       ourstatus->value.execd_pathname[tts.tts_u.tts_exec.tts_pathlen] = 0;
898 #else
899       ourstatus->kind = TARGET_WAITKIND_STOPPED;
900       ourstatus->value.sig = TARGET_SIGNAL_TRAP;
901 #endif
902       break;
903
904     case TTEVT_EXIT:
905       store_waitstatus (ourstatus, tts.tts_u.tts_exit.tts_exitcode);
906       inf_ttrace_num_lwps = 0;
907       break;
908
909     case TTEVT_FORK:
910       ourstatus->kind = TARGET_WAITKIND_FORKED;
911       ourstatus->value.related_pid = tts.tts_u.tts_fork.tts_fpid;
912
913       /* Make sure the other end of the fork is stopped too.  */
914       if (ttrace_wait (tts.tts_u.tts_fork.tts_fpid,
915                        tts.tts_u.tts_fork.tts_flwpid,
916                        TTRACE_WAITOK, &tts, sizeof tts) == -1)
917         perror_with_name (("ttrace_wait"));
918
919       gdb_assert (tts.tts_event == TTEVT_FORK);
920       if (tts.tts_u.tts_fork.tts_isparent)
921         {
922           ptid = ptid_build (tts.tts_pid, tts.tts_lwpid, 0);
923           ourstatus->value.related_pid = tts.tts_u.tts_fork.tts_fpid;
924         }
925       break;
926
927     case TTEVT_VFORK:
928       gdb_assert (!tts.tts_u.tts_fork.tts_isparent);
929
930       ourstatus->kind = TARGET_WAITKIND_VFORKED;
931       ourstatus->value.related_pid = tts.tts_u.tts_fork.tts_fpid;
932
933       /* HACK: To avoid touching the parent during the vfork, switch
934          away from it.  */
935       inferior_ptid = ptid;
936       break;
937
938     case TTEVT_LWP_CREATE:
939       lwpid = tts.tts_u.tts_thread.tts_target_lwpid;
940       ptid = ptid_build (tts.tts_pid, lwpid, 0);
941       if (inf_ttrace_num_lwps == 0)
942         {
943           /* Now that we're going to be multi-threaded, add the
944              original thread to the list first.  */
945           add_thread (ptid_build (tts.tts_pid, tts.tts_lwpid, 0));
946           inf_ttrace_num_lwps++;
947         }
948       printf_filtered (_("[New %s]\n"), target_pid_to_str (ptid));
949       add_thread (ptid);
950       inf_ttrace_num_lwps++;
951       ptid = ptid_build (tts.tts_pid, tts.tts_lwpid, 0);
952       break;
953
954     case TTEVT_LWP_EXIT:
955       printf_filtered(_("[%s exited]\n"), target_pid_to_str (ptid));
956       delete_thread (ptid);
957       inf_ttrace_num_lwps--;
958       /* If we don't return -1 here, core GDB will re-add the thread.  */
959       ptid = minus_one_ptid;
960       break;
961
962     case TTEVT_LWP_TERMINATE:
963       lwpid = tts.tts_u.tts_thread.tts_target_lwpid;
964       ptid = ptid_build (tts.tts_pid, lwpid, 0);
965       printf_filtered(_("[%s has been terminated]\n"), target_pid_to_str (ptid));
966       delete_thread (ptid);
967       inf_ttrace_num_lwps--;
968       ptid = ptid_build (tts.tts_pid, tts.tts_lwpid, 0);
969       break;
970
971     case TTEVT_SIGNAL:
972       ourstatus->kind = TARGET_WAITKIND_STOPPED;
973       ourstatus->value.sig =
974         target_signal_from_host (tts.tts_u.tts_signal.tts_signo);
975       break;
976
977     case TTEVT_SYSCALL_ENTRY:
978       gdb_assert (inf_ttrace_reenable_page_protections == 0);
979       inf_ttrace_num_lwps_in_syscall++;
980       if (inf_ttrace_num_lwps_in_syscall == 1)
981         {
982           /* A thread has just entered a system call.  Disable any
983              page protections as the kernel can't deal with them.  */
984           inf_ttrace_disable_page_protections (tts.tts_pid);
985         }
986       ourstatus->kind = TARGET_WAITKIND_SYSCALL_ENTRY;
987       ourstatus->value.syscall_id = tts.tts_scno;
988       break;
989
990     case TTEVT_SYSCALL_RETURN:
991       if (inf_ttrace_num_lwps_in_syscall > 0)
992         {
993           /* If the last thread has just left the system call, this
994              would be a logical place to re-enable the page
995              protections, but that doesn't work.  We can't re-enable
996              them until we've done another wait.  */
997           inf_ttrace_reenable_page_protections = 
998             (inf_ttrace_num_lwps_in_syscall == 1);
999           inf_ttrace_num_lwps_in_syscall--;
1000         }
1001       ourstatus->kind = TARGET_WAITKIND_SYSCALL_RETURN;
1002       ourstatus->value.syscall_id = tts.tts_scno;
1003       break;
1004
1005     default:
1006       gdb_assert (!"Unexpected ttrace event");
1007       break;
1008     }
1009
1010   /* Make sure all threads within the process are stopped.  */
1011   if (ttrace (TT_PROC_STOP, tts.tts_pid, 0, 0, 0, 0) == -1)
1012     perror_with_name (("ttrace"));
1013
1014   /* HACK: Twiddle INFERIOR_PTID such that the initial thread of a
1015      process isn't recognized as a new thread.  */
1016   if (ptid_get_lwp (inferior_ptid) == 0)
1017     inferior_ptid = ptid;
1018
1019   return ptid;
1020 }
1021
1022 /* Transfer LEN bytes from ADDR in the inferior's memory into READBUF,
1023    and transfer LEN bytes from WRITEBUF into the inferior's memory at
1024    ADDR.  Either READBUF or WRITEBUF may be null, in which case the
1025    corresponding transfer doesn't happen.  Return the number of bytes
1026    actually transferred (which may be zero if an error occurs).  */
1027
1028 static LONGEST
1029 inf_ttrace_xfer_memory (CORE_ADDR addr, ULONGEST len,
1030                         void *readbuf, const void *writebuf)
1031 {
1032   pid_t pid = ptid_get_pid (inferior_ptid);
1033
1034   /* HP-UX treats text space and data space differently.  GDB however,
1035      doesn't really know the difference.  Therefore we try both.  Try
1036      text space before data space though because when we're writing
1037      into text space the instruction cache might need to be flushed.  */
1038
1039   if (readbuf
1040       && ttrace (TT_PROC_RDTEXT, pid, 0, addr, len, (uintptr_t)readbuf) == -1
1041       && ttrace (TT_PROC_RDDATA, pid, 0, addr, len, (uintptr_t)readbuf) == -1)
1042     return 0;
1043
1044   if (writebuf
1045       && ttrace (TT_PROC_WRTEXT, pid, 0, addr, len, (uintptr_t)writebuf) == -1
1046       && ttrace (TT_PROC_WRDATA, pid, 0, addr, len, (uintptr_t)writebuf) == -1)
1047     return 0;
1048
1049   return len;
1050 }
1051
1052 static LONGEST
1053 inf_ttrace_xfer_partial (struct target_ops *ops, enum target_object object,
1054                          const char *annex, gdb_byte *readbuf,
1055                          const gdb_byte *writebuf, ULONGEST offset, LONGEST len)
1056 {
1057   switch (object)
1058     {
1059     case TARGET_OBJECT_MEMORY:
1060       return inf_ttrace_xfer_memory (offset, len, readbuf, writebuf);
1061
1062     case TARGET_OBJECT_UNWIND_TABLE:
1063       return -1;
1064
1065     case TARGET_OBJECT_AUXV:
1066       return -1;
1067
1068     case TARGET_OBJECT_WCOOKIE:
1069       return -1;
1070
1071     default:
1072       return -1;
1073     }
1074 }
1075
1076 /* Print status information about what we're accessing.  */
1077
1078 static void
1079 inf_ttrace_files_info (struct target_ops *ignore)
1080 {
1081   printf_filtered (_("\tUsing the running image of %s %s.\n"),
1082                    attach_flag ? "attached" : "child",
1083                    target_pid_to_str (inferior_ptid));
1084 }
1085
1086 static int
1087 inf_ttrace_thread_alive (ptid_t ptid)
1088 {
1089   return 1;
1090 }
1091
1092 static char *
1093 inf_ttrace_pid_to_str (ptid_t ptid)
1094 {
1095   if (inf_ttrace_num_lwps > 0)
1096     {
1097       pid_t pid = ptid_get_pid (ptid);
1098       lwpid_t lwpid = ptid_get_lwp (ptid);
1099       static char buf[128];
1100
1101       xsnprintf (buf, sizeof buf, "process %ld, lwp %ld",
1102                  (long)pid, (long)lwpid);
1103       return buf;
1104     }
1105
1106   return normal_pid_to_str (ptid);
1107 }
1108 \f
1109
1110 struct target_ops *
1111 inf_ttrace_target (void)
1112 {
1113   struct target_ops *t = inf_child_target ();
1114
1115   t->to_attach = inf_ttrace_attach;
1116   t->to_detach = inf_ttrace_detach;
1117   t->to_resume = inf_ttrace_resume;
1118   t->to_wait = inf_ttrace_wait;
1119   t->to_files_info = inf_ttrace_files_info;
1120   t->to_can_use_hw_breakpoint = inf_ttrace_can_use_hw_breakpoint;
1121   t->to_insert_watchpoint = inf_ttrace_insert_watchpoint;
1122   t->to_remove_watchpoint = inf_ttrace_remove_watchpoint;
1123   t->to_stopped_by_watchpoint = inf_ttrace_stopped_by_watchpoint;
1124   t->to_region_ok_for_hw_watchpoint =
1125     inf_ttrace_region_ok_for_hw_watchpoint;
1126   t->to_kill = inf_ttrace_kill;
1127   t->to_create_inferior = inf_ttrace_create_inferior;
1128   t->to_follow_fork = inf_ttrace_follow_fork;
1129   t->to_mourn_inferior = inf_ttrace_mourn_inferior;
1130   t->to_thread_alive = inf_ttrace_thread_alive;
1131   t->to_pid_to_str = inf_ttrace_pid_to_str;
1132   t->to_xfer_partial = inf_ttrace_xfer_partial;
1133
1134   ttrace_ops_hack = t;
1135   return t;
1136 }
1137 #endif
1138 \f
1139
1140 /* Prevent warning from -Wmissing-prototypes.  */
1141 void _initialize_hppa_hpux_nat (void);
1142
1143 void
1144 _initialize_inf_ttrace (void)
1145 {
1146 #ifdef HAVE_TTRACE
1147   inf_ttrace_page_dict.pagesize = getpagesize();
1148 #endif
1149 }