]> Git Repo - binutils.git/blob - gdb/inf-ttrace.c
* elf64-ppc.c (ppc64_elf_gc_mark_hook): Don't hang forever in loop.
[binutils.git] / gdb / inf-ttrace.c
1 /* Low-level child interface to ttrace.
2
3    Copyright (C) 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., 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 "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 /* When tracking a vfork(2), we cannot detach from the parent until
401    after the child has called exec(3) or has exited.  If we are still
402    attached to the parent, this variable will be set to the process ID
403    of the parent.  Otherwise it will be set to zero.  */
404 static pid_t inf_ttrace_vfork_ppid = -1;
405
406 static int
407 inf_ttrace_follow_fork (struct target_ops *ops, int follow_child)
408 {
409   pid_t pid, fpid;
410   lwpid_t lwpid, flwpid;
411   ttstate_t tts;
412
413   /* FIXME: kettenis/20050720: This stuff should really be passed as
414      an argument by our caller.  */
415   {
416     ptid_t ptid;
417     struct target_waitstatus status;
418
419     get_last_target_status (&ptid, &status);
420     gdb_assert (status.kind == TARGET_WAITKIND_FORKED
421                 || status.kind == TARGET_WAITKIND_VFORKED);
422
423     pid = ptid_get_pid (ptid);
424     lwpid = ptid_get_lwp (ptid);
425   }
426
427   /* Get all important details that core GDB doesn't (and shouldn't)
428      know about.  */
429   if (ttrace (TT_LWP_GET_STATE, pid, lwpid,
430               (uintptr_t)&tts, sizeof tts, 0) == -1)
431     perror_with_name (("ttrace"));
432
433   gdb_assert (tts.tts_event == TTEVT_FORK || tts.tts_event == TTEVT_VFORK);
434
435   if (tts.tts_u.tts_fork.tts_isparent)
436     {
437       pid = tts.tts_pid;
438       lwpid = tts.tts_lwpid;
439       fpid = tts.tts_u.tts_fork.tts_fpid;
440       flwpid = tts.tts_u.tts_fork.tts_flwpid;
441     }
442   else
443     {
444       pid = tts.tts_u.tts_fork.tts_fpid;
445       lwpid = tts.tts_u.tts_fork.tts_flwpid;
446       fpid = tts.tts_pid;
447       flwpid = tts.tts_lwpid;
448     }
449
450   if (follow_child)
451     {
452       inferior_ptid = ptid_build (fpid, flwpid, 0);
453       detach_breakpoints (pid);
454
455       target_terminal_ours ();
456       fprintf_unfiltered (gdb_stdlog, _("\
457 Attaching after fork to child process %ld.\n"), (long)fpid);
458     }
459   else
460     {
461       inferior_ptid = ptid_build (pid, lwpid, 0);
462       detach_breakpoints (fpid);
463
464       target_terminal_ours ();
465       fprintf_unfiltered (gdb_stdlog, _("\
466 Detaching after fork from child process %ld.\n"), (long)fpid);
467     }
468
469   if (tts.tts_event == TTEVT_VFORK)
470     {
471       gdb_assert (!tts.tts_u.tts_fork.tts_isparent);
472
473       if (follow_child)
474         {
475           /* We can't detach from the parent yet.  */
476           inf_ttrace_vfork_ppid = pid;
477
478           reattach_breakpoints (fpid);
479         }
480       else
481         {
482           if (ttrace (TT_PROC_DETACH, fpid, 0, 0, 0, 0) == -1)
483             perror_with_name (("ttrace"));
484
485           /* Wait till we get the TTEVT_VFORK event in the parent.
486              This indicates that the child has called exec(3) or has
487              exited and that the parent is ready to be traced again.  */
488           if (ttrace_wait (pid, lwpid, TTRACE_WAITOK, &tts, sizeof tts) == -1)
489             perror_with_name (("ttrace_wait"));
490           gdb_assert (tts.tts_event == TTEVT_VFORK);
491           gdb_assert (tts.tts_u.tts_fork.tts_isparent);
492
493           reattach_breakpoints (pid);
494         }
495     }
496   else
497     {
498       gdb_assert (tts.tts_u.tts_fork.tts_isparent);
499
500       if (follow_child)
501         {
502           if (ttrace (TT_PROC_DETACH, pid, 0, 0, 0, 0) == -1)
503             perror_with_name (("ttrace"));
504         }
505       else
506         {
507           if (ttrace (TT_PROC_DETACH, fpid, 0, 0, 0, 0) == -1)
508             perror_with_name (("ttrace"));
509         }
510     }
511
512   if (follow_child)
513     {
514       /* The child will start out single-threaded.  */
515       inf_ttrace_num_lwps = 0;
516       inf_ttrace_num_lwps_in_syscall = 0;
517
518       /* Reset breakpoints in the child as appropriate.  */
519       follow_inferior_reset_breakpoints ();
520     }
521
522   return 0;
523 }
524 \f
525
526 /* File descriptors for pipes used as semaphores during initial
527    startup of an inferior.  */
528 static int inf_ttrace_pfd1[2];
529 static int inf_ttrace_pfd2[2];
530
531 static void
532 do_cleanup_pfds (void *dummy)
533 {
534   close (inf_ttrace_pfd1[0]);
535   close (inf_ttrace_pfd1[1]);
536   close (inf_ttrace_pfd2[0]);
537   close (inf_ttrace_pfd2[1]);
538 }
539
540 static void
541 inf_ttrace_prepare (void)
542 {
543   if (pipe (inf_ttrace_pfd1) == -1)
544     perror_with_name (("pipe"));
545
546   if (pipe (inf_ttrace_pfd2) == -1)
547     {
548       close (inf_ttrace_pfd1[0]);
549       close (inf_ttrace_pfd2[0]);
550       perror_with_name (("pipe"));
551     }
552 }
553
554 /* Prepare to be traced.  */
555
556 static void
557 inf_ttrace_me (void)
558 {
559   struct cleanup *old_chain = make_cleanup (do_cleanup_pfds, 0);
560   char c;
561
562   /* "Trace me, Dr. Memory!"  */
563   if (ttrace (TT_PROC_SETTRC, 0, 0, 0, TT_VERSION, 0) == -1)
564     perror_with_name (("ttrace"));
565
566   /* Tell our parent that we are ready to be traced.  */
567   if (write (inf_ttrace_pfd1[1], &c, sizeof c) != sizeof c)
568     perror_with_name (("write"));
569
570   /* Wait until our parent has set the initial event mask.  */
571   if (read (inf_ttrace_pfd2[0], &c, sizeof c) != sizeof c)
572     perror_with_name (("read"));
573
574   do_cleanups (old_chain);
575 }
576
577 /* Start tracing PID.  */
578
579 static void
580 inf_ttrace_him (int pid)
581 {
582   struct cleanup *old_chain = make_cleanup (do_cleanup_pfds, 0);
583   ttevent_t tte;
584   char c;
585
586   /* Wait until our child is ready to be traced.  */
587   if (read (inf_ttrace_pfd1[0], &c, sizeof c) != sizeof c)
588     perror_with_name (("read"));
589
590   /* Set the initial event mask.  */
591   memset (&tte, 0, sizeof (tte));
592   tte.tte_events |= TTEVT_EXEC | TTEVT_EXIT | TTEVT_FORK | TTEVT_VFORK;
593   tte.tte_events |= TTEVT_LWP_CREATE | TTEVT_LWP_EXIT | TTEVT_LWP_TERMINATE;
594 #ifdef TTEVT_BPT_SSTEP
595   tte.tte_events |= TTEVT_BPT_SSTEP;
596 #endif
597   tte.tte_opts |= TTEO_PROC_INHERIT;
598   if (ttrace (TT_PROC_SET_EVENT_MASK, pid, 0,
599               (uintptr_t)&tte, sizeof tte, 0) == -1)
600     perror_with_name (("ttrace"));
601
602   /* Tell our child that we have set the initial event mask.  */
603   if (write (inf_ttrace_pfd2[1], &c, sizeof c) != sizeof c)
604     perror_with_name (("write"));
605
606   do_cleanups (old_chain);
607
608   push_target (ttrace_ops_hack);
609
610   /* On some targets, there must be some explicit synchronization
611      between the parent and child processes after the debugger forks,
612      and before the child execs the debuggee program.  This call
613      basically gives permission for the child to exec.  */
614
615   target_acknowledge_created_inferior (pid);
616
617   /* START_INFERIOR_TRAPS_EXPECTED is defined in inferior.h, and will
618      be 1 or 2 depending on whether we're starting without or with a
619      shell.  */
620   startup_inferior (START_INFERIOR_TRAPS_EXPECTED);
621
622   /* On some targets, there must be some explicit actions taken after
623      the inferior has been started up.  */
624   target_post_startup_inferior (pid_to_ptid (pid));
625 }
626
627 static void
628 inf_ttrace_create_inferior (char *exec_file, char *allargs, char **env,
629                             int from_tty)
630 {
631   gdb_assert (inf_ttrace_num_lwps == 0);
632   gdb_assert (inf_ttrace_num_lwps_in_syscall == 0);
633   gdb_assert (inf_ttrace_page_dict.count == 0);
634   gdb_assert (inf_ttrace_reenable_page_protections == 0);
635   gdb_assert (inf_ttrace_vfork_ppid == -1);
636
637   fork_inferior (exec_file, allargs, env, inf_ttrace_me, inf_ttrace_him,
638                  inf_ttrace_prepare, NULL);
639
640   /* We are at the first instruction we care about.  */
641   observer_notify_inferior_created (&current_target, from_tty);
642
643   /* Pedal to the metal...  */
644   proceed ((CORE_ADDR) -1, TARGET_SIGNAL_0, 0);
645 }
646
647 static void
648 inf_ttrace_mourn_inferior (void)
649 {
650   const int num_buckets = ARRAY_SIZE (inf_ttrace_page_dict.buckets);
651   int bucket;
652
653   inf_ttrace_num_lwps = 0;
654   inf_ttrace_num_lwps_in_syscall = 0;
655
656   for (bucket = 0; bucket < num_buckets; bucket++)
657     {
658       struct inf_ttrace_page *page;
659       struct inf_ttrace_page *next;
660
661       page = inf_ttrace_page_dict.buckets[bucket].next;
662       while (page)
663         {
664           next = page->next;
665           xfree (page);
666           page = next;
667         }
668     }
669   inf_ttrace_page_dict.count = 0;
670
671   unpush_target (ttrace_ops_hack);
672   generic_mourn_inferior ();
673 }
674
675 static void
676 inf_ttrace_attach (char *args, int from_tty)
677 {
678   char *exec_file;
679   pid_t pid;
680   char *dummy;
681   ttevent_t tte;
682
683   if (!args)
684     error_no_arg (_("process-id to attach"));
685
686   dummy = args;
687   pid = strtol (args, &dummy, 0);
688   if (pid == 0 && args == dummy)
689     error (_("Illegal process-id: %s."), args);
690
691   if (pid == getpid ())         /* Trying to masturbate?  */
692     error (_("I refuse to debug myself!"));
693
694   if (from_tty)
695     {
696       exec_file = get_exec_file (0);
697
698       if (exec_file)
699         printf_unfiltered (_("Attaching to program: %s, %s\n"), exec_file,
700                            target_pid_to_str (pid_to_ptid (pid)));
701       else
702         printf_unfiltered (_("Attaching to %s\n"),
703                            target_pid_to_str (pid_to_ptid (pid)));
704
705       gdb_flush (gdb_stdout);
706     }
707
708   gdb_assert (inf_ttrace_num_lwps == 0);
709   gdb_assert (inf_ttrace_num_lwps_in_syscall == 0);
710   gdb_assert (inf_ttrace_vfork_ppid == -1);
711
712   if (ttrace (TT_PROC_ATTACH, pid, 0, TT_KILL_ON_EXIT, TT_VERSION, 0) == -1)
713     perror_with_name (("ttrace"));
714   attach_flag = 1;
715
716   /* Set the initial event mask.  */
717   memset (&tte, 0, sizeof (tte));
718   tte.tte_events |= TTEVT_EXEC | TTEVT_EXIT | TTEVT_FORK | TTEVT_VFORK;
719   tte.tte_events |= TTEVT_LWP_CREATE | TTEVT_LWP_EXIT | TTEVT_LWP_TERMINATE;
720 #ifdef TTEVT_BPT_SSTEP
721   tte.tte_events |= TTEVT_BPT_SSTEP;
722 #endif
723   tte.tte_opts |= TTEO_PROC_INHERIT;
724   if (ttrace (TT_PROC_SET_EVENT_MASK, pid, 0,
725               (uintptr_t)&tte, sizeof tte, 0) == -1)
726     perror_with_name (("ttrace"));
727
728   inferior_ptid = pid_to_ptid (pid);
729   push_target (ttrace_ops_hack);
730
731   /* Do this first, before anything has had a chance to query the
732      inferior's symbol table or similar.  */
733   observer_notify_inferior_created (&current_target, from_tty);
734 }
735
736 static void
737 inf_ttrace_detach (char *args, int from_tty)
738 {
739   pid_t pid = ptid_get_pid (inferior_ptid);
740   int sig = 0;
741
742   if (from_tty)
743     {
744       char *exec_file = get_exec_file (0);
745       if (exec_file == 0)
746         exec_file = "";
747       printf_unfiltered (_("Detaching from program: %s, %s\n"), exec_file,
748                          target_pid_to_str (pid_to_ptid (pid)));
749       gdb_flush (gdb_stdout);
750     }
751   if (args)
752     sig = atoi (args);
753
754   /* ??? The HP-UX 11.0 ttrace(2) manual page doesn't mention that we
755      can pass a signal number here.  Does this really work?  */
756   if (ttrace (TT_PROC_DETACH, pid, 0, 0, sig, 0) == -1)
757     perror_with_name (("ttrace"));
758
759   if (inf_ttrace_vfork_ppid != -1)
760     {
761       if (ttrace (TT_PROC_DETACH, inf_ttrace_vfork_ppid, 0, 0, 0, 0) == -1)
762         perror_with_name (("ttrace"));
763       inf_ttrace_vfork_ppid = -1;
764     }
765
766   inf_ttrace_num_lwps = 0;
767   inf_ttrace_num_lwps_in_syscall = 0;
768
769   unpush_target (ttrace_ops_hack);
770   inferior_ptid = null_ptid;
771 }
772
773 static void
774 inf_ttrace_kill (void)
775 {
776   pid_t pid = ptid_get_pid (inferior_ptid);
777
778   if (pid == 0)
779     return;
780
781   if (ttrace (TT_PROC_EXIT, pid, 0, 0, 0, 0) == -1)
782     perror_with_name (("ttrace"));
783   /* ??? Is it necessary to call ttrace_wait() here?  */
784
785   if (inf_ttrace_vfork_ppid != -1)
786     {
787       if (ttrace (TT_PROC_DETACH, inf_ttrace_vfork_ppid, 0, 0, 0, 0) == -1)
788         perror_with_name (("ttrace"));
789       inf_ttrace_vfork_ppid = -1;
790     }
791
792   target_mourn_inferior ();
793 }
794
795 static int
796 inf_ttrace_resume_callback (struct thread_info *info, void *arg)
797 {
798   if (!ptid_equal (info->ptid, inferior_ptid))
799     {
800       pid_t pid = ptid_get_pid (info->ptid);
801       lwpid_t lwpid = ptid_get_lwp (info->ptid);
802
803       if (ttrace (TT_LWP_CONTINUE, pid, lwpid, TT_NOPC, 0, 0) == -1)
804         perror_with_name (("ttrace"));
805     }
806
807   return 0;
808 }
809
810 static void
811 inf_ttrace_resume (ptid_t ptid, int step, enum target_signal signal)
812 {
813   pid_t pid = ptid_get_pid (ptid);
814   lwpid_t lwpid = ptid_get_lwp (ptid);
815   ttreq_t request = step ? TT_LWP_SINGLE : TT_LWP_CONTINUE;
816   int sig = target_signal_to_host (signal);
817
818   if (pid == -1)
819     {
820       pid = ptid_get_pid (inferior_ptid);
821       lwpid = ptid_get_lwp (inferior_ptid);
822     }
823
824   if (ttrace (request, pid, lwpid, TT_NOPC, sig, 0) == -1)
825     perror_with_name (("ttrace"));
826
827   if (ptid_equal (ptid, minus_one_ptid) && inf_ttrace_num_lwps > 0)
828     {
829       /* Let all the other threads run too.  */
830       iterate_over_threads (inf_ttrace_resume_callback, NULL);
831     }
832 }
833
834 static ptid_t
835 inf_ttrace_wait (ptid_t ptid, struct target_waitstatus *ourstatus)
836 {
837   pid_t pid = ptid_get_pid (ptid);
838   lwpid_t lwpid = ptid_get_lwp (ptid);
839   ttstate_t tts;
840
841   /* Until proven otherwise.  */
842   ourstatus->kind = TARGET_WAITKIND_SPURIOUS;
843
844   if (pid == -1)
845     pid = lwpid = 0;
846
847   gdb_assert (pid != 0 || lwpid == 0);
848
849   do
850     {
851       set_sigint_trap ();
852       set_sigio_trap ();
853
854       if (ttrace_wait (pid, lwpid, TTRACE_WAITOK, &tts, sizeof tts) == -1)
855         perror_with_name (("ttrace_wait"));
856
857       if (tts.tts_event == TTEVT_VFORK && tts.tts_u.tts_fork.tts_isparent)
858         {
859           if (inf_ttrace_vfork_ppid != -1)
860             {
861               gdb_assert (inf_ttrace_vfork_ppid == tts.tts_pid);
862
863               if (ttrace (TT_PROC_DETACH, tts.tts_pid, 0, 0, 0, 0) == -1)
864                 perror_with_name (("ttrace"));
865               inf_ttrace_vfork_ppid = -1;
866             }
867
868           tts.tts_event = TTEVT_NONE;
869         }
870
871       clear_sigio_trap ();
872       clear_sigint_trap ();
873     }
874   while (tts.tts_event == TTEVT_NONE);
875
876   /* Now that we've waited, we can re-enable the page protections.  */
877   if (inf_ttrace_reenable_page_protections)
878     {
879       gdb_assert (inf_ttrace_num_lwps_in_syscall == 0);
880       inf_ttrace_enable_page_protections (tts.tts_pid);
881       inf_ttrace_reenable_page_protections = 0;
882     }
883
884   ptid = ptid_build (tts.tts_pid, tts.tts_lwpid, 0);
885
886   switch (tts.tts_event)
887     {
888 #ifdef TTEVT_BPT_SSTEP
889     case TTEVT_BPT_SSTEP:
890       /* Make it look like a breakpoint.  */
891       ourstatus->kind = TARGET_WAITKIND_STOPPED;
892       ourstatus->value.sig = TARGET_SIGNAL_TRAP;
893       break;
894 #endif
895
896     case TTEVT_EXEC:
897       /* FIXME: kettenis/20051029: GDB doesn't really know how to deal
898          with TARGET_WAITKIND_EXECD events yet.  So we make it look
899          like a SIGTRAP instead.  */
900 #if 0
901       ourstatus->kind = TARGET_WAITKIND_EXECD;
902       ourstatus->value.execd_pathname =
903         xmalloc (tts.tts_u.tts_exec.tts_pathlen + 1);
904       if (ttrace (TT_PROC_GET_PATHNAME, tts.tts_pid, 0,
905                   (uintptr_t)ourstatus->value.execd_pathname,
906                   tts.tts_u.tts_exec.tts_pathlen, 0) == -1)
907         perror_with_name (("ttrace"));
908       ourstatus->value.execd_pathname[tts.tts_u.tts_exec.tts_pathlen] = 0;
909 #else
910       ourstatus->kind = TARGET_WAITKIND_STOPPED;
911       ourstatus->value.sig = TARGET_SIGNAL_TRAP;
912 #endif
913       break;
914
915     case TTEVT_EXIT:
916       store_waitstatus (ourstatus, tts.tts_u.tts_exit.tts_exitcode);
917       inf_ttrace_num_lwps = 0;
918       break;
919
920     case TTEVT_FORK:
921       ourstatus->kind = TARGET_WAITKIND_FORKED;
922       ourstatus->value.related_pid = tts.tts_u.tts_fork.tts_fpid;
923
924       /* Make sure the other end of the fork is stopped too.  */
925       if (ttrace_wait (tts.tts_u.tts_fork.tts_fpid,
926                        tts.tts_u.tts_fork.tts_flwpid,
927                        TTRACE_WAITOK, &tts, sizeof tts) == -1)
928         perror_with_name (("ttrace_wait"));
929
930       gdb_assert (tts.tts_event == TTEVT_FORK);
931       if (tts.tts_u.tts_fork.tts_isparent)
932         {
933           ptid = ptid_build (tts.tts_pid, tts.tts_lwpid, 0);
934           ourstatus->value.related_pid = tts.tts_u.tts_fork.tts_fpid;
935         }
936       break;
937
938     case TTEVT_VFORK:
939       gdb_assert (!tts.tts_u.tts_fork.tts_isparent);
940
941       ourstatus->kind = TARGET_WAITKIND_VFORKED;
942       ourstatus->value.related_pid = tts.tts_u.tts_fork.tts_fpid;
943
944       /* HACK: To avoid touching the parent during the vfork, switch
945          away from it.  */
946       inferior_ptid = ptid;
947       break;
948
949     case TTEVT_LWP_CREATE:
950       lwpid = tts.tts_u.tts_thread.tts_target_lwpid;
951       ptid = ptid_build (tts.tts_pid, lwpid, 0);
952       if (inf_ttrace_num_lwps == 0)
953         {
954           /* Now that we're going to be multi-threaded, add the
955              original thread to the list first.  */
956           add_thread (ptid_build (tts.tts_pid, tts.tts_lwpid, 0));
957           inf_ttrace_num_lwps++;
958         }
959       printf_filtered (_("[New %s]\n"), target_pid_to_str (ptid));
960       add_thread (ptid);
961       inf_ttrace_num_lwps++;
962       ptid = ptid_build (tts.tts_pid, tts.tts_lwpid, 0);
963       break;
964
965     case TTEVT_LWP_EXIT:
966       printf_filtered(_("[%s exited]\n"), target_pid_to_str (ptid));
967       delete_thread (ptid);
968       inf_ttrace_num_lwps--;
969       /* If we don't return -1 here, core GDB will re-add the thread.  */
970       ptid = minus_one_ptid;
971       break;
972
973     case TTEVT_LWP_TERMINATE:
974       lwpid = tts.tts_u.tts_thread.tts_target_lwpid;
975       ptid = ptid_build (tts.tts_pid, lwpid, 0);
976       printf_filtered(_("[%s has been terminated]\n"), target_pid_to_str (ptid));
977       delete_thread (ptid);
978       inf_ttrace_num_lwps--;
979       ptid = ptid_build (tts.tts_pid, tts.tts_lwpid, 0);
980       break;
981
982     case TTEVT_SIGNAL:
983       ourstatus->kind = TARGET_WAITKIND_STOPPED;
984       ourstatus->value.sig =
985         target_signal_from_host (tts.tts_u.tts_signal.tts_signo);
986       break;
987
988     case TTEVT_SYSCALL_ENTRY:
989       gdb_assert (inf_ttrace_reenable_page_protections == 0);
990       inf_ttrace_num_lwps_in_syscall++;
991       if (inf_ttrace_num_lwps_in_syscall == 1)
992         {
993           /* A thread has just entered a system call.  Disable any
994              page protections as the kernel can't deal with them.  */
995           inf_ttrace_disable_page_protections (tts.tts_pid);
996         }
997       ourstatus->kind = TARGET_WAITKIND_SYSCALL_ENTRY;
998       ourstatus->value.syscall_id = tts.tts_scno;
999       break;
1000
1001     case TTEVT_SYSCALL_RETURN:
1002       if (inf_ttrace_num_lwps_in_syscall > 0)
1003         {
1004           /* If the last thread has just left the system call, this
1005              would be a logical place to re-enable the page
1006              protections, but that doesn't work.  We can't re-enable
1007              them until we've done another wait.  */
1008           inf_ttrace_reenable_page_protections = 
1009             (inf_ttrace_num_lwps_in_syscall == 1);
1010           inf_ttrace_num_lwps_in_syscall--;
1011         }
1012       ourstatus->kind = TARGET_WAITKIND_SYSCALL_RETURN;
1013       ourstatus->value.syscall_id = tts.tts_scno;
1014       break;
1015
1016     default:
1017       gdb_assert (!"Unexpected ttrace event");
1018       break;
1019     }
1020
1021   /* Make sure all threads within the process are stopped.  */
1022   if (ttrace (TT_PROC_STOP, tts.tts_pid, 0, 0, 0, 0) == -1)
1023     perror_with_name (("ttrace"));
1024
1025   /* HACK: Twiddle INFERIOR_PTID such that the initial thread of a
1026      process isn't recognized as a new thread.  */
1027   if (ptid_get_lwp (inferior_ptid) == 0)
1028     inferior_ptid = ptid;
1029
1030   return ptid;
1031 }
1032
1033 /* Transfer LEN bytes from ADDR in the inferior's memory into READBUF,
1034    and transfer LEN bytes from WRITEBUF into the inferior's memory at
1035    ADDR.  Either READBUF or WRITEBUF may be null, in which case the
1036    corresponding transfer doesn't happen.  Return the number of bytes
1037    actually transferred (which may be zero if an error occurs).  */
1038
1039 static LONGEST
1040 inf_ttrace_xfer_memory (CORE_ADDR addr, ULONGEST len,
1041                         void *readbuf, const void *writebuf)
1042 {
1043   pid_t pid = ptid_get_pid (inferior_ptid);
1044
1045   /* HP-UX treats text space and data space differently.  GDB however,
1046      doesn't really know the difference.  Therefore we try both.  Try
1047      text space before data space though because when we're writing
1048      into text space the instruction cache might need to be flushed.  */
1049
1050   if (readbuf
1051       && ttrace (TT_PROC_RDTEXT, pid, 0, addr, len, (uintptr_t)readbuf) == -1
1052       && ttrace (TT_PROC_RDDATA, pid, 0, addr, len, (uintptr_t)readbuf) == -1)
1053     return 0;
1054
1055   if (writebuf
1056       && ttrace (TT_PROC_WRTEXT, pid, 0, addr, len, (uintptr_t)writebuf) == -1
1057       && ttrace (TT_PROC_WRDATA, pid, 0, addr, len, (uintptr_t)writebuf) == -1)
1058     return 0;
1059
1060   return len;
1061 }
1062
1063 static LONGEST
1064 inf_ttrace_xfer_partial (struct target_ops *ops, enum target_object object,
1065                          const char *annex, gdb_byte *readbuf,
1066                          const gdb_byte *writebuf, ULONGEST offset, LONGEST len)
1067 {
1068   switch (object)
1069     {
1070     case TARGET_OBJECT_MEMORY:
1071       return inf_ttrace_xfer_memory (offset, len, readbuf, writebuf);
1072
1073     case TARGET_OBJECT_UNWIND_TABLE:
1074       return -1;
1075
1076     case TARGET_OBJECT_AUXV:
1077       return -1;
1078
1079     case TARGET_OBJECT_WCOOKIE:
1080       return -1;
1081
1082     default:
1083       return -1;
1084     }
1085 }
1086
1087 /* Print status information about what we're accessing.  */
1088
1089 static void
1090 inf_ttrace_files_info (struct target_ops *ignore)
1091 {
1092   printf_filtered (_("\tUsing the running image of %s %s.\n"),
1093                    attach_flag ? "attached" : "child",
1094                    target_pid_to_str (inferior_ptid));
1095 }
1096
1097 static int
1098 inf_ttrace_thread_alive (ptid_t ptid)
1099 {
1100   return 1;
1101 }
1102
1103 static char *
1104 inf_ttrace_pid_to_str (ptid_t ptid)
1105 {
1106   if (inf_ttrace_num_lwps > 0)
1107     {
1108       pid_t pid = ptid_get_pid (ptid);
1109       lwpid_t lwpid = ptid_get_lwp (ptid);
1110       static char buf[128];
1111
1112       xsnprintf (buf, sizeof buf, "process %ld, lwp %ld",
1113                  (long)pid, (long)lwpid);
1114       return buf;
1115     }
1116
1117   return normal_pid_to_str (ptid);
1118 }
1119 \f
1120
1121 struct target_ops *
1122 inf_ttrace_target (void)
1123 {
1124   struct target_ops *t = inf_child_target ();
1125
1126   t->to_attach = inf_ttrace_attach;
1127   t->to_detach = inf_ttrace_detach;
1128   t->to_resume = inf_ttrace_resume;
1129   t->to_wait = inf_ttrace_wait;
1130   t->to_files_info = inf_ttrace_files_info;
1131   t->to_can_use_hw_breakpoint = inf_ttrace_can_use_hw_breakpoint;
1132   t->to_insert_watchpoint = inf_ttrace_insert_watchpoint;
1133   t->to_remove_watchpoint = inf_ttrace_remove_watchpoint;
1134   t->to_stopped_by_watchpoint = inf_ttrace_stopped_by_watchpoint;
1135   t->to_region_size_ok_for_hw_watchpoint =
1136     inf_ttrace_region_size_ok_for_hw_watchpoint;
1137   t->to_kill = inf_ttrace_kill;
1138   t->to_create_inferior = inf_ttrace_create_inferior;
1139   t->to_follow_fork = inf_ttrace_follow_fork;
1140   t->to_mourn_inferior = inf_ttrace_mourn_inferior;
1141   t->to_thread_alive = inf_ttrace_thread_alive;
1142   t->to_pid_to_str = inf_ttrace_pid_to_str;
1143   t->to_xfer_partial = inf_ttrace_xfer_partial;
1144
1145   ttrace_ops_hack = t;
1146   return t;
1147 }
1148 #endif
1149 \f
1150
1151 /* Prevent warning from -Wmissing-prototypes.  */
1152 void _initialize_hppa_hpux_nat (void);
1153
1154 void
1155 _initialize_inf_ttrace (void)
1156 {
1157 #ifdef HAVE_TTRACE
1158   inf_ttrace_page_dict.pagesize = getpagesize();
1159 #endif
1160 }
This page took 0.094828 seconds and 4 git commands to generate.