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.
This commit is contained in:
parent
7cde5fc2ec
commit
1163a4b7a3
@ -1,3 +1,34 @@
|
||||
2019-03-12 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-03-12 Eli Zaretskii <eliz@gnu.org>
|
||||
|
||||
PR/24325
|
||||
|
@ -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);
|
||||
|
||||
|
@ -21,6 +21,7 @@
|
||||
#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);
|
||||
|
||||
#endif /* ARCH_I386_H */
|
||||
|
15
gdb/features/i386/32bit-segments.c
Normal file
15
gdb/features/i386/32bit-segments.c
Normal file
@ -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;
|
||||
}
|
12
gdb/features/i386/32bit-segments.xml
Normal file
12
gdb/features/i386/32bit-segments.xml
Normal file
@ -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-03-12 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-03-12 Tom Tromey <tromey@adacore.com>
|
||||
|
||||
* linux-low.c (iterate_over_lwps): Update.
|
||||
|
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user