/* Target-dependent code for GNU/Linux x86-64.
- Copyright (C) 2001-2014 Free Software Foundation, Inc.
+ Copyright (C) 2001-2016 Free Software Foundation, Inc.
Contributed by Jiri Smid, SuSE Labs.
This file is part of GDB.
#include "gdbtypes.h"
#include "reggroups.h"
#include "regset.h"
+#include "parser-defs.h"
+#include "user-regs.h"
#include "amd64-linux-tdep.h"
#include "i386-linux-tdep.h"
#include "linux-tdep.h"
case amd64_sys_arch_prctl:
case amd64_x32_sys_arch_prctl:
- return -1; /* Note */
+ return gdb_sys_no_syscall; /* Note */
case amd64_sys_adjtimex:
case amd64_x32_sys_adjtimex:
return gdb_sys_move_pages;
default:
- return -1;
+ return gdb_sys_no_syscall;
}
}
{
int ret;
ULONGEST syscall_native;
- enum gdb_syscall syscall_gdb = -1;
+ enum gdb_syscall syscall_gdb = gdb_sys_no_syscall;
regcache_raw_read_unsigned (regcache, AMD64_RAX_REGNUM, &syscall_native);
break;
}
- syscall_gdb = amd64_canonicalize_syscall (syscall_native);
+ syscall_gdb
+ = amd64_canonicalize_syscall ((enum amd64_syscall) syscall_native);
- if (syscall_gdb < 0)
+ if (syscall_gdb == gdb_sys_no_syscall)
{
printf_unfiltered (_("Process record and replay target doesn't "
"support syscall number %s\n"),
}
}
+/* Similar to amd64_supply_fpregset, but use XSAVE extended state. */
+
+static void
+amd64_linux_supply_xstateregset (const struct regset *regset,
+ struct regcache *regcache, int regnum,
+ const void *xstateregs, size_t len)
+{
+ amd64_supply_xsave (regcache, regnum, xstateregs);
+}
+
+/* Similar to amd64_collect_fpregset, but use XSAVE extended state. */
+
+static void
+amd64_linux_collect_xstateregset (const struct regset *regset,
+ const struct regcache *regcache,
+ int regnum, void *xstateregs, size_t len)
+{
+ amd64_collect_xsave (regcache, regnum, xstateregs, 1);
+}
+
+static const struct regset amd64_linux_xstateregset =
+ {
+ NULL,
+ amd64_linux_supply_xstateregset,
+ amd64_linux_collect_xstateregset
+ };
+
/* Iterate over core file register note sections. */
static void
void *cb_data,
const struct regcache *regcache)
{
- cb (".reg", 27 * 8, "general-purpose", cb_data);
- cb (".reg2", 512, "floating-point", cb_data);
- cb (".reg-xstate", X86_XSTATE_MAX_SIZE, "XSAVE extended state", cb_data);
+ struct gdbarch_tdep *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),
+ &amd64_linux_xstateregset, "XSAVE extended state", cb_data);
+}
+
+/* The instruction sequences used in x86_64 machines for a
+ disabled is-enabled probe. */
+
+const gdb_byte amd64_dtrace_disabled_probe_sequence_1[] = {
+ /* xor %rax, %rax */ 0x48, 0x33, 0xc0,
+ /* nop */ 0x90,
+ /* nop */ 0x90
+};
+
+const gdb_byte amd64_dtrace_disabled_probe_sequence_2[] = {
+ /* xor %rax, %rax */ 0x48, 0x33, 0xc0,
+ /* ret */ 0xc3,
+ /* nop */ 0x90
+};
+
+/* The instruction sequence used in x86_64 machines for enabling a
+ DTrace is-enabled probe. */
+
+const gdb_byte amd64_dtrace_enable_probe_sequence[] = {
+ /* mov $0x1, %eax */ 0xb8, 0x01, 0x00, 0x00, 0x00
+};
+
+/* The instruction sequence used in x86_64 machines for disabling a
+ DTrace is-enabled probe. */
+
+const gdb_byte amd64_dtrace_disable_probe_sequence[] = {
+ /* xor %rax, %rax; nop; nop */ 0x48, 0x33, 0xC0, 0x90, 0x90
+};
+
+/* Implementation of `gdbarch_dtrace_probe_is_enabled', as defined in
+ gdbarch.h. */
+
+static int
+amd64_dtrace_probe_is_enabled (struct gdbarch *gdbarch, CORE_ADDR addr)
+{
+ gdb_byte buf[5];
+
+ /* This function returns 1 if the instructions at ADDR do _not_
+ follow any of the amd64_dtrace_disabled_probe_sequence_*
+ patterns.
+
+ Note that ADDR is offset 3 bytes from the beginning of these
+ sequences. */
+
+ read_code (addr - 3, buf, 5);
+ return (memcmp (buf, amd64_dtrace_disabled_probe_sequence_1, 5) != 0
+ && memcmp (buf, amd64_dtrace_disabled_probe_sequence_2, 5) != 0);
+}
+
+/* Implementation of `gdbarch_dtrace_enable_probe', as defined in
+ gdbarch.h. */
+
+static void
+amd64_dtrace_enable_probe (struct gdbarch *gdbarch, CORE_ADDR addr)
+{
+ /* Note also that ADDR is offset 3 bytes from the beginning of
+ amd64_dtrace_enable_probe_sequence. */
+
+ write_memory (addr - 3, amd64_dtrace_enable_probe_sequence, 5);
+}
+
+/* Implementation of `gdbarch_dtrace_disable_probe', as defined in
+ gdbarch.h. */
+
+static void
+amd64_dtrace_disable_probe (struct gdbarch *gdbarch, CORE_ADDR addr)
+{
+ /* Note also that ADDR is offset 3 bytes from the beginning of
+ amd64_dtrace_disable_probe_sequence. */
+
+ write_memory (addr - 3, amd64_dtrace_disable_probe_sequence, 5);
+}
+
+/* Implementation of `gdbarch_dtrace_parse_probe_argument', as defined
+ in gdbarch.h. */
+
+static void
+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. */
+
+ if (narg < 6)
+ {
+ static const int arg_reg_map[6] =
+ {
+ AMD64_RDI_REGNUM, /* Arg 1. */
+ AMD64_RSI_REGNUM, /* Arg 2. */
+ AMD64_RDX_REGNUM, /* Arg 3. */
+ AMD64_RCX_REGNUM, /* Arg 4. */
+ AMD64_R8_REGNUM, /* Arg 5. */
+ AMD64_R9_REGNUM /* Arg 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);
+ }
+ 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);
+
+ /* 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);
+
+ write_exp_elt_opcode (pstate, BINOP_ADD);
+
+ /* 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);
+
+ write_exp_elt_opcode (pstate, UNOP_IND);
+ }
}
static void
tdep->register_reggroup_p = amd64_linux_register_reggroup_p;
/* Functions for 'catch syscall'. */
- set_xml_syscall_file_name (XML_SYSCALL_FILENAME_AMD64);
+ set_xml_syscall_file_name (gdbarch, XML_SYSCALL_FILENAME_AMD64);
set_gdbarch_get_syscall_number (gdbarch,
amd64_linux_get_syscall_number);
set_gdbarch_displaced_step_free_closure (gdbarch,
simple_displaced_step_free_closure);
set_gdbarch_displaced_step_location (gdbarch,
- displaced_step_at_entry_point);
-
- set_gdbarch_get_siginfo_type (gdbarch, linux_get_siginfo_type);
+ linux_displaced_step_location);
set_gdbarch_process_record (gdbarch, i386_process_record);
set_gdbarch_process_record_signal (gdbarch, amd64_linux_record_signal);
{
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;
+ struct tdesc_arch_data *tdesc_data
+ = (struct tdesc_arch_data *) info.tdep_info;
const struct tdesc_feature *feature;
int valid_p;
amd64_linux_record_tdep.size_ustat = 32;
/* ADM64 doesn't need this size because it doesn't have sys_sigaction
but sys_rt_sigaction. */
- amd64_linux_record_tdep.size_old_sigaction = 152;
+ amd64_linux_record_tdep.size_old_sigaction = 32;
/* ADM64 doesn't need this size because it doesn't have sys_sigpending
but sys_rt_sigpending. */
- amd64_linux_record_tdep.size_old_sigset_t = 128;
+ amd64_linux_record_tdep.size_old_sigset_t = 8;
amd64_linux_record_tdep.size_rlimit = 16;
amd64_linux_record_tdep.size_rusage = 144;
amd64_linux_record_tdep.size_timeval = 16;
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_NFS_FHSIZE = 32;
amd64_linux_record_tdep.size_knfsd_fh = 132;
amd64_linux_record_tdep.size_TASK_COMM_LEN = 16;
- amd64_linux_record_tdep.size_sigaction = 152;
- amd64_linux_record_tdep.size_sigset_t = 128;
+ amd64_linux_record_tdep.size_sigaction = 32;
+ amd64_linux_record_tdep.size_sigset_t = 8;
amd64_linux_record_tdep.size_siginfo_t = 128;
amd64_linux_record_tdep.size_cap_user_data_t = 8;
amd64_linux_record_tdep.size_stack_t = 24;
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_siginfo = 128;
- 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);
+
+ /* Register DTrace handlers. */
+ set_gdbarch_dtrace_parse_probe_argument (gdbarch, amd64_dtrace_parse_probe_argument);
+ set_gdbarch_dtrace_probe_is_enabled (gdbarch, amd64_dtrace_probe_is_enabled);
+ set_gdbarch_dtrace_enable_probe (gdbarch, amd64_dtrace_enable_probe);
+ set_gdbarch_dtrace_disable_probe (gdbarch, amd64_dtrace_disable_probe);
}
static void
-amd64_x32_linux_init_abi(struct gdbarch_info info, struct gdbarch *gdbarch)
+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;
+ struct tdesc_arch_data *tdesc_data
+ = (struct tdesc_arch_data *) info.tdep_info;
const struct tdesc_feature *feature;
int valid_p;
amd64_x32_linux_record_tdep.size_ustat = 32;
/* ADM64 doesn't need this size because it doesn't have sys_sigaction
but sys_rt_sigaction. */
- amd64_x32_linux_record_tdep.size_old_sigaction = 152;
+ amd64_x32_linux_record_tdep.size_old_sigaction = 16;
/* ADM64 doesn't need this size because it doesn't have sys_sigpending
but sys_rt_sigpending. */
- amd64_x32_linux_record_tdep.size_old_sigset_t = 128;
+ amd64_x32_linux_record_tdep.size_old_sigset_t = 4;
amd64_x32_linux_record_tdep.size_rlimit = 16;
amd64_x32_linux_record_tdep.size_rusage = 144;
amd64_x32_linux_record_tdep.size_timeval = 16;
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_NFS_FHSIZE = 32;
amd64_x32_linux_record_tdep.size_knfsd_fh = 132;
amd64_x32_linux_record_tdep.size_TASK_COMM_LEN = 16;
- amd64_x32_linux_record_tdep.size_sigaction = 152;
- amd64_x32_linux_record_tdep.size_sigset_t = 128;
+ amd64_x32_linux_record_tdep.size_sigaction = 20;
+ 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_siginfo = 128;
- 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. */