OSDN Git Service

*** empty log message ***
[pf3gnuchains/sourceware.git] / gdb / spu-linux-nat.c
index 21a7c5d..db47292 100644 (file)
@@ -1,5 +1,6 @@
 /* SPU native-dependent code for GDB, the GNU debugger.
-   Copyright (C) 2006, 2007 Free Software Foundation, Inc.
+   Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011
+   Free Software Foundation, Inc.
 
    Contributed by Ulrich Weigand <uweigand@de.ibm.com>.
 
@@ -7,7 +8,7 @@
 
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 2 of the License, or
+   the Free Software Foundation; either version 3 of the License, or
    (at your option) any later version.
 
    This program is distributed in the hope that it will be useful,
@@ -16,9 +17,7 @@
    GNU General Public License for more details.
 
    You should have received a copy of the GNU General Public License
-   along with this program; if not, write to the Free Software
-   Foundation, Inc., 51 Franklin Street, Fifth Floor,
-   Boston, MA 02110-1301, USA.  */
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
 
 #include "defs.h"
 #include "gdbcore.h"
@@ -29,7 +28,7 @@
 #include "regcache.h"
 #include "symfile.h"
 #include "gdb_wait.h"
-#include "gdb_stdint.h"
+#include "gdbthread.h"
 
 #include <sys/ptrace.h>
 #include <asm/ptrace.h>
@@ -206,6 +205,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);
   gdb_byte buf[4];
   ULONGEST pc = fetch_ppc_register (32);  /* nip */
 
@@ -213,7 +213,7 @@ parse_spufs_run (int *fd, ULONGEST *addr)
   if (fetch_ppc_memory (pc-4, buf, 4) != 0)
     return 0;
   /* It should be a "sc" instruction.  */
-  if (extract_unsigned_integer (buf, 4) != INSTR_SC)
+  if (extract_unsigned_integer (buf, 4, byte_order) != INSTR_SC)
     return 0;
   /* System call number should be NR_spu_run.  */
   if (fetch_ppc_register (0) != NR_spu_run)
@@ -310,6 +310,7 @@ static bfd *
 spu_bfd_open (ULONGEST addr)
 {
   struct bfd *nbfd;
+  asection *spu_name;
 
   ULONGEST *open_closure = xmalloc (sizeof (ULONGEST));
   *open_closure = addr;
@@ -327,6 +328,22 @@ spu_bfd_open (ULONGEST addr)
       return NULL;
     }
 
+  /* Retrieve SPU name note and update BFD name.  */
+  spu_name = bfd_get_section_by_name (nbfd, ".note.spu_name");
+  if (spu_name)
+    {
+      int sect_size = bfd_section_size (nbfd, spu_name);
+      if (sect_size > 20)
+       {
+         char *buf = alloca (sect_size - 20 + 1);
+         bfd_get_section_contents (nbfd, spu_name, buf, 20, sect_size - 20);
+         buf[sect_size - 20] = '\0';
+
+         xfree ((char *)nbfd->filename);
+         nbfd->filename = xstrdup (buf);
+       }
+    }
+
   return nbfd;
 }
 
@@ -357,7 +374,8 @@ 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, 0, NULL, 1, 0);
+    symbol_file_add_from_bfd (nbfd, SYMFILE_VERBOSE | SYMFILE_MAINLINE,
+                              NULL, 0);
 }
 
 
@@ -406,7 +424,8 @@ spu_child_post_attach (int pid)
 /* Wait for child PTID to do something.  Return id of the child,
    minus_one_ptid in case of error; store status into *OURSTATUS.  */
 static ptid_t
-spu_child_wait (ptid_t ptid, struct target_waitstatus *ourstatus)
+spu_child_wait (struct target_ops *ops,
+               ptid_t ptid, struct target_waitstatus *ourstatus, int options)
 {
   int save_errno;
   int status;
@@ -416,7 +435,6 @@ spu_child_wait (ptid_t ptid, struct target_waitstatus *ourstatus)
     {
       set_sigint_trap ();      /* Causes SIGINT to be passed on to the
                                   attached process.  */
-      set_sigio_trap ();
 
       pid = waitpid (PIDGET (ptid), &status, 0);
       if (pid == -1 && errno == ECHILD)
@@ -433,7 +451,6 @@ spu_child_wait (ptid_t ptid, struct target_waitstatus *ourstatus)
          save_errno = EINTR;
        }
 
-      clear_sigio_trap ();
       clear_sigint_trap ();
     }
   while (pid == -1 && save_errno == EINTR);
@@ -446,7 +463,7 @@ spu_child_wait (ptid_t ptid, struct target_waitstatus *ourstatus)
       /* Claim it exited with unknown signal.  */
       ourstatus->kind = TARGET_WAITKIND_SIGNALLED;
       ourstatus->value.sig = TARGET_SIGNAL_UNKNOWN;
-      return minus_one_ptid;
+      return inferior_ptid;
     }
 
   store_waitstatus (ourstatus, status);
@@ -455,7 +472,8 @@ spu_child_wait (ptid_t ptid, struct target_waitstatus *ourstatus)
 
 /* Override the fetch_inferior_register routine.  */
 static void
-spu_fetch_inferior_registers (struct regcache *regcache, int regno)
+spu_fetch_inferior_registers (struct target_ops *ops,
+                             struct regcache *regcache, int regno)
 {
   int fd;
   ULONGEST addr;
@@ -467,8 +485,10 @@ spu_fetch_inferior_registers (struct regcache *regcache, int regno)
   /* The ID register holds the spufs file handle.  */
   if (regno == -1 || regno == SPU_ID_REGNUM)
     {
+      struct gdbarch *gdbarch = get_regcache_arch (regcache);
+      enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
       char buf[4];
-      store_unsigned_integer (buf, 4, fd);
+      store_unsigned_integer (buf, 4, byte_order, fd);
       regcache_raw_supply (regcache, SPU_ID_REGNUM, buf);
     }
 
@@ -496,7 +516,8 @@ spu_fetch_inferior_registers (struct regcache *regcache, int regno)
 
 /* Override the store_inferior_register routine.  */
 static void
-spu_store_inferior_registers (struct regcache *regcache, int regno)
+spu_store_inferior_registers (struct target_ops *ops,
+                             struct regcache *regcache, int regno)
 {
   int fd;
   ULONGEST addr;
@@ -535,11 +556,17 @@ spu_xfer_partial (struct target_ops *ops,
                  gdb_byte *readbuf, const gdb_byte *writebuf,
                  ULONGEST offset, LONGEST len)
 {
+  if (object == TARGET_OBJECT_SPU)
+    return spu_proc_xfer_spu (annex, readbuf, writebuf, offset, len);
+
   if (object == TARGET_OBJECT_MEMORY)
     {
       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))
@@ -547,7 +574,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;
@@ -581,4 +623,3 @@ _initialize_spu_nat (void)
   /* Register SPU target.  */
   add_target (t);
 }
-