X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=gdb%2Famd64-linux-tdep.c;h=8d27225b4ad356f72a51af365f714bf8734ba947;hb=d55e5aa6b29906346c51ad00e6a9b112590aa294;hp=b948ea77fad9f00226b97fdb279e98b144f3d425;hpb=618f726fcb851883a0094aa7fa17003889b7189f;p=deliverable%2Fbinutils-gdb.git diff --git a/gdb/amd64-linux-tdep.c b/gdb/amd64-linux-tdep.c index b948ea77fa..8d27225b4a 100644 --- a/gdb/amd64-linux-tdep.c +++ b/gdb/amd64-linux-tdep.c @@ -1,6 +1,6 @@ /* Target-dependent code for GNU/Linux x86-64. - Copyright (C) 2001-2016 Free Software Foundation, Inc. + Copyright (C) 2001-2019 Free Software Foundation, Inc. Contributed by Jiri Smid, SuSE Labs. This file is part of GDB. @@ -19,35 +19,29 @@ along with this program. If not, see . */ #include "defs.h" + +/* Local non-gdb includes. */ +#include "amd64-linux-tdep.h" +#include "amd64-tdep.h" #include "arch-utils.h" +#include "arch/amd64.h" +#include "common/x86-xstate.h" #include "frame.h" #include "gdbcore.h" -#include "regcache.h" -#include "osabi.h" -#include "symtab.h" #include "gdbtypes.h" -#include "reggroups.h" -#include "regset.h" -#include "parser-defs.h" -#include "user-regs.h" -#include "amd64-linux-tdep.h" +#include "glibc-tdep.h" #include "i386-linux-tdep.h" #include "linux-tdep.h" -#include "x86-xstate.h" - -#include "amd64-tdep.h" +#include "osabi.h" +#include "parser-defs.h" +#include "regcache.h" +#include "reggroups.h" +#include "regset.h" #include "solib-svr4.h" +#include "symtab.h" +#include "target-descriptions.h" +#include "user-regs.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" /* The syscall's XML filename for i386. */ #define XML_SYSCALL_FILENAME_AMD64 "syscalls/amd64-linux.xml" @@ -102,6 +96,10 @@ int amd64_linux_gregset_reg_offset[] = -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" */ }; @@ -225,9 +223,9 @@ amd64_linux_sigcontext_addr (struct frame_info *this_frame) 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]; @@ -237,7 +235,7 @@ amd64_linux_get_syscall_number (struct gdbarch *gdbarch, /* 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); @@ -283,7 +281,9 @@ static int 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); @@ -364,6 +364,9 @@ amd64_all_but_ip_registers_record (struct regcache *regcache) 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: @@ -1431,6 +1434,8 @@ amd64_canonicalize_syscall (enum amd64_syscall syscall_number) default: return gdb_sys_no_syscall; } + + DIAGNOSTIC_POP } /* Parse the arguments of current system call instruction and record @@ -1567,6 +1572,35 @@ amd64_linux_record_signal (struct gdbarch *gdbarch, 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 * @@ -1577,30 +1611,8 @@ amd64_linux_core_read_description (struct gdbarch *gdbarch, /* 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. */ @@ -1640,9 +1652,9 @@ amd64_linux_iterate_over_regset_sections (struct gdbarch *gdbarch, { 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), + 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); } @@ -1724,11 +1736,9 @@ amd64_dtrace_disable_probe (struct gdbarch *gdbarch, CORE_ADDR addr) static void amd64_dtrace_parse_probe_argument (struct gdbarch *gdbarch, - struct parser_state *pstate, + struct expr_builder *builder, 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 @@ -1749,40 +1759,39 @@ amd64_dtrace_parse_probe_argument (struct gdbarch *gdbarch, int regno = arg_reg_map[narg]; const char *regname = user_reg_map_regnum_to_name (gdbarch, regno); - write_exp_elt_opcode (pstate, OP_REGISTER); + write_exp_elt_opcode (builder, OP_REGISTER); str.ptr = regname; str.length = strlen (regname); - write_exp_string (pstate, str); - write_exp_elt_opcode (pstate, OP_REGISTER); + write_exp_string (builder, str); + write_exp_elt_opcode (builder, 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); + write_exp_elt_opcode (builder, OP_LONG); + write_exp_elt_type (builder, builtin_type (gdbarch)->builtin_long); + write_exp_elt_longcst (builder, narg - 6); + write_exp_elt_opcode (builder, OP_LONG); /* Register: SP. */ - write_exp_elt_opcode (pstate, OP_REGISTER); + write_exp_elt_opcode (builder, OP_REGISTER); str.ptr = regname; str.length = strlen (regname); - write_exp_string (pstate, str); - write_exp_elt_opcode (pstate, OP_REGISTER); + write_exp_string (builder, str); + write_exp_elt_opcode (builder, OP_REGISTER); - write_exp_elt_opcode (pstate, BINOP_ADD); + write_exp_elt_opcode (builder, BINOP_ADD); /* Cast to long. */ - write_exp_elt_opcode (pstate, UNOP_CAST); - write_exp_elt_type (pstate, + write_exp_elt_opcode (builder, UNOP_CAST); + write_exp_elt_type (builder, lookup_pointer_type (builtin_type (gdbarch)->builtin_long)); - write_exp_elt_opcode (pstate, UNOP_CAST); + write_exp_elt_opcode (builder, UNOP_CAST); - write_exp_elt_opcode (pstate, UNOP_IND); + write_exp_elt_opcode (builder, UNOP_IND); } } @@ -1831,22 +1840,22 @@ amd64_linux_init_abi_common(struct gdbarch_info info, struct gdbarch *gdbarch) set_gdbarch_displaced_step_copy_insn (gdbarch, 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_handle_segmentation_fault (gdbarch, + i386_linux_handle_segmentation_fault); } 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; + struct tdesc_arch_data *tdesc_data = info.tdesc_data; const struct tdesc_feature *feature; int valid_p; @@ -1856,15 +1865,14 @@ amd64_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) 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; @@ -2061,9 +2069,7 @@ 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; + struct tdesc_arch_data *tdesc_data = info.tdesc_data; const struct tdesc_feature *feature; int valid_p; @@ -2073,14 +2079,14 @@ amd64_x32_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) 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) @@ -2266,10 +2272,6 @@ amd64_x32_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) set_solib_svr4_fetch_link_map_offsets (gdbarch, svr4_ilp32_fetch_link_map_offsets); } - - -/* Provide a prototype to silence -Wmissing-prototypes. */ -extern void _initialize_amd64_linux_tdep (void); void _initialize_amd64_linux_tdep (void) @@ -2279,13 +2281,31 @@ _initialize_amd64_linux_tdep (void) 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 (); +#if GDB_SELF_TEST + struct + { + const char *xml; + uint64_t mask; + } xml_masks[] = { + { "i386/amd64-linux.xml", X86_XSTATE_SSE_MASK }, + { "i386/amd64-avx-linux.xml", X86_XSTATE_AVX_MASK }, + { "i386/amd64-mpx-linux.xml", X86_XSTATE_MPX_MASK }, + { "i386/amd64-avx-mpx-linux.xml", X86_XSTATE_AVX_MPX_MASK }, + { "i386/amd64-avx-avx512-linux.xml", X86_XSTATE_AVX_AVX512_MASK }, + { "i386/amd64-avx-mpx-avx512-pku-linux.xml", + X86_XSTATE_AVX_MPX_AVX512_PKU_MASK }, + { "i386/x32-linux.xml", X86_XSTATE_SSE_MASK }, + { "i386/x32-avx-linux.xml", X86_XSTATE_AVX_MASK }, + { "i386/x32-avx-avx512-linux.xml", X86_XSTATE_AVX_AVX512_MASK }, + }; + + for (auto &a : xml_masks) + { + auto tdesc = amd64_linux_read_description (a.mask, + startswith (a.xml, + "i386/x32")); - initialize_tdesc_x32_linux (); - initialize_tdesc_x32_avx_linux (); - initialize_tdesc_x32_avx512_linux (); + selftests::record_xml_tdesc (a.xml, tdesc); + } +#endif /* GDB_SELF_TEST */ }