* lib/gas-defs.exp: Support new directive "warning".
[platform/upstream/binutils.git] / gdb / inf-ttrace.c
1 /* Low-level child interface to ttrace.
2
3    Copyright 2004 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., 59 Temple Place - Suite 330,
20    Boston, MA 02111-1307, 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 "observer.h"
33 #include "target.h"
34
35 #include "gdb_assert.h"
36 #include "gdb_string.h"
37 #include <sys/mman.h>
38 #include <sys/ttrace.h>
39
40 #include "inf-child.h"
41 #include "inf-ttrace.h"
42
43 /* HACK: Save the ttrace ops returned by inf_ttrace_target.  */
44 static struct target_ops *ttrace_ops_hack;
45 \f
46
47 /* HP-UX uses a threading model where each user-space thread
48    corresponds to a kernel thread.  These kernel threads are called
49    lwps.  The ttrace(2) interface gives us almost full control over
50    the threads, which makes it very easy to support them in GDB.  We
51    identify the threads by process ID and lwp ID.  The ttrace(2) also
52    provides us with a thread's user ID (in the `tts_user_tid' member
53    of `ttstate_t') but we don't use that (yet) as it isn't necessary
54    to uniquely label the thread.  */
55
56 /* Number of active lwps.  */
57 static int inf_ttrace_num_lwps;
58 \f
59
60 /* On HP-UX versions that have the ttrace(2) system call, we can
61    implement "hardware" watchpoints by fiddling with the protection of
62    pages in the address space that contain the variable being watched.
63    In order to implement this, we keep a dictionary of pages for which
64    we have changed the protection.  */
65
66 struct inf_ttrace_page
67 {
68   CORE_ADDR addr;               /* Page address.  */
69   int prot;                     /* Protection.  */
70   int refcount;                 /* Reference count.  */
71   struct inf_ttrace_page *next;
72   struct inf_ttrace_page *prev;
73 };
74
75 struct inf_ttrace_page_dict
76 {
77   struct inf_ttrace_page buckets[128];
78   int pagesize;                 /* Page size.  */
79   int count;                    /* Number of pages in this dictionary.  */
80 } inf_ttrace_page_dict;
81
82 /* Number of lwps that are currently in a system call.  */
83 static int inf_ttrace_num_lwps_in_syscall;
84
85 /* Flag to indicate whether we should re-enable page protections after
86    the next wait.  */
87 static int inf_ttrace_reenable_page_protections;
88
89 /* Enable system call events for process PID.  */
90
91 static void
92 inf_ttrace_enable_syscall_events (pid_t pid)
93 {
94   ttevent_t tte;
95   ttstate_t tts;
96
97   gdb_assert (inf_ttrace_num_lwps_in_syscall == 0);
98
99   if (ttrace (TT_PROC_GET_EVENT_MASK, pid, 0,
100               (uintptr_t)&tte, sizeof tte, 0) == -1)
101     perror_with_name ("ttrace");
102
103   tte.tte_events |= (TTEVT_SYSCALL_ENTRY | TTEVT_SYSCALL_RETURN);
104
105   if (ttrace (TT_PROC_SET_EVENT_MASK, pid, 0,
106               (uintptr_t)&tte, sizeof tte, 0) == -1)
107     perror_with_name ("ttrace");
108
109   if (ttrace (TT_PROC_GET_FIRST_LWP_STATE, pid, 0,
110               (uintptr_t)&tts, sizeof tts, 0) == -1)
111     perror_with_name ("ttrace");
112
113   if (tts.tts_flags & TTS_INSYSCALL)
114     inf_ttrace_num_lwps_in_syscall++;
115
116   /* FIXME: Handle multiple threads.  */
117 }
118
119 /* Disable system call events for process PID.  */
120
121 static void
122 inf_ttrace_disable_syscall_events (pid_t pid)
123 {
124   ttevent_t tte;
125
126   gdb_assert (inf_ttrace_page_dict.count == 0);
127
128   if (ttrace (TT_PROC_GET_EVENT_MASK, pid, 0,
129               (uintptr_t)&tte, sizeof tte, 0) == -1)
130     perror_with_name ("ttrace");
131
132   tte.tte_events &= ~(TTEVT_SYSCALL_ENTRY | TTEVT_SYSCALL_RETURN);
133
134   if (ttrace (TT_PROC_SET_EVENT_MASK, pid, 0,
135               (uintptr_t)&tte, sizeof tte, 0) == -1)
136     perror_with_name ("ttrace");
137
138   inf_ttrace_num_lwps_in_syscall = 0;
139 }
140
141 /* Get information about the page at address ADDR for process PID from
142    the dictionary.  */
143
144 static struct inf_ttrace_page *
145 inf_ttrace_get_page (pid_t pid, CORE_ADDR addr)
146 {
147   const int num_buckets = ARRAY_SIZE (inf_ttrace_page_dict.buckets);
148   const int pagesize = inf_ttrace_page_dict.pagesize;
149   int bucket;
150   struct inf_ttrace_page *page;
151
152   bucket = (addr / pagesize) % num_buckets;
153   page = &inf_ttrace_page_dict.buckets[bucket];
154   while (page)
155     {
156       if (page->addr == addr)
157         break;
158
159       page = page->next;
160     }
161
162   return page;
163 }
164
165 /* Add the page at address ADDR for process PID to the dictionary.  */
166
167 static struct inf_ttrace_page *
168 inf_ttrace_add_page (pid_t pid, CORE_ADDR addr)
169 {
170   const int num_buckets = ARRAY_SIZE (inf_ttrace_page_dict.buckets);
171   const int pagesize = inf_ttrace_page_dict.pagesize;
172   int bucket;
173   struct inf_ttrace_page *page;
174   struct inf_ttrace_page *prev = NULL;
175
176   bucket = (addr / pagesize) % num_buckets;
177   page = &inf_ttrace_page_dict.buckets[bucket];
178   while (page)
179     {
180       if (page->addr == addr)
181         break;
182
183       prev = page;
184       page = page->next;
185     }
186   
187   if (!page)
188     {
189       int prot;
190
191       if (ttrace (TT_PROC_GET_MPROTECT, pid, 0,
192                   addr, 0, (uintptr_t)&prot) == -1)
193         perror_with_name ("ttrace");
194       
195       page = XMALLOC (struct inf_ttrace_page);
196       page->addr = addr;
197       page->prot = prot;
198       page->refcount = 0;
199       page->next = NULL;
200
201       page->prev = prev;
202       prev->next = page;
203
204       inf_ttrace_page_dict.count++;
205       if (inf_ttrace_page_dict.count == 1)
206         inf_ttrace_enable_syscall_events (pid);
207
208       if (inf_ttrace_num_lwps_in_syscall == 0)
209         {
210           if (ttrace (TT_PROC_SET_MPROTECT, pid, 0,
211                       addr, pagesize, prot & ~PROT_WRITE) == -1)
212             perror_with_name ("ttrace");
213         }
214     }
215
216   return page;
217 }
218
219 /* Insert the page at address ADDR of process PID to the dictionary.  */
220
221 static void
222 inf_ttrace_insert_page (pid_t pid, CORE_ADDR addr)
223 {
224   struct inf_ttrace_page *page;
225
226   page = inf_ttrace_get_page (pid, addr);
227   if (!page)
228     page = inf_ttrace_add_page (pid, addr);
229
230   page->refcount++;
231 }
232
233 /* Remove the page at address ADDR of process PID from the dictionary.  */
234
235 static void
236 inf_ttrace_remove_page (pid_t pid, CORE_ADDR addr)
237 {
238   const int pagesize = inf_ttrace_page_dict.pagesize;
239   struct inf_ttrace_page *page;
240
241   page = inf_ttrace_get_page (pid, addr);
242   page->refcount--;
243
244   gdb_assert (page->refcount >= 0);
245
246   if (page->refcount == 0)
247     {
248       if (inf_ttrace_num_lwps_in_syscall == 0)
249         {
250           if (ttrace (TT_PROC_SET_MPROTECT, pid, 0,
251                       addr, pagesize, page->prot) == -1)
252             perror_with_name ("ttrace");
253         }
254
255       inf_ttrace_page_dict.count--;
256       if (inf_ttrace_page_dict.count == 0)
257         inf_ttrace_disable_syscall_events (pid);
258
259       page->prev->next = page->next;
260       if (page->next)
261         page->next->prev = page->prev;
262
263       xfree (page);
264     }
265 }
266
267 /* Mask the bits in PROT from the page protections that are currently
268    in the dictionary for process PID.  */
269
270 static void
271 inf_ttrace_mask_page_protections (pid_t pid, int prot)
272 {
273   const int num_buckets = ARRAY_SIZE (inf_ttrace_page_dict.buckets);
274   const int pagesize = inf_ttrace_page_dict.pagesize;
275   int bucket;
276
277   for (bucket = 0; bucket < num_buckets; bucket++)
278     {
279       struct inf_ttrace_page *page;
280
281       page = inf_ttrace_page_dict.buckets[bucket].next;
282       while (page)
283         {
284           if (ttrace (TT_PROC_SET_MPROTECT, pid, 0,
285                       page->addr, pagesize, page->prot & ~prot) == -1)
286             perror_with_name ("ttrace");
287
288           page = page->next;
289         }
290     }
291 }
292
293 /* Write-protect the pages in the dictionary for process PID.  */
294
295 static void
296 inf_ttrace_enable_page_protections (pid_t pid)
297 {
298   inf_ttrace_mask_page_protections (pid, PROT_WRITE);
299 }
300
301 /* Restore the protection of the pages in the dictionary for process
302    PID.  */
303
304 static void
305 inf_ttrace_disable_page_protections (pid_t pid)
306 {
307   inf_ttrace_mask_page_protections (pid, 0);
308 }
309
310 /* Insert a "hardware" watchpoint for LEN bytes at address ADDR of
311    type TYPE.  */
312
313 static int
314 inf_ttrace_insert_watchpoint (CORE_ADDR addr, int len, int type)
315 {
316   const int pagesize = inf_ttrace_page_dict.pagesize;
317   pid_t pid = ptid_get_pid (inferior_ptid);
318   CORE_ADDR page_addr;
319   int num_pages;
320   int page;
321
322   gdb_assert (type == hw_write);
323
324   page_addr = (addr / pagesize) * pagesize;
325   num_pages = (len + pagesize - 1) / pagesize;
326
327   for (page = 0; page < num_pages; page++, page_addr += pagesize)
328     inf_ttrace_insert_page (pid, page_addr);
329
330   return 1;
331 }
332
333 /* Remove a "hardware" watchpoint for LEN bytes at address ADDR of
334    type TYPE.  */
335
336 static int
337 inf_ttrace_remove_watchpoint (CORE_ADDR addr, int len, int type)
338 {
339   const int pagesize = inf_ttrace_page_dict.pagesize;
340   pid_t pid = ptid_get_pid (inferior_ptid);
341   CORE_ADDR page_addr;
342   int num_pages;
343   int page;
344
345   gdb_assert (type == hw_write);
346
347   page_addr = (addr / pagesize) * pagesize;
348   num_pages = (len + pagesize - 1) / pagesize;
349
350   for (page = 0; page < num_pages; page++, page_addr += pagesize)
351     inf_ttrace_remove_page (pid, page_addr);
352
353   return 1;
354 }
355
356 static int
357 inf_ttrace_can_use_hw_breakpoint (int type, int len, int ot)
358 {
359   return (type == bp_hardware_watchpoint);
360 }
361
362 static int
363 inf_ttrace_region_size_ok_for_hw_watchpoint (int len)
364 {
365   return 1;
366 }
367
368 /* Return non-zero if the current inferior was (potentially) stopped
369    by hitting a "hardware" watchpoint.  */
370
371 static int
372 inf_ttrace_stopped_by_watchpoint (void)
373 {
374   pid_t pid = ptid_get_pid (inferior_ptid);
375   lwpid_t lwpid = ptid_get_lwp (inferior_ptid);
376   ttstate_t tts;
377
378   if (inf_ttrace_page_dict.count > 0)
379     {
380       if (ttrace (TT_LWP_GET_STATE, pid, lwpid,
381                   (uintptr_t)&tts, sizeof tts, 0) == -1)
382         perror_with_name ("ttrace");
383
384       if (tts.tts_event == TTEVT_SIGNAL
385           && tts.tts_u.tts_signal.tts_signo == SIGBUS)
386         {
387           const int pagesize = inf_ttrace_page_dict.pagesize;
388           void *addr = tts.tts_u.tts_signal.tts_siginfo.si_addr;
389           CORE_ADDR page_addr = ((uintptr_t)addr / pagesize) * pagesize;
390
391           if (inf_ttrace_get_page (pid, page_addr))
392             return 1;
393         }
394     }
395
396   return 0;
397 }
398 \f
399
400 /* File descriptors for pipes used as semaphores during initial
401    startup of an inferior.  */
402 static int inf_ttrace_pfd1[2];
403 static int inf_ttrace_pfd2[2];
404
405 static void
406 do_cleanup_pfds (void *dummy)
407 {
408   close (inf_ttrace_pfd1[0]);
409   close (inf_ttrace_pfd1[1]);
410   close (inf_ttrace_pfd2[0]);
411   close (inf_ttrace_pfd2[1]);
412 }
413
414 static void
415 inf_ttrace_prepare (void)
416 {
417   if (pipe (inf_ttrace_pfd1) == -1)
418     perror_with_name ("pipe");
419
420   if (pipe (inf_ttrace_pfd2) == -1)
421     {
422       close (inf_ttrace_pfd1[0]);
423       close (inf_ttrace_pfd2[0]);
424       perror_with_name ("pipe");
425     }
426 }
427
428 /* Prepare to be traced.  */
429
430 static void
431 inf_ttrace_me (void)
432 {
433   struct cleanup *old_chain = make_cleanup (do_cleanup_pfds, 0);
434   char c;
435
436   /* "Trace me, Dr. Memory!"  */
437   if (ttrace (TT_PROC_SETTRC, 0, 0, 0, TT_VERSION, 0) == -1)
438     perror_with_name ("ttrace");
439
440   /* Tell our parent that we are ready to be traced.  */
441   if (write (inf_ttrace_pfd1[1], &c, sizeof c) != sizeof c)
442     perror_with_name ("write");
443
444   /* Wait until our parent has set the initial event mask.  */
445   if (read (inf_ttrace_pfd2[0], &c, sizeof c) != sizeof c)
446     perror_with_name ("read");
447
448   do_cleanups (old_chain);
449 }
450
451 /* Start tracing PID.  */
452
453 static void
454 inf_ttrace_him (int pid)
455 {
456   struct cleanup *old_chain = make_cleanup (do_cleanup_pfds, 0);
457   ttevent_t tte;
458   char c;
459
460   /* Wait until our child is ready to be traced.  */
461   if (read (inf_ttrace_pfd1[0], &c, sizeof c) != sizeof c)
462     perror_with_name ("read");
463
464   /* Set the initial event mask.  */
465   memset (&tte, 0, sizeof (tte));
466   tte.tte_events |= TTEVT_EXEC | TTEVT_EXIT;
467   tte.tte_events |= TTEVT_LWP_CREATE | TTEVT_LWP_EXIT | TTEVT_LWP_TERMINATE;
468 #ifdef TTEVT_BPT_SSTEP
469   tte.tte_events |= TTEVT_BPT_SSTEP;
470 #endif
471   tte.tte_opts = TTEO_NOSTRCCHLD;
472   if (ttrace (TT_PROC_SET_EVENT_MASK, pid, 0,
473               (uintptr_t)&tte, sizeof tte, 0) == -1)
474     perror_with_name ("ttrace");
475
476   /* Tell our child that we have set the initial event mask.  */
477   if (write (inf_ttrace_pfd2[1], &c, sizeof c) != sizeof c)
478     perror_with_name ("write");
479
480   do_cleanups (old_chain);
481
482   push_target (ttrace_ops_hack);
483
484   /* On some targets, there must be some explicit synchronization
485      between the parent and child processes after the debugger forks,
486      and before the child execs the debuggee program.  This call
487      basically gives permission for the child to exec.  */
488
489   target_acknowledge_created_inferior (pid);
490
491   /* START_INFERIOR_TRAPS_EXPECTED is defined in inferior.h, and will
492      be 1 or 2 depending on whether we're starting without or with a
493      shell.  */
494   startup_inferior (START_INFERIOR_TRAPS_EXPECTED);
495
496   /* On some targets, there must be some explicit actions taken after
497      the inferior has been started up.  */
498   target_post_startup_inferior (pid_to_ptid (pid));
499 }
500
501 static void
502 inf_ttrace_create_inferior (char *exec_file, char *allargs, char **env,
503                             int from_tty)
504 {
505   gdb_assert (inf_ttrace_num_lwps == 0);
506   gdb_assert (inf_ttrace_num_lwps_in_syscall == 0);
507   gdb_assert (inf_ttrace_page_dict.count == 0);
508   gdb_assert (inf_ttrace_reenable_page_protections == 0);
509
510   fork_inferior (exec_file, allargs, env, inf_ttrace_me, inf_ttrace_him,
511                  inf_ttrace_prepare, NULL);
512
513   /* We are at the first instruction we care about.  */
514   observer_notify_inferior_created (&current_target, from_tty);
515
516   /* Pedal to the metal...  */
517   proceed ((CORE_ADDR) -1, TARGET_SIGNAL_0, 0);
518 }
519
520 static void
521 inf_ttrace_kill_inferior (void)
522 {
523   pid_t pid = ptid_get_pid (inferior_ptid);
524
525   if (pid == 0)
526     return;
527
528   if (ttrace (TT_PROC_EXIT, pid, 0, 0, 0, 0) == -1)
529     perror_with_name ("ttrace");
530   /* ??? Is it necessary to call ttrace_wait() here?  */
531   target_mourn_inferior ();
532 }
533
534 static void
535 inf_ttrace_mourn_inferior (void)
536 {
537   const int num_buckets = ARRAY_SIZE (inf_ttrace_page_dict.buckets);
538   int bucket;
539
540   inf_ttrace_num_lwps = 0;
541   inf_ttrace_num_lwps_in_syscall = 0;
542
543   for (bucket = 0; bucket < num_buckets; bucket++)
544     {
545       struct inf_ttrace_page *page;
546       struct inf_ttrace_page *next;
547
548       page = inf_ttrace_page_dict.buckets[bucket].next;
549       while (page)
550         {
551           next = page->next;
552           xfree (page);
553           page = next;
554         }
555     }
556   inf_ttrace_page_dict.count = 0;
557
558   unpush_target (ttrace_ops_hack);
559   generic_mourn_inferior ();
560 }
561
562 static void
563 inf_ttrace_attach (char *args, int from_tty)
564 {
565   char *exec_file;
566   pid_t pid;
567   char *dummy;
568   ttevent_t tte;
569
570   if (!args)
571     error_no_arg ("process-id to attach");
572
573   dummy = args;
574   pid = strtol (args, &dummy, 0);
575   if (pid == 0 && args == dummy)
576     error ("Illegal process-id: %s\n", args);
577
578   if (pid == getpid ())         /* Trying to masturbate?  */
579     error ("I refuse to debug myself!");
580
581   if (from_tty)
582     {
583       exec_file = (char *) get_exec_file (0);
584
585       if (exec_file)
586         printf_unfiltered ("Attaching to program: %s, %s\n", exec_file,
587                            target_pid_to_str (pid_to_ptid (pid)));
588       else
589         printf_unfiltered ("Attaching to %s\n",
590                            target_pid_to_str (pid_to_ptid (pid)));
591
592       gdb_flush (gdb_stdout);
593     }
594
595   gdb_assert (inf_ttrace_num_lwps == 0);
596   gdb_assert (inf_ttrace_num_lwps_in_syscall == 0);
597
598   if (ttrace (TT_PROC_ATTACH, pid, 0, TT_KILL_ON_EXIT, TT_VERSION, 0) == -1)
599     perror_with_name ("ttrace");
600   attach_flag = 1;
601
602   /* Set the initial event mask.  */
603   memset (&tte, 0, sizeof (tte));
604   tte.tte_events |= TTEVT_EXEC | TTEVT_EXIT;
605   tte.tte_events |= TTEVT_LWP_CREATE | TTEVT_LWP_EXIT | TTEVT_LWP_TERMINATE;
606 #ifdef TTEVT_BPT_SSTEP
607   tte.tte_events |= TTEVT_BPT_SSTEP;
608 #endif
609   tte.tte_opts = TTEO_NOSTRCCHLD;
610   if (ttrace (TT_PROC_SET_EVENT_MASK, pid, 0,
611               (uintptr_t)&tte, sizeof tte, 0) == -1)
612     perror_with_name ("ttrace");
613
614   inferior_ptid = pid_to_ptid (pid);
615   push_target (ttrace_ops_hack);
616
617   /* Do this first, before anything has had a chance to query the
618      inferior's symbol table or similar.  */
619   observer_notify_inferior_created (&current_target, from_tty);
620 }
621
622 static void
623 inf_ttrace_detach (char *args, int from_tty)
624 {
625   int sig = 0;
626   pid_t pid = ptid_get_pid (inferior_ptid);
627
628   if (from_tty)
629     {
630       char *exec_file = get_exec_file (0);
631       if (exec_file == 0)
632         exec_file = "";
633       printf_unfiltered ("Detaching from program: %s, %s\n", exec_file,
634                          target_pid_to_str (pid_to_ptid (pid)));
635       gdb_flush (gdb_stdout);
636     }
637   if (args)
638     sig = atoi (args);
639
640   /* ??? The HP-UX 11.0 ttrace(2) manual page doesn't mention that we
641      can pass a signal number here.  Does this really work?  */
642   if (ttrace (TT_PROC_DETACH, pid, 0, 0, sig, 0) == -1)
643     perror_with_name ("ttrace");
644
645   inf_ttrace_num_lwps = 0;
646   inf_ttrace_num_lwps_in_syscall = 0;
647
648   unpush_target (ttrace_ops_hack);
649   inferior_ptid = null_ptid;
650 }
651
652 static int
653 inf_ttrace_resume_callback (struct thread_info *info, void *arg)
654 {
655   if (!ptid_equal (info->ptid, inferior_ptid))
656     {
657       pid_t pid = ptid_get_pid (info->ptid);
658       lwpid_t lwpid = ptid_get_lwp (info->ptid);
659
660       if (ttrace (TT_LWP_CONTINUE, pid, lwpid, TT_NOPC, 0, 0) == -1)
661         perror_with_name ("ttrace");
662     }
663
664   return 0;
665 }
666
667 static void
668 inf_ttrace_resume (ptid_t ptid, int step, enum target_signal signal)
669 {
670   pid_t pid = ptid_get_pid (ptid);
671   lwpid_t lwpid = ptid_get_lwp (ptid);
672   ttreq_t request = step ? TT_LWP_SINGLE : TT_LWP_CONTINUE;
673   int sig = target_signal_to_host (signal);
674
675   if (pid == -1)
676     {
677       pid = ptid_get_pid (inferior_ptid);
678       lwpid = ptid_get_lwp (inferior_ptid);
679     }
680
681   if (ttrace (request, pid, lwpid, TT_NOPC, sig, 0) == -1)
682     perror_with_name ("ttrace");
683
684   if (ptid_equal (ptid, minus_one_ptid) && inf_ttrace_num_lwps > 0)
685     {
686       /* Let all the other threads run too.  */
687       iterate_over_threads (inf_ttrace_resume_callback, NULL);
688     }
689 }
690
691 static ptid_t
692 inf_ttrace_wait (ptid_t ptid, struct target_waitstatus *ourstatus)
693 {
694   pid_t pid = ptid_get_pid (ptid);
695   lwpid_t lwpid = ptid_get_lwp (ptid);
696   ttstate_t tts;
697
698   /* Until proven otherwise.  */
699   ourstatus->kind = TARGET_WAITKIND_SPURIOUS;
700
701   if (pid == -1)
702     pid = 0;
703
704   gdb_assert (lwpid == 0 || pid != 0);
705
706   do
707     {
708       set_sigint_trap ();
709       set_sigio_trap ();
710
711       if (ttrace_wait (pid, lwpid, TTRACE_WAITOK, &tts, sizeof tts) == -1)
712         perror_with_name ("ttrace_wait");
713
714       clear_sigio_trap ();
715       clear_sigint_trap ();
716     }
717   while (tts.tts_event == TTEVT_NONE);
718
719   /* Now that we've waited, we can re-enable the page protections.  */
720   if (inf_ttrace_reenable_page_protections)
721     {
722       gdb_assert (inf_ttrace_num_lwps_in_syscall == 0);
723       inf_ttrace_enable_page_protections (tts.tts_pid);
724       inf_ttrace_reenable_page_protections = 0;
725     }
726
727   ptid = ptid_build (tts.tts_pid, tts.tts_lwpid, 0);
728
729   switch (tts.tts_event)
730     {
731 #ifdef TTEVT_BPT_SSTEP
732     case TTEVT_BPT_SSTEP:
733       /* Make it look like a breakpoint.  */
734       ourstatus->kind = TARGET_WAITKIND_STOPPED;
735       ourstatus->value.sig = TARGET_SIGNAL_TRAP;
736       break;
737 #endif
738
739     case TTEVT_EXEC:
740       /* Make it look like a breakpoint.  */
741       ourstatus->kind = TARGET_WAITKIND_STOPPED;
742       ourstatus->value.sig = TARGET_SIGNAL_TRAP;
743       break;
744
745     case TTEVT_EXIT:
746       store_waitstatus (ourstatus, tts.tts_u.tts_exit.tts_exitcode);
747       inf_ttrace_num_lwps = 0;
748       break;
749
750     case TTEVT_LWP_CREATE:
751       lwpid = tts.tts_u.tts_thread.tts_target_lwpid;
752       ptid = ptid_build (tts.tts_pid, lwpid, 0);
753       if (inf_ttrace_num_lwps == 0)
754         {
755           /* Now that we're going to be multi-threaded, add the
756              origional thread to the list first.  */
757           add_thread (ptid_build (tts.tts_pid, tts.tts_lwpid, 0));
758           inf_ttrace_num_lwps++;
759         }
760       printf_filtered ("[New %s]\n", target_pid_to_str (ptid));
761       add_thread (ptid);
762       inf_ttrace_num_lwps++;
763       ptid = ptid_build (tts.tts_pid, tts.tts_lwpid, 0);
764       break;
765
766     case TTEVT_LWP_EXIT:
767       printf_filtered("[%s exited]\n", target_pid_to_str (ptid));
768       delete_thread (ptid);
769       inf_ttrace_num_lwps--;
770       /* If we don't return -1 here, core GDB will re-add the thread.  */
771       ptid = minus_one_ptid;
772       break;
773
774     case TTEVT_LWP_TERMINATE:
775       lwpid = tts.tts_u.tts_thread.tts_target_lwpid;
776       ptid = ptid_build (tts.tts_pid, lwpid, 0);
777       printf_filtered("[%s has been terminated]\n", target_pid_to_str (ptid));
778       delete_thread (ptid);
779       inf_ttrace_num_lwps--;
780       ptid = ptid_build (tts.tts_pid, tts.tts_lwpid, 0);
781       break;
782
783     case TTEVT_SIGNAL:
784       ourstatus->kind = TARGET_WAITKIND_STOPPED;
785       ourstatus->value.sig =
786         target_signal_from_host (tts.tts_u.tts_signal.tts_signo);
787       break;
788
789     case TTEVT_SYSCALL_ENTRY:
790       gdb_assert (inf_ttrace_reenable_page_protections == 0);
791       inf_ttrace_num_lwps_in_syscall++;
792       if (inf_ttrace_num_lwps_in_syscall == 1)
793         {
794           /* A thread has just entered a system call.  Disable any
795              page protections as the kernel can't deal with them.  */
796           inf_ttrace_disable_page_protections (tts.tts_pid);
797         }
798       ourstatus->kind = TARGET_WAITKIND_SYSCALL_ENTRY;
799       ourstatus->value.syscall_id = tts.tts_scno;
800       break;
801
802     case TTEVT_SYSCALL_RETURN:
803       if (inf_ttrace_num_lwps_in_syscall > 0)
804         {
805           /* If the last thread has just left the system call, this
806              would be a logical place to re-enable the page
807              protections, but that doesn't work.  We can't re-enable
808              them until we've done another wait.  */
809           inf_ttrace_reenable_page_protections = 
810             (inf_ttrace_num_lwps_in_syscall == 1);
811           inf_ttrace_num_lwps_in_syscall--;
812         }
813       ourstatus->kind = TARGET_WAITKIND_SYSCALL_RETURN;
814       ourstatus->value.syscall_id = tts.tts_scno;
815       break;
816
817     default:
818       gdb_assert (!"Unexpected ttrace event");
819       break;
820     }
821
822   /* Make sure all threads within the process are stopped.  */
823   if (ttrace (TT_PROC_STOP, tts.tts_pid, 0, 0, 0, 0) == -1)
824     perror_with_name ("ttrace");
825
826   /* HACK: Twiddle INFERIOR_PTID such that the initial thread of a
827      process isn't recognized as a new thread.  */
828   if (ptid_get_lwp (inferior_ptid) == 0)
829     inferior_ptid = ptid;
830
831   return ptid;
832 }
833
834 /* Transfer LEN bytes from ADDR in the inferior's memory into READBUF,
835    and transfer LEN bytes from WRITEBUF into the inferior's memory at
836    ADDR.  Either READBUF or WRITEBUF may be null, in which case the
837    corresponding transfer doesn't happen.  Return the number of bytes
838    actually transferred (which may be zero if an error occurs).  */
839
840 static LONGEST
841 inf_ttrace_xfer_memory (CORE_ADDR addr, ULONGEST len,
842                         void *readbuf, const void *writebuf)
843 {
844   pid_t pid = ptid_get_pid (inferior_ptid);
845
846   /* HP-UX treats text space and data space differently.  GDB however,
847      doesn't really know the difference.  Therefore we try both.  Try
848      text space before data space though because when we're writing
849      into text space the instruction cache might need to be flushed.  */
850
851   if (readbuf
852       && ttrace (TT_PROC_RDTEXT, pid, 0, addr, len, (uintptr_t)readbuf) == -1
853       && ttrace (TT_PROC_RDDATA, pid, 0, addr, len, (uintptr_t)readbuf) == -1)
854     return 0;
855
856   if (writebuf
857       && ttrace (TT_PROC_WRTEXT, pid, 0, addr, len, (uintptr_t)writebuf) == -1
858       && ttrace (TT_PROC_WRDATA, pid, 0, addr, len, (uintptr_t)writebuf) == -1)
859     return 0;
860
861   return len;
862 }
863
864 static LONGEST
865 inf_ttrace_xfer_partial (struct target_ops *ops, enum target_object object,
866                          const char *annex, void *readbuf,
867                          const void *writebuf, ULONGEST offset, LONGEST len)
868 {
869   switch (object)
870     {
871     case TARGET_OBJECT_MEMORY:
872       return inf_ttrace_xfer_memory (offset, len, readbuf, writebuf);
873
874     case TARGET_OBJECT_UNWIND_TABLE:
875       return -1;
876
877     case TARGET_OBJECT_AUXV:
878       return -1;
879
880     case TARGET_OBJECT_WCOOKIE:
881       return -1;
882
883     default:
884       return -1;
885     }
886 }
887
888 /* Print status information about what we're accessing.  */
889
890 static void
891 inf_ttrace_files_info (struct target_ops *ignore)
892 {
893   printf_unfiltered ("\tUsing the running image of %s %s.\n",
894                      attach_flag ? "attached" : "child",
895                      target_pid_to_str (inferior_ptid));
896 }
897
898 static int
899 inf_ttrace_thread_alive (ptid_t ptid)
900 {
901   return 1;
902 }
903
904 static char *
905 inf_ttrace_pid_to_str (ptid_t ptid)
906 {
907   if (inf_ttrace_num_lwps > 0)
908     {
909       pid_t pid = ptid_get_pid (ptid);
910       lwpid_t lwpid = ptid_get_lwp (ptid);
911       static char buf[80];
912
913       sprintf (buf, "process %ld, lwp %ld", (long)pid, (long)lwpid);
914       return buf;
915     }
916
917   return normal_pid_to_str (ptid);
918 }
919 \f
920
921 struct target_ops *
922 inf_ttrace_target (void)
923 {
924   struct target_ops *t = inf_child_target ();
925
926   t->to_create_inferior = inf_ttrace_create_inferior;
927   t->to_kill = inf_ttrace_kill_inferior;
928   t->to_mourn_inferior = inf_ttrace_mourn_inferior;
929   t->to_attach = inf_ttrace_attach;
930   t->to_detach = inf_ttrace_detach;
931   t->to_resume = inf_ttrace_resume;
932   t->to_wait = inf_ttrace_wait;
933   t->to_xfer_partial = inf_ttrace_xfer_partial;
934   t->to_files_info = inf_ttrace_files_info;
935   t->to_thread_alive = inf_ttrace_thread_alive;
936   t->to_pid_to_str = inf_ttrace_pid_to_str;
937   t->to_can_use_hw_breakpoint = inf_ttrace_can_use_hw_breakpoint;
938   t->to_region_size_ok_for_hw_watchpoint =
939     inf_ttrace_region_size_ok_for_hw_watchpoint;
940   t->to_insert_watchpoint = inf_ttrace_insert_watchpoint;
941   t->to_remove_watchpoint = inf_ttrace_remove_watchpoint;
942   t->to_stopped_by_watchpoint = inf_ttrace_stopped_by_watchpoint;
943
944   ttrace_ops_hack = t;
945   return t;
946 }
947 #endif
948 \f
949
950 /* Prevent warning from -Wmissing-prototypes.  */
951 void _initialize_hppa_hpux_nat (void);
952
953 void
954 _initialize_inf_ttrace (void)
955 {
956 #ifdef HAVE_TTRACE
957   inf_ttrace_page_dict.pagesize = getpagesize();
958 #endif
959 }