1 /* Low-level child interface to ttrace.
2 
3    Copyright 2004, 2005 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 
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 
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
inf_ttrace_enable_syscall_events(pid_t pid)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
inf_ttrace_disable_syscall_events(pid_t pid)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 *
inf_ttrace_get_page(pid_t pid,CORE_ADDR addr)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 *
inf_ttrace_add_page(pid_t pid,CORE_ADDR addr)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
inf_ttrace_insert_page(pid_t pid,CORE_ADDR addr)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
inf_ttrace_remove_page(pid_t pid,CORE_ADDR addr)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
inf_ttrace_mask_page_protections(pid_t pid,int prot)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
inf_ttrace_enable_page_protections(pid_t pid)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
inf_ttrace_disable_page_protections(pid_t pid)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
inf_ttrace_insert_watchpoint(CORE_ADDR addr,int len,int type)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
inf_ttrace_remove_watchpoint(CORE_ADDR addr,int len,int type)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
inf_ttrace_can_use_hw_breakpoint(int type,int len,int ot)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
inf_ttrace_region_size_ok_for_hw_watchpoint(int len)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
inf_ttrace_stopped_by_watchpoint(void)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 
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
do_cleanup_pfds(void * dummy)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
inf_ttrace_prepare(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
inf_ttrace_me(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
inf_ttrace_him(int pid)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
inf_ttrace_create_inferior(char * exec_file,char * allargs,char ** env,int from_tty)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
inf_ttrace_kill_inferior(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
inf_ttrace_mourn_inferior(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
inf_ttrace_attach(char * args,int from_tty)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."), 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
inf_ttrace_detach(char * args,int from_tty)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
inf_ttrace_resume_callback(struct thread_info * info,void * arg)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
inf_ttrace_resume(ptid_t ptid,int step,enum target_signal signal)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
inf_ttrace_wait(ptid_t ptid,struct target_waitstatus * ourstatus)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
inf_ttrace_xfer_memory(CORE_ADDR addr,ULONGEST len,void * readbuf,const void * writebuf)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
inf_ttrace_xfer_partial(struct target_ops * ops,enum target_object object,const char * annex,gdb_byte * readbuf,const gdb_byte * writebuf,ULONGEST offset,LONGEST len)865 inf_ttrace_xfer_partial (struct target_ops *ops, enum target_object object,
866 			 const char *annex, gdb_byte *readbuf,
867 			 const gdb_byte *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
inf_ttrace_files_info(struct target_ops * ignore)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
inf_ttrace_thread_alive(ptid_t ptid)899 inf_ttrace_thread_alive (ptid_t ptid)
900 {
901   return 1;
902 }
903 
904 static char *
inf_ttrace_pid_to_str(ptid_t ptid)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[128];
912       int size;
913 
914       size = snprintf (buf, sizeof buf, "process %ld, lwp %ld",
915 		       (long)pid, (long)lwpid);
916       gdb_assert (size < sizeof buf);
917       return buf;
918     }
919 
920   return normal_pid_to_str (ptid);
921 }
922 
923 
924 struct target_ops *
inf_ttrace_target(void)925 inf_ttrace_target (void)
926 {
927   struct target_ops *t = inf_child_target ();
928 
929   t->to_create_inferior = inf_ttrace_create_inferior;
930   t->to_kill = inf_ttrace_kill_inferior;
931   t->to_mourn_inferior = inf_ttrace_mourn_inferior;
932   t->to_attach = inf_ttrace_attach;
933   t->to_detach = inf_ttrace_detach;
934   t->to_resume = inf_ttrace_resume;
935   t->to_wait = inf_ttrace_wait;
936   t->to_xfer_partial = inf_ttrace_xfer_partial;
937   t->to_files_info = inf_ttrace_files_info;
938   t->to_thread_alive = inf_ttrace_thread_alive;
939   t->to_pid_to_str = inf_ttrace_pid_to_str;
940   t->to_can_use_hw_breakpoint = inf_ttrace_can_use_hw_breakpoint;
941   t->to_region_size_ok_for_hw_watchpoint =
942     inf_ttrace_region_size_ok_for_hw_watchpoint;
943   t->to_insert_watchpoint = inf_ttrace_insert_watchpoint;
944   t->to_remove_watchpoint = inf_ttrace_remove_watchpoint;
945   t->to_stopped_by_watchpoint = inf_ttrace_stopped_by_watchpoint;
946 
947   ttrace_ops_hack = t;
948   return t;
949 }
950 #endif
951 
952 
953 /* Prevent warning from -Wmissing-prototypes.  */
954 void _initialize_hppa_hpux_nat (void);
955 
956 void
_initialize_inf_ttrace(void)957 _initialize_inf_ttrace (void)
958 {
959 #ifdef HAVE_TTRACE
960   inf_ttrace_page_dict.pagesize = getpagesize();
961 #endif
962 }
963