mirror of
https://github.com/bminor/binutils-gdb.git
synced 2025-12-05 23:23:09 +00:00
gdb, gdbserver: Use xstate_bv for target description creation on x86.
The XSAVE function set is organized in state components, which are a set of registers or parts of registers. So-called XSAVE-supported features are organized using state-component bitmaps, each bit corresponding to a single state component. The Intel Software Developer's Manual uses the term xstate_bv for a state-component bitmap, which is defined as XCR0 | IA32_XSS. The control register XCR0 only contains a state-component bitmap that specifies user state components, while IA32_XSS contains a state-component bitmap that specifies supervisor state components. Until now, XCR0 is used as input for target description creation in GDB. However, a following patch will add userspace support for the CET shadow stack feature by Intel. The CET state is configured in IA32_XSS and consists of 2 state components: - State component 11 used for the 2 MSRs controlling user-mode functionality for CET (CET_U state) - State component 12 used for the 3 MSRs containing shadow-stack pointers for privilege levels 0-2 (CET_S state). Reading the CET shadow stack pointer register on linux requires a separate ptrace call using NT_X86_SHSTK. To pass the CET shadow stack enablement state we would like to pass the xstate_bv value instead of xcr0 for target description creation. To prepare for that, we rename the xcr0 mask values for target description creation to xstate_bv. However, this patch doesn't add any functional changes in GDB. Future states specified in IA32_XSS such as CET will create a combined xstate_bv_mask including xcr0 register value and its corresponding bit in the state component bitmap. This combined mask will then be used to create the target descriptions. Reviewed-By: Thiago Jung Bauermann <thiago.bauermann@linaro.org> Approved-By: Luis Machado <luis.machado@arm.com>
This commit is contained in:
@@ -3568,23 +3568,23 @@ amd64_x32_none_init_abi (gdbarch_info info, gdbarch *arch)
|
|||||||
amd64_target_description (X86_XSTATE_SSE_MASK, true));
|
amd64_target_description (X86_XSTATE_SSE_MASK, true));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Return the target description for a specified XSAVE feature mask. */
|
/* See amd64-tdep.h. */
|
||||||
|
|
||||||
const struct target_desc *
|
const struct target_desc *
|
||||||
amd64_target_description (uint64_t xcr0, bool segments)
|
amd64_target_description (uint64_t xstate_bv, bool segments)
|
||||||
{
|
{
|
||||||
static target_desc *amd64_tdescs \
|
static target_desc *amd64_tdescs \
|
||||||
[2/*AVX*/][2/*AVX512*/][2/*PKRU*/][2/*segments*/] = {};
|
[2/*AVX*/][2/*AVX512*/][2/*PKRU*/][2/*segments*/] = {};
|
||||||
target_desc **tdesc;
|
target_desc **tdesc;
|
||||||
|
|
||||||
tdesc = &amd64_tdescs[(xcr0 & X86_XSTATE_AVX) ? 1 : 0]
|
tdesc = &amd64_tdescs[(xstate_bv & X86_XSTATE_AVX) ? 1 : 0]
|
||||||
[(xcr0 & X86_XSTATE_AVX512) ? 1 : 0]
|
[(xstate_bv & X86_XSTATE_AVX512) ? 1 : 0]
|
||||||
[(xcr0 & X86_XSTATE_PKRU) ? 1 : 0]
|
[(xstate_bv & X86_XSTATE_PKRU) ? 1 : 0]
|
||||||
[segments ? 1 : 0];
|
[segments ? 1 : 0];
|
||||||
|
|
||||||
if (*tdesc == NULL)
|
if (*tdesc == NULL)
|
||||||
*tdesc = amd64_create_target_description (xcr0, false, false,
|
*tdesc = amd64_create_target_description (xstate_bv, false,
|
||||||
segments);
|
false, segments);
|
||||||
|
|
||||||
return *tdesc;
|
return *tdesc;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -108,8 +108,12 @@ extern void amd64_init_abi (struct gdbarch_info info,
|
|||||||
extern void amd64_x32_init_abi (struct gdbarch_info info,
|
extern void amd64_x32_init_abi (struct gdbarch_info info,
|
||||||
struct gdbarch *gdbarch,
|
struct gdbarch *gdbarch,
|
||||||
const target_desc *default_tdesc);
|
const target_desc *default_tdesc);
|
||||||
extern const struct target_desc *amd64_target_description (uint64_t xcr0,
|
|
||||||
bool segments);
|
/* Return the target description for the specified xsave features as
|
||||||
|
defined in XSTATE_BV and SEGMENTS. */
|
||||||
|
|
||||||
|
extern const struct target_desc *amd64_target_description
|
||||||
|
(uint64_t xstate_bv, bool segments);
|
||||||
|
|
||||||
/* Fill register REGNUM in REGCACHE with the appropriate
|
/* Fill register REGNUM in REGCACHE with the appropriate
|
||||||
floating-point or SSE register value from *FXSAVE. If REGNUM is
|
floating-point or SSE register value from *FXSAVE. If REGNUM is
|
||||||
|
|||||||
@@ -26,34 +26,35 @@
|
|||||||
/* See arch/amd64-linux-tdesc.h. */
|
/* See arch/amd64-linux-tdesc.h. */
|
||||||
|
|
||||||
const struct target_desc *
|
const struct target_desc *
|
||||||
amd64_linux_read_description (uint64_t xcr0, bool is_x32)
|
amd64_linux_read_description (uint64_t xstate_bv, bool is_x32)
|
||||||
{
|
{
|
||||||
/* The type used for the amd64 and x32 target description caches. */
|
/* The type used for the amd64 and x32 target description caches. */
|
||||||
using tdesc_cache_type = std::unordered_map<uint64_t, const target_desc_up>;
|
using tdesc_cache_type = std::unordered_map<uint64_t, const target_desc_up>;
|
||||||
|
|
||||||
/* Caches for the previously seen amd64 and x32 target descriptions,
|
/* Caches for the previously seen amd64 and x32 target descriptions,
|
||||||
indexed by the xcr0 value that created the target description. These
|
indexed by the xstate_bv value that created the target
|
||||||
need to be static within this function to ensure they are initialised
|
description. These need to be static within this function to ensure
|
||||||
before first use. */
|
they are initialised before first use. */
|
||||||
static tdesc_cache_type amd64_tdesc_cache, x32_tdesc_cache;
|
static tdesc_cache_type amd64_tdesc_cache, x32_tdesc_cache;
|
||||||
|
|
||||||
tdesc_cache_type &tdesc_cache = is_x32 ? x32_tdesc_cache : amd64_tdesc_cache;
|
tdesc_cache_type &tdesc_cache = is_x32 ? x32_tdesc_cache : amd64_tdesc_cache;
|
||||||
|
|
||||||
/* Only some bits are checked when creating a tdesc, but the XCR0 value
|
/* Only some bits are checked when creating a tdesc, but the
|
||||||
contains other feature bits that are not relevant for tdesc creation.
|
xstate_bv value contains other feature bits that are not
|
||||||
When indexing into the TDESC_CACHE we need to use a consistent xcr0
|
relevant for tdesc creation.
|
||||||
value otherwise we might fail to find an existing tdesc which has the
|
When indexing into the TDESC_CACHE we need to use a consistent
|
||||||
same set of relevant bits set. */
|
xstate_bv value otherwise we might fail to find an existing
|
||||||
xcr0 &= is_x32
|
tdesc which has the same set of relevant bits set. */
|
||||||
? x86_linux_x32_xcr0_feature_mask ()
|
xstate_bv &= is_x32
|
||||||
: x86_linux_amd64_xcr0_feature_mask ();
|
? x86_linux_x32_xstate_bv_feature_mask ()
|
||||||
|
: x86_linux_amd64_xstate_bv_feature_mask ();
|
||||||
|
|
||||||
const auto it = tdesc_cache.find (xcr0);
|
const auto it = tdesc_cache.find (xstate_bv);
|
||||||
if (it != tdesc_cache.end ())
|
if (it != tdesc_cache.end ())
|
||||||
return it->second.get ();
|
return it->second.get ();
|
||||||
|
|
||||||
/* Create the previously unseen target description. */
|
/* Create the previously unseen target description. */
|
||||||
target_desc_up tdesc (amd64_create_target_description (xcr0, is_x32,
|
target_desc_up tdesc (amd64_create_target_description (xstate_bv, is_x32,
|
||||||
true, true));
|
true, true));
|
||||||
x86_linux_post_init_tdesc (tdesc.get (), true);
|
x86_linux_post_init_tdesc (tdesc.get (), true);
|
||||||
|
|
||||||
@@ -61,6 +62,6 @@ amd64_linux_read_description (uint64_t xcr0, bool is_x32)
|
|||||||
target_desc_up. This is safe as the cache (and the pointers contained
|
target_desc_up. This is safe as the cache (and the pointers contained
|
||||||
within it) are not deleted until GDB exits. */
|
within it) are not deleted until GDB exits. */
|
||||||
target_desc *ptr = tdesc.get ();
|
target_desc *ptr = tdesc.get ();
|
||||||
tdesc_cache.emplace (xcr0, std::move (tdesc));
|
tdesc_cache.emplace (xstate_bv, std::move (tdesc));
|
||||||
return ptr;
|
return ptr;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,9 +22,10 @@
|
|||||||
|
|
||||||
struct target_desc;
|
struct target_desc;
|
||||||
|
|
||||||
/* Return the AMD64 target descriptions corresponding to XCR0 and IS_X32. */
|
/* Return the AMD64 target descriptions corresponding to XSTATE_BV and
|
||||||
|
IS_X32. */
|
||||||
|
|
||||||
extern const target_desc *amd64_linux_read_description (uint64_t xcr0,
|
extern const target_desc *amd64_linux_read_description
|
||||||
bool is_x32);
|
(uint64_t xstate_bv, bool is_x32);
|
||||||
|
|
||||||
#endif /* GDB_ARCH_AMD64_LINUX_TDESC_H */
|
#endif /* GDB_ARCH_AMD64_LINUX_TDESC_H */
|
||||||
|
|||||||
@@ -30,14 +30,11 @@
|
|||||||
|
|
||||||
#include "../features/i386/x32-core.c"
|
#include "../features/i386/x32-core.c"
|
||||||
|
|
||||||
/* Create amd64 target descriptions according to XCR0. If IS_X32 is
|
/* See arch/amd64.h. */
|
||||||
true, create the x32 ones. If IS_LINUX is true, create target
|
|
||||||
descriptions for Linux. If SEGMENTS is true, then include
|
|
||||||
the "org.gnu.gdb.i386.segments" feature registers. */
|
|
||||||
|
|
||||||
target_desc *
|
target_desc *
|
||||||
amd64_create_target_description (uint64_t xcr0, bool is_x32, bool is_linux,
|
amd64_create_target_description (uint64_t xstate_bv, bool is_x32,
|
||||||
bool segments)
|
bool is_linux, bool segments)
|
||||||
{
|
{
|
||||||
target_desc_up tdesc = allocate_target_description ();
|
target_desc_up tdesc = allocate_target_description ();
|
||||||
|
|
||||||
@@ -62,13 +59,13 @@ amd64_create_target_description (uint64_t xcr0, bool is_x32, bool is_linux,
|
|||||||
if (segments)
|
if (segments)
|
||||||
regnum = create_feature_i386_64bit_segments (tdesc.get (), regnum);
|
regnum = create_feature_i386_64bit_segments (tdesc.get (), regnum);
|
||||||
|
|
||||||
if (xcr0 & X86_XSTATE_AVX)
|
if (xstate_bv & X86_XSTATE_AVX)
|
||||||
regnum = create_feature_i386_64bit_avx (tdesc.get (), regnum);
|
regnum = create_feature_i386_64bit_avx (tdesc.get (), regnum);
|
||||||
|
|
||||||
if (xcr0 & X86_XSTATE_AVX512)
|
if (xstate_bv & X86_XSTATE_AVX512)
|
||||||
regnum = create_feature_i386_64bit_avx512 (tdesc.get (), regnum);
|
regnum = create_feature_i386_64bit_avx512 (tdesc.get (), regnum);
|
||||||
|
|
||||||
if (xcr0 & X86_XSTATE_PKRU)
|
if (xstate_bv & X86_XSTATE_PKRU)
|
||||||
regnum = create_feature_i386_pkeys (tdesc.get (), regnum);
|
regnum = create_feature_i386_pkeys (tdesc.get (), regnum);
|
||||||
|
|
||||||
return tdesc.release ();
|
return tdesc.release ();
|
||||||
|
|||||||
@@ -21,7 +21,13 @@
|
|||||||
#include "gdbsupport/tdesc.h"
|
#include "gdbsupport/tdesc.h"
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
target_desc *amd64_create_target_description (uint64_t xcr0, bool is_x32,
|
/* Create amd64 target descriptions according to XSTATE_BV. If
|
||||||
bool is_linux, bool segments);
|
IS_X32 is true, create the x32 ones. If IS_LINUX is true, create
|
||||||
|
target descriptions for Linux. If SEGMENTS is true, then include
|
||||||
|
the "org.gnu.gdb.i386.segments" feature registers. */
|
||||||
|
|
||||||
|
target_desc *amd64_create_target_description (uint64_t xstate_bv,
|
||||||
|
bool is_x32, bool is_linux,
|
||||||
|
bool segments);
|
||||||
|
|
||||||
#endif /* GDB_ARCH_AMD64_H */
|
#endif /* GDB_ARCH_AMD64_H */
|
||||||
|
|||||||
@@ -25,32 +25,35 @@
|
|||||||
/* See arch/i386-linux-tdesc.h. */
|
/* See arch/i386-linux-tdesc.h. */
|
||||||
|
|
||||||
const target_desc *
|
const target_desc *
|
||||||
i386_linux_read_description (uint64_t xcr0)
|
i386_linux_read_description (uint64_t xstate_bv)
|
||||||
{
|
{
|
||||||
/* Cache of previously seen i386 target descriptions, indexed by the xcr0
|
/* Cache of previously seen i386 target descriptions, indexed by the
|
||||||
value that created the target description. This needs to be static
|
xstate_bv value that created the target description. This
|
||||||
within this function to ensure it is initialised before first use. */
|
needs to be static within this function to ensure it is initialised
|
||||||
|
before first use. */
|
||||||
static std::unordered_map<uint64_t, const target_desc_up> i386_tdesc_cache;
|
static std::unordered_map<uint64_t, const target_desc_up> i386_tdesc_cache;
|
||||||
|
|
||||||
/* Only some bits are checked when creating a tdesc, but the XCR0 value
|
/* Only some bits are checked when creating a tdesc, but the
|
||||||
contains other feature bits that are not relevant for tdesc creation.
|
XSTATE_BV value contains other feature bits that are not relevant
|
||||||
When indexing into the I386_TDESC_CACHE we need to use a consistent
|
for tdesc creation. When indexing into the I386_TDESC_CACHE
|
||||||
xcr0 value otherwise we might fail to find an existing tdesc which has
|
we need to use a consistent XSTATE_BV value otherwise we might fail
|
||||||
the same set of relevant bits set. */
|
to find an existing tdesc which has the same set of relevant bits
|
||||||
xcr0 &= x86_linux_i386_xcr0_feature_mask ();
|
set. */
|
||||||
|
xstate_bv &= x86_linux_i386_xstate_bv_feature_mask ();
|
||||||
|
|
||||||
const auto it = i386_tdesc_cache.find (xcr0);
|
const auto it = i386_tdesc_cache.find (xstate_bv);
|
||||||
if (it != i386_tdesc_cache.end ())
|
if (it != i386_tdesc_cache.end ())
|
||||||
return it->second.get ();
|
return it->second.get ();
|
||||||
|
|
||||||
/* Create the previously unseen target description. */
|
/* Create the previously unseen target description. */
|
||||||
target_desc_up tdesc (i386_create_target_description (xcr0, true, false));
|
target_desc_up tdesc
|
||||||
|
(i386_create_target_description (xstate_bv, true, false));
|
||||||
x86_linux_post_init_tdesc (tdesc.get (), false);
|
x86_linux_post_init_tdesc (tdesc.get (), false);
|
||||||
|
|
||||||
/* Add to the cache, and return a pointer borrowed from the
|
/* Add to the cache, and return a pointer borrowed from the
|
||||||
target_desc_up. This is safe as the cache (and the pointers contained
|
target_desc_up. This is safe as the cache (and the pointers contained
|
||||||
within it) are not deleted until GDB exits. */
|
within it) are not deleted until GDB exits. */
|
||||||
target_desc *ptr = tdesc.get ();
|
target_desc *ptr = tdesc.get ();
|
||||||
i386_tdesc_cache.emplace (xcr0, std::move (tdesc));
|
i386_tdesc_cache.emplace (xstate_bv, std::move (tdesc));
|
||||||
return ptr;
|
return ptr;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,8 +22,9 @@
|
|||||||
|
|
||||||
struct target_desc;
|
struct target_desc;
|
||||||
|
|
||||||
/* Return the i386 target description corresponding to XCR0. */
|
/* Return the i386 target description corresponding to XSTATE_BV. */
|
||||||
|
|
||||||
extern const struct target_desc *i386_linux_read_description (uint64_t xcr0);
|
extern const struct target_desc *i386_linux_read_description
|
||||||
|
(uint64_t xstate_bv);
|
||||||
|
|
||||||
#endif /* GDB_ARCH_I386_LINUX_TDESC_H */
|
#endif /* GDB_ARCH_I386_LINUX_TDESC_H */
|
||||||
|
|||||||
@@ -29,10 +29,11 @@
|
|||||||
#include "../features/i386/32bit-segments.c"
|
#include "../features/i386/32bit-segments.c"
|
||||||
#include "../features/i386/pkeys.c"
|
#include "../features/i386/pkeys.c"
|
||||||
|
|
||||||
/* Create i386 target descriptions according to XCR0. */
|
/* See arch/i386.h. */
|
||||||
|
|
||||||
target_desc *
|
target_desc *
|
||||||
i386_create_target_description (uint64_t xcr0, bool is_linux, bool segments)
|
i386_create_target_description (uint64_t xstate_bv, bool is_linux,
|
||||||
|
bool segments)
|
||||||
{
|
{
|
||||||
target_desc_up tdesc = allocate_target_description ();
|
target_desc_up tdesc = allocate_target_description ();
|
||||||
|
|
||||||
@@ -44,10 +45,10 @@ i386_create_target_description (uint64_t xcr0, bool is_linux, bool segments)
|
|||||||
|
|
||||||
long regnum = 0;
|
long regnum = 0;
|
||||||
|
|
||||||
if (xcr0 & X86_XSTATE_X87)
|
if (xstate_bv & X86_XSTATE_X87)
|
||||||
regnum = create_feature_i386_32bit_core (tdesc.get (), regnum);
|
regnum = create_feature_i386_32bit_core (tdesc.get (), regnum);
|
||||||
|
|
||||||
if (xcr0 & X86_XSTATE_SSE)
|
if (xstate_bv & X86_XSTATE_SSE)
|
||||||
regnum = create_feature_i386_32bit_sse (tdesc.get (), regnum);
|
regnum = create_feature_i386_32bit_sse (tdesc.get (), regnum);
|
||||||
|
|
||||||
if (is_linux)
|
if (is_linux)
|
||||||
@@ -56,13 +57,13 @@ i386_create_target_description (uint64_t xcr0, bool is_linux, bool segments)
|
|||||||
if (segments)
|
if (segments)
|
||||||
regnum = create_feature_i386_32bit_segments (tdesc.get (), regnum);
|
regnum = create_feature_i386_32bit_segments (tdesc.get (), regnum);
|
||||||
|
|
||||||
if (xcr0 & X86_XSTATE_AVX)
|
if (xstate_bv & X86_XSTATE_AVX)
|
||||||
regnum = create_feature_i386_32bit_avx (tdesc.get (), regnum);
|
regnum = create_feature_i386_32bit_avx (tdesc.get (), regnum);
|
||||||
|
|
||||||
if (xcr0 & X86_XSTATE_AVX512)
|
if (xstate_bv & X86_XSTATE_AVX512)
|
||||||
regnum = create_feature_i386_32bit_avx512 (tdesc.get (), regnum);
|
regnum = create_feature_i386_32bit_avx512 (tdesc.get (), regnum);
|
||||||
|
|
||||||
if (xcr0 & X86_XSTATE_PKRU)
|
if (xstate_bv & X86_XSTATE_PKRU)
|
||||||
regnum = create_feature_i386_pkeys (tdesc.get (), regnum);
|
regnum = create_feature_i386_pkeys (tdesc.get (), regnum);
|
||||||
|
|
||||||
return tdesc.release ();
|
return tdesc.release ();
|
||||||
|
|||||||
@@ -21,7 +21,12 @@
|
|||||||
#include "gdbsupport/tdesc.h"
|
#include "gdbsupport/tdesc.h"
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
target_desc *i386_create_target_description (uint64_t xcr0, bool is_linux,
|
/* Create i386 target descriptions according to XSTATE_BV. If IS_LINUX is
|
||||||
|
true, create target descriptions for Linux. If SEGMENTS is true, then
|
||||||
|
include the "org.gnu.gdb.i386.segments" feature registers. */
|
||||||
|
|
||||||
|
target_desc *i386_create_target_description (uint64_t xstate_bv,
|
||||||
|
bool is_linux,
|
||||||
bool segments);
|
bool segments);
|
||||||
|
|
||||||
#endif /* GDB_ARCH_I386_H */
|
#endif /* GDB_ARCH_I386_H */
|
||||||
|
|||||||
@@ -28,18 +28,21 @@
|
|||||||
|
|
||||||
We want to cache target descriptions, and this is currently done in
|
We want to cache target descriptions, and this is currently done in
|
||||||
three separate caches, one each for i386, amd64, and x32. Additionally,
|
three separate caches, one each for i386, amd64, and x32. Additionally,
|
||||||
the caching we're discussing here is Linux only, and for Linux, the only
|
the caching we're discussing here is Linux only. Currently for Linux,
|
||||||
thing that has an impact on target description creation is the xcr0
|
the only thing that has an impact on target description creation are
|
||||||
value.
|
the supported features in xsave which are modelled by a xstate_bv
|
||||||
|
value, which has the same format than the state component bitmap.
|
||||||
|
|
||||||
In order to ensure the cache functions correctly we need to filter out
|
In order to ensure the cache functions correctly we need to filter only
|
||||||
only those xcr0 feature bits that are relevant, we can then cache target
|
those xstate_bv feature bits that are relevant, we can then cache
|
||||||
descriptions based on the relevant feature bits. Two xcr0 values might
|
target descriptions based on the relevant feature bits. Two xstate_bv
|
||||||
be different, but have the same relevant feature bits. In this case we
|
values might be different, but have the same relevant feature bits. In
|
||||||
would expect the two xcr0 values to map to the same cache entry. */
|
this case we would expect the two xstate_bv values to map to the same
|
||||||
|
cache entry. */
|
||||||
|
|
||||||
struct x86_xstate_feature {
|
struct x86_xstate_feature {
|
||||||
/* The xstate feature mask. This is a mask against an xcr0 value. */
|
/* The xstate feature mask. This is a mask against the state component
|
||||||
|
bitmap. */
|
||||||
uint64_t feature;
|
uint64_t feature;
|
||||||
|
|
||||||
/* Is this feature checked when creating an i386 target description. */
|
/* Is this feature checked when creating an i386 target description. */
|
||||||
@@ -56,9 +59,9 @@ struct x86_xstate_feature {
|
|||||||
checked when building a target description for i386, amd64, or x32.
|
checked when building a target description for i386, amd64, or x32.
|
||||||
|
|
||||||
If in the future, due to simplifications or refactoring, this table ever
|
If in the future, due to simplifications or refactoring, this table ever
|
||||||
ends up with 'true' for every xcr0 feature on every target type, then this
|
ends up with 'true' for every xsave feature on every target type, then
|
||||||
is an indication that this table should probably be removed, and that the
|
this is an indication that this table should probably be removed, and
|
||||||
rest of the code in this file can be simplified. */
|
that the rest of the code in this file can be simplified. */
|
||||||
|
|
||||||
static constexpr x86_xstate_feature x86_linux_all_xstate_features[] = {
|
static constexpr x86_xstate_feature x86_linux_all_xstate_features[] = {
|
||||||
/* Feature, i386, amd64, x32. */
|
/* Feature, i386, amd64, x32. */
|
||||||
@@ -73,7 +76,7 @@ static constexpr x86_xstate_feature x86_linux_all_xstate_features[] = {
|
|||||||
that are checked for when building an i386 target description. */
|
that are checked for when building an i386 target description. */
|
||||||
|
|
||||||
static constexpr uint64_t
|
static constexpr uint64_t
|
||||||
x86_linux_i386_xcr0_feature_mask_1 ()
|
x86_linux_i386_xstate_bv_feature_mask_1 ()
|
||||||
{
|
{
|
||||||
uint64_t mask = 0;
|
uint64_t mask = 0;
|
||||||
|
|
||||||
@@ -88,7 +91,7 @@ x86_linux_i386_xcr0_feature_mask_1 ()
|
|||||||
that are checked for when building an amd64 target description. */
|
that are checked for when building an amd64 target description. */
|
||||||
|
|
||||||
static constexpr uint64_t
|
static constexpr uint64_t
|
||||||
x86_linux_amd64_xcr0_feature_mask_1 ()
|
x86_linux_amd64_xstate_bv_feature_mask_1 ()
|
||||||
{
|
{
|
||||||
uint64_t mask = 0;
|
uint64_t mask = 0;
|
||||||
|
|
||||||
@@ -103,7 +106,7 @@ x86_linux_amd64_xcr0_feature_mask_1 ()
|
|||||||
that are checked for when building an x32 target description. */
|
that are checked for when building an x32 target description. */
|
||||||
|
|
||||||
static constexpr uint64_t
|
static constexpr uint64_t
|
||||||
x86_linux_x32_xcr0_feature_mask_1 ()
|
x86_linux_x32_xstate_bv_feature_mask_1 ()
|
||||||
{
|
{
|
||||||
uint64_t mask = 0;
|
uint64_t mask = 0;
|
||||||
|
|
||||||
@@ -117,25 +120,25 @@ x86_linux_x32_xcr0_feature_mask_1 ()
|
|||||||
/* See arch/x86-linux-tdesc-features.h. */
|
/* See arch/x86-linux-tdesc-features.h. */
|
||||||
|
|
||||||
uint64_t
|
uint64_t
|
||||||
x86_linux_i386_xcr0_feature_mask ()
|
x86_linux_i386_xstate_bv_feature_mask ()
|
||||||
{
|
{
|
||||||
return x86_linux_i386_xcr0_feature_mask_1 ();
|
return x86_linux_i386_xstate_bv_feature_mask_1 ();
|
||||||
}
|
}
|
||||||
|
|
||||||
/* See arch/x86-linux-tdesc-features.h. */
|
/* See arch/x86-linux-tdesc-features.h. */
|
||||||
|
|
||||||
uint64_t
|
uint64_t
|
||||||
x86_linux_amd64_xcr0_feature_mask ()
|
x86_linux_amd64_xstate_bv_feature_mask ()
|
||||||
{
|
{
|
||||||
return x86_linux_amd64_xcr0_feature_mask_1 ();
|
return x86_linux_amd64_xstate_bv_feature_mask_1 ();
|
||||||
}
|
}
|
||||||
|
|
||||||
/* See arch/x86-linux-tdesc-features.h. */
|
/* See arch/x86-linux-tdesc-features.h. */
|
||||||
|
|
||||||
uint64_t
|
uint64_t
|
||||||
x86_linux_x32_xcr0_feature_mask ()
|
x86_linux_x32_xstate_bv_feature_mask ()
|
||||||
{
|
{
|
||||||
return x86_linux_x32_xcr0_feature_mask_1 ();
|
return x86_linux_x32_xstate_bv_feature_mask_1 ();
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef GDBSERVER
|
#ifdef GDBSERVER
|
||||||
@@ -143,7 +146,7 @@ x86_linux_x32_xcr0_feature_mask ()
|
|||||||
/* See arch/x86-linux-tdesc-features.h. */
|
/* See arch/x86-linux-tdesc-features.h. */
|
||||||
|
|
||||||
int
|
int
|
||||||
x86_linux_xcr0_to_tdesc_idx (uint64_t xcr0)
|
x86_linux_xstate_bv_to_tdesc_idx (uint64_t xstate_bv)
|
||||||
{
|
{
|
||||||
/* The following table shows which features are checked for when creating
|
/* The following table shows which features are checked for when creating
|
||||||
the target descriptions (see nat/x86-linux-tdesc.c), the feature order
|
the target descriptions (see nat/x86-linux-tdesc.c), the feature order
|
||||||
@@ -160,7 +163,7 @@ x86_linux_xcr0_to_tdesc_idx (uint64_t xcr0)
|
|||||||
|
|
||||||
for (int i = 0; i < ARRAY_SIZE (x86_linux_all_xstate_features); ++i)
|
for (int i = 0; i < ARRAY_SIZE (x86_linux_all_xstate_features); ++i)
|
||||||
{
|
{
|
||||||
if ((xcr0 & x86_linux_all_xstate_features[i].feature)
|
if ((xstate_bv & x86_linux_all_xstate_features[i].feature)
|
||||||
== x86_linux_all_xstate_features[i].feature)
|
== x86_linux_all_xstate_features[i].feature)
|
||||||
idx |= (1 << i);
|
idx |= (1 << i);
|
||||||
}
|
}
|
||||||
@@ -250,17 +253,17 @@ x86_linux_i386_tdesc_count ()
|
|||||||
/* See arch/x86-linux-tdesc-features.h. */
|
/* See arch/x86-linux-tdesc-features.h. */
|
||||||
|
|
||||||
uint64_t
|
uint64_t
|
||||||
x86_linux_tdesc_idx_to_xcr0 (int idx)
|
x86_linux_tdesc_idx_to_xstate_bv (int idx)
|
||||||
{
|
{
|
||||||
uint64_t xcr0 = 0;
|
uint64_t xstate_bv = 0;
|
||||||
|
|
||||||
for (int i = 0; i < ARRAY_SIZE (x86_linux_all_xstate_features); ++i)
|
for (int i = 0; i < ARRAY_SIZE (x86_linux_all_xstate_features); ++i)
|
||||||
{
|
{
|
||||||
if ((idx & (1 << i)) != 0)
|
if ((idx & (1 << i)) != 0)
|
||||||
xcr0 |= x86_linux_all_xstate_features[i].feature;
|
xstate_bv |= x86_linux_all_xstate_features[i].feature;
|
||||||
}
|
}
|
||||||
|
|
||||||
return xcr0;
|
return xstate_bv;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* IN_PROCESS_AGENT */
|
#endif /* IN_PROCESS_AGENT */
|
||||||
|
|||||||
@@ -27,17 +27,20 @@
|
|||||||
the set of features which are checked for when creating the target
|
the set of features which are checked for when creating the target
|
||||||
description for each of amd64, x32, and i386. */
|
description for each of amd64, x32, and i386. */
|
||||||
|
|
||||||
extern uint64_t x86_linux_amd64_xcr0_feature_mask ();
|
extern uint64_t x86_linux_amd64_xstate_bv_feature_mask ();
|
||||||
extern uint64_t x86_linux_x32_xcr0_feature_mask ();
|
extern uint64_t x86_linux_x32_xstate_bv_feature_mask ();
|
||||||
extern uint64_t x86_linux_i386_xcr0_feature_mask ();
|
extern uint64_t x86_linux_i386_xstate_bv_feature_mask ();
|
||||||
|
|
||||||
#ifdef GDBSERVER
|
#ifdef GDBSERVER
|
||||||
|
|
||||||
/* Convert an xcr0 value into an integer. The integer will be passed from
|
/* Convert an XSTATE_BV value into an integer. XSTATE_BV has the same
|
||||||
gdbserver to the in-process-agent where it will then be passed through
|
format than the state component bitmap and does include user and
|
||||||
x86_linux_tdesc_idx_to_xcr0 to get back the original xcr0 value. */
|
supervisor state components. The integer will be passed from gdbserver
|
||||||
|
to the in-process-agent where it will then be passed through
|
||||||
|
x86_linux_tdesc_idx_to_xstate_bv to get back the original value. */
|
||||||
|
|
||||||
extern int x86_linux_xcr0_to_tdesc_idx (uint64_t xcr0);
|
|
||||||
|
extern int x86_linux_xstate_bv_to_tdesc_idx (uint64_t xstate_bv);
|
||||||
|
|
||||||
#endif /* GDBSERVER */
|
#endif /* GDBSERVER */
|
||||||
|
|
||||||
@@ -51,11 +54,13 @@ extern int x86_linux_amd64_tdesc_count ();
|
|||||||
extern int x86_linux_x32_tdesc_count ();
|
extern int x86_linux_x32_tdesc_count ();
|
||||||
extern int x86_linux_i386_tdesc_count ();
|
extern int x86_linux_i386_tdesc_count ();
|
||||||
|
|
||||||
/* Convert an index number (as returned from x86_linux_xcr0_to_tdesc_idx)
|
/* Convert an index number (as returned from
|
||||||
into an xcr0 value which can then be used to create a target
|
x86_linux_xstate_bv_to_tdesc_idx) into an xstate_bv value which can
|
||||||
description. */
|
then be used to create a target description.
|
||||||
|
The return mask has the same format than the state component bitmap
|
||||||
|
and does include user and supervisor state components. */
|
||||||
|
|
||||||
extern uint64_t x86_linux_tdesc_idx_to_xcr0 (int idx);
|
extern uint64_t x86_linux_tdesc_idx_to_xstate_bv (int idx);
|
||||||
|
|
||||||
#endif /* IN_PROCESS_AGENT */
|
#endif /* IN_PROCESS_AGENT */
|
||||||
|
|
||||||
|
|||||||
@@ -9097,23 +9097,23 @@ i386_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* Return the target description for a specified XSAVE feature mask. */
|
/* See i386-tdep.h. */
|
||||||
|
|
||||||
const struct target_desc *
|
const struct target_desc *
|
||||||
i386_target_description (uint64_t xcr0, bool segments)
|
i386_target_description (uint64_t xstate_bv, bool segments)
|
||||||
{
|
{
|
||||||
static target_desc *i386_tdescs \
|
static target_desc *i386_tdescs \
|
||||||
[2/*SSE*/][2/*AVX*/][2/*AVX512*/][2/*PKRU*/][2/*segments*/] = {};
|
[2/*SSE*/][2/*AVX*/][2/*AVX512*/][2/*PKRU*/][2/*segments*/] = {};
|
||||||
target_desc **tdesc;
|
target_desc **tdesc;
|
||||||
|
|
||||||
tdesc = &i386_tdescs[(xcr0 & X86_XSTATE_SSE) ? 1 : 0]
|
tdesc = &i386_tdescs[(xstate_bv & X86_XSTATE_SSE) ? 1 : 0]
|
||||||
[(xcr0 & X86_XSTATE_AVX) ? 1 : 0]
|
[(xstate_bv & X86_XSTATE_AVX) ? 1 : 0]
|
||||||
[(xcr0 & X86_XSTATE_AVX512) ? 1 : 0]
|
[(xstate_bv & X86_XSTATE_AVX512) ? 1 : 0]
|
||||||
[(xcr0 & X86_XSTATE_PKRU) ? 1 : 0]
|
[(xstate_bv & X86_XSTATE_PKRU) ? 1 : 0]
|
||||||
[segments ? 1 : 0];
|
[segments ? 1 : 0];
|
||||||
|
|
||||||
if (*tdesc == NULL)
|
if (*tdesc == NULL)
|
||||||
*tdesc = i386_create_target_description (xcr0, false, segments);
|
*tdesc = i386_create_target_description (xstate_bv, false, segments);
|
||||||
|
|
||||||
return *tdesc;
|
return *tdesc;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -454,8 +454,11 @@ extern int i386_svr4_reg_to_regnum (struct gdbarch *gdbarch, int reg);
|
|||||||
|
|
||||||
extern int i386_process_record (struct gdbarch *gdbarch,
|
extern int i386_process_record (struct gdbarch *gdbarch,
|
||||||
struct regcache *regcache, CORE_ADDR addr);
|
struct regcache *regcache, CORE_ADDR addr);
|
||||||
extern const struct target_desc *i386_target_description (uint64_t xcr0,
|
|
||||||
bool segments);
|
/* Return the target description for the specified xsave features as
|
||||||
|
defined in XSTATE_BV and SEGMENTS. */
|
||||||
|
extern const struct target_desc *i386_target_description
|
||||||
|
(uint64_t xstate_bv, bool segments);
|
||||||
|
|
||||||
/* Functions and variables exported from i386-bsd-tdep.c. */
|
/* Functions and variables exported from i386-bsd-tdep.c. */
|
||||||
|
|
||||||
|
|||||||
@@ -43,7 +43,7 @@
|
|||||||
/* See nat/x86-linux-tdesc.h. */
|
/* See nat/x86-linux-tdesc.h. */
|
||||||
|
|
||||||
const target_desc *
|
const target_desc *
|
||||||
x86_linux_tdesc_for_tid (int tid, uint64_t *xcr0_storage,
|
x86_linux_tdesc_for_tid (int tid, uint64_t *xstate_bv_storage,
|
||||||
x86_xsave_layout *xsave_layout_storage)
|
x86_xsave_layout *xsave_layout_storage)
|
||||||
{
|
{
|
||||||
#ifdef __x86_64__
|
#ifdef __x86_64__
|
||||||
@@ -96,30 +96,32 @@ x86_linux_tdesc_for_tid (int tid, uint64_t *xcr0_storage,
|
|||||||
these bits being set we generate a completely empty tdesc for
|
these bits being set we generate a completely empty tdesc for
|
||||||
i386 which will be rejected by GDB. */
|
i386 which will be rejected by GDB. */
|
||||||
have_ptrace_getregset = TRIBOOL_FALSE;
|
have_ptrace_getregset = TRIBOOL_FALSE;
|
||||||
*xcr0_storage = X86_XSTATE_SSE_MASK;
|
*xstate_bv_storage = X86_XSTATE_SSE_MASK;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
have_ptrace_getregset = TRIBOOL_TRUE;
|
have_ptrace_getregset = TRIBOOL_TRUE;
|
||||||
|
|
||||||
/* Get XCR0 from XSAVE extended state. */
|
/* Get XCR0 from XSAVE extended state. */
|
||||||
*xcr0_storage = xstateregs[(I386_LINUX_XSAVE_XCR0_OFFSET
|
uint64_t xcr0 = xstateregs[(I386_LINUX_XSAVE_XCR0_OFFSET
|
||||||
/ sizeof (uint64_t))];
|
/ sizeof (uint64_t))];
|
||||||
|
|
||||||
*xsave_layout_storage
|
*xsave_layout_storage
|
||||||
= x86_fetch_xsave_layout (*xcr0_storage, x86_xsave_length ());
|
= x86_fetch_xsave_layout (xcr0, x86_xsave_length ());
|
||||||
|
|
||||||
|
*xstate_bv_storage = xcr0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Use cached xcr0 value. */
|
/* Use cached XSTATE_BV_STORAGE value. */
|
||||||
uint64_t xcr0_features_bits = *xcr0_storage & X86_XSTATE_ALL_MASK;
|
uint64_t xstate_bv_features_bits = *xstate_bv_storage & X86_XSTATE_ALL_MASK;
|
||||||
|
|
||||||
#ifdef __x86_64__
|
#ifdef __x86_64__
|
||||||
if (is_64bit)
|
if (is_64bit)
|
||||||
return amd64_linux_read_description (xcr0_features_bits, is_x32);
|
return amd64_linux_read_description (xstate_bv_features_bits, is_x32);
|
||||||
else
|
else
|
||||||
#endif
|
#endif
|
||||||
return i386_linux_read_description (xcr0_features_bits);
|
return i386_linux_read_description (xstate_bv_features_bits);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* !IN_PROCESS_AGENT */
|
#endif /* !IN_PROCESS_AGENT */
|
||||||
|
|||||||
@@ -27,9 +27,9 @@ struct x86_xsave_layout;
|
|||||||
|
|
||||||
/* Return the target description for Linux thread TID.
|
/* Return the target description for Linux thread TID.
|
||||||
|
|
||||||
The storage pointed to by XCR0_STORAGE and XSAVE_LAYOUT_STORAGE must
|
The storage pointed to by XSTATE_BV_STORAGE and XSAVE_LAYOUT_STORAGE must
|
||||||
exist until the program (GDB or gdbserver) terminates, this storage is
|
exist until the program (GDB or gdbserver) terminates, this storage is
|
||||||
used to cache the xcr0 and xsave layout values. The values pointed to
|
used to cache the xstate_bv and xsave layout values. The values pointed to
|
||||||
by these arguments are only updated at most once, the first time this
|
by these arguments are only updated at most once, the first time this
|
||||||
function is called if the have_ptrace_getregset global is set to
|
function is called if the have_ptrace_getregset global is set to
|
||||||
TRIBOOL_UNKNOWN.
|
TRIBOOL_UNKNOWN.
|
||||||
@@ -45,6 +45,7 @@ struct x86_xsave_layout;
|
|||||||
returned. */
|
returned. */
|
||||||
|
|
||||||
extern const target_desc *x86_linux_tdesc_for_tid
|
extern const target_desc *x86_linux_tdesc_for_tid
|
||||||
(int tid, uint64_t *xcr0_storage, x86_xsave_layout *xsave_layout_storage);
|
(int tid, uint64_t *xstate_bv_storage,
|
||||||
|
x86_xsave_layout *xsave_layout_storage);
|
||||||
|
|
||||||
#endif /* GDB_NAT_X86_LINUX_TDESC_H */
|
#endif /* GDB_NAT_X86_LINUX_TDESC_H */
|
||||||
|
|||||||
@@ -97,15 +97,20 @@ const struct target_desc *
|
|||||||
x86_linux_nat_target::read_description ()
|
x86_linux_nat_target::read_description ()
|
||||||
{
|
{
|
||||||
/* The x86_linux_tdesc_for_tid call only reads xcr0 the first time it is
|
/* The x86_linux_tdesc_for_tid call only reads xcr0 the first time it is
|
||||||
called, the xcr0 value is stored here and reused on subsequent calls. */
|
called. The mask is stored in XSTATE_BV_STORAGE and reused on
|
||||||
static uint64_t xcr0_storage;
|
subsequent calls. Note that GDB currently supports features for user
|
||||||
|
state components only. However, once supervisor state components are
|
||||||
|
supported in GDB, the value XSTATE_BV_STORAGE will not be configured
|
||||||
|
based on xcr0 only. */
|
||||||
|
static uint64_t xstate_bv_storage;
|
||||||
|
|
||||||
if (inferior_ptid == null_ptid)
|
if (inferior_ptid == null_ptid)
|
||||||
return this->beneath ()->read_description ();
|
return this->beneath ()->read_description ();
|
||||||
|
|
||||||
int tid = inferior_ptid.pid ();
|
int tid = inferior_ptid.pid ();
|
||||||
|
|
||||||
return x86_linux_tdesc_for_tid (tid, &xcr0_storage, &this->m_xsave_layout);
|
return x86_linux_tdesc_for_tid (tid, &xstate_bv_storage,
|
||||||
|
&this->m_xsave_layout);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -21,7 +21,7 @@
|
|||||||
#include "nat/x86-xstate.h"
|
#include "nat/x86-xstate.h"
|
||||||
|
|
||||||
/* Default to SSE. */
|
/* Default to SSE. */
|
||||||
static uint64_t x86_xcr0 = X86_XSTATE_SSE_MASK;
|
static uint64_t x86_xstate_bv = X86_XSTATE_SSE_MASK;
|
||||||
|
|
||||||
static const int num_avx512_k_registers = 8;
|
static const int num_avx512_k_registers = 8;
|
||||||
static const int num_pkeys_registers = 1;
|
static const int num_pkeys_registers = 1;
|
||||||
@@ -265,7 +265,7 @@ i387_cache_to_xsave (struct regcache *regcache, void *buf)
|
|||||||
|
|
||||||
/* The supported bits in `xstat_bv' are 8 bytes. Clear part in
|
/* The supported bits in `xstat_bv' are 8 bytes. Clear part in
|
||||||
vector registers if its bit in xstat_bv is zero. */
|
vector registers if its bit in xstat_bv is zero. */
|
||||||
clear_bv = (~fp->xstate_bv) & x86_xcr0;
|
clear_bv = (~fp->xstate_bv) & x86_xstate_bv;
|
||||||
|
|
||||||
/* Clear part in x87 and vector registers if its bit in xstat_bv is
|
/* Clear part in x87 and vector registers if its bit in xstat_bv is
|
||||||
zero. */
|
zero. */
|
||||||
@@ -315,7 +315,7 @@ i387_cache_to_xsave (struct regcache *regcache, void *buf)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Check if any x87 registers are changed. */
|
/* Check if any x87 registers are changed. */
|
||||||
if ((x86_xcr0 & X86_XSTATE_X87))
|
if ((x86_xstate_bv & X86_XSTATE_X87))
|
||||||
{
|
{
|
||||||
int st0_regnum = find_regno (regcache->tdesc, "st0");
|
int st0_regnum = find_regno (regcache->tdesc, "st0");
|
||||||
|
|
||||||
@@ -332,7 +332,7 @@ i387_cache_to_xsave (struct regcache *regcache, void *buf)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Check if any SSE registers are changed. */
|
/* Check if any SSE registers are changed. */
|
||||||
if ((x86_xcr0 & X86_XSTATE_SSE))
|
if ((x86_xstate_bv & X86_XSTATE_SSE))
|
||||||
{
|
{
|
||||||
int xmm0_regnum = find_regno (regcache->tdesc, "xmm0");
|
int xmm0_regnum = find_regno (regcache->tdesc, "xmm0");
|
||||||
|
|
||||||
@@ -349,7 +349,7 @@ i387_cache_to_xsave (struct regcache *regcache, void *buf)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Check if any AVX registers are changed. */
|
/* Check if any AVX registers are changed. */
|
||||||
if ((x86_xcr0 & X86_XSTATE_AVX))
|
if ((x86_xstate_bv & X86_XSTATE_AVX))
|
||||||
{
|
{
|
||||||
int ymm0h_regnum = find_regno (regcache->tdesc, "ymm0h");
|
int ymm0h_regnum = find_regno (regcache->tdesc, "ymm0h");
|
||||||
|
|
||||||
@@ -366,7 +366,7 @@ i387_cache_to_xsave (struct regcache *regcache, void *buf)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Check if any K registers are changed. */
|
/* Check if any K registers are changed. */
|
||||||
if ((x86_xcr0 & X86_XSTATE_K))
|
if ((x86_xstate_bv & X86_XSTATE_K))
|
||||||
{
|
{
|
||||||
int k0_regnum = find_regno (regcache->tdesc, "k0");
|
int k0_regnum = find_regno (regcache->tdesc, "k0");
|
||||||
|
|
||||||
@@ -383,7 +383,7 @@ i387_cache_to_xsave (struct regcache *regcache, void *buf)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Check if any of ZMM0H-ZMM15H registers are changed. */
|
/* Check if any of ZMM0H-ZMM15H registers are changed. */
|
||||||
if ((x86_xcr0 & X86_XSTATE_ZMM_H))
|
if ((x86_xstate_bv & X86_XSTATE_ZMM_H))
|
||||||
{
|
{
|
||||||
int zmm0h_regnum = find_regno (regcache->tdesc, "zmm0h");
|
int zmm0h_regnum = find_regno (regcache->tdesc, "zmm0h");
|
||||||
|
|
||||||
@@ -400,7 +400,7 @@ i387_cache_to_xsave (struct regcache *regcache, void *buf)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Check if any of ZMM16-ZMM31 registers are changed. */
|
/* Check if any of ZMM16-ZMM31 registers are changed. */
|
||||||
if ((x86_xcr0 & X86_XSTATE_ZMM) && num_zmm_high_registers != 0)
|
if ((x86_xstate_bv & X86_XSTATE_ZMM) && num_zmm_high_registers != 0)
|
||||||
{
|
{
|
||||||
int zmm16h_regnum = find_regno (regcache->tdesc, "zmm16h");
|
int zmm16h_regnum = find_regno (regcache->tdesc, "zmm16h");
|
||||||
int ymm16h_regnum = find_regno (regcache->tdesc, "ymm16h");
|
int ymm16h_regnum = find_regno (regcache->tdesc, "ymm16h");
|
||||||
@@ -437,7 +437,7 @@ i387_cache_to_xsave (struct regcache *regcache, void *buf)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Check if any PKEYS registers are changed. */
|
/* Check if any PKEYS registers are changed. */
|
||||||
if ((x86_xcr0 & X86_XSTATE_PKRU))
|
if ((x86_xstate_bv & X86_XSTATE_PKRU))
|
||||||
{
|
{
|
||||||
int pkru_regnum = find_regno (regcache->tdesc, "pkru");
|
int pkru_regnum = find_regno (regcache->tdesc, "pkru");
|
||||||
|
|
||||||
@@ -453,7 +453,7 @@ i387_cache_to_xsave (struct regcache *regcache, void *buf)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((x86_xcr0 & X86_XSTATE_SSE) || (x86_xcr0 & X86_XSTATE_AVX))
|
if ((x86_xstate_bv & X86_XSTATE_SSE) || (x86_xstate_bv & X86_XSTATE_AVX))
|
||||||
{
|
{
|
||||||
collect_register_by_name (regcache, "mxcsr", raw);
|
collect_register_by_name (regcache, "mxcsr", raw);
|
||||||
if (memcmp (raw, &fp->mxcsr, 4) != 0)
|
if (memcmp (raw, &fp->mxcsr, 4) != 0)
|
||||||
@@ -465,7 +465,7 @@ i387_cache_to_xsave (struct regcache *regcache, void *buf)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (x86_xcr0 & X86_XSTATE_X87)
|
if (x86_xstate_bv & X86_XSTATE_X87)
|
||||||
{
|
{
|
||||||
collect_register_by_name (regcache, "fioff", raw);
|
collect_register_by_name (regcache, "fioff", raw);
|
||||||
if (memcmp (raw, &fp->fioff, 4) != 0)
|
if (memcmp (raw, &fp->fioff, 4) != 0)
|
||||||
@@ -658,10 +658,10 @@ i387_xsave_to_cache (struct regcache *regcache, const void *buf)
|
|||||||
|
|
||||||
/* The supported bits in `xstat_bv' are 8 bytes. Clear part in
|
/* The supported bits in `xstat_bv' are 8 bytes. Clear part in
|
||||||
vector registers if its bit in xstat_bv is zero. */
|
vector registers if its bit in xstat_bv is zero. */
|
||||||
clear_bv = (~fp->xstate_bv) & x86_xcr0;
|
clear_bv = (~fp->xstate_bv) & x86_xstate_bv;
|
||||||
|
|
||||||
/* Check if any x87 registers are changed. */
|
/* Check if any x87 registers are changed. */
|
||||||
if ((x86_xcr0 & X86_XSTATE_X87) != 0)
|
if ((x86_xstate_bv & X86_XSTATE_X87) != 0)
|
||||||
{
|
{
|
||||||
int st0_regnum = find_regno (regcache->tdesc, "st0");
|
int st0_regnum = find_regno (regcache->tdesc, "st0");
|
||||||
|
|
||||||
@@ -678,7 +678,7 @@ i387_xsave_to_cache (struct regcache *regcache, const void *buf)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((x86_xcr0 & X86_XSTATE_SSE) != 0)
|
if ((x86_xstate_bv & X86_XSTATE_SSE) != 0)
|
||||||
{
|
{
|
||||||
int xmm0_regnum = find_regno (regcache->tdesc, "xmm0");
|
int xmm0_regnum = find_regno (regcache->tdesc, "xmm0");
|
||||||
|
|
||||||
@@ -695,7 +695,7 @@ i387_xsave_to_cache (struct regcache *regcache, const void *buf)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((x86_xcr0 & X86_XSTATE_AVX) != 0)
|
if ((x86_xstate_bv & X86_XSTATE_AVX) != 0)
|
||||||
{
|
{
|
||||||
int ymm0h_regnum = find_regno (regcache->tdesc, "ymm0h");
|
int ymm0h_regnum = find_regno (regcache->tdesc, "ymm0h");
|
||||||
|
|
||||||
@@ -712,7 +712,7 @@ i387_xsave_to_cache (struct regcache *regcache, const void *buf)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((x86_xcr0 & X86_XSTATE_K) != 0)
|
if ((x86_xstate_bv & X86_XSTATE_K) != 0)
|
||||||
{
|
{
|
||||||
int k0_regnum = find_regno (regcache->tdesc, "k0");
|
int k0_regnum = find_regno (regcache->tdesc, "k0");
|
||||||
|
|
||||||
@@ -729,7 +729,7 @@ i387_xsave_to_cache (struct regcache *regcache, const void *buf)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((x86_xcr0 & X86_XSTATE_ZMM_H) != 0)
|
if ((x86_xstate_bv & X86_XSTATE_ZMM_H) != 0)
|
||||||
{
|
{
|
||||||
int zmm0h_regnum = find_regno (regcache->tdesc, "zmm0h");
|
int zmm0h_regnum = find_regno (regcache->tdesc, "zmm0h");
|
||||||
|
|
||||||
@@ -746,7 +746,7 @@ i387_xsave_to_cache (struct regcache *regcache, const void *buf)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((x86_xcr0 & X86_XSTATE_ZMM) != 0 && num_zmm_high_registers != 0)
|
if ((x86_xstate_bv & X86_XSTATE_ZMM) != 0 && num_zmm_high_registers != 0)
|
||||||
{
|
{
|
||||||
int zmm16h_regnum = find_regno (regcache->tdesc, "zmm16h");
|
int zmm16h_regnum = find_regno (regcache->tdesc, "zmm16h");
|
||||||
int ymm16h_regnum = find_regno (regcache->tdesc, "ymm16h");
|
int ymm16h_regnum = find_regno (regcache->tdesc, "ymm16h");
|
||||||
@@ -773,7 +773,7 @@ i387_xsave_to_cache (struct regcache *regcache, const void *buf)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((x86_xcr0 & X86_XSTATE_PKRU) != 0)
|
if ((x86_xstate_bv & X86_XSTATE_PKRU) != 0)
|
||||||
{
|
{
|
||||||
int pkru_regnum = find_regno (regcache->tdesc, "pkru");
|
int pkru_regnum = find_regno (regcache->tdesc, "pkru");
|
||||||
|
|
||||||
@@ -858,5 +858,5 @@ i387_xsave_to_cache (struct regcache *regcache, const void *buf)
|
|||||||
std::pair<uint64_t *, x86_xsave_layout *>
|
std::pair<uint64_t *, x86_xsave_layout *>
|
||||||
i387_get_xsave_storage ()
|
i387_get_xsave_storage ()
|
||||||
{
|
{
|
||||||
return { &x86_xcr0, &xsave_layout };
|
return { &x86_xstate_bv, &xsave_layout };
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -82,7 +82,7 @@ get_raw_reg (const unsigned char *raw_regs, int regnum)
|
|||||||
const struct target_desc *
|
const struct target_desc *
|
||||||
get_ipa_tdesc (int idx)
|
get_ipa_tdesc (int idx)
|
||||||
{
|
{
|
||||||
uint64_t xcr0 = x86_linux_tdesc_idx_to_xcr0 (idx);
|
uint64_t xstate_bv = x86_linux_tdesc_idx_to_xstate_bv (idx);
|
||||||
|
|
||||||
#if defined __ILP32__
|
#if defined __ILP32__
|
||||||
bool is_x32 = true;
|
bool is_x32 = true;
|
||||||
@@ -90,7 +90,7 @@ get_ipa_tdesc (int idx)
|
|||||||
bool is_x32 = false;
|
bool is_x32 = false;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
return amd64_linux_read_description (xcr0, is_x32);
|
return amd64_linux_read_description (xstate_bv, is_x32);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Allocate buffer for the jump pads. The branch instruction has a
|
/* Allocate buffer for the jump pads. The branch instruction has a
|
||||||
@@ -159,9 +159,11 @@ initialize_low_tracepoint (void)
|
|||||||
{
|
{
|
||||||
#if defined __ILP32__
|
#if defined __ILP32__
|
||||||
for (int i = 0; i < x86_linux_x32_tdesc_count (); i++)
|
for (int i = 0; i < x86_linux_x32_tdesc_count (); i++)
|
||||||
amd64_linux_read_description (x86_linux_tdesc_idx_to_xcr0 (i), true);
|
amd64_linux_read_description
|
||||||
|
(x86_linux_tdesc_idx_to_xstate_bv (i), true);
|
||||||
#else
|
#else
|
||||||
for (int i = 0; i < x86_linux_amd64_tdesc_count (); i++)
|
for (int i = 0; i < x86_linux_amd64_tdesc_count (); i++)
|
||||||
amd64_linux_read_description (x86_linux_tdesc_idx_to_xcr0 (i), false);
|
amd64_linux_read_description
|
||||||
|
(x86_linux_tdesc_idx_to_xstate_bv (i), false);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -174,9 +174,9 @@ initialize_fast_tracepoint_trampoline_buffer (void)
|
|||||||
const struct target_desc *
|
const struct target_desc *
|
||||||
get_ipa_tdesc (int idx)
|
get_ipa_tdesc (int idx)
|
||||||
{
|
{
|
||||||
uint64_t xcr0 = x86_linux_tdesc_idx_to_xcr0 (idx);
|
uint64_t xstate_bv = x86_linux_tdesc_idx_to_xstate_bv (idx);
|
||||||
|
|
||||||
return i386_linux_read_description (xcr0);
|
return i386_linux_read_description (xstate_bv);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Allocate buffer for the jump pads. On i386, we can reach an arbitrary
|
/* Allocate buffer for the jump pads. On i386, we can reach an arbitrary
|
||||||
@@ -199,5 +199,5 @@ initialize_low_tracepoint (void)
|
|||||||
{
|
{
|
||||||
initialize_fast_tracepoint_trampoline_buffer ();
|
initialize_fast_tracepoint_trampoline_buffer ();
|
||||||
for (int i = 0; i < x86_linux_i386_tdesc_count (); i++)
|
for (int i = 0; i < x86_linux_i386_tdesc_count (); i++)
|
||||||
i386_linux_read_description (x86_linux_tdesc_idx_to_xcr0 (i));
|
i386_linux_read_description (x86_linux_tdesc_idx_to_xstate_bv (i));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -873,7 +873,7 @@ x86_linux_read_description ()
|
|||||||
bool have_ptrace_getregset_was_unknown
|
bool have_ptrace_getregset_was_unknown
|
||||||
= have_ptrace_getregset == TRIBOOL_UNKNOWN;
|
= have_ptrace_getregset == TRIBOOL_UNKNOWN;
|
||||||
|
|
||||||
/* Get pointers to where we should store the xcr0 and xsave_layout
|
/* Get pointers to where we should store the xstate_bv and xsave_layout
|
||||||
values. These will be filled in by x86_linux_tdesc_for_tid the first
|
values. These will be filled in by x86_linux_tdesc_for_tid the first
|
||||||
time that the function is called. Subsequent calls will not modify
|
time that the function is called. Subsequent calls will not modify
|
||||||
the stored values. */
|
the stored values. */
|
||||||
@@ -2892,17 +2892,16 @@ x86_target::get_ipa_tdesc_idx ()
|
|||||||
|| tdesc == tdesc_amd64_linux_no_xml.get ()
|
|| tdesc == tdesc_amd64_linux_no_xml.get ()
|
||||||
#endif /* __x86_64__ */
|
#endif /* __x86_64__ */
|
||||||
);
|
);
|
||||||
return x86_linux_xcr0_to_tdesc_idx (X86_XSTATE_SSE_MASK);
|
return x86_linux_xstate_bv_to_tdesc_idx (X86_XSTATE_SSE_MASK);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* The xcr0 value and xsave layout value are cached when the target
|
/* The xstate_bv value and xsave layout value are cached when the target
|
||||||
description is read. Grab their cache location, and use the cached
|
description is read. Grab their cache location, and use the cached
|
||||||
value to calculate a tdesc index. */
|
value to calculate a tdesc index. */
|
||||||
std::pair<uint64_t *, x86_xsave_layout *> storage
|
std::pair<uint64_t *, x86_xsave_layout *> storage
|
||||||
= i387_get_xsave_storage ();
|
= i387_get_xsave_storage ();
|
||||||
uint64_t xcr0 = *storage.first;
|
|
||||||
|
|
||||||
return x86_linux_xcr0_to_tdesc_idx (xcr0);
|
return x86_linux_xstate_bv_to_tdesc_idx (*storage.first);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* The linux target ops object. */
|
/* The linux target ops object. */
|
||||||
|
|||||||
@@ -83,8 +83,10 @@ constexpr bool operator!= (const x86_xsave_layout &lhs,
|
|||||||
#define X86_XSTATE_AVX_AVX512_PKU_MASK (X86_XSTATE_AVX_MASK\
|
#define X86_XSTATE_AVX_AVX512_PKU_MASK (X86_XSTATE_AVX_MASK\
|
||||||
| X86_XSTATE_AVX512 | X86_XSTATE_PKRU)
|
| X86_XSTATE_AVX512 | X86_XSTATE_PKRU)
|
||||||
|
|
||||||
#define X86_XSTATE_ALL_MASK (X86_XSTATE_AVX_AVX512_PKU_MASK)
|
/* Supported mask of state-component bitmap xstate_bv. The SDM defines
|
||||||
|
xstate_bv as XCR0 | IA32_XSS. */
|
||||||
|
|
||||||
|
#define X86_XSTATE_ALL_MASK (X86_XSTATE_AVX_AVX512_PKU_MASK)
|
||||||
|
|
||||||
#define X86_XSTATE_SSE_SIZE 576
|
#define X86_XSTATE_SSE_SIZE 576
|
||||||
#define X86_XSTATE_AVX_SIZE 832
|
#define X86_XSTATE_AVX_SIZE 832
|
||||||
|
|||||||
Reference in New Issue
Block a user