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