gdb/
[deliverable/binutils-gdb.git] / gdb / inf-ttrace.c
CommitLineData
eee22bf8
MK
1/* Low-level child interface to ttrace.
2
9b254dd1 3 Copyright (C) 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
eee22bf8
MK
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
a9762ec7 9 the Free Software Foundation; either version 3 of the License, or
eee22bf8
MK
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
a9762ec7 18 along with this program. If not, see <http://www.gnu.org/licenses/>. */
eee22bf8
MK
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"
a7be7fa8 28#include "gdbthread.h"
eee22bf8 29#include "inferior.h"
eee22bf8
MK
30#include "target.h"
31
32#include "gdb_assert.h"
33#include "gdb_string.h"
932936f0 34#include <sys/mman.h>
eee22bf8
MK
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. */
41static struct target_ops *ttrace_ops_hack;
932936f0
MK
42\f
43
a7be7fa8
MK
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. */
54static int inf_ttrace_num_lwps;
55\f
56
932936f0
MK
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
63struct 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
72struct 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
60e2c248
JG
79struct inf_ttrace_private_thread_info
80{
81 int dying;
82};
83
a7be7fa8
MK
84/* Number of lwps that are currently in a system call. */
85static int inf_ttrace_num_lwps_in_syscall;
932936f0
MK
86
87/* Flag to indicate whether we should re-enable page protections after
88 the next wait. */
89static int inf_ttrace_reenable_page_protections;
90
91/* Enable system call events for process PID. */
92
93static void
94inf_ttrace_enable_syscall_events (pid_t pid)
95{
96 ttevent_t tte;
97 ttstate_t tts;
98
a7be7fa8 99 gdb_assert (inf_ttrace_num_lwps_in_syscall == 0);
932936f0
MK
100
101 if (ttrace (TT_PROC_GET_EVENT_MASK, pid, 0,
102 (uintptr_t)&tte, sizeof tte, 0) == -1)
e2e0b3e5 103 perror_with_name (("ttrace"));
932936f0
MK
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)
e2e0b3e5 109 perror_with_name (("ttrace"));
932936f0
MK
110
111 if (ttrace (TT_PROC_GET_FIRST_LWP_STATE, pid, 0,
112 (uintptr_t)&tts, sizeof tts, 0) == -1)
e2e0b3e5 113 perror_with_name (("ttrace"));
932936f0
MK
114
115 if (tts.tts_flags & TTS_INSYSCALL)
a7be7fa8 116 inf_ttrace_num_lwps_in_syscall++;
932936f0
MK
117
118 /* FIXME: Handle multiple threads. */
119}
120
121/* Disable system call events for process PID. */
122
123static void
124inf_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)
e2e0b3e5 132 perror_with_name (("ttrace"));
932936f0
MK
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)
e2e0b3e5 138 perror_with_name (("ttrace"));
932936f0 139
a7be7fa8 140 inf_ttrace_num_lwps_in_syscall = 0;
932936f0
MK
141}
142
143/* Get information about the page at address ADDR for process PID from
144 the dictionary. */
145
146static struct inf_ttrace_page *
147inf_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
169static struct inf_ttrace_page *
170inf_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)
e2e0b3e5 195 perror_with_name (("ttrace"));
932936f0
MK
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
a7be7fa8 210 if (inf_ttrace_num_lwps_in_syscall == 0)
932936f0
MK
211 {
212 if (ttrace (TT_PROC_SET_MPROTECT, pid, 0,
213 addr, pagesize, prot & ~PROT_WRITE) == -1)
e2e0b3e5 214 perror_with_name (("ttrace"));
932936f0
MK
215 }
216 }
217
218 return page;
219}
220
221/* Insert the page at address ADDR of process PID to the dictionary. */
222
223static void
224inf_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
237static void
238inf_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 {
a7be7fa8 250 if (inf_ttrace_num_lwps_in_syscall == 0)
932936f0
MK
251 {
252 if (ttrace (TT_PROC_SET_MPROTECT, pid, 0,
253 addr, pagesize, page->prot) == -1)
e2e0b3e5 254 perror_with_name (("ttrace"));
932936f0
MK
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
272static void
273inf_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)
e2e0b3e5 288 perror_with_name (("ttrace"));
932936f0
MK
289
290 page = page->next;
291 }
292 }
293}
294
295/* Write-protect the pages in the dictionary for process PID. */
296
297static void
298inf_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
306static void
307inf_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
315static int
316inf_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
338static int
339inf_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
358static int
359inf_ttrace_can_use_hw_breakpoint (int type, int len, int ot)
360{
361 return (type == bp_hardware_watchpoint);
362}
363
364static int
2a3cdf79 365inf_ttrace_region_ok_for_hw_watchpoint (CORE_ADDR addr, int len)
932936f0
MK
366{
367 return 1;
368}
369
370/* Return non-zero if the current inferior was (potentially) stopped
371 by hitting a "hardware" watchpoint. */
372
373static int
374inf_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)
e2e0b3e5 384 perror_with_name (("ttrace"));
932936f0
MK
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
eee22bf8 401
b2a4db28
MK
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. */
406static pid_t inf_ttrace_vfork_ppid = -1;
407
408static int
ee057212 409inf_ttrace_follow_fork (struct target_ops *ops, int follow_child)
b2a4db28
MK
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, _("\
459Attaching 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, _("\
468Detaching 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
eee22bf8
MK
528/* File descriptors for pipes used as semaphores during initial
529 startup of an inferior. */
530static int inf_ttrace_pfd1[2];
531static int inf_ttrace_pfd2[2];
532
533static void
534do_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
542static void
543inf_ttrace_prepare (void)
544{
545 if (pipe (inf_ttrace_pfd1) == -1)
a3f17187 546 perror_with_name (("pipe"));
eee22bf8
MK
547
548 if (pipe (inf_ttrace_pfd2) == -1)
549 {
550 close (inf_ttrace_pfd1[0]);
551 close (inf_ttrace_pfd2[0]);
a3f17187 552 perror_with_name (("pipe"));
eee22bf8
MK
553 }
554}
555
556/* Prepare to be traced. */
557
558static void
559inf_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)
e2e0b3e5 566 perror_with_name (("ttrace"));
eee22bf8
MK
567
568 /* Tell our parent that we are ready to be traced. */
569 if (write (inf_ttrace_pfd1[1], &c, sizeof c) != sizeof c)
e2e0b3e5 570 perror_with_name (("write"));
eee22bf8
MK
571
572 /* Wait until our parent has set the initial event mask. */
573 if (read (inf_ttrace_pfd2[0], &c, sizeof c) != sizeof c)
e2e0b3e5 574 perror_with_name (("read"));
eee22bf8
MK
575
576 do_cleanups (old_chain);
577}
578
579/* Start tracing PID. */
580
581static void
582inf_ttrace_him (int pid)
583{
584 struct cleanup *old_chain = make_cleanup (do_cleanup_pfds, 0);
585 ttevent_t tte;
eee22bf8
MK
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)
e2e0b3e5 590 perror_with_name (("read"));
eee22bf8
MK
591
592 /* Set the initial event mask. */
593 memset (&tte, 0, sizeof (tte));
b2a4db28 594 tte.tte_events |= TTEVT_EXEC | TTEVT_EXIT | TTEVT_FORK | TTEVT_VFORK;
a7be7fa8 595 tte.tte_events |= TTEVT_LWP_CREATE | TTEVT_LWP_EXIT | TTEVT_LWP_TERMINATE;
7ba0e0c2
MK
596#ifdef TTEVT_BPT_SSTEP
597 tte.tte_events |= TTEVT_BPT_SSTEP;
598#endif
b2a4db28 599 tte.tte_opts |= TTEO_PROC_INHERIT;
eee22bf8
MK
600 if (ttrace (TT_PROC_SET_EVENT_MASK, pid, 0,
601 (uintptr_t)&tte, sizeof tte, 0) == -1)
e2e0b3e5 602 perror_with_name (("ttrace"));
eee22bf8
MK
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)
e2e0b3e5 606 perror_with_name (("write"));
eee22bf8
MK
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
629static void
630inf_ttrace_create_inferior (char *exec_file, char *allargs, char **env,
631 int from_tty)
632{
a7be7fa8
MK
633 gdb_assert (inf_ttrace_num_lwps == 0);
634 gdb_assert (inf_ttrace_num_lwps_in_syscall == 0);
932936f0 635 gdb_assert (inf_ttrace_page_dict.count == 0);
932936f0 636 gdb_assert (inf_ttrace_reenable_page_protections == 0);
b2a4db28 637 gdb_assert (inf_ttrace_vfork_ppid == -1);
932936f0 638
eee22bf8
MK
639 fork_inferior (exec_file, allargs, env, inf_ttrace_me, inf_ttrace_him,
640 inf_ttrace_prepare, NULL);
eee22bf8
MK
641}
642
eee22bf8
MK
643static void
644inf_ttrace_mourn_inferior (void)
645{
932936f0
MK
646 const int num_buckets = ARRAY_SIZE (inf_ttrace_page_dict.buckets);
647 int bucket;
648
a7be7fa8
MK
649 inf_ttrace_num_lwps = 0;
650 inf_ttrace_num_lwps_in_syscall = 0;
932936f0
MK
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
eee22bf8
MK
667 unpush_target (ttrace_ops_hack);
668 generic_mourn_inferior ();
669}
670
671static void
672inf_ttrace_attach (char *args, int from_tty)
673{
674 char *exec_file;
675 pid_t pid;
676 char *dummy;
932936f0 677 ttevent_t tte;
eee22bf8
MK
678
679 if (!args)
a3f17187 680 error_no_arg (_("process-id to attach"));
eee22bf8
MK
681
682 dummy = args;
683 pid = strtol (args, &dummy, 0);
684 if (pid == 0 && args == dummy)
8a3fe4f8 685 error (_("Illegal process-id: %s."), args);
eee22bf8
MK
686
687 if (pid == getpid ()) /* Trying to masturbate? */
8a3fe4f8 688 error (_("I refuse to debug myself!"));
eee22bf8
MK
689
690 if (from_tty)
691 {
346e281c 692 exec_file = get_exec_file (0);
eee22bf8
MK
693
694 if (exec_file)
a3f17187 695 printf_unfiltered (_("Attaching to program: %s, %s\n"), exec_file,
eee22bf8
MK
696 target_pid_to_str (pid_to_ptid (pid)));
697 else
a3f17187 698 printf_unfiltered (_("Attaching to %s\n"),
eee22bf8
MK
699 target_pid_to_str (pid_to_ptid (pid)));
700
701 gdb_flush (gdb_stdout);
702 }
703
a7be7fa8
MK
704 gdb_assert (inf_ttrace_num_lwps == 0);
705 gdb_assert (inf_ttrace_num_lwps_in_syscall == 0);
b2a4db28 706 gdb_assert (inf_ttrace_vfork_ppid == -1);
a7be7fa8 707
eee22bf8 708 if (ttrace (TT_PROC_ATTACH, pid, 0, TT_KILL_ON_EXIT, TT_VERSION, 0) == -1)
e2e0b3e5 709 perror_with_name (("ttrace"));
eee22bf8
MK
710 attach_flag = 1;
711
932936f0 712 /* Set the initial event mask. */
932936f0 713 memset (&tte, 0, sizeof (tte));
b2a4db28 714 tte.tte_events |= TTEVT_EXEC | TTEVT_EXIT | TTEVT_FORK | TTEVT_VFORK;
a7be7fa8 715 tte.tte_events |= TTEVT_LWP_CREATE | TTEVT_LWP_EXIT | TTEVT_LWP_TERMINATE;
7ba0e0c2
MK
716#ifdef TTEVT_BPT_SSTEP
717 tte.tte_events |= TTEVT_BPT_SSTEP;
718#endif
b2a4db28 719 tte.tte_opts |= TTEO_PROC_INHERIT;
932936f0
MK
720 if (ttrace (TT_PROC_SET_EVENT_MASK, pid, 0,
721 (uintptr_t)&tte, sizeof tte, 0) == -1)
e2e0b3e5 722 perror_with_name (("ttrace"));
932936f0 723
eee22bf8
MK
724 inferior_ptid = pid_to_ptid (pid);
725 push_target (ttrace_ops_hack);
eee22bf8
MK
726}
727
728static void
729inf_ttrace_detach (char *args, int from_tty)
730{
eee22bf8 731 pid_t pid = ptid_get_pid (inferior_ptid);
5d426ff1 732 int sig = 0;
eee22bf8
MK
733
734 if (from_tty)
735 {
736 char *exec_file = get_exec_file (0);
737 if (exec_file == 0)
738 exec_file = "";
a3f17187 739 printf_unfiltered (_("Detaching from program: %s, %s\n"), exec_file,
eee22bf8
MK
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)
e2e0b3e5 749 perror_with_name (("ttrace"));
eee22bf8 750
b2a4db28
MK
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
a7be7fa8
MK
758 inf_ttrace_num_lwps = 0;
759 inf_ttrace_num_lwps_in_syscall = 0;
932936f0 760
eee22bf8 761 unpush_target (ttrace_ops_hack);
932936f0 762 inferior_ptid = null_ptid;
eee22bf8
MK
763}
764
346e281c
MK
765static void
766inf_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
7ba0e0c2
MK
787static int
788inf_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)
e2e0b3e5 796 perror_with_name (("ttrace"));
7ba0e0c2
MK
797 }
798
799 return 0;
800}
801
60e2c248
JG
802static int
803inf_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
eee22bf8
MK
810static void
811inf_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)
e2e0b3e5 825 perror_with_name (("ttrace"));
eee22bf8 826
7ba0e0c2 827 if (ptid_equal (ptid, minus_one_ptid) && inf_ttrace_num_lwps > 0)
eee22bf8
MK
828 {
829 /* Let all the other threads run too. */
7ba0e0c2 830 iterate_over_threads (inf_ttrace_resume_callback, NULL);
60e2c248 831 iterate_over_threads (inf_ttrace_delete_dying_threads_callback, NULL);
eee22bf8
MK
832 }
833}
834
835static ptid_t
836inf_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;
60e2c248 841 struct thread_info *ti;
eee22bf8 842
932936f0 843 /* Until proven otherwise. */
a7be7fa8 844 ourstatus->kind = TARGET_WAITKIND_SPURIOUS;
eee22bf8
MK
845
846 if (pid == -1)
b2a4db28 847 pid = lwpid = 0;
eee22bf8 848
b2a4db28 849 gdb_assert (pid != 0 || lwpid == 0);
eee22bf8
MK
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)
a3f17187 857 perror_with_name (("ttrace_wait"));
eee22bf8 858
b2a4db28
MK
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
eee22bf8
MK
873 clear_sigio_trap ();
874 clear_sigint_trap ();
875 }
876 while (tts.tts_event == TTEVT_NONE);
877
932936f0
MK
878 /* Now that we've waited, we can re-enable the page protections. */
879 if (inf_ttrace_reenable_page_protections)
880 {
a7be7fa8 881 gdb_assert (inf_ttrace_num_lwps_in_syscall == 0);
932936f0
MK
882 inf_ttrace_enable_page_protections (tts.tts_pid);
883 inf_ttrace_reenable_page_protections = 0;
884 }
885
a7be7fa8
MK
886 ptid = ptid_build (tts.tts_pid, tts.tts_lwpid, 0);
887
eee22bf8
MK
888 switch (tts.tts_event)
889 {
7ba0e0c2
MK
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
eee22bf8 898 case TTEVT_EXEC:
7c35e3f3
MK
899 /* FIXME: kettenis/20051029: GDB doesn't really know how to deal
900 with TARGET_WAITKIND_EXECD events yet. So we make it look
901 like a SIGTRAP instead. */
902#if 0
5d426ff1
MK
903 ourstatus->kind = TARGET_WAITKIND_EXECD;
904 ourstatus->value.execd_pathname =
905 xmalloc (tts.tts_u.tts_exec.tts_pathlen + 1);
906 if (ttrace (TT_PROC_GET_PATHNAME, tts.tts_pid, 0,
907 (uintptr_t)ourstatus->value.execd_pathname,
908 tts.tts_u.tts_exec.tts_pathlen, 0) == -1)
909 perror_with_name (("ttrace"));
910 ourstatus->value.execd_pathname[tts.tts_u.tts_exec.tts_pathlen] = 0;
7c35e3f3
MK
911#else
912 ourstatus->kind = TARGET_WAITKIND_STOPPED;
913 ourstatus->value.sig = TARGET_SIGNAL_TRAP;
914#endif
eee22bf8 915 break;
932936f0 916
eee22bf8
MK
917 case TTEVT_EXIT:
918 store_waitstatus (ourstatus, tts.tts_u.tts_exit.tts_exitcode);
a7be7fa8
MK
919 inf_ttrace_num_lwps = 0;
920 break;
921
b2a4db28
MK
922 case TTEVT_FORK:
923 ourstatus->kind = TARGET_WAITKIND_FORKED;
924 ourstatus->value.related_pid = tts.tts_u.tts_fork.tts_fpid;
925
926 /* Make sure the other end of the fork is stopped too. */
927 if (ttrace_wait (tts.tts_u.tts_fork.tts_fpid,
928 tts.tts_u.tts_fork.tts_flwpid,
929 TTRACE_WAITOK, &tts, sizeof tts) == -1)
930 perror_with_name (("ttrace_wait"));
931
932 gdb_assert (tts.tts_event == TTEVT_FORK);
933 if (tts.tts_u.tts_fork.tts_isparent)
934 {
935 ptid = ptid_build (tts.tts_pid, tts.tts_lwpid, 0);
936 ourstatus->value.related_pid = tts.tts_u.tts_fork.tts_fpid;
937 }
938 break;
939
940 case TTEVT_VFORK:
941 gdb_assert (!tts.tts_u.tts_fork.tts_isparent);
942
943 ourstatus->kind = TARGET_WAITKIND_VFORKED;
944 ourstatus->value.related_pid = tts.tts_u.tts_fork.tts_fpid;
945
946 /* HACK: To avoid touching the parent during the vfork, switch
947 away from it. */
948 inferior_ptid = ptid;
949 break;
950
a7be7fa8
MK
951 case TTEVT_LWP_CREATE:
952 lwpid = tts.tts_u.tts_thread.tts_target_lwpid;
953 ptid = ptid_build (tts.tts_pid, lwpid, 0);
954 if (inf_ttrace_num_lwps == 0)
955 {
956 /* Now that we're going to be multi-threaded, add the
3d450bdd 957 original thread to the list first. */
60e2c248
JG
958 ti = add_thread (ptid_build (tts.tts_pid, tts.tts_lwpid, 0));
959 ti->private =
960 xmalloc (sizeof (struct inf_ttrace_private_thread_info));
961 memset (ti->private, 0,
962 sizeof (struct inf_ttrace_private_thread_info));
a7be7fa8
MK
963 inf_ttrace_num_lwps++;
964 }
a3f17187 965 printf_filtered (_("[New %s]\n"), target_pid_to_str (ptid));
60e2c248
JG
966 ti = add_thread (ptid);
967 ti->private =
968 xmalloc (sizeof (struct inf_ttrace_private_thread_info));
969 memset (ti->private, 0,
970 sizeof (struct inf_ttrace_private_thread_info));
a7be7fa8
MK
971 inf_ttrace_num_lwps++;
972 ptid = ptid_build (tts.tts_pid, tts.tts_lwpid, 0);
973 break;
974
975 case TTEVT_LWP_EXIT:
a3f17187 976 printf_filtered(_("[%s exited]\n"), target_pid_to_str (ptid));
60e2c248
JG
977 ti = find_thread_pid (ptid);
978 gdb_assert (ti != NULL);
979 ((struct inf_ttrace_private_thread_info *)ti->private)->dying = 1;
a7be7fa8 980 inf_ttrace_num_lwps--;
60e2c248
JG
981 ttrace (TT_LWP_CONTINUE, ptid_get_pid (ptid),
982 ptid_get_lwp (ptid), TT_NOPC, 0, 0);
a7be7fa8
MK
983 /* If we don't return -1 here, core GDB will re-add the thread. */
984 ptid = minus_one_ptid;
985 break;
986
987 case TTEVT_LWP_TERMINATE:
988 lwpid = tts.tts_u.tts_thread.tts_target_lwpid;
989 ptid = ptid_build (tts.tts_pid, lwpid, 0);
a3f17187 990 printf_filtered(_("[%s has been terminated]\n"), target_pid_to_str (ptid));
60e2c248
JG
991 ti = find_thread_pid (ptid);
992 gdb_assert (ti != NULL);
993 ((struct inf_ttrace_private_thread_info *)ti->private)->dying = 1;
a7be7fa8
MK
994 inf_ttrace_num_lwps--;
995 ptid = ptid_build (tts.tts_pid, tts.tts_lwpid, 0);
eee22bf8 996 break;
932936f0 997
eee22bf8
MK
998 case TTEVT_SIGNAL:
999 ourstatus->kind = TARGET_WAITKIND_STOPPED;
1000 ourstatus->value.sig =
1001 target_signal_from_host (tts.tts_u.tts_signal.tts_signo);
1002 break;
932936f0
MK
1003
1004 case TTEVT_SYSCALL_ENTRY:
1005 gdb_assert (inf_ttrace_reenable_page_protections == 0);
a7be7fa8
MK
1006 inf_ttrace_num_lwps_in_syscall++;
1007 if (inf_ttrace_num_lwps_in_syscall == 1)
932936f0
MK
1008 {
1009 /* A thread has just entered a system call. Disable any
1010 page protections as the kernel can't deal with them. */
1011 inf_ttrace_disable_page_protections (tts.tts_pid);
1012 }
1013 ourstatus->kind = TARGET_WAITKIND_SYSCALL_ENTRY;
1014 ourstatus->value.syscall_id = tts.tts_scno;
1015 break;
1016
1017 case TTEVT_SYSCALL_RETURN:
a7be7fa8 1018 if (inf_ttrace_num_lwps_in_syscall > 0)
932936f0
MK
1019 {
1020 /* If the last thread has just left the system call, this
1021 would be a logical place to re-enable the page
1022 protections, but that doesn't work. We can't re-enable
1023 them until we've done another wait. */
1024 inf_ttrace_reenable_page_protections =
a7be7fa8
MK
1025 (inf_ttrace_num_lwps_in_syscall == 1);
1026 inf_ttrace_num_lwps_in_syscall--;
932936f0
MK
1027 }
1028 ourstatus->kind = TARGET_WAITKIND_SYSCALL_RETURN;
1029 ourstatus->value.syscall_id = tts.tts_scno;
1030 break;
a7be7fa8
MK
1031
1032 default:
1033 gdb_assert (!"Unexpected ttrace event");
1034 break;
eee22bf8
MK
1035 }
1036
1037 /* Make sure all threads within the process are stopped. */
1038 if (ttrace (TT_PROC_STOP, tts.tts_pid, 0, 0, 0, 0) == -1)
e2e0b3e5 1039 perror_with_name (("ttrace"));
eee22bf8
MK
1040
1041 /* HACK: Twiddle INFERIOR_PTID such that the initial thread of a
1042 process isn't recognized as a new thread. */
1043 if (ptid_get_lwp (inferior_ptid) == 0)
a7be7fa8 1044 inferior_ptid = ptid;
eee22bf8 1045
a7be7fa8 1046 return ptid;
eee22bf8
MK
1047}
1048
1049/* Transfer LEN bytes from ADDR in the inferior's memory into READBUF,
1050 and transfer LEN bytes from WRITEBUF into the inferior's memory at
1051 ADDR. Either READBUF or WRITEBUF may be null, in which case the
1052 corresponding transfer doesn't happen. Return the number of bytes
1053 actually transferred (which may be zero if an error occurs). */
1054
1055static LONGEST
1056inf_ttrace_xfer_memory (CORE_ADDR addr, ULONGEST len,
1057 void *readbuf, const void *writebuf)
1058{
1059 pid_t pid = ptid_get_pid (inferior_ptid);
1060
1061 /* HP-UX treats text space and data space differently. GDB however,
1062 doesn't really know the difference. Therefore we try both. Try
1063 text space before data space though because when we're writing
1064 into text space the instruction cache might need to be flushed. */
1065
1066 if (readbuf
1067 && ttrace (TT_PROC_RDTEXT, pid, 0, addr, len, (uintptr_t)readbuf) == -1
1068 && ttrace (TT_PROC_RDDATA, pid, 0, addr, len, (uintptr_t)readbuf) == -1)
1069 return 0;
1070
1071 if (writebuf
1072 && ttrace (TT_PROC_WRTEXT, pid, 0, addr, len, (uintptr_t)writebuf) == -1
1073 && ttrace (TT_PROC_WRDATA, pid, 0, addr, len, (uintptr_t)writebuf) == -1)
1074 return 0;
1075
1076 return len;
1077}
1078
1079static LONGEST
1080inf_ttrace_xfer_partial (struct target_ops *ops, enum target_object object,
7a4609f7
MK
1081 const char *annex, gdb_byte *readbuf,
1082 const gdb_byte *writebuf, ULONGEST offset, LONGEST len)
eee22bf8
MK
1083{
1084 switch (object)
1085 {
1086 case TARGET_OBJECT_MEMORY:
1087 return inf_ttrace_xfer_memory (offset, len, readbuf, writebuf);
1088
1089 case TARGET_OBJECT_UNWIND_TABLE:
1090 return -1;
1091
1092 case TARGET_OBJECT_AUXV:
1093 return -1;
1094
1095 case TARGET_OBJECT_WCOOKIE:
1096 return -1;
1097
1098 default:
1099 return -1;
1100 }
1101}
1102
1103/* Print status information about what we're accessing. */
1104
1105static void
1106inf_ttrace_files_info (struct target_ops *ignore)
1107{
346e281c
MK
1108 printf_filtered (_("\tUsing the running image of %s %s.\n"),
1109 attach_flag ? "attached" : "child",
1110 target_pid_to_str (inferior_ptid));
eee22bf8 1111}
a7be7fa8
MK
1112
1113static int
1114inf_ttrace_thread_alive (ptid_t ptid)
1115{
60e2c248
JG
1116 struct thread_info *ti;
1117 ti = find_thread_pid (ptid);
1118 return !(((struct inf_ttrace_private_thread_info *)ti->private)->dying);
a7be7fa8
MK
1119}
1120
1121static char *
1122inf_ttrace_pid_to_str (ptid_t ptid)
1123{
1124 if (inf_ttrace_num_lwps > 0)
1125 {
1126 pid_t pid = ptid_get_pid (ptid);
1127 lwpid_t lwpid = ptid_get_lwp (ptid);
fd0a2a6f 1128 static char buf[128];
a7be7fa8 1129
5fff8fc0
MK
1130 xsnprintf (buf, sizeof buf, "process %ld, lwp %ld",
1131 (long)pid, (long)lwpid);
a7be7fa8
MK
1132 return buf;
1133 }
1134
1135 return normal_pid_to_str (ptid);
1136}
eee22bf8
MK
1137\f
1138
1139struct target_ops *
1140inf_ttrace_target (void)
1141{
1142 struct target_ops *t = inf_child_target ();
1143
eee22bf8
MK
1144 t->to_attach = inf_ttrace_attach;
1145 t->to_detach = inf_ttrace_detach;
1146 t->to_resume = inf_ttrace_resume;
1147 t->to_wait = inf_ttrace_wait;
eee22bf8 1148 t->to_files_info = inf_ttrace_files_info;
932936f0 1149 t->to_can_use_hw_breakpoint = inf_ttrace_can_use_hw_breakpoint;
932936f0
MK
1150 t->to_insert_watchpoint = inf_ttrace_insert_watchpoint;
1151 t->to_remove_watchpoint = inf_ttrace_remove_watchpoint;
1152 t->to_stopped_by_watchpoint = inf_ttrace_stopped_by_watchpoint;
2a3cdf79
WZ
1153 t->to_region_ok_for_hw_watchpoint =
1154 inf_ttrace_region_ok_for_hw_watchpoint;
346e281c
MK
1155 t->to_kill = inf_ttrace_kill;
1156 t->to_create_inferior = inf_ttrace_create_inferior;
1157 t->to_follow_fork = inf_ttrace_follow_fork;
1158 t->to_mourn_inferior = inf_ttrace_mourn_inferior;
1159 t->to_thread_alive = inf_ttrace_thread_alive;
1160 t->to_pid_to_str = inf_ttrace_pid_to_str;
1161 t->to_xfer_partial = inf_ttrace_xfer_partial;
eee22bf8
MK
1162
1163 ttrace_ops_hack = t;
1164 return t;
1165}
d3322e8a 1166#endif
932936f0
MK
1167\f
1168
1169/* Prevent warning from -Wmissing-prototypes. */
1170void _initialize_hppa_hpux_nat (void);
eee22bf8 1171
932936f0
MK
1172void
1173_initialize_inf_ttrace (void)
1174{
d3322e8a 1175#ifdef HAVE_TTRACE
932936f0 1176 inf_ttrace_page_dict.pagesize = getpagesize();
eee22bf8 1177#endif
d3322e8a 1178}
This page took 0.316403 seconds and 4 git commands to generate.