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

Subversion Repositories openrisc_me

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

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 24 jeremybenn
/* Low-level child interface to ttrace.
2
 
3
   Copyright (C) 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
4
 
5
   This file is part of GDB.
6
 
7
   This program is free software; you can redistribute it and/or modify
8
   it under the terms of the GNU General Public License as published by
9
   the Free Software Foundation; either version 3 of the License, or
10
   (at your option) any later version.
11
 
12
   This program is distributed in the hope that it will be useful,
13
   but WITHOUT ANY WARRANTY; without even the implied warranty of
14
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15
   GNU General Public License for more details.
16
 
17
   You should have received a copy of the GNU General Public License
18
   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
19
 
20
#include "defs.h"
21
 
22
/* The ttrace(2) system call didn't exist before HP-UX 10.30.  Don't
23
   try to compile this code unless we have it.  */
24
#ifdef HAVE_TTRACE
25
 
26
#include "command.h"
27
#include "gdbcore.h"
28
#include "gdbthread.h"
29
#include "inferior.h"
30
#include "target.h"
31
 
32
#include "gdb_assert.h"
33
#include "gdb_string.h"
34
#include <sys/mman.h>
35
#include <sys/ttrace.h>
36
 
37
#include "inf-child.h"
38
#include "inf-ttrace.h"
39
 
40
/* HACK: Save the ttrace ops returned by inf_ttrace_target.  */
41
static struct target_ops *ttrace_ops_hack;
42
 
43
 
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.  */
54
static int inf_ttrace_num_lwps;
55
 
56
 
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
 
63
struct 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
 
72
struct 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
 
79
struct inf_ttrace_private_thread_info
80
{
81
  int dying;
82
};
83
 
84
/* Number of lwps that are currently in a system call.  */
85
static int inf_ttrace_num_lwps_in_syscall;
86
 
87
/* Flag to indicate whether we should re-enable page protections after
88
   the next wait.  */
89
static int inf_ttrace_reenable_page_protections;
90
 
91
/* Enable system call events for process PID.  */
92
 
93
static void
94
inf_ttrace_enable_syscall_events (pid_t pid)
95
{
96
  ttevent_t tte;
97
  ttstate_t tts;
98
 
99
  gdb_assert (inf_ttrace_num_lwps_in_syscall == 0);
100
 
101
  if (ttrace (TT_PROC_GET_EVENT_MASK, pid, 0,
102
              (uintptr_t)&tte, sizeof tte, 0) == -1)
103
    perror_with_name (("ttrace"));
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)
109
    perror_with_name (("ttrace"));
110
 
111
  if (ttrace (TT_PROC_GET_FIRST_LWP_STATE, pid, 0,
112
              (uintptr_t)&tts, sizeof tts, 0) == -1)
113
    perror_with_name (("ttrace"));
114
 
115
  if (tts.tts_flags & TTS_INSYSCALL)
116
    inf_ttrace_num_lwps_in_syscall++;
117
 
118
  /* FIXME: Handle multiple threads.  */
119
}
120
 
121
/* Disable system call events for process PID.  */
122
 
123
static void
124
inf_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)
132
    perror_with_name (("ttrace"));
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)
138
    perror_with_name (("ttrace"));
139
 
140
  inf_ttrace_num_lwps_in_syscall = 0;
141
}
142
 
143
/* Get information about the page at address ADDR for process PID from
144
   the dictionary.  */
145
 
146
static struct inf_ttrace_page *
147
inf_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
 
169
static struct inf_ttrace_page *
170
inf_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)
195
        perror_with_name (("ttrace"));
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
 
210
      if (inf_ttrace_num_lwps_in_syscall == 0)
211
        {
212
          if (ttrace (TT_PROC_SET_MPROTECT, pid, 0,
213
                      addr, pagesize, prot & ~PROT_WRITE) == -1)
214
            perror_with_name (("ttrace"));
215
        }
216
    }
217
 
218
  return page;
219
}
220
 
221
/* Insert the page at address ADDR of process PID to the dictionary.  */
222
 
223
static void
224
inf_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
 
237
static void
238
inf_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
    {
250
      if (inf_ttrace_num_lwps_in_syscall == 0)
251
        {
252
          if (ttrace (TT_PROC_SET_MPROTECT, pid, 0,
253
                      addr, pagesize, page->prot) == -1)
254
            perror_with_name (("ttrace"));
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
 
272
static void
273
inf_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)
288
            perror_with_name (("ttrace"));
289
 
290
          page = page->next;
291
        }
292
    }
293
}
294
 
295
/* Write-protect the pages in the dictionary for process PID.  */
296
 
297
static void
298
inf_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
 
306
static void
307
inf_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
 
315
static int
316
inf_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
 
338
static int
339
inf_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
 
358
static int
359
inf_ttrace_can_use_hw_breakpoint (int type, int len, int ot)
360
{
361
  return (type == bp_hardware_watchpoint);
362
}
363
 
364
static int
365
inf_ttrace_region_ok_for_hw_watchpoint (CORE_ADDR addr, int len)
366
{
367
  return 1;
368
}
369
 
370
/* Return non-zero if the current inferior was (potentially) stopped
371
   by hitting a "hardware" watchpoint.  */
372
 
373
static int
374
inf_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)
384
        perror_with_name (("ttrace"));
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
 
401
 
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.  */
406
static pid_t inf_ttrace_vfork_ppid = -1;
407
 
408
static int
409
inf_ttrace_follow_fork (struct target_ops *ops, int follow_child)
410
{
411
  pid_t pid, fpid;
412
  lwpid_t lwpid, flwpid;
413
  ttstate_t tts;
414
 
415
  /* FIXME: kettenis/20050720: This stuff should really be passed as
416
     an argument by our caller.  */
417
  {
418
    ptid_t ptid;
419
    struct target_waitstatus status;
420
 
421
    get_last_target_status (&ptid, &status);
422
    gdb_assert (status.kind == TARGET_WAITKIND_FORKED
423
                || status.kind == TARGET_WAITKIND_VFORKED);
424
 
425
    pid = ptid_get_pid (ptid);
426
    lwpid = ptid_get_lwp (ptid);
427
  }
428
 
429
  /* Get all important details that core GDB doesn't (and shouldn't)
430
     know about.  */
431
  if (ttrace (TT_LWP_GET_STATE, pid, lwpid,
432
              (uintptr_t)&tts, sizeof tts, 0) == -1)
433
    perror_with_name (("ttrace"));
434
 
435
  gdb_assert (tts.tts_event == TTEVT_FORK || tts.tts_event == TTEVT_VFORK);
436
 
437
  if (tts.tts_u.tts_fork.tts_isparent)
438
    {
439
      pid = tts.tts_pid;
440
      lwpid = tts.tts_lwpid;
441
      fpid = tts.tts_u.tts_fork.tts_fpid;
442
      flwpid = tts.tts_u.tts_fork.tts_flwpid;
443
    }
444
  else
445
    {
446
      pid = tts.tts_u.tts_fork.tts_fpid;
447
      lwpid = tts.tts_u.tts_fork.tts_flwpid;
448
      fpid = tts.tts_pid;
449
      flwpid = tts.tts_lwpid;
450
    }
451
 
452
  if (follow_child)
453
    {
454
      inferior_ptid = ptid_build (fpid, flwpid, 0);
455
      detach_breakpoints (pid);
456
 
457
      target_terminal_ours ();
458
      fprintf_unfiltered (gdb_stdlog, _("\
459
Attaching after fork to child process %ld.\n"), (long)fpid);
460
    }
461
  else
462
    {
463
      inferior_ptid = ptid_build (pid, lwpid, 0);
464
      detach_breakpoints (fpid);
465
 
466
      target_terminal_ours ();
467
      fprintf_unfiltered (gdb_stdlog, _("\
468
Detaching after fork from child process %ld.\n"), (long)fpid);
469
    }
470
 
471
  if (tts.tts_event == TTEVT_VFORK)
472
    {
473
      gdb_assert (!tts.tts_u.tts_fork.tts_isparent);
474
 
475
      if (follow_child)
476
        {
477
          /* We can't detach from the parent yet.  */
478
          inf_ttrace_vfork_ppid = pid;
479
 
480
          reattach_breakpoints (fpid);
481
        }
482
      else
483
        {
484
          if (ttrace (TT_PROC_DETACH, fpid, 0, 0, 0, 0) == -1)
485
            perror_with_name (("ttrace"));
486
 
487
          /* Wait till we get the TTEVT_VFORK event in the parent.
488
             This indicates that the child has called exec(3) or has
489
             exited and that the parent is ready to be traced again.  */
490
          if (ttrace_wait (pid, lwpid, TTRACE_WAITOK, &tts, sizeof tts) == -1)
491
            perror_with_name (("ttrace_wait"));
492
          gdb_assert (tts.tts_event == TTEVT_VFORK);
493
          gdb_assert (tts.tts_u.tts_fork.tts_isparent);
494
 
495
          reattach_breakpoints (pid);
496
        }
497
    }
498
  else
499
    {
500
      gdb_assert (tts.tts_u.tts_fork.tts_isparent);
501
 
502
      if (follow_child)
503
        {
504
          if (ttrace (TT_PROC_DETACH, pid, 0, 0, 0, 0) == -1)
505
            perror_with_name (("ttrace"));
506
        }
507
      else
508
        {
509
          if (ttrace (TT_PROC_DETACH, fpid, 0, 0, 0, 0) == -1)
510
            perror_with_name (("ttrace"));
511
        }
512
    }
513
 
514
  if (follow_child)
515
    {
516
      /* The child will start out single-threaded.  */
517
      inf_ttrace_num_lwps = 0;
518
      inf_ttrace_num_lwps_in_syscall = 0;
519
 
520
      /* Reset breakpoints in the child as appropriate.  */
521
      follow_inferior_reset_breakpoints ();
522
    }
523
 
524
  return 0;
525
}
526
 
527
 
528
/* File descriptors for pipes used as semaphores during initial
529
   startup of an inferior.  */
530
static int inf_ttrace_pfd1[2];
531
static int inf_ttrace_pfd2[2];
532
 
533
static void
534
do_cleanup_pfds (void *dummy)
535
{
536
  close (inf_ttrace_pfd1[0]);
537
  close (inf_ttrace_pfd1[1]);
538
  close (inf_ttrace_pfd2[0]);
539
  close (inf_ttrace_pfd2[1]);
540
}
541
 
542
static void
543
inf_ttrace_prepare (void)
544
{
545
  if (pipe (inf_ttrace_pfd1) == -1)
546
    perror_with_name (("pipe"));
547
 
548
  if (pipe (inf_ttrace_pfd2) == -1)
549
    {
550
      close (inf_ttrace_pfd1[0]);
551
      close (inf_ttrace_pfd2[0]);
552
      perror_with_name (("pipe"));
553
    }
554
}
555
 
556
/* Prepare to be traced.  */
557
 
558
static void
559
inf_ttrace_me (void)
560
{
561
  struct cleanup *old_chain = make_cleanup (do_cleanup_pfds, 0);
562
  char c;
563
 
564
  /* "Trace me, Dr. Memory!"  */
565
  if (ttrace (TT_PROC_SETTRC, 0, 0, 0, TT_VERSION, 0) == -1)
566
    perror_with_name (("ttrace"));
567
 
568
  /* Tell our parent that we are ready to be traced.  */
569
  if (write (inf_ttrace_pfd1[1], &c, sizeof c) != sizeof c)
570
    perror_with_name (("write"));
571
 
572
  /* Wait until our parent has set the initial event mask.  */
573
  if (read (inf_ttrace_pfd2[0], &c, sizeof c) != sizeof c)
574
    perror_with_name (("read"));
575
 
576
  do_cleanups (old_chain);
577
}
578
 
579
/* Start tracing PID.  */
580
 
581
static void
582
inf_ttrace_him (int pid)
583
{
584
  struct cleanup *old_chain = make_cleanup (do_cleanup_pfds, 0);
585
  ttevent_t tte;
586
  char c;
587
 
588
  /* Wait until our child is ready to be traced.  */
589
  if (read (inf_ttrace_pfd1[0], &c, sizeof c) != sizeof c)
590
    perror_with_name (("read"));
591
 
592
  /* Set the initial event mask.  */
593
  memset (&tte, 0, sizeof (tte));
594
  tte.tte_events |= TTEVT_EXEC | TTEVT_EXIT | TTEVT_FORK | TTEVT_VFORK;
595
  tte.tte_events |= TTEVT_LWP_CREATE | TTEVT_LWP_EXIT | TTEVT_LWP_TERMINATE;
596
#ifdef TTEVT_BPT_SSTEP
597
  tte.tte_events |= TTEVT_BPT_SSTEP;
598
#endif
599
  tte.tte_opts |= TTEO_PROC_INHERIT;
600
  if (ttrace (TT_PROC_SET_EVENT_MASK, pid, 0,
601
              (uintptr_t)&tte, sizeof tte, 0) == -1)
602
    perror_with_name (("ttrace"));
603
 
604
  /* Tell our child that we have set the initial event mask.  */
605
  if (write (inf_ttrace_pfd2[1], &c, sizeof c) != sizeof c)
606
    perror_with_name (("write"));
607
 
608
  do_cleanups (old_chain);
609
 
610
  push_target (ttrace_ops_hack);
611
 
612
  /* On some targets, there must be some explicit synchronization
613
     between the parent and child processes after the debugger forks,
614
     and before the child execs the debuggee program.  This call
615
     basically gives permission for the child to exec.  */
616
 
617
  target_acknowledge_created_inferior (pid);
618
 
619
  /* START_INFERIOR_TRAPS_EXPECTED is defined in inferior.h, and will
620
     be 1 or 2 depending on whether we're starting without or with a
621
     shell.  */
622
  startup_inferior (START_INFERIOR_TRAPS_EXPECTED);
623
 
624
  /* On some targets, there must be some explicit actions taken after
625
     the inferior has been started up.  */
626
  target_post_startup_inferior (pid_to_ptid (pid));
627
}
628
 
629
static void
630
inf_ttrace_create_inferior (char *exec_file, char *allargs, char **env,
631
                            int from_tty)
632
{
633
  gdb_assert (inf_ttrace_num_lwps == 0);
634
  gdb_assert (inf_ttrace_num_lwps_in_syscall == 0);
635
  gdb_assert (inf_ttrace_page_dict.count == 0);
636
  gdb_assert (inf_ttrace_reenable_page_protections == 0);
637
  gdb_assert (inf_ttrace_vfork_ppid == -1);
638
 
639
  fork_inferior (exec_file, allargs, env, inf_ttrace_me, inf_ttrace_him,
640
                 inf_ttrace_prepare, NULL);
641
}
642
 
643
static void
644
inf_ttrace_mourn_inferior (void)
645
{
646
  const int num_buckets = ARRAY_SIZE (inf_ttrace_page_dict.buckets);
647
  int bucket;
648
 
649
  inf_ttrace_num_lwps = 0;
650
  inf_ttrace_num_lwps_in_syscall = 0;
651
 
652
  for (bucket = 0; bucket < num_buckets; bucket++)
653
    {
654
      struct inf_ttrace_page *page;
655
      struct inf_ttrace_page *next;
656
 
657
      page = inf_ttrace_page_dict.buckets[bucket].next;
658
      while (page)
659
        {
660
          next = page->next;
661
          xfree (page);
662
          page = next;
663
        }
664
    }
665
  inf_ttrace_page_dict.count = 0;
666
 
667
  unpush_target (ttrace_ops_hack);
668
  generic_mourn_inferior ();
669
}
670
 
671
static void
672
inf_ttrace_attach (char *args, int from_tty)
673
{
674
  char *exec_file;
675
  pid_t pid;
676
  char *dummy;
677
  ttevent_t tte;
678
 
679
  if (!args)
680
    error_no_arg (_("process-id to attach"));
681
 
682
  dummy = args;
683
  pid = strtol (args, &dummy, 0);
684
  if (pid == 0 && args == dummy)
685
    error (_("Illegal process-id: %s."), args);
686
 
687
  if (pid == getpid ())         /* Trying to masturbate?  */
688
    error (_("I refuse to debug myself!"));
689
 
690
  if (from_tty)
691
    {
692
      exec_file = get_exec_file (0);
693
 
694
      if (exec_file)
695
        printf_unfiltered (_("Attaching to program: %s, %s\n"), exec_file,
696
                           target_pid_to_str (pid_to_ptid (pid)));
697
      else
698
        printf_unfiltered (_("Attaching to %s\n"),
699
                           target_pid_to_str (pid_to_ptid (pid)));
700
 
701
      gdb_flush (gdb_stdout);
702
    }
703
 
704
  gdb_assert (inf_ttrace_num_lwps == 0);
705
  gdb_assert (inf_ttrace_num_lwps_in_syscall == 0);
706
  gdb_assert (inf_ttrace_vfork_ppid == -1);
707
 
708
  if (ttrace (TT_PROC_ATTACH, pid, 0, TT_KILL_ON_EXIT, TT_VERSION, 0) == -1)
709
    perror_with_name (("ttrace"));
710
  attach_flag = 1;
711
 
712
  /* Set the initial event mask.  */
713
  memset (&tte, 0, sizeof (tte));
714
  tte.tte_events |= TTEVT_EXEC | TTEVT_EXIT | TTEVT_FORK | TTEVT_VFORK;
715
  tte.tte_events |= TTEVT_LWP_CREATE | TTEVT_LWP_EXIT | TTEVT_LWP_TERMINATE;
716
#ifdef TTEVT_BPT_SSTEP
717
  tte.tte_events |= TTEVT_BPT_SSTEP;
718
#endif
719
  tte.tte_opts |= TTEO_PROC_INHERIT;
720
  if (ttrace (TT_PROC_SET_EVENT_MASK, pid, 0,
721
              (uintptr_t)&tte, sizeof tte, 0) == -1)
722
    perror_with_name (("ttrace"));
723
 
724
  inferior_ptid = pid_to_ptid (pid);
725
  push_target (ttrace_ops_hack);
726
}
727
 
728
static void
729
inf_ttrace_detach (char *args, int from_tty)
730
{
731
  pid_t pid = ptid_get_pid (inferior_ptid);
732
  int sig = 0;
733
 
734
  if (from_tty)
735
    {
736
      char *exec_file = get_exec_file (0);
737
      if (exec_file == 0)
738
        exec_file = "";
739
      printf_unfiltered (_("Detaching from program: %s, %s\n"), exec_file,
740
                         target_pid_to_str (pid_to_ptid (pid)));
741
      gdb_flush (gdb_stdout);
742
    }
743
  if (args)
744
    sig = atoi (args);
745
 
746
  /* ??? The HP-UX 11.0 ttrace(2) manual page doesn't mention that we
747
     can pass a signal number here.  Does this really work?  */
748
  if (ttrace (TT_PROC_DETACH, pid, 0, 0, sig, 0) == -1)
749
    perror_with_name (("ttrace"));
750
 
751
  if (inf_ttrace_vfork_ppid != -1)
752
    {
753
      if (ttrace (TT_PROC_DETACH, inf_ttrace_vfork_ppid, 0, 0, 0, 0) == -1)
754
        perror_with_name (("ttrace"));
755
      inf_ttrace_vfork_ppid = -1;
756
    }
757
 
758
  inf_ttrace_num_lwps = 0;
759
  inf_ttrace_num_lwps_in_syscall = 0;
760
 
761
  unpush_target (ttrace_ops_hack);
762
  inferior_ptid = null_ptid;
763
}
764
 
765
static void
766
inf_ttrace_kill (void)
767
{
768
  pid_t pid = ptid_get_pid (inferior_ptid);
769
 
770
  if (pid == 0)
771
    return;
772
 
773
  if (ttrace (TT_PROC_EXIT, pid, 0, 0, 0, 0) == -1)
774
    perror_with_name (("ttrace"));
775
  /* ??? Is it necessary to call ttrace_wait() here?  */
776
 
777
  if (inf_ttrace_vfork_ppid != -1)
778
    {
779
      if (ttrace (TT_PROC_DETACH, inf_ttrace_vfork_ppid, 0, 0, 0, 0) == -1)
780
        perror_with_name (("ttrace"));
781
      inf_ttrace_vfork_ppid = -1;
782
    }
783
 
784
  target_mourn_inferior ();
785
}
786
 
787
static int
788
inf_ttrace_resume_callback (struct thread_info *info, void *arg)
789
{
790
  if (!ptid_equal (info->ptid, inferior_ptid))
791
    {
792
      pid_t pid = ptid_get_pid (info->ptid);
793
      lwpid_t lwpid = ptid_get_lwp (info->ptid);
794
 
795
      if (ttrace (TT_LWP_CONTINUE, pid, lwpid, TT_NOPC, 0, 0) == -1)
796
        perror_with_name (("ttrace"));
797
    }
798
 
799
  return 0;
800
}
801
 
802
static int
803
inf_ttrace_delete_dying_threads_callback (struct thread_info *info, void *arg)
804
{
805
  if (((struct inf_ttrace_private_thread_info *)info->private)->dying == 1)
806
    delete_thread (info->ptid);
807
  return 0;
808
}
809
 
810
static void
811
inf_ttrace_resume (ptid_t ptid, int step, enum target_signal signal)
812
{
813
  pid_t pid = ptid_get_pid (ptid);
814
  lwpid_t lwpid = ptid_get_lwp (ptid);
815
  ttreq_t request = step ? TT_LWP_SINGLE : TT_LWP_CONTINUE;
816
  int sig = target_signal_to_host (signal);
817
 
818
  if (pid == -1)
819
    {
820
      pid = ptid_get_pid (inferior_ptid);
821
      lwpid = ptid_get_lwp (inferior_ptid);
822
    }
823
 
824
  if (ttrace (request, pid, lwpid, TT_NOPC, sig, 0) == -1)
825
    perror_with_name (("ttrace"));
826
 
827
  if (ptid_equal (ptid, minus_one_ptid) && inf_ttrace_num_lwps > 0)
828
    {
829
      /* Let all the other threads run too.  */
830
      iterate_over_threads (inf_ttrace_resume_callback, NULL);
831
      iterate_over_threads (inf_ttrace_delete_dying_threads_callback, NULL);
832
    }
833
}
834
 
835
static ptid_t
836
inf_ttrace_wait (ptid_t ptid, struct target_waitstatus *ourstatus)
837
{
838
  pid_t pid = ptid_get_pid (ptid);
839
  lwpid_t lwpid = ptid_get_lwp (ptid);
840
  ttstate_t tts;
841
  struct thread_info *ti;
842
 
843
  /* Until proven otherwise.  */
844
  ourstatus->kind = TARGET_WAITKIND_SPURIOUS;
845
 
846
  if (pid == -1)
847
    pid = lwpid = 0;
848
 
849
  gdb_assert (pid != 0 || lwpid == 0);
850
 
851
  do
852
    {
853
      set_sigint_trap ();
854
      set_sigio_trap ();
855
 
856
      if (ttrace_wait (pid, lwpid, TTRACE_WAITOK, &tts, sizeof tts) == -1)
857
        perror_with_name (("ttrace_wait"));
858
 
859
      if (tts.tts_event == TTEVT_VFORK && tts.tts_u.tts_fork.tts_isparent)
860
        {
861
          if (inf_ttrace_vfork_ppid != -1)
862
            {
863
              gdb_assert (inf_ttrace_vfork_ppid == tts.tts_pid);
864
 
865
              if (ttrace (TT_PROC_DETACH, tts.tts_pid, 0, 0, 0, 0) == -1)
866
                perror_with_name (("ttrace"));
867
              inf_ttrace_vfork_ppid = -1;
868
            }
869
 
870
          tts.tts_event = TTEVT_NONE;
871
        }
872
 
873
      clear_sigio_trap ();
874
      clear_sigint_trap ();
875
    }
876
  while (tts.tts_event == TTEVT_NONE);
877
 
878
  /* Now that we've waited, we can re-enable the page protections.  */
879
  if (inf_ttrace_reenable_page_protections)
880
    {
881
      gdb_assert (inf_ttrace_num_lwps_in_syscall == 0);
882
      inf_ttrace_enable_page_protections (tts.tts_pid);
883
      inf_ttrace_reenable_page_protections = 0;
884
    }
885
 
886
  ptid = ptid_build (tts.tts_pid, tts.tts_lwpid, 0);
887
 
888
  switch (tts.tts_event)
889
    {
890
#ifdef TTEVT_BPT_SSTEP
891
    case TTEVT_BPT_SSTEP:
892
      /* Make it look like a breakpoint.  */
893
      ourstatus->kind = TARGET_WAITKIND_STOPPED;
894
      ourstatus->value.sig = TARGET_SIGNAL_TRAP;
895
      break;
896
#endif
897
 
898
    case TTEVT_EXEC:
899
      ourstatus->kind = TARGET_WAITKIND_EXECD;
900
      ourstatus->value.execd_pathname =
901
        xmalloc (tts.tts_u.tts_exec.tts_pathlen + 1);
902
      if (ttrace (TT_PROC_GET_PATHNAME, tts.tts_pid, 0,
903
                  (uintptr_t)ourstatus->value.execd_pathname,
904
                  tts.tts_u.tts_exec.tts_pathlen, 0) == -1)
905
        perror_with_name (("ttrace"));
906
      ourstatus->value.execd_pathname[tts.tts_u.tts_exec.tts_pathlen] = 0;
907
      break;
908
 
909
    case TTEVT_EXIT:
910
      store_waitstatus (ourstatus, tts.tts_u.tts_exit.tts_exitcode);
911
      inf_ttrace_num_lwps = 0;
912
      break;
913
 
914
    case TTEVT_FORK:
915
      ourstatus->kind = TARGET_WAITKIND_FORKED;
916
      ourstatus->value.related_pid = tts.tts_u.tts_fork.tts_fpid;
917
 
918
      /* Make sure the other end of the fork is stopped too.  */
919
      if (ttrace_wait (tts.tts_u.tts_fork.tts_fpid,
920
                       tts.tts_u.tts_fork.tts_flwpid,
921
                       TTRACE_WAITOK, &tts, sizeof tts) == -1)
922
        perror_with_name (("ttrace_wait"));
923
 
924
      gdb_assert (tts.tts_event == TTEVT_FORK);
925
      if (tts.tts_u.tts_fork.tts_isparent)
926
        {
927
          ptid = ptid_build (tts.tts_pid, tts.tts_lwpid, 0);
928
          ourstatus->value.related_pid = tts.tts_u.tts_fork.tts_fpid;
929
        }
930
      break;
931
 
932
    case TTEVT_VFORK:
933
      gdb_assert (!tts.tts_u.tts_fork.tts_isparent);
934
 
935
      ourstatus->kind = TARGET_WAITKIND_VFORKED;
936
      ourstatus->value.related_pid = tts.tts_u.tts_fork.tts_fpid;
937
 
938
      /* HACK: To avoid touching the parent during the vfork, switch
939
         away from it.  */
940
      inferior_ptid = ptid;
941
      break;
942
 
943
    case TTEVT_LWP_CREATE:
944
      lwpid = tts.tts_u.tts_thread.tts_target_lwpid;
945
      ptid = ptid_build (tts.tts_pid, lwpid, 0);
946
      if (inf_ttrace_num_lwps == 0)
947
        {
948
          /* Now that we're going to be multi-threaded, add the
949
             original thread to the list first.  */
950
          ti = add_thread (ptid_build (tts.tts_pid, tts.tts_lwpid, 0));
951
          ti->private =
952
            xmalloc (sizeof (struct inf_ttrace_private_thread_info));
953
          memset (ti->private, 0,
954
                  sizeof (struct inf_ttrace_private_thread_info));
955
          inf_ttrace_num_lwps++;
956
        }
957
      ti = add_thread (ptid);
958
      ti->private =
959
        xmalloc (sizeof (struct inf_ttrace_private_thread_info));
960
      memset (ti->private, 0,
961
              sizeof (struct inf_ttrace_private_thread_info));
962
      inf_ttrace_num_lwps++;
963
      ptid = ptid_build (tts.tts_pid, tts.tts_lwpid, 0);
964
      break;
965
 
966
    case TTEVT_LWP_EXIT:
967
      printf_filtered(_("[%s exited]\n"), target_pid_to_str (ptid));
968
      ti = find_thread_pid (ptid);
969
      gdb_assert (ti != NULL);
970
      ((struct inf_ttrace_private_thread_info *)ti->private)->dying = 1;
971
      inf_ttrace_num_lwps--;
972
      ttrace (TT_LWP_CONTINUE, ptid_get_pid (ptid),
973
              ptid_get_lwp (ptid), TT_NOPC, 0, 0);
974
      /* If we don't return -1 here, core GDB will re-add the thread.  */
975
      ptid = minus_one_ptid;
976
      break;
977
 
978
    case TTEVT_LWP_TERMINATE:
979
      lwpid = tts.tts_u.tts_thread.tts_target_lwpid;
980
      ptid = ptid_build (tts.tts_pid, lwpid, 0);
981
      printf_filtered(_("[%s has been terminated]\n"), target_pid_to_str (ptid));
982
      ti = find_thread_pid (ptid);
983
      gdb_assert (ti != NULL);
984
      ((struct inf_ttrace_private_thread_info *)ti->private)->dying = 1;
985
      inf_ttrace_num_lwps--;
986
      ptid = ptid_build (tts.tts_pid, tts.tts_lwpid, 0);
987
      break;
988
 
989
    case TTEVT_SIGNAL:
990
      ourstatus->kind = TARGET_WAITKIND_STOPPED;
991
      ourstatus->value.sig =
992
        target_signal_from_host (tts.tts_u.tts_signal.tts_signo);
993
      break;
994
 
995
    case TTEVT_SYSCALL_ENTRY:
996
      gdb_assert (inf_ttrace_reenable_page_protections == 0);
997
      inf_ttrace_num_lwps_in_syscall++;
998
      if (inf_ttrace_num_lwps_in_syscall == 1)
999
        {
1000
          /* A thread has just entered a system call.  Disable any
1001
             page protections as the kernel can't deal with them.  */
1002
          inf_ttrace_disable_page_protections (tts.tts_pid);
1003
        }
1004
      ourstatus->kind = TARGET_WAITKIND_SYSCALL_ENTRY;
1005
      ourstatus->value.syscall_id = tts.tts_scno;
1006
      break;
1007
 
1008
    case TTEVT_SYSCALL_RETURN:
1009
      if (inf_ttrace_num_lwps_in_syscall > 0)
1010
        {
1011
          /* If the last thread has just left the system call, this
1012
             would be a logical place to re-enable the page
1013
             protections, but that doesn't work.  We can't re-enable
1014
             them until we've done another wait.  */
1015
          inf_ttrace_reenable_page_protections =
1016
            (inf_ttrace_num_lwps_in_syscall == 1);
1017
          inf_ttrace_num_lwps_in_syscall--;
1018
        }
1019
      ourstatus->kind = TARGET_WAITKIND_SYSCALL_RETURN;
1020
      ourstatus->value.syscall_id = tts.tts_scno;
1021
      break;
1022
 
1023
    default:
1024
      gdb_assert (!"Unexpected ttrace event");
1025
      break;
1026
    }
1027
 
1028
  /* Make sure all threads within the process are stopped.  */
1029
  if (ttrace (TT_PROC_STOP, tts.tts_pid, 0, 0, 0, 0) == -1)
1030
    perror_with_name (("ttrace"));
1031
 
1032
  /* HACK: Twiddle INFERIOR_PTID such that the initial thread of a
1033
     process isn't recognized as a new thread.  */
1034
  if (ptid_get_lwp (inferior_ptid) == 0)
1035
    inferior_ptid = ptid;
1036
 
1037
  return ptid;
1038
}
1039
 
1040
/* Transfer LEN bytes from ADDR in the inferior's memory into READBUF,
1041
   and transfer LEN bytes from WRITEBUF into the inferior's memory at
1042
   ADDR.  Either READBUF or WRITEBUF may be null, in which case the
1043
   corresponding transfer doesn't happen.  Return the number of bytes
1044
   actually transferred (which may be zero if an error occurs).  */
1045
 
1046
static LONGEST
1047
inf_ttrace_xfer_memory (CORE_ADDR addr, ULONGEST len,
1048
                        void *readbuf, const void *writebuf)
1049
{
1050
  pid_t pid = ptid_get_pid (inferior_ptid);
1051
 
1052
  /* HP-UX treats text space and data space differently.  GDB however,
1053
     doesn't really know the difference.  Therefore we try both.  Try
1054
     text space before data space though because when we're writing
1055
     into text space the instruction cache might need to be flushed.  */
1056
 
1057
  if (readbuf
1058
      && ttrace (TT_PROC_RDTEXT, pid, 0, addr, len, (uintptr_t)readbuf) == -1
1059
      && ttrace (TT_PROC_RDDATA, pid, 0, addr, len, (uintptr_t)readbuf) == -1)
1060
    return 0;
1061
 
1062
  if (writebuf
1063
      && ttrace (TT_PROC_WRTEXT, pid, 0, addr, len, (uintptr_t)writebuf) == -1
1064
      && ttrace (TT_PROC_WRDATA, pid, 0, addr, len, (uintptr_t)writebuf) == -1)
1065
    return 0;
1066
 
1067
  return len;
1068
}
1069
 
1070
static LONGEST
1071
inf_ttrace_xfer_partial (struct target_ops *ops, enum target_object object,
1072
                         const char *annex, gdb_byte *readbuf,
1073
                         const gdb_byte *writebuf, ULONGEST offset, LONGEST len)
1074
{
1075
  switch (object)
1076
    {
1077
    case TARGET_OBJECT_MEMORY:
1078
      return inf_ttrace_xfer_memory (offset, len, readbuf, writebuf);
1079
 
1080
    case TARGET_OBJECT_UNWIND_TABLE:
1081
      return -1;
1082
 
1083
    case TARGET_OBJECT_AUXV:
1084
      return -1;
1085
 
1086
    case TARGET_OBJECT_WCOOKIE:
1087
      return -1;
1088
 
1089
    default:
1090
      return -1;
1091
    }
1092
}
1093
 
1094
/* Print status information about what we're accessing.  */
1095
 
1096
static void
1097
inf_ttrace_files_info (struct target_ops *ignore)
1098
{
1099
  printf_filtered (_("\tUsing the running image of %s %s.\n"),
1100
                   attach_flag ? "attached" : "child",
1101
                   target_pid_to_str (inferior_ptid));
1102
}
1103
 
1104
static int
1105
inf_ttrace_thread_alive (ptid_t ptid)
1106
{
1107
  struct thread_info *ti;
1108
  ti = find_thread_pid (ptid);
1109
  return !(((struct inf_ttrace_private_thread_info *)ti->private)->dying);
1110
}
1111
 
1112
static char *
1113
inf_ttrace_pid_to_str (ptid_t ptid)
1114
{
1115
  if (inf_ttrace_num_lwps > 0)
1116
    {
1117
      pid_t pid = ptid_get_pid (ptid);
1118
      lwpid_t lwpid = ptid_get_lwp (ptid);
1119
      static char buf[128];
1120
 
1121
      xsnprintf (buf, sizeof buf, "process %ld, lwp %ld",
1122
                 (long)pid, (long)lwpid);
1123
      return buf;
1124
    }
1125
 
1126
  return normal_pid_to_str (ptid);
1127
}
1128
 
1129
 
1130
struct target_ops *
1131
inf_ttrace_target (void)
1132
{
1133
  struct target_ops *t = inf_child_target ();
1134
 
1135
  t->to_attach = inf_ttrace_attach;
1136
  t->to_detach = inf_ttrace_detach;
1137
  t->to_resume = inf_ttrace_resume;
1138
  t->to_wait = inf_ttrace_wait;
1139
  t->to_files_info = inf_ttrace_files_info;
1140
  t->to_can_use_hw_breakpoint = inf_ttrace_can_use_hw_breakpoint;
1141
  t->to_insert_watchpoint = inf_ttrace_insert_watchpoint;
1142
  t->to_remove_watchpoint = inf_ttrace_remove_watchpoint;
1143
  t->to_stopped_by_watchpoint = inf_ttrace_stopped_by_watchpoint;
1144
  t->to_region_ok_for_hw_watchpoint =
1145
    inf_ttrace_region_ok_for_hw_watchpoint;
1146
  t->to_kill = inf_ttrace_kill;
1147
  t->to_create_inferior = inf_ttrace_create_inferior;
1148
  t->to_follow_fork = inf_ttrace_follow_fork;
1149
  t->to_mourn_inferior = inf_ttrace_mourn_inferior;
1150
  t->to_thread_alive = inf_ttrace_thread_alive;
1151
  t->to_pid_to_str = inf_ttrace_pid_to_str;
1152
  t->to_xfer_partial = inf_ttrace_xfer_partial;
1153
 
1154
  ttrace_ops_hack = t;
1155
  return t;
1156
}
1157
#endif
1158
 
1159
 
1160
/* Prevent warning from -Wmissing-prototypes.  */
1161
void _initialize_hppa_hpux_nat (void);
1162
 
1163
void
1164
_initialize_inf_ttrace (void)
1165
{
1166
#ifdef HAVE_TTRACE
1167
  inf_ttrace_page_dict.pagesize = getpagesize();
1168
#endif
1169
}

powered by: WebSVN 2.1.0

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