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
@@ -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
@@ -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)
@@ -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)
@@ -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);
@@ -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);
new file mode 100644
@@ -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;
+}
new file mode 100644
@@ -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>
@@ -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.
@@ -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);
}
@@ -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);
@@ -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);
@@ -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
@@ -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
@@ -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. */
@@ -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,
@@ -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;
}
@@ -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);
}
@@ -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);