| 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 ();
|
| }
|
|
|