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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-old/] [gdb-7.1/] [gdb/] [spu-linux-nat.c] - Blame information for rev 853

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

Line No. Rev Author Line
1 227 jeremybenn
/* SPU native-dependent code for GDB, the GNU debugger.
2
   Copyright (C) 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
3
 
4
   Contributed by Ulrich Weigand <uweigand@de.ibm.com>.
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
#include "gdbcore.h"
23
#include "gdb_string.h"
24
#include "target.h"
25
#include "inferior.h"
26
#include "inf-ptrace.h"
27
#include "regcache.h"
28
#include "symfile.h"
29
#include "gdb_wait.h"
30
#include "gdbthread.h"
31
 
32
#include <sys/ptrace.h>
33
#include <asm/ptrace.h>
34
#include <sys/types.h>
35
#include <sys/param.h>
36
 
37
#include "spu-tdep.h"
38
 
39
/* PPU side system calls.  */
40
#define INSTR_SC        0x44000002
41
#define NR_spu_run      0x0116
42
 
43
 
44
/* Fetch PPU register REGNO.  */
45
static ULONGEST
46
fetch_ppc_register (int regno)
47
{
48
  PTRACE_TYPE_RET res;
49
 
50
  int tid = TIDGET (inferior_ptid);
51
  if (tid == 0)
52
    tid = PIDGET (inferior_ptid);
53
 
54
#ifndef __powerpc64__
55
  /* If running as a 32-bit process on a 64-bit system, we attempt
56
     to get the full 64-bit register content of the target process.
57
     If the PPC special ptrace call fails, we're on a 32-bit system;
58
     just fall through to the regular ptrace call in that case.  */
59
  {
60
    gdb_byte buf[8];
61
 
62
    errno = 0;
63
    ptrace (PPC_PTRACE_PEEKUSR_3264, tid,
64
            (PTRACE_TYPE_ARG3) (regno * 8), buf);
65
    if (errno == 0)
66
      ptrace (PPC_PTRACE_PEEKUSR_3264, tid,
67
              (PTRACE_TYPE_ARG3) (regno * 8 + 4), buf + 4);
68
    if (errno == 0)
69
      return (ULONGEST) *(uint64_t *)buf;
70
  }
71
#endif
72
 
73
  errno = 0;
74
  res = ptrace (PT_READ_U, tid,
75
                (PTRACE_TYPE_ARG3) (regno * sizeof (PTRACE_TYPE_RET)), 0);
76
  if (errno != 0)
77
    {
78
      char mess[128];
79
      xsnprintf (mess, sizeof mess, "reading PPC register #%d", regno);
80
      perror_with_name (_(mess));
81
    }
82
 
83
  return (ULONGEST) (unsigned long) res;
84
}
85
 
86
/* Fetch WORD from PPU memory at (aligned) MEMADDR in thread TID.  */
87
static int
88
fetch_ppc_memory_1 (int tid, ULONGEST memaddr, PTRACE_TYPE_RET *word)
89
{
90
  errno = 0;
91
 
92
#ifndef __powerpc64__
93
  if (memaddr >> 32)
94
    {
95
      uint64_t addr_8 = (uint64_t) memaddr;
96
      ptrace (PPC_PTRACE_PEEKTEXT_3264, tid, (PTRACE_TYPE_ARG3) &addr_8, word);
97
    }
98
  else
99
#endif
100
    *word = ptrace (PT_READ_I, tid, (PTRACE_TYPE_ARG3) (size_t) memaddr, 0);
101
 
102
  return errno;
103
}
104
 
105
/* Store WORD into PPU memory at (aligned) MEMADDR in thread TID.  */
106
static int
107
store_ppc_memory_1 (int tid, ULONGEST memaddr, PTRACE_TYPE_RET word)
108
{
109
  errno = 0;
110
 
111
#ifndef __powerpc64__
112
  if (memaddr >> 32)
113
    {
114
      uint64_t addr_8 = (uint64_t) memaddr;
115
      ptrace (PPC_PTRACE_POKEDATA_3264, tid, (PTRACE_TYPE_ARG3) &addr_8, word);
116
    }
117
  else
118
#endif
119
    ptrace (PT_WRITE_D, tid, (PTRACE_TYPE_ARG3) (size_t) memaddr, word);
120
 
121
  return errno;
122
}
123
 
124
/* Fetch LEN bytes of PPU memory at MEMADDR to MYADDR.  */
125
static int
126
fetch_ppc_memory (ULONGEST memaddr, gdb_byte *myaddr, int len)
127
{
128
  int i, ret;
129
 
130
  ULONGEST addr = memaddr & -(ULONGEST) sizeof (PTRACE_TYPE_RET);
131
  int count = ((((memaddr + len) - addr) + sizeof (PTRACE_TYPE_RET) - 1)
132
               / sizeof (PTRACE_TYPE_RET));
133
  PTRACE_TYPE_RET *buffer;
134
 
135
  int tid = TIDGET (inferior_ptid);
136
  if (tid == 0)
137
    tid = PIDGET (inferior_ptid);
138
 
139
  buffer = (PTRACE_TYPE_RET *) alloca (count * sizeof (PTRACE_TYPE_RET));
140
  for (i = 0; i < count; i++, addr += sizeof (PTRACE_TYPE_RET))
141
    {
142
      ret = fetch_ppc_memory_1 (tid, addr, &buffer[i]);
143
      if (ret)
144
        return ret;
145
    }
146
 
147
  memcpy (myaddr,
148
          (char *) buffer + (memaddr & (sizeof (PTRACE_TYPE_RET) - 1)),
149
          len);
150
 
151
  return 0;
152
}
153
 
154
/* Store LEN bytes from MYADDR to PPU memory at MEMADDR.  */
155
static int
156
store_ppc_memory (ULONGEST memaddr, const gdb_byte *myaddr, int len)
157
{
158
  int i, ret;
159
 
160
  ULONGEST addr = memaddr & -(ULONGEST) sizeof (PTRACE_TYPE_RET);
161
  int count = ((((memaddr + len) - addr) + sizeof (PTRACE_TYPE_RET) - 1)
162
               / sizeof (PTRACE_TYPE_RET));
163
  PTRACE_TYPE_RET *buffer;
164
 
165
  int tid = TIDGET (inferior_ptid);
166
  if (tid == 0)
167
    tid = PIDGET (inferior_ptid);
168
 
169
  buffer = (PTRACE_TYPE_RET *) alloca (count * sizeof (PTRACE_TYPE_RET));
170
 
171
  if (addr != memaddr || len < (int) sizeof (PTRACE_TYPE_RET))
172
    {
173
      ret = fetch_ppc_memory_1 (tid, addr, &buffer[0]);
174
      if (ret)
175
        return ret;
176
    }
177
 
178
  if (count > 1)
179
    {
180
      ret = fetch_ppc_memory_1 (tid, addr + (count - 1)
181
                                               * sizeof (PTRACE_TYPE_RET),
182
                                &buffer[count - 1]);
183
      if (ret)
184
        return ret;
185
    }
186
 
187
  memcpy ((char *) buffer + (memaddr & (sizeof (PTRACE_TYPE_RET) - 1)),
188
          myaddr, len);
189
 
190
  for (i = 0; i < count; i++, addr += sizeof (PTRACE_TYPE_RET))
191
    {
192
      ret = store_ppc_memory_1 (tid, addr, buffer[i]);
193
      if (ret)
194
        return ret;
195
    }
196
 
197
  return 0;
198
}
199
 
200
 
201
/* If the PPU thread is currently stopped on a spu_run system call,
202
   return to FD and ADDR the file handle and NPC parameter address
203
   used with the system call.  Return non-zero if successful.  */
204
static int
205
parse_spufs_run (int *fd, ULONGEST *addr)
206
{
207
  enum bfd_endian byte_order = gdbarch_byte_order (target_gdbarch);
208
  gdb_byte buf[4];
209
  ULONGEST pc = fetch_ppc_register (32);  /* nip */
210
 
211
  /* Fetch instruction preceding current NIP.  */
212
  if (fetch_ppc_memory (pc-4, buf, 4) != 0)
213
    return 0;
214
  /* It should be a "sc" instruction.  */
215
  if (extract_unsigned_integer (buf, 4, byte_order) != INSTR_SC)
216
    return 0;
217
  /* System call number should be NR_spu_run.  */
218
  if (fetch_ppc_register (0) != NR_spu_run)
219
    return 0;
220
 
221
  /* Register 3 contains fd, register 4 the NPC param pointer.  */
222
  *fd = fetch_ppc_register (34);  /* orig_gpr3 */
223
  *addr = fetch_ppc_register (4);
224
  return 1;
225
}
226
 
227
 
228
/* Copy LEN bytes at OFFSET in spufs file ANNEX into/from READBUF or WRITEBUF,
229
   using the /proc file system.  */
230
static LONGEST
231
spu_proc_xfer_spu (const char *annex, gdb_byte *readbuf,
232
                   const gdb_byte *writebuf,
233
                   ULONGEST offset, LONGEST len)
234
{
235
  char buf[128];
236
  int fd = 0;
237
  int ret = -1;
238
  int pid = PIDGET (inferior_ptid);
239
 
240
  if (!annex)
241
    return 0;
242
 
243
  xsnprintf (buf, sizeof buf, "/proc/%d/fd/%s", pid, annex);
244
  fd = open (buf, writebuf? O_WRONLY : O_RDONLY);
245
  if (fd <= 0)
246
    return -1;
247
 
248
  if (offset != 0
249
      && lseek (fd, (off_t) offset, SEEK_SET) != (off_t) offset)
250
    {
251
      close (fd);
252
      return 0;
253
    }
254
 
255
  if (writebuf)
256
    ret = write (fd, writebuf, (size_t) len);
257
  else if (readbuf)
258
    ret = read (fd, readbuf, (size_t) len);
259
 
260
  close (fd);
261
  return ret;
262
}
263
 
264
 
265
/* Inferior memory should contain an SPE executable image at location ADDR.
266
   Allocate a BFD representing that executable.  Return NULL on error.  */
267
 
268
static void *
269
spu_bfd_iovec_open (struct bfd *nbfd, void *open_closure)
270
{
271
  return open_closure;
272
}
273
 
274
static int
275
spu_bfd_iovec_close (struct bfd *nbfd, void *stream)
276
{
277
  xfree (stream);
278
  return 1;
279
}
280
 
281
static file_ptr
282
spu_bfd_iovec_pread (struct bfd *abfd, void *stream, void *buf,
283
                     file_ptr nbytes, file_ptr offset)
284
{
285
  ULONGEST addr = *(ULONGEST *)stream;
286
 
287
  if (fetch_ppc_memory (addr + offset, buf, nbytes) != 0)
288
    {
289
      bfd_set_error (bfd_error_invalid_operation);
290
      return -1;
291
    }
292
 
293
  return nbytes;
294
}
295
 
296
static int
297
spu_bfd_iovec_stat (struct bfd *abfd, void *stream, struct stat *sb)
298
{
299
  /* We don't have an easy way of finding the size of embedded spu
300
     images.  We could parse the in-memory ELF header and section
301
     table to find the extent of the last section but that seems
302
     pointless when the size is needed only for checks of other
303
     parsed values in dbxread.c.  */
304
  sb->st_size = INT_MAX;
305
  return 0;
306
}
307
 
308
static bfd *
309
spu_bfd_open (ULONGEST addr)
310
{
311
  struct bfd *nbfd;
312
  asection *spu_name;
313
 
314
  ULONGEST *open_closure = xmalloc (sizeof (ULONGEST));
315
  *open_closure = addr;
316
 
317
  nbfd = bfd_openr_iovec (xstrdup ("<in-memory>"), "elf32-spu",
318
                          spu_bfd_iovec_open, open_closure,
319
                          spu_bfd_iovec_pread, spu_bfd_iovec_close,
320
                          spu_bfd_iovec_stat);
321
  if (!nbfd)
322
    return NULL;
323
 
324
  if (!bfd_check_format (nbfd, bfd_object))
325
    {
326
      bfd_close (nbfd);
327
      return NULL;
328
    }
329
 
330
  /* Retrieve SPU name note and update BFD name.  */
331
  spu_name = bfd_get_section_by_name (nbfd, ".note.spu_name");
332
  if (spu_name)
333
    {
334
      int sect_size = bfd_section_size (nbfd, spu_name);
335
      if (sect_size > 20)
336
        {
337
          char *buf = alloca (sect_size - 20 + 1);
338
          bfd_get_section_contents (nbfd, spu_name, buf, 20, sect_size - 20);
339
          buf[sect_size - 20] = '\0';
340
 
341
          xfree ((char *)nbfd->filename);
342
          nbfd->filename = xstrdup (buf);
343
        }
344
    }
345
 
346
  return nbfd;
347
}
348
 
349
/* INFERIOR_FD is a file handle passed by the inferior to the
350
   spu_run system call.  Assuming the SPE context was allocated
351
   by the libspe library, try to retrieve the main SPE executable
352
   file from its copy within the target process.  */
353
static void
354
spu_symbol_file_add_from_memory (int inferior_fd)
355
{
356
  ULONGEST addr;
357
  struct bfd *nbfd;
358
 
359
  char id[128];
360
  char annex[32];
361
  int len;
362
 
363
  /* Read object ID.  */
364
  xsnprintf (annex, sizeof annex, "%d/object-id", inferior_fd);
365
  len = spu_proc_xfer_spu (annex, id, NULL, 0, sizeof id);
366
  if (len <= 0 || len >= sizeof id)
367
    return;
368
  id[len] = 0;
369
  addr = strtoulst (id, NULL, 16);
370
  if (!addr)
371
    return;
372
 
373
  /* Open BFD representing SPE executable and read its symbols.  */
374
  nbfd = spu_bfd_open (addr);
375
  if (nbfd)
376
    symbol_file_add_from_bfd (nbfd, SYMFILE_VERBOSE | SYMFILE_MAINLINE,
377
                              NULL, 0);
378
}
379
 
380
 
381
/* Override the post_startup_inferior routine to continue running
382
   the inferior until the first spu_run system call.  */
383
static void
384
spu_child_post_startup_inferior (ptid_t ptid)
385
{
386
  int fd;
387
  ULONGEST addr;
388
 
389
  int tid = TIDGET (ptid);
390
  if (tid == 0)
391
    tid = PIDGET (ptid);
392
 
393
  while (!parse_spufs_run (&fd, &addr))
394
    {
395
      ptrace (PT_SYSCALL, tid, (PTRACE_TYPE_ARG3) 0, 0);
396
      waitpid (tid, NULL, __WALL | __WNOTHREAD);
397
    }
398
}
399
 
400
/* Override the post_attach routine to try load the SPE executable
401
   file image from its copy inside the target process.  */
402
static void
403
spu_child_post_attach (int pid)
404
{
405
  int fd;
406
  ULONGEST addr;
407
 
408
  /* Like child_post_startup_inferior, if we happened to attach to
409
     the inferior while it wasn't currently in spu_run, continue
410
     running it until we get back there.  */
411
  while (!parse_spufs_run (&fd, &addr))
412
    {
413
      ptrace (PT_SYSCALL, pid, (PTRACE_TYPE_ARG3) 0, 0);
414
      waitpid (pid, NULL, __WALL | __WNOTHREAD);
415
    }
416
 
417
  /* If the user has not provided an executable file, try to extract
418
     the image from inside the target process.  */
419
  if (!get_exec_file (0))
420
    spu_symbol_file_add_from_memory (fd);
421
}
422
 
423
/* Wait for child PTID to do something.  Return id of the child,
424
   minus_one_ptid in case of error; store status into *OURSTATUS.  */
425
static ptid_t
426
spu_child_wait (struct target_ops *ops,
427
                ptid_t ptid, struct target_waitstatus *ourstatus, int options)
428
{
429
  int save_errno;
430
  int status;
431
  pid_t pid;
432
 
433
  do
434
    {
435
      set_sigint_trap ();       /* Causes SIGINT to be passed on to the
436
                                   attached process.  */
437
 
438
      pid = waitpid (PIDGET (ptid), &status, 0);
439
      if (pid == -1 && errno == ECHILD)
440
        /* Try again with __WCLONE to check cloned processes.  */
441
        pid = waitpid (PIDGET (ptid), &status, __WCLONE);
442
 
443
      save_errno = errno;
444
 
445
      /* Make sure we don't report an event for the exit of the
446
         original program, if we've detached from it.  */
447
      if (pid != -1 && !WIFSTOPPED (status) && pid != PIDGET (inferior_ptid))
448
        {
449
          pid = -1;
450
          save_errno = EINTR;
451
        }
452
 
453
      clear_sigint_trap ();
454
    }
455
  while (pid == -1 && save_errno == EINTR);
456
 
457
  if (pid == -1)
458
    {
459
      warning (_("Child process unexpectedly missing: %s"),
460
               safe_strerror (save_errno));
461
 
462
      /* Claim it exited with unknown signal.  */
463
      ourstatus->kind = TARGET_WAITKIND_SIGNALLED;
464
      ourstatus->value.sig = TARGET_SIGNAL_UNKNOWN;
465
      return inferior_ptid;
466
    }
467
 
468
  store_waitstatus (ourstatus, status);
469
  return pid_to_ptid (pid);
470
}
471
 
472
/* Override the fetch_inferior_register routine.  */
473
static void
474
spu_fetch_inferior_registers (struct target_ops *ops,
475
                              struct regcache *regcache, int regno)
476
{
477
  int fd;
478
  ULONGEST addr;
479
 
480
  /* We must be stopped on a spu_run system call.  */
481
  if (!parse_spufs_run (&fd, &addr))
482
    return;
483
 
484
  /* The ID register holds the spufs file handle.  */
485
  if (regno == -1 || regno == SPU_ID_REGNUM)
486
    {
487
      struct gdbarch *gdbarch = get_regcache_arch (regcache);
488
      enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
489
      char buf[4];
490
      store_unsigned_integer (buf, 4, byte_order, fd);
491
      regcache_raw_supply (regcache, SPU_ID_REGNUM, buf);
492
    }
493
 
494
  /* The NPC register is found at ADDR.  */
495
  if (regno == -1 || regno == SPU_PC_REGNUM)
496
    {
497
      gdb_byte buf[4];
498
      if (fetch_ppc_memory (addr, buf, 4) == 0)
499
        regcache_raw_supply (regcache, SPU_PC_REGNUM, buf);
500
    }
501
 
502
  /* The GPRs are found in the "regs" spufs file.  */
503
  if (regno == -1 || (regno >= 0 && regno < SPU_NUM_GPRS))
504
    {
505
      gdb_byte buf[16 * SPU_NUM_GPRS];
506
      char annex[32];
507
      int i;
508
 
509
      xsnprintf (annex, sizeof annex, "%d/regs", fd);
510
      if (spu_proc_xfer_spu (annex, buf, NULL, 0, sizeof buf) == sizeof buf)
511
        for (i = 0; i < SPU_NUM_GPRS; i++)
512
          regcache_raw_supply (regcache, i, buf + i*16);
513
    }
514
}
515
 
516
/* Override the store_inferior_register routine.  */
517
static void
518
spu_store_inferior_registers (struct target_ops *ops,
519
                              struct regcache *regcache, int regno)
520
{
521
  int fd;
522
  ULONGEST addr;
523
 
524
  /* We must be stopped on a spu_run system call.  */
525
  if (!parse_spufs_run (&fd, &addr))
526
    return;
527
 
528
  /* The NPC register is found at ADDR.  */
529
  if (regno == -1 || regno == SPU_PC_REGNUM)
530
    {
531
      gdb_byte buf[4];
532
      regcache_raw_collect (regcache, SPU_PC_REGNUM, buf);
533
      store_ppc_memory (addr, buf, 4);
534
    }
535
 
536
  /* The GPRs are found in the "regs" spufs file.  */
537
  if (regno == -1 || (regno >= 0 && regno < SPU_NUM_GPRS))
538
    {
539
      gdb_byte buf[16 * SPU_NUM_GPRS];
540
      char annex[32];
541
      int i;
542
 
543
      for (i = 0; i < SPU_NUM_GPRS; i++)
544
        regcache_raw_collect (regcache, i, buf + i*16);
545
 
546
      xsnprintf (annex, sizeof annex, "%d/regs", fd);
547
      spu_proc_xfer_spu (annex, NULL, buf, 0, sizeof buf);
548
    }
549
}
550
 
551
/* Override the to_xfer_partial routine.  */
552
static LONGEST
553
spu_xfer_partial (struct target_ops *ops,
554
                  enum target_object object, const char *annex,
555
                  gdb_byte *readbuf, const gdb_byte *writebuf,
556
                  ULONGEST offset, LONGEST len)
557
{
558
  if (object == TARGET_OBJECT_SPU)
559
    return spu_proc_xfer_spu (annex, readbuf, writebuf, offset, len);
560
 
561
  if (object == TARGET_OBJECT_MEMORY)
562
    {
563
      int fd;
564
      ULONGEST addr;
565
      char mem_annex[32];
566
 
567
      /* We must be stopped on a spu_run system call.  */
568
      if (!parse_spufs_run (&fd, &addr))
569
        return 0;
570
 
571
      /* Use the "mem" spufs file to access SPU local store.  */
572
      xsnprintf (mem_annex, sizeof mem_annex, "%d/mem", fd);
573
      return spu_proc_xfer_spu (mem_annex, readbuf, writebuf, offset, len);
574
    }
575
 
576
  return -1;
577
}
578
 
579
/* Override the to_can_use_hw_breakpoint routine.  */
580
static int
581
spu_can_use_hw_breakpoint (int type, int cnt, int othertype)
582
{
583
  return 0;
584
}
585
 
586
 
587
/* Initialize SPU native target.  */
588
void
589
_initialize_spu_nat (void)
590
{
591
  /* Generic ptrace methods.  */
592
  struct target_ops *t;
593
  t = inf_ptrace_target ();
594
 
595
  /* Add SPU methods.  */
596
  t->to_post_attach = spu_child_post_attach;
597
  t->to_post_startup_inferior = spu_child_post_startup_inferior;
598
  t->to_wait = spu_child_wait;
599
  t->to_fetch_registers = spu_fetch_inferior_registers;
600
  t->to_store_registers = spu_store_inferior_registers;
601
  t->to_xfer_partial = spu_xfer_partial;
602
  t->to_can_use_hw_breakpoint = spu_can_use_hw_breakpoint;
603
 
604
  /* Register SPU target.  */
605
  add_target (t);
606
}

powered by: WebSVN 2.1.0

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