Index: gdb/amd64-linux-tdep.c |
diff --git a/gdb/amd64-linux-tdep.c b/gdb/amd64-linux-tdep.c |
index ca9ade6bc671a1cfe470dd57422496b59bd7b8d5..d9192164ec41ed89a611b6a097b0422eff3e07c9 100644 |
--- a/gdb/amd64-linux-tdep.c |
+++ b/gdb/amd64-linux-tdep.c |
@@ -38,9 +38,12 @@ |
#include "amd64-tdep.h" |
#include "solib-svr4.h" |
#include "xml-syscall.h" |
+#include "glibc-tdep.h" |
#include "features/i386/amd64-linux.c" |
#include "features/i386/amd64-avx-linux.c" |
+#include "features/i386/x32-linux.c" |
+#include "features/i386/x32-avx-linux.c" |
/* The syscall's XML filename for i386. */ |
#define XML_SYSCALL_FILENAME_AMD64 "syscalls/amd64-linux.xml" |
@@ -104,7 +107,7 @@ int amd64_linux_gregset_reg_offset[] = |
#define LINUX_SIGTRAMP_INSN1 0x0f /* syscall */ |
#define LINUX_SIGTRAMP_OFFSET1 7 |
-static const gdb_byte linux_sigtramp_code[] = |
+static const gdb_byte amd64_linux_sigtramp_code[] = |
{ |
/* mov $__NR_rt_sigreturn, %rax */ |
LINUX_SIGTRAMP_INSN0, 0xc7, 0xc0, 0x0f, 0x00, 0x00, 0x00, |
@@ -112,7 +115,15 @@ static const gdb_byte linux_sigtramp_code[] = |
LINUX_SIGTRAMP_INSN1, 0x05 |
}; |
-#define LINUX_SIGTRAMP_LEN (sizeof linux_sigtramp_code) |
+static const gdb_byte amd64_x32_linux_sigtramp_code[] = |
+{ |
+ /* mov $__NR_rt_sigreturn, %rax. */ |
+ LINUX_SIGTRAMP_INSN0, 0xc7, 0xc0, 0x01, 0x02, 0x00, 0x40, |
+ /* syscall */ |
+ LINUX_SIGTRAMP_INSN1, 0x05 |
+}; |
+ |
+#define LINUX_SIGTRAMP_LEN (sizeof amd64_linux_sigtramp_code) |
/* If PC is in a sigtramp routine, return the address of the start of |
the routine. Otherwise, return 0. */ |
@@ -120,6 +131,8 @@ static const gdb_byte linux_sigtramp_code[] = |
static CORE_ADDR |
amd64_linux_sigtramp_start (struct frame_info *this_frame) |
{ |
+ struct gdbarch *gdbarch; |
+ const gdb_byte *sigtramp_code; |
CORE_ADDR pc = get_frame_pc (this_frame); |
gdb_byte buf[LINUX_SIGTRAMP_LEN]; |
@@ -143,7 +156,12 @@ amd64_linux_sigtramp_start (struct frame_info *this_frame) |
return 0; |
} |
- if (memcmp (buf, linux_sigtramp_code, LINUX_SIGTRAMP_LEN) != 0) |
+ gdbarch = get_frame_arch (this_frame); |
+ if (gdbarch_ptr_bit (gdbarch) == 32) |
+ sigtramp_code = amd64_x32_linux_sigtramp_code; |
+ else |
+ sigtramp_code = amd64_linux_sigtramp_code; |
+ if (memcmp (buf, sigtramp_code, LINUX_SIGTRAMP_LEN) != 0) |
return 0; |
return pc; |
@@ -156,7 +174,7 @@ static int |
amd64_linux_sigtramp_p (struct frame_info *this_frame) |
{ |
CORE_ADDR pc = get_frame_pc (this_frame); |
- char *name; |
+ const char *name; |
find_pc_partial_function (pc, &name, NULL, NULL); |
@@ -1225,10 +1243,10 @@ amd64_linux_syscall_record (struct regcache *regcache) |
#define AMD64_LINUX_xstate 512 |
#define AMD64_LINUX_frame_size 560 |
-int |
+static int |
amd64_linux_record_signal (struct gdbarch *gdbarch, |
struct regcache *regcache, |
- enum target_signal signal) |
+ enum gdb_signal signal) |
{ |
ULONGEST rsp; |
@@ -1272,48 +1290,25 @@ amd64_linux_core_read_description (struct gdbarch *gdbarch, |
switch ((xcr0 & I386_XSTATE_AVX_MASK)) |
{ |
case I386_XSTATE_AVX_MASK: |
- return tdesc_amd64_avx_linux; |
+ if (gdbarch_ptr_bit (gdbarch) == 32) |
+ return tdesc_x32_avx_linux; |
+ else |
+ return tdesc_amd64_avx_linux; |
default: |
- return tdesc_amd64_linux; |
+ if (gdbarch_ptr_bit (gdbarch) == 32) |
+ return tdesc_x32_linux; |
+ else |
+ return tdesc_amd64_linux; |
} |
} |
static void |
-amd64_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) |
+amd64_linux_init_abi_common(struct gdbarch_info info, struct gdbarch *gdbarch) |
{ |
struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); |
- const struct target_desc *tdesc = info.target_desc; |
- struct tdesc_arch_data *tdesc_data = (void *) info.tdep_info; |
- const struct tdesc_feature *feature; |
- int valid_p; |
- |
- gdb_assert (tdesc_data); |
linux_init_abi (info, gdbarch); |
- tdep->gregset_reg_offset = amd64_linux_gregset_reg_offset; |
- tdep->gregset_num_regs = ARRAY_SIZE (amd64_linux_gregset_reg_offset); |
- tdep->sizeof_gregset = 27 * 8; |
- |
- amd64_init_abi (info, gdbarch); |
- |
- /* Reserve a number for orig_rax. */ |
- set_gdbarch_num_regs (gdbarch, AMD64_LINUX_NUM_REGS); |
- |
- if (! tdesc_has_registers (tdesc)) |
- tdesc = tdesc_amd64_linux; |
- tdep->tdesc = tdesc; |
- |
- feature = tdesc_find_feature (tdesc, "org.gnu.gdb.i386.linux"); |
- if (feature == NULL) |
- return; |
- |
- valid_p = tdesc_numbered_register (feature, tdesc_data, |
- AMD64_LINUX_ORIG_RAX_REGNUM, |
- "orig_rax"); |
- if (!valid_p) |
- return; |
- |
tdep->sigtramp_p = amd64_linux_sigtramp_p; |
tdep->sigcontext_addr = amd64_linux_sigcontext_addr; |
tdep->sc_reg_offset = amd64_linux_sc_reg_offset; |
@@ -1321,10 +1316,6 @@ amd64_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) |
tdep->xsave_xcr0_offset = I386_LINUX_XSAVE_XCR0_OFFSET; |
- /* GNU/Linux uses SVR4-style shared libraries. */ |
- set_solib_svr4_fetch_link_map_offsets |
- (gdbarch, svr4_lp64_fetch_link_map_offsets); |
- |
/* Add the %orig_rax register used for syscall restarting. */ |
set_gdbarch_write_pc (gdbarch, amd64_linux_write_pc); |
@@ -1342,6 +1333,9 @@ amd64_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) |
/* GNU/Linux uses SVR4-style shared libraries. */ |
set_gdbarch_skip_trampoline_code (gdbarch, find_solib_trampoline_target); |
+ /* GNU/Linux uses the dynamic linker included in the GNU C Library. */ |
+ set_gdbarch_skip_solib_resolver (gdbarch, glibc_skip_solib_resolver); |
+ |
/* Install supported register note sections. */ |
set_gdbarch_core_regset_sections (gdbarch, amd64_linux_regset_sections); |
@@ -1531,6 +1525,88 @@ amd64_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) |
tdep->i386_syscall_record = amd64_linux_syscall_record; |
} |
+ |
+static void |
+amd64_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) |
+{ |
+ struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); |
+ const struct target_desc *tdesc = info.target_desc; |
+ struct tdesc_arch_data *tdesc_data = (void *) info.tdep_info; |
+ const struct tdesc_feature *feature; |
+ int valid_p; |
+ |
+ gdb_assert (tdesc_data); |
+ |
+ tdep->gregset_reg_offset = amd64_linux_gregset_reg_offset; |
+ tdep->gregset_num_regs = ARRAY_SIZE (amd64_linux_gregset_reg_offset); |
+ tdep->sizeof_gregset = 27 * 8; |
+ |
+ amd64_init_abi (info, gdbarch); |
+ |
+ /* Reserve a number for orig_rax. */ |
+ set_gdbarch_num_regs (gdbarch, AMD64_LINUX_NUM_REGS); |
+ |
+ if (! tdesc_has_registers (tdesc)) |
+ tdesc = tdesc_amd64_linux; |
+ tdep->tdesc = tdesc; |
+ |
+ feature = tdesc_find_feature (tdesc, "org.gnu.gdb.i386.linux"); |
+ if (feature == NULL) |
+ return; |
+ |
+ valid_p = tdesc_numbered_register (feature, tdesc_data, |
+ AMD64_LINUX_ORIG_RAX_REGNUM, |
+ "orig_rax"); |
+ if (!valid_p) |
+ return; |
+ |
+ amd64_linux_init_abi_common (info, gdbarch); |
+ |
+ /* GNU/Linux uses SVR4-style shared libraries. */ |
+ set_solib_svr4_fetch_link_map_offsets |
+ (gdbarch, svr4_lp64_fetch_link_map_offsets); |
+} |
+ |
+static void |
+amd64_x32_linux_init_abi(struct gdbarch_info info, struct gdbarch *gdbarch) |
+{ |
+ struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); |
+ const struct target_desc *tdesc = info.target_desc; |
+ struct tdesc_arch_data *tdesc_data = (void *) info.tdep_info; |
+ const struct tdesc_feature *feature; |
+ int valid_p; |
+ |
+ gdb_assert (tdesc_data); |
+ |
+ tdep->gregset_reg_offset = amd64_linux_gregset_reg_offset; |
+ tdep->gregset_num_regs = ARRAY_SIZE (amd64_linux_gregset_reg_offset); |
+ tdep->sizeof_gregset = 27 * 8; |
+ |
+ amd64_x32_init_abi (info, gdbarch); |
+ |
+ /* Reserve a number for orig_rax. */ |
+ set_gdbarch_num_regs (gdbarch, AMD64_LINUX_NUM_REGS); |
+ |
+ if (! tdesc_has_registers (tdesc)) |
+ tdesc = tdesc_x32_linux; |
+ tdep->tdesc = tdesc; |
+ |
+ feature = tdesc_find_feature (tdesc, "org.gnu.gdb.i386.linux"); |
+ if (feature == NULL) |
+ return; |
+ |
+ valid_p = tdesc_numbered_register (feature, tdesc_data, |
+ AMD64_LINUX_ORIG_RAX_REGNUM, |
+ "orig_rax"); |
+ if (!valid_p) |
+ return; |
+ |
+ amd64_linux_init_abi_common (info, gdbarch); |
+ |
+ /* GNU/Linux uses SVR4-style shared libraries. */ |
+ set_solib_svr4_fetch_link_map_offsets |
+ (gdbarch, svr4_ilp32_fetch_link_map_offsets); |
+} |
/* Provide a prototype to silence -Wmissing-prototypes. */ |
@@ -1541,8 +1617,12 @@ _initialize_amd64_linux_tdep (void) |
{ |
gdbarch_register_osabi (bfd_arch_i386, bfd_mach_x86_64, |
GDB_OSABI_LINUX, amd64_linux_init_abi); |
+ gdbarch_register_osabi (bfd_arch_i386, bfd_mach_x64_32, |
+ GDB_OSABI_LINUX, amd64_x32_linux_init_abi); |
/* Initialize the Linux target description. */ |
initialize_tdesc_amd64_linux (); |
initialize_tdesc_amd64_avx_linux (); |
+ initialize_tdesc_x32_linux (); |
+ initialize_tdesc_x32_avx_linux (); |
} |