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

Subversion Repositories openrisc_me

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

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 227 jeremybenn
/* Low-level child interface to ptrace.
2
 
3
   Copyright (C) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1998,
4
   1999, 2000, 2001, 2002, 2004, 2005, 2006, 2007, 2008, 2009, 2010
5
   Free Software Foundation, Inc.
6
 
7
   This file is part of GDB.
8
 
9
   This program is free software; you can redistribute it and/or modify
10
   it under the terms of the GNU General Public License as published by
11
   the Free Software Foundation; either version 3 of the License, or
12
   (at your option) any later version.
13
 
14
   This program is distributed in the hope that it will be useful,
15
   but WITHOUT ANY WARRANTY; without even the implied warranty of
16
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17
   GNU General Public License for more details.
18
 
19
   You should have received a copy of the GNU General Public License
20
   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
21
 
22
#include "defs.h"
23
#include "command.h"
24
#include "inferior.h"
25
#include "inflow.h"
26
#include "terminal.h"
27
#include "gdbcore.h"
28
#include "regcache.h"
29
 
30
#include "gdb_assert.h"
31
#include "gdb_string.h"
32
#include "gdb_ptrace.h"
33
#include "gdb_wait.h"
34
#include <signal.h>
35
 
36
#include "inf-ptrace.h"
37
#include "inf-child.h"
38
#include "gdbthread.h"
39
 
40
 
41
 
42
#ifdef PT_GET_PROCESS_STATE
43
 
44
static int
45
inf_ptrace_follow_fork (struct target_ops *ops, int follow_child)
46
{
47
  pid_t pid, fpid;
48
  ptrace_state_t pe;
49
 
50
  pid = ptid_get_pid (inferior_ptid);
51
 
52
  if (ptrace (PT_GET_PROCESS_STATE, pid,
53
               (PTRACE_TYPE_ARG3)&pe, sizeof pe) == -1)
54
    perror_with_name (("ptrace"));
55
 
56
  gdb_assert (pe.pe_report_event == PTRACE_FORK);
57
  fpid = pe.pe_other_pid;
58
 
59
  if (follow_child)
60
    {
61
      struct inferior *parent_inf, *child_inf;
62
      struct thread_info *tp;
63
 
64
      parent_inf = find_inferior_pid (pid);
65
 
66
      /* Add the child.  */
67
      child_inf = add_inferior (fpid);
68
      child_inf->attach_flag = parent_inf->attach_flag;
69
      copy_terminal_info (child_inf, parent_inf);
70
      child_inf->pspace = parent_inf->pspace;
71
      child_inf->aspace = parent_inf->aspace;
72
 
73
      /* Before detaching from the parent, remove all breakpoints from
74
         it.  */
75
      remove_breakpoints ();
76
 
77
      if (ptrace (PT_DETACH, pid, (PTRACE_TYPE_ARG3)1, 0) == -1)
78
        perror_with_name (("ptrace"));
79
 
80
      /* Switch inferior_ptid out of the parent's way.  */
81
      inferior_ptid = pid_to_ptid (fpid);
82
 
83
      /* Delete the parent.  */
84
      detach_inferior (pid);
85
 
86
      add_thread_silent (inferior_ptid);
87
    }
88
  else
89
    {
90
      /* Breakpoints have already been detached from the child by
91
         infrun.c.  */
92
 
93
      if (ptrace (PT_DETACH, fpid, (PTRACE_TYPE_ARG3)1, 0) == -1)
94
        perror_with_name (("ptrace"));
95
    }
96
 
97
  return 0;
98
}
99
 
100
#endif /* PT_GET_PROCESS_STATE */
101
 
102
 
103
/* Prepare to be traced.  */
104
 
105
static void
106
inf_ptrace_me (void)
107
{
108
  /* "Trace me, Dr. Memory!"  */
109
  ptrace (PT_TRACE_ME, 0, (PTRACE_TYPE_ARG3)0, 0);
110
}
111
 
112
/* Start a new inferior Unix child process.  EXEC_FILE is the file to
113
   run, ALLARGS is a string containing the arguments to the program.
114
   ENV is the environment vector to pass.  If FROM_TTY is non-zero, be
115
   chatty about it.  */
116
 
117
static void
118
inf_ptrace_create_inferior (struct target_ops *ops,
119
                            char *exec_file, char *allargs, char **env,
120
                            int from_tty)
121
{
122
  int pid;
123
 
124
  pid = fork_inferior (exec_file, allargs, env, inf_ptrace_me, NULL,
125
                       NULL, NULL);
126
 
127
  push_target (ops);
128
 
129
  /* On some targets, there must be some explicit synchronization
130
     between the parent and child processes after the debugger
131
     forks, and before the child execs the debuggee program.  This
132
     call basically gives permission for the child to exec.  */
133
 
134
  target_acknowledge_created_inferior (pid);
135
 
136
  /* START_INFERIOR_TRAPS_EXPECTED is defined in inferior.h, and will
137
     be 1 or 2 depending on whether we're starting without or with a
138
     shell.  */
139
  startup_inferior (START_INFERIOR_TRAPS_EXPECTED);
140
 
141
  /* On some targets, there must be some explicit actions taken after
142
     the inferior has been started up.  */
143
  target_post_startup_inferior (pid_to_ptid (pid));
144
}
145
 
146
#ifdef PT_GET_PROCESS_STATE
147
 
148
static void
149
inf_ptrace_post_startup_inferior (ptid_t pid)
150
{
151
  ptrace_event_t pe;
152
 
153
  /* Set the initial event mask.  */
154
  memset (&pe, 0, sizeof pe);
155
  pe.pe_set_event |= PTRACE_FORK;
156
  if (ptrace (PT_SET_EVENT_MASK, ptid_get_pid (pid),
157
              (PTRACE_TYPE_ARG3)&pe, sizeof pe) == -1)
158
    perror_with_name (("ptrace"));
159
}
160
 
161
#endif
162
 
163
/* Clean up a rotting corpse of an inferior after it died.  */
164
 
165
static void
166
inf_ptrace_mourn_inferior (struct target_ops *ops)
167
{
168
  int status;
169
 
170
  /* Wait just one more time to collect the inferior's exit status.
171
     Do not check whether this succeeds though, since we may be
172
     dealing with a process that we attached to.  Such a process will
173
     only report its exit status to its original parent.  */
174
  waitpid (ptid_get_pid (inferior_ptid), &status, 0);
175
 
176
  generic_mourn_inferior ();
177
 
178
  if (!have_inferiors ())
179
    unpush_target (ops);
180
}
181
 
182
/* Attach to the process specified by ARGS.  If FROM_TTY is non-zero,
183
   be chatty about it.  */
184
 
185
static void
186
inf_ptrace_attach (struct target_ops *ops, char *args, int from_tty)
187
{
188
  char *exec_file;
189
  pid_t pid;
190
  struct inferior *inf;
191
 
192
  pid = parse_pid_to_attach (args);
193
 
194
  if (pid == getpid ())         /* Trying to masturbate?  */
195
    error (_("I refuse to debug myself!"));
196
 
197
  if (from_tty)
198
    {
199
      exec_file = get_exec_file (0);
200
 
201
      if (exec_file)
202
        printf_unfiltered (_("Attaching to program: %s, %s\n"), exec_file,
203
                           target_pid_to_str (pid_to_ptid (pid)));
204
      else
205
        printf_unfiltered (_("Attaching to %s\n"),
206
                           target_pid_to_str (pid_to_ptid (pid)));
207
 
208
      gdb_flush (gdb_stdout);
209
    }
210
 
211
#ifdef PT_ATTACH
212
  errno = 0;
213
  ptrace (PT_ATTACH, pid, (PTRACE_TYPE_ARG3)0, 0);
214
  if (errno != 0)
215
    perror_with_name (("ptrace"));
216
#else
217
  error (_("This system does not support attaching to a process"));
218
#endif
219
 
220
  inf = current_inferior ();
221
  inferior_appeared (inf, pid);
222
  inf->attach_flag = 1;
223
  inferior_ptid = pid_to_ptid (pid);
224
 
225
  /* Always add a main thread.  If some target extends the ptrace
226
     target, it should decorate the ptid later with more info.  */
227
  add_thread_silent (inferior_ptid);
228
 
229
  push_target(ops);
230
}
231
 
232
#ifdef PT_GET_PROCESS_STATE
233
 
234
void
235
inf_ptrace_post_attach (int pid)
236
{
237
  ptrace_event_t pe;
238
 
239
  /* Set the initial event mask.  */
240
  memset (&pe, 0, sizeof pe);
241
  pe.pe_set_event |= PTRACE_FORK;
242
  if (ptrace (PT_SET_EVENT_MASK, pid,
243
              (PTRACE_TYPE_ARG3)&pe, sizeof pe) == -1)
244
    perror_with_name (("ptrace"));
245
}
246
 
247
#endif
248
 
249
/* Detach from the inferior, optionally passing it the signal
250
   specified by ARGS.  If FROM_TTY is non-zero, be chatty about it.  */
251
 
252
static void
253
inf_ptrace_detach (struct target_ops *ops, char *args, int from_tty)
254
{
255
  pid_t pid = ptid_get_pid (inferior_ptid);
256
  int sig = 0;
257
 
258
  if (from_tty)
259
    {
260
      char *exec_file = get_exec_file (0);
261
      if (exec_file == 0)
262
        exec_file = "";
263
      printf_unfiltered (_("Detaching from program: %s, %s\n"), exec_file,
264
                         target_pid_to_str (pid_to_ptid (pid)));
265
      gdb_flush (gdb_stdout);
266
    }
267
  if (args)
268
    sig = atoi (args);
269
 
270
#ifdef PT_DETACH
271
  /* We'd better not have left any breakpoints in the program or it'll
272
     die when it hits one.  Also note that this may only work if we
273
     previously attached to the inferior.  It *might* work if we
274
     started the process ourselves.  */
275
  errno = 0;
276
  ptrace (PT_DETACH, pid, (PTRACE_TYPE_ARG3)1, sig);
277
  if (errno != 0)
278
    perror_with_name (("ptrace"));
279
#else
280
  error (_("This system does not support detaching from a process"));
281
#endif
282
 
283
  inferior_ptid = null_ptid;
284
  detach_inferior (pid);
285
 
286
  if (!have_inferiors ())
287
    unpush_target (ops);
288
}
289
 
290
/* Kill the inferior.  */
291
 
292
static void
293
inf_ptrace_kill (struct target_ops *ops)
294
{
295
  pid_t pid = ptid_get_pid (inferior_ptid);
296
  int status;
297
 
298
  if (pid == 0)
299
    return;
300
 
301
  ptrace (PT_KILL, pid, (PTRACE_TYPE_ARG3)0, 0);
302
  waitpid (pid, &status, 0);
303
 
304
  target_mourn_inferior ();
305
}
306
 
307
/* Stop the inferior.  */
308
 
309
static void
310
inf_ptrace_stop (ptid_t ptid)
311
{
312
  /* Send a SIGINT to the process group.  This acts just like the user
313
     typed a ^C on the controlling terminal.  Note that using a
314
     negative process number in kill() is a System V-ism.  The proper
315
     BSD interface is killpg().  However, all modern BSDs support the
316
     System V interface too.  */
317
  kill (-inferior_process_group (), SIGINT);
318
}
319
 
320
/* Resume execution of thread PTID, or all threads if PTID is -1.  If
321
   STEP is nonzero, single-step it.  If SIGNAL is nonzero, give it
322
   that signal.  */
323
 
324
static void
325
inf_ptrace_resume (struct target_ops *ops,
326
                   ptid_t ptid, int step, enum target_signal signal)
327
{
328
  pid_t pid = ptid_get_pid (ptid);
329
  int request;
330
 
331
  if (pid == -1)
332
    /* Resume all threads.  Traditionally ptrace() only supports
333
       single-threaded processes, so simply resume the inferior.  */
334
    pid = ptid_get_pid (inferior_ptid);
335
 
336
  if (catch_syscall_enabled () > 0)
337
    request = PT_SYSCALL;
338
  else
339
    request = PT_CONTINUE;
340
 
341
  if (step)
342
    {
343
      /* If this system does not support PT_STEP, a higher level
344
         function will have called single_step() to transmute the step
345
         request into a continue request (by setting breakpoints on
346
         all possible successor instructions), so we don't have to
347
         worry about that here.  */
348
      request = PT_STEP;
349
    }
350
 
351
  /* An address of (PTRACE_TYPE_ARG3)1 tells ptrace to continue from
352
     where it was.  If GDB wanted it to start some other way, we have
353
     already written a new program counter value to the child.  */
354
  errno = 0;
355
  ptrace (request, pid, (PTRACE_TYPE_ARG3)1, target_signal_to_host (signal));
356
  if (errno != 0)
357
    perror_with_name (("ptrace"));
358
}
359
 
360
/* Wait for the child specified by PTID to do something.  Return the
361
   process ID of the child, or MINUS_ONE_PTID in case of error; store
362
   the status in *OURSTATUS.  */
363
 
364
static ptid_t
365
inf_ptrace_wait (struct target_ops *ops,
366
                 ptid_t ptid, struct target_waitstatus *ourstatus, int options)
367
{
368
  pid_t pid;
369
  int status, save_errno;
370
 
371
  do
372
    {
373
      set_sigint_trap ();
374
 
375
      do
376
        {
377
          pid = waitpid (ptid_get_pid (ptid), &status, 0);
378
          save_errno = errno;
379
        }
380
      while (pid == -1 && errno == EINTR);
381
 
382
      clear_sigint_trap ();
383
 
384
      if (pid == -1)
385
        {
386
          fprintf_unfiltered (gdb_stderr,
387
                              _("Child process unexpectedly missing: %s.\n"),
388
                              safe_strerror (save_errno));
389
 
390
          /* Claim it exited with unknown signal.  */
391
          ourstatus->kind = TARGET_WAITKIND_SIGNALLED;
392
          ourstatus->value.sig = TARGET_SIGNAL_UNKNOWN;
393
          return inferior_ptid;
394
        }
395
 
396
      /* Ignore terminated detached child processes.  */
397
      if (!WIFSTOPPED (status) && pid != ptid_get_pid (inferior_ptid))
398
        pid = -1;
399
    }
400
  while (pid == -1);
401
 
402
#ifdef PT_GET_PROCESS_STATE
403
  if (WIFSTOPPED (status))
404
    {
405
      ptrace_state_t pe;
406
      pid_t fpid;
407
 
408
      if (ptrace (PT_GET_PROCESS_STATE, pid,
409
                  (PTRACE_TYPE_ARG3)&pe, sizeof pe) == -1)
410
        perror_with_name (("ptrace"));
411
 
412
      switch (pe.pe_report_event)
413
        {
414
        case PTRACE_FORK:
415
          ourstatus->kind = TARGET_WAITKIND_FORKED;
416
          ourstatus->value.related_pid = pid_to_ptid (pe.pe_other_pid);
417
 
418
          /* Make sure the other end of the fork is stopped too.  */
419
          fpid = waitpid (pe.pe_other_pid, &status, 0);
420
          if (fpid == -1)
421
            perror_with_name (("waitpid"));
422
 
423
          if (ptrace (PT_GET_PROCESS_STATE, fpid,
424
                      (PTRACE_TYPE_ARG3)&pe, sizeof pe) == -1)
425
            perror_with_name (("ptrace"));
426
 
427
          gdb_assert (pe.pe_report_event == PTRACE_FORK);
428
          gdb_assert (pe.pe_other_pid == pid);
429
          if (fpid == ptid_get_pid (inferior_ptid))
430
            {
431
              ourstatus->value.related_pid = pid_to_ptid (pe.pe_other_pid);
432
              return pid_to_ptid (fpid);
433
            }
434
 
435
          return pid_to_ptid (pid);
436
        }
437
    }
438
#endif
439
 
440
  store_waitstatus (ourstatus, status);
441
  return pid_to_ptid (pid);
442
}
443
 
444
/* Attempt a transfer all LEN bytes starting at OFFSET between the
445
   inferior's OBJECT:ANNEX space and GDB's READBUF/WRITEBUF buffer.
446
   Return the number of bytes actually transferred.  */
447
 
448
static LONGEST
449
inf_ptrace_xfer_partial (struct target_ops *ops, enum target_object object,
450
                         const char *annex, gdb_byte *readbuf,
451
                         const gdb_byte *writebuf,
452
                         ULONGEST offset, LONGEST len)
453
{
454
  pid_t pid = ptid_get_pid (inferior_ptid);
455
 
456
  switch (object)
457
    {
458
    case TARGET_OBJECT_MEMORY:
459
#ifdef PT_IO
460
      /* OpenBSD 3.1, NetBSD 1.6 and FreeBSD 5.0 have a new PT_IO
461
         request that promises to be much more efficient in reading
462
         and writing data in the traced process's address space.  */
463
      {
464
        struct ptrace_io_desc piod;
465
 
466
        /* NOTE: We assume that there are no distinct address spaces
467
           for instruction and data.  However, on OpenBSD 3.9 and
468
           later, PIOD_WRITE_D doesn't allow changing memory that's
469
           mapped read-only.  Since most code segments will be
470
           read-only, using PIOD_WRITE_D will prevent us from
471
           inserting breakpoints, so we use PIOD_WRITE_I instead.  */
472
        piod.piod_op = writebuf ? PIOD_WRITE_I : PIOD_READ_D;
473
        piod.piod_addr = writebuf ? (void *) writebuf : readbuf;
474
        piod.piod_offs = (void *) (long) offset;
475
        piod.piod_len = len;
476
 
477
        errno = 0;
478
        if (ptrace (PT_IO, pid, (caddr_t)&piod, 0) == 0)
479
          /* Return the actual number of bytes read or written.  */
480
          return piod.piod_len;
481
        /* If the PT_IO request is somehow not supported, fallback on
482
           using PT_WRITE_D/PT_READ_D.  Otherwise we will return zero
483
           to indicate failure.  */
484
        if (errno != EINVAL)
485
          return 0;
486
      }
487
#endif
488
      {
489
        union
490
        {
491
          PTRACE_TYPE_RET word;
492
          gdb_byte byte[sizeof (PTRACE_TYPE_RET)];
493
        } buffer;
494
        ULONGEST rounded_offset;
495
        LONGEST partial_len;
496
 
497
        /* Round the start offset down to the next long word
498
           boundary.  */
499
        rounded_offset = offset & -(ULONGEST) sizeof (PTRACE_TYPE_RET);
500
 
501
        /* Since ptrace will transfer a single word starting at that
502
           rounded_offset the partial_len needs to be adjusted down to
503
           that (remember this function only does a single transfer).
504
           Should the required length be even less, adjust it down
505
           again.  */
506
        partial_len = (rounded_offset + sizeof (PTRACE_TYPE_RET)) - offset;
507
        if (partial_len > len)
508
          partial_len = len;
509
 
510
        if (writebuf)
511
          {
512
            /* If OFFSET:PARTIAL_LEN is smaller than
513
               ROUNDED_OFFSET:WORDSIZE then a read/modify write will
514
               be needed.  Read in the entire word.  */
515
            if (rounded_offset < offset
516
                || (offset + partial_len
517
                    < rounded_offset + sizeof (PTRACE_TYPE_RET)))
518
              /* Need part of initial word -- fetch it.  */
519
              buffer.word = ptrace (PT_READ_I, pid,
520
                                    (PTRACE_TYPE_ARG3)(uintptr_t)
521
                                    rounded_offset, 0);
522
 
523
            /* Copy data to be written over corresponding part of
524
               buffer.  */
525
            memcpy (buffer.byte + (offset - rounded_offset),
526
                    writebuf, partial_len);
527
 
528
            errno = 0;
529
            ptrace (PT_WRITE_D, pid,
530
                    (PTRACE_TYPE_ARG3)(uintptr_t)rounded_offset,
531
                    buffer.word);
532
            if (errno)
533
              {
534
                /* Using the appropriate one (I or D) is necessary for
535
                   Gould NP1, at least.  */
536
                errno = 0;
537
                ptrace (PT_WRITE_I, pid,
538
                        (PTRACE_TYPE_ARG3)(uintptr_t)rounded_offset,
539
                        buffer.word);
540
                if (errno)
541
                  return 0;
542
              }
543
          }
544
 
545
        if (readbuf)
546
          {
547
            errno = 0;
548
            buffer.word = ptrace (PT_READ_I, pid,
549
                                  (PTRACE_TYPE_ARG3)(uintptr_t)rounded_offset,
550
                                  0);
551
            if (errno)
552
              return 0;
553
            /* Copy appropriate bytes out of the buffer.  */
554
            memcpy (readbuf, buffer.byte + (offset - rounded_offset),
555
                    partial_len);
556
          }
557
 
558
        return partial_len;
559
      }
560
 
561
    case TARGET_OBJECT_UNWIND_TABLE:
562
      return -1;
563
 
564
    case TARGET_OBJECT_AUXV:
565
      return -1;
566
 
567
    case TARGET_OBJECT_WCOOKIE:
568
      return -1;
569
 
570
    default:
571
      return -1;
572
    }
573
}
574
 
575
/* Return non-zero if the thread specified by PTID is alive.  */
576
 
577
static int
578
inf_ptrace_thread_alive (struct target_ops *ops, ptid_t ptid)
579
{
580
  /* ??? Is kill the right way to do this?  */
581
  return (kill (ptid_get_pid (ptid), 0) != -1);
582
}
583
 
584
/* Print status information about what we're accessing.  */
585
 
586
static void
587
inf_ptrace_files_info (struct target_ops *ignore)
588
{
589
  struct inferior *inf = current_inferior ();
590
 
591
  printf_filtered (_("\tUsing the running image of %s %s.\n"),
592
                   inf->attach_flag ? "attached" : "child",
593
                   target_pid_to_str (inferior_ptid));
594
}
595
 
596
static char *
597
inf_ptrace_pid_to_str (struct target_ops *ops, ptid_t ptid)
598
{
599
  return normal_pid_to_str (ptid);
600
}
601
 
602
/* Create a prototype ptrace target.  The client can override it with
603
   local methods.  */
604
 
605
struct target_ops *
606
inf_ptrace_target (void)
607
{
608
  struct target_ops *t = inf_child_target ();
609
 
610
  t->to_attach = inf_ptrace_attach;
611
  t->to_detach = inf_ptrace_detach;
612
  t->to_resume = inf_ptrace_resume;
613
  t->to_wait = inf_ptrace_wait;
614
  t->to_files_info = inf_ptrace_files_info;
615
  t->to_kill = inf_ptrace_kill;
616
  t->to_create_inferior = inf_ptrace_create_inferior;
617
#ifdef PT_GET_PROCESS_STATE
618
  t->to_follow_fork = inf_ptrace_follow_fork;
619
  t->to_post_startup_inferior = inf_ptrace_post_startup_inferior;
620
  t->to_post_attach = inf_ptrace_post_attach;
621
#endif
622
  t->to_mourn_inferior = inf_ptrace_mourn_inferior;
623
  t->to_thread_alive = inf_ptrace_thread_alive;
624
  t->to_pid_to_str = inf_ptrace_pid_to_str;
625
  t->to_stop = inf_ptrace_stop;
626
  t->to_xfer_partial = inf_ptrace_xfer_partial;
627
 
628
  return t;
629
}
630
 
631
 
632
/* Pointer to a function that returns the offset within the user area
633
   where a particular register is stored.  */
634
static CORE_ADDR (*inf_ptrace_register_u_offset)(struct gdbarch *, int, int);
635
 
636
/* Fetch register REGNUM from the inferior.  */
637
 
638
static void
639
inf_ptrace_fetch_register (struct regcache *regcache, int regnum)
640
{
641
  struct gdbarch *gdbarch = get_regcache_arch (regcache);
642
  CORE_ADDR addr;
643
  size_t size;
644
  PTRACE_TYPE_RET *buf;
645
  int pid, i;
646
 
647
  /* This isn't really an address, but ptrace thinks of it as one.  */
648
  addr = inf_ptrace_register_u_offset (gdbarch, regnum, 0);
649
  if (addr == (CORE_ADDR)-1
650
      || gdbarch_cannot_fetch_register (gdbarch, regnum))
651
    {
652
      regcache_raw_supply (regcache, regnum, NULL);
653
      return;
654
    }
655
 
656
  /* Cater for systems like GNU/Linux, that implement threads as
657
     separate processes.  */
658
  pid = ptid_get_lwp (inferior_ptid);
659
  if (pid == 0)
660
    pid = ptid_get_pid (inferior_ptid);
661
 
662
  size = register_size (gdbarch, regnum);
663
  gdb_assert ((size % sizeof (PTRACE_TYPE_RET)) == 0);
664
  buf = alloca (size);
665
 
666
  /* Read the register contents from the inferior a chunk at a time.  */
667
  for (i = 0; i < size / sizeof (PTRACE_TYPE_RET); i++)
668
    {
669
      errno = 0;
670
      buf[i] = ptrace (PT_READ_U, pid, (PTRACE_TYPE_ARG3)(uintptr_t)addr, 0);
671
      if (errno != 0)
672
        error (_("Couldn't read register %s (#%d): %s."),
673
               gdbarch_register_name (gdbarch, regnum),
674
               regnum, safe_strerror (errno));
675
 
676
      addr += sizeof (PTRACE_TYPE_RET);
677
    }
678
  regcache_raw_supply (regcache, regnum, buf);
679
}
680
 
681
/* Fetch register REGNUM from the inferior.  If REGNUM is -1, do this
682
   for all registers.  */
683
 
684
static void
685
inf_ptrace_fetch_registers (struct target_ops *ops,
686
                            struct regcache *regcache, int regnum)
687
{
688
  if (regnum == -1)
689
    for (regnum = 0;
690
         regnum < gdbarch_num_regs (get_regcache_arch (regcache));
691
         regnum++)
692
      inf_ptrace_fetch_register (regcache, regnum);
693
  else
694
    inf_ptrace_fetch_register (regcache, regnum);
695
}
696
 
697
/* Store register REGNUM into the inferior.  */
698
 
699
static void
700
inf_ptrace_store_register (const struct regcache *regcache, int regnum)
701
{
702
  struct gdbarch *gdbarch = get_regcache_arch (regcache);
703
  CORE_ADDR addr;
704
  size_t size;
705
  PTRACE_TYPE_RET *buf;
706
  int pid, i;
707
 
708
  /* This isn't really an address, but ptrace thinks of it as one.  */
709
  addr = inf_ptrace_register_u_offset (gdbarch, regnum, 1);
710
  if (addr == (CORE_ADDR)-1
711
      || gdbarch_cannot_store_register (gdbarch, regnum))
712
    return;
713
 
714
  /* Cater for systems like GNU/Linux, that implement threads as
715
     separate processes.  */
716
  pid = ptid_get_lwp (inferior_ptid);
717
  if (pid == 0)
718
    pid = ptid_get_pid (inferior_ptid);
719
 
720
  size = register_size (gdbarch, regnum);
721
  gdb_assert ((size % sizeof (PTRACE_TYPE_RET)) == 0);
722
  buf = alloca (size);
723
 
724
  /* Write the register contents into the inferior a chunk at a time.  */
725
  regcache_raw_collect (regcache, regnum, buf);
726
  for (i = 0; i < size / sizeof (PTRACE_TYPE_RET); i++)
727
    {
728
      errno = 0;
729
      ptrace (PT_WRITE_U, pid, (PTRACE_TYPE_ARG3)(uintptr_t)addr, buf[i]);
730
      if (errno != 0)
731
        error (_("Couldn't write register %s (#%d): %s."),
732
               gdbarch_register_name (gdbarch, regnum),
733
               regnum, safe_strerror (errno));
734
 
735
      addr += sizeof (PTRACE_TYPE_RET);
736
    }
737
}
738
 
739
/* Store register REGNUM back into the inferior.  If REGNUM is -1, do
740
   this for all registers.  */
741
 
742
static void
743
inf_ptrace_store_registers (struct target_ops *ops,
744
                            struct regcache *regcache, int regnum)
745
{
746
  if (regnum == -1)
747
    for (regnum = 0;
748
         regnum < gdbarch_num_regs (get_regcache_arch (regcache));
749
         regnum++)
750
      inf_ptrace_store_register (regcache, regnum);
751
  else
752
    inf_ptrace_store_register (regcache, regnum);
753
}
754
 
755
/* Create a "traditional" ptrace target.  REGISTER_U_OFFSET should be
756
   a function returning the offset within the user area where a
757
   particular register is stored.  */
758
 
759
struct target_ops *
760
inf_ptrace_trad_target (CORE_ADDR (*register_u_offset)
761
                                        (struct gdbarch *, int, int))
762
{
763
  struct target_ops *t = inf_ptrace_target();
764
 
765
  gdb_assert (register_u_offset);
766
  inf_ptrace_register_u_offset = register_u_offset;
767
  t->to_fetch_registers = inf_ptrace_fetch_registers;
768
  t->to_store_registers = inf_ptrace_store_registers;
769
 
770
  return t;
771
}

powered by: WebSVN 2.1.0

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