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