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

Subversion Repositories openrisc_me

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

Go to most recent revision | Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

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