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