From: John Baldwin Date: Tue, 12 Mar 2019 20:39:02 +0000 (-0700) Subject: Support the fs_base and gs_base registers on i386. X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=1163a4b7a38a79ebd153dc5ee76ce93877d21dbd;p=binutils-gdb.git Support the fs_base and gs_base registers on i386. As on amd64, these registers hold the base address of the fs and gs segments, respectively. For i386 these two registers are 32 bits. gdb/ChangeLog: * amd64-fbsd-nat.c (amd64_fbsd_nat_target::read_description): Update calls to i386_target_description to add 'segments' parameter. * amd64-tdep.c (amd64_init_abi): Set tdep->fsbase_regnum. Don't add segment base registers. * arch/i386.c (i386_create_target_description): Add 'segments' parameter to enable segment base registers. * arch/i386.h (i386_create_target_description): Likewise. * features/i386/32bit-segments.xml: New file. * features/i386/32bit-segments.c: Generate. * i386-fbsd-nat.c (i386_fbsd_nat_target::read_description): Update call to i386_target_description to add 'segments' parameter. * i386-fbsd-tdep.c (i386fbsd_core_read_description): Likewise. * i386-go32-tdep.c (i386_go32_init_abi): Likewise. * i386-linux-tdep.c (i386_linux_read_description): Likewise. * i386-tdep.c (i386_validate_tdesc_p): Add segment base registers if feature is present. (i386_gdbarch_init): Pass I386_NUM_REGS to set_gdbarch_num_regs. Add 'segments' parameter to call to i386_target_description. (i386_target_description): Add 'segments' parameter to enable segment base registers. (_initialize_i386_tdep) [GDB_SELF_TEST]: Add 'segments' parameter to call to i386_target_description. * i386-tdep.h (struct gdbarch_tdep): Add 'fsbase_regnum'. (enum i386_regnum): Add I386_FSBASE_REGNUM and I386_GSBASE_REGNUM. Define I386_NUM_REGS. (i386_target_description): Add 'segments' parameter to enable segment base registers. gdb/gdbserver/ChangeLog: * linux-x86-tdesc.c (i386_linux_read_description): Update call to i386_create_target_description for 'segments' parameter. * lynx-i386-low.c (lynx_i386_arch_setup): Likewise. * nto-x86-low.c (nto_x86_arch_setup): Likewise. * win32-i386-low.c (i386_arch_setup): Likewise. --- diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 4e592a38f40..79ba9416780 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,34 @@ +2019-03-12 John Baldwin + + * amd64-fbsd-nat.c (amd64_fbsd_nat_target::read_description): + Update calls to i386_target_description to add 'segments' + parameter. + * amd64-tdep.c (amd64_init_abi): Set tdep->fsbase_regnum. Don't + add segment base registers. + * arch/i386.c (i386_create_target_description): Add 'segments' + parameter to enable segment base registers. + * arch/i386.h (i386_create_target_description): Likewise. + * features/i386/32bit-segments.xml: New file. + * features/i386/32bit-segments.c: Generate. + * i386-fbsd-nat.c (i386_fbsd_nat_target::read_description): Update + call to i386_target_description to add 'segments' parameter. + * i386-fbsd-tdep.c (i386fbsd_core_read_description): Likewise. + * i386-go32-tdep.c (i386_go32_init_abi): Likewise. + * i386-linux-tdep.c (i386_linux_read_description): Likewise. + * i386-tdep.c (i386_validate_tdesc_p): Add segment base registers + if feature is present. + (i386_gdbarch_init): Pass I386_NUM_REGS to set_gdbarch_num_regs. + Add 'segments' parameter to call to i386_target_description. + (i386_target_description): Add 'segments' parameter to enable + segment base registers. + (_initialize_i386_tdep) [GDB_SELF_TEST]: Add 'segments' parameter + to call to i386_target_description. + * i386-tdep.h (struct gdbarch_tdep): Add 'fsbase_regnum'. + (enum i386_regnum): Add I386_FSBASE_REGNUM and I386_GSBASE_REGNUM. + Define I386_NUM_REGS. + (i386_target_description): Add 'segments' parameter to enable + segment base registers. + 2019-03-12 Eli Zaretskii PR/24325 diff --git a/gdb/amd64-fbsd-nat.c b/gdb/amd64-fbsd-nat.c index 74ef2407660..9fff763dd36 100644 --- a/gdb/amd64-fbsd-nat.c +++ b/gdb/amd64-fbsd-nat.c @@ -190,13 +190,13 @@ amd64_fbsd_nat_target::read_description () if (is64) return amd64_target_description (xcr0, true); else - return i386_target_description (xcr0); + return i386_target_description (xcr0, false); } #endif if (is64) return amd64_target_description (X86_XSTATE_SSE_MASK, true); else - return i386_target_description (X86_XSTATE_SSE_MASK); + return i386_target_description (X86_XSTATE_SSE_MASK, false); } #if defined(HAVE_PT_GETDBREGS) && defined(USE_SIGTRAP_SIGINFO) diff --git a/gdb/amd64-tdep.c b/gdb/amd64-tdep.c index 3f61997d663..d5892954d74 100644 --- a/gdb/amd64-tdep.c +++ b/gdb/amd64-tdep.c @@ -3107,15 +3107,7 @@ amd64_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch, if (tdesc_find_feature (tdesc, "org.gnu.gdb.i386.segments") != NULL) { - const struct tdesc_feature *feature = - tdesc_find_feature (tdesc, "org.gnu.gdb.i386.segments"); - struct tdesc_arch_data *tdesc_data_segments = - (struct tdesc_arch_data *) info.tdep_info; - - tdesc_numbered_register (feature, tdesc_data_segments, - AMD64_FSBASE_REGNUM, "fs_base"); - tdesc_numbered_register (feature, tdesc_data_segments, - AMD64_GSBASE_REGNUM, "gs_base"); + tdep->fsbase_regnum = AMD64_FSBASE_REGNUM; } if (tdesc_find_feature (tdesc, "org.gnu.gdb.i386.pkeys") != NULL) diff --git a/gdb/arch/i386.c b/gdb/arch/i386.c index 7d2901333b9..ab24cf71cb5 100644 --- a/gdb/arch/i386.c +++ b/gdb/arch/i386.c @@ -28,11 +28,12 @@ #include "../features/i386/32bit-avx512.c" #include "../features/i386/32bit-mpx.c" #include "../features/i386/32bit-pkeys.c" +#include "../features/i386/32bit-segments.c" /* Create i386 target descriptions according to XCR0. */ target_desc * -i386_create_target_description (uint64_t xcr0, bool is_linux) +i386_create_target_description (uint64_t xcr0, bool is_linux, bool segments) { target_desc *tdesc = allocate_target_description (); @@ -53,6 +54,9 @@ i386_create_target_description (uint64_t xcr0, bool is_linux) if (is_linux) regnum = create_feature_i386_32bit_linux (tdesc, regnum); + if (segments) + regnum = create_feature_i386_32bit_segments (tdesc, regnum); + if (xcr0 & X86_XSTATE_AVX) regnum = create_feature_i386_32bit_avx (tdesc, regnum); diff --git a/gdb/arch/i386.h b/gdb/arch/i386.h index fa854380809..9a831cea300 100644 --- a/gdb/arch/i386.h +++ b/gdb/arch/i386.h @@ -21,6 +21,7 @@ #include "common/tdesc.h" #include -target_desc *i386_create_target_description (uint64_t xcr0, bool is_linux); +target_desc *i386_create_target_description (uint64_t xcr0, bool is_linux, + bool segments); #endif /* ARCH_I386_H */ diff --git a/gdb/features/i386/32bit-segments.c b/gdb/features/i386/32bit-segments.c new file mode 100644 index 00000000000..c22c3dfbc3c --- /dev/null +++ b/gdb/features/i386/32bit-segments.c @@ -0,0 +1,15 @@ +/* THIS FILE IS GENERATED. -*- buffer-read-only: t -*- vi:set ro: + Original: 32bit-segments.xml */ + +#include "common/tdesc.h" + +static int +create_feature_i386_32bit_segments (struct target_desc *result, long regnum) +{ + struct tdesc_feature *feature; + + feature = tdesc_create_feature (result, "org.gnu.gdb.i386.segments"); + tdesc_create_reg (feature, "fs_base", regnum++, 1, NULL, 32, "int"); + tdesc_create_reg (feature, "gs_base", regnum++, 1, NULL, 32, "int"); + return regnum; +} diff --git a/gdb/features/i386/32bit-segments.xml b/gdb/features/i386/32bit-segments.xml new file mode 100644 index 00000000000..098948e5ece --- /dev/null +++ b/gdb/features/i386/32bit-segments.xml @@ -0,0 +1,12 @@ + + + + + + + + diff --git a/gdb/gdbserver/ChangeLog b/gdb/gdbserver/ChangeLog index 3eb9ec05efa..9879481b17e 100644 --- a/gdb/gdbserver/ChangeLog +++ b/gdb/gdbserver/ChangeLog @@ -1,3 +1,11 @@ +2019-03-12 John Baldwin + + * linux-x86-tdesc.c (i386_linux_read_description): Update call to + i386_create_target_description for 'segments' parameter. + * lynx-i386-low.c (lynx_i386_arch_setup): Likewise. + * nto-x86-low.c (nto_x86_arch_setup): Likewise. + * win32-i386-low.c (i386_arch_setup): Likewise. + 2019-03-12 Tom Tromey * linux-low.c (iterate_over_lwps): Update. diff --git a/gdb/gdbserver/linux-x86-tdesc.c b/gdb/gdbserver/linux-x86-tdesc.c index 04bccc84ed0..8f24a3d72d1 100644 --- a/gdb/gdbserver/linux-x86-tdesc.c +++ b/gdb/gdbserver/linux-x86-tdesc.c @@ -87,7 +87,7 @@ i386_linux_read_description (uint64_t xcr0) if (*tdesc == NULL) { - *tdesc = i386_create_target_description (xcr0, true); + *tdesc = i386_create_target_description (xcr0, true, false); init_target_desc (*tdesc, i386_expedite_regs); } diff --git a/gdb/gdbserver/lynx-i386-low.c b/gdb/gdbserver/lynx-i386-low.c index bc1027dc52a..e47f6b92f63 100644 --- a/gdb/gdbserver/lynx-i386-low.c +++ b/gdb/gdbserver/lynx-i386-low.c @@ -331,7 +331,7 @@ static void lynx_i386_arch_setup (void) { struct target_desc *tdesc - = i386_create_target_description (X86_XSTATE_SSE_MASK, false); + = i386_create_target_description (X86_XSTATE_SSE_MASK, false, false); init_target_desc (tdesc, i386_expedite_regs); diff --git a/gdb/gdbserver/nto-x86-low.c b/gdb/gdbserver/nto-x86-low.c index 1b00f7f6cca..cfbe7ba6d81 100644 --- a/gdb/gdbserver/nto-x86-low.c +++ b/gdb/gdbserver/nto-x86-low.c @@ -89,7 +89,7 @@ nto_x86_arch_setup (void) { the_low_target.num_regs = 16; struct target_desc *tdesc - = i386_create_target_description (X86_XSTATE_SSE_MASK, false); + = i386_create_target_description (X86_XSTATE_SSE_MASK, false, false); init_target_desc (tdesc, i386_expedite_regs); diff --git a/gdb/gdbserver/win32-i386-low.c b/gdb/gdbserver/win32-i386-low.c index 3be75d2bf2a..7b187d3bea3 100644 --- a/gdb/gdbserver/win32-i386-low.c +++ b/gdb/gdbserver/win32-i386-low.c @@ -439,7 +439,7 @@ i386_arch_setup (void) false, false); const char **expedite_regs = amd64_expedite_regs; #else - tdesc = i386_create_target_description (X86_XSTATE_SSE_MASK, false); + tdesc = i386_create_target_description (X86_XSTATE_SSE_MASK, false, false); const char **expedite_regs = i386_expedite_regs; #endif diff --git a/gdb/i386-fbsd-nat.c b/gdb/i386-fbsd-nat.c index 2309b765068..7106e908014 100644 --- a/gdb/i386-fbsd-nat.c +++ b/gdb/i386-fbsd-nat.c @@ -160,7 +160,7 @@ i386_fbsd_nat_target::read_description () if (x86bsd_xsave_len == 0) xcr0 = X86_XSTATE_SSE_MASK; - return i386_target_description (xcr0); + return i386_target_description (xcr0, false); } #endif diff --git a/gdb/i386-fbsd-tdep.c b/gdb/i386-fbsd-tdep.c index 236edd692a1..2f28bad7286 100644 --- a/gdb/i386-fbsd-tdep.c +++ b/gdb/i386-fbsd-tdep.c @@ -267,7 +267,7 @@ i386fbsd_core_read_description (struct gdbarch *gdbarch, struct target_ops *target, bfd *abfd) { - return i386_target_description (i386fbsd_core_read_xcr0 (abfd)); + return i386_target_description (i386fbsd_core_read_xcr0 (abfd), false); } /* Similar to i386_supply_fpregset, but use XSAVE extended state. */ diff --git a/gdb/i386-go32-tdep.c b/gdb/i386-go32-tdep.c index 06833c346ca..30db72d880e 100644 --- a/gdb/i386-go32-tdep.c +++ b/gdb/i386-go32-tdep.c @@ -35,7 +35,7 @@ i386_go32_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) /* DJGPP does not support the SSE registers. */ if (!tdesc_has_registers (info.target_desc)) - tdep->tdesc = i386_target_description (X86_XSTATE_X87_MASK); + tdep->tdesc = i386_target_description (X86_XSTATE_X87_MASK, false); /* Native compiler is GCC, which uses the SVR4 register numbering even in COFF and STABS. See the comment in i386_gdbarch_init, diff --git a/gdb/i386-linux-tdep.c b/gdb/i386-linux-tdep.c index da81715061e..fa6b86f1c89 100644 --- a/gdb/i386-linux-tdep.c +++ b/gdb/i386-linux-tdep.c @@ -694,7 +694,7 @@ i386_linux_read_description (uint64_t xcr0) [(xcr0 & X86_XSTATE_PKRU) ? 1 : 0]; if (*tdesc == NULL) - *tdesc = i386_create_target_description (xcr0, true); + *tdesc = i386_create_target_description (xcr0, true, false); return *tdesc; } diff --git a/gdb/i386-tdep.c b/gdb/i386-tdep.c index bc9ba752edf..4e63832b0e6 100644 --- a/gdb/i386-tdep.c +++ b/gdb/i386-tdep.c @@ -8175,7 +8175,7 @@ i386_validate_tdesc_p (struct gdbarch_tdep *tdep, const struct tdesc_feature *feature_core; const struct tdesc_feature *feature_sse, *feature_avx, *feature_mpx, - *feature_avx512, *feature_pkeys; + *feature_avx512, *feature_pkeys, *feature_segments; int i, num_regs, valid_p; if (! tdesc_has_registers (tdesc)) @@ -8198,6 +8198,9 @@ i386_validate_tdesc_p (struct gdbarch_tdep *tdep, /* Try AVX512 registers. */ feature_avx512 = tdesc_find_feature (tdesc, "org.gnu.gdb.i386.avx512"); + /* Try segment base registers. */ + feature_segments = tdesc_find_feature (tdesc, "org.gnu.gdb.i386.segments"); + /* Try PKEYS */ feature_pkeys = tdesc_find_feature (tdesc, "org.gnu.gdb.i386.pkeys"); @@ -8307,6 +8310,16 @@ i386_validate_tdesc_p (struct gdbarch_tdep *tdep, tdep->mpx_register_names[i]); } + if (feature_segments) + { + if (tdep->fsbase_regnum < 0) + tdep->fsbase_regnum = I386_FSBASE_REGNUM; + valid_p &= tdesc_numbered_register (feature_segments, tdesc_data, + tdep->fsbase_regnum, "fs_base"); + valid_p &= tdesc_numbered_register (feature_segments, tdesc_data, + tdep->fsbase_regnum + 1, "gs_base"); + } + if (feature_pkeys) { tdep->xcr0 |= X86_XSTATE_PKRU; @@ -8543,14 +8556,14 @@ i386_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) /* Even though the default ABI only includes general-purpose registers, floating-point registers and the SSE registers, we have to leave a gap for the upper AVX, MPX and AVX512 registers. */ - set_gdbarch_num_regs (gdbarch, I386_PKEYS_NUM_REGS); + set_gdbarch_num_regs (gdbarch, I386_NUM_REGS); set_gdbarch_gnu_triplet_regexp (gdbarch, i386_gnu_triplet_regexp); /* Get the x86 target description from INFO. */ tdesc = info.target_desc; if (! tdesc_has_registers (tdesc)) - tdesc = i386_target_description (X86_XSTATE_SSE_MASK); + tdesc = i386_target_description (X86_XSTATE_SSE_MASK, false); tdep->tdesc = tdesc; tdep->num_core_regs = I386_NUM_GREGS + I387_NUM_REGS; @@ -8592,6 +8605,9 @@ i386_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) tdep->pkru_regnum = -1; tdep->num_pkeys_regs = 0; + /* No segment base registers. */ + tdep->fsbase_regnum = -1; + tdesc_data = tdesc_data_alloc (); set_gdbarch_relocate_instruction (gdbarch, i386_relocate_instruction); @@ -8717,20 +8733,21 @@ i386_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) /* Return the target description for a specified XSAVE feature mask. */ const struct target_desc * -i386_target_description (uint64_t xcr0) +i386_target_description (uint64_t xcr0, bool segments) { static target_desc *i386_tdescs \ - [2/*SSE*/][2/*AVX*/][2/*MPX*/][2/*AVX512*/][2/*PKRU*/] = {}; + [2/*SSE*/][2/*AVX*/][2/*MPX*/][2/*AVX512*/][2/*PKRU*/][2/*segments*/] = {}; target_desc **tdesc; tdesc = &i386_tdescs[(xcr0 & X86_XSTATE_SSE) ? 1 : 0] [(xcr0 & X86_XSTATE_AVX) ? 1 : 0] [(xcr0 & X86_XSTATE_MPX) ? 1 : 0] [(xcr0 & X86_XSTATE_AVX512) ? 1 : 0] - [(xcr0 & X86_XSTATE_PKRU) ? 1 : 0]; + [(xcr0 & X86_XSTATE_PKRU) ? 1 : 0] + [segments ? 1 : 0]; if (*tdesc == NULL) - *tdesc = i386_create_target_description (xcr0, false); + *tdesc = i386_create_target_description (xcr0, false, segments); return *tdesc; } @@ -9072,7 +9089,7 @@ Show Intel Memory Protection Extensions specific variables."), for (auto &a : xml_masks) { - auto tdesc = i386_target_description (a.mask); + auto tdesc = i386_target_description (a.mask, false); selftests::record_xml_tdesc (a.xml, tdesc); } diff --git a/gdb/i386-tdep.h b/gdb/i386-tdep.h index 2532306e5c8..c0d494824cc 100644 --- a/gdb/i386-tdep.h +++ b/gdb/i386-tdep.h @@ -200,6 +200,10 @@ struct gdbarch_tdep /* PKEYS register names. */ const char **pkeys_register_names; + /* Register number for %fsbase. Set this to -1 to indicate the + absence of segment base registers. */ + int fsbase_regnum; + /* Target description. */ const struct target_desc *tdesc; @@ -296,7 +300,9 @@ enum i386_regnum I386_K7_REGNUM = I386_K0_REGNUM + 7, I386_ZMM0H_REGNUM, /* %zmm0h */ I386_ZMM7H_REGNUM = I386_ZMM0H_REGNUM + 7, - I386_PKRU_REGNUM + I386_PKRU_REGNUM, + I386_FSBASE_REGNUM, + I386_GSBASE_REGNUM }; /* Register numbers of RECORD_REGMAP. */ @@ -337,6 +343,7 @@ enum record_i386_regnum #define I386_MPX_NUM_REGS (I386_BNDSTATUS_REGNUM + 1) #define I386_AVX512_NUM_REGS (I386_ZMM7H_REGNUM + 1) #define I386_PKEYS_NUM_REGS (I386_PKRU_REGNUM + 1) +#define I386_NUM_REGS (I386_GSBASE_REGNUM + 1) /* Size of the largest register. */ #define I386_MAX_REGISTER_SIZE 64 @@ -440,7 +447,8 @@ extern int i386_svr4_reg_to_regnum (struct gdbarch *gdbarch, int reg); extern int i386_process_record (struct gdbarch *gdbarch, struct regcache *regcache, CORE_ADDR addr); -extern const struct target_desc *i386_target_description (uint64_t xcr0); +extern const struct target_desc *i386_target_description (uint64_t xcr0, + bool segments); /* Return true iff the current target is MPX enabled. */ extern int i386_mpx_enabled (void);