]> git.ipfire.org Git - thirdparty/binutils-gdb.git/commitdiff
Fix gdbserver's regcache_raw_read_unsigned on big endian hosts users/palves/gdbserver-extract-unsigned-integer
authorPedro Alves <palves@redhat.com>
Thu, 11 Feb 2016 11:44:35 +0000 (11:44 +0000)
committerPedro Alves <palves@redhat.com>
Thu, 11 Feb 2016 12:20:36 +0000 (12:20 +0000)
The regcache_raw_read_unsigned function is memcpy'ing a 32-bit value
directly into a 64-bit variable, which doesn't work on big endian
targets.

Fix this by memcpy'ing to a buffer, and then using
extract_unsigned_integer, just like gdb's version.

gdb/gdbserver/ChangeLog:
2016-02-11  Pedro Alves  <palves@redhat.com>

* Makefile.in (SFILES): Add $(srcdir)/common/gdb-byteswap.c.
(gdb-byteswap.o): New rule.
* regcache.c: Include "gdb-byteswap.h".
(host_bfd_endian): New function.
(regcache_raw_read_unsigned): Use extract_unsigned_integer and
host_bfd_endian.

gdb/gdbserver/Makefile.in
gdb/gdbserver/regcache.c

index 1e874e39ef1ecf0a140fda771cda2eba53380ba3..06a6f1bbff4c14405353ce1e15a85ec97ebf7d4f 100644 (file)
@@ -185,7 +185,8 @@ SFILES=     $(srcdir)/gdbreplay.c $(srcdir)/inferiors.c $(srcdir)/dll.c \
        $(srcdir)/common/btrace-common.c \
        $(srcdir)/common/fileio.c $(srcdir)/nat/linux-namespaces.c \
        $(srcdir)/arch/arm.c $(srcdir)/common/common-regcache.c \
-       $(srcdir)/arch/arm-linux.c $(srcdir)/arch/arm-get-next-pcs.c
+       $(srcdir)/arch/arm-linux.c $(srcdir)/arch/arm-get-next-pcs.c \
+       $(srcdir)/common/gdb-byteswap.c
 
 DEPFILES = @GDBSERVER_DEPFILES@
 
@@ -200,6 +201,7 @@ OBS = agent.o ax.o inferiors.o regcache.o remote-utils.o server.o signals.o \
       common-utils.o ptid.o buffer.o format.o filestuff.o dll.o notif.o \
       tdesc.o print-utils.o rsp-low.o errors.o common-debug.o cleanups.o \
       common-exceptions.o symbol.o btrace-common.o fileio.o common-regcache.o \
+      gdb-byteswap.o \
       $(XML_BUILTIN) $(DEPFILES) $(LIBOBJS)
 GDBREPLAY_OBS = gdbreplay.o version.o
 GDBSERVER_LIBS = @GDBSERVER_LIBS@
@@ -590,6 +592,9 @@ fileio.o: ../common/fileio.c
 common-regcache.o: ../common/common-regcache.c
        $(COMPILE) $<
        $(POSTCOMPILE)
+gdb-byteswap.o: ../common/gdb-byteswap.c
+       $(COMPILE) $<
+       $(POSTCOMPILE)
 
 # Arch object files rules form ../arch
 
index 2af8e241d98db5a8795682aa203f1585a4820ddb..f875b1091d780f49899599e83f9e4ccee7d0cf89 100644 (file)
@@ -21,6 +21,9 @@
 #include "gdbthread.h"
 #include "tdesc.h"
 #include "rsp-low.h"
+#include "bfd-types.h"
+#include "gdb-byteswap.h"
+
 #ifndef IN_PROCESS_AGENT
 
 struct regcache *
@@ -424,14 +427,25 @@ collect_register (struct regcache *regcache, int n, void *buf)
          register_size (regcache->tdesc, n));
 }
 
+#ifndef IN_PROCESS_AGENT
+
+/* Return host endianness as an enum bfd_endian.  */
+
+static enum bfd_endian
+host_bfd_endian (void)
+{
+  return (__BYTE_ORDER == __LITTLE_ENDIAN
+         ? BFD_ENDIAN_LITTLE
+         : BFD_ENDIAN_BIG);
+}
+
 enum register_status
 regcache_raw_read_unsigned (struct regcache *regcache, int regnum,
                            ULONGEST *val)
 {
   int size;
-
-  gdb_assert (regcache != NULL);
-  gdb_assert (regnum >= 0 && regnum < regcache->tdesc->num_registers);
+  gdb_byte *buf;
+  enum bfd_endian byteorder;
 
   size = register_size (regcache->tdesc, regnum);
 
@@ -440,14 +454,17 @@ regcache_raw_read_unsigned (struct regcache *regcache, int regnum,
             "%d bytes."),
           (int) sizeof (ULONGEST));
 
-  *val = 0;
-  collect_register (regcache, regnum, val);
+  buf = (gdb_byte *) alloca (size);
+  collect_register (regcache, regnum, buf);
+
+  /* Assume the inferior's byte order is the same as gdbserver's (the
+     host).  */
+  byteorder = host_bfd_endian ();
 
+  *val = extract_unsigned_integer (buf, size, byteorder);
   return REG_VALID;
 }
 
-#ifndef IN_PROCESS_AGENT
-
 void
 collect_register_as_string (struct regcache *regcache, int n, char *buf)
 {