summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPedro Alves <palves@redhat.com>2016-02-11 11:44:35 +0000
committerPedro Alves <palves@redhat.com>2016-02-11 12:20:36 +0000
commit04956cf9b84b53728e20f0dae1f561ab26714453 (patch)
treedd8aaeac0a7d0bb0acbc9536295dcd064d3303ec
parentca47aa93d4a13e676e771041eb7372ff2cdb1487 (diff)
downloadbinutils-gdb-users/palves/gdbserver-extract-unsigned-integer.tar.gz
Fix gdbserver's regcache_raw_read_unsigned on big endian hostsusers/palves/gdbserver-extract-unsigned-integer
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.
-rw-r--r--gdb/gdbserver/Makefile.in7
-rw-r--r--gdb/gdbserver/regcache.c31
2 files changed, 30 insertions, 8 deletions
diff --git a/gdb/gdbserver/Makefile.in b/gdb/gdbserver/Makefile.in
index 1e874e39ef1..06a6f1bbff4 100644
--- a/gdb/gdbserver/Makefile.in
+++ b/gdb/gdbserver/Makefile.in
@@ -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
diff --git a/gdb/gdbserver/regcache.c b/gdb/gdbserver/regcache.c
index 2af8e241d98..f875b1091d7 100644
--- a/gdb/gdbserver/regcache.c
+++ b/gdb/gdbserver/regcache.c
@@ -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)
{