OpenCores
URL https://opencores.org/ocsvn/openrisc_me/openrisc_me/trunk

Subversion Repositories openrisc_me

[/] [openrisc/] [trunk/] [gnu-src/] [gdb-7.2/] [gdb/] [inf-ttrace.c] - Blame information for rev 330

Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.