Remove sp_regnum_from_eax and pc_regnum_from_eax
[deliverable/binutils-gdb.git] / gdb / inf-ttrace.c
CommitLineData
eee22bf8
MK
1/* Low-level child interface to ttrace.
2
0b302171 3 Copyright (C) 2004-2012 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"
191c4426 30#include "terminal.h"
eee22bf8
MK
31#include "target.h"
32
33#include "gdb_assert.h"
34#include "gdb_string.h"
932936f0 35#include <sys/mman.h>
eee22bf8 36#include <sys/ttrace.h>
438ac09b 37#include <signal.h>
eee22bf8
MK
38
39#include "inf-child.h"
40#include "inf-ttrace.h"
41
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
0cf6dd15
TJB
316inf_ttrace_insert_watchpoint (CORE_ADDR addr, int len, int type,
317 struct expression *cond)
932936f0
MK
318{
319 const int pagesize = inf_ttrace_page_dict.pagesize;
320 pid_t pid = ptid_get_pid (inferior_ptid);
321 CORE_ADDR page_addr;
322 int num_pages;
323 int page;
324
325 gdb_assert (type == hw_write);
326
327 page_addr = (addr / pagesize) * pagesize;
328 num_pages = (len + pagesize - 1) / pagesize;
329
330 for (page = 0; page < num_pages; page++, page_addr += pagesize)
331 inf_ttrace_insert_page (pid, page_addr);
332
333 return 1;
334}
335
336/* Remove a "hardware" watchpoint for LEN bytes at address ADDR of
337 type TYPE. */
338
339static int
0cf6dd15
TJB
340inf_ttrace_remove_watchpoint (CORE_ADDR addr, int len, int type,
341 struct expression *cond)
932936f0
MK
342{
343 const int pagesize = inf_ttrace_page_dict.pagesize;
344 pid_t pid = ptid_get_pid (inferior_ptid);
345 CORE_ADDR page_addr;
346 int num_pages;
347 int page;
348
349 gdb_assert (type == hw_write);
350
351 page_addr = (addr / pagesize) * pagesize;
352 num_pages = (len + pagesize - 1) / pagesize;
353
354 for (page = 0; page < num_pages; page++, page_addr += pagesize)
355 inf_ttrace_remove_page (pid, page_addr);
356
357 return 1;
358}
359
360static int
361inf_ttrace_can_use_hw_breakpoint (int type, int len, int ot)
362{
363 return (type == bp_hardware_watchpoint);
364}
365
366static int
2a3cdf79 367inf_ttrace_region_ok_for_hw_watchpoint (CORE_ADDR addr, int len)
932936f0
MK
368{
369 return 1;
370}
371
372/* Return non-zero if the current inferior was (potentially) stopped
373 by hitting a "hardware" watchpoint. */
374
375static int
376inf_ttrace_stopped_by_watchpoint (void)
377{
378 pid_t pid = ptid_get_pid (inferior_ptid);
379 lwpid_t lwpid = ptid_get_lwp (inferior_ptid);
380 ttstate_t tts;
381
382 if (inf_ttrace_page_dict.count > 0)
383 {
384 if (ttrace (TT_LWP_GET_STATE, pid, lwpid,
385 (uintptr_t)&tts, sizeof tts, 0) == -1)
e2e0b3e5 386 perror_with_name (("ttrace"));
932936f0
MK
387
388 if (tts.tts_event == TTEVT_SIGNAL
389 && tts.tts_u.tts_signal.tts_signo == SIGBUS)
390 {
391 const int pagesize = inf_ttrace_page_dict.pagesize;
392 void *addr = tts.tts_u.tts_signal.tts_siginfo.si_addr;
393 CORE_ADDR page_addr = ((uintptr_t)addr / pagesize) * pagesize;
394
395 if (inf_ttrace_get_page (pid, page_addr))
396 return 1;
397 }
398 }
399
400 return 0;
401}
402\f
eee22bf8 403
b2a4db28
MK
404/* When tracking a vfork(2), we cannot detach from the parent until
405 after the child has called exec(3) or has exited. If we are still
406 attached to the parent, this variable will be set to the process ID
407 of the parent. Otherwise it will be set to zero. */
408static pid_t inf_ttrace_vfork_ppid = -1;
409
410static int
ee057212 411inf_ttrace_follow_fork (struct target_ops *ops, int follow_child)
b2a4db28
MK
412{
413 pid_t pid, fpid;
414 lwpid_t lwpid, flwpid;
415 ttstate_t tts;
e58b0e63
PA
416 struct thread_info *tp = inferior_thread ();
417
418 gdb_assert (tp->pending_follow.kind == TARGET_WAITKIND_FORKED
419 || tp->pending_follow.kind == TARGET_WAITKIND_VFORKED);
420
421 pid = ptid_get_pid (inferior_ptid);
422 lwpid = ptid_get_lwp (inferior_ptid);
b2a4db28
MK
423
424 /* Get all important details that core GDB doesn't (and shouldn't)
425 know about. */
426 if (ttrace (TT_LWP_GET_STATE, pid, lwpid,
427 (uintptr_t)&tts, sizeof tts, 0) == -1)
428 perror_with_name (("ttrace"));
429
430 gdb_assert (tts.tts_event == TTEVT_FORK || tts.tts_event == TTEVT_VFORK);
431
432 if (tts.tts_u.tts_fork.tts_isparent)
433 {
434 pid = tts.tts_pid;
435 lwpid = tts.tts_lwpid;
436 fpid = tts.tts_u.tts_fork.tts_fpid;
437 flwpid = tts.tts_u.tts_fork.tts_flwpid;
438 }
439 else
440 {
441 pid = tts.tts_u.tts_fork.tts_fpid;
442 lwpid = tts.tts_u.tts_fork.tts_flwpid;
443 fpid = tts.tts_pid;
444 flwpid = tts.tts_lwpid;
445 }
446
447 if (follow_child)
448 {
77435e4c 449 struct inferior *inf;
191c4426
PA
450 struct inferior *parent_inf;
451
452 parent_inf = find_inferior_pid (pid);
77435e4c 453
b2a4db28 454 inferior_ptid = ptid_build (fpid, flwpid, 0);
77435e4c 455 inf = add_inferior (fpid);
191c4426 456 inf->attach_flag = parent_inf->attach_flag;
6c95b8df
PA
457 inf->pspace = parent_inf->pspace;
458 inf->aspace = parent_inf->aspace;
191c4426 459 copy_terminal_info (inf, parent_inf);
d80ee84f 460 detach_breakpoints (ptid_build (pid, lwpid, 0));
b2a4db28
MK
461
462 target_terminal_ours ();
3e43a32a
MS
463 fprintf_unfiltered (gdb_stdlog,
464 _("Attaching after fork to child process %ld.\n"),
465 (long)fpid);
b2a4db28
MK
466 }
467 else
468 {
469 inferior_ptid = ptid_build (pid, lwpid, 0);
2dcc6086
JB
470 /* Detach any remaining breakpoints in the child. In the case
471 of fork events, we do not need to do this, because breakpoints
472 should have already been removed earlier. */
473 if (tts.tts_event == TTEVT_VFORK)
d80ee84f 474 detach_breakpoints (ptid_build (fpid, flwpid, 0));
b2a4db28
MK
475
476 target_terminal_ours ();
3e43a32a
MS
477 fprintf_unfiltered (gdb_stdlog,
478 _("Detaching after fork from child process %ld.\n"),
479 (long)fpid);
b2a4db28
MK
480 }
481
482 if (tts.tts_event == TTEVT_VFORK)
483 {
484 gdb_assert (!tts.tts_u.tts_fork.tts_isparent);
485
486 if (follow_child)
487 {
488 /* We can't detach from the parent yet. */
489 inf_ttrace_vfork_ppid = pid;
490
491 reattach_breakpoints (fpid);
492 }
493 else
494 {
495 if (ttrace (TT_PROC_DETACH, fpid, 0, 0, 0, 0) == -1)
496 perror_with_name (("ttrace"));
497
498 /* Wait till we get the TTEVT_VFORK event in the parent.
499 This indicates that the child has called exec(3) or has
500 exited and that the parent is ready to be traced again. */
501 if (ttrace_wait (pid, lwpid, TTRACE_WAITOK, &tts, sizeof tts) == -1)
502 perror_with_name (("ttrace_wait"));
503 gdb_assert (tts.tts_event == TTEVT_VFORK);
504 gdb_assert (tts.tts_u.tts_fork.tts_isparent);
505
506 reattach_breakpoints (pid);
507 }
508 }
509 else
510 {
511 gdb_assert (tts.tts_u.tts_fork.tts_isparent);
512
513 if (follow_child)
514 {
515 if (ttrace (TT_PROC_DETACH, pid, 0, 0, 0, 0) == -1)
516 perror_with_name (("ttrace"));
517 }
518 else
519 {
520 if (ttrace (TT_PROC_DETACH, fpid, 0, 0, 0, 0) == -1)
521 perror_with_name (("ttrace"));
522 }
523 }
524
525 if (follow_child)
526 {
2935f27f
PA
527 struct thread_info *ti;
528
b2a4db28 529 /* The child will start out single-threaded. */
2935f27f 530 inf_ttrace_num_lwps = 1;
b2a4db28
MK
531 inf_ttrace_num_lwps_in_syscall = 0;
532
2935f27f
PA
533 /* Delete parent. */
534 delete_thread_silent (ptid_build (pid, lwpid, 0));
7f9f62ba 535 detach_inferior (pid);
2935f27f 536
7f9f62ba 537 /* Add child thread. inferior_ptid was already set above. */
2935f27f
PA
538 ti = add_thread_silent (inferior_ptid);
539 ti->private =
540 xmalloc (sizeof (struct inf_ttrace_private_thread_info));
541 memset (ti->private, 0,
542 sizeof (struct inf_ttrace_private_thread_info));
b2a4db28
MK
543 }
544
545 return 0;
546}
547\f
548
eee22bf8
MK
549/* File descriptors for pipes used as semaphores during initial
550 startup of an inferior. */
551static int inf_ttrace_pfd1[2];
552static int inf_ttrace_pfd2[2];
553
554static void
555do_cleanup_pfds (void *dummy)
556{
557 close (inf_ttrace_pfd1[0]);
558 close (inf_ttrace_pfd1[1]);
559 close (inf_ttrace_pfd2[0]);
560 close (inf_ttrace_pfd2[1]);
561}
562
563static void
564inf_ttrace_prepare (void)
565{
566 if (pipe (inf_ttrace_pfd1) == -1)
a3f17187 567 perror_with_name (("pipe"));
eee22bf8
MK
568
569 if (pipe (inf_ttrace_pfd2) == -1)
570 {
571 close (inf_ttrace_pfd1[0]);
572 close (inf_ttrace_pfd2[0]);
a3f17187 573 perror_with_name (("pipe"));
eee22bf8
MK
574 }
575}
576
577/* Prepare to be traced. */
578
579static void
580inf_ttrace_me (void)
581{
582 struct cleanup *old_chain = make_cleanup (do_cleanup_pfds, 0);
583 char c;
584
585 /* "Trace me, Dr. Memory!" */
586 if (ttrace (TT_PROC_SETTRC, 0, 0, 0, TT_VERSION, 0) == -1)
e2e0b3e5 587 perror_with_name (("ttrace"));
eee22bf8
MK
588
589 /* Tell our parent that we are ready to be traced. */
590 if (write (inf_ttrace_pfd1[1], &c, sizeof c) != sizeof c)
e2e0b3e5 591 perror_with_name (("write"));
eee22bf8
MK
592
593 /* Wait until our parent has set the initial event mask. */
594 if (read (inf_ttrace_pfd2[0], &c, sizeof c) != sizeof c)
e2e0b3e5 595 perror_with_name (("read"));
eee22bf8
MK
596
597 do_cleanups (old_chain);
598}
599
600/* Start tracing PID. */
601
602static void
28439f5e 603inf_ttrace_him (struct target_ops *ops, int pid)
eee22bf8
MK
604{
605 struct cleanup *old_chain = make_cleanup (do_cleanup_pfds, 0);
606 ttevent_t tte;
eee22bf8
MK
607 char c;
608
609 /* Wait until our child is ready to be traced. */
610 if (read (inf_ttrace_pfd1[0], &c, sizeof c) != sizeof c)
e2e0b3e5 611 perror_with_name (("read"));
eee22bf8
MK
612
613 /* Set the initial event mask. */
614 memset (&tte, 0, sizeof (tte));
b2a4db28 615 tte.tte_events |= TTEVT_EXEC | TTEVT_EXIT | TTEVT_FORK | TTEVT_VFORK;
a7be7fa8 616 tte.tte_events |= TTEVT_LWP_CREATE | TTEVT_LWP_EXIT | TTEVT_LWP_TERMINATE;
7ba0e0c2
MK
617#ifdef TTEVT_BPT_SSTEP
618 tte.tte_events |= TTEVT_BPT_SSTEP;
619#endif
b2a4db28 620 tte.tte_opts |= TTEO_PROC_INHERIT;
eee22bf8
MK
621 if (ttrace (TT_PROC_SET_EVENT_MASK, pid, 0,
622 (uintptr_t)&tte, sizeof tte, 0) == -1)
e2e0b3e5 623 perror_with_name (("ttrace"));
eee22bf8
MK
624
625 /* Tell our child that we have set the initial event mask. */
626 if (write (inf_ttrace_pfd2[1], &c, sizeof c) != sizeof c)
e2e0b3e5 627 perror_with_name (("write"));
eee22bf8
MK
628
629 do_cleanups (old_chain);
630
28439f5e 631 push_target (ops);
eee22bf8 632
eee22bf8
MK
633 /* START_INFERIOR_TRAPS_EXPECTED is defined in inferior.h, and will
634 be 1 or 2 depending on whether we're starting without or with a
635 shell. */
636 startup_inferior (START_INFERIOR_TRAPS_EXPECTED);
637
638 /* On some targets, there must be some explicit actions taken after
639 the inferior has been started up. */
640 target_post_startup_inferior (pid_to_ptid (pid));
641}
642
643static void
136d6dae
VP
644inf_ttrace_create_inferior (struct target_ops *ops, char *exec_file,
645 char *allargs, char **env, int from_tty)
eee22bf8 646{
28439f5e
PA
647 int pid;
648
a7be7fa8
MK
649 gdb_assert (inf_ttrace_num_lwps == 0);
650 gdb_assert (inf_ttrace_num_lwps_in_syscall == 0);
932936f0 651 gdb_assert (inf_ttrace_page_dict.count == 0);
932936f0 652 gdb_assert (inf_ttrace_reenable_page_protections == 0);
b2a4db28 653 gdb_assert (inf_ttrace_vfork_ppid == -1);
932936f0 654
28439f5e 655 pid = fork_inferior (exec_file, allargs, env, inf_ttrace_me, NULL,
e69860f1 656 inf_ttrace_prepare, NULL, NULL);
28439f5e
PA
657
658 inf_ttrace_him (ops, pid);
eee22bf8
MK
659}
660
eee22bf8 661static void
136d6dae 662inf_ttrace_mourn_inferior (struct target_ops *ops)
eee22bf8 663{
932936f0
MK
664 const int num_buckets = ARRAY_SIZE (inf_ttrace_page_dict.buckets);
665 int bucket;
666
a7be7fa8
MK
667 inf_ttrace_num_lwps = 0;
668 inf_ttrace_num_lwps_in_syscall = 0;
932936f0
MK
669
670 for (bucket = 0; bucket < num_buckets; bucket++)
671 {
672 struct inf_ttrace_page *page;
673 struct inf_ttrace_page *next;
674
675 page = inf_ttrace_page_dict.buckets[bucket].next;
676 while (page)
677 {
678 next = page->next;
679 xfree (page);
680 page = next;
681 }
682 }
683 inf_ttrace_page_dict.count = 0;
684
28439f5e 685 unpush_target (ops);
eee22bf8
MK
686 generic_mourn_inferior ();
687}
688
f688d93f
JB
689/* Assuming we just attached the debugger to a new inferior, create
690 a new thread_info structure for each thread, and add it to our
691 list of threads. */
692
693static void
694inf_ttrace_create_threads_after_attach (int pid)
695{
696 int status;
697 ptid_t ptid;
698 ttstate_t tts;
699 struct thread_info *ti;
700
701 status = ttrace (TT_PROC_GET_FIRST_LWP_STATE, pid, 0,
702 (uintptr_t) &tts, sizeof (ttstate_t), 0);
703 if (status < 0)
704 perror_with_name (_("TT_PROC_GET_FIRST_LWP_STATE ttrace call failed"));
705 gdb_assert (tts.tts_pid == pid);
706
707 /* Add the stopped thread. */
708 ptid = ptid_build (pid, tts.tts_lwpid, 0);
709 ti = add_thread (ptid);
710 ti->private = xzalloc (sizeof (struct inf_ttrace_private_thread_info));
711 inf_ttrace_num_lwps++;
712
713 /* We use the "first stopped thread" as the currently active thread. */
714 inferior_ptid = ptid;
715
716 /* Iterative over all the remaining threads. */
717
718 for (;;)
719 {
720 ptid_t ptid;
721
722 status = ttrace (TT_PROC_GET_NEXT_LWP_STATE, pid, 0,
723 (uintptr_t) &tts, sizeof (ttstate_t), 0);
724 if (status < 0)
725 perror_with_name (_("TT_PROC_GET_NEXT_LWP_STATE ttrace call failed"));
726 if (status == 0)
727 break; /* End of list. */
728
729 ptid = ptid_build (tts.tts_pid, tts.tts_lwpid, 0);
730 ti = add_thread (ptid);
731 ti->private = xzalloc (sizeof (struct inf_ttrace_private_thread_info));
732 inf_ttrace_num_lwps++;
733 }
734}
735
eee22bf8 736static void
136d6dae 737inf_ttrace_attach (struct target_ops *ops, char *args, int from_tty)
eee22bf8
MK
738{
739 char *exec_file;
740 pid_t pid;
932936f0 741 ttevent_t tte;
181e7f93 742 struct inferior *inf;
eee22bf8 743
74164c56 744 pid = parse_pid_to_attach (args);
eee22bf8
MK
745
746 if (pid == getpid ()) /* Trying to masturbate? */
8a3fe4f8 747 error (_("I refuse to debug myself!"));
eee22bf8
MK
748
749 if (from_tty)
750 {
346e281c 751 exec_file = get_exec_file (0);
eee22bf8
MK
752
753 if (exec_file)
a3f17187 754 printf_unfiltered (_("Attaching to program: %s, %s\n"), exec_file,
eee22bf8
MK
755 target_pid_to_str (pid_to_ptid (pid)));
756 else
a3f17187 757 printf_unfiltered (_("Attaching to %s\n"),
eee22bf8
MK
758 target_pid_to_str (pid_to_ptid (pid)));
759
760 gdb_flush (gdb_stdout);
761 }
762
a7be7fa8
MK
763 gdb_assert (inf_ttrace_num_lwps == 0);
764 gdb_assert (inf_ttrace_num_lwps_in_syscall == 0);
b2a4db28 765 gdb_assert (inf_ttrace_vfork_ppid == -1);
a7be7fa8 766
eee22bf8 767 if (ttrace (TT_PROC_ATTACH, pid, 0, TT_KILL_ON_EXIT, TT_VERSION, 0) == -1)
e2e0b3e5 768 perror_with_name (("ttrace"));
eee22bf8 769
6c95b8df
PA
770 inf = current_inferior ();
771 inferior_appeared (inf, pid);
181e7f93 772 inf->attach_flag = 1;
7f9f62ba 773
932936f0 774 /* Set the initial event mask. */
932936f0 775 memset (&tte, 0, sizeof (tte));
b2a4db28 776 tte.tte_events |= TTEVT_EXEC | TTEVT_EXIT | TTEVT_FORK | TTEVT_VFORK;
a7be7fa8 777 tte.tte_events |= TTEVT_LWP_CREATE | TTEVT_LWP_EXIT | TTEVT_LWP_TERMINATE;
7ba0e0c2
MK
778#ifdef TTEVT_BPT_SSTEP
779 tte.tte_events |= TTEVT_BPT_SSTEP;
780#endif
b2a4db28 781 tte.tte_opts |= TTEO_PROC_INHERIT;
932936f0
MK
782 if (ttrace (TT_PROC_SET_EVENT_MASK, pid, 0,
783 (uintptr_t)&tte, sizeof tte, 0) == -1)
e2e0b3e5 784 perror_with_name (("ttrace"));
932936f0 785
28439f5e 786 push_target (ops);
2935f27f 787
f688d93f 788 inf_ttrace_create_threads_after_attach (pid);
eee22bf8
MK
789}
790
791static void
136d6dae 792inf_ttrace_detach (struct target_ops *ops, char *args, int from_tty)
eee22bf8 793{
eee22bf8 794 pid_t pid = ptid_get_pid (inferior_ptid);
5d426ff1 795 int sig = 0;
eee22bf8
MK
796
797 if (from_tty)
798 {
799 char *exec_file = get_exec_file (0);
800 if (exec_file == 0)
801 exec_file = "";
a3f17187 802 printf_unfiltered (_("Detaching from program: %s, %s\n"), exec_file,
eee22bf8
MK
803 target_pid_to_str (pid_to_ptid (pid)));
804 gdb_flush (gdb_stdout);
805 }
806 if (args)
807 sig = atoi (args);
808
809 /* ??? The HP-UX 11.0 ttrace(2) manual page doesn't mention that we
810 can pass a signal number here. Does this really work? */
811 if (ttrace (TT_PROC_DETACH, pid, 0, 0, sig, 0) == -1)
e2e0b3e5 812 perror_with_name (("ttrace"));
eee22bf8 813
b2a4db28
MK
814 if (inf_ttrace_vfork_ppid != -1)
815 {
816 if (ttrace (TT_PROC_DETACH, inf_ttrace_vfork_ppid, 0, 0, 0, 0) == -1)
817 perror_with_name (("ttrace"));
818 inf_ttrace_vfork_ppid = -1;
819 }
820
a7be7fa8
MK
821 inf_ttrace_num_lwps = 0;
822 inf_ttrace_num_lwps_in_syscall = 0;
932936f0 823
932936f0 824 inferior_ptid = null_ptid;
7f9f62ba
PA
825 detach_inferior (pid);
826
28439f5e 827 unpush_target (ops);
eee22bf8
MK
828}
829
346e281c 830static void
7d85a9c0 831inf_ttrace_kill (struct target_ops *ops)
346e281c
MK
832{
833 pid_t pid = ptid_get_pid (inferior_ptid);
834
835 if (pid == 0)
836 return;
837
838 if (ttrace (TT_PROC_EXIT, pid, 0, 0, 0, 0) == -1)
839 perror_with_name (("ttrace"));
840 /* ??? Is it necessary to call ttrace_wait() here? */
841
842 if (inf_ttrace_vfork_ppid != -1)
843 {
844 if (ttrace (TT_PROC_DETACH, inf_ttrace_vfork_ppid, 0, 0, 0, 0) == -1)
845 perror_with_name (("ttrace"));
846 inf_ttrace_vfork_ppid = -1;
847 }
848
849 target_mourn_inferior ();
850}
851
438ac09b
PA
852/* Check is a dying thread is dead by now, and delete it from GDBs
853 thread list if so. */
7ba0e0c2 854static int
438ac09b 855inf_ttrace_delete_dead_threads_callback (struct thread_info *info, void *arg)
7ba0e0c2 856{
438ac09b
PA
857 lwpid_t lwpid;
858 struct inf_ttrace_private_thread_info *p;
7ba0e0c2 859
438ac09b
PA
860 if (is_exited (info->ptid))
861 return 0;
862
863 lwpid = ptid_get_lwp (info->ptid);
864 p = (struct inf_ttrace_private_thread_info *) info->private;
865
866 /* Check if an lwp that was dying is still there or not. */
867 if (p->dying && (kill (lwpid, 0) == -1))
868 /* It's gone now. */
869 delete_thread (info->ptid);
7ba0e0c2
MK
870
871 return 0;
872}
873
438ac09b
PA
874/* Resume the lwp pointed to by INFO, with REQUEST, and pass it signal
875 SIG. */
876
877static void
878inf_ttrace_resume_lwp (struct thread_info *info, ttreq_t request, int sig)
879{
880 pid_t pid = ptid_get_pid (info->ptid);
881 lwpid_t lwpid = ptid_get_lwp (info->ptid);
882
883 if (ttrace (request, pid, lwpid, TT_NOPC, sig, 0) == -1)
884 {
885 struct inf_ttrace_private_thread_info *p
886 = (struct inf_ttrace_private_thread_info *) info->private;
887 if (p->dying && errno == EPROTO)
888 /* This is expected, it means the dying lwp is really gone
889 by now. If ttrace had an event to inform the debugger
890 the lwp is really gone, this wouldn't be needed. */
891 delete_thread (info->ptid);
892 else
893 /* This was really unexpected. */
894 perror_with_name (("ttrace"));
895 }
896}
897
898/* Callback for iterate_over_threads. */
899
60e2c248 900static int
438ac09b 901inf_ttrace_resume_callback (struct thread_info *info, void *arg)
60e2c248 902{
438ac09b
PA
903 if (!ptid_equal (info->ptid, inferior_ptid) && !is_exited (info->ptid))
904 inf_ttrace_resume_lwp (info, TT_LWP_CONTINUE, 0);
905
60e2c248
JG
906 return 0;
907}
908
eee22bf8 909static void
28439f5e 910inf_ttrace_resume (struct target_ops *ops,
2ea28649 911 ptid_t ptid, int step, enum gdb_signal signal)
eee22bf8 912{
438ac09b 913 int resume_all;
eee22bf8 914 ttreq_t request = step ? TT_LWP_SINGLE : TT_LWP_CONTINUE;
2ea28649 915 int sig = gdb_signal_to_host (signal);
438ac09b 916 struct thread_info *info;
eee22bf8 917
438ac09b
PA
918 /* A specific PTID means `step only this process id'. */
919 resume_all = (ptid_equal (ptid, minus_one_ptid));
eee22bf8 920
438ac09b
PA
921 /* If resuming all threads, it's the current thread that should be
922 handled specially. */
923 if (resume_all)
924 ptid = inferior_ptid;
eee22bf8 925
e09875d4 926 info = find_thread_ptid (ptid);
438ac09b
PA
927 inf_ttrace_resume_lwp (info, request, sig);
928
929 if (resume_all)
930 /* Let all the other threads run too. */
931 iterate_over_threads (inf_ttrace_resume_callback, NULL);
eee22bf8
MK
932}
933
934static ptid_t
117de6a9 935inf_ttrace_wait (struct target_ops *ops,
47608cb1 936 ptid_t ptid, struct target_waitstatus *ourstatus, int options)
eee22bf8
MK
937{
938 pid_t pid = ptid_get_pid (ptid);
939 lwpid_t lwpid = ptid_get_lwp (ptid);
940 ttstate_t tts;
60e2c248 941 struct thread_info *ti;
3a3e9ee3 942 ptid_t related_ptid;
eee22bf8 943
932936f0 944 /* Until proven otherwise. */
a7be7fa8 945 ourstatus->kind = TARGET_WAITKIND_SPURIOUS;
eee22bf8
MK
946
947 if (pid == -1)
b2a4db28 948 pid = lwpid = 0;
eee22bf8 949
b2a4db28 950 gdb_assert (pid != 0 || lwpid == 0);
eee22bf8
MK
951
952 do
953 {
954 set_sigint_trap ();
eee22bf8
MK
955
956 if (ttrace_wait (pid, lwpid, TTRACE_WAITOK, &tts, sizeof tts) == -1)
a3f17187 957 perror_with_name (("ttrace_wait"));
eee22bf8 958
b2a4db28
MK
959 if (tts.tts_event == TTEVT_VFORK && tts.tts_u.tts_fork.tts_isparent)
960 {
961 if (inf_ttrace_vfork_ppid != -1)
962 {
963 gdb_assert (inf_ttrace_vfork_ppid == tts.tts_pid);
964
965 if (ttrace (TT_PROC_DETACH, tts.tts_pid, 0, 0, 0, 0) == -1)
966 perror_with_name (("ttrace"));
967 inf_ttrace_vfork_ppid = -1;
968 }
969
970 tts.tts_event = TTEVT_NONE;
971 }
972
eee22bf8
MK
973 clear_sigint_trap ();
974 }
975 while (tts.tts_event == TTEVT_NONE);
976
932936f0
MK
977 /* Now that we've waited, we can re-enable the page protections. */
978 if (inf_ttrace_reenable_page_protections)
979 {
a7be7fa8 980 gdb_assert (inf_ttrace_num_lwps_in_syscall == 0);
932936f0
MK
981 inf_ttrace_enable_page_protections (tts.tts_pid);
982 inf_ttrace_reenable_page_protections = 0;
983 }
984
a7be7fa8
MK
985 ptid = ptid_build (tts.tts_pid, tts.tts_lwpid, 0);
986
2935f27f
PA
987 if (inf_ttrace_num_lwps == 0)
988 {
989 struct thread_info *ti;
990
991 inf_ttrace_num_lwps = 1;
992
993 /* This is the earliest we hear about the lwp member of
994 INFERIOR_PTID, after an attach or fork_inferior. */
995 gdb_assert (ptid_get_lwp (inferior_ptid) == 0);
996
997 /* We haven't set the private member on the main thread yet. Do
998 it now. */
e09875d4 999 ti = find_thread_ptid (inferior_ptid);
2935f27f
PA
1000 gdb_assert (ti != NULL && ti->private == NULL);
1001 ti->private =
1002 xmalloc (sizeof (struct inf_ttrace_private_thread_info));
1003 memset (ti->private, 0,
1004 sizeof (struct inf_ttrace_private_thread_info));
1005
1006 /* Notify the core that this ptid changed. This changes
1007 inferior_ptid as well. */
1008 thread_change_ptid (inferior_ptid, ptid);
1009 }
1010
eee22bf8
MK
1011 switch (tts.tts_event)
1012 {
7ba0e0c2
MK
1013#ifdef TTEVT_BPT_SSTEP
1014 case TTEVT_BPT_SSTEP:
1015 /* Make it look like a breakpoint. */
1016 ourstatus->kind = TARGET_WAITKIND_STOPPED;
a493e3e2 1017 ourstatus->value.sig = GDB_SIGNAL_TRAP;
7ba0e0c2
MK
1018 break;
1019#endif
1020
eee22bf8 1021 case TTEVT_EXEC:
5d426ff1
MK
1022 ourstatus->kind = TARGET_WAITKIND_EXECD;
1023 ourstatus->value.execd_pathname =
1024 xmalloc (tts.tts_u.tts_exec.tts_pathlen + 1);
1025 if (ttrace (TT_PROC_GET_PATHNAME, tts.tts_pid, 0,
1026 (uintptr_t)ourstatus->value.execd_pathname,
1027 tts.tts_u.tts_exec.tts_pathlen, 0) == -1)
1028 perror_with_name (("ttrace"));
1029 ourstatus->value.execd_pathname[tts.tts_u.tts_exec.tts_pathlen] = 0;
25b22b0a
PA
1030
1031 /* At this point, all inserted breakpoints are gone. Doing this
1032 as soon as we detect an exec prevents the badness of deleting
1033 a breakpoint writing the current "shadow contents" to lift
1034 the bp. That shadow is NOT valid after an exec. */
1035 mark_breakpoints_out ();
eee22bf8 1036 break;
932936f0 1037
eee22bf8
MK
1038 case TTEVT_EXIT:
1039 store_waitstatus (ourstatus, tts.tts_u.tts_exit.tts_exitcode);
a7be7fa8
MK
1040 inf_ttrace_num_lwps = 0;
1041 break;
1042
b2a4db28 1043 case TTEVT_FORK:
3a3e9ee3
PA
1044 related_ptid = ptid_build (tts.tts_u.tts_fork.tts_fpid,
1045 tts.tts_u.tts_fork.tts_flwpid, 0);
1046
b2a4db28 1047 ourstatus->kind = TARGET_WAITKIND_FORKED;
3a3e9ee3 1048 ourstatus->value.related_pid = related_ptid;
b2a4db28
MK
1049
1050 /* Make sure the other end of the fork is stopped too. */
1051 if (ttrace_wait (tts.tts_u.tts_fork.tts_fpid,
1052 tts.tts_u.tts_fork.tts_flwpid,
1053 TTRACE_WAITOK, &tts, sizeof tts) == -1)
1054 perror_with_name (("ttrace_wait"));
1055
1056 gdb_assert (tts.tts_event == TTEVT_FORK);
1057 if (tts.tts_u.tts_fork.tts_isparent)
1058 {
3a3e9ee3
PA
1059 related_ptid = ptid_build (tts.tts_u.tts_fork.tts_fpid,
1060 tts.tts_u.tts_fork.tts_flwpid, 0);
b2a4db28 1061 ptid = ptid_build (tts.tts_pid, tts.tts_lwpid, 0);
3a3e9ee3 1062 ourstatus->value.related_pid = related_ptid;
b2a4db28
MK
1063 }
1064 break;
1065
1066 case TTEVT_VFORK:
1067 gdb_assert (!tts.tts_u.tts_fork.tts_isparent);
1068
3a3e9ee3
PA
1069 related_ptid = ptid_build (tts.tts_u.tts_fork.tts_fpid,
1070 tts.tts_u.tts_fork.tts_flwpid, 0);
1071
b2a4db28 1072 ourstatus->kind = TARGET_WAITKIND_VFORKED;
3a3e9ee3 1073 ourstatus->value.related_pid = related_ptid;
b2a4db28
MK
1074
1075 /* HACK: To avoid touching the parent during the vfork, switch
1076 away from it. */
1077 inferior_ptid = ptid;
1078 break;
1079
a7be7fa8
MK
1080 case TTEVT_LWP_CREATE:
1081 lwpid = tts.tts_u.tts_thread.tts_target_lwpid;
1082 ptid = ptid_build (tts.tts_pid, lwpid, 0);
60e2c248
JG
1083 ti = add_thread (ptid);
1084 ti->private =
1085 xmalloc (sizeof (struct inf_ttrace_private_thread_info));
1086 memset (ti->private, 0,
1087 sizeof (struct inf_ttrace_private_thread_info));
a7be7fa8
MK
1088 inf_ttrace_num_lwps++;
1089 ptid = ptid_build (tts.tts_pid, tts.tts_lwpid, 0);
62a93fa9
PA
1090 /* Let the lwp_create-caller thread continue. */
1091 ttrace (TT_LWP_CONTINUE, ptid_get_pid (ptid),
1092 ptid_get_lwp (ptid), TT_NOPC, 0, 0);
1093 /* Return without stopping the whole process. */
1094 ourstatus->kind = TARGET_WAITKIND_IGNORE;
1095 return ptid;
a7be7fa8
MK
1096
1097 case TTEVT_LWP_EXIT:
17faa917
DJ
1098 if (print_thread_events)
1099 printf_unfiltered (_("[%s exited]\n"), target_pid_to_str (ptid));
e09875d4 1100 ti = find_thread_ptid (ptid);
60e2c248
JG
1101 gdb_assert (ti != NULL);
1102 ((struct inf_ttrace_private_thread_info *)ti->private)->dying = 1;
a7be7fa8 1103 inf_ttrace_num_lwps--;
62a93fa9 1104 /* Let the thread really exit. */
60e2c248
JG
1105 ttrace (TT_LWP_CONTINUE, ptid_get_pid (ptid),
1106 ptid_get_lwp (ptid), TT_NOPC, 0, 0);
62a93fa9
PA
1107 /* Return without stopping the whole process. */
1108 ourstatus->kind = TARGET_WAITKIND_IGNORE;
1109 return ptid;
a7be7fa8
MK
1110
1111 case TTEVT_LWP_TERMINATE:
1112 lwpid = tts.tts_u.tts_thread.tts_target_lwpid;
1113 ptid = ptid_build (tts.tts_pid, lwpid, 0);
62a93fa9 1114 if (print_thread_events)
b861ac81 1115 printf_unfiltered(_("[%s has been terminated]\n"),
62a93fa9 1116 target_pid_to_str (ptid));
e09875d4 1117 ti = find_thread_ptid (ptid);
60e2c248
JG
1118 gdb_assert (ti != NULL);
1119 ((struct inf_ttrace_private_thread_info *)ti->private)->dying = 1;
a7be7fa8 1120 inf_ttrace_num_lwps--;
62a93fa9
PA
1121
1122 /* Resume the lwp_terminate-caller thread. */
a7be7fa8 1123 ptid = ptid_build (tts.tts_pid, tts.tts_lwpid, 0);
62a93fa9
PA
1124 ttrace (TT_LWP_CONTINUE, ptid_get_pid (ptid),
1125 ptid_get_lwp (ptid), TT_NOPC, 0, 0);
1126 /* Return without stopping the whole process. */
1127 ourstatus->kind = TARGET_WAITKIND_IGNORE;
1128 return ptid;
932936f0 1129
eee22bf8
MK
1130 case TTEVT_SIGNAL:
1131 ourstatus->kind = TARGET_WAITKIND_STOPPED;
1132 ourstatus->value.sig =
2ea28649 1133 gdb_signal_from_host (tts.tts_u.tts_signal.tts_signo);
eee22bf8 1134 break;
932936f0
MK
1135
1136 case TTEVT_SYSCALL_ENTRY:
1137 gdb_assert (inf_ttrace_reenable_page_protections == 0);
a7be7fa8
MK
1138 inf_ttrace_num_lwps_in_syscall++;
1139 if (inf_ttrace_num_lwps_in_syscall == 1)
932936f0
MK
1140 {
1141 /* A thread has just entered a system call. Disable any
1142 page protections as the kernel can't deal with them. */
1143 inf_ttrace_disable_page_protections (tts.tts_pid);
1144 }
1145 ourstatus->kind = TARGET_WAITKIND_SYSCALL_ENTRY;
01dedca2 1146 ourstatus->value.syscall_number = tts.tts_scno;
932936f0
MK
1147 break;
1148
1149 case TTEVT_SYSCALL_RETURN:
a7be7fa8 1150 if (inf_ttrace_num_lwps_in_syscall > 0)
932936f0
MK
1151 {
1152 /* If the last thread has just left the system call, this
1153 would be a logical place to re-enable the page
1154 protections, but that doesn't work. We can't re-enable
1155 them until we've done another wait. */
1156 inf_ttrace_reenable_page_protections =
a7be7fa8
MK
1157 (inf_ttrace_num_lwps_in_syscall == 1);
1158 inf_ttrace_num_lwps_in_syscall--;
932936f0
MK
1159 }
1160 ourstatus->kind = TARGET_WAITKIND_SYSCALL_RETURN;
01dedca2 1161 ourstatus->value.syscall_number = tts.tts_scno;
932936f0 1162 break;
a7be7fa8
MK
1163
1164 default:
1165 gdb_assert (!"Unexpected ttrace event");
1166 break;
eee22bf8
MK
1167 }
1168
1169 /* Make sure all threads within the process are stopped. */
1170 if (ttrace (TT_PROC_STOP, tts.tts_pid, 0, 0, 0, 0) == -1)
e2e0b3e5 1171 perror_with_name (("ttrace"));
eee22bf8 1172
438ac09b
PA
1173 /* Now that the whole process is stopped, check if any dying thread
1174 is really dead by now. If a dying thread is still alive, it will
1175 be stopped too, and will still show up in `info threads', tagged
1176 with "(Exiting)". We could make `info threads' prune dead
1177 threads instead via inf_ttrace_thread_alive, but doing this here
1178 has the advantage that a frontend is notificed sooner of thread
1179 exits. Note that a dying lwp is still alive, it still has to be
1180 resumed, like any other lwp. */
1181 iterate_over_threads (inf_ttrace_delete_dead_threads_callback, NULL);
1182
a7be7fa8 1183 return ptid;
eee22bf8
MK
1184}
1185
1186/* Transfer LEN bytes from ADDR in the inferior's memory into READBUF,
1187 and transfer LEN bytes from WRITEBUF into the inferior's memory at
1188 ADDR. Either READBUF or WRITEBUF may be null, in which case the
1189 corresponding transfer doesn't happen. Return the number of bytes
1190 actually transferred (which may be zero if an error occurs). */
1191
1192static LONGEST
1193inf_ttrace_xfer_memory (CORE_ADDR addr, ULONGEST len,
1194 void *readbuf, const void *writebuf)
1195{
1196 pid_t pid = ptid_get_pid (inferior_ptid);
1197
1198 /* HP-UX treats text space and data space differently. GDB however,
1199 doesn't really know the difference. Therefore we try both. Try
1200 text space before data space though because when we're writing
1201 into text space the instruction cache might need to be flushed. */
1202
1203 if (readbuf
1204 && ttrace (TT_PROC_RDTEXT, pid, 0, addr, len, (uintptr_t)readbuf) == -1
1205 && ttrace (TT_PROC_RDDATA, pid, 0, addr, len, (uintptr_t)readbuf) == -1)
1206 return 0;
1207
1208 if (writebuf
1209 && ttrace (TT_PROC_WRTEXT, pid, 0, addr, len, (uintptr_t)writebuf) == -1
1210 && ttrace (TT_PROC_WRDATA, pid, 0, addr, len, (uintptr_t)writebuf) == -1)
1211 return 0;
1212
1213 return len;
1214}
1215
1216static LONGEST
1217inf_ttrace_xfer_partial (struct target_ops *ops, enum target_object object,
7a4609f7 1218 const char *annex, gdb_byte *readbuf,
3e43a32a
MS
1219 const gdb_byte *writebuf,
1220 ULONGEST offset, LONGEST len)
eee22bf8
MK
1221{
1222 switch (object)
1223 {
1224 case TARGET_OBJECT_MEMORY:
1225 return inf_ttrace_xfer_memory (offset, len, readbuf, writebuf);
1226
1227 case TARGET_OBJECT_UNWIND_TABLE:
1228 return -1;
1229
1230 case TARGET_OBJECT_AUXV:
1231 return -1;
1232
1233 case TARGET_OBJECT_WCOOKIE:
1234 return -1;
1235
1236 default:
1237 return -1;
1238 }
1239}
1240
1241/* Print status information about what we're accessing. */
1242
1243static void
1244inf_ttrace_files_info (struct target_ops *ignore)
1245{
181e7f93 1246 struct inferior *inf = current_inferior ();
346e281c 1247 printf_filtered (_("\tUsing the running image of %s %s.\n"),
181e7f93 1248 inf->attach_flag ? "attached" : "child",
346e281c 1249 target_pid_to_str (inferior_ptid));
eee22bf8 1250}
a7be7fa8
MK
1251
1252static int
28439f5e 1253inf_ttrace_thread_alive (struct target_ops *ops, ptid_t ptid)
a7be7fa8 1254{
438ac09b
PA
1255 return 1;
1256}
1257
1258/* Return a string describing the state of the thread specified by
1259 INFO. */
1260
1261static char *
1262inf_ttrace_extra_thread_info (struct thread_info *info)
1263{
1264 struct inf_ttrace_private_thread_info* private =
1265 (struct inf_ttrace_private_thread_info *) info->private;
1266
1267 if (private != NULL && private->dying)
1268 return "Exiting";
1269
1270 return NULL;
a7be7fa8
MK
1271}
1272
1273static char *
117de6a9 1274inf_ttrace_pid_to_str (struct target_ops *ops, ptid_t ptid)
a7be7fa8 1275{
2935f27f
PA
1276 pid_t pid = ptid_get_pid (ptid);
1277 lwpid_t lwpid = ptid_get_lwp (ptid);
1278 static char buf[128];
a7be7fa8 1279
2935f27f
PA
1280 if (lwpid == 0)
1281 xsnprintf (buf, sizeof buf, "process %ld",
1282 (long) pid);
1283 else
1284 xsnprintf (buf, sizeof buf, "process %ld, lwp %ld",
1285 (long) pid, (long) lwpid);
1286 return buf;
a7be7fa8 1287}
eee22bf8
MK
1288\f
1289
fa07e785
JB
1290/* Implement the get_ada_task_ptid target_ops method. */
1291
1292static ptid_t
1293inf_ttrace_get_ada_task_ptid (long lwp, long thread)
1294{
1295 return ptid_build (ptid_get_pid (inferior_ptid), lwp, 0);
1296}
1297
1298\f
eee22bf8
MK
1299struct target_ops *
1300inf_ttrace_target (void)
1301{
1302 struct target_ops *t = inf_child_target ();
1303
eee22bf8
MK
1304 t->to_attach = inf_ttrace_attach;
1305 t->to_detach = inf_ttrace_detach;
1306 t->to_resume = inf_ttrace_resume;
1307 t->to_wait = inf_ttrace_wait;
eee22bf8 1308 t->to_files_info = inf_ttrace_files_info;
932936f0 1309 t->to_can_use_hw_breakpoint = inf_ttrace_can_use_hw_breakpoint;
932936f0
MK
1310 t->to_insert_watchpoint = inf_ttrace_insert_watchpoint;
1311 t->to_remove_watchpoint = inf_ttrace_remove_watchpoint;
1312 t->to_stopped_by_watchpoint = inf_ttrace_stopped_by_watchpoint;
2a3cdf79
WZ
1313 t->to_region_ok_for_hw_watchpoint =
1314 inf_ttrace_region_ok_for_hw_watchpoint;
346e281c
MK
1315 t->to_kill = inf_ttrace_kill;
1316 t->to_create_inferior = inf_ttrace_create_inferior;
1317 t->to_follow_fork = inf_ttrace_follow_fork;
1318 t->to_mourn_inferior = inf_ttrace_mourn_inferior;
1319 t->to_thread_alive = inf_ttrace_thread_alive;
438ac09b 1320 t->to_extra_thread_info = inf_ttrace_extra_thread_info;
346e281c
MK
1321 t->to_pid_to_str = inf_ttrace_pid_to_str;
1322 t->to_xfer_partial = inf_ttrace_xfer_partial;
fa07e785 1323 t->to_get_ada_task_ptid = inf_ttrace_get_ada_task_ptid;
eee22bf8 1324
eee22bf8
MK
1325 return t;
1326}
d3322e8a 1327#endif
932936f0
MK
1328\f
1329
1330/* Prevent warning from -Wmissing-prototypes. */
0b155465 1331void _initialize_inf_ttrace (void);
eee22bf8 1332
932936f0
MK
1333void
1334_initialize_inf_ttrace (void)
1335{
d3322e8a 1336#ifdef HAVE_TTRACE
932936f0 1337 inf_ttrace_page_dict.pagesize = getpagesize();
eee22bf8 1338#endif
d3322e8a 1339}
This page took 0.753361 seconds and 4 git commands to generate.