2013-03-11 Sebastian Huber <sebastian.huber@embedded-brains.de>
[deliverable/binutils-gdb.git] / gdb / spu-linux-nat.c
index f5a5fb10e571d25e315d0c6bc0df3a9a4f612dff..ca8d92d33ac114bedbb0df638c0498bba4cec8fb 100644 (file)
@@ -1,5 +1,5 @@
 /* SPU native-dependent code for GDB, the GNU debugger.
-   Copyright (C) 2006, 2007, 2008, 2009 Free Software Foundation, Inc.
+   Copyright (C) 2006-2013 Free Software Foundation, Inc.
 
    Contributed by Ulrich Weigand <uweigand@de.ibm.com>.
 
 #include "gdb_string.h"
 #include "target.h"
 #include "inferior.h"
+#include "inf-child.h"
 #include "inf-ptrace.h"
 #include "regcache.h"
 #include "symfile.h"
 #include "gdb_wait.h"
 #include "gdbthread.h"
+#include "gdb_bfd.h"
 
 #include <sys/ptrace.h>
 #include <asm/ptrace.h>
@@ -204,7 +206,7 @@ store_ppc_memory (ULONGEST memaddr, const gdb_byte *myaddr, int len)
 static int 
 parse_spufs_run (int *fd, ULONGEST *addr)
 {
-  enum bfd_endian byte_order = gdbarch_byte_order (target_gdbarch);
+  enum bfd_endian byte_order = gdbarch_byte_order (target_gdbarch ());
   gdb_byte buf[4];
   ULONGEST pc = fetch_ppc_register (32);  /* nip */
 
@@ -314,16 +316,16 @@ spu_bfd_open (ULONGEST addr)
   ULONGEST *open_closure = xmalloc (sizeof (ULONGEST));
   *open_closure = addr;
 
-  nbfd = bfd_openr_iovec (xstrdup ("<in-memory>"), "elf32-spu",
-                         spu_bfd_iovec_open, open_closure,
-                         spu_bfd_iovec_pread, spu_bfd_iovec_close,
-                         spu_bfd_iovec_stat);
+  nbfd = gdb_bfd_openr_iovec ("<in-memory>", "elf32-spu",
+                             spu_bfd_iovec_open, open_closure,
+                             spu_bfd_iovec_pread, spu_bfd_iovec_close,
+                             spu_bfd_iovec_stat);
   if (!nbfd)
     return NULL;
 
   if (!bfd_check_format (nbfd, bfd_object))
     {
-      bfd_close (nbfd);
+      gdb_bfd_unref (nbfd);
       return NULL;
     }
 
@@ -373,8 +375,13 @@ spu_symbol_file_add_from_memory (int inferior_fd)
   /* Open BFD representing SPE executable and read its symbols.  */
   nbfd = spu_bfd_open (addr);
   if (nbfd)
-    symbol_file_add_from_bfd (nbfd, SYMFILE_VERBOSE | SYMFILE_MAINLINE,
-                              NULL, 0);
+    {
+      struct cleanup *cleanup = make_cleanup_bfd_unref (nbfd);
+
+      symbol_file_add_from_bfd (nbfd, SYMFILE_VERBOSE | SYMFILE_MAINLINE,
+                               NULL, 0, NULL);
+      do_cleanups (cleanup);
+    }
 }
 
 
@@ -461,7 +468,7 @@ spu_child_wait (struct target_ops *ops,
 
       /* Claim it exited with unknown signal.  */
       ourstatus->kind = TARGET_WAITKIND_SIGNALLED;
-      ourstatus->value.sig = TARGET_SIGNAL_UNKNOWN;
+      ourstatus->value.sig = GDB_SIGNAL_UNKNOWN;
       return inferior_ptid;
     }
 
@@ -486,7 +493,7 @@ spu_fetch_inferior_registers (struct target_ops *ops,
     {
       struct gdbarch *gdbarch = get_regcache_arch (regcache);
       enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
-      char buf[4];
+      gdb_byte buf[4];
       store_unsigned_integer (buf, 4, byte_order, fd);
       regcache_raw_supply (regcache, SPU_ID_REGNUM, buf);
     }
@@ -562,7 +569,10 @@ spu_xfer_partial (struct target_ops *ops,
     {
       int fd;
       ULONGEST addr;
-      char mem_annex[32];
+      char mem_annex[32], lslr_annex[32];
+      gdb_byte buf[32];
+      ULONGEST lslr;
+      LONGEST ret;
 
       /* We must be stopped on a spu_run system call.  */
       if (!parse_spufs_run (&fd, &addr))
@@ -570,7 +580,22 @@ spu_xfer_partial (struct target_ops *ops,
 
       /* Use the "mem" spufs file to access SPU local store.  */
       xsnprintf (mem_annex, sizeof mem_annex, "%d/mem", fd);
-      return spu_proc_xfer_spu (mem_annex, readbuf, writebuf, offset, len);
+      ret = spu_proc_xfer_spu (mem_annex, readbuf, writebuf, offset, len);
+      if (ret > 0)
+       return ret;
+
+      /* SPU local store access wraps the address around at the
+        local store limit.  We emulate this here.  To avoid needing
+        an extra access to retrieve the LSLR, we only do that after
+        trying the original address first, and getting end-of-file.  */
+      xsnprintf (lslr_annex, sizeof lslr_annex, "%d/lslr", fd);
+      memset (buf, 0, sizeof buf);
+      if (spu_proc_xfer_spu (lslr_annex, buf, NULL, 0, sizeof buf) <= 0)
+       return ret;
+
+      lslr = strtoulst (buf, NULL, 16);
+      return spu_proc_xfer_spu (mem_annex, readbuf, writebuf,
+                               offset & lslr, len);
     }
 
   return -1;
This page took 0.029904 seconds and 4 git commands to generate.