diff options
-rw-r--r-- | gdb/nat/x86-linux.c | 47 | ||||
-rw-r--r-- | gdb/nat/x86-linux.h | 28 | ||||
-rw-r--r-- | gdb/x86-linux-nat.c | 42 |
3 files changed, 80 insertions, 37 deletions
diff --git a/gdb/nat/x86-linux.c b/gdb/nat/x86-linux.c index e61f4d7..4242a1b 100644 --- a/gdb/nat/x86-linux.c +++ b/gdb/nat/x86-linux.c @@ -20,6 +20,8 @@ #include "gdbsupport/common-defs.h" #include "x86-linux.h" #include "x86-linux-dregs.h" +#include "nat/gdb_ptrace.h" +#include <sys/user.h> /* Per-thread arch-specific data we want to keep. */ @@ -80,3 +82,48 @@ x86_linux_prepare_to_resume (struct lwp_info *lwp) { x86_linux_update_debug_registers (lwp); } + +#ifdef __x86_64__ +/* Value of CS segment register: + 64bit process: 0x33 + 32bit process: 0x23 */ +#define AMD64_LINUX_USER64_CS 0x33 + +/* Value of DS segment register: + LP64 process: 0x0 + X32 process: 0x2b */ +#define AMD64_LINUX_X32_DS 0x2b +#endif + +/* See nat/x86-linux.h. */ + +x86_linux_arch_size +x86_linux_ptrace_get_arch_size (int tid) +{ +#ifdef __x86_64__ + unsigned long cs; + unsigned long ds; + + /* Get CS register. */ + errno = 0; + cs = ptrace (PTRACE_PEEKUSER, tid, + offsetof (struct user_regs_struct, cs), 0); + if (errno != 0) + perror_with_name (_("Couldn't get CS register")); + + bool is_64bit = cs == AMD64_LINUX_USER64_CS; + + /* Get DS register. */ + errno = 0; + ds = ptrace (PTRACE_PEEKUSER, tid, + offsetof (struct user_regs_struct, ds), 0); + if (errno != 0) + perror_with_name (_("Couldn't get DS register")); + + bool is_x32 = ds == AMD64_LINUX_X32_DS; + + return x86_linux_arch_size (is_64bit, is_x32); +#else + return x86_linux_arch_size (false, false); +#endif +} diff --git a/gdb/nat/x86-linux.h b/gdb/nat/x86-linux.h index 8228821..15153ea 100644 --- a/gdb/nat/x86-linux.h +++ b/gdb/nat/x86-linux.h @@ -47,4 +47,32 @@ extern void x86_linux_delete_thread (struct arch_lwp_info *arch_lwp); extern void x86_linux_prepare_to_resume (struct lwp_info *lwp); +/* Return value from x86_linux_ptrace_get_arch_size function. Indicates if + a thread is 32-bit, 64-bit, or x32. */ + +struct x86_linux_arch_size +{ + explicit x86_linux_arch_size (bool is_64bit, bool is_x32) + : m_is_64bit (is_64bit), + m_is_x32 (is_x32) + { + /* Nothing. */ + } + + bool is_64bit () const + { return m_is_64bit; } + + bool is_x32 () const + { return m_is_x32; } + +private: + bool m_is_64bit = false; + bool m_is_x32 = false; +}; + +/* Use ptrace calls to figure out if thread TID is 32-bit, 64-bit, or + 64-bit running in x32 mode. */ + +extern x86_linux_arch_size x86_linux_ptrace_get_arch_size (int tid); + #endif /* NAT_X86_LINUX_H */ diff --git a/gdb/x86-linux-nat.c b/gdb/x86-linux-nat.c index b93ffca..b39d05c 100644 --- a/gdb/x86-linux-nat.c +++ b/gdb/x86-linux-nat.c @@ -91,18 +91,6 @@ x86_linux_nat_target::post_startup_inferior (ptid_t ptid) linux_nat_target::post_startup_inferior (ptid); } -#ifdef __x86_64__ -/* Value of CS segment register: - 64bit process: 0x33 - 32bit process: 0x23 */ -#define AMD64_LINUX_USER64_CS 0x33 - -/* Value of DS segment register: - LP64 process: 0x0 - X32 process: 0x2b */ -#define AMD64_LINUX_X32_DS 0x2b -#endif - /* Get Linux/x86 target description from running target. */ const struct target_desc * @@ -122,31 +110,11 @@ x86_linux_nat_target::read_description () tid = inferior_ptid.pid (); #ifdef __x86_64__ - { - unsigned long cs; - unsigned long ds; - - /* Get CS register. */ - errno = 0; - cs = ptrace (PTRACE_PEEKUSER, tid, - offsetof (struct user_regs_struct, cs), 0); - if (errno != 0) - perror_with_name (_("Couldn't get CS register")); - - is_64bit = cs == AMD64_LINUX_USER64_CS; - - /* Get DS register. */ - errno = 0; - ds = ptrace (PTRACE_PEEKUSER, tid, - offsetof (struct user_regs_struct, ds), 0); - if (errno != 0) - perror_with_name (_("Couldn't get DS register")); - - is_x32 = ds == AMD64_LINUX_X32_DS; - - if (sizeof (void *) == 4 && is_64bit && !is_x32) - error (_("Can't debug 64-bit process with 32-bit GDB")); - } + + x86_linux_arch_size arch_size = x86_linux_ptrace_get_arch_size (tid); + is_64bit = arch_size.is_64bit (); + is_x32 = arch_size.is_x32 (); + #elif HAVE_PTRACE_GETFPXREGS if (have_ptrace_getfpxregs == -1) { |