public inbox for gdb-patches@sourceware.org
 help / color / mirror / Atom feed
* [pushed] Fix PR server/20414 - x32 gdbserver always crashes inferior
@ 2016-07-26 21:22 Pedro Alves
  0 siblings, 0 replies; only message in thread
From: Pedro Alves @ 2016-07-26 21:22 UTC (permalink / raw)
  To: gdb-patches

Debugging an x32 process with an x32 gdbserver always results in:

 (gdb) c
 Continuing.

 Program received signal SIGSEGV, Segmentation fault.
 0xf7de9600 in _dl_debug_state () from target:/libx32/ld-linux-x32.so.2
 (gdb)

Looking at the remote debug logs reveals the problem, here:

  Packet received: T05swbreak:;06:a0d4ffff00000000;07:b8d3ffff00000000;10:0096def701000000;thread:p7d7a.7d7a;core:1;
                                                                          ^^^^^^^^^^^^^^^^

The underlined value is the expedited value of RIP (in little endian).
But notice that 01 in 0x01f7de9600, while gdb says the program stopped
at 0xf7de9600.  0x01ffffffff is over 32 bits, which indicates that
something wen't wrong somewhere in gdbserver.

The problem turns out to be in gdbserver's x86_get_pc / x86_set_pc
routines, where "unsigned long" is used assuming that it can fit a
64-bit value, while unsigned long is actually 32-bit on x32.  The
result is that collect_register_by_name / supply_register_by_name end
up reading/writing random bytes off the stack.

Fix this by using explicit uint64_t instead of unsigned long.
For consistency, use uint32_t instead of unsigned int in the 32-bit
paths.

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

	PR server/20414
	* linux-x86-low.c (x86_get_pc, x86_set_pc): Use uint64_t instead
	of unsigned long for 64-bit registers and use uint32_t instead of
	unsigned int for 32-bit registers.
---
 gdb/gdbserver/ChangeLog       |  7 +++++++
 gdb/gdbserver/linux-x86-low.c | 12 ++++++++----
 2 files changed, 15 insertions(+), 4 deletions(-)

diff --git a/gdb/gdbserver/ChangeLog b/gdb/gdbserver/ChangeLog
index 5e6fb7e..dfdbc21 100644
--- a/gdb/gdbserver/ChangeLog
+++ b/gdb/gdbserver/ChangeLog
@@ -1,5 +1,12 @@
 2016-07-26  Pedro Alves  <palves@redhat.com>
 
+	PR server/20414
+	* linux-x86-low.c (x86_get_pc, x86_set_pc): Use uint64_t instead
+	of unsigned long for 64-bit registers and use uint32_t instead of
+	unsigned int for 32-bit registers.
+
+2016-07-26  Pedro Alves  <palves@redhat.com>
+
 	* linux-x86-low.c (x86_siginfo_fixup): Rename 'native' parameter
 	to 'ptrace'.
 
diff --git a/gdb/gdbserver/linux-x86-low.c b/gdb/gdbserver/linux-x86-low.c
index 4e6dbce..d6b67c1 100644
--- a/gdb/gdbserver/linux-x86-low.c
+++ b/gdb/gdbserver/linux-x86-low.c
@@ -427,13 +427,15 @@ x86_get_pc (struct regcache *regcache)
 
   if (use_64bit)
     {
-      unsigned long pc;
+      uint64_t pc;
+
       collect_register_by_name (regcache, "rip", &pc);
       return (CORE_ADDR) pc;
     }
   else
     {
-      unsigned int pc;
+      uint32_t pc;
+
       collect_register_by_name (regcache, "eip", &pc);
       return (CORE_ADDR) pc;
     }
@@ -446,12 +448,14 @@ x86_set_pc (struct regcache *regcache, CORE_ADDR pc)
 
   if (use_64bit)
     {
-      unsigned long newpc = pc;
+      uint64_t newpc = pc;
+
       supply_register_by_name (regcache, "rip", &newpc);
     }
   else
     {
-      unsigned int newpc = pc;
+      uint32_t newpc = pc;
+
       supply_register_by_name (regcache, "eip", &newpc);
     }
 }
-- 
2.5.5

^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2016-07-26 21:22 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-07-26 21:22 [pushed] Fix PR server/20414 - x32 gdbserver always crashes inferior Pedro Alves

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).