This is the mail archive of the gdb-cvs@sourceware.org mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[binutils-gdb] MIPS/gdbserver: Correctly handle narrow big-endian register transfers


https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=7e947ad3438b2954e0bd248fd2c95a86bd9fe33b

commit 7e947ad3438b2954e0bd248fd2c95a86bd9fe33b
Author: Maciej W. Rozycki <macro@mips.com>
Date:   Tue May 22 22:52:14 2018 +0100

    MIPS/gdbserver: Correctly handle narrow big-endian register transfers
    
    Fix an issue with `gdbserver' on big-endian n64 MIPS targets, where
    $dspctl is 32-bit while the `ptrace' transfer data type is 64-bit.
    
    Such register data is held in the low order 32 bits of the 64-bit data
    quantity exchanged with the buffer used by `fetch_register' and
    `store_register', however `supply_register' and `collect_register'
    access the same data as a 32-bit quantity.  Consequently the register is
    presented and written as all-zeros held in the most-significant part of
    the big-endian 64-bit data quantity represented in the buffer:
    
    (gdb) info registers
                      zero               at               v0               v1
     R0   0000000000000000 0000000000000001 0000000000000001 0000000000000000
                        a0               a1               a2               a3
     R4   00000001200212b0 0000000000000000 0000000000000021 000000012001a260
                        a4               a5               a6               a7
     R8   000000012001a260 0000000000000004 800000010c60c000 fffffffffffffff8
                        t0               t1               t2               t3
     R12  0000000000000000 000000fff7edab68 0000000000000001 0000000000000000
                        s0               s1               s2               s3
     R16  000000fff7ee2068 0000000120008b80 0000000000000000 0000000000000000
                        s4               s5               s6               s7
     R20  000000000052e5c8 000000000052f008 0000000000000000 0000000000000000
                        t8               t9               k0               k1
     R24  0000000000000000 00000001200027c0 0000000000000000 0000000000000000
                        gp               sp               s8               ra
     R28  00000001200212b0 000000ffffffc850 000000ffffffc850 0000000120005ee8
                    status               lo               hi         badvaddr
          0000000000109cf3 0000000000943efe 000000000000000e 000000012001a008
                     cause               pc
          0000000000800024 0000000120005ee8
                      fcsr              fir              hi1              lo1
                  0e800000         00f30000 0000000000000000 0101010101010101
                       hi2              lo2              hi3              lo3
          0202020202020202 0303030303030303 0404040404040404 0505050505050505
                    dspctl          restart
                  00000000 0000000000000000
    (gdb)
    
    Correct this problem then by using the `mips_supply_register'
    `mips_collect_register' accessors for 32-bit registers where the
    `ptrace' data type is 64-bit.  These accessors already operate on 32-bit
    data quantities held in 64-bit containers:
    
    (gdb) info registers
                      zero               at               v0               v1
     R0   0000000000000000 0000000000000001 0000000000000001 0000000000000000
                        a0               a1               a2               a3
     R4   00000001200212b0 0000000000000000 0000000000000021 000000012001a260
                        a4               a5               a6               a7
     R8   000000012001a260 0000000000000004 800000010d82e900 fffffffffffffff8
                        t0               t1               t2               t3
     R12  0000000000000000 000000fff7edab68 0000000000000001 0000000000000000
                        s0               s1               s2               s3
     R16  000000fff7ee2068 0000000120008b80 0000000000000000 0000000000000000
                        s4               s5               s6               s7
     R20  000000000052e5c8 000000000052f008 0000000000000000 0000000000000000
                        t8               t9               k0               k1
     R24  0000000000000000 00000001200027c0 0000000000000000 0000000000000000
                        gp               sp               s8               ra
     R28  00000001200212b0 000000ffffffc850 000000ffffffc850 0000000120005ee8
                    status               lo               hi         badvaddr
          0000000000109cf3 0000000000943efe 000000000000000e 000000012001a008
                     cause               pc
          0000000000800024 0000000120005ee8
                      fcsr              fir              hi1              lo1
                  0e800000         00f30000 0000000000000000 0101010101010101
                       hi2              lo2              hi3              lo3
          0202020202020202 0303030303030303 0404040404040404 0505050505050505
                    dspctl          restart
                  55aa33cc 0000000000000000
    (gdb)
    
    	gdb/gdbserver/
    	* linux-mips-low.c [HAVE_PTRACE_GETREGS] (mips_collect_register)
    	(mips_supply_register): Move outside HAVE_PTRACE_GETREGS.
    	(mips_collect_ptrace_register, mips_supply_ptrace_register): New
    	functions.
    	(the_low_target): Wire them.

Diff:
---
 gdb/gdbserver/ChangeLog        |  8 +++++++
 gdb/gdbserver/linux-mips-low.c | 48 ++++++++++++++++++++++++++++++++++++++----
 2 files changed, 52 insertions(+), 4 deletions(-)

diff --git a/gdb/gdbserver/ChangeLog b/gdb/gdbserver/ChangeLog
index 13e3426..54a07b8 100644
--- a/gdb/gdbserver/ChangeLog
+++ b/gdb/gdbserver/ChangeLog
@@ -1,3 +1,11 @@
+2018-05-22  Maciej W. Rozycki  <macro@mips.com>
+
+	* linux-mips-low.c [HAVE_PTRACE_GETREGS] (mips_collect_register)
+	(mips_supply_register): Move outside HAVE_PTRACE_GETREGS.
+	(mips_collect_ptrace_register, mips_supply_ptrace_register): New
+	functions.
+	(the_low_target): Wire them.
+
 2018-05-22  Pedro Franco de Carvalho  <pedromfc@linux.vnet.ibm.com>
 
 	* linux-ppc-low.c (ppc_fill_vrregset): Add vscr_offset variable.
diff --git a/gdb/gdbserver/linux-mips-low.c b/gdb/gdbserver/linux-mips-low.c
index 7fae2e6..17fb897 100644
--- a/gdb/gdbserver/linux-mips-low.c
+++ b/gdb/gdbserver/linux-mips-low.c
@@ -677,8 +677,6 @@ ps_get_thread_area (struct ps_prochandle *ph,
   return PS_OK;
 }
 
-#ifdef HAVE_PTRACE_GETREGS
-
 static void
 mips_collect_register (struct regcache *regcache,
 		       int use_64bit, int regno, union mips_register *reg)
@@ -711,6 +709,8 @@ mips_supply_register (struct regcache *regcache,
   supply_register (regcache, regno, reg->buf + offset);
 }
 
+#ifdef HAVE_PTRACE_GETREGS
+
 static void
 mips_collect_register_32bit (struct regcache *regcache,
 			     int use_64bit, int regno, unsigned char *buf)
@@ -846,6 +846,46 @@ mips_store_fpregset (struct regcache *regcache, const void *buf)
 }
 #endif /* HAVE_PTRACE_GETREGS */
 
+/* Take care of 32-bit registers with 64-bit ptrace, POKEUSER side.  */
+
+static void
+mips_collect_ptrace_register (struct regcache *regcache,
+			      int regno, char *buf)
+{
+  const struct target_desc *tdesc = current_process ()->tdesc;
+  int use_64bit = sizeof (PTRACE_XFER_TYPE) == 8;
+
+  if (use_64bit && register_size (regcache->tdesc, regno) == 4)
+    {
+      union mips_register reg;
+
+      mips_collect_register (regcache, 0, regno, &reg);
+      memcpy (buf, &reg, sizeof (reg));
+    }
+  else
+    collect_register (regcache, regno, buf);
+}
+
+/* Take care of 32-bit registers with 64-bit ptrace, PEEKUSER side.  */
+
+static void
+mips_supply_ptrace_register (struct regcache *regcache,
+			     int regno, const char *buf)
+{
+  const struct target_desc *tdesc = current_process ()->tdesc;
+  int use_64bit = sizeof (PTRACE_XFER_TYPE) == 8;
+
+  if (use_64bit && register_size (regcache->tdesc, regno) == 4)
+    {
+      union mips_register reg;
+
+      memcpy (&reg, buf, sizeof (reg));
+      mips_supply_register (regcache, 0, regno, &reg);
+    }
+  else
+    supply_register (regcache, regno, buf);
+}
+
 static struct regset_info mips_regsets[] = {
 #ifdef HAVE_PTRACE_GETREGS
   { PTRACE_GETREGS, PTRACE_SETREGS, 0, 38 * 8, GENERAL_REGS,
@@ -916,8 +956,8 @@ struct linux_target_ops the_low_target = {
   mips_remove_point,
   mips_stopped_by_watchpoint,
   mips_stopped_data_address,
-  NULL,
-  NULL,
+  mips_collect_ptrace_register,
+  mips_supply_ptrace_register,
   NULL, /* siginfo_fixup */
   mips_linux_new_process,
   mips_linux_delete_process,


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]