diff --git a/gdb/ChangeLog b/gdb/ChangeLog index a877d0b30f..1cc8753619 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,9 @@ +2012-06-15 H.J. Lu + + * amd64-linux-nat.c (AMD64_LINUX_X32_DS): New. + (amd64_linux_read_description): Check DS segment register for + x32 process. + 2012-06-15 Tom Tromey * dwarf2read.c (dw2_find_symbol_file): Unconditionally use diff --git a/gdb/amd64-linux-nat.c b/gdb/amd64-linux-nat.c index 5ebba3a747..ce62e2a8ca 100644 --- a/gdb/amd64-linux-nat.c +++ b/gdb/amd64-linux-nat.c @@ -755,16 +755,23 @@ amd64_linux_siginfo_fixup (siginfo_t *native, gdb_byte *inf, int direction) Value of CS segment register: 1. 64bit process: 0x33. 2. 32bit process: 0x23. + + Value of DS segment register: + 1. LP64 process: 0x0. + 2. X32 process: 0x2b. */ #define AMD64_LINUX_USER64_CS 0x33 +#define AMD64_LINUX_X32_DS 0x2b static const struct target_desc * amd64_linux_read_description (struct target_ops *ops) { unsigned long cs; + unsigned long ds; int tid; int is_64bit; + int is_x32; static uint64_t xcr0; /* GNU/Linux LWP ID's are process ID's. */ @@ -781,6 +788,18 @@ amd64_linux_read_description (struct target_ops *ops) 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")); + if (have_ptrace_getregset == -1) { uint64_t xstateregs[(I386_XSTATE_SSE_SIZE / sizeof (uint64_t))]; @@ -808,14 +827,24 @@ amd64_linux_read_description (struct target_ops *ops) && (xcr0 & I386_XSTATE_AVX_MASK) == I386_XSTATE_AVX_MASK) { if (is_64bit) - return tdesc_amd64_avx_linux; + { + if (is_x32) + return tdesc_x32_avx_linux; + else + return tdesc_amd64_avx_linux; + } else return tdesc_i386_avx_linux; } else { if (is_64bit) - return tdesc_amd64_linux; + { + if (is_x32) + return tdesc_x32_linux; + else + return tdesc_amd64_linux; + } else return tdesc_i386_linux; }