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] PR gdb/22286: linux-nat-trad: Support arbitrary register widths


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

commit 1d7611244c140a1a08f3365cd5881120eba7749d
Author: Maciej W. Rozycki <macro@mips.com>
Date:   Wed May 16 20:43:30 2018 +0100

    PR gdb/22286: linux-nat-trad: Support arbitrary register widths
    
    Update `fetch_register' and `store_register' code to support arbitrary
    register widths rather than only ones that are a multiply of the size of
    the `ptrace' data type used with PTRACE_PEEKUSR and PTRACE_POKEUSR
    requests to access registers.  Remove associated assertions, correcting
    an issue with accessing the DSPControl (`$dspctl') register on n64 MIPS
    native targets:
    
    (gdb) print /x $dspctl
    .../gdb/linux-nat-trad.c:50: internal-error: void linux_nat_trad_target::fetch_register(regcache*, int): Assertion `(size % sizeof (PTRACE_TYPE_RET)) == 0' failed.
    A problem internal to GDB has been detected,
    further debugging may prove unreliable.
    Quit this debugging session? (y or n) n
    
    This is a bug, please report it.  For instructions, see:
    <http://www.gnu.org/software/gdb/bugs/>.
    
    .../gdb/linux-nat-trad.c:50: internal-error: void linux_nat_trad_target::fetch_register(regcache*, int): Assertion `(size % sizeof (PTRACE_TYPE_RET)) == 0' failed.
    A problem internal to GDB has been detected,
    further debugging may prove unreliable.
    Create a core file of GDB? (y or n) n
    Command aborted.
    (gdb)
    
    All registers are now reported correctly and their architectural
    hardware widths respected:
    
    (gdb) print /x $dspctl
    $1 = 0x55aa33cc
    (gdb) info registers
                      zero               at               v0               v1
     R0   0000000000000000 0000000000000001 000000fff7ffeb20 0000000000000000
                        a0               a1               a2               a3
     R4   0000000000000001 000000ffffffeaf8 000000ffffffeb08 0000000000000000
                        a4               a5               a6               a7
     R8   000000fff7ee3800 000000fff7ede8f0 000000ffffffeaf0 2f2f2f2f2f2f2f2f
                        t0               t1               t2               t3
     R12  0000000000000437 0000000000000002 000000fff7ffd000 0000000120000ad0
                        s0               s1               s2               s3
     R16  000000fff7ee2068 0000000120000e60 0000000000000000 0000000000000000
                        s4               s5               s6               s7
     R20  0000000000521ec8 0000000000522608 0000000000000000 0000000000000000
                        t8               t9               k0               k1
     R24  0000000000000000 0000000120000d9c 0000000000000000 0000000000000000
                        gp               sp               s8               ra
     R28  0000000120019030 000000ffffffe990 000000ffffffe990 000000fff7d5b88c
                    status               lo               hi         badvaddr
          0000000000109cf3 0000000000005ea5 0000000000000211 000000fff7fc6fe0
                     cause               pc
          0000000000800024 0000000120000dbc
                      fcsr              fir              hi1              lo1
                  00000000         00f30000 0000000000000000 0101010101010101
                       hi2              lo2              hi3              lo3
          0202020202020202 0303030303030303 0404040404040404 0505050505050505
                    dspctl          restart
                  55aa33cc 0000000000000000
    (gdb)
    
    NB due to the lack of access to 64-bit DSP hardware all DSP register
    values in the dumps are artificial and have been created with a debug
    change applied to the kernel handler of the `ptrace' syscall.
    
    The use of `store_unsigned_integer' and `extract_unsigned_integer'
    unconditionally in all cases rather than when actual data occupies a
    part of the data quantity exchanged with `ptrace' makes code perhaps
    marginally slower, however I think avoiding it is not worth code
    obfuscation it would cause.  If this turns out unfounded, then there
    should be no problem with optimizing this code later.
    
    	gdb/
    	PR gdb/22286
    	* linux-nat-trad.c (linux_nat_trad_target::fetch_register):
    	Also handle registers whose width is not a multiple of
    	PTRACE_TYPE_RET.
    	(linux_nat_trad_target::store_register): Likewise.

Diff:
---
 gdb/ChangeLog        |  8 ++++++++
 gdb/linux-nat-trad.c | 28 ++++++++++++++++++----------
 2 files changed, 26 insertions(+), 10 deletions(-)

diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index b8d8fe6..eb3c5f7 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,3 +1,11 @@
+2018-05-16  Maciej W. Rozycki  <macro@mips.com>
+
+	PR gdb/22286
+	* linux-nat-trad.c (linux_nat_trad_target::fetch_register):
+	Also handle registers whose width is not a multiple of
+	PTRACE_TYPE_RET.
+	(linux_nat_trad_target::store_register): Likewise.
+
 2018-05-16  Tom Tromey  <tom@tromey.com>
 
 	* gdbcore.h (core_bfd): Redefine.
diff --git a/gdb/linux-nat-trad.c b/gdb/linux-nat-trad.c
index 066d15a..ce6788c 100644
--- a/gdb/linux-nat-trad.c
+++ b/gdb/linux-nat-trad.c
@@ -29,9 +29,10 @@ void
 linux_nat_trad_target::fetch_register (struct regcache *regcache, int regnum)
 {
   struct gdbarch *gdbarch = regcache->arch ();
+  enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
   CORE_ADDR addr;
+  gdb_byte *buf;
   size_t size;
-  PTRACE_TYPE_RET *buf;
   pid_t pid;
   int i;
 
@@ -47,18 +48,21 @@ linux_nat_trad_target::fetch_register (struct regcache *regcache, int regnum)
   pid = get_ptrace_pid (regcache_get_ptid (regcache));
 
   size = register_size (gdbarch, regnum);
-  gdb_assert ((size % sizeof (PTRACE_TYPE_RET)) == 0);
-  buf = (PTRACE_TYPE_RET *) alloca (size);
+  buf = (gdb_byte *) alloca (size);
 
   /* Read the register contents from the inferior a chunk at a time.  */
-  for (i = 0; i < size / sizeof (PTRACE_TYPE_RET); i++)
+  for (i = 0; i < size; i += sizeof (PTRACE_TYPE_RET))
     {
+      size_t chunk = std::min (sizeof (PTRACE_TYPE_RET), size - i);
+      PTRACE_TYPE_RET val;
+
       errno = 0;
-      buf[i] = ptrace (PT_READ_U, pid, (PTRACE_TYPE_ARG3)(uintptr_t)addr, 0);
+      val = ptrace (PT_READ_U, pid, (PTRACE_TYPE_ARG3) (uintptr_t) addr, 0);
       if (errno != 0)
 	error (_("Couldn't read register %s (#%d): %s."),
 	       gdbarch_register_name (gdbarch, regnum),
 	       regnum, safe_strerror (errno));
+      store_unsigned_integer (buf + i, chunk, byte_order, val);
 
       addr += sizeof (PTRACE_TYPE_RET);
     }
@@ -87,9 +91,10 @@ linux_nat_trad_target::store_register (const struct regcache *regcache,
 				       int regnum)
 {
   struct gdbarch *gdbarch = regcache->arch ();
+  enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
   CORE_ADDR addr;
   size_t size;
-  PTRACE_TYPE_RET *buf;
+  gdb_byte *buf;
   pid_t pid;
   int i;
 
@@ -102,15 +107,18 @@ linux_nat_trad_target::store_register (const struct regcache *regcache,
   pid = get_ptrace_pid (regcache_get_ptid (regcache));
 
   size = register_size (gdbarch, regnum);
-  gdb_assert ((size % sizeof (PTRACE_TYPE_RET)) == 0);
-  buf = (PTRACE_TYPE_RET *) alloca (size);
+  buf = (gdb_byte *) alloca (size);
 
   /* Write the register contents into the inferior a chunk at a time.  */
   regcache_raw_collect (regcache, regnum, buf);
-  for (i = 0; i < size / sizeof (PTRACE_TYPE_RET); i++)
+  for (i = 0; i < size; i += sizeof (PTRACE_TYPE_RET))
     {
+      size_t chunk = std::min (sizeof (PTRACE_TYPE_RET), size - i);
+      PTRACE_TYPE_RET val;
+
+      val = extract_unsigned_integer (buf + i, chunk, byte_order);
       errno = 0;
-      ptrace (PT_WRITE_U, pid, (PTRACE_TYPE_ARG3)(uintptr_t)addr, buf[i]);
+      ptrace (PT_WRITE_U, pid, (PTRACE_TYPE_ARG3) (uintptr_t) addr, val);
       if (errno != 0)
 	error (_("Couldn't write register %s (#%d): %s."),
 	       gdbarch_register_name (gdbarch, regnum),


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