]> git.ipfire.org Git - thirdparty/binutils-gdb.git/commitdiff
* gdb/Makefile.in (arm-linux-nat.o): Update dependencies.
authorDaniel Jacobowitz <drow@false.org>
Wed, 30 Mar 2005 14:59:31 +0000 (14:59 +0000)
committerDaniel Jacobowitz <drow@false.org>
Wed, 30 Mar 2005 14:59:31 +0000 (14:59 +0000)
* gdb/arm-linux-nat.c: Include "gdb_assert.h".
(PTRACE_GETWMMXREGS, PTRACE_SETWMMXREGS): Define.
(arm_linux_has_wmmx_registers): New flag.
(GET_THREAD_ID): Remove stray punctuation.
(IWMMXT_REGS_SIZE): Define.
(fetch_wmmx_regs, store_wmmx_regs): New functions.
(fetch_inferior_registers, store_inferior_registers): Call them.
(arm_linux_available_registers): New function.
* gdb/inftarg.c (child_xfer_partial): Handle
TARGET_OBJECT_AVAILABLE_REGISTERS.
* gdb/config/arm/nm-linux.h (arm_linux_available_registers): Add
prototype.
(NATIVE_XFER_AVAILABLE_REGISTERS): Define.

* gdb/gdbserver/linux-arm-low.c (arm_fill_wmmxregset)
(arm_store_wmmxregset): Remove stray text.
(arm_available_registers): Remove debugging output.  Use hex.
* gdb/gdbserver/regcache.c (num_registers): Make global.
* gdb/gdbserver/server.c (handle_p_packet, handle_P_packet): Check
the value of regnum.

ChangeLog.csl
gdb/Makefile.in
gdb/arm-linux-nat.c
gdb/config/arm/nm-linux.h
gdb/gdbserver/linux-arm-low.c
gdb/gdbserver/regcache.c
gdb/gdbserver/server.c
gdb/inftarg.c

index 57842ed6e0ea2b41cb5375b3952bb8d33db55636..2d493e7fa296b30b048c1e2cf25cd36d4469e164 100644 (file)
@@ -1,3 +1,27 @@
+2005-03-30  Daniel Jacobowitz  <dan@codesourcery.com>
+
+       * gdb/Makefile.in (arm-linux-nat.o): Update dependencies.
+       * gdb/arm-linux-nat.c: Include "gdb_assert.h".
+       (PTRACE_GETWMMXREGS, PTRACE_SETWMMXREGS): Define.
+       (arm_linux_has_wmmx_registers): New flag.
+       (GET_THREAD_ID): Remove stray punctuation.
+       (IWMMXT_REGS_SIZE): Define.
+       (fetch_wmmx_regs, store_wmmx_regs): New functions.
+       (fetch_inferior_registers, store_inferior_registers): Call them.
+       (arm_linux_available_registers): New function.
+       * gdb/inftarg.c (child_xfer_partial): Handle
+       TARGET_OBJECT_AVAILABLE_REGISTERS.
+       * gdb/config/arm/nm-linux.h (arm_linux_available_registers): Add
+       prototype.
+       (NATIVE_XFER_AVAILABLE_REGISTERS): Define.
+
+       * gdb/gdbserver/linux-arm-low.c (arm_fill_wmmxregset)
+       (arm_store_wmmxregset): Remove stray text.
+       (arm_available_registers): Remove debugging output.  Use hex.
+       * gdb/gdbserver/regcache.c (num_registers): Make global. 
+       * gdb/gdbserver/server.c (handle_p_packet, handle_P_packet): Check
+       the value of regnum.
+
 2005-03-28  Paul Brook  <paul@codesourcery.com>
        Daniel Jacobowitz  <dan@codesourcery.com>
 
index 4a6e97158352df4712f27f1bddc76cba04671a0a..b126430bc1cc4ff375df9155f9962fcb4767fd77 100644 (file)
@@ -1732,7 +1732,7 @@ arch-utils.o: arch-utils.c $(defs_h) $(arch_utils_h) $(buildsym_h) \
        $(floatformat_h)
 arm-linux-nat.o: arm-linux-nat.c $(defs_h) $(inferior_h) $(gdbcore_h) \
        $(gdb_string_h) $(regcache_h) $(arm_tdep_h) $(gregset_h)\
-       $(gdb_proc_service_h)
+       $(gdb_proc_service_h) $(gdb_assert_h)
 arm-linux-tdep.o: arm-linux-tdep.c $(defs_h) $(target_h) $(value_h) \
        $(gdbtypes_h) $(floatformat_h) $(gdbcore_h) $(frame_h) $(regcache_h) \
        $(doublest_h) $(solib_svr4_h) $(osabi_h) $(arm_tdep_h) \
index cd9d5ff66bac951015761d2e02889668328f7332..59377be64937bd569bb4ff42bdba37d594081a8a 100644 (file)
@@ -23,6 +23,7 @@
 #include "gdbcore.h"
 #include "gdb_string.h"
 #include "regcache.h"
+#include "gdb_assert.h"
 
 #include "arm-tdep.h"
 
 #define PTRACE_GET_THREAD_AREA 22
 #endif
 
+#ifndef PTRACE_GETWMMXREGS
+#define PTRACE_GETWMMXREGS 18
+#define PTRACE_SETWMMXREGS 19
+#endif
+
+static int arm_linux_has_wmmx_registers = 1;
+
 extern int arm_apcs_32;
 
 #define                typeNone                0x00
@@ -99,7 +107,7 @@ get_thread_id (ptid_t ptid)
     tid = PIDGET (ptid);
   return tid;
 }
-#define GET_THREAD_ID(PTID)    get_thread_id ((PTID));
+#define GET_THREAD_ID(PTID)    get_thread_id (PTID)
 
 static void
 fetch_nwfpe_single (unsigned int fn, FPA11 * fpa11)
@@ -550,6 +558,97 @@ store_regs (void)
     }
 }
 
+/* Fetch all WMMX registers of the process and store into
+   regcache.  */
+
+#define IWMMXT_REGS_SIZE (16 * 8 + 6 * 4)
+
+static void
+fetch_wmmx_regs (void)
+{
+  char regbuf[IWMMXT_REGS_SIZE];
+  int ret, regno, tid, first;
+
+  /* Get the thread id for the ptrace call.  */
+  tid = GET_THREAD_ID (inferior_ptid);
+  
+  ret = ptrace (PTRACE_GETWMMXREGS, tid, 0, regbuf);
+  if (ret < 0)
+    {
+      warning (_("Unable to fetch WMMX registers."));
+      return;
+    }
+
+  first = gdbarch_tdep (current_gdbarch)->first_iwmmxt_regnum;
+
+  for (regno = 0; regno < NUM_IWMMXT_COP0REGS; regno++)
+    regcache_raw_supply (current_regcache, first + regno,
+                        &regbuf[regno * 8]);
+
+  first += NUM_IWMMXT_COP0REGS;
+
+  for (regno = 0; regno < 2; regno++)
+    regcache_raw_supply (current_regcache, first + regno, NULL);
+
+  for (regno = 2; regno < 4; regno++)
+    regcache_raw_supply (current_regcache, first + regno,
+                        &regbuf[16 * 8 + (regno - 2) * 4]);
+
+  for (regno = 4; regno < 8; regno++)
+    regcache_raw_supply (current_regcache, first + regno, NULL);
+
+  for (regno = 8; regno < 12; regno++)
+    regcache_raw_supply (current_regcache, first + regno,
+                        &regbuf[16 * 8 + 2 * 4 + (regno - 8) * 4]);
+
+  for (regno = 12; regno < 16; regno++)
+    regcache_raw_supply (current_regcache, first + regno, NULL);
+}
+
+static void
+store_wmmx_regs (void)
+{
+  char regbuf[IWMMXT_REGS_SIZE];
+  int ret, regno, tid, first;
+
+  /* Get the thread id for the ptrace call.  */
+  tid = GET_THREAD_ID (inferior_ptid);
+  
+  ret = ptrace (PTRACE_GETWMMXREGS, tid, 0, regbuf);
+  if (ret < 0)
+    {
+      warning (_("Unable to fetch WMMX registers."));
+      return;
+    }
+
+  first = gdbarch_tdep (current_gdbarch)->first_iwmmxt_regnum;
+
+  for (regno = 0; regno < NUM_IWMMXT_COP0REGS; regno++)
+    if (register_cached (first + regno))
+      regcache_raw_collect (current_regcache, first + regno,
+                           &regbuf[regno * 8]);
+
+  first += 18;
+  for (regno = 0; regno < 2; regno++)
+    if (register_cached (first + regno))
+      regcache_raw_collect (current_regcache, first + regno,
+                           &regbuf[16 * 8 + regno * 4]);
+
+  first += 6;
+  for (regno = 0; regno < 4; regno++)
+    if (register_cached (first + regno))
+      regcache_raw_collect (current_regcache, first + regno,
+                           &regbuf[16 * 8 + 2 * 4 + regno * 4]);
+
+  ret = ptrace (PTRACE_SETWMMXREGS, tid, 0, regbuf);
+
+  if (ret < 0)
+    {
+      warning (_("Unable to store WMMX registers."));
+      return;
+    }
+}
+
 /* Fetch registers from the child process.  Fetch all registers if
    regno == -1, otherwise fetch all general registers or all floating
    point registers depending upon the value of regno.  */
@@ -561,14 +660,21 @@ fetch_inferior_registers (int regno)
     {
       fetch_regs ();
       fetch_fpa_regs ();
+      if (arm_linux_has_wmmx_registers)
+       fetch_wmmx_regs ();
     }
   else 
     {
-      if (regno < ARM_F0_REGNUM || regno > ARM_FPS_REGNUM)
+      if (regno < ARM_F0_REGNUM || regno == ARM_PS_REGNUM)
         fetch_register (regno);
-
-      if (regno >= ARM_F0_REGNUM && regno <= ARM_FPS_REGNUM)
+      else if (regno >= ARM_F0_REGNUM && regno <= ARM_FPS_REGNUM)
         fetch_fpa_register (regno);
+      else if (arm_linux_has_wmmx_registers)
+       {
+         int first = gdbarch_tdep (current_gdbarch)->first_iwmmxt_regnum;
+         if (regno >= first && regno < first + NUM_IWMMXT_REGS)
+           fetch_wmmx_regs ();
+       }
     }
 }
 
@@ -583,14 +689,21 @@ store_inferior_registers (int regno)
     {
       store_regs ();
       store_fpa_regs ();
+      if (arm_linux_has_wmmx_registers)
+       store_wmmx_regs ();
     }
   else
     {
-      if ((regno < ARM_F0_REGNUM) || (regno > ARM_FPS_REGNUM))
+      if (regno < ARM_F0_REGNUM || regno == ARM_PS_REGNUM)
         store_register (regno);
-
-      if ((regno >= ARM_F0_REGNUM) && (regno <= ARM_FPS_REGNUM))
-        store_fpa_register (regno);
+      else if ((regno >= ARM_F0_REGNUM) && (regno <= ARM_FPS_REGNUM))
+        store_fpa_register (regno); 
+      else if (arm_linux_has_wmmx_registers)
+       {
+         int first = gdbarch_tdep (current_gdbarch)->first_iwmmxt_regnum;
+         if (regno >= first && regno < first + NUM_IWMMXT_REGS)
+           store_wmmx_regs ();
+       }
     }
 }
 
@@ -740,6 +853,50 @@ get_linux_version (unsigned int *vmajor,
   return ((*vmajor << 16) | (*vminor << 8) | *vrelease);
 }
 
+LONGEST
+arm_linux_available_registers (struct target_ops *ops,
+                              int /* enum target_object */ object,
+                              const char *annex,
+                              void *readbuf,
+                              const void *writebuf,
+                              ULONGEST offset,
+                              LONGEST len)
+{
+  char *result = NULL;
+  int total_len;
+
+  gdb_assert (object == TARGET_OBJECT_AVAILABLE_REGISTERS);
+  gdb_assert (readbuf && !writebuf);
+
+  if (arm_linux_has_wmmx_registers)
+    {
+      int ret;
+      char regbuf[IWMMXT_REGS_SIZE];
+
+      ret = ptrace (PTRACE_GETWMMXREGS, GET_THREAD_ID (inferior_ptid), 0,
+                   regbuf);
+      if (ret < 0)
+       /* Should we be checking the error code?  */
+       arm_linux_has_wmmx_registers = 0;
+    }
+
+  if (arm_linux_has_wmmx_registers)
+    result = "iwmmxt";
+
+  if (result == NULL)
+    return 0;
+
+  total_len = strlen (result);
+  if (total_len > offset)
+    {
+      int bytes_read = min (total_len - offset, len);
+      memcpy (readbuf, result + offset, bytes_read);
+      return bytes_read;
+    }
+
+  return 0;
+}
+
 void
 _initialize_arm_linux_nat (void)
 {
index 1d7bbaa86506f3119ca08f8a57bfb576b3c64bef..2ad3968f636b9ee8adff0c200c81bfd5b94dd156 100644 (file)
@@ -38,4 +38,20 @@ extern int kernel_u_size (void);
 /* Override copies of {fetch,store}_inferior_registers in infptrace.c.  */
 #define FETCH_INFERIOR_REGISTERS
 
+/* This function is called like a to_xfer_partial hook,
+   but must be called with TARGET_OBJECT_AVAILABLE_REGISTERS.  */
+
+struct target_ops;
+
+extern LONGEST arm_linux_available_registers
+  (struct target_ops *ops,
+   int /* enum target_object */ object,
+   const char *annex,
+   void *readbuf,
+   const void *writebuf,
+   ULONGEST offset,
+   LONGEST len);
+
+#define NATIVE_XFER_AVAILABLE_REGISTERS arm_linux_available_registers
+
 #endif /* NM_ARMLINUX_H */
index e49c86e16e108c4da557c4a30e491af4525cfc49..606a6669edec70c4108cbad97317a8517b8650fa 100644 (file)
@@ -155,11 +155,6 @@ arm_fill_wmmxregset (void *buf)
  
   for (i = 0; i < 4; i++)
     collect_register (arm_num_regs + i + 16 + 8, ((char *) buf) + 16 * 8 + 8 + i * 4);
-
-        ((int*)buf)[0], 
-        ((int*)buf)[1], 
-        ((int*)buf)[2], 
-        ((int*)buf)[3]);
 }
  
 static void
@@ -167,10 +162,6 @@ arm_store_wmmxregset (const void *buf)
 {
   int i;
 
-        ((int*)buf)[0], 
-        ((int*)buf)[1], 
-        ((int*)buf)[2], 
-        ((int*)buf)[3]);
   for (i = 0; i < 16; i++)
     supply_register (arm_num_regs + i, ((char *) buf) + i * 8);
   
@@ -186,11 +177,10 @@ arm_available_registers (void)
 {
   char buf[64];
 
-  printf ("use_regsets %d target_regsets %d\n", use_regsets_p, target_regsets[1].size);
   if (use_regsets_p && target_regsets[1].size > 0)
     {
       int wr0 = find_regno ("wr0");
-      sprintf (buf, "iwmmxt:%d", wr0);
+      sprintf (buf, "iwmmxt:%x", wr0);
       return strdup (buf);
     }
 
index 011fac1c5d9d37b1a179fec9ac8011075b5c7fea..8bfb3ec783395d0e99d15aa134fd78158ac6068a 100644 (file)
@@ -38,7 +38,7 @@ struct inferior_regcache_data
 static int register_bytes, g_register_bytes;
 
 static struct reg *reg_defs;
-static int num_registers;
+int num_registers;
 
 const char **gdbserver_expedite_regs;
 
index 1389231770f5d1c14e71c7e787147e53df17760f..1c5f767c295c60d923e654b41e2c55b3ebdab265 100644 (file)
@@ -295,6 +295,8 @@ handle_v_requests (char *own_buf, char *status, unsigned char *signal)
   return;
 }
 
+extern int num_registers;
+
 /* Handle a register fetch ('p') request.  */
 void
 handle_p_packet (char *own_buf)
@@ -302,7 +304,7 @@ handle_p_packet (char *own_buf)
   char *end = own_buf + 1;
   int regnum = strtol (own_buf + 1, &end, 16);
 
-  if (*end)
+  if (*end || regnum < 0 || regnum >= num_registers)
     {
       write_enn (own_buf);
       return;
@@ -318,7 +320,7 @@ handle_P_packet (char *own_buf)
   char *end = own_buf + 1;
   int regnum = strtol (own_buf + 1, &end, 16);
 
-  if (*end != '=')
+  if (*end != '=' || regnum < 0 || regnum >= num_registers)
     {
       write_enn (own_buf);
       return;
index cd8674dc7585b055861f3834fc4998215ef254e6..15dd8ebc0878e0f6fd0aecf89f462baecc5cfb14 100644 (file)
@@ -559,6 +559,13 @@ child_xfer_partial (struct target_ops *ops, enum target_object object,
       return NATIVE_XFER_AUXV (ops, object, annex, readbuf, writebuf,
                               offset, len);
 
+    case TARGET_OBJECT_AVAILABLE_REGISTERS:
+#ifndef NATIVE_XFER_AVAILABLE_REGISTERS
+#define NATIVE_XFER_AVAILABLE_REGISTERS(OPS,OBJECT,ANNEX,WRITEBUF,READBUF,OFFSET,LEN) (-1)
+#endif
+      return NATIVE_XFER_AVAILABLE_REGISTERS (ops, object, annex, readbuf,
+                                             writebuf, offset, len);
+
     default:
       return -1;
     }