Copy this patch over from master gcc repository:
[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:
5d426ff1
MK
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;
eee22bf8 907 break;
932936f0 908
eee22bf8
MK
909 case TTEVT_EXIT:
910 store_waitstatus (ourstatus, tts.tts_u.tts_exit.tts_exitcode);
a7be7fa8
MK
911 inf_ttrace_num_lwps = 0;
912 break;
913
b2a4db28
MK
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
a7be7fa8
MK
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
3d450bdd 949 original thread to the list first. */
60e2c248
JG
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));
a7be7fa8
MK
955 inf_ttrace_num_lwps++;
956 }
60e2c248
JG
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));
a7be7fa8
MK
962 inf_ttrace_num_lwps++;
963 ptid = ptid_build (tts.tts_pid, tts.tts_lwpid, 0);
964 break;
965
966 case TTEVT_LWP_EXIT:
a3f17187 967 printf_filtered(_("[%s exited]\n"), target_pid_to_str (ptid));
60e2c248
JG
968 ti = find_thread_pid (ptid);
969 gdb_assert (ti != NULL);
970 ((struct inf_ttrace_private_thread_info *)ti->private)->dying = 1;
a7be7fa8 971 inf_ttrace_num_lwps--;
60e2c248
JG
972 ttrace (TT_LWP_CONTINUE, ptid_get_pid (ptid),
973 ptid_get_lwp (ptid), TT_NOPC, 0, 0);
a7be7fa8
MK
974 /* If we don't return -1 here, core GDB will re-add the thread. */
975 ptid = minus_one_ptid;
976 break;
977
978 case TTEVT_LWP_TERMINATE:
979 lwpid = tts.tts_u.tts_thread.tts_target_lwpid;
980 ptid = ptid_build (tts.tts_pid, lwpid, 0);
a3f17187 981 printf_filtered(_("[%s has been terminated]\n"), target_pid_to_str (ptid));
60e2c248
JG
982 ti = find_thread_pid (ptid);
983 gdb_assert (ti != NULL);
984 ((struct inf_ttrace_private_thread_info *)ti->private)->dying = 1;
a7be7fa8
MK
985 inf_ttrace_num_lwps--;
986 ptid = ptid_build (tts.tts_pid, tts.tts_lwpid, 0);
eee22bf8 987 break;
932936f0 988
eee22bf8
MK
989 case TTEVT_SIGNAL:
990 ourstatus->kind = TARGET_WAITKIND_STOPPED;
991 ourstatus->value.sig =
992 target_signal_from_host (tts.tts_u.tts_signal.tts_signo);
993 break;
932936f0
MK
994
995 case TTEVT_SYSCALL_ENTRY:
996 gdb_assert (inf_ttrace_reenable_page_protections == 0);
a7be7fa8
MK
997 inf_ttrace_num_lwps_in_syscall++;
998 if (inf_ttrace_num_lwps_in_syscall == 1)
932936f0
MK
999 {
1000 /* A thread has just entered a system call. Disable any
1001 page protections as the kernel can't deal with them. */
1002 inf_ttrace_disable_page_protections (tts.tts_pid);
1003 }
1004 ourstatus->kind = TARGET_WAITKIND_SYSCALL_ENTRY;
1005 ourstatus->value.syscall_id = tts.tts_scno;
1006 break;
1007
1008 case TTEVT_SYSCALL_RETURN:
a7be7fa8 1009 if (inf_ttrace_num_lwps_in_syscall > 0)
932936f0
MK
1010 {
1011 /* If the last thread has just left the system call, this
1012 would be a logical place to re-enable the page
1013 protections, but that doesn't work. We can't re-enable
1014 them until we've done another wait. */
1015 inf_ttrace_reenable_page_protections =
a7be7fa8
MK
1016 (inf_ttrace_num_lwps_in_syscall == 1);
1017 inf_ttrace_num_lwps_in_syscall--;
932936f0
MK
1018 }
1019 ourstatus->kind = TARGET_WAITKIND_SYSCALL_RETURN;
1020 ourstatus->value.syscall_id = tts.tts_scno;
1021 break;
a7be7fa8
MK
1022
1023 default:
1024 gdb_assert (!"Unexpected ttrace event");
1025 break;
eee22bf8
MK
1026 }
1027
1028 /* Make sure all threads within the process are stopped. */
1029 if (ttrace (TT_PROC_STOP, tts.tts_pid, 0, 0, 0, 0) == -1)
e2e0b3e5 1030 perror_with_name (("ttrace"));
eee22bf8
MK
1031
1032 /* HACK: Twiddle INFERIOR_PTID such that the initial thread of a
1033 process isn't recognized as a new thread. */
1034 if (ptid_get_lwp (inferior_ptid) == 0)
a7be7fa8 1035 inferior_ptid = ptid;
eee22bf8 1036
a7be7fa8 1037 return ptid;
eee22bf8
MK
1038}
1039
1040/* Transfer LEN bytes from ADDR in the inferior's memory into READBUF,
1041 and transfer LEN bytes from WRITEBUF into the inferior's memory at
1042 ADDR. Either READBUF or WRITEBUF may be null, in which case the
1043 corresponding transfer doesn't happen. Return the number of bytes
1044 actually transferred (which may be zero if an error occurs). */
1045
1046static LONGEST
1047inf_ttrace_xfer_memory (CORE_ADDR addr, ULONGEST len,
1048 void *readbuf, const void *writebuf)
1049{
1050 pid_t pid = ptid_get_pid (inferior_ptid);
1051
1052 /* HP-UX treats text space and data space differently. GDB however,
1053 doesn't really know the difference. Therefore we try both. Try
1054 text space before data space though because when we're writing
1055 into text space the instruction cache might need to be flushed. */
1056
1057 if (readbuf
1058 && ttrace (TT_PROC_RDTEXT, pid, 0, addr, len, (uintptr_t)readbuf) == -1
1059 && ttrace (TT_PROC_RDDATA, pid, 0, addr, len, (uintptr_t)readbuf) == -1)
1060 return 0;
1061
1062 if (writebuf
1063 && ttrace (TT_PROC_WRTEXT, pid, 0, addr, len, (uintptr_t)writebuf) == -1
1064 && ttrace (TT_PROC_WRDATA, pid, 0, addr, len, (uintptr_t)writebuf) == -1)
1065 return 0;
1066
1067 return len;
1068}
1069
1070static LONGEST
1071inf_ttrace_xfer_partial (struct target_ops *ops, enum target_object object,
7a4609f7
MK
1072 const char *annex, gdb_byte *readbuf,
1073 const gdb_byte *writebuf, ULONGEST offset, LONGEST len)
eee22bf8
MK
1074{
1075 switch (object)
1076 {
1077 case TARGET_OBJECT_MEMORY:
1078 return inf_ttrace_xfer_memory (offset, len, readbuf, writebuf);
1079
1080 case TARGET_OBJECT_UNWIND_TABLE:
1081 return -1;
1082
1083 case TARGET_OBJECT_AUXV:
1084 return -1;
1085
1086 case TARGET_OBJECT_WCOOKIE:
1087 return -1;
1088
1089 default:
1090 return -1;
1091 }
1092}
1093
1094/* Print status information about what we're accessing. */
1095
1096static void
1097inf_ttrace_files_info (struct target_ops *ignore)
1098{
346e281c
MK
1099 printf_filtered (_("\tUsing the running image of %s %s.\n"),
1100 attach_flag ? "attached" : "child",
1101 target_pid_to_str (inferior_ptid));
eee22bf8 1102}
a7be7fa8
MK
1103
1104static int
1105inf_ttrace_thread_alive (ptid_t ptid)
1106{
60e2c248
JG
1107 struct thread_info *ti;
1108 ti = find_thread_pid (ptid);
1109 return !(((struct inf_ttrace_private_thread_info *)ti->private)->dying);
a7be7fa8
MK
1110}
1111
1112static char *
1113inf_ttrace_pid_to_str (ptid_t ptid)
1114{
1115 if (inf_ttrace_num_lwps > 0)
1116 {
1117 pid_t pid = ptid_get_pid (ptid);
1118 lwpid_t lwpid = ptid_get_lwp (ptid);
fd0a2a6f 1119 static char buf[128];
a7be7fa8 1120
5fff8fc0
MK
1121 xsnprintf (buf, sizeof buf, "process %ld, lwp %ld",
1122 (long)pid, (long)lwpid);
a7be7fa8
MK
1123 return buf;
1124 }
1125
1126 return normal_pid_to_str (ptid);
1127}
eee22bf8
MK
1128\f
1129
1130struct target_ops *
1131inf_ttrace_target (void)
1132{
1133 struct target_ops *t = inf_child_target ();
1134
eee22bf8
MK
1135 t->to_attach = inf_ttrace_attach;
1136 t->to_detach = inf_ttrace_detach;
1137 t->to_resume = inf_ttrace_resume;
1138 t->to_wait = inf_ttrace_wait;
eee22bf8 1139 t->to_files_info = inf_ttrace_files_info;
932936f0 1140 t->to_can_use_hw_breakpoint = inf_ttrace_can_use_hw_breakpoint;
932936f0
MK
1141 t->to_insert_watchpoint = inf_ttrace_insert_watchpoint;
1142 t->to_remove_watchpoint = inf_ttrace_remove_watchpoint;
1143 t->to_stopped_by_watchpoint = inf_ttrace_stopped_by_watchpoint;
2a3cdf79
WZ
1144 t->to_region_ok_for_hw_watchpoint =
1145 inf_ttrace_region_ok_for_hw_watchpoint;
346e281c
MK
1146 t->to_kill = inf_ttrace_kill;
1147 t->to_create_inferior = inf_ttrace_create_inferior;
1148 t->to_follow_fork = inf_ttrace_follow_fork;
1149 t->to_mourn_inferior = inf_ttrace_mourn_inferior;
1150 t->to_thread_alive = inf_ttrace_thread_alive;
1151 t->to_pid_to_str = inf_ttrace_pid_to_str;
1152 t->to_xfer_partial = inf_ttrace_xfer_partial;
eee22bf8
MK
1153
1154 ttrace_ops_hack = t;
1155 return t;
1156}
d3322e8a 1157#endif
932936f0
MK
1158\f
1159
1160/* Prevent warning from -Wmissing-prototypes. */
1161void _initialize_hppa_hpux_nat (void);
eee22bf8 1162
932936f0
MK
1163void
1164_initialize_inf_ttrace (void)
1165{
d3322e8a 1166#ifdef HAVE_TTRACE
932936f0 1167 inf_ttrace_page_dict.pagesize = getpagesize();
eee22bf8 1168#endif
d3322e8a 1169}
This page took 0.30012 seconds and 4 git commands to generate.