Message ID | afb3f5e132cc8844216f7da3084b2db9ddf73d14.1548180889.git.jhb@FreeBSD.org |
---|---|
State | New |
Headers | show |
On 2019-01-22 1:42 p.m., John Baldwin wrote: > As on amd64, these registers hold the base address of the fs and gs > segments, respectively. For i386 these two registers are 32 bits. I just started to look at this, still trying to get my head around it and connect all the dots. Just a silly question for now: > diff --git a/gdb/amd64-tdep.c b/gdb/amd64-tdep.c > index d4143ae155..1eb0bcdf17 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; > } Can you explain what this change does and why it is needed? I am a bit lost. I see you add something equivalent in i386-tdep.c, but as far as I know, they are completely separate. Simon
On 1/26/19 7:47 PM, Simon Marchi wrote: > On 2019-01-22 1:42 p.m., John Baldwin wrote: >> As on amd64, these registers hold the base address of the fs and gs >> segments, respectively. For i386 these two registers are 32 bits. > > I just started to look at this, still trying to get my head around it and > connect all the dots. Just a silly question for now: > >> diff --git a/gdb/amd64-tdep.c b/gdb/amd64-tdep.c >> index d4143ae155..1eb0bcdf17 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; >> } > > Can you explain what this change does and why it is needed? I am a bit lost. > > I see you add something equivalent in i386-tdep.c, but as far as I know, they are completely > separate. It took a while for me to understand this as well. :-/ The 64-bit (amd64) and 32-bit (i386) gdbarch's share a fair bit of code. In particular, the 64-bit gdbarch is "inherited" from the 32-bit one, but overrides various behaviors. Specifically, see the comment above i386_gdbarch_init. amd64_init_abi is called from OSABI specific handlers part way through i386_gdbarch_init from gdbarch_init_osabi() to apply 64-bit overrides. One of the things that gets overridden is that 32-bit and 64-bit gdbarch's use different register numbers. This is because 64-bit x86 has r8-15. The first 8 registers are the same, but the remaining registers for FPU, SSE, etc. are all shifted by 8 for amd64. There's a comment that hints at this in i386-tdep.h: /* GDB's i386 target supports both the 32-bit Intel Architecture (IA-32) and the 64-bit AMD x86-64 architecture. Internally it uses a similar register layout for both. - General purpose registers - FPU data registers - FPU control registers - SSE data registers - SSE control register The general purpose registers for the x86-64 architecture are quite different from IA-32. Therefore, gdbarch_fp0_regnum determines the register number at which the FPU data registers start. The number of FPU data and control registers is the same for both architectures. The number of SSE registers however, differs and is determined by the num_xmm_regs member of `struct gdbarch_tdep'. */ As the comment notes, the way this is handled for the FPU registers is that tdep->fp0_regnum holds the value of the first FPU register (AMD64_ST0_REGNUM vs I386_ST0_REGNUM). This same approach is then used for all the other shared register banks (tdep->mm0_regnum, ymm0_regnum, zmm0_regnum, etc.). Helper variables are also used to handle the different numbers of SSE/AVX registers on 32-bit vs 64-bit. i386_validate_tdesc_p() is called after gdbarch_init_osabi() to add the shared register sets. It checks for each feature being present. If it is, it first checks to see if the corresponding tdep fields (e.g. ymm0_regnum) have been set. If they aren't, it sets them to the I386 values. Then it adds the appropriate registers for each feature. In the case of a 64-bit architecture, amd64_init_abi() is called from gdbarch_init_osabi() before i386_validate_tdesc_p() is called. amd64_init_abi() sets the various tdep variables for any features that are present to the AMD64 values. Then when i386_validate_tdesc_p() runs, it still adds the registers, but it does so using the 64-bit register numbers instead of 32-bit register numbers. When fs_base and gs_base were first added, they were only added on amd64, so they were not treated as a shared register set. Instead, they were just added directly in amd64_init_abi() using the AMD64 register numbers. This particular part of the patch (along with the change to i386_validate_tdesc_p in i386-tdep.c) is changing the fs_base/gs_base register set to be a shared register set like FPU, AVX/SSE, etc. It does this by adding a new tdep->fsbase_regnum to hold the base number of the two registers. It then changes amd64_init_abi() to just set the tdep field as it does for other register sets and changes i386_validate_tdesc_p to add the registers at the appropriate register number, defaulting to the I386 values if the tdep field wasn't set. Hopefully that isn't too confusing. It took me a while to figure it out myself.
On 2019-01-28 12:54, John Baldwin wrote: > On 1/26/19 7:47 PM, Simon Marchi wrote: >> On 2019-01-22 1:42 p.m., John Baldwin wrote: >>> As on amd64, these registers hold the base address of the fs and gs >>> segments, respectively. For i386 these two registers are 32 bits. >> >> I just started to look at this, still trying to get my head around it >> and >> connect all the dots. Just a silly question for now: >> >>> diff --git a/gdb/amd64-tdep.c b/gdb/amd64-tdep.c >>> index d4143ae155..1eb0bcdf17 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; >>> } >> >> Can you explain what this change does and why it is needed? I am a >> bit lost. >> >> I see you add something equivalent in i386-tdep.c, but as far as I >> know, they are completely >> separate. > > It took a while for me to understand this as well. :-/ > > The 64-bit (amd64) and 32-bit (i386) gdbarch's share a fair bit of > code. > In particular, the 64-bit gdbarch is "inherited" from the 32-bit one, > but > overrides various behaviors. Specifically, see the comment above > i386_gdbarch_init. amd64_init_abi is called from OSABI specific > handlers > part way through i386_gdbarch_init from gdbarch_init_osabi() to apply > 64-bit overrides. > > One of the things that gets overridden is that 32-bit and 64-bit > gdbarch's > use different register numbers. This is because 64-bit x86 has r8-15. > The first 8 registers are the same, but the remaining registers for > FPU, > SSE, etc. are all shifted by 8 for amd64. There's a comment that hints > at > this in i386-tdep.h: > > /* GDB's i386 target supports both the 32-bit Intel Architecture > (IA-32) and the 64-bit AMD x86-64 architecture. Internally it uses > a similar register layout for both. > > - General purpose registers > - FPU data registers > - FPU control registers > - SSE data registers > - SSE control register > > The general purpose registers for the x86-64 architecture are quite > different from IA-32. Therefore, gdbarch_fp0_regnum > determines the register number at which the FPU data registers > start. The number of FPU data and control registers is the same > for both architectures. The number of SSE registers however, > differs and is determined by the num_xmm_regs member of `struct > gdbarch_tdep'. */ > > As the comment notes, the way this is handled for the FPU registers is > that > tdep->fp0_regnum holds the value of the first FPU register > (AMD64_ST0_REGNUM > vs I386_ST0_REGNUM). This same approach is then used for all the other > shared register banks (tdep->mm0_regnum, ymm0_regnum, zmm0_regnum, > etc.). > Helper variables are also used to handle the different numbers of > SSE/AVX > registers on 32-bit vs 64-bit. > > i386_validate_tdesc_p() is called after gdbarch_init_osabi() to add the > shared register sets. It checks for each feature being present. If it > is, > it first checks to see if the corresponding tdep fields (e.g. > ymm0_regnum) > have been set. If they aren't, it sets them to the I386 values. Then > it > adds the appropriate registers for each feature. In the case of a > 64-bit > architecture, amd64_init_abi() is called from gdbarch_init_osabi() > before > i386_validate_tdesc_p() is called. amd64_init_abi() sets the various > tdep > variables for any features that are present to the AMD64 values. Then > when > i386_validate_tdesc_p() runs, it still adds the registers, but it does > so > using the 64-bit register numbers instead of 32-bit register numbers. > > When fs_base and gs_base were first added, they were only added on > amd64, > so they were not treated as a shared register set. Instead, they were > just added directly in amd64_init_abi() using the AMD64 register > numbers. > This particular part of the patch (along with the change to > i386_validate_tdesc_p in i386-tdep.c) is changing the fs_base/gs_base > register set to be a shared register set like FPU, AVX/SSE, etc. It > does > this by adding a new tdep->fsbase_regnum to hold the base number of the > two registers. It then changes amd64_init_abi() to just set the tdep > field as it does for other register sets and changes > i386_validate_tdesc_p > to add the registers at the appropriate register number, defaulting to > the > I386 values if the tdep field wasn't set. > > Hopefully that isn't too confusing. It took me a while to figure it > out > myself. Thanks for the explanation, it does clear it up. There was nothing else in this patch that stood out to me. Simon
diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 8e03dbf883..4afd5b664e 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,34 @@ +2019-01-22 John Baldwin <jhb@FreeBSD.org> + + * 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-01-22 Philippe Waroquiers <philippe.waroquiers@skynet.be> * event-top.c (handle_line_of_input): use unique_xmalloc_ptr for diff --git a/gdb/amd64-fbsd-nat.c b/gdb/amd64-fbsd-nat.c index 6d8e12b033..39ba69d9bf 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 d4143ae155..1eb0bcdf17 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 73987da97b..311b5fd8c8 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 a6a801b818..af8c6bd73f 100644 --- a/gdb/arch/i386.h +++ b/gdb/arch/i386.h @@ -18,4 +18,5 @@ #include "common/tdesc.h" #include <stdint.h> -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); diff --git a/gdb/features/i386/32bit-segments.c b/gdb/features/i386/32bit-segments.c new file mode 100644 index 0000000000..c22c3dfbc3 --- /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 0000000000..098948e5ec --- /dev/null +++ b/gdb/features/i386/32bit-segments.xml @@ -0,0 +1,12 @@ +<?xml version="1.0"?> +<!-- Copyright (C) 2016-2018 Free Software Foundation, Inc. + + Copying and distribution of this file, with or without modification, + are permitted in any medium without royalty provided the copyright + notice and this notice are preserved. --> + +<!DOCTYPE feature SYSTEM "gdb-target.dtd"> +<feature name="org.gnu.gdb.i386.segments"> + <reg name="fs_base" bitsize="32" type="int"/> + <reg name="gs_base" bitsize="32" type="int"/> +</feature> diff --git a/gdb/gdbserver/ChangeLog b/gdb/gdbserver/ChangeLog index 5312ca9919..fc8b37976a 100644 --- a/gdb/gdbserver/ChangeLog +++ b/gdb/gdbserver/ChangeLog @@ -1,3 +1,11 @@ +2019-01-22 John Baldwin <jhb@FreeBSD.org> + + * 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-01-21 Tom Tromey <tom@tromey.com> * tracepoint.c: Fix includes. diff --git a/gdb/gdbserver/linux-x86-tdesc.c b/gdb/gdbserver/linux-x86-tdesc.c index 04bccc84ed..8f24a3d72d 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 0731d2a73d..77ec8235e0 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 19c9acf42b..6930664e00 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 30f7af7553..9b7bc40225 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 855572143b..8ff104cf72 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 82dfbd5c35..43b15167ae 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 5a18f35f99..200de53cd8 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 0f344b0710..b2461836ad 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 8b2c72ac7b..65a5d6ab95 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 2532306e5c..c0d494824c 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);