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