]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blame - gdb/inf-ttrace.c
Update year range in copyright notice of all files owned by the GDB project.
[thirdparty/binutils-gdb.git] / gdb / inf-ttrace.c
CommitLineData
eee22bf8
MK
1/* Low-level child interface to ttrace.
2
32d0add0 3 Copyright (C) 2004-2015 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 31#include "target.h"
932936f0 32#include <sys/mman.h>
eee22bf8 33#include <sys/ttrace.h>
438ac09b 34#include <signal.h>
eee22bf8
MK
35
36#include "inf-child.h"
37#include "inf-ttrace.h"
21ff4686 38#include "common/filestuff.h"
eee22bf8 39
932936f0
MK
40\f
41
a7be7fa8
MK
42/* HP-UX uses a threading model where each user-space thread
43 corresponds to a kernel thread. These kernel threads are called
44 lwps. The ttrace(2) interface gives us almost full control over
45 the threads, which makes it very easy to support them in GDB. We
46 identify the threads by process ID and lwp ID. The ttrace(2) also
47 provides us with a thread's user ID (in the `tts_user_tid' member
48 of `ttstate_t') but we don't use that (yet) as it isn't necessary
49 to uniquely label the thread. */
50
51/* Number of active lwps. */
52static int inf_ttrace_num_lwps;
53\f
54
932936f0
MK
55/* On HP-UX versions that have the ttrace(2) system call, we can
56 implement "hardware" watchpoints by fiddling with the protection of
57 pages in the address space that contain the variable being watched.
58 In order to implement this, we keep a dictionary of pages for which
59 we have changed the protection. */
60
61struct inf_ttrace_page
62{
63 CORE_ADDR addr; /* Page address. */
64 int prot; /* Protection. */
65 int refcount; /* Reference count. */
66 struct inf_ttrace_page *next;
67 struct inf_ttrace_page *prev;
68};
69
70struct inf_ttrace_page_dict
71{
72 struct inf_ttrace_page buckets[128];
73 int pagesize; /* Page size. */
74 int count; /* Number of pages in this dictionary. */
75} inf_ttrace_page_dict;
76
60e2c248
JG
77struct inf_ttrace_private_thread_info
78{
79 int dying;
80};
81
a7be7fa8
MK
82/* Number of lwps that are currently in a system call. */
83static int inf_ttrace_num_lwps_in_syscall;
932936f0
MK
84
85/* Flag to indicate whether we should re-enable page protections after
86 the next wait. */
87static int inf_ttrace_reenable_page_protections;
88
89/* Enable system call events for process PID. */
90
91static void
92inf_ttrace_enable_syscall_events (pid_t pid)
93{
94 ttevent_t tte;
95 ttstate_t tts;
96
a7be7fa8 97 gdb_assert (inf_ttrace_num_lwps_in_syscall == 0);
932936f0
MK
98
99 if (ttrace (TT_PROC_GET_EVENT_MASK, pid, 0,
100 (uintptr_t)&tte, sizeof tte, 0) == -1)
e2e0b3e5 101 perror_with_name (("ttrace"));
932936f0
MK
102
103 tte.tte_events |= (TTEVT_SYSCALL_ENTRY | TTEVT_SYSCALL_RETURN);
104
105 if (ttrace (TT_PROC_SET_EVENT_MASK, pid, 0,
106 (uintptr_t)&tte, sizeof tte, 0) == -1)
e2e0b3e5 107 perror_with_name (("ttrace"));
932936f0
MK
108
109 if (ttrace (TT_PROC_GET_FIRST_LWP_STATE, pid, 0,
110 (uintptr_t)&tts, sizeof tts, 0) == -1)
e2e0b3e5 111 perror_with_name (("ttrace"));
932936f0
MK
112
113 if (tts.tts_flags & TTS_INSYSCALL)
a7be7fa8 114 inf_ttrace_num_lwps_in_syscall++;
932936f0
MK
115
116 /* FIXME: Handle multiple threads. */
117}
118
119/* Disable system call events for process PID. */
120
121static void
122inf_ttrace_disable_syscall_events (pid_t pid)
123{
124 ttevent_t tte;
125
126 gdb_assert (inf_ttrace_page_dict.count == 0);
127
128 if (ttrace (TT_PROC_GET_EVENT_MASK, pid, 0,
129 (uintptr_t)&tte, sizeof tte, 0) == -1)
e2e0b3e5 130 perror_with_name (("ttrace"));
932936f0
MK
131
132 tte.tte_events &= ~(TTEVT_SYSCALL_ENTRY | TTEVT_SYSCALL_RETURN);
133
134 if (ttrace (TT_PROC_SET_EVENT_MASK, pid, 0,
135 (uintptr_t)&tte, sizeof tte, 0) == -1)
e2e0b3e5 136 perror_with_name (("ttrace"));
932936f0 137
a7be7fa8 138 inf_ttrace_num_lwps_in_syscall = 0;
932936f0
MK
139}
140
141/* Get information about the page at address ADDR for process PID from
142 the dictionary. */
143
144static struct inf_ttrace_page *
145inf_ttrace_get_page (pid_t pid, CORE_ADDR addr)
146{
147 const int num_buckets = ARRAY_SIZE (inf_ttrace_page_dict.buckets);
148 const int pagesize = inf_ttrace_page_dict.pagesize;
149 int bucket;
150 struct inf_ttrace_page *page;
151
152 bucket = (addr / pagesize) % num_buckets;
153 page = &inf_ttrace_page_dict.buckets[bucket];
154 while (page)
155 {
156 if (page->addr == addr)
157 break;
158
159 page = page->next;
160 }
161
162 return page;
163}
164
165/* Add the page at address ADDR for process PID to the dictionary. */
166
167static struct inf_ttrace_page *
168inf_ttrace_add_page (pid_t pid, CORE_ADDR addr)
169{
170 const int num_buckets = ARRAY_SIZE (inf_ttrace_page_dict.buckets);
171 const int pagesize = inf_ttrace_page_dict.pagesize;
172 int bucket;
173 struct inf_ttrace_page *page;
174 struct inf_ttrace_page *prev = NULL;
175
176 bucket = (addr / pagesize) % num_buckets;
177 page = &inf_ttrace_page_dict.buckets[bucket];
178 while (page)
179 {
180 if (page->addr == addr)
181 break;
182
183 prev = page;
184 page = page->next;
185 }
186
187 if (!page)
188 {
189 int prot;
190
191 if (ttrace (TT_PROC_GET_MPROTECT, pid, 0,
192 addr, 0, (uintptr_t)&prot) == -1)
e2e0b3e5 193 perror_with_name (("ttrace"));
932936f0 194
70ba0933 195 page = XNEW (struct inf_ttrace_page);
932936f0
MK
196 page->addr = addr;
197 page->prot = prot;
198 page->refcount = 0;
199 page->next = NULL;
200
201 page->prev = prev;
202 prev->next = page;
203
204 inf_ttrace_page_dict.count++;
205 if (inf_ttrace_page_dict.count == 1)
206 inf_ttrace_enable_syscall_events (pid);
207
a7be7fa8 208 if (inf_ttrace_num_lwps_in_syscall == 0)
932936f0
MK
209 {
210 if (ttrace (TT_PROC_SET_MPROTECT, pid, 0,
211 addr, pagesize, prot & ~PROT_WRITE) == -1)
e2e0b3e5 212 perror_with_name (("ttrace"));
932936f0
MK
213 }
214 }
215
216 return page;
217}
218
219/* Insert the page at address ADDR of process PID to the dictionary. */
220
221static void
222inf_ttrace_insert_page (pid_t pid, CORE_ADDR addr)
223{
224 struct inf_ttrace_page *page;
225
226 page = inf_ttrace_get_page (pid, addr);
227 if (!page)
228 page = inf_ttrace_add_page (pid, addr);
229
230 page->refcount++;
231}
232
233/* Remove the page at address ADDR of process PID from the dictionary. */
234
235static void
236inf_ttrace_remove_page (pid_t pid, CORE_ADDR addr)
237{
238 const int pagesize = inf_ttrace_page_dict.pagesize;
239 struct inf_ttrace_page *page;
240
241 page = inf_ttrace_get_page (pid, addr);
242 page->refcount--;
243
244 gdb_assert (page->refcount >= 0);
245
246 if (page->refcount == 0)
247 {
a7be7fa8 248 if (inf_ttrace_num_lwps_in_syscall == 0)
932936f0
MK
249 {
250 if (ttrace (TT_PROC_SET_MPROTECT, pid, 0,
251 addr, pagesize, page->prot) == -1)
e2e0b3e5 252 perror_with_name (("ttrace"));
932936f0
MK
253 }
254
255 inf_ttrace_page_dict.count--;
256 if (inf_ttrace_page_dict.count == 0)
257 inf_ttrace_disable_syscall_events (pid);
258
259 page->prev->next = page->next;
260 if (page->next)
261 page->next->prev = page->prev;
262
263 xfree (page);
264 }
265}
266
267/* Mask the bits in PROT from the page protections that are currently
268 in the dictionary for process PID. */
269
270static void
271inf_ttrace_mask_page_protections (pid_t pid, int prot)
272{
273 const int num_buckets = ARRAY_SIZE (inf_ttrace_page_dict.buckets);
274 const int pagesize = inf_ttrace_page_dict.pagesize;
275 int bucket;
276
277 for (bucket = 0; bucket < num_buckets; bucket++)
278 {
279 struct inf_ttrace_page *page;
280
281 page = inf_ttrace_page_dict.buckets[bucket].next;
282 while (page)
283 {
284 if (ttrace (TT_PROC_SET_MPROTECT, pid, 0,
285 page->addr, pagesize, page->prot & ~prot) == -1)
e2e0b3e5 286 perror_with_name (("ttrace"));
932936f0
MK
287
288 page = page->next;
289 }
290 }
291}
292
293/* Write-protect the pages in the dictionary for process PID. */
294
295static void
296inf_ttrace_enable_page_protections (pid_t pid)
297{
298 inf_ttrace_mask_page_protections (pid, PROT_WRITE);
299}
300
301/* Restore the protection of the pages in the dictionary for process
302 PID. */
303
304static void
305inf_ttrace_disable_page_protections (pid_t pid)
306{
307 inf_ttrace_mask_page_protections (pid, 0);
308}
309
310/* Insert a "hardware" watchpoint for LEN bytes at address ADDR of
311 type TYPE. */
312
313static int
7bb99c53
TT
314inf_ttrace_insert_watchpoint (struct target_ops *self,
315 CORE_ADDR addr, int len, int type,
0cf6dd15 316 struct expression *cond)
932936f0
MK
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
11b5219a
TT
339inf_ttrace_remove_watchpoint (struct target_ops *self,
340 CORE_ADDR addr, int len, int type,
0cf6dd15 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
5461485a
TT
361inf_ttrace_can_use_hw_breakpoint (struct target_ops *self,
362 int type, int len, int ot)
932936f0
MK
363{
364 return (type == bp_hardware_watchpoint);
365}
366
367static int
31568a15
TT
368inf_ttrace_region_ok_for_hw_watchpoint (struct target_ops *self,
369 CORE_ADDR addr, int len)
932936f0
MK
370{
371 return 1;
372}
373
374/* Return non-zero if the current inferior was (potentially) stopped
375 by hitting a "hardware" watchpoint. */
376
377static int
6a109b6b 378inf_ttrace_stopped_by_watchpoint (struct target_ops *ops)
932936f0
MK
379{
380 pid_t pid = ptid_get_pid (inferior_ptid);
381 lwpid_t lwpid = ptid_get_lwp (inferior_ptid);
382 ttstate_t tts;
383
384 if (inf_ttrace_page_dict.count > 0)
385 {
386 if (ttrace (TT_LWP_GET_STATE, pid, lwpid,
387 (uintptr_t)&tts, sizeof tts, 0) == -1)
e2e0b3e5 388 perror_with_name (("ttrace"));
932936f0
MK
389
390 if (tts.tts_event == TTEVT_SIGNAL
391 && tts.tts_u.tts_signal.tts_signo == SIGBUS)
392 {
393 const int pagesize = inf_ttrace_page_dict.pagesize;
394 void *addr = tts.tts_u.tts_signal.tts_siginfo.si_addr;
395 CORE_ADDR page_addr = ((uintptr_t)addr / pagesize) * pagesize;
396
397 if (inf_ttrace_get_page (pid, page_addr))
398 return 1;
399 }
400 }
401
402 return 0;
403}
404\f
eee22bf8 405
d83ad864
DB
406/* Target hook for follow_fork. On entry and at return inferior_ptid
407 is the ptid of the followed inferior. */
b2a4db28
MK
408
409static int
07107ca6
LM
410inf_ttrace_follow_fork (struct target_ops *ops, int follow_child,
411 int detach_fork)
b2a4db28 412{
e58b0e63
PA
413 struct thread_info *tp = inferior_thread ();
414
415 gdb_assert (tp->pending_follow.kind == TARGET_WAITKIND_FORKED
416 || tp->pending_follow.kind == TARGET_WAITKIND_VFORKED);
417
b2a4db28
MK
418 if (follow_child)
419 {
2935f27f
PA
420 struct thread_info *ti;
421
b2a4db28 422 /* The child will start out single-threaded. */
2935f27f 423 inf_ttrace_num_lwps = 1;
b2a4db28
MK
424 inf_ttrace_num_lwps_in_syscall = 0;
425
d83ad864 426 ti = inferior_thread ();
2935f27f
PA
427 ti->private =
428 xmalloc (sizeof (struct inf_ttrace_private_thread_info));
429 memset (ti->private, 0,
430 sizeof (struct inf_ttrace_private_thread_info));
b2a4db28 431 }
d83ad864
DB
432 else
433 {
434 pid_t child_pid;
435
436 /* Following parent. Detach child now. */
437 child_pid = ptid_get_pid (tp->pending_follow.value.related_pid);
438 if (ttrace (TT_PROC_DETACH, child_pid, 0, 0, 0, 0) == -1)
439 perror_with_name (("ttrace"));
440 }
b2a4db28
MK
441
442 return 0;
443}
444\f
445
eee22bf8
MK
446/* File descriptors for pipes used as semaphores during initial
447 startup of an inferior. */
448static int inf_ttrace_pfd1[2];
449static int inf_ttrace_pfd2[2];
450
451static void
452do_cleanup_pfds (void *dummy)
453{
454 close (inf_ttrace_pfd1[0]);
455 close (inf_ttrace_pfd1[1]);
456 close (inf_ttrace_pfd2[0]);
457 close (inf_ttrace_pfd2[1]);
21ff4686
TT
458
459 unmark_fd_no_cloexec (inf_ttrace_pfd1[0]);
460 unmark_fd_no_cloexec (inf_ttrace_pfd1[1]);
461 unmark_fd_no_cloexec (inf_ttrace_pfd2[0]);
462 unmark_fd_no_cloexec (inf_ttrace_pfd2[1]);
eee22bf8
MK
463}
464
465static void
466inf_ttrace_prepare (void)
467{
468 if (pipe (inf_ttrace_pfd1) == -1)
a3f17187 469 perror_with_name (("pipe"));
eee22bf8
MK
470
471 if (pipe (inf_ttrace_pfd2) == -1)
472 {
473 close (inf_ttrace_pfd1[0]);
474 close (inf_ttrace_pfd2[0]);
a3f17187 475 perror_with_name (("pipe"));
eee22bf8 476 }
21ff4686
TT
477
478 mark_fd_no_cloexec (inf_ttrace_pfd1[0]);
479 mark_fd_no_cloexec (inf_ttrace_pfd1[1]);
480 mark_fd_no_cloexec (inf_ttrace_pfd2[0]);
481 mark_fd_no_cloexec (inf_ttrace_pfd2[1]);
eee22bf8
MK
482}
483
484/* Prepare to be traced. */
485
486static void
487inf_ttrace_me (void)
488{
489 struct cleanup *old_chain = make_cleanup (do_cleanup_pfds, 0);
490 char c;
491
492 /* "Trace me, Dr. Memory!" */
493 if (ttrace (TT_PROC_SETTRC, 0, 0, 0, TT_VERSION, 0) == -1)
e2e0b3e5 494 perror_with_name (("ttrace"));
eee22bf8
MK
495
496 /* Tell our parent that we are ready to be traced. */
497 if (write (inf_ttrace_pfd1[1], &c, sizeof c) != sizeof c)
e2e0b3e5 498 perror_with_name (("write"));
eee22bf8
MK
499
500 /* Wait until our parent has set the initial event mask. */
501 if (read (inf_ttrace_pfd2[0], &c, sizeof c) != sizeof c)
e2e0b3e5 502 perror_with_name (("read"));
eee22bf8
MK
503
504 do_cleanups (old_chain);
505}
506
507/* Start tracing PID. */
508
509static void
28439f5e 510inf_ttrace_him (struct target_ops *ops, int pid)
eee22bf8
MK
511{
512 struct cleanup *old_chain = make_cleanup (do_cleanup_pfds, 0);
513 ttevent_t tte;
eee22bf8
MK
514 char c;
515
516 /* Wait until our child is ready to be traced. */
517 if (read (inf_ttrace_pfd1[0], &c, sizeof c) != sizeof c)
e2e0b3e5 518 perror_with_name (("read"));
eee22bf8
MK
519
520 /* Set the initial event mask. */
521 memset (&tte, 0, sizeof (tte));
b2a4db28 522 tte.tte_events |= TTEVT_EXEC | TTEVT_EXIT | TTEVT_FORK | TTEVT_VFORK;
a7be7fa8 523 tte.tte_events |= TTEVT_LWP_CREATE | TTEVT_LWP_EXIT | TTEVT_LWP_TERMINATE;
7ba0e0c2
MK
524#ifdef TTEVT_BPT_SSTEP
525 tte.tte_events |= TTEVT_BPT_SSTEP;
526#endif
b2a4db28 527 tte.tte_opts |= TTEO_PROC_INHERIT;
eee22bf8
MK
528 if (ttrace (TT_PROC_SET_EVENT_MASK, pid, 0,
529 (uintptr_t)&tte, sizeof tte, 0) == -1)
e2e0b3e5 530 perror_with_name (("ttrace"));
eee22bf8
MK
531
532 /* Tell our child that we have set the initial event mask. */
533 if (write (inf_ttrace_pfd2[1], &c, sizeof c) != sizeof c)
e2e0b3e5 534 perror_with_name (("write"));
eee22bf8
MK
535
536 do_cleanups (old_chain);
537
6a3cb8e8
PA
538 if (!target_is_pushed (ops))
539 push_target (ops);
eee22bf8 540
eee22bf8
MK
541 startup_inferior (START_INFERIOR_TRAPS_EXPECTED);
542
543 /* On some targets, there must be some explicit actions taken after
544 the inferior has been started up. */
545 target_post_startup_inferior (pid_to_ptid (pid));
546}
547
548static void
136d6dae
VP
549inf_ttrace_create_inferior (struct target_ops *ops, char *exec_file,
550 char *allargs, char **env, int from_tty)
eee22bf8 551{
28439f5e
PA
552 int pid;
553
a7be7fa8
MK
554 gdb_assert (inf_ttrace_num_lwps == 0);
555 gdb_assert (inf_ttrace_num_lwps_in_syscall == 0);
932936f0 556 gdb_assert (inf_ttrace_page_dict.count == 0);
932936f0
MK
557 gdb_assert (inf_ttrace_reenable_page_protections == 0);
558
28439f5e 559 pid = fork_inferior (exec_file, allargs, env, inf_ttrace_me, NULL,
e69860f1 560 inf_ttrace_prepare, NULL, NULL);
28439f5e
PA
561
562 inf_ttrace_him (ops, pid);
eee22bf8
MK
563}
564
eee22bf8 565static void
136d6dae 566inf_ttrace_mourn_inferior (struct target_ops *ops)
eee22bf8 567{
932936f0
MK
568 const int num_buckets = ARRAY_SIZE (inf_ttrace_page_dict.buckets);
569 int bucket;
570
a7be7fa8
MK
571 inf_ttrace_num_lwps = 0;
572 inf_ttrace_num_lwps_in_syscall = 0;
932936f0
MK
573
574 for (bucket = 0; bucket < num_buckets; bucket++)
575 {
576 struct inf_ttrace_page *page;
577 struct inf_ttrace_page *next;
578
579 page = inf_ttrace_page_dict.buckets[bucket].next;
580 while (page)
581 {
582 next = page->next;
583 xfree (page);
584 page = next;
585 }
586 }
587 inf_ttrace_page_dict.count = 0;
588
c1ee2fb3 589 inf_child_mourn_inferior (ops);
eee22bf8
MK
590}
591
f688d93f
JB
592/* Assuming we just attached the debugger to a new inferior, create
593 a new thread_info structure for each thread, and add it to our
594 list of threads. */
595
596static void
597inf_ttrace_create_threads_after_attach (int pid)
598{
599 int status;
600 ptid_t ptid;
601 ttstate_t tts;
602 struct thread_info *ti;
603
604 status = ttrace (TT_PROC_GET_FIRST_LWP_STATE, pid, 0,
605 (uintptr_t) &tts, sizeof (ttstate_t), 0);
606 if (status < 0)
607 perror_with_name (_("TT_PROC_GET_FIRST_LWP_STATE ttrace call failed"));
608 gdb_assert (tts.tts_pid == pid);
609
610 /* Add the stopped thread. */
611 ptid = ptid_build (pid, tts.tts_lwpid, 0);
612 ti = add_thread (ptid);
613 ti->private = xzalloc (sizeof (struct inf_ttrace_private_thread_info));
614 inf_ttrace_num_lwps++;
615
616 /* We use the "first stopped thread" as the currently active thread. */
617 inferior_ptid = ptid;
618
619 /* Iterative over all the remaining threads. */
620
621 for (;;)
622 {
623 ptid_t ptid;
624
625 status = ttrace (TT_PROC_GET_NEXT_LWP_STATE, pid, 0,
626 (uintptr_t) &tts, sizeof (ttstate_t), 0);
627 if (status < 0)
628 perror_with_name (_("TT_PROC_GET_NEXT_LWP_STATE ttrace call failed"));
629 if (status == 0)
630 break; /* End of list. */
631
632 ptid = ptid_build (tts.tts_pid, tts.tts_lwpid, 0);
633 ti = add_thread (ptid);
634 ti->private = xzalloc (sizeof (struct inf_ttrace_private_thread_info));
635 inf_ttrace_num_lwps++;
636 }
637}
638
eee22bf8 639static void
c0939df1 640inf_ttrace_attach (struct target_ops *ops, const char *args, int from_tty)
eee22bf8
MK
641{
642 char *exec_file;
643 pid_t pid;
932936f0 644 ttevent_t tte;
181e7f93 645 struct inferior *inf;
eee22bf8 646
74164c56 647 pid = parse_pid_to_attach (args);
eee22bf8
MK
648
649 if (pid == getpid ()) /* Trying to masturbate? */
8a3fe4f8 650 error (_("I refuse to debug myself!"));
eee22bf8
MK
651
652 if (from_tty)
653 {
346e281c 654 exec_file = get_exec_file (0);
eee22bf8
MK
655
656 if (exec_file)
a3f17187 657 printf_unfiltered (_("Attaching to program: %s, %s\n"), exec_file,
eee22bf8
MK
658 target_pid_to_str (pid_to_ptid (pid)));
659 else
a3f17187 660 printf_unfiltered (_("Attaching to %s\n"),
eee22bf8
MK
661 target_pid_to_str (pid_to_ptid (pid)));
662
663 gdb_flush (gdb_stdout);
664 }
665
a7be7fa8
MK
666 gdb_assert (inf_ttrace_num_lwps == 0);
667 gdb_assert (inf_ttrace_num_lwps_in_syscall == 0);
668
eee22bf8 669 if (ttrace (TT_PROC_ATTACH, pid, 0, TT_KILL_ON_EXIT, TT_VERSION, 0) == -1)
e2e0b3e5 670 perror_with_name (("ttrace"));
eee22bf8 671
6c95b8df
PA
672 inf = current_inferior ();
673 inferior_appeared (inf, pid);
181e7f93 674 inf->attach_flag = 1;
7f9f62ba 675
932936f0 676 /* Set the initial event mask. */
932936f0 677 memset (&tte, 0, sizeof (tte));
b2a4db28 678 tte.tte_events |= TTEVT_EXEC | TTEVT_EXIT | TTEVT_FORK | TTEVT_VFORK;
a7be7fa8 679 tte.tte_events |= TTEVT_LWP_CREATE | TTEVT_LWP_EXIT | TTEVT_LWP_TERMINATE;
7ba0e0c2
MK
680#ifdef TTEVT_BPT_SSTEP
681 tte.tte_events |= TTEVT_BPT_SSTEP;
682#endif
b2a4db28 683 tte.tte_opts |= TTEO_PROC_INHERIT;
932936f0
MK
684 if (ttrace (TT_PROC_SET_EVENT_MASK, pid, 0,
685 (uintptr_t)&tte, sizeof tte, 0) == -1)
e2e0b3e5 686 perror_with_name (("ttrace"));
932936f0 687
6a3cb8e8
PA
688 if (!target_is_pushed (ops))
689 push_target (ops);
2935f27f 690
f688d93f 691 inf_ttrace_create_threads_after_attach (pid);
eee22bf8
MK
692}
693
694static void
52554a0e 695inf_ttrace_detach (struct target_ops *ops, const char *args, int from_tty)
eee22bf8 696{
eee22bf8 697 pid_t pid = ptid_get_pid (inferior_ptid);
5d426ff1 698 int sig = 0;
eee22bf8
MK
699
700 if (from_tty)
701 {
702 char *exec_file = get_exec_file (0);
703 if (exec_file == 0)
704 exec_file = "";
a3f17187 705 printf_unfiltered (_("Detaching from program: %s, %s\n"), exec_file,
eee22bf8
MK
706 target_pid_to_str (pid_to_ptid (pid)));
707 gdb_flush (gdb_stdout);
708 }
709 if (args)
710 sig = atoi (args);
711
712 /* ??? The HP-UX 11.0 ttrace(2) manual page doesn't mention that we
713 can pass a signal number here. Does this really work? */
714 if (ttrace (TT_PROC_DETACH, pid, 0, 0, sig, 0) == -1)
e2e0b3e5 715 perror_with_name (("ttrace"));
eee22bf8 716
a7be7fa8
MK
717 inf_ttrace_num_lwps = 0;
718 inf_ttrace_num_lwps_in_syscall = 0;
932936f0 719
932936f0 720 inferior_ptid = null_ptid;
7f9f62ba
PA
721 detach_inferior (pid);
722
6a3cb8e8 723 inf_child_maybe_unpush_target (ops);
eee22bf8
MK
724}
725
346e281c 726static void
7d85a9c0 727inf_ttrace_kill (struct target_ops *ops)
346e281c
MK
728{
729 pid_t pid = ptid_get_pid (inferior_ptid);
730
731 if (pid == 0)
732 return;
733
734 if (ttrace (TT_PROC_EXIT, pid, 0, 0, 0, 0) == -1)
735 perror_with_name (("ttrace"));
736 /* ??? Is it necessary to call ttrace_wait() here? */
737
346e281c
MK
738 target_mourn_inferior ();
739}
740
438ac09b
PA
741/* Check is a dying thread is dead by now, and delete it from GDBs
742 thread list if so. */
7ba0e0c2 743static int
438ac09b 744inf_ttrace_delete_dead_threads_callback (struct thread_info *info, void *arg)
7ba0e0c2 745{
438ac09b
PA
746 lwpid_t lwpid;
747 struct inf_ttrace_private_thread_info *p;
7ba0e0c2 748
438ac09b
PA
749 if (is_exited (info->ptid))
750 return 0;
751
752 lwpid = ptid_get_lwp (info->ptid);
753 p = (struct inf_ttrace_private_thread_info *) info->private;
754
755 /* Check if an lwp that was dying is still there or not. */
756 if (p->dying && (kill (lwpid, 0) == -1))
757 /* It's gone now. */
758 delete_thread (info->ptid);
7ba0e0c2
MK
759
760 return 0;
761}
762
438ac09b
PA
763/* Resume the lwp pointed to by INFO, with REQUEST, and pass it signal
764 SIG. */
765
766static void
767inf_ttrace_resume_lwp (struct thread_info *info, ttreq_t request, int sig)
768{
769 pid_t pid = ptid_get_pid (info->ptid);
770 lwpid_t lwpid = ptid_get_lwp (info->ptid);
771
772 if (ttrace (request, pid, lwpid, TT_NOPC, sig, 0) == -1)
773 {
774 struct inf_ttrace_private_thread_info *p
775 = (struct inf_ttrace_private_thread_info *) info->private;
776 if (p->dying && errno == EPROTO)
777 /* This is expected, it means the dying lwp is really gone
778 by now. If ttrace had an event to inform the debugger
779 the lwp is really gone, this wouldn't be needed. */
780 delete_thread (info->ptid);
781 else
782 /* This was really unexpected. */
783 perror_with_name (("ttrace"));
784 }
785}
786
787/* Callback for iterate_over_threads. */
788
60e2c248 789static int
438ac09b 790inf_ttrace_resume_callback (struct thread_info *info, void *arg)
60e2c248 791{
438ac09b
PA
792 if (!ptid_equal (info->ptid, inferior_ptid) && !is_exited (info->ptid))
793 inf_ttrace_resume_lwp (info, TT_LWP_CONTINUE, 0);
794
60e2c248
JG
795 return 0;
796}
797
eee22bf8 798static void
28439f5e 799inf_ttrace_resume (struct target_ops *ops,
2ea28649 800 ptid_t ptid, int step, enum gdb_signal signal)
eee22bf8 801{
438ac09b 802 int resume_all;
eee22bf8 803 ttreq_t request = step ? TT_LWP_SINGLE : TT_LWP_CONTINUE;
2ea28649 804 int sig = gdb_signal_to_host (signal);
438ac09b 805 struct thread_info *info;
eee22bf8 806
438ac09b
PA
807 /* A specific PTID means `step only this process id'. */
808 resume_all = (ptid_equal (ptid, minus_one_ptid));
eee22bf8 809
438ac09b
PA
810 /* If resuming all threads, it's the current thread that should be
811 handled specially. */
812 if (resume_all)
813 ptid = inferior_ptid;
eee22bf8 814
e09875d4 815 info = find_thread_ptid (ptid);
438ac09b
PA
816 inf_ttrace_resume_lwp (info, request, sig);
817
818 if (resume_all)
819 /* Let all the other threads run too. */
820 iterate_over_threads (inf_ttrace_resume_callback, NULL);
eee22bf8
MK
821}
822
823static ptid_t
117de6a9 824inf_ttrace_wait (struct target_ops *ops,
47608cb1 825 ptid_t ptid, struct target_waitstatus *ourstatus, int options)
eee22bf8
MK
826{
827 pid_t pid = ptid_get_pid (ptid);
828 lwpid_t lwpid = ptid_get_lwp (ptid);
829 ttstate_t tts;
60e2c248 830 struct thread_info *ti;
3a3e9ee3 831 ptid_t related_ptid;
eee22bf8 832
932936f0 833 /* Until proven otherwise. */
a7be7fa8 834 ourstatus->kind = TARGET_WAITKIND_SPURIOUS;
eee22bf8
MK
835
836 if (pid == -1)
b2a4db28 837 pid = lwpid = 0;
eee22bf8 838
b2a4db28 839 gdb_assert (pid != 0 || lwpid == 0);
eee22bf8
MK
840
841 do
842 {
843 set_sigint_trap ();
eee22bf8
MK
844
845 if (ttrace_wait (pid, lwpid, TTRACE_WAITOK, &tts, sizeof tts) == -1)
a3f17187 846 perror_with_name (("ttrace_wait"));
eee22bf8 847
eee22bf8
MK
848 clear_sigint_trap ();
849 }
850 while (tts.tts_event == TTEVT_NONE);
851
932936f0
MK
852 /* Now that we've waited, we can re-enable the page protections. */
853 if (inf_ttrace_reenable_page_protections)
854 {
a7be7fa8 855 gdb_assert (inf_ttrace_num_lwps_in_syscall == 0);
932936f0
MK
856 inf_ttrace_enable_page_protections (tts.tts_pid);
857 inf_ttrace_reenable_page_protections = 0;
858 }
859
a7be7fa8
MK
860 ptid = ptid_build (tts.tts_pid, tts.tts_lwpid, 0);
861
2935f27f
PA
862 if (inf_ttrace_num_lwps == 0)
863 {
864 struct thread_info *ti;
865
866 inf_ttrace_num_lwps = 1;
867
868 /* This is the earliest we hear about the lwp member of
869 INFERIOR_PTID, after an attach or fork_inferior. */
870 gdb_assert (ptid_get_lwp (inferior_ptid) == 0);
871
872 /* We haven't set the private member on the main thread yet. Do
873 it now. */
e09875d4 874 ti = find_thread_ptid (inferior_ptid);
2935f27f
PA
875 gdb_assert (ti != NULL && ti->private == NULL);
876 ti->private =
877 xmalloc (sizeof (struct inf_ttrace_private_thread_info));
878 memset (ti->private, 0,
879 sizeof (struct inf_ttrace_private_thread_info));
880
881 /* Notify the core that this ptid changed. This changes
882 inferior_ptid as well. */
883 thread_change_ptid (inferior_ptid, ptid);
884 }
885
eee22bf8
MK
886 switch (tts.tts_event)
887 {
7ba0e0c2
MK
888#ifdef TTEVT_BPT_SSTEP
889 case TTEVT_BPT_SSTEP:
890 /* Make it look like a breakpoint. */
891 ourstatus->kind = TARGET_WAITKIND_STOPPED;
a493e3e2 892 ourstatus->value.sig = GDB_SIGNAL_TRAP;
7ba0e0c2
MK
893 break;
894#endif
895
eee22bf8 896 case TTEVT_EXEC:
5d426ff1
MK
897 ourstatus->kind = TARGET_WAITKIND_EXECD;
898 ourstatus->value.execd_pathname =
899 xmalloc (tts.tts_u.tts_exec.tts_pathlen + 1);
900 if (ttrace (TT_PROC_GET_PATHNAME, tts.tts_pid, 0,
901 (uintptr_t)ourstatus->value.execd_pathname,
902 tts.tts_u.tts_exec.tts_pathlen, 0) == -1)
903 perror_with_name (("ttrace"));
904 ourstatus->value.execd_pathname[tts.tts_u.tts_exec.tts_pathlen] = 0;
25b22b0a
PA
905
906 /* At this point, all inserted breakpoints are gone. Doing this
907 as soon as we detect an exec prevents the badness of deleting
908 a breakpoint writing the current "shadow contents" to lift
909 the bp. That shadow is NOT valid after an exec. */
910 mark_breakpoints_out ();
eee22bf8 911 break;
932936f0 912
eee22bf8
MK
913 case TTEVT_EXIT:
914 store_waitstatus (ourstatus, tts.tts_u.tts_exit.tts_exitcode);
a7be7fa8
MK
915 inf_ttrace_num_lwps = 0;
916 break;
917
b2a4db28 918 case TTEVT_FORK:
3a3e9ee3
PA
919 related_ptid = ptid_build (tts.tts_u.tts_fork.tts_fpid,
920 tts.tts_u.tts_fork.tts_flwpid, 0);
921
b2a4db28 922 ourstatus->kind = TARGET_WAITKIND_FORKED;
3a3e9ee3 923 ourstatus->value.related_pid = related_ptid;
b2a4db28
MK
924
925 /* Make sure the other end of the fork is stopped too. */
926 if (ttrace_wait (tts.tts_u.tts_fork.tts_fpid,
927 tts.tts_u.tts_fork.tts_flwpid,
928 TTRACE_WAITOK, &tts, sizeof tts) == -1)
929 perror_with_name (("ttrace_wait"));
930
931 gdb_assert (tts.tts_event == TTEVT_FORK);
932 if (tts.tts_u.tts_fork.tts_isparent)
933 {
3a3e9ee3
PA
934 related_ptid = ptid_build (tts.tts_u.tts_fork.tts_fpid,
935 tts.tts_u.tts_fork.tts_flwpid, 0);
b2a4db28 936 ptid = ptid_build (tts.tts_pid, tts.tts_lwpid, 0);
3a3e9ee3 937 ourstatus->value.related_pid = related_ptid;
b2a4db28
MK
938 }
939 break;
940
941 case TTEVT_VFORK:
d83ad864
DB
942 if (tts.tts_u.tts_fork.tts_isparent)
943 ourstatus->kind = TARGET_WAITKIND_VFORK_DONE;
944 else
945 {
946 related_ptid = ptid_build (tts.tts_u.tts_fork.tts_fpid,
947 tts.tts_u.tts_fork.tts_flwpid, 0);
b2a4db28 948
d83ad864
DB
949 ourstatus->kind = TARGET_WAITKIND_VFORKED;
950 ourstatus->value.related_pid = related_ptid;
951 }
b2a4db28
MK
952 break;
953
a7be7fa8
MK
954 case TTEVT_LWP_CREATE:
955 lwpid = tts.tts_u.tts_thread.tts_target_lwpid;
956 ptid = ptid_build (tts.tts_pid, lwpid, 0);
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);
62a93fa9
PA
964 /* Let the lwp_create-caller thread continue. */
965 ttrace (TT_LWP_CONTINUE, ptid_get_pid (ptid),
966 ptid_get_lwp (ptid), TT_NOPC, 0, 0);
967 /* Return without stopping the whole process. */
968 ourstatus->kind = TARGET_WAITKIND_IGNORE;
969 return ptid;
a7be7fa8
MK
970
971 case TTEVT_LWP_EXIT:
17faa917
DJ
972 if (print_thread_events)
973 printf_unfiltered (_("[%s exited]\n"), target_pid_to_str (ptid));
e09875d4 974 ti = find_thread_ptid (ptid);
60e2c248
JG
975 gdb_assert (ti != NULL);
976 ((struct inf_ttrace_private_thread_info *)ti->private)->dying = 1;
a7be7fa8 977 inf_ttrace_num_lwps--;
62a93fa9 978 /* Let the thread really exit. */
60e2c248
JG
979 ttrace (TT_LWP_CONTINUE, ptid_get_pid (ptid),
980 ptid_get_lwp (ptid), TT_NOPC, 0, 0);
62a93fa9
PA
981 /* Return without stopping the whole process. */
982 ourstatus->kind = TARGET_WAITKIND_IGNORE;
983 return ptid;
a7be7fa8
MK
984
985 case TTEVT_LWP_TERMINATE:
986 lwpid = tts.tts_u.tts_thread.tts_target_lwpid;
987 ptid = ptid_build (tts.tts_pid, lwpid, 0);
62a93fa9 988 if (print_thread_events)
b861ac81 989 printf_unfiltered(_("[%s has been terminated]\n"),
62a93fa9 990 target_pid_to_str (ptid));
e09875d4 991 ti = find_thread_ptid (ptid);
60e2c248
JG
992 gdb_assert (ti != NULL);
993 ((struct inf_ttrace_private_thread_info *)ti->private)->dying = 1;
a7be7fa8 994 inf_ttrace_num_lwps--;
62a93fa9
PA
995
996 /* Resume the lwp_terminate-caller thread. */
a7be7fa8 997 ptid = ptid_build (tts.tts_pid, tts.tts_lwpid, 0);
62a93fa9
PA
998 ttrace (TT_LWP_CONTINUE, ptid_get_pid (ptid),
999 ptid_get_lwp (ptid), TT_NOPC, 0, 0);
1000 /* Return without stopping the whole process. */
1001 ourstatus->kind = TARGET_WAITKIND_IGNORE;
1002 return ptid;
932936f0 1003
eee22bf8
MK
1004 case TTEVT_SIGNAL:
1005 ourstatus->kind = TARGET_WAITKIND_STOPPED;
1006 ourstatus->value.sig =
2ea28649 1007 gdb_signal_from_host (tts.tts_u.tts_signal.tts_signo);
eee22bf8 1008 break;
932936f0
MK
1009
1010 case TTEVT_SYSCALL_ENTRY:
1011 gdb_assert (inf_ttrace_reenable_page_protections == 0);
a7be7fa8
MK
1012 inf_ttrace_num_lwps_in_syscall++;
1013 if (inf_ttrace_num_lwps_in_syscall == 1)
932936f0
MK
1014 {
1015 /* A thread has just entered a system call. Disable any
1016 page protections as the kernel can't deal with them. */
1017 inf_ttrace_disable_page_protections (tts.tts_pid);
1018 }
1019 ourstatus->kind = TARGET_WAITKIND_SYSCALL_ENTRY;
01dedca2 1020 ourstatus->value.syscall_number = tts.tts_scno;
932936f0
MK
1021 break;
1022
1023 case TTEVT_SYSCALL_RETURN:
a7be7fa8 1024 if (inf_ttrace_num_lwps_in_syscall > 0)
932936f0
MK
1025 {
1026 /* If the last thread has just left the system call, this
1027 would be a logical place to re-enable the page
1028 protections, but that doesn't work. We can't re-enable
1029 them until we've done another wait. */
1030 inf_ttrace_reenable_page_protections =
a7be7fa8
MK
1031 (inf_ttrace_num_lwps_in_syscall == 1);
1032 inf_ttrace_num_lwps_in_syscall--;
932936f0
MK
1033 }
1034 ourstatus->kind = TARGET_WAITKIND_SYSCALL_RETURN;
01dedca2 1035 ourstatus->value.syscall_number = tts.tts_scno;
932936f0 1036 break;
a7be7fa8
MK
1037
1038 default:
1039 gdb_assert (!"Unexpected ttrace event");
1040 break;
eee22bf8
MK
1041 }
1042
1043 /* Make sure all threads within the process are stopped. */
1044 if (ttrace (TT_PROC_STOP, tts.tts_pid, 0, 0, 0, 0) == -1)
e2e0b3e5 1045 perror_with_name (("ttrace"));
eee22bf8 1046
438ac09b
PA
1047 /* Now that the whole process is stopped, check if any dying thread
1048 is really dead by now. If a dying thread is still alive, it will
1049 be stopped too, and will still show up in `info threads', tagged
1050 with "(Exiting)". We could make `info threads' prune dead
1051 threads instead via inf_ttrace_thread_alive, but doing this here
1052 has the advantage that a frontend is notificed sooner of thread
1053 exits. Note that a dying lwp is still alive, it still has to be
1054 resumed, like any other lwp. */
1055 iterate_over_threads (inf_ttrace_delete_dead_threads_callback, NULL);
1056
a7be7fa8 1057 return ptid;
eee22bf8
MK
1058}
1059
1060/* Transfer LEN bytes from ADDR in the inferior's memory into READBUF,
1061 and transfer LEN bytes from WRITEBUF into the inferior's memory at
1062 ADDR. Either READBUF or WRITEBUF may be null, in which case the
1063 corresponding transfer doesn't happen. Return the number of bytes
1064 actually transferred (which may be zero if an error occurs). */
1065
1066static LONGEST
1067inf_ttrace_xfer_memory (CORE_ADDR addr, ULONGEST len,
1068 void *readbuf, const void *writebuf)
1069{
1070 pid_t pid = ptid_get_pid (inferior_ptid);
1071
1072 /* HP-UX treats text space and data space differently. GDB however,
1073 doesn't really know the difference. Therefore we try both. Try
1074 text space before data space though because when we're writing
1075 into text space the instruction cache might need to be flushed. */
1076
1077 if (readbuf
1078 && ttrace (TT_PROC_RDTEXT, pid, 0, addr, len, (uintptr_t)readbuf) == -1
1079 && ttrace (TT_PROC_RDDATA, pid, 0, addr, len, (uintptr_t)readbuf) == -1)
1080 return 0;
1081
1082 if (writebuf
1083 && ttrace (TT_PROC_WRTEXT, pid, 0, addr, len, (uintptr_t)writebuf) == -1
1084 && ttrace (TT_PROC_WRDATA, pid, 0, addr, len, (uintptr_t)writebuf) == -1)
1085 return 0;
1086
1087 return len;
1088}
1089
9b409511 1090static enum target_xfer_status
eee22bf8 1091inf_ttrace_xfer_partial (struct target_ops *ops, enum target_object object,
7a4609f7 1092 const char *annex, gdb_byte *readbuf,
3e43a32a 1093 const gdb_byte *writebuf,
9b409511 1094 ULONGEST offset, ULONGEST len, ULONGEST *xfered_len)
eee22bf8
MK
1095{
1096 switch (object)
1097 {
1098 case TARGET_OBJECT_MEMORY:
9b409511
YQ
1099 {
1100 LONGEST val = inf_ttrace_xfer_memory (offset, len, readbuf, writebuf);
1101
1102 if (val == 0)
1103 return TARGET_XFER_EOF;
1104 else
1105 {
1106 *xfered_len = (ULONGEST) val;
1107 return TARGET_XFER_OK;
1108 }
1109 }
eee22bf8
MK
1110
1111 case TARGET_OBJECT_UNWIND_TABLE:
2ed4b548 1112 return TARGET_XFER_E_IO;
eee22bf8
MK
1113
1114 case TARGET_OBJECT_AUXV:
2ed4b548 1115 return TARGET_XFER_E_IO;
eee22bf8
MK
1116
1117 case TARGET_OBJECT_WCOOKIE:
2ed4b548 1118 return TARGET_XFER_E_IO;
eee22bf8
MK
1119
1120 default:
2ed4b548 1121 return TARGET_XFER_E_IO;
eee22bf8
MK
1122 }
1123}
1124
1125/* Print status information about what we're accessing. */
1126
1127static void
1128inf_ttrace_files_info (struct target_ops *ignore)
1129{
181e7f93 1130 struct inferior *inf = current_inferior ();
346e281c 1131 printf_filtered (_("\tUsing the running image of %s %s.\n"),
181e7f93 1132 inf->attach_flag ? "attached" : "child",
346e281c 1133 target_pid_to_str (inferior_ptid));
eee22bf8 1134}
a7be7fa8
MK
1135
1136static int
28439f5e 1137inf_ttrace_thread_alive (struct target_ops *ops, ptid_t ptid)
a7be7fa8 1138{
438ac09b
PA
1139 return 1;
1140}
1141
1142/* Return a string describing the state of the thread specified by
1143 INFO. */
1144
1145static char *
c15906d8
TT
1146inf_ttrace_extra_thread_info (struct target_ops *self,
1147 struct thread_info *info)
438ac09b
PA
1148{
1149 struct inf_ttrace_private_thread_info* private =
1150 (struct inf_ttrace_private_thread_info *) info->private;
1151
1152 if (private != NULL && private->dying)
1153 return "Exiting";
1154
1155 return NULL;
a7be7fa8
MK
1156}
1157
1158static char *
117de6a9 1159inf_ttrace_pid_to_str (struct target_ops *ops, ptid_t ptid)
a7be7fa8 1160{
2935f27f
PA
1161 pid_t pid = ptid_get_pid (ptid);
1162 lwpid_t lwpid = ptid_get_lwp (ptid);
1163 static char buf[128];
a7be7fa8 1164
2935f27f
PA
1165 if (lwpid == 0)
1166 xsnprintf (buf, sizeof buf, "process %ld",
1167 (long) pid);
1168 else
1169 xsnprintf (buf, sizeof buf, "process %ld, lwp %ld",
1170 (long) pid, (long) lwpid);
1171 return buf;
a7be7fa8 1172}
eee22bf8
MK
1173\f
1174
fa07e785
JB
1175/* Implement the get_ada_task_ptid target_ops method. */
1176
1177static ptid_t
1e6b91a4 1178inf_ttrace_get_ada_task_ptid (struct target_ops *self, long lwp, long thread)
fa07e785
JB
1179{
1180 return ptid_build (ptid_get_pid (inferior_ptid), lwp, 0);
1181}
1182
1183\f
eee22bf8
MK
1184struct target_ops *
1185inf_ttrace_target (void)
1186{
1187 struct target_ops *t = inf_child_target ();
1188
eee22bf8
MK
1189 t->to_attach = inf_ttrace_attach;
1190 t->to_detach = inf_ttrace_detach;
1191 t->to_resume = inf_ttrace_resume;
1192 t->to_wait = inf_ttrace_wait;
eee22bf8 1193 t->to_files_info = inf_ttrace_files_info;
932936f0 1194 t->to_can_use_hw_breakpoint = inf_ttrace_can_use_hw_breakpoint;
932936f0
MK
1195 t->to_insert_watchpoint = inf_ttrace_insert_watchpoint;
1196 t->to_remove_watchpoint = inf_ttrace_remove_watchpoint;
1197 t->to_stopped_by_watchpoint = inf_ttrace_stopped_by_watchpoint;
2a3cdf79
WZ
1198 t->to_region_ok_for_hw_watchpoint =
1199 inf_ttrace_region_ok_for_hw_watchpoint;
346e281c
MK
1200 t->to_kill = inf_ttrace_kill;
1201 t->to_create_inferior = inf_ttrace_create_inferior;
1202 t->to_follow_fork = inf_ttrace_follow_fork;
1203 t->to_mourn_inferior = inf_ttrace_mourn_inferior;
1204 t->to_thread_alive = inf_ttrace_thread_alive;
438ac09b 1205 t->to_extra_thread_info = inf_ttrace_extra_thread_info;
346e281c
MK
1206 t->to_pid_to_str = inf_ttrace_pid_to_str;
1207 t->to_xfer_partial = inf_ttrace_xfer_partial;
fa07e785 1208 t->to_get_ada_task_ptid = inf_ttrace_get_ada_task_ptid;
eee22bf8 1209
eee22bf8
MK
1210 return t;
1211}
d3322e8a 1212#endif
932936f0
MK
1213\f
1214
1215/* Prevent warning from -Wmissing-prototypes. */
0b155465 1216void _initialize_inf_ttrace (void);
eee22bf8 1217
932936f0
MK
1218void
1219_initialize_inf_ttrace (void)
1220{
d3322e8a 1221#ifdef HAVE_TTRACE
932936f0 1222 inf_ttrace_page_dict.pagesize = getpagesize();
eee22bf8 1223#endif
d3322e8a 1224}