/* Target-dependent code for GNU/Linux x86-64.
- Copyright (C) 2001-2015 Free Software Foundation, Inc.
+ Copyright (C) 2001-2022 Free Software Foundation, Inc.
Contributed by Jiri Smid, SuSE Labs.
This file is part of GDB.
#include "amd64-linux-tdep.h"
#include "i386-linux-tdep.h"
#include "linux-tdep.h"
-#include "x86-xstate.h"
+#include "gdbsupport/x86-xstate.h"
#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/amd64-mpx-linux.c"
-#include "features/i386/amd64-avx512-linux.c"
-
-#include "features/i386/x32-linux.c"
-#include "features/i386/x32-avx-linux.c"
-#include "features/i386/x32-avx512-linux.c"
+#include "arch/amd64.h"
+#include "target-descriptions.h"
+#include "expop.h"
/* The syscall's XML filename for i386. */
#define XML_SYSCALL_FILENAME_AMD64 "syscalls/amd64-linux.xml"
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, /* PKEYS register pkru */
+
+ /* End of hardware registers */
+ 21 * 8, 22 * 8, /* fs_base and gs_base. */
15 * 8 /* "orig_rax" */
};
\f
PC is not at the start of the instruction sequence, there will be
a few trailing readable bytes on the stack. */
- if (!safe_frame_unwind_memory (this_frame, pc, buf, sizeof buf))
+ if (!safe_frame_unwind_memory (this_frame, pc, buf))
return 0;
if (buf[0] != LINUX_SIGTRAMP_INSN0)
return 0;
pc -= LINUX_SIGTRAMP_OFFSET1;
- if (!safe_frame_unwind_memory (this_frame, pc, buf, sizeof buf))
+ if (!safe_frame_unwind_memory (this_frame, pc, buf))
return 0;
}
static LONGEST
amd64_linux_get_syscall_number (struct gdbarch *gdbarch,
- ptid_t ptid)
+ thread_info *thread)
{
- struct regcache *regcache = get_thread_regcache (ptid);
+ struct regcache *regcache = get_thread_regcache (thread);
enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
/* The content of a register. */
gdb_byte buf[8];
/* Getting the system call number from the register.
When dealing with x86_64 architecture, this information
is stored at %rax register. */
- regcache_cooked_read (regcache, AMD64_LINUX_ORIG_RAX_REGNUM, buf);
+ regcache->cooked_read (AMD64_LINUX_ORIG_RAX_REGNUM, buf);
- ret = extract_signed_integer (buf, 8, byte_order);
+ ret = extract_signed_integer (buf, byte_order);
return ret;
}
amd64_linux_register_reggroup_p (struct gdbarch *gdbarch, int regnum,
struct reggroup *group)
{
- if (regnum == AMD64_LINUX_ORIG_RAX_REGNUM)
+ if (regnum == AMD64_LINUX_ORIG_RAX_REGNUM
+ || regnum == AMD64_FSBASE_REGNUM
+ || regnum == AMD64_GSBASE_REGNUM)
return (group == system_reggroup
- || group == save_reggroup
- || group == restore_reggroup);
+ || group == save_reggroup
+ || group == restore_reggroup);
return i386_register_reggroup_p (gdbarch, regnum, group);
}
static enum gdb_syscall
amd64_canonicalize_syscall (enum amd64_syscall syscall_number)
{
+ DIAGNOSTIC_PUSH
+ DIAGNOSTIC_IGNORE_SWITCH_DIFFERENT_ENUM_TYPES
+
switch (syscall_number) {
case amd64_sys_read:
case amd64_x32_sys_read:
default:
return gdb_sys_no_syscall;
}
+
+ DIAGNOSTIC_POP
}
/* Parse the arguments of current system call instruction and record
case amd64_sys_rt_sigreturn:
case amd64_x32_sys_rt_sigreturn:
if (amd64_all_but_ip_registers_record (regcache))
- return -1;
+ return -1;
return 0;
break;
if (syscall_gdb == gdb_sys_no_syscall)
{
- printf_unfiltered (_("Process record and replay target doesn't "
- "support syscall number %s\n"),
- pulongest (syscall_native));
+ fprintf_unfiltered (gdb_stderr,
+ _("Process record and replay target doesn't "
+ "support syscall number %s\n"),
+ pulongest (syscall_native));
return -1;
}
else
{
ret = record_linux_system_call (syscall_gdb, regcache,
- linux_record_tdep_p);
+ linux_record_tdep_p);
if (ret)
- return ret;
+ return ret;
}
record_regs:
static int
amd64_linux_record_signal (struct gdbarch *gdbarch,
- struct regcache *regcache,
- enum gdb_signal signal)
+ struct regcache *regcache,
+ enum gdb_signal signal)
{
ULONGEST rsp;
sp -= sizeof (struct rt_sigframe); */
rsp -= AMD64_LINUX_frame_size;
if (record_full_arch_list_add_mem (rsp, AMD64_LINUX_redzone
- + AMD64_LINUX_xstate
- + AMD64_LINUX_frame_size))
+ + AMD64_LINUX_xstate
+ + AMD64_LINUX_frame_size))
return -1;
if (record_full_arch_list_add_end ())
return 0;
}
+const target_desc *
+amd64_linux_read_description (uint64_t xcr0_features_bit, bool is_x32)
+{
+ static target_desc *amd64_linux_tdescs \
+ [2/*AVX*/][2/*MPX*/][2/*AVX512*/][2/*PKRU*/] = {};
+ static target_desc *x32_linux_tdescs[2/*AVX*/][2/*AVX512*/] = {};
+
+ target_desc **tdesc;
+
+ if (is_x32)
+ {
+ tdesc = &x32_linux_tdescs[(xcr0_features_bit & X86_XSTATE_AVX) ? 1 : 0 ]
+ [(xcr0_features_bit & X86_XSTATE_AVX512) ? 1 : 0];
+ }
+ else
+ {
+ tdesc = &amd64_linux_tdescs[(xcr0_features_bit & X86_XSTATE_AVX) ? 1 : 0]
+ [(xcr0_features_bit & X86_XSTATE_MPX) ? 1 : 0]
+ [(xcr0_features_bit & X86_XSTATE_AVX512) ? 1 : 0]
+ [(xcr0_features_bit & X86_XSTATE_PKRU) ? 1 : 0];
+ }
+
+ if (*tdesc == NULL)
+ *tdesc = amd64_create_target_description (xcr0_features_bit, is_x32,
+ true, true);
+
+ return *tdesc;
+}
+
/* Get Linux/x86 target description from core dump. */
static const struct target_desc *
/* Linux/x86-64. */
uint64_t xcr0 = i386_linux_core_read_xcr0 (abfd);
- switch (xcr0 & X86_XSTATE_ALL_MASK)
- {
- case X86_XSTATE_MPX_AVX512_MASK:
- case X86_XSTATE_AVX512_MASK:
- if (gdbarch_ptr_bit (gdbarch) == 32)
- return tdesc_x32_avx512_linux;
- else
- return tdesc_amd64_avx512_linux;
- case X86_XSTATE_MPX_MASK:
- if (gdbarch_ptr_bit (gdbarch) == 32)
- return tdesc_x32_avx_linux; /* No x32 MPX falling back to AVX. */
- else
- return tdesc_amd64_mpx_linux;
- case X86_XSTATE_AVX_MASK:
- if (gdbarch_ptr_bit (gdbarch) == 32)
- return tdesc_x32_avx_linux;
- else
- return tdesc_amd64_avx_linux;
- default:
- if (gdbarch_ptr_bit (gdbarch) == 32)
- return tdesc_x32_linux;
- else
- return tdesc_amd64_linux;
- }
+ return amd64_linux_read_description (xcr0 & X86_XSTATE_ALL_MASK,
+ gdbarch_ptr_bit (gdbarch) == 32);
}
/* Similar to amd64_supply_fpregset, but use XSAVE extended state. */
void *cb_data,
const struct regcache *regcache)
{
- struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+ i386_gdbarch_tdep *tdep = (i386_gdbarch_tdep *) gdbarch_tdep (gdbarch);
- cb (".reg", 27 * 8, &i386_gregset, NULL, cb_data);
- cb (".reg2", 512, &amd64_fpregset, NULL, cb_data);
- cb (".reg-xstate", X86_XSTATE_SIZE (tdep->xcr0),
+ cb (".reg", 27 * 8, 27 * 8, &i386_gregset, NULL, cb_data);
+ cb (".reg2", 512, 512, &amd64_fpregset, NULL, cb_data);
+ cb (".reg-xstate", X86_XSTATE_SIZE (tdep->xcr0), X86_XSTATE_SIZE (tdep->xcr0),
&amd64_linux_xstateregset, "XSAVE extended state", cb_data);
}
/* Implementation of `gdbarch_dtrace_parse_probe_argument', as defined
in gdbarch.h. */
-static void
+static expr::operation_up
amd64_dtrace_parse_probe_argument (struct gdbarch *gdbarch,
- struct parser_state *pstate,
int narg)
{
- enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
- struct frame_info *this_frame = get_selected_frame (NULL);
- struct stoken str;
-
/* DTrace probe arguments can be found on the ABI-defined places for
regular arguments at the current PC. The probe abstraction
currently supports up to 12 arguments for probes. */
+ using namespace expr;
+
if (narg < 6)
{
static const int arg_reg_map[6] =
};
int regno = arg_reg_map[narg];
const char *regname = user_reg_map_regnum_to_name (gdbarch, regno);
-
- write_exp_elt_opcode (pstate, OP_REGISTER);
- str.ptr = regname;
- str.length = strlen (regname);
- write_exp_string (pstate, str);
- write_exp_elt_opcode (pstate, OP_REGISTER);
+ return make_operation<register_operation> (regname);
}
else
{
/* Additional arguments are passed on the stack. */
- CORE_ADDR sp;
const char *regname = user_reg_map_regnum_to_name (gdbarch, AMD64_RSP_REGNUM);
/* Displacement. */
- write_exp_elt_opcode (pstate, OP_LONG);
- write_exp_elt_type (pstate, builtin_type (gdbarch)->builtin_long);
- write_exp_elt_longcst (pstate, narg - 6);
- write_exp_elt_opcode (pstate, OP_LONG);
+ struct type *long_type = builtin_type (gdbarch)->builtin_long;
+ operation_up disp = make_operation<long_const_operation> (long_type,
+ narg - 6);
/* Register: SP. */
- write_exp_elt_opcode (pstate, OP_REGISTER);
- str.ptr = regname;
- str.length = strlen (regname);
- write_exp_string (pstate, str);
- write_exp_elt_opcode (pstate, OP_REGISTER);
+ operation_up reg = make_operation<register_operation> (regname);
- write_exp_elt_opcode (pstate, BINOP_ADD);
+ operation_up add = make_operation<add_operation> (std::move (disp),
+ std::move (reg));
/* Cast to long. */
- write_exp_elt_opcode (pstate, UNOP_CAST);
- write_exp_elt_type (pstate,
- lookup_pointer_type (builtin_type (gdbarch)->builtin_long));
- write_exp_elt_opcode (pstate, UNOP_CAST);
+ operation_up cast = make_operation<unop_cast_operation> (std::move (add),
+ long_type);
- write_exp_elt_opcode (pstate, UNOP_IND);
+ return make_operation<unop_ind_operation> (std::move (cast));
}
}
static void
-amd64_linux_init_abi_common(struct gdbarch_info info, struct gdbarch *gdbarch)
+amd64_linux_init_abi_common(struct gdbarch_info info, struct gdbarch *gdbarch,
+ int num_disp_step_buffers)
{
- struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+ i386_gdbarch_tdep *tdep = (i386_gdbarch_tdep *) gdbarch_tdep (gdbarch);
- linux_init_abi (info, gdbarch);
+ linux_init_abi (info, gdbarch, num_disp_step_buffers);
tdep->sigtramp_p = amd64_linux_sigtramp_p;
tdep->sigcontext_addr = amd64_linux_sigcontext_addr;
/* Functions for 'catch syscall'. */
set_xml_syscall_file_name (gdbarch, XML_SYSCALL_FILENAME_AMD64);
set_gdbarch_get_syscall_number (gdbarch,
- amd64_linux_get_syscall_number);
+ amd64_linux_get_syscall_number);
/* Enable TLS support. */
set_gdbarch_fetch_tls_load_module_address (gdbarch,
- svr4_fetch_objfile_link_map);
+ svr4_fetch_objfile_link_map);
/* GNU/Linux uses SVR4-style shared libraries. */
set_gdbarch_skip_trampoline_code (gdbarch, find_solib_trampoline_target);
/* Displaced stepping. */
set_gdbarch_displaced_step_copy_insn (gdbarch,
- amd64_displaced_step_copy_insn);
+ amd64_displaced_step_copy_insn);
set_gdbarch_displaced_step_fixup (gdbarch, amd64_displaced_step_fixup);
- set_gdbarch_displaced_step_free_closure (gdbarch,
- simple_displaced_step_free_closure);
- set_gdbarch_displaced_step_location (gdbarch,
- linux_displaced_step_location);
set_gdbarch_process_record (gdbarch, i386_process_record);
set_gdbarch_process_record_signal (gdbarch, amd64_linux_record_signal);
+
+ set_gdbarch_get_siginfo_type (gdbarch, x86_linux_get_siginfo_type);
+ set_gdbarch_report_signal_info (gdbarch, i386_linux_report_signal_info);
}
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
- = (struct tdesc_arch_data *) info.tdep_info;
+ i386_gdbarch_tdep *tdep = (i386_gdbarch_tdep *) gdbarch_tdep (gdbarch);
+ struct tdesc_arch_data *tdesc_data = info.tdesc_data;
const struct tdesc_feature *feature;
int valid_p;
tdep->gregset_num_regs = ARRAY_SIZE (amd64_linux_gregset_reg_offset);
tdep->sizeof_gregset = 27 * 8;
- amd64_init_abi (info, gdbarch);
+ amd64_init_abi (info, gdbarch,
+ amd64_linux_read_description (X86_XSTATE_SSE_MASK, false));
+
+ const target_desc *tdesc = tdep->tdesc;
/* 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;
if (!valid_p)
return;
- amd64_linux_init_abi_common (info, gdbarch);
+ amd64_linux_init_abi_common (info, gdbarch, 2);
/* Initialize the amd64_linux_record_tdep. */
/* These values are the size of the type that will be used in a system
but sys_getresuid. */
amd64_linux_record_tdep.size_old_uid_t = 2;
amd64_linux_record_tdep.size_fd_set = 128;
- amd64_linux_record_tdep.size_dirent = 280;
- amd64_linux_record_tdep.size_dirent64 = 280;
+ /* ADM64 doesn't need this size because it doesn't have sys_readdir. */
+ amd64_linux_record_tdep.size_old_dirent = 280;
amd64_linux_record_tdep.size_statfs = 120;
amd64_linux_record_tdep.size_statfs64 = 120;
amd64_linux_record_tdep.size_sockaddr = 16;
amd64_linux_record_tdep.size_epoll_event = 12;
amd64_linux_record_tdep.size_itimerspec = 32;
amd64_linux_record_tdep.size_mq_attr = 64;
- amd64_linux_record_tdep.size_termios = 60;
+ amd64_linux_record_tdep.size_termios = 36;
amd64_linux_record_tdep.size_termios2 = 44;
amd64_linux_record_tdep.size_pid_t = 4;
amd64_linux_record_tdep.size_winsize = 8;
amd64_linux_record_tdep.size_hayes_esp_config = 12;
amd64_linux_record_tdep.size_size_t = 8;
amd64_linux_record_tdep.size_iovec = 16;
+ amd64_linux_record_tdep.size_time_t = 8;
/* These values are the second argument of system call "sys_fcntl"
and "sys_fcntl64". They are obtained from Linux Kernel source. */
/* GNU/Linux uses SVR4-style shared libraries. */
set_solib_svr4_fetch_link_map_offsets
- (gdbarch, svr4_lp64_fetch_link_map_offsets);
+ (gdbarch, linux_lp64_fetch_link_map_offsets);
/* Register DTrace handlers. */
set_gdbarch_dtrace_parse_probe_argument (gdbarch, amd64_dtrace_parse_probe_argument);
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
- = (struct tdesc_arch_data *) info.tdep_info;
+ i386_gdbarch_tdep *tdep = (i386_gdbarch_tdep *) gdbarch_tdep (gdbarch);
+ struct tdesc_arch_data *tdesc_data = info.tdesc_data;
const struct tdesc_feature *feature;
int valid_p;
tdep->gregset_num_regs = ARRAY_SIZE (amd64_linux_gregset_reg_offset);
tdep->sizeof_gregset = 27 * 8;
- amd64_x32_init_abi (info, gdbarch);
+ amd64_x32_init_abi (info, gdbarch,
+ amd64_linux_read_description (X86_XSTATE_SSE_MASK,
+ true));
/* 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;
+ const target_desc *tdesc = tdep->tdesc;
feature = tdesc_find_feature (tdesc, "org.gnu.gdb.i386.linux");
if (feature == NULL)
if (!valid_p)
return;
- amd64_linux_init_abi_common (info, gdbarch);
+ amd64_linux_init_abi_common (info, gdbarch, 0);
/* Initialize the amd64_x32_linux_record_tdep. */
/* These values are the size of the type that will be used in a system
but sys_getresuid. */
amd64_x32_linux_record_tdep.size_old_uid_t = 2;
amd64_x32_linux_record_tdep.size_fd_set = 128;
- amd64_x32_linux_record_tdep.size_dirent = 280;
- amd64_x32_linux_record_tdep.size_dirent64 = 280;
+ /* ADM64 doesn't need this size because it doesn't have sys_readdir. */
+ amd64_x32_linux_record_tdep.size_old_dirent = 268;
amd64_x32_linux_record_tdep.size_statfs = 120;
amd64_x32_linux_record_tdep.size_statfs64 = 120;
amd64_x32_linux_record_tdep.size_sockaddr = 16;
= gdbarch_long_bit (gdbarch) / TARGET_CHAR_BIT;
amd64_x32_linux_record_tdep.size_ulong
= gdbarch_long_bit (gdbarch) / TARGET_CHAR_BIT;
- amd64_x32_linux_record_tdep.size_msghdr = 56;
+ amd64_x32_linux_record_tdep.size_msghdr = 28;
amd64_x32_linux_record_tdep.size_itimerval = 32;
amd64_x32_linux_record_tdep.size_stat = 144;
amd64_x32_linux_record_tdep.size_old_utsname = 325;
amd64_x32_linux_record_tdep.size_sigset_t = 8;
amd64_x32_linux_record_tdep.size_siginfo_t = 128;
amd64_x32_linux_record_tdep.size_cap_user_data_t = 8;
- amd64_x32_linux_record_tdep.size_stack_t = 24;
+ amd64_x32_linux_record_tdep.size_stack_t = 12;
amd64_x32_linux_record_tdep.size_off_t = 8;
amd64_x32_linux_record_tdep.size_stat64 = 144;
amd64_x32_linux_record_tdep.size_gid_t = 4;
amd64_x32_linux_record_tdep.size_epoll_event = 12;
amd64_x32_linux_record_tdep.size_itimerspec = 32;
amd64_x32_linux_record_tdep.size_mq_attr = 64;
- amd64_x32_linux_record_tdep.size_termios = 60;
+ amd64_x32_linux_record_tdep.size_termios = 36;
amd64_x32_linux_record_tdep.size_termios2 = 44;
amd64_x32_linux_record_tdep.size_pid_t = 4;
amd64_x32_linux_record_tdep.size_winsize = 8;
amd64_x32_linux_record_tdep.size_serial_struct = 72;
amd64_x32_linux_record_tdep.size_serial_icounter_struct = 80;
amd64_x32_linux_record_tdep.size_hayes_esp_config = 12;
- amd64_x32_linux_record_tdep.size_size_t = 8;
- amd64_x32_linux_record_tdep.size_iovec = 16;
+ amd64_x32_linux_record_tdep.size_size_t = 4;
+ amd64_x32_linux_record_tdep.size_iovec = 8;
+ amd64_x32_linux_record_tdep.size_time_t = 8;
/* These values are the second argument of system call "sys_fcntl"
and "sys_fcntl64". They are obtained from Linux Kernel source. */
/* GNU/Linux uses SVR4-style shared libraries. */
set_solib_svr4_fetch_link_map_offsets
- (gdbarch, svr4_ilp32_fetch_link_map_offsets);
+ (gdbarch, linux_ilp32_fetch_link_map_offsets);
}
-\f
-
-/* Provide a prototype to silence -Wmissing-prototypes. */
-extern void _initialize_amd64_linux_tdep (void);
+void _initialize_amd64_linux_tdep ();
void
-_initialize_amd64_linux_tdep (void)
+_initialize_amd64_linux_tdep ()
{
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_amd64_mpx_linux ();
- initialize_tdesc_amd64_avx512_linux ();
-
- initialize_tdesc_x32_linux ();
- initialize_tdesc_x32_avx_linux ();
- initialize_tdesc_x32_avx512_linux ();
}