mirror of
https://github.com/bminor/binutils-gdb.git
synced 2025-11-16 04:24:43 +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:
@@ -21,7 +21,7 @@
|
||||
#include "nat/x86-xstate.h"
|
||||
|
||||
/* 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_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
|
||||
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
|
||||
zero. */
|
||||
@@ -315,7 +315,7 @@ i387_cache_to_xsave (struct regcache *regcache, void *buf)
|
||||
}
|
||||
|
||||
/* 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");
|
||||
|
||||
@@ -332,7 +332,7 @@ i387_cache_to_xsave (struct regcache *regcache, void *buf)
|
||||
}
|
||||
|
||||
/* 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");
|
||||
|
||||
@@ -349,7 +349,7 @@ i387_cache_to_xsave (struct regcache *regcache, void *buf)
|
||||
}
|
||||
|
||||
/* 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");
|
||||
|
||||
@@ -366,7 +366,7 @@ i387_cache_to_xsave (struct regcache *regcache, void *buf)
|
||||
}
|
||||
|
||||
/* 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");
|
||||
|
||||
@@ -383,7 +383,7 @@ i387_cache_to_xsave (struct regcache *regcache, void *buf)
|
||||
}
|
||||
|
||||
/* 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");
|
||||
|
||||
@@ -400,7 +400,7 @@ i387_cache_to_xsave (struct regcache *regcache, void *buf)
|
||||
}
|
||||
|
||||
/* 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 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. */
|
||||
if ((x86_xcr0 & X86_XSTATE_PKRU))
|
||||
if ((x86_xstate_bv & X86_XSTATE_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);
|
||||
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);
|
||||
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
|
||||
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. */
|
||||
if ((x86_xcr0 & X86_XSTATE_X87) != 0)
|
||||
if ((x86_xstate_bv & X86_XSTATE_X87) != 0)
|
||||
{
|
||||
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");
|
||||
|
||||
@@ -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");
|
||||
|
||||
@@ -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");
|
||||
|
||||
@@ -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");
|
||||
|
||||
@@ -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 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");
|
||||
|
||||
@@ -858,5 +858,5 @@ i387_xsave_to_cache (struct regcache *regcache, const void *buf)
|
||||
std::pair<uint64_t *, x86_xsave_layout *>
|
||||
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 *
|
||||
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__
|
||||
bool is_x32 = true;
|
||||
@@ -90,7 +90,7 @@ get_ipa_tdesc (int idx)
|
||||
bool is_x32 = false;
|
||||
#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
|
||||
@@ -159,9 +159,11 @@ initialize_low_tracepoint (void)
|
||||
{
|
||||
#if defined __ILP32__
|
||||
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
|
||||
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
|
||||
}
|
||||
|
||||
@@ -174,9 +174,9 @@ initialize_fast_tracepoint_trampoline_buffer (void)
|
||||
const struct target_desc *
|
||||
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
|
||||
@@ -199,5 +199,5 @@ initialize_low_tracepoint (void)
|
||||
{
|
||||
initialize_fast_tracepoint_trampoline_buffer ();
|
||||
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
|
||||
= 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
|
||||
time that the function is called. Subsequent calls will not modify
|
||||
the stored values. */
|
||||
@@ -2892,17 +2892,16 @@ x86_target::get_ipa_tdesc_idx ()
|
||||
|| tdesc == tdesc_amd64_linux_no_xml.get ()
|
||||
#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
|
||||
value to calculate a tdesc index. */
|
||||
std::pair<uint64_t *, x86_xsave_layout *> 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. */
|
||||
|
||||
Reference in New Issue
Block a user