Backport patches for x86 XSTATE update in gdb and gdbserver.
Resolves: RHEL-10464
This commit is contained in:
parent
250ae50eab
commit
bd876a4f72
@ -521,3 +521,92 @@ Patch125: gdb-rhel-17399-sect_index_data-not-initialized.patch
|
||||
# (Andreas Arnez, RHEL-10550)
|
||||
Patch126: gdb-rhel-10550-add-arch14-record.patch
|
||||
|
||||
# Backport "x86: Add an x86_xsave_layout structure to
|
||||
# handle variable XSAVE layouts."
|
||||
# (John Baldwin, RHEL-10464)
|
||||
Patch127: gdb-rhel-10464-xsave-update-1of21.patch
|
||||
|
||||
# Backport "gdb: Store an x86_xsave_layout in i386_gdbarch_tdep."
|
||||
# (John Baldwin, RHEL-10464)
|
||||
Patch128: gdb-rhel-10464-xsave-update-2of21.patch
|
||||
|
||||
# Backport "core: Support fetching x86 XSAVE layout from architectures."
|
||||
# (John Baldwin, RHEL-10464)
|
||||
Patch129: gdb-rhel-10464-xsave-update-3of21.patch
|
||||
|
||||
# Backport "nat/x86--cpuid.h: Add x86_cpuid_count wrapper around
|
||||
# __get_cpuid_count."
|
||||
# (John Baldwin, RHEL-10464)
|
||||
Patch130: gdb-rhel-10464-xsave-update-4of21.patch
|
||||
|
||||
# Backport "x86 nat: Add helper functions to save the XSAVE layout for
|
||||
# the host."
|
||||
# (John Baldwin, RHEL-10464)
|
||||
Patch131: gdb-rhel-10464-xsave-update-5of21.patch
|
||||
|
||||
# Backport "gdb: Update x86 Linux architectures to support XSAVE layouts."
|
||||
# (John Baldwin, RHEL-10464)
|
||||
Patch132: gdb-rhel-10464-xsave-update-6of21.patch
|
||||
|
||||
# Backport "gdb: Support XSAVE layouts for the current host in the Linux
|
||||
# x86 targets."
|
||||
# (John Baldwin, RHEL-10464)
|
||||
Patch133: gdb-rhel-10464-xsave-update-7of21.patch
|
||||
|
||||
# Backport "gdb: Use x86_xstate_layout to parse the XSAVE extended state area."
|
||||
# (John Baldwin, RHEL-10464)
|
||||
Patch134: gdb-rhel-10464-xsave-update-8of21.patch
|
||||
|
||||
# Backport "gdbserver: Add a function to set the XSAVE mask and size."
|
||||
# (John Baldwin, RHEL-10464)
|
||||
Patch135: gdb-rhel-10464-xsave-update-9of21.patch
|
||||
|
||||
# Backport "x86: Remove X86_XSTATE_SIZE and related constants."
|
||||
# (John Baldwin, RHEL-10464)
|
||||
Patch136: gdb-rhel-10464-xsave-update-10of21.patch
|
||||
|
||||
# Backport "[gdb/tdep] Fix avx512 -m32 support in gdbserver"
|
||||
# (Tom de Vries, RHEL-10464)
|
||||
Patch137: gdb-rhel-10464-xsave-update-11of21.patch
|
||||
|
||||
# Backport "gdbserver: Use x86_xstate_layout to parse the XSAVE extended
|
||||
# state area."
|
||||
# (Aleksandar Paunovic, RHEL-10464)
|
||||
Patch138: gdb-rhel-10464-xsave-update-12of21.patch
|
||||
|
||||
# Backport "gdbserver: Simplify handling of ZMM registers."
|
||||
# (John Baldwin, RHEL-10464)
|
||||
Patch139: gdb-rhel-10464-xsave-update-13of21.patch
|
||||
|
||||
# Backport "gdbserver: Refactor the legacy region within the xsave struct"
|
||||
# (Aleksandar Paunovic, RHEL-10464)
|
||||
Patch140: gdb-rhel-10464-xsave-update-14of21.patch
|
||||
|
||||
# Backport "gdbserver: Fix style of struct declarations in i387-fp.cc"
|
||||
# (John Baldwin, RHEL-10464)
|
||||
Patch141: gdb-rhel-10464-xsave-update-15of21.patch
|
||||
|
||||
# Backport "nat/x86-cpuid.h: Remove non-x86 fallbacks"
|
||||
# (John Baldwin, RHEL-10464)
|
||||
Patch142: gdb-rhel-10464-xsave-update-16of21.patch
|
||||
|
||||
# Backport "i386: Use a fallback XSAVE layout for remote targets"
|
||||
# (John Baldwin, RHEL-10464)
|
||||
Patch143: gdb-rhel-10464-xsave-update-17of21.patch
|
||||
|
||||
# Backport "gdbserver: i387_cache_to_xsave: fix copy dest of zmm registers"
|
||||
# (Simon Marchi, RHEL-10464)
|
||||
Patch144: gdb-rhel-10464-xsave-update-18of21.patch
|
||||
|
||||
# Backport "bfd/binutils: support for gdb target descriptions in the core file"
|
||||
# (Andrew Burgess, RHEL-10464)
|
||||
Patch145: gdb-rhel-10464-xsave-update-19of21.patch
|
||||
|
||||
# Backport "gdb: write target description into core file"
|
||||
# (Andrew Burgess, RHEL-10464)
|
||||
Patch146: gdb-rhel-10464-xsave-update-20of21.patch
|
||||
|
||||
# Backport "gdb/corefile: write NT_GDB_TDESC based on signalled thread"
|
||||
# (Andrew Burgess, RHEL-10464)
|
||||
Patch147: gdb-rhel-10464-xsave-update-21of21.patch
|
||||
|
||||
|
@ -124,3 +124,24 @@
|
||||
%patch124 -p1
|
||||
%patch125 -p1
|
||||
%patch126 -p1
|
||||
%patch127 -p1
|
||||
%patch128 -p1
|
||||
%patch129 -p1
|
||||
%patch130 -p1
|
||||
%patch131 -p1
|
||||
%patch132 -p1
|
||||
%patch133 -p1
|
||||
%patch134 -p1
|
||||
%patch135 -p1
|
||||
%patch136 -p1
|
||||
%patch137 -p1
|
||||
%patch138 -p1
|
||||
%patch139 -p1
|
||||
%patch140 -p1
|
||||
%patch141 -p1
|
||||
%patch142 -p1
|
||||
%patch143 -p1
|
||||
%patch144 -p1
|
||||
%patch145 -p1
|
||||
%patch146 -p1
|
||||
%patch147 -p1
|
||||
|
21
_patch_order
21
_patch_order
@ -124,3 +124,24 @@ gdb-find_and_open_source-empty-string-ub-3of4.patch
|
||||
gdb-find_and_open_source-empty-string-ub-4of4.patch
|
||||
gdb-rhel-17399-sect_index_data-not-initialized.patch
|
||||
gdb-rhel-10550-add-arch14-record.patch
|
||||
gdb-rhel-10464-xsave-update-1of21.patch
|
||||
gdb-rhel-10464-xsave-update-2of21.patch
|
||||
gdb-rhel-10464-xsave-update-3of21.patch
|
||||
gdb-rhel-10464-xsave-update-4of21.patch
|
||||
gdb-rhel-10464-xsave-update-5of21.patch
|
||||
gdb-rhel-10464-xsave-update-6of21.patch
|
||||
gdb-rhel-10464-xsave-update-7of21.patch
|
||||
gdb-rhel-10464-xsave-update-8of21.patch
|
||||
gdb-rhel-10464-xsave-update-9of21.patch
|
||||
gdb-rhel-10464-xsave-update-10of21.patch
|
||||
gdb-rhel-10464-xsave-update-11of21.patch
|
||||
gdb-rhel-10464-xsave-update-12of21.patch
|
||||
gdb-rhel-10464-xsave-update-13of21.patch
|
||||
gdb-rhel-10464-xsave-update-14of21.patch
|
||||
gdb-rhel-10464-xsave-update-15of21.patch
|
||||
gdb-rhel-10464-xsave-update-16of21.patch
|
||||
gdb-rhel-10464-xsave-update-17of21.patch
|
||||
gdb-rhel-10464-xsave-update-18of21.patch
|
||||
gdb-rhel-10464-xsave-update-19of21.patch
|
||||
gdb-rhel-10464-xsave-update-20of21.patch
|
||||
gdb-rhel-10464-xsave-update-21of21.patch
|
||||
|
39
gdb-rhel-10464-xsave-update-10of21.patch
Normal file
39
gdb-rhel-10464-xsave-update-10of21.patch
Normal file
@ -0,0 +1,39 @@
|
||||
From FEDORA_PATCHES Mon Sep 17 00:00:00 2001
|
||||
From: John Baldwin <jhb@FreeBSD.org>
|
||||
Date: Thu, 11 Apr 2024 14:05:44 -0700
|
||||
Subject: gdb-rhel-10464-xsave-update-10of21.patch
|
||||
|
||||
;; Backport "x86: Remove X86_XSTATE_SIZE and related constants."
|
||||
;; (John Baldwin, RHEL-10464)
|
||||
|
||||
Approved-By: Simon Marchi <simon.marchi@efficios.com>
|
||||
|
||||
diff --git a/gdbsupport/x86-xstate.h b/gdbsupport/x86-xstate.h
|
||||
--- a/gdbsupport/x86-xstate.h
|
||||
+++ b/gdbsupport/x86-xstate.h
|
||||
@@ -99,11 +99,6 @@ constexpr bool operator!= (const x86_xsave_layout &lhs,
|
||||
|
||||
#define X86_XSTATE_SSE_SIZE 576
|
||||
#define X86_XSTATE_AVX_SIZE 832
|
||||
-#define X86_XSTATE_BNDREGS_SIZE 1024
|
||||
-#define X86_XSTATE_BNDCFG_SIZE 1088
|
||||
-#define X86_XSTATE_AVX512_SIZE 2688
|
||||
-#define X86_XSTATE_PKRU_SIZE 2696
|
||||
-#define X86_XSTATE_MAX_SIZE 2696
|
||||
|
||||
|
||||
/* In case one of the MPX XCR0 bits is set we consider we have MPX. */
|
||||
@@ -112,13 +107,6 @@ constexpr bool operator!= (const x86_xsave_layout &lhs,
|
||||
#define HAS_AVX512(XCR0) (((XCR0) & X86_XSTATE_AVX512) != 0)
|
||||
#define HAS_PKRU(XCR0) (((XCR0) & X86_XSTATE_PKRU) != 0)
|
||||
|
||||
-/* Get I386 XSAVE extended state size. */
|
||||
-#define X86_XSTATE_SIZE(XCR0) \
|
||||
- (HAS_PKRU (XCR0) ? X86_XSTATE_PKRU_SIZE : \
|
||||
- (HAS_AVX512 (XCR0) ? X86_XSTATE_AVX512_SIZE : \
|
||||
- (HAS_MPX (XCR0) ? X86_XSTATE_BNDCFG_SIZE : \
|
||||
- (HAS_AVX (XCR0) ? X86_XSTATE_AVX_SIZE : X86_XSTATE_SSE_SIZE))))
|
||||
-
|
||||
/* Initial value for fctrl register, as defined in the X86 manual, and
|
||||
confirmed in the (Linux) kernel source. When the x87 floating point
|
||||
feature is not enabled in an inferior we use this as the value of the
|
170
gdb-rhel-10464-xsave-update-11of21.patch
Normal file
170
gdb-rhel-10464-xsave-update-11of21.patch
Normal file
@ -0,0 +1,170 @@
|
||||
From FEDORA_PATCHES Mon Sep 17 00:00:00 2001
|
||||
From: Tom de Vries <tdevries@suse.de>
|
||||
Date: Thu, 11 Apr 2024 14:05:44 -0700
|
||||
Subject: gdb-rhel-10464-xsave-update-11of21.patch
|
||||
|
||||
;; Backport "[gdb/tdep] Fix avx512 -m32 support in gdbserver"
|
||||
;; (Tom de Vries, RHEL-10464)
|
||||
|
||||
PR27257 reports a problem that can be reproduced as follows:
|
||||
- use x86_64 machine with avx512 support
|
||||
- compile a hello world with -m32 to a.out
|
||||
- start a gdbserver session with a.out
|
||||
- use gdb to connect to the gdbserver session
|
||||
|
||||
This makes us run into:
|
||||
...
|
||||
Listening on port 2346
|
||||
Remote debugging from host ::1, port 34940
|
||||
src/gdbserver/regcache.cc:257: \
|
||||
A problem internal to GDBserver has been detected.
|
||||
Unknown register zmm16h requested
|
||||
...
|
||||
|
||||
The problem is that i387_xsave_to_cache in gdbserver/i387-fp.cc can't find a
|
||||
register zmm16h in the register cache.
|
||||
|
||||
To understand how this happens, first some background.
|
||||
|
||||
SSE has 16 128-bit wide xmm registers.
|
||||
|
||||
AVX extends the SSE registers set as follows:
|
||||
- it extends the 16 existing 128-bit wide xmm registers to 256-bit wide ymm
|
||||
registers.
|
||||
|
||||
AVX512 extends the AVX register set as follows:
|
||||
- it extends the 16 existing 256-bit wide ymm registers to 512-bit wide zmm
|
||||
registers.
|
||||
- it adds 16 additional 512-bit wide zmm registers (with corresponding ymm and
|
||||
xmm subregisters added as well)
|
||||
|
||||
However, in 32-bit mode, there are only 8 xmm/ymm/zmm registers.
|
||||
|
||||
The problem we're running into is that gdbserver/i387-fp.cc uses these
|
||||
constants to describe the size of the register file:
|
||||
...
|
||||
static const int num_avx512_zmmh_low_registers = 16;
|
||||
static const int num_avx512_zmmh_high_registers = 16;
|
||||
static const int num_avx512_ymmh_registers = 16;
|
||||
static const int num_avx512_xmm_registers = 16;
|
||||
...
|
||||
which are all incorrect for the 32-bit case.
|
||||
|
||||
Fix this by replacing the constants with variables that have the appropriate
|
||||
values in 64-bit and 32-bit mode.
|
||||
|
||||
Tested on x86_64-linux with native and unix/-m32.
|
||||
|
||||
diff --git a/gdbserver/i387-fp.cc b/gdbserver/i387-fp.cc
|
||||
--- a/gdbserver/i387-fp.cc
|
||||
+++ b/gdbserver/i387-fp.cc
|
||||
@@ -27,10 +27,6 @@ static unsigned long long x86_xcr0 = X86_XSTATE_SSE_MASK;
|
||||
static const int num_mpx_bnd_registers = 4;
|
||||
static const int num_mpx_cfg_registers = 2;
|
||||
static const int num_avx512_k_registers = 8;
|
||||
-static const int num_avx512_zmmh_low_registers = 16;
|
||||
-static const int num_avx512_zmmh_high_registers = 16;
|
||||
-static const int num_avx512_ymmh_registers = 16;
|
||||
-static const int num_avx512_xmm_registers = 16;
|
||||
static const int num_pkeys_registers = 1;
|
||||
|
||||
static x86_xsave_layout xsave_layout;
|
||||
@@ -262,14 +258,22 @@ void
|
||||
i387_cache_to_xsave (struct regcache *regcache, void *buf)
|
||||
{
|
||||
struct i387_xsave *fp = (struct i387_xsave *) buf;
|
||||
+ bool amd64 = register_size (regcache->tdesc, 0) == 8;
|
||||
int i;
|
||||
unsigned long val, val2;
|
||||
unsigned long long xstate_bv = 0;
|
||||
unsigned long long clear_bv = 0;
|
||||
char raw[64];
|
||||
char *p;
|
||||
+
|
||||
/* Amd64 has 16 xmm regs; I386 has 8 xmm regs. */
|
||||
- int num_xmm_registers = register_size (regcache->tdesc, 0) == 8 ? 16 : 8;
|
||||
+ int num_xmm_registers = amd64 ? 16 : 8;
|
||||
+ /* AVX512 extends the existing xmm/ymm registers to a wider mode: zmm. */
|
||||
+ int num_avx512_zmmh_low_registers = num_xmm_registers;
|
||||
+ /* AVX512 adds 16 extra regs in Amd64 mode, but none in I386 mode.*/
|
||||
+ int num_avx512_zmmh_high_registers = amd64 ? 16 : 0;
|
||||
+ int num_avx512_ymmh_registers = amd64 ? 16 : 0;
|
||||
+ int num_avx512_xmm_registers = amd64 ? 16 : 0;
|
||||
|
||||
/* The supported bits in `xstat_bv' are 8 bytes. Clear part in
|
||||
vector registers if its bit in xstat_bv is zero. */
|
||||
@@ -458,7 +462,9 @@ i387_cache_to_xsave (struct regcache *regcache, void *buf)
|
||||
/* Check if any of ZMM16H-ZMM31H registers are changed. */
|
||||
if ((x86_xcr0 & X86_XSTATE_ZMM))
|
||||
{
|
||||
- int zmm16h_regnum = find_regno (regcache->tdesc, "zmm16h");
|
||||
+ int zmm16h_regnum = (num_avx512_zmmh_high_registers == 0
|
||||
+ ? -1
|
||||
+ : find_regno (regcache->tdesc, "zmm16h"));
|
||||
|
||||
for (i = 0; i < num_avx512_zmmh_high_registers; i++)
|
||||
{
|
||||
@@ -475,7 +481,9 @@ i387_cache_to_xsave (struct regcache *regcache, void *buf)
|
||||
/* Check if any XMM_AVX512 registers are changed. */
|
||||
if ((x86_xcr0 & X86_XSTATE_ZMM))
|
||||
{
|
||||
- int xmm_avx512_regnum = find_regno (regcache->tdesc, "xmm16");
|
||||
+ int xmm_avx512_regnum = (num_avx512_xmm_registers == 0
|
||||
+ ? -1
|
||||
+ : find_regno (regcache->tdesc, "xmm16"));
|
||||
|
||||
for (i = 0; i < num_avx512_xmm_registers; i++)
|
||||
{
|
||||
@@ -492,7 +500,9 @@ i387_cache_to_xsave (struct regcache *regcache, void *buf)
|
||||
/* Check if any YMMH_AVX512 registers are changed. */
|
||||
if ((x86_xcr0 & X86_XSTATE_ZMM))
|
||||
{
|
||||
- int ymmh_avx512_regnum = find_regno (regcache->tdesc, "ymm16h");
|
||||
+ int ymmh_avx512_regnum = (num_avx512_ymmh_registers == 0
|
||||
+ ? -1
|
||||
+ : find_regno (regcache->tdesc, "ymm16h"));
|
||||
|
||||
for (i = 0; i < num_avx512_ymmh_registers; i++)
|
||||
{
|
||||
@@ -716,12 +726,20 @@ i387_xsave_to_cache (struct regcache *regcache, const void *buf)
|
||||
{
|
||||
struct i387_xsave *fp = (struct i387_xsave *) buf;
|
||||
struct i387_fxsave *fxp = (struct i387_fxsave *) buf;
|
||||
+ bool amd64 = register_size (regcache->tdesc, 0) == 8;
|
||||
int i, top;
|
||||
unsigned long val;
|
||||
unsigned long long clear_bv;
|
||||
gdb_byte *p;
|
||||
- /* Amd64 has 16 xmm regs; I386 has 8 xmm regs. */
|
||||
- int num_xmm_registers = register_size (regcache->tdesc, 0) == 8 ? 16 : 8;
|
||||
+
|
||||
+ /* Amd64 has 16 xmm regs; I386 has 8 xmm regs. */
|
||||
+ int num_xmm_registers = amd64 ? 16 : 8;
|
||||
+ /* AVX512 extends the existing xmm/ymm registers to a wider mode: zmm. */
|
||||
+ int num_avx512_zmmh_low_registers = num_xmm_registers;
|
||||
+ /* AVX512 adds 16 extra regs in Amd64 mode, but none in I386 mode.*/
|
||||
+ int num_avx512_zmmh_high_registers = amd64 ? 16 : 0;
|
||||
+ int num_avx512_ymmh_registers = amd64 ? 16 : 0;
|
||||
+ int num_avx512_xmm_registers = amd64 ? 16 : 0;
|
||||
|
||||
/* The supported bits in `xstat_bv' are 8 bytes. Clear part in
|
||||
vector registers if its bit in xstat_bv is zero. */
|
||||
@@ -851,9 +869,15 @@ i387_xsave_to_cache (struct regcache *regcache, const void *buf)
|
||||
|
||||
if ((x86_xcr0 & X86_XSTATE_ZMM) != 0)
|
||||
{
|
||||
- int zmm16h_regnum = find_regno (regcache->tdesc, "zmm16h");
|
||||
- int ymm16h_regnum = find_regno (regcache->tdesc, "ymm16h");
|
||||
- int xmm16_regnum = find_regno (regcache->tdesc, "xmm16");
|
||||
+ int zmm16h_regnum = (num_avx512_zmmh_high_registers == 0
|
||||
+ ? -1
|
||||
+ : find_regno (regcache->tdesc, "zmm16h"));
|
||||
+ int ymm16h_regnum = (num_avx512_ymmh_registers == 0
|
||||
+ ? -1
|
||||
+ : find_regno (regcache->tdesc, "ymm16h"));
|
||||
+ int xmm16_regnum = (num_avx512_xmm_registers == 0
|
||||
+ ? -1
|
||||
+ : find_regno (regcache->tdesc, "xmm16"));
|
||||
|
||||
if ((clear_bv & X86_XSTATE_ZMM) != 0)
|
||||
{
|
341
gdb-rhel-10464-xsave-update-12of21.patch
Normal file
341
gdb-rhel-10464-xsave-update-12of21.patch
Normal file
@ -0,0 +1,341 @@
|
||||
From FEDORA_PATCHES Mon Sep 17 00:00:00 2001
|
||||
From: Aleksandar Paunovic <aleksandar.paunovic@intel.com>
|
||||
Date: Thu, 11 Apr 2024 14:05:45 -0700
|
||||
Subject: gdb-rhel-10464-xsave-update-12of21.patch
|
||||
|
||||
;; Backport "gdbserver: Use x86_xstate_layout to parse the XSAVE extended
|
||||
;; state area."
|
||||
;; (Aleksandar Paunovic, RHEL-10464)
|
||||
|
||||
Replace the extended state area fields of i387_xsave with methods which
|
||||
return an offset into the XSAVE buffer.
|
||||
|
||||
The two changed functions are called within all tests which runs
|
||||
gdbserver.
|
||||
|
||||
Signed-off-by: Aleksandar Paunovic <aleksandar.paunovic@intel.com>
|
||||
Co-authored-by: John Baldwin <jhb@FreeBSD.org>
|
||||
Approved-By: Simon Marchi <simon.marchi@efficios.com>
|
||||
|
||||
diff --git a/gdbserver/i387-fp.cc b/gdbserver/i387-fp.cc
|
||||
--- a/gdbserver/i387-fp.cc
|
||||
+++ b/gdbserver/i387-fp.cc
|
||||
@@ -81,6 +81,8 @@ struct i387_fxsave {
|
||||
unsigned char xmm_space[256];
|
||||
};
|
||||
|
||||
+gdb_static_assert (sizeof(i387_fxsave) == 416);
|
||||
+
|
||||
struct i387_xsave {
|
||||
/* All these are only sixteen bits, plus padding, except for fop (which
|
||||
is only eleven bits), and fooff / fioff (which are 32 bits each). */
|
||||
@@ -115,36 +117,57 @@ struct i387_xsave {
|
||||
/* The XSTATE_BV bit vector. */
|
||||
unsigned long long xstate_bv;
|
||||
|
||||
- unsigned char reserved3[56];
|
||||
-
|
||||
- /* Space for eight upper 128-bit YMM values, or 16 on x86-64. */
|
||||
- unsigned char ymmh_space[256];
|
||||
+ /* The XCOMP_BV bit vector. */
|
||||
+ unsigned long long xcomp_bv;
|
||||
|
||||
- unsigned char reserved4[128];
|
||||
+ unsigned char reserved3[48];
|
||||
|
||||
- /* Space for 4 bound registers values of 128 bits. */
|
||||
- unsigned char mpx_bnd_space[64];
|
||||
-
|
||||
- /* Space for 2 MPX configuration registers of 64 bits
|
||||
- plus reserved space. */
|
||||
- unsigned char mpx_cfg_space[16];
|
||||
+ /* Byte 576. End of registers with fixed position in XSAVE.
|
||||
+ The position of other XSAVE registers will be calculated
|
||||
+ from the appropriate CPUID calls. */
|
||||
|
||||
- unsigned char reserved5[48];
|
||||
+private:
|
||||
+ /* Base address of XSAVE data as an unsigned char *. Used to derive
|
||||
+ pointers to XSAVE state components in the extended state
|
||||
+ area. */
|
||||
+ unsigned char *xsave ()
|
||||
+ { return reinterpret_cast<unsigned char *> (this); }
|
||||
|
||||
- /* Space for 8 OpMask register values of 64 bits. */
|
||||
- unsigned char k_space[64];
|
||||
+public:
|
||||
+ /* Memory address of eight upper 128-bit YMM values, or 16 on x86-64. */
|
||||
+ unsigned char *ymmh_space ()
|
||||
+ { return xsave () + xsave_layout.avx_offset; }
|
||||
|
||||
- /* Space for 16 256-bit zmm0-15. */
|
||||
- unsigned char zmmh_low_space[512];
|
||||
+ /* Memory address of 4 bound registers values of 128 bits. */
|
||||
+ unsigned char *bndregs_space ()
|
||||
+ { return xsave () + xsave_layout.bndregs_offset; }
|
||||
|
||||
- /* Space for 16 512-bit zmm16-31 values. */
|
||||
- unsigned char zmmh_high_space[1024];
|
||||
-
|
||||
- /* Space for 1 32-bit PKRU register. The HW XSTATE size for this feature is
|
||||
- actually 64 bits, but WRPKRU/RDPKRU instructions ignore upper 32 bits. */
|
||||
- unsigned char pkru_space[8];
|
||||
+ /* Memory address of 2 MPX configuration registers of 64 bits
|
||||
+ plus reserved space. */
|
||||
+ unsigned char *bndcfg_space ()
|
||||
+ { return xsave () + xsave_layout.bndcfg_offset; }
|
||||
+
|
||||
+ /* Memory address of 8 OpMask register values of 64 bits. */
|
||||
+ unsigned char *k_space ()
|
||||
+ { return xsave () + xsave_layout.k_offset; }
|
||||
+
|
||||
+ /* Memory address of 16 256-bit zmm0-15. */
|
||||
+ unsigned char *zmmh_space ()
|
||||
+ { return xsave () + xsave_layout.zmm_h_offset; }
|
||||
+
|
||||
+ /* Memory address of 16 512-bit zmm16-31 values. */
|
||||
+ unsigned char *zmm16_space ()
|
||||
+ { return xsave () + xsave_layout.zmm_offset; }
|
||||
+
|
||||
+ /* Memory address of 1 32-bit PKRU register. The HW XSTATE size for this
|
||||
+ feature is actually 64 bits, but WRPKRU/RDPKRU instructions ignore upper
|
||||
+ 32 bits. */
|
||||
+ unsigned char *pkru_space ()
|
||||
+ { return xsave () + xsave_layout.pkru_offset; }
|
||||
};
|
||||
|
||||
+gdb_static_assert (sizeof(i387_xsave) == 576);
|
||||
+
|
||||
void
|
||||
i387_cache_to_fsave (struct regcache *regcache, void *buf)
|
||||
{
|
||||
@@ -264,7 +287,7 @@ i387_cache_to_xsave (struct regcache *regcache, void *buf)
|
||||
unsigned long long xstate_bv = 0;
|
||||
unsigned long long clear_bv = 0;
|
||||
char raw[64];
|
||||
- char *p;
|
||||
+ unsigned char *p;
|
||||
|
||||
/* Amd64 has 16 xmm regs; I386 has 8 xmm regs. */
|
||||
int num_xmm_registers = amd64 ? 16 : 8;
|
||||
@@ -304,40 +327,40 @@ i387_cache_to_xsave (struct regcache *regcache, void *buf)
|
||||
|
||||
if ((clear_bv & X86_XSTATE_AVX))
|
||||
for (i = 0; i < num_xmm_registers; i++)
|
||||
- memset (((char *) &fp->ymmh_space[0]) + i * 16, 0, 16);
|
||||
+ memset (fp->ymmh_space () + i * 16, 0, 16);
|
||||
|
||||
if ((clear_bv & X86_XSTATE_SSE) && (clear_bv & X86_XSTATE_AVX))
|
||||
memset (((char *) &fp->mxcsr), 0, 4);
|
||||
|
||||
if ((clear_bv & X86_XSTATE_BNDREGS))
|
||||
for (i = 0; i < num_mpx_bnd_registers; i++)
|
||||
- memset (((char *) &fp->mpx_bnd_space[0]) + i * 16, 0, 16);
|
||||
+ memset (fp->bndregs_space () + i * 16, 0, 16);
|
||||
|
||||
if ((clear_bv & X86_XSTATE_BNDCFG))
|
||||
for (i = 0; i < num_mpx_cfg_registers; i++)
|
||||
- memset (((char *) &fp->mpx_cfg_space[0]) + i * 8, 0, 8);
|
||||
+ memset (fp->bndcfg_space () + i * 8, 0, 8);
|
||||
|
||||
if ((clear_bv & X86_XSTATE_K))
|
||||
for (i = 0; i < num_avx512_k_registers; i++)
|
||||
- memset (((char *) &fp->k_space[0]) + i * 8, 0, 8);
|
||||
+ memset (fp->k_space () + i * 8, 0, 8);
|
||||
|
||||
if ((clear_bv & X86_XSTATE_ZMM_H))
|
||||
for (i = 0; i < num_avx512_zmmh_low_registers; i++)
|
||||
- memset (((char *) &fp->zmmh_low_space[0]) + i * 32, 0, 32);
|
||||
+ memset (fp->zmmh_space () + i * 32, 0, 32);
|
||||
|
||||
if ((clear_bv & X86_XSTATE_ZMM))
|
||||
{
|
||||
for (i = 0; i < num_avx512_zmmh_high_registers; i++)
|
||||
- memset (((char *) &fp->zmmh_low_space[0]) + 32 + i * 64, 0, 32);
|
||||
+ memset (fp->zmm16_space () + 32 + i * 64, 0, 32);
|
||||
for (i = 0; i < num_avx512_xmm_registers; i++)
|
||||
- memset (((char *) &fp->zmmh_high_space[0]) + i * 64, 0, 16);
|
||||
+ memset (fp->zmm16_space () + i * 64, 0, 16);
|
||||
for (i = 0; i < num_avx512_ymmh_registers; i++)
|
||||
- memset (((char *) &fp->zmmh_high_space[0]) + 16 + i * 64, 0, 16);
|
||||
+ memset (fp->zmm16_space () + 16 + i * 64, 0, 16);
|
||||
}
|
||||
|
||||
if ((clear_bv & X86_XSTATE_PKRU))
|
||||
for (i = 0; i < num_pkeys_registers; i++)
|
||||
- memset (((char *) &fp->pkru_space[0]) + i * 4, 0, 4);
|
||||
+ memset (fp->pkru_space () + i * 4, 0, 4);
|
||||
}
|
||||
|
||||
/* Check if any x87 registers are changed. */
|
||||
@@ -348,7 +371,7 @@ i387_cache_to_xsave (struct regcache *regcache, void *buf)
|
||||
for (i = 0; i < 8; i++)
|
||||
{
|
||||
collect_register (regcache, i + st0_regnum, raw);
|
||||
- p = ((char *) &fp->st_space[0]) + i * 16;
|
||||
+ p = fp->st_space + i * 16;
|
||||
if (memcmp (raw, p, 10))
|
||||
{
|
||||
xstate_bv |= X86_XSTATE_X87;
|
||||
@@ -365,7 +388,7 @@ i387_cache_to_xsave (struct regcache *regcache, void *buf)
|
||||
for (i = 0; i < num_xmm_registers; i++)
|
||||
{
|
||||
collect_register (regcache, i + xmm0_regnum, raw);
|
||||
- p = ((char *) &fp->xmm_space[0]) + i * 16;
|
||||
+ p = fp->xmm_space + i * 16;
|
||||
if (memcmp (raw, p, 16))
|
||||
{
|
||||
xstate_bv |= X86_XSTATE_SSE;
|
||||
@@ -382,7 +405,7 @@ i387_cache_to_xsave (struct regcache *regcache, void *buf)
|
||||
for (i = 0; i < num_xmm_registers; i++)
|
||||
{
|
||||
collect_register (regcache, i + ymm0h_regnum, raw);
|
||||
- p = ((char *) &fp->ymmh_space[0]) + i * 16;
|
||||
+ p = fp->ymmh_space () + i * 16;
|
||||
if (memcmp (raw, p, 16))
|
||||
{
|
||||
xstate_bv |= X86_XSTATE_AVX;
|
||||
@@ -399,7 +422,7 @@ i387_cache_to_xsave (struct regcache *regcache, void *buf)
|
||||
for (i = 0; i < num_mpx_bnd_registers; i++)
|
||||
{
|
||||
collect_register (regcache, i + bnd0r_regnum, raw);
|
||||
- p = ((char *) &fp->mpx_bnd_space[0]) + i * 16;
|
||||
+ p = fp->bndregs_space () + i * 16;
|
||||
if (memcmp (raw, p, 16))
|
||||
{
|
||||
xstate_bv |= X86_XSTATE_BNDREGS;
|
||||
@@ -416,7 +439,7 @@ i387_cache_to_xsave (struct regcache *regcache, void *buf)
|
||||
for (i = 0; i < num_mpx_cfg_registers; i++)
|
||||
{
|
||||
collect_register (regcache, i + bndcfg_regnum, raw);
|
||||
- p = ((char *) &fp->mpx_cfg_space[0]) + i * 8;
|
||||
+ p = fp->bndcfg_space () + i * 8;
|
||||
if (memcmp (raw, p, 8))
|
||||
{
|
||||
xstate_bv |= X86_XSTATE_BNDCFG;
|
||||
@@ -433,7 +456,7 @@ i387_cache_to_xsave (struct regcache *regcache, void *buf)
|
||||
for (i = 0; i < num_avx512_k_registers; i++)
|
||||
{
|
||||
collect_register (regcache, i + k0_regnum, raw);
|
||||
- p = ((char *) &fp->k_space[0]) + i * 8;
|
||||
+ p = fp->k_space () + i * 8;
|
||||
if (memcmp (raw, p, 8) != 0)
|
||||
{
|
||||
xstate_bv |= X86_XSTATE_K;
|
||||
@@ -450,7 +473,7 @@ i387_cache_to_xsave (struct regcache *regcache, void *buf)
|
||||
for (i = 0; i < num_avx512_zmmh_low_registers; i++)
|
||||
{
|
||||
collect_register (regcache, i + zmm0h_regnum, raw);
|
||||
- p = ((char *) &fp->zmmh_low_space[0]) + i * 32;
|
||||
+ p = fp->zmmh_space () + i * 32;
|
||||
if (memcmp (raw, p, 32) != 0)
|
||||
{
|
||||
xstate_bv |= X86_XSTATE_ZMM_H;
|
||||
@@ -469,7 +492,7 @@ i387_cache_to_xsave (struct regcache *regcache, void *buf)
|
||||
for (i = 0; i < num_avx512_zmmh_high_registers; i++)
|
||||
{
|
||||
collect_register (regcache, i + zmm16h_regnum, raw);
|
||||
- p = ((char *) &fp->zmmh_high_space[0]) + 32 + i * 64;
|
||||
+ p = fp->zmm16_space () + 32 + i * 64;
|
||||
if (memcmp (raw, p, 32) != 0)
|
||||
{
|
||||
xstate_bv |= X86_XSTATE_ZMM;
|
||||
@@ -488,7 +511,7 @@ i387_cache_to_xsave (struct regcache *regcache, void *buf)
|
||||
for (i = 0; i < num_avx512_xmm_registers; i++)
|
||||
{
|
||||
collect_register (regcache, i + xmm_avx512_regnum, raw);
|
||||
- p = ((char *) &fp->zmmh_high_space[0]) + i * 64;
|
||||
+ p = fp->zmm16_space () + i * 64;
|
||||
if (memcmp (raw, p, 16) != 0)
|
||||
{
|
||||
xstate_bv |= X86_XSTATE_ZMM;
|
||||
@@ -507,7 +530,7 @@ i387_cache_to_xsave (struct regcache *regcache, void *buf)
|
||||
for (i = 0; i < num_avx512_ymmh_registers; i++)
|
||||
{
|
||||
collect_register (regcache, i + ymmh_avx512_regnum, raw);
|
||||
- p = ((char *) &fp->zmmh_high_space[0]) + 16 + i * 64;
|
||||
+ p = fp->zmm16_space () + 16 + i * 64;
|
||||
if (memcmp (raw, p, 16) != 0)
|
||||
{
|
||||
xstate_bv |= X86_XSTATE_ZMM;
|
||||
@@ -524,7 +547,7 @@ i387_cache_to_xsave (struct regcache *regcache, void *buf)
|
||||
for (i = 0; i < num_pkeys_registers; i++)
|
||||
{
|
||||
collect_register (regcache, i + pkru_regnum, raw);
|
||||
- p = ((char *) &fp->pkru_space[0]) + i * 4;
|
||||
+ p = fp->pkru_space () + i * 4;
|
||||
if (memcmp (raw, p, 4) != 0)
|
||||
{
|
||||
xstate_bv |= X86_XSTATE_PKRU;
|
||||
@@ -730,7 +753,7 @@ i387_xsave_to_cache (struct regcache *regcache, const void *buf)
|
||||
int i, top;
|
||||
unsigned long val;
|
||||
unsigned long long clear_bv;
|
||||
- gdb_byte *p;
|
||||
+ unsigned char *p;
|
||||
|
||||
/* Amd64 has 16 xmm regs; I386 has 8 xmm regs. */
|
||||
int num_xmm_registers = amd64 ? 16 : 8;
|
||||
@@ -791,7 +814,7 @@ i387_xsave_to_cache (struct regcache *regcache, const void *buf)
|
||||
}
|
||||
else
|
||||
{
|
||||
- p = (gdb_byte *) &fp->ymmh_space[0];
|
||||
+ p = fp->ymmh_space ();
|
||||
for (i = 0; i < num_xmm_registers; i++)
|
||||
supply_register (regcache, i + ymm0h_regnum, p + i * 16);
|
||||
}
|
||||
@@ -809,7 +832,7 @@ i387_xsave_to_cache (struct regcache *regcache, const void *buf)
|
||||
}
|
||||
else
|
||||
{
|
||||
- p = (gdb_byte *) &fp->mpx_bnd_space[0];
|
||||
+ p = fp->bndregs_space ();
|
||||
for (i = 0; i < num_mpx_bnd_registers; i++)
|
||||
supply_register (regcache, i + bnd0r_regnum, p + i * 16);
|
||||
}
|
||||
@@ -827,7 +850,7 @@ i387_xsave_to_cache (struct regcache *regcache, const void *buf)
|
||||
}
|
||||
else
|
||||
{
|
||||
- p = (gdb_byte *) &fp->mpx_cfg_space[0];
|
||||
+ p = fp->bndcfg_space ();
|
||||
for (i = 0; i < num_mpx_cfg_registers; i++)
|
||||
supply_register (regcache, i + bndcfg_regnum, p + i * 8);
|
||||
}
|
||||
@@ -844,7 +867,7 @@ i387_xsave_to_cache (struct regcache *regcache, const void *buf)
|
||||
}
|
||||
else
|
||||
{
|
||||
- p = (gdb_byte *) &fp->k_space[0];
|
||||
+ p = fp->k_space ();
|
||||
for (i = 0; i < num_avx512_k_registers; i++)
|
||||
supply_register (regcache, i + k0_regnum, p + i * 8);
|
||||
}
|
||||
@@ -861,7 +884,7 @@ i387_xsave_to_cache (struct regcache *regcache, const void *buf)
|
||||
}
|
||||
else
|
||||
{
|
||||
- p = (gdb_byte *) &fp->zmmh_low_space[0];
|
||||
+ p = fp->zmmh_space ();
|
||||
for (i = 0; i < num_avx512_zmmh_low_registers; i++)
|
||||
supply_register (regcache, i + zmm0h_regnum, p + i * 32);
|
||||
}
|
||||
@@ -890,7 +913,7 @@ i387_xsave_to_cache (struct regcache *regcache, const void *buf)
|
||||
}
|
||||
else
|
||||
{
|
||||
- p = (gdb_byte *) &fp->zmmh_high_space[0];
|
||||
+ p = fp->zmm16_space ();
|
||||
for (i = 0; i < num_avx512_zmmh_high_registers; i++)
|
||||
supply_register (regcache, i + zmm16h_regnum, p + 32 + i * 64);
|
||||
for (i = 0; i < num_avx512_ymmh_registers; i++)
|
||||
@@ -911,7 +934,7 @@ i387_xsave_to_cache (struct regcache *regcache, const void *buf)
|
||||
}
|
||||
else
|
||||
{
|
||||
- p = (gdb_byte *) &fp->pkru_space[0];
|
||||
+ p = fp->pkru_space ();
|
||||
for (i = 0; i < num_pkeys_registers; i++)
|
||||
supply_register (regcache, i + pkru_regnum, p + i * 4);
|
||||
}
|
229
gdb-rhel-10464-xsave-update-13of21.patch
Normal file
229
gdb-rhel-10464-xsave-update-13of21.patch
Normal file
@ -0,0 +1,229 @@
|
||||
From FEDORA_PATCHES Mon Sep 17 00:00:00 2001
|
||||
From: John Baldwin <jhb@FreeBSD.org>
|
||||
Date: Thu, 11 Apr 2024 14:05:45 -0700
|
||||
Subject: gdb-rhel-10464-xsave-update-13of21.patch
|
||||
|
||||
;; Backport "gdbserver: Simplify handling of ZMM registers."
|
||||
;; (John Baldwin, RHEL-10464)
|
||||
|
||||
- Reuse num_xmm_registers directly for the count of ZMM0-15 registers
|
||||
as is already done for the YMM registers for AVX rather than using
|
||||
a new variable that is always the same.
|
||||
|
||||
- Replace 3 identical variables for the count of upper ZMM16-31
|
||||
registers with a single variable. Make use of this to merge
|
||||
various loops working on the ZMM XSAVE region so that all of the
|
||||
handling for the various sub-registers in this region are always
|
||||
handled in a single loop.
|
||||
|
||||
- While here, fix some bugs in i387_cache_to_xsave where if
|
||||
X86_XSTATE_ZMM was set on i386 (e.g. a 32-bit process on a 64-bit
|
||||
kernel), the -1 register nums would wrap around and store the value
|
||||
of GPRs in the XSAVE area. This should be harmless, but is
|
||||
definitely odd. Instead, check num_zmm_high_registers directly when
|
||||
checking X86_XSTATE_ZMM and skip the ZMM region handling entirely if
|
||||
the register count is 0.
|
||||
|
||||
Approved-By: Simon Marchi <simon.marchi@efficios.com>
|
||||
|
||||
diff --git a/gdbserver/i387-fp.cc b/gdbserver/i387-fp.cc
|
||||
--- a/gdbserver/i387-fp.cc
|
||||
+++ b/gdbserver/i387-fp.cc
|
||||
@@ -291,12 +291,8 @@ i387_cache_to_xsave (struct regcache *regcache, void *buf)
|
||||
|
||||
/* Amd64 has 16 xmm regs; I386 has 8 xmm regs. */
|
||||
int num_xmm_registers = amd64 ? 16 : 8;
|
||||
- /* AVX512 extends the existing xmm/ymm registers to a wider mode: zmm. */
|
||||
- int num_avx512_zmmh_low_registers = num_xmm_registers;
|
||||
- /* AVX512 adds 16 extra regs in Amd64 mode, but none in I386 mode.*/
|
||||
- int num_avx512_zmmh_high_registers = amd64 ? 16 : 0;
|
||||
- int num_avx512_ymmh_registers = amd64 ? 16 : 0;
|
||||
- int num_avx512_xmm_registers = amd64 ? 16 : 0;
|
||||
+ /* AVX512 adds 16 extra ZMM regs in Amd64 mode, but none in I386 mode.*/
|
||||
+ int num_zmm_high_registers = amd64 ? 16 : 0;
|
||||
|
||||
/* The supported bits in `xstat_bv' are 8 bytes. Clear part in
|
||||
vector registers if its bit in xstat_bv is zero. */
|
||||
@@ -345,18 +341,12 @@ i387_cache_to_xsave (struct regcache *regcache, void *buf)
|
||||
memset (fp->k_space () + i * 8, 0, 8);
|
||||
|
||||
if ((clear_bv & X86_XSTATE_ZMM_H))
|
||||
- for (i = 0; i < num_avx512_zmmh_low_registers; i++)
|
||||
+ for (i = 0; i < num_xmm_registers; i++)
|
||||
memset (fp->zmmh_space () + i * 32, 0, 32);
|
||||
|
||||
if ((clear_bv & X86_XSTATE_ZMM))
|
||||
- {
|
||||
- for (i = 0; i < num_avx512_zmmh_high_registers; i++)
|
||||
- memset (fp->zmm16_space () + 32 + i * 64, 0, 32);
|
||||
- for (i = 0; i < num_avx512_xmm_registers; i++)
|
||||
- memset (fp->zmm16_space () + i * 64, 0, 16);
|
||||
- for (i = 0; i < num_avx512_ymmh_registers; i++)
|
||||
- memset (fp->zmm16_space () + 16 + i * 64, 0, 16);
|
||||
- }
|
||||
+ for (i = 0; i < num_zmm_high_registers; i++)
|
||||
+ memset (fp->zmm16_space () + i * 64, 0, 64);
|
||||
|
||||
if ((clear_bv & X86_XSTATE_PKRU))
|
||||
for (i = 0; i < num_pkeys_registers; i++)
|
||||
@@ -470,7 +460,7 @@ i387_cache_to_xsave (struct regcache *regcache, void *buf)
|
||||
{
|
||||
int zmm0h_regnum = find_regno (regcache->tdesc, "zmm0h");
|
||||
|
||||
- for (i = 0; i < num_avx512_zmmh_low_registers; i++)
|
||||
+ for (i = 0; i < num_xmm_registers; i++)
|
||||
{
|
||||
collect_register (regcache, i + zmm0h_regnum, raw);
|
||||
p = fp->zmmh_space () + i * 32;
|
||||
@@ -482,55 +472,36 @@ i387_cache_to_xsave (struct regcache *regcache, void *buf)
|
||||
}
|
||||
}
|
||||
|
||||
- /* Check if any of ZMM16H-ZMM31H registers are changed. */
|
||||
- if ((x86_xcr0 & X86_XSTATE_ZMM))
|
||||
+ /* Check if any of ZMM16-ZMM31 registers are changed. */
|
||||
+ if ((x86_xcr0 & X86_XSTATE_ZMM) && num_zmm_high_registers != 0)
|
||||
{
|
||||
- int zmm16h_regnum = (num_avx512_zmmh_high_registers == 0
|
||||
- ? -1
|
||||
- : find_regno (regcache->tdesc, "zmm16h"));
|
||||
+ int zmm16h_regnum = find_regno (regcache->tdesc, "zmm16h");
|
||||
+ int ymm16h_regnum = find_regno (regcache->tdesc, "ymm16h");
|
||||
+ int xmm16_regnum = find_regno (regcache->tdesc, "xmm16");
|
||||
|
||||
- for (i = 0; i < num_avx512_zmmh_high_registers; i++)
|
||||
+ for (i = 0; i < num_zmm_high_registers; i++)
|
||||
{
|
||||
+ p = fp->zmm16_space () + i * 64;
|
||||
+
|
||||
+ /* ZMMH sub-register. */
|
||||
collect_register (regcache, i + zmm16h_regnum, raw);
|
||||
p = fp->zmm16_space () + 32 + i * 64;
|
||||
- if (memcmp (raw, p, 32) != 0)
|
||||
+ if (memcmp (raw, p + 32, 32) != 0)
|
||||
{
|
||||
xstate_bv |= X86_XSTATE_ZMM;
|
||||
memcpy (p, raw, 32);
|
||||
}
|
||||
- }
|
||||
- }
|
||||
-
|
||||
- /* Check if any XMM_AVX512 registers are changed. */
|
||||
- if ((x86_xcr0 & X86_XSTATE_ZMM))
|
||||
- {
|
||||
- int xmm_avx512_regnum = (num_avx512_xmm_registers == 0
|
||||
- ? -1
|
||||
- : find_regno (regcache->tdesc, "xmm16"));
|
||||
|
||||
- for (i = 0; i < num_avx512_xmm_registers; i++)
|
||||
- {
|
||||
- collect_register (regcache, i + xmm_avx512_regnum, raw);
|
||||
- p = fp->zmm16_space () + i * 64;
|
||||
- if (memcmp (raw, p, 16) != 0)
|
||||
+ /* YMMH sub-register. */
|
||||
+ collect_register (regcache, i + ymm16h_regnum, raw);
|
||||
+ if (memcmp (raw, p + 16, 16) != 0)
|
||||
{
|
||||
xstate_bv |= X86_XSTATE_ZMM;
|
||||
memcpy (p, raw, 16);
|
||||
}
|
||||
- }
|
||||
- }
|
||||
|
||||
- /* Check if any YMMH_AVX512 registers are changed. */
|
||||
- if ((x86_xcr0 & X86_XSTATE_ZMM))
|
||||
- {
|
||||
- int ymmh_avx512_regnum = (num_avx512_ymmh_registers == 0
|
||||
- ? -1
|
||||
- : find_regno (regcache->tdesc, "ymm16h"));
|
||||
-
|
||||
- for (i = 0; i < num_avx512_ymmh_registers; i++)
|
||||
- {
|
||||
- collect_register (regcache, i + ymmh_avx512_regnum, raw);
|
||||
- p = fp->zmm16_space () + 16 + i * 64;
|
||||
+ /* XMM sub-register. */
|
||||
+ collect_register (regcache, i + xmm16_regnum, raw);
|
||||
if (memcmp (raw, p, 16) != 0)
|
||||
{
|
||||
xstate_bv |= X86_XSTATE_ZMM;
|
||||
@@ -757,12 +728,8 @@ i387_xsave_to_cache (struct regcache *regcache, const void *buf)
|
||||
|
||||
/* Amd64 has 16 xmm regs; I386 has 8 xmm regs. */
|
||||
int num_xmm_registers = amd64 ? 16 : 8;
|
||||
- /* AVX512 extends the existing xmm/ymm registers to a wider mode: zmm. */
|
||||
- int num_avx512_zmmh_low_registers = num_xmm_registers;
|
||||
- /* AVX512 adds 16 extra regs in Amd64 mode, but none in I386 mode.*/
|
||||
- int num_avx512_zmmh_high_registers = amd64 ? 16 : 0;
|
||||
- int num_avx512_ymmh_registers = amd64 ? 16 : 0;
|
||||
- int num_avx512_xmm_registers = amd64 ? 16 : 0;
|
||||
+ /* AVX512 adds 16 extra ZMM regs in Amd64 mode, but none in I386 mode.*/
|
||||
+ int num_zmm_high_registers = amd64 ? 16 : 0;
|
||||
|
||||
/* The supported bits in `xstat_bv' are 8 bytes. Clear part in
|
||||
vector registers if its bit in xstat_bv is zero. */
|
||||
@@ -879,47 +846,41 @@ i387_xsave_to_cache (struct regcache *regcache, const void *buf)
|
||||
|
||||
if ((clear_bv & X86_XSTATE_ZMM_H) != 0)
|
||||
{
|
||||
- for (i = 0; i < num_avx512_zmmh_low_registers; i++)
|
||||
+ for (i = 0; i < num_xmm_registers; i++)
|
||||
supply_register_zeroed (regcache, i + zmm0h_regnum);
|
||||
}
|
||||
else
|
||||
{
|
||||
p = fp->zmmh_space ();
|
||||
- for (i = 0; i < num_avx512_zmmh_low_registers; i++)
|
||||
+ for (i = 0; i < num_xmm_registers; i++)
|
||||
supply_register (regcache, i + zmm0h_regnum, p + i * 32);
|
||||
}
|
||||
}
|
||||
|
||||
- if ((x86_xcr0 & X86_XSTATE_ZMM) != 0)
|
||||
+ if ((x86_xcr0 & X86_XSTATE_ZMM) != 0 && num_zmm_high_registers != 0)
|
||||
{
|
||||
- int zmm16h_regnum = (num_avx512_zmmh_high_registers == 0
|
||||
- ? -1
|
||||
- : find_regno (regcache->tdesc, "zmm16h"));
|
||||
- int ymm16h_regnum = (num_avx512_ymmh_registers == 0
|
||||
- ? -1
|
||||
- : find_regno (regcache->tdesc, "ymm16h"));
|
||||
- int xmm16_regnum = (num_avx512_xmm_registers == 0
|
||||
- ? -1
|
||||
- : find_regno (regcache->tdesc, "xmm16"));
|
||||
+ int zmm16h_regnum = find_regno (regcache->tdesc, "zmm16h");
|
||||
+ int ymm16h_regnum = find_regno (regcache->tdesc, "ymm16h");
|
||||
+ int xmm16_regnum = find_regno (regcache->tdesc, "xmm16");
|
||||
|
||||
if ((clear_bv & X86_XSTATE_ZMM) != 0)
|
||||
{
|
||||
- for (i = 0; i < num_avx512_zmmh_high_registers; i++)
|
||||
- supply_register_zeroed (regcache, i + zmm16h_regnum);
|
||||
- for (i = 0; i < num_avx512_ymmh_registers; i++)
|
||||
- supply_register_zeroed (regcache, i + ymm16h_regnum);
|
||||
- for (i = 0; i < num_avx512_xmm_registers; i++)
|
||||
- supply_register_zeroed (regcache, i + xmm16_regnum);
|
||||
+ for (i = 0; i < num_zmm_high_registers; i++)
|
||||
+ {
|
||||
+ supply_register_zeroed (regcache, i + zmm16h_regnum);
|
||||
+ supply_register_zeroed (regcache, i + ymm16h_regnum);
|
||||
+ supply_register_zeroed (regcache, i + xmm16_regnum);
|
||||
+ }
|
||||
}
|
||||
else
|
||||
{
|
||||
p = fp->zmm16_space ();
|
||||
- for (i = 0; i < num_avx512_zmmh_high_registers; i++)
|
||||
- supply_register (regcache, i + zmm16h_regnum, p + 32 + i * 64);
|
||||
- for (i = 0; i < num_avx512_ymmh_registers; i++)
|
||||
- supply_register (regcache, i + ymm16h_regnum, p + 16 + i * 64);
|
||||
- for (i = 0; i < num_avx512_xmm_registers; i++)
|
||||
- supply_register (regcache, i + xmm16_regnum, p + i * 64);
|
||||
+ for (i = 0; i < num_zmm_high_registers; i++)
|
||||
+ {
|
||||
+ supply_register (regcache, i + zmm16h_regnum, p + 32 + i * 64);
|
||||
+ supply_register (regcache, i + ymm16h_regnum, p + 16 + i * 64);
|
||||
+ supply_register (regcache, i + xmm16_regnum, p + i * 64);
|
||||
+ }
|
||||
}
|
||||
}
|
||||
|
69
gdb-rhel-10464-xsave-update-14of21.patch
Normal file
69
gdb-rhel-10464-xsave-update-14of21.patch
Normal file
@ -0,0 +1,69 @@
|
||||
From FEDORA_PATCHES Mon Sep 17 00:00:00 2001
|
||||
From: Aleksandar Paunovic <aleksandar.paunovic@intel.com>
|
||||
Date: Thu, 11 Apr 2024 14:05:45 -0700
|
||||
Subject: gdb-rhel-10464-xsave-update-14of21.patch
|
||||
|
||||
;; Backport "gdbserver: Refactor the legacy region within the xsave struct"
|
||||
;; (Aleksandar Paunovic, RHEL-10464)
|
||||
|
||||
Legacy fields of the XSAVE area are already defined within fx_save
|
||||
struct. Use class inheritance to remove code duplication.
|
||||
|
||||
The two changed functions are called within all tests which run
|
||||
gdbserver.
|
||||
|
||||
Signed-off-by: Aleksandar Paunovic <aleksandar.paunovic@intel.com>
|
||||
Co-authored-by: John Baldwin <jhb@FreeBSD.org>
|
||||
Approved-By: Simon Marchi <simon.marchi@efficios.com>
|
||||
|
||||
diff --git a/gdbserver/i387-fp.cc b/gdbserver/i387-fp.cc
|
||||
--- a/gdbserver/i387-fp.cc
|
||||
+++ b/gdbserver/i387-fp.cc
|
||||
@@ -83,29 +83,7 @@ struct i387_fxsave {
|
||||
|
||||
gdb_static_assert (sizeof(i387_fxsave) == 416);
|
||||
|
||||
-struct i387_xsave {
|
||||
- /* All these are only sixteen bits, plus padding, except for fop (which
|
||||
- is only eleven bits), and fooff / fioff (which are 32 bits each). */
|
||||
- unsigned short fctrl;
|
||||
- unsigned short fstat;
|
||||
- unsigned short ftag;
|
||||
- unsigned short fop;
|
||||
- unsigned int fioff;
|
||||
- unsigned short fiseg;
|
||||
- unsigned short pad1;
|
||||
- unsigned int fooff;
|
||||
- unsigned short foseg;
|
||||
- unsigned short pad12;
|
||||
-
|
||||
- unsigned int mxcsr;
|
||||
- unsigned int mxcsr_mask;
|
||||
-
|
||||
- /* Space for eight 80-bit FP values in 128-bit spaces. */
|
||||
- unsigned char st_space[128];
|
||||
-
|
||||
- /* Space for eight 128-bit XMM values, or 16 on x86-64. */
|
||||
- unsigned char xmm_space[256];
|
||||
-
|
||||
+struct i387_xsave : public i387_fxsave {
|
||||
unsigned char reserved1[48];
|
||||
|
||||
/* The extended control register 0 (the XFEATURE_ENABLED_MASK
|
||||
@@ -719,7 +697,6 @@ void
|
||||
i387_xsave_to_cache (struct regcache *regcache, const void *buf)
|
||||
{
|
||||
struct i387_xsave *fp = (struct i387_xsave *) buf;
|
||||
- struct i387_fxsave *fxp = (struct i387_fxsave *) buf;
|
||||
bool amd64 = register_size (regcache->tdesc, 0) == 8;
|
||||
int i, top;
|
||||
unsigned long val;
|
||||
@@ -946,7 +923,7 @@ i387_xsave_to_cache (struct regcache *regcache, const void *buf)
|
||||
{
|
||||
int tag;
|
||||
if (fp->ftag & (1 << i))
|
||||
- tag = i387_ftag (fxp, (i + 8 - top) % 8);
|
||||
+ tag = i387_ftag (fp, (i + 8 - top) % 8);
|
||||
else
|
||||
tag = 3;
|
||||
val |= tag << (2 * i);
|
41
gdb-rhel-10464-xsave-update-15of21.patch
Normal file
41
gdb-rhel-10464-xsave-update-15of21.patch
Normal file
@ -0,0 +1,41 @@
|
||||
From FEDORA_PATCHES Mon Sep 17 00:00:00 2001
|
||||
From: John Baldwin <jhb@FreeBSD.org>
|
||||
Date: Thu, 11 Apr 2024 14:05:45 -0700
|
||||
Subject: gdb-rhel-10464-xsave-update-15of21.patch
|
||||
|
||||
;; Backport "gdbserver: Fix style of struct declarations in i387-fp.cc"
|
||||
;; (John Baldwin, RHEL-10464)
|
||||
|
||||
diff --git a/gdbserver/i387-fp.cc b/gdbserver/i387-fp.cc
|
||||
--- a/gdbserver/i387-fp.cc
|
||||
+++ b/gdbserver/i387-fp.cc
|
||||
@@ -37,7 +37,8 @@ static x86_xsave_layout xsave_layout;
|
||||
/* These structs should have the proper sizes and alignment on both
|
||||
i386 and x86-64 machines. */
|
||||
|
||||
-struct i387_fsave {
|
||||
+struct i387_fsave
|
||||
+{
|
||||
/* All these are only sixteen bits, plus padding, except for fop (which
|
||||
is only eleven bits), and fooff / fioff (which are 32 bits each). */
|
||||
unsigned short fctrl;
|
||||
@@ -57,7 +58,8 @@ struct i387_fsave {
|
||||
unsigned char st_space[80];
|
||||
};
|
||||
|
||||
-struct i387_fxsave {
|
||||
+struct i387_fxsave
|
||||
+{
|
||||
/* All these are only sixteen bits, plus padding, except for fop (which
|
||||
is only eleven bits), and fooff / fioff (which are 32 bits each). */
|
||||
unsigned short fctrl;
|
||||
@@ -83,7 +85,8 @@ struct i387_fxsave {
|
||||
|
||||
gdb_static_assert (sizeof(i387_fxsave) == 416);
|
||||
|
||||
-struct i387_xsave : public i387_fxsave {
|
||||
+struct i387_xsave : public i387_fxsave
|
||||
+{
|
||||
unsigned char reserved1[48];
|
||||
|
||||
/* The extended control register 0 (the XFEATURE_ENABLED_MASK
|
52
gdb-rhel-10464-xsave-update-16of21.patch
Normal file
52
gdb-rhel-10464-xsave-update-16of21.patch
Normal file
@ -0,0 +1,52 @@
|
||||
From FEDORA_PATCHES Mon Sep 17 00:00:00 2001
|
||||
From: John Baldwin <jhb@FreeBSD.org>
|
||||
Date: Thu, 11 Apr 2024 14:05:45 -0700
|
||||
Subject: gdb-rhel-10464-xsave-update-16of21.patch
|
||||
|
||||
;; Backport "nat/x86-cpuid.h: Remove non-x86 fallbacks"
|
||||
;; (John Baldwin, RHEL-10464)
|
||||
|
||||
This header is only suitable for use on x86 hosts and is only included
|
||||
there, so these fallbacks should not be needed.
|
||||
|
||||
Approved-By: Simon Marchi <simon.marchi@efficios.com>
|
||||
|
||||
diff --git a/gdb/nat/x86-cpuid.h b/gdb/nat/x86-cpuid.h
|
||||
--- a/gdb/nat/x86-cpuid.h
|
||||
+++ b/gdb/nat/x86-cpuid.h
|
||||
@@ -28,8 +28,6 @@
|
||||
#define nullptr ((void *) 0)
|
||||
#endif
|
||||
|
||||
-#if defined(__i386__) || defined(__x86_64__)
|
||||
-
|
||||
/* Return cpuid data for requested cpuid level, as found in returned
|
||||
eax, ebx, ecx and edx registers. The function checks if cpuid is
|
||||
supported and returns 1 for valid cpuid information or 0 for
|
||||
@@ -78,26 +76,6 @@ x86_cpuid_count (unsigned int __level, unsigned int __sublevel,
|
||||
return __get_cpuid_count (__level, __sublevel, __eax, __ebx, __ecx, __edx);
|
||||
}
|
||||
|
||||
-#else
|
||||
-
|
||||
-static __inline int
|
||||
-x86_cpuid (unsigned int __level,
|
||||
- unsigned int *__eax, unsigned int *__ebx,
|
||||
- unsigned int *__ecx, unsigned int *__edx)
|
||||
-{
|
||||
- return 0;
|
||||
-}
|
||||
-
|
||||
-static __inline int
|
||||
-x86_cpuid_count (unsigned int __level, unsigned int __sublevel,
|
||||
- unsigned int *__eax, unsigned int *__ebx,
|
||||
- unsigned int *__ecx, unsigned int *__edx)
|
||||
-{
|
||||
- return 0;
|
||||
-}
|
||||
-
|
||||
-#endif /* i386 && x86_64 */
|
||||
-
|
||||
#ifndef __cplusplus
|
||||
/* Avoid leaking this local definition beyond the scope of this header
|
||||
file. */
|
188
gdb-rhel-10464-xsave-update-17of21.patch
Normal file
188
gdb-rhel-10464-xsave-update-17of21.patch
Normal file
@ -0,0 +1,188 @@
|
||||
From FEDORA_PATCHES Mon Sep 17 00:00:00 2001
|
||||
From: John Baldwin <jhb@FreeBSD.org>
|
||||
Date: Thu, 11 Apr 2024 14:05:46 -0700
|
||||
Subject: gdb-rhel-10464-xsave-update-17of21.patch
|
||||
|
||||
;; Backport "i386: Use a fallback XSAVE layout for remote targets"
|
||||
;; (John Baldwin, RHEL-10464)
|
||||
|
||||
If a target provides a target description including registers from the
|
||||
XSAVE extended region, but does not provide an XSAVE layout, use a
|
||||
fallback XSAVE layout based on the included registers. This fallback
|
||||
layout matches GDB's behavior in earlier releases which assumes the
|
||||
layout from Intel CPUs.
|
||||
|
||||
This fallback layout is currently only used for remote targets since
|
||||
native targets which support XSAVE provide an explicit layout derived
|
||||
from CPUID.
|
||||
|
||||
PR gdb/30912
|
||||
Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=30912
|
||||
Approved-By: Simon Marchi <simon.marchi@efficios.com>
|
||||
|
||||
diff --git a/gdb/i386-tdep.c b/gdb/i386-tdep.c
|
||||
--- a/gdb/i386-tdep.c
|
||||
+++ b/gdb/i386-tdep.c
|
||||
@@ -8244,6 +8244,72 @@ i386_floatformat_for_type (struct gdbarch *gdbarch,
|
||||
return default_floatformat_for_type (gdbarch, name, len);
|
||||
}
|
||||
|
||||
+/* Compute an XCR0 mask based on a target description. */
|
||||
+
|
||||
+static uint64_t
|
||||
+i386_xcr0_from_tdesc (const struct target_desc *tdesc)
|
||||
+{
|
||||
+ if (! tdesc_has_registers (tdesc))
|
||||
+ return 0;
|
||||
+
|
||||
+ const struct tdesc_feature *feature_core;
|
||||
+
|
||||
+ const struct tdesc_feature *feature_sse, *feature_avx, *feature_mpx,
|
||||
+ *feature_avx512, *feature_pkeys;
|
||||
+
|
||||
+ /* Get core registers. */
|
||||
+ feature_core = tdesc_find_feature (tdesc, "org.gnu.gdb.i386.core");
|
||||
+ if (feature_core == NULL)
|
||||
+ return 0;
|
||||
+
|
||||
+ /* Get SSE registers. */
|
||||
+ feature_sse = tdesc_find_feature (tdesc, "org.gnu.gdb.i386.sse");
|
||||
+
|
||||
+ /* Try AVX registers. */
|
||||
+ feature_avx = tdesc_find_feature (tdesc, "org.gnu.gdb.i386.avx");
|
||||
+
|
||||
+ /* Try MPX registers. */
|
||||
+ feature_mpx = tdesc_find_feature (tdesc, "org.gnu.gdb.i386.mpx");
|
||||
+
|
||||
+ /* Try AVX512 registers. */
|
||||
+ feature_avx512 = tdesc_find_feature (tdesc, "org.gnu.gdb.i386.avx512");
|
||||
+
|
||||
+ /* Try PKEYS */
|
||||
+ feature_pkeys = tdesc_find_feature (tdesc, "org.gnu.gdb.i386.pkeys");
|
||||
+
|
||||
+ /* The XCR0 bits. */
|
||||
+ uint64_t xcr0 = X86_XSTATE_X87;
|
||||
+
|
||||
+ if (feature_sse)
|
||||
+ xcr0 |= X86_XSTATE_SSE;
|
||||
+
|
||||
+ if (feature_avx)
|
||||
+ {
|
||||
+ /* AVX register description requires SSE register description. */
|
||||
+ if (!feature_sse)
|
||||
+ return 0;
|
||||
+
|
||||
+ xcr0 |= X86_XSTATE_AVX;
|
||||
+ }
|
||||
+
|
||||
+ if (feature_mpx)
|
||||
+ xcr0 |= X86_XSTATE_MPX_MASK;
|
||||
+
|
||||
+ if (feature_avx512)
|
||||
+ {
|
||||
+ /* AVX512 register description requires AVX register description. */
|
||||
+ if (!feature_avx)
|
||||
+ return 0;
|
||||
+
|
||||
+ xcr0 |= X86_XSTATE_AVX512;
|
||||
+ }
|
||||
+
|
||||
+ if (feature_pkeys)
|
||||
+ xcr0 |= X86_XSTATE_PKRU;
|
||||
+
|
||||
+ return xcr0;
|
||||
+}
|
||||
+
|
||||
static int
|
||||
i386_validate_tdesc_p (struct gdbarch_tdep *tdep,
|
||||
struct tdesc_arch_data *tdesc_data)
|
||||
@@ -8458,6 +8524,15 @@ i386_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
|
||||
|
||||
x86_xsave_layout xsave_layout = target_fetch_x86_xsave_layout ();
|
||||
|
||||
+ /* If the target did not provide an XSAVE layout but the target
|
||||
+ description includes registers from the XSAVE extended region,
|
||||
+ use a fallback XSAVE layout. Specifically, this fallback layout
|
||||
+ is used when writing out a local core dump for a remote
|
||||
+ target. */
|
||||
+ if (xsave_layout.sizeof_xsave == 0)
|
||||
+ xsave_layout
|
||||
+ = i387_fallback_xsave_layout (i386_xcr0_from_tdesc (info.target_desc));
|
||||
+
|
||||
/* If there is already a candidate, use it. */
|
||||
for (arches = gdbarch_list_lookup_by_info (arches, &info);
|
||||
arches != NULL;
|
||||
diff --git a/gdb/i387-tdep.c b/gdb/i387-tdep.c
|
||||
--- a/gdb/i387-tdep.c
|
||||
+++ b/gdb/i387-tdep.c
|
||||
@@ -982,6 +982,55 @@ i387_guess_xsave_layout (uint64_t xcr0, size_t xsave_size,
|
||||
return true;
|
||||
}
|
||||
|
||||
+/* See i387-tdep.h. */
|
||||
+
|
||||
+x86_xsave_layout
|
||||
+i387_fallback_xsave_layout (uint64_t xcr0)
|
||||
+{
|
||||
+ x86_xsave_layout layout;
|
||||
+ memset (&layout, 0, sizeof (x86_xsave_layout));
|
||||
+
|
||||
+ if (HAS_PKRU (xcr0))
|
||||
+ {
|
||||
+ /* Intel CPUs supporting PKRU. */
|
||||
+ layout.avx_offset = 576;
|
||||
+ layout.bndregs_offset = 960;
|
||||
+ layout.bndcfg_offset = 1024;
|
||||
+ layout.k_offset = 1088;
|
||||
+ layout.zmm_h_offset = 1152;
|
||||
+ layout.zmm_offset = 1664;
|
||||
+ layout.pkru_offset = 2688;
|
||||
+ layout.sizeof_xsave = 2696;
|
||||
+ }
|
||||
+ else if (HAS_AVX512 (xcr0))
|
||||
+ {
|
||||
+ /* Intel CPUs supporting AVX512. */
|
||||
+ layout.avx_offset = 576;
|
||||
+ layout.bndregs_offset = 960;
|
||||
+ layout.bndcfg_offset = 1024;
|
||||
+ layout.k_offset = 1088;
|
||||
+ layout.zmm_h_offset = 1152;
|
||||
+ layout.zmm_offset = 1664;
|
||||
+ layout.sizeof_xsave = 2688;
|
||||
+ }
|
||||
+ else if (HAS_MPX (xcr0))
|
||||
+ {
|
||||
+ /* Intel CPUs supporting MPX. */
|
||||
+ layout.avx_offset = 576;
|
||||
+ layout.bndregs_offset = 960;
|
||||
+ layout.bndcfg_offset = 1024;
|
||||
+ layout.sizeof_xsave = 1088;
|
||||
+ }
|
||||
+ else if (HAS_AVX (xcr0))
|
||||
+ {
|
||||
+ /* Intel and AMD CPUs supporting AVX. */
|
||||
+ layout.avx_offset = 576;
|
||||
+ layout.sizeof_xsave = 832;
|
||||
+ }
|
||||
+
|
||||
+ return layout;
|
||||
+}
|
||||
+
|
||||
/* Extract from XSAVE a bitset of the features that are available on the
|
||||
target, but which have not yet been enabled. */
|
||||
|
||||
diff --git a/gdb/i387-tdep.h b/gdb/i387-tdep.h
|
||||
--- a/gdb/i387-tdep.h
|
||||
+++ b/gdb/i387-tdep.h
|
||||
@@ -148,6 +148,11 @@ extern bool i387_guess_xsave_layout (uint64_t xcr0, size_t xsave_size,
|
||||
x86_xsave_layout &layout);
|
||||
|
||||
|
||||
+/* Compute an XSAVE layout based on the XCR0 bitmask. This is used
|
||||
+ as a fallback if a target does not provide an XSAVE layout. */
|
||||
+
|
||||
+extern x86_xsave_layout i387_fallback_xsave_layout (uint64_t xcr0);
|
||||
+
|
||||
/* Similar to i387_supply_fxsave, but use XSAVE extended state. */
|
||||
|
||||
extern void i387_supply_xsave (struct regcache *regcache, int regnum,
|
67
gdb-rhel-10464-xsave-update-18of21.patch
Normal file
67
gdb-rhel-10464-xsave-update-18of21.patch
Normal file
@ -0,0 +1,67 @@
|
||||
From FEDORA_PATCHES Mon Sep 17 00:00:00 2001
|
||||
From: Simon Marchi <simon.marchi@efficios.com>
|
||||
Date: Thu, 11 Apr 2024 14:05:46 -0700
|
||||
Subject: gdb-rhel-10464-xsave-update-18of21.patch
|
||||
|
||||
;; Backport "gdbserver: i387_cache_to_xsave: fix copy dest of zmm registers"
|
||||
;; (Simon Marchi, RHEL-10464)
|
||||
|
||||
On a machine with AVX512 support (AMD EPYC 9634), I see these failures:
|
||||
|
||||
$ make check TESTS="gdb.arch/i386-avx512.exp" RUNTESTFLAGS="--target_board=native-gdbserver"
|
||||
...
|
||||
FAIL: gdb.arch/i386-avx512.exp: check contents of zmm_data[16] after writing ZMM regs
|
||||
FAIL: gdb.arch/i386-avx512.exp: check contents of zmm_data[17] after writing ZMM regs
|
||||
FAIL: gdb.arch/i386-avx512.exp: check contents of zmm_data[18] after writing ZMM regs
|
||||
...
|
||||
|
||||
The problem can be reduced to:
|
||||
|
||||
(gdb) print $zmm16.v8_int64
|
||||
$1 = {0, 0, 0, 0, 0, 0, 0, 0}
|
||||
(gdb) print $zmm16.v8_int64 = {11,22,33,44,55,66,77,88}
|
||||
$2 = {11, 22, 33, 44, 55, 66, 77, 88}
|
||||
(gdb) print $zmm16.v8_int64
|
||||
$3 = {11, 22, 33, 44, 55, 66, 77, 88}
|
||||
(gdb) step
|
||||
5 ++x;
|
||||
(gdb) print $zmm16.v8_int64
|
||||
$4 = {11, 22, 77, 88, 0, 0, 0, 0}
|
||||
|
||||
Writing to the local regcache in GDB works fine, but the writeback to
|
||||
gdbserver (which happens when resuming / stepping) doesn't work (the
|
||||
code being stepped doesn't touch AVX registers, so we don't expect the
|
||||
value of zmm16 to change when stepping).
|
||||
|
||||
The problem is on the gdbserver side, the zmmh and ymmh portions of the
|
||||
zmm register are not memcpied at the right place in the xsave buffer. Fix
|
||||
that. Note now how the two modified memcpy calls match the memcmp calls
|
||||
just above them.
|
||||
|
||||
With this patch, gdb.arch/i386-avx512.exp passes completely for me.
|
||||
|
||||
Change-Id: I22c417e0f5e88d4bc635a0f08f8817a031c76433
|
||||
Reviewed-by: John Baldwin <jhb@FreeBSD.org>
|
||||
Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=30818
|
||||
|
||||
diff --git a/gdbserver/i387-fp.cc b/gdbserver/i387-fp.cc
|
||||
--- a/gdbserver/i387-fp.cc
|
||||
+++ b/gdbserver/i387-fp.cc
|
||||
@@ -470,7 +470,7 @@ i387_cache_to_xsave (struct regcache *regcache, void *buf)
|
||||
if (memcmp (raw, p + 32, 32) != 0)
|
||||
{
|
||||
xstate_bv |= X86_XSTATE_ZMM;
|
||||
- memcpy (p, raw, 32);
|
||||
+ memcpy (p + 32, raw, 32);
|
||||
}
|
||||
|
||||
/* YMMH sub-register. */
|
||||
@@ -478,7 +478,7 @@ i387_cache_to_xsave (struct regcache *regcache, void *buf)
|
||||
if (memcmp (raw, p + 16, 16) != 0)
|
||||
{
|
||||
xstate_bv |= X86_XSTATE_ZMM;
|
||||
- memcpy (p, raw, 16);
|
||||
+ memcpy (p + 16, raw, 16);
|
||||
}
|
||||
|
||||
/* XMM sub-register. */
|
132
gdb-rhel-10464-xsave-update-19of21.patch
Normal file
132
gdb-rhel-10464-xsave-update-19of21.patch
Normal file
@ -0,0 +1,132 @@
|
||||
From FEDORA_PATCHES Mon Sep 17 00:00:00 2001
|
||||
From: Andrew Burgess <andrew.burgess@embecosm.com>
|
||||
Date: Thu, 11 Apr 2024 14:05:46 -0700
|
||||
Subject: gdb-rhel-10464-xsave-update-19of21.patch
|
||||
|
||||
;; Backport "bfd/binutils: support for gdb target descriptions in the core file"
|
||||
;; (Andrew Burgess, RHEL-10464)
|
||||
|
||||
This commit lays the ground work for allowing GDB to write its target
|
||||
description into a generated core file.
|
||||
|
||||
The goal of this work is to allow a user to connect to a remote
|
||||
target, capture a core file from within GDB, then pass the executable
|
||||
and core file to another user and have the user be able to examine the
|
||||
state of the machine without needing to connect to a running target.
|
||||
|
||||
Different remote targets can have different register sets and this
|
||||
information is communicated from the target to GDB in the target
|
||||
description.
|
||||
|
||||
It is possible for a user to extract the target description from GDB
|
||||
and pass this along with the core file so that when the core file is
|
||||
used the target description can be fed back into GDB, however this is
|
||||
not a great user experience.
|
||||
It would be nicer, I think, if GDB could write the target description
|
||||
directly into the core file, and then make use of this description
|
||||
when loading a core file.
|
||||
|
||||
This commit performs the binutils/bfd side of this task, adding the
|
||||
boiler plate functions to access the target description from within a
|
||||
core file note, and reserving a new number for a note containing the
|
||||
target description. Later commits will extend GDB to make use of
|
||||
this.
|
||||
|
||||
The new note is given the name 'GDB' and a type NT_GDB_TDESC. This
|
||||
should hopefully protect us if there's ever a reuse of the number
|
||||
assigned to NT_GDB_TDESC by some other core file producer. It should
|
||||
also, hopefully, make it clearer to users that this note carries GDB
|
||||
specific information.
|
||||
|
||||
diff --git a/bfd/elf-bfd.h b/bfd/elf-bfd.h
|
||||
--- a/bfd/elf-bfd.h
|
||||
+++ b/bfd/elf-bfd.h
|
||||
@@ -2795,6 +2795,8 @@ extern char *elfcore_write_aarch_pauth
|
||||
(bfd *, char *, int *, const void *, int);
|
||||
extern char *elfcore_write_arc_v2
|
||||
(bfd *, char *, int *, const void *, int);
|
||||
+extern char *elfcore_write_gdb_tdesc
|
||||
+ (bfd *, char *, int *, const void *, int);
|
||||
extern char *elfcore_write_lwpstatus
|
||||
(bfd *, char *, int *, long, int, const void *);
|
||||
extern char *elfcore_write_register_note
|
||||
diff --git a/bfd/elf.c b/bfd/elf.c
|
||||
--- a/bfd/elf.c
|
||||
+++ b/bfd/elf.c
|
||||
@@ -9903,6 +9903,15 @@ elfcore_grok_arc_v2 (bfd *abfd, Elf_Internal_Note *note)
|
||||
return elfcore_make_note_pseudosection (abfd, ".reg-arc-v2", note);
|
||||
}
|
||||
|
||||
+/* Convert NOTE into a bfd_section called ".gdb-tdesc". Return TRUE if
|
||||
+ successful otherwise, return FALSE. */
|
||||
+
|
||||
+static bfd_boolean
|
||||
+elfcore_grok_gdb_tdesc (bfd *abfd, Elf_Internal_Note *note)
|
||||
+{
|
||||
+ return elfcore_make_note_pseudosection (abfd, ".gdb-tdesc", note);
|
||||
+}
|
||||
+
|
||||
#if defined (HAVE_PRPSINFO_T)
|
||||
typedef prpsinfo_t elfcore_psinfo_t;
|
||||
#if defined (HAVE_PRPSINFO32_T) /* Sparc64 cross Sparc32 */
|
||||
@@ -10560,6 +10569,13 @@ elfcore_grok_note (bfd *abfd, Elf_Internal_Note *note)
|
||||
else
|
||||
return TRUE;
|
||||
|
||||
+ case NT_GDB_TDESC:
|
||||
+ if (note->namesz == 4
|
||||
+ && strcmp (note->namedata, "GDB") == 0)
|
||||
+ return elfcore_grok_gdb_tdesc (abfd, note);
|
||||
+ else
|
||||
+ return TRUE;
|
||||
+
|
||||
case NT_PRPSINFO:
|
||||
case NT_PSINFO:
|
||||
if (bed->elf_backend_grok_psinfo)
|
||||
@@ -11941,6 +11957,23 @@ elfcore_write_arc_v2 (bfd *abfd,
|
||||
note_name, NT_ARC_V2, arc_v2, size);
|
||||
}
|
||||
|
||||
+/* Write the target description (a string) pointed to by TDESC, length
|
||||
+ SIZE, into the note buffer BUF, and update *BUFSIZ. ABFD is the bfd the
|
||||
+ note is being written into. Return a pointer to the new start of the
|
||||
+ note buffer, to replace BUF which may no longer be valid. */
|
||||
+
|
||||
+char *
|
||||
+elfcore_write_gdb_tdesc (bfd *abfd,
|
||||
+ char *buf,
|
||||
+ int *bufsiz,
|
||||
+ const void *tdesc,
|
||||
+ int size)
|
||||
+{
|
||||
+ const char *note_name = "GDB";
|
||||
+ return elfcore_write_note (abfd, buf, bufsiz,
|
||||
+ note_name, NT_GDB_TDESC, tdesc, size);
|
||||
+}
|
||||
+
|
||||
char *
|
||||
elfcore_write_register_note (bfd *abfd,
|
||||
char *buf,
|
||||
@@ -12025,6 +12058,8 @@ elfcore_write_register_note (bfd *abfd,
|
||||
return elfcore_write_aarch_pauth (abfd, buf, bufsiz, data, size);
|
||||
if (strcmp (section, ".reg-arc-v2") == 0)
|
||||
return elfcore_write_arc_v2 (abfd, buf, bufsiz, data, size);
|
||||
+ if (strcmp (section, ".gdb-tdesc") == 0)
|
||||
+ return elfcore_write_gdb_tdesc (abfd, buf, bufsiz, data, size);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
diff --git a/include/elf/common.h b/include/elf/common.h
|
||||
--- a/include/elf/common.h
|
||||
+++ b/include/elf/common.h
|
||||
@@ -665,6 +665,10 @@
|
||||
#define NT_SIGINFO 0x53494749 /* Fields of siginfo_t. */
|
||||
#define NT_FILE 0x46494c45 /* Description of mapped files. */
|
||||
|
||||
+/* The range 0xff000000 to 0xffffffff is set aside for notes that don't
|
||||
+ originate from any particular operating system. */
|
||||
+#define NT_GDB_TDESC 0xff000000 /* Contains copy of GDB's target description XML. */
|
||||
+
|
||||
/* Note segments for core files on dir-style procfs systems. */
|
||||
|
||||
#define NT_PSTATUS 10 /* Has a struct pstatus */
|
125
gdb-rhel-10464-xsave-update-1of21.patch
Normal file
125
gdb-rhel-10464-xsave-update-1of21.patch
Normal file
@ -0,0 +1,125 @@
|
||||
From FEDORA_PATCHES Mon Sep 17 00:00:00 2001
|
||||
From: John Baldwin <jhb@FreeBSD.org>
|
||||
Date: Thu, 11 Apr 2024 14:05:42 -0700
|
||||
Subject: gdb-rhel-10464-xsave-update-1of21.patch
|
||||
|
||||
;; Backport "x86: Add an x86_xsave_layout structure to
|
||||
;; handle variable XSAVE layouts."
|
||||
;; (John Baldwin, RHEL-10464)
|
||||
|
||||
The standard layout of the XSAVE extended state area consists of three
|
||||
regions. The first 512 bytes (legacy region) match the layout of the
|
||||
FXSAVE instruction including floating point registers, MMX registers,
|
||||
and SSE registers. The next 64 bytes (XSAVE header) contains a header
|
||||
with a fixed layout. The final region (extended region) contains zero
|
||||
or more optional state components. Examples of these include the
|
||||
upper 128 bits of YMM registers for AVX.
|
||||
|
||||
These optional state components generally have an
|
||||
architecturally-fixed size, but they are not assigned architectural
|
||||
offsets in the extended region. Instead, processors provide
|
||||
additional CPUID leafs describing the size and offset of each
|
||||
component in the "standard" layout for a given CPU. (There is also a
|
||||
"compact" format which uses an alternate layout, but existing OS's
|
||||
currently export the "standard" layout when exporting XSAVE data via
|
||||
ptrace() and core dumps.)
|
||||
|
||||
To date, GDB has assumed the layout used on current Intel processors
|
||||
for state components in the extended region and hardcoded those
|
||||
offsets in the tables in i387-tdep.c and i387-fp.cc. However, this
|
||||
fails on recent AMD processors which use a different layout.
|
||||
Specifically, AMD Zen3 and later processors do not leave space for the
|
||||
MPX register set in between the AVX and AVX512 register sets.
|
||||
|
||||
To rectify this, add an x86_xsave_layout structure which contains the
|
||||
total size of the XSAVE extended state area as well as the offset of
|
||||
each known optional state component.
|
||||
|
||||
Subsequent commits will modify XSAVE parsing in both gdb and gdbserver
|
||||
to use x86_xsave_layout.
|
||||
|
||||
Co-authored-by: Aleksandar Paunovic <aleksandar.paunovic@intel.com>
|
||||
Approved-By: Simon Marchi <simon.marchi@efficios.com>
|
||||
|
||||
diff --git a/gdbsupport/x86-xstate.h b/gdbsupport/x86-xstate.h
|
||||
--- a/gdbsupport/x86-xstate.h
|
||||
+++ b/gdbsupport/x86-xstate.h
|
||||
@@ -20,22 +20,69 @@
|
||||
#ifndef COMMON_X86_XSTATE_H
|
||||
#define COMMON_X86_XSTATE_H
|
||||
|
||||
+/* The extended state feature IDs in the state component bitmap. */
|
||||
+#define X86_XSTATE_X87_ID 0
|
||||
+#define X86_XSTATE_SSE_ID 1
|
||||
+#define X86_XSTATE_AVX_ID 2
|
||||
+#define X86_XSTATE_BNDREGS_ID 3
|
||||
+#define X86_XSTATE_BNDCFG_ID 4
|
||||
+#define X86_XSTATE_K_ID 5
|
||||
+#define X86_XSTATE_ZMM_H_ID 6
|
||||
+#define X86_XSTATE_ZMM_ID 7
|
||||
+#define X86_XSTATE_PKRU_ID 9
|
||||
+
|
||||
/* The extended state feature bits. */
|
||||
-#define X86_XSTATE_X87 (1ULL << 0)
|
||||
-#define X86_XSTATE_SSE (1ULL << 1)
|
||||
-#define X86_XSTATE_AVX (1ULL << 2)
|
||||
-#define X86_XSTATE_BNDREGS (1ULL << 3)
|
||||
-#define X86_XSTATE_BNDCFG (1ULL << 4)
|
||||
+#define X86_XSTATE_X87 (1ULL << X86_XSTATE_X87_ID)
|
||||
+#define X86_XSTATE_SSE (1ULL << X86_XSTATE_SSE_ID)
|
||||
+#define X86_XSTATE_AVX (1ULL << X86_XSTATE_AVX_ID)
|
||||
+#define X86_XSTATE_BNDREGS (1ULL << X86_XSTATE_BNDREGS_ID)
|
||||
+#define X86_XSTATE_BNDCFG (1ULL << X86_XSTATE_BNDCFG_ID)
|
||||
#define X86_XSTATE_MPX (X86_XSTATE_BNDREGS | X86_XSTATE_BNDCFG)
|
||||
|
||||
/* AVX 512 adds three feature bits. All three must be enabled. */
|
||||
-#define X86_XSTATE_K (1ULL << 5)
|
||||
-#define X86_XSTATE_ZMM_H (1ULL << 6)
|
||||
-#define X86_XSTATE_ZMM (1ULL << 7)
|
||||
+#define X86_XSTATE_K (1ULL << X86_XSTATE_K_ID)
|
||||
+#define X86_XSTATE_ZMM_H (1ULL << X86_XSTATE_ZMM_H_ID)
|
||||
+#define X86_XSTATE_ZMM (1ULL << X86_XSTATE_ZMM_ID)
|
||||
#define X86_XSTATE_AVX512 (X86_XSTATE_K | X86_XSTATE_ZMM_H \
|
||||
| X86_XSTATE_ZMM)
|
||||
|
||||
-#define X86_XSTATE_PKRU (1ULL << 9)
|
||||
+#define X86_XSTATE_PKRU (1ULL << X86_XSTATE_PKRU_ID)
|
||||
+
|
||||
+/* Total size of the XSAVE area extended region and offsets of
|
||||
+ register states within the region. Offsets are set to 0 to
|
||||
+ indicate the absence of the associated registers. */
|
||||
+
|
||||
+struct x86_xsave_layout
|
||||
+{
|
||||
+ int sizeof_xsave;
|
||||
+ int avx_offset;
|
||||
+ int bndregs_offset;
|
||||
+ int bndcfg_offset;
|
||||
+ int k_offset;
|
||||
+ int zmm_h_offset;
|
||||
+ int zmm_offset;
|
||||
+ int pkru_offset;
|
||||
+};
|
||||
+
|
||||
+constexpr bool operator== (const x86_xsave_layout &lhs,
|
||||
+ const x86_xsave_layout &rhs)
|
||||
+{
|
||||
+ return lhs.sizeof_xsave == rhs.sizeof_xsave
|
||||
+ && lhs.avx_offset == rhs.avx_offset
|
||||
+ && lhs.bndregs_offset == rhs.bndregs_offset
|
||||
+ && lhs.bndcfg_offset == rhs.bndcfg_offset
|
||||
+ && lhs.k_offset == rhs.k_offset
|
||||
+ && lhs.zmm_h_offset == rhs.zmm_h_offset
|
||||
+ && lhs.zmm_offset == rhs.zmm_offset
|
||||
+ && lhs.pkru_offset == rhs.pkru_offset;
|
||||
+}
|
||||
+
|
||||
+constexpr bool operator!= (const x86_xsave_layout &lhs,
|
||||
+ const x86_xsave_layout &rhs)
|
||||
+{
|
||||
+ return !(lhs == rhs);
|
||||
+}
|
||||
+
|
||||
|
||||
/* Supported mask and size of the extended state. */
|
||||
#define X86_XSTATE_X87_MASK X86_XSTATE_X87
|
162
gdb-rhel-10464-xsave-update-20of21.patch
Normal file
162
gdb-rhel-10464-xsave-update-20of21.patch
Normal file
@ -0,0 +1,162 @@
|
||||
From FEDORA_PATCHES Mon Sep 17 00:00:00 2001
|
||||
From: root <root@dell-pexr7620-01.khw.eng.bos2.dc.redhat.com>
|
||||
Date: Thu, 11 Apr 2024 14:05:47 -0700
|
||||
Subject: gdb-rhel-10464-xsave-update-20of21.patch
|
||||
|
||||
;; Backport "gdb: write target description into core file"
|
||||
;; (Andrew Burgess, RHEL-10464)
|
||||
|
||||
When a core file is created from within GDB add the target description
|
||||
into a note within the core file.
|
||||
|
||||
When loading a core file, if the target description note is present
|
||||
then load the target description from the core file.
|
||||
|
||||
The benefit of this is that we can be sure that, when analysing the
|
||||
core file within GDB, that we are using the exact same target
|
||||
description as was in use at the time the core file was created.
|
||||
|
||||
GDB already supports a mechanism for figuring out the target
|
||||
description from a given corefile; gdbarch_core_read_description.
|
||||
This new mechanism (GDB adding the target description) is not going to
|
||||
replace the old mechanism. Core files generated outside of GDB will
|
||||
not include a target description, and so GDB still needs to be able to
|
||||
figure out a target description for these files.
|
||||
|
||||
My primary motivation for adding this feature is that, in a future
|
||||
commit, I will be adding support for bare metal core dumps on some
|
||||
targets. For RISC-V specifically, I want to be able to dump all the
|
||||
available control status registers. As different targets will present
|
||||
different sets of register in their target description, including
|
||||
registers that are possibly not otherwise known to GDB I wanted a way
|
||||
to capture these registers in the core dump.
|
||||
|
||||
I therefore need a mechanism to write out an arbitrary set of
|
||||
registers, and to then derive a target description from this arbitrary
|
||||
set when later loading the core file. The obvious approach (I think)
|
||||
is to just reuse the target description.
|
||||
|
||||
Once I'd decided to add support for writing out the target description
|
||||
I could either choose to make this RISC-V only, or make it generic. I
|
||||
figure that having the target description in the core file doesn't
|
||||
hurt, and _might_ be helpful. So that's how I got here, general
|
||||
support for including the target description in GDB generated core
|
||||
files.
|
||||
|
||||
In previous versions of this patch I added the target description from
|
||||
generic code (in gcore.c). However, doing this creates a dependency
|
||||
between GDB's common code and bfd ELF support. As ELF support in gdb
|
||||
is optional (for example the target x86_64-apple-darwin20.3.0 does not
|
||||
include ELF support) then having gcore.c require ELF support would
|
||||
break the GDB build in some cases.
|
||||
|
||||
Instead, in this version of the patch, writing the target description
|
||||
note is done from each specific targets make notes function. Each of
|
||||
these now calls a common function in gcore-elf.c (which is only linked
|
||||
in when bfd has ELF support). And so only targets that are ELF based
|
||||
will call the new function and we can therefore avoid an unconditional
|
||||
dependency on ELF support.
|
||||
|
||||
diff --git a/gdb/corelow.c b/gdb/corelow.c
|
||||
--- a/gdb/corelow.c
|
||||
+++ b/gdb/corelow.c
|
||||
@@ -54,6 +54,7 @@
|
||||
#include <unordered_map>
|
||||
#include <unordered_set>
|
||||
#include "gdbcmd.h"
|
||||
+#include "xml-tdesc.h"
|
||||
|
||||
#ifndef O_LARGEFILE
|
||||
#define O_LARGEFILE 0
|
||||
@@ -1032,6 +1033,29 @@ core_target::thread_alive (ptid_t ptid)
|
||||
const struct target_desc *
|
||||
core_target::read_description ()
|
||||
{
|
||||
+ /* If the core file contains a target description note then we will use
|
||||
+ that in preference to anything else. */
|
||||
+ bfd_size_type tdesc_note_size = 0;
|
||||
+ struct bfd_section *tdesc_note_section
|
||||
+ = bfd_get_section_by_name (core_bfd, ".gdb-tdesc");
|
||||
+ if (tdesc_note_section != nullptr)
|
||||
+ tdesc_note_size = bfd_section_size (tdesc_note_section);
|
||||
+ if (tdesc_note_size > 0)
|
||||
+ {
|
||||
+ gdb::char_vector contents (tdesc_note_size + 1);
|
||||
+ if (bfd_get_section_contents (core_bfd, tdesc_note_section,
|
||||
+ contents.data (), (file_ptr) 0,
|
||||
+ tdesc_note_size))
|
||||
+ {
|
||||
+ /* Ensure we have a null terminator. */
|
||||
+ contents[tdesc_note_size] = '\0';
|
||||
+ const struct target_desc *result
|
||||
+ = string_read_description_xml (contents.data ());
|
||||
+ if (result != nullptr)
|
||||
+ return result;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
if (m_core_gdbarch && gdbarch_core_read_description_p (m_core_gdbarch))
|
||||
{
|
||||
const struct target_desc *result;
|
||||
diff --git a/gdb/linux-tdep.c b/gdb/linux-tdep.c
|
||||
--- a/gdb/linux-tdep.c
|
||||
+++ b/gdb/linux-tdep.c
|
||||
@@ -39,6 +39,7 @@
|
||||
#include "gdb_regex.h"
|
||||
#include "gdbsupport/enum-flags.h"
|
||||
#include "gdbsupport/gdb_optional.h"
|
||||
+#include "gdbsupport/tdesc.h"
|
||||
|
||||
#include <ctype.h>
|
||||
|
||||
@@ -1968,6 +1969,40 @@ find_signalled_thread ()
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
+/* Add content to *NOTE_DATA (and update *NOTE_SIZE) to include a note
|
||||
+ containing the current targtet's target description. The core file is
|
||||
+ being written to OBFD. If something goes wrong then *NOTE_DATA can be
|
||||
+ set to nullptr. */
|
||||
+
|
||||
+static char *
|
||||
+gcore_elf_make_tdesc_note (bfd *obfd,
|
||||
+ char *note_data,
|
||||
+ int *note_size)
|
||||
+{
|
||||
+ /* Append the target description to the core file. */
|
||||
+ const struct target_desc *tdesc = gdbarch_target_desc (target_gdbarch ());
|
||||
+ const char *tdesc_xml
|
||||
+ = tdesc == nullptr ? nullptr : tdesc_get_features_xml (tdesc);
|
||||
+ if (tdesc_xml != nullptr && *tdesc_xml != '\0')
|
||||
+ {
|
||||
+ /* Skip the leading '@'. */
|
||||
+ if (*tdesc_xml == '@')
|
||||
+ ++tdesc_xml;
|
||||
+
|
||||
+ /* Include the null terminator in the length. */
|
||||
+ size_t tdesc_len = strlen (tdesc_xml) + 1;
|
||||
+
|
||||
+ /* Now add the target description into the core file. */
|
||||
+ note_data = elfcore_write_register_note (obfd,
|
||||
+ note_data,
|
||||
+ note_size,
|
||||
+ ".gdb-tdesc", tdesc_xml,
|
||||
+ tdesc_len);
|
||||
+ }
|
||||
+
|
||||
+ return note_data;
|
||||
+}
|
||||
+
|
||||
/* Build the note section for a corefile, and return it in a malloc
|
||||
buffer. */
|
||||
|
||||
@@ -2048,6 +2083,9 @@ linux_make_corefile_notes (struct gdbarch *gdbarch, bfd *obfd, int *note_size)
|
||||
note_data = linux_make_mappings_corefile_notes (gdbarch, obfd,
|
||||
note_data, note_size);
|
||||
|
||||
+ /* Target description. */
|
||||
+ note_data = gcore_elf_make_tdesc_note (obfd, note_data, note_size);
|
||||
+
|
||||
return note_data;
|
||||
}
|
||||
|
66
gdb-rhel-10464-xsave-update-21of21.patch
Normal file
66
gdb-rhel-10464-xsave-update-21of21.patch
Normal file
@ -0,0 +1,66 @@
|
||||
From FEDORA_PATCHES Mon Sep 17 00:00:00 2001
|
||||
From: root <root@dell-pexr7620-01.khw.eng.bos2.dc.redhat.com>
|
||||
Date: Thu, 11 Apr 2024 14:05:47 -0700
|
||||
Subject: gdb-rhel-10464-xsave-update-21of21.patch
|
||||
|
||||
;; Backport "gdb/corefile: write NT_GDB_TDESC based on signalled thread"
|
||||
;; (Andrew Burgess, RHEL-10464)
|
||||
|
||||
When creating a core file from within GDB we include a NT_GDB_TDESC
|
||||
that includes the target description of the architecture in use.
|
||||
|
||||
For architectures with dynamic architectures (e.g. AArch64 with
|
||||
sve/sme) the original architecture, calculated from the original
|
||||
target description, might not match the per-thread architecture.
|
||||
|
||||
In the general case, where each thread has a different architecture,
|
||||
then we really need a separate NT_GDB_TDESC for each thread, however,
|
||||
there's currently no way to read in multiple NT_GDB_TDESC.
|
||||
|
||||
This commit is a step towards per-thread NT_GDB_TDESC. In this commit
|
||||
I have updated the function that writes the NT_GDB_TDESC to accept a
|
||||
gdbarch (rather than calling target_gdbarch() to find a gdbarch), and
|
||||
I now pass in the gdbarch of the signalled thread.
|
||||
|
||||
In many cases (though NOT all) targets with dynamic architectures
|
||||
really only use a single architecture, even when there are multiple
|
||||
threads, so in the common case, this should ensure that GDB emits an
|
||||
architecture that is more likely to be correct.
|
||||
|
||||
Additional work will be needed in order to support corefiles with
|
||||
truly per-thread architectures, but that will need to be done in the
|
||||
future.
|
||||
|
||||
diff --git a/gdb/linux-tdep.c b/gdb/linux-tdep.c
|
||||
--- a/gdb/linux-tdep.c
|
||||
+++ b/gdb/linux-tdep.c
|
||||
@@ -1975,12 +1975,12 @@ find_signalled_thread ()
|
||||
set to nullptr. */
|
||||
|
||||
static char *
|
||||
-gcore_elf_make_tdesc_note (bfd *obfd,
|
||||
+gcore_elf_make_tdesc_note (struct gdbarch *gdbarch, bfd *obfd,
|
||||
char *note_data,
|
||||
int *note_size)
|
||||
{
|
||||
/* Append the target description to the core file. */
|
||||
- const struct target_desc *tdesc = gdbarch_target_desc (target_gdbarch ());
|
||||
+ const struct target_desc *tdesc = gdbarch_target_desc (gdbarch);
|
||||
const char *tdesc_xml
|
||||
= tdesc == nullptr ? nullptr : tdesc_get_features_xml (tdesc);
|
||||
if (tdesc_xml != nullptr && *tdesc_xml != '\0')
|
||||
@@ -2083,8 +2083,12 @@ linux_make_corefile_notes (struct gdbarch *gdbarch, bfd *obfd, int *note_size)
|
||||
note_data = linux_make_mappings_corefile_notes (gdbarch, obfd,
|
||||
note_data, note_size);
|
||||
|
||||
- /* Target description. */
|
||||
- note_data = gcore_elf_make_tdesc_note (obfd, note_data, note_size);
|
||||
+ /* Include the target description when possible. Some architectures
|
||||
+ allow for per-thread gdbarch so we should really be emitting a tdesc
|
||||
+ per-thread, however, we don't currently support reading in a
|
||||
+ per-thread tdesc, so just emit the tdesc for the signalled thread. */
|
||||
+ gdbarch = target_thread_architecture (signalled_thr->ptid);
|
||||
+ note_data = gcore_elf_make_tdesc_note (gdbarch, obfd, note_data, note_size);
|
||||
|
||||
return note_data;
|
||||
}
|
190
gdb-rhel-10464-xsave-update-2of21.patch
Normal file
190
gdb-rhel-10464-xsave-update-2of21.patch
Normal file
@ -0,0 +1,190 @@
|
||||
From FEDORA_PATCHES Mon Sep 17 00:00:00 2001
|
||||
From: Keith Seitz <keiths@redhat.com>
|
||||
Date: Thu, 11 Apr 2024 14:05:42 -0700
|
||||
Subject: gdb-rhel-10464-xsave-update-2of21.patch
|
||||
|
||||
;; Backport "gdb: Store an x86_xsave_layout in i386_gdbarch_tdep."
|
||||
;; (John Baldwin, RHEL-10464)
|
||||
|
||||
This structure is fetched from the current target in i386_gdbarch_init
|
||||
via a new "fetch_x86_xsave_layout" target method.
|
||||
|
||||
Approved-By: Simon Marchi <simon.marchi@efficios.com>
|
||||
|
||||
diff --git a/gdb/i386-tdep.c b/gdb/i386-tdep.c
|
||||
--- a/gdb/i386-tdep.c
|
||||
+++ b/gdb/i386-tdep.c
|
||||
@@ -8456,10 +8456,20 @@ i386_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
|
||||
int bnd0_regnum;
|
||||
int num_bnd_cooked;
|
||||
|
||||
+ x86_xsave_layout xsave_layout = target_fetch_x86_xsave_layout ();
|
||||
+
|
||||
/* If there is already a candidate, use it. */
|
||||
- arches = gdbarch_list_lookup_by_info (arches, &info);
|
||||
- if (arches != NULL)
|
||||
- return arches->gdbarch;
|
||||
+ for (arches = gdbarch_list_lookup_by_info (arches, &info);
|
||||
+ arches != NULL;
|
||||
+ arches = gdbarch_list_lookup_by_info (arches->next, &info))
|
||||
+ {
|
||||
+ /* Check that the XSAVE layout of ARCHES matches the layout for
|
||||
+ the current target. */
|
||||
+ struct gdbarch_tdep *other_tdep = gdbarch_tdep (arches->gdbarch);
|
||||
+
|
||||
+ if (other_tdep->xsave_layout == xsave_layout)
|
||||
+ return arches->gdbarch;
|
||||
+ }
|
||||
|
||||
/* Allocate space for the new architecture. Assume i386 for now. */
|
||||
tdep = XCNEW (struct gdbarch_tdep);
|
||||
@@ -8711,6 +8721,7 @@ i386_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
|
||||
gdbarch_free (gdbarch);
|
||||
return NULL;
|
||||
}
|
||||
+ tdep->xsave_layout = xsave_layout;
|
||||
|
||||
num_bnd_cooked = (tdep->bnd0r_regnum > 0 ? I387_NUM_BND_REGS : 0);
|
||||
|
||||
diff --git a/gdb/i386-tdep.h b/gdb/i386-tdep.h
|
||||
--- a/gdb/i386-tdep.h
|
||||
+++ b/gdb/i386-tdep.h
|
||||
@@ -22,6 +22,7 @@
|
||||
|
||||
#include "gdbarch.h"
|
||||
#include "infrun.h"
|
||||
+#include "gdbsupport/x86-xstate.h"
|
||||
|
||||
struct frame_info;
|
||||
struct gdbarch;
|
||||
@@ -144,6 +145,9 @@ struct gdbarch_tdep
|
||||
/* Offset of XCR0 in XSAVE extended state. */
|
||||
int xsave_xcr0_offset;
|
||||
|
||||
+ /* Layout of the XSAVE area extended region. */
|
||||
+ x86_xsave_layout xsave_layout;
|
||||
+
|
||||
/* Register names. */
|
||||
const char **register_names;
|
||||
|
||||
diff --git a/gdb/target-debug.h b/gdb/target-debug.h
|
||||
--- a/gdb/target-debug.h
|
||||
+++ b/gdb/target-debug.h
|
||||
@@ -226,4 +226,23 @@ target_debug_print_signals (gdb::array_view<const unsigned char> sigs)
|
||||
fputs_unfiltered (" }", gdb_stdlog);
|
||||
}
|
||||
|
||||
+static void
|
||||
+target_debug_print_x86_xsave_layout (const x86_xsave_layout &layout)
|
||||
+{
|
||||
+ fputs_unfiltered ("{", gdb_stdlog);
|
||||
+ fprintf_unfiltered (gdb_stdlog, " sizeof_xsave=%d", layout.sizeof_xsave);
|
||||
+#define POFFS(region) \
|
||||
+ if (layout.region##_offset != 0) \
|
||||
+ fprintf_unfiltered (gdb_stdlog, ", %s_offset=%d", #region, \
|
||||
+ layout.region##_offset)
|
||||
+ POFFS(avx);
|
||||
+ POFFS(bndregs);
|
||||
+ POFFS(bndcfg);
|
||||
+ POFFS(k);
|
||||
+ POFFS(zmm_h);
|
||||
+ POFFS(zmm);
|
||||
+ POFFS(pkru);
|
||||
+#undef POFFS
|
||||
+ fputs_unfiltered (" }", gdb_stdlog);
|
||||
+}
|
||||
#endif /* TARGET_DEBUG_H */
|
||||
diff --git a/gdb/target-delegates.c b/gdb/target-delegates.c
|
||||
--- a/gdb/target-delegates.c
|
||||
+++ b/gdb/target-delegates.c
|
||||
@@ -173,6 +173,7 @@ struct dummy_target : public target_ops
|
||||
const struct frame_unwind *get_tailcall_unwinder () override;
|
||||
void prepare_to_generate_core () override;
|
||||
void done_generating_core () override;
|
||||
+ x86_xsave_layout fetch_x86_xsave_layout () override;
|
||||
};
|
||||
|
||||
struct debug_target : public target_ops
|
||||
@@ -344,6 +345,7 @@ struct debug_target : public target_ops
|
||||
const struct frame_unwind *get_tailcall_unwinder () override;
|
||||
void prepare_to_generate_core () override;
|
||||
void done_generating_core () override;
|
||||
+ x86_xsave_layout fetch_x86_xsave_layout () override;
|
||||
};
|
||||
|
||||
void
|
||||
@@ -4413,3 +4415,27 @@ debug_target::done_generating_core ()
|
||||
fputs_unfiltered (")\n", gdb_stdlog);
|
||||
}
|
||||
|
||||
+x86_xsave_layout
|
||||
+target_ops::fetch_x86_xsave_layout ()
|
||||
+{
|
||||
+ return this->beneath ()->fetch_x86_xsave_layout ();
|
||||
+}
|
||||
+
|
||||
+x86_xsave_layout
|
||||
+dummy_target::fetch_x86_xsave_layout ()
|
||||
+{
|
||||
+ return x86_xsave_layout ();
|
||||
+}
|
||||
+
|
||||
+x86_xsave_layout
|
||||
+debug_target::fetch_x86_xsave_layout ()
|
||||
+{
|
||||
+ x86_xsave_layout result;
|
||||
+ fprintf_unfiltered (gdb_stdlog, "-> %s->fetch_x86_xsave_layout (...)\n", this->beneath ()->shortname ());
|
||||
+ result = this->beneath ()->fetch_x86_xsave_layout ();
|
||||
+ fprintf_unfiltered (gdb_stdlog, "<- %s->fetch_x86_xsave_layout (", this->beneath ()->shortname ());
|
||||
+ fputs_unfiltered (") = ", gdb_stdlog);
|
||||
+ target_debug_print_x86_xsave_layout (result);
|
||||
+ fputs_unfiltered ("\n", gdb_stdlog);
|
||||
+ return result;
|
||||
+}
|
||||
diff --git a/gdb/target.c b/gdb/target.c
|
||||
--- a/gdb/target.c
|
||||
+++ b/gdb/target.c
|
||||
@@ -227,6 +227,12 @@ target_has_execution_current (void)
|
||||
return target_has_execution_1 (current_inferior ());
|
||||
}
|
||||
|
||||
+x86_xsave_layout
|
||||
+target_fetch_x86_xsave_layout ()
|
||||
+{
|
||||
+ return current_inferior ()->top_target ()->fetch_x86_xsave_layout ();
|
||||
+}
|
||||
+
|
||||
/* This is used to implement the various target commands. */
|
||||
|
||||
static void
|
||||
diff --git a/gdb/target.h b/gdb/target.h
|
||||
--- a/gdb/target.h
|
||||
+++ b/gdb/target.h
|
||||
@@ -81,6 +81,7 @@ struct inferior;
|
||||
#include "command.h"
|
||||
#include "disasm.h"
|
||||
#include "tracepoint.h"
|
||||
+#include "gdbsupport/x86-xstate.h"
|
||||
|
||||
#include "gdbsupport/break-common.h" /* For enum target_hw_bp_type. */
|
||||
|
||||
@@ -1260,6 +1261,10 @@ struct target_ops
|
||||
/* Cleanup after generating a core file. */
|
||||
virtual void done_generating_core ()
|
||||
TARGET_DEFAULT_IGNORE ();
|
||||
+
|
||||
+ /* Return the x86 XSAVE extended state area layout. */
|
||||
+ virtual x86_xsave_layout fetch_x86_xsave_layout ()
|
||||
+ TARGET_DEFAULT_RETURN (x86_xsave_layout ());
|
||||
};
|
||||
|
||||
/* Deleter for std::unique_ptr. See comments in
|
||||
@@ -2326,6 +2331,8 @@ extern gdb::unique_xmalloc_ptr<char> target_fileio_read_stralloc
|
||||
#define target_augmented_libraries_svr4_read() \
|
||||
(current_top_target ()->augmented_libraries_svr4_read) ()
|
||||
|
||||
+extern x86_xsave_layout target_fetch_x86_xsave_layout ();
|
||||
+
|
||||
/* Command logging facility. */
|
||||
|
||||
#define target_log_command(p) \
|
269
gdb-rhel-10464-xsave-update-3of21.patch
Normal file
269
gdb-rhel-10464-xsave-update-3of21.patch
Normal file
@ -0,0 +1,269 @@
|
||||
From FEDORA_PATCHES Mon Sep 17 00:00:00 2001
|
||||
From: John Baldwin <jhb@FreeBSD.org>
|
||||
Date: Thu, 11 Apr 2024 14:05:42 -0700
|
||||
Subject: gdb-rhel-10464-xsave-update-3of21.patch
|
||||
|
||||
;; Backport "core: Support fetching x86 XSAVE layout from architectures."
|
||||
;; (John Baldwin, RHEL-10464)
|
||||
|
||||
Add gdbarch_core_read_x86_xsave_layout to fetch the x86 XSAVE layout
|
||||
structure from a core file.
|
||||
|
||||
Current OS's do not export the offsets of XSAVE state components in
|
||||
core dumps, so provide an i387_guess_xsave_layout helper function to
|
||||
set offsets based on known combinations of XCR0 masks and total state
|
||||
sizes. Eventually when core dumps do contain this information this
|
||||
function should only be used as a fall back for older core dumps.
|
||||
|
||||
Approved-By: Simon Marchi <simon.marchi@efficios.com>
|
||||
Please enter the commit message for your changes. Lines starting
|
||||
|
||||
diff --git a/gdb/corelow.c b/gdb/corelow.c
|
||||
--- a/gdb/corelow.c
|
||||
+++ b/gdb/corelow.c
|
||||
@@ -50,6 +50,7 @@
|
||||
#include "gdbsupport/filestuff.h"
|
||||
#include "build-id.h"
|
||||
#include "gdbsupport/pathstuff.h"
|
||||
+#include "gdbsupport/x86-xstate.h"
|
||||
#include <unordered_map>
|
||||
#include <unordered_set>
|
||||
#include "gdbcmd.h"
|
||||
@@ -103,6 +104,8 @@ class core_target final : public process_stratum_target
|
||||
|
||||
bool info_proc (const char *, enum info_proc_what) override;
|
||||
|
||||
+ x86_xsave_layout fetch_x86_xsave_layout () override;
|
||||
+
|
||||
/* A few helpers. */
|
||||
|
||||
/* Getter, see variable definition. */
|
||||
@@ -1113,6 +1116,25 @@ core_target::info_proc (const char *args, enum info_proc_what request)
|
||||
return true;
|
||||
}
|
||||
|
||||
+/* Implementation of the "fetch_x86_xsave_layout" target_ops method. */
|
||||
+
|
||||
+x86_xsave_layout
|
||||
+core_target::fetch_x86_xsave_layout ()
|
||||
+{
|
||||
+ if (m_core_gdbarch != nullptr &&
|
||||
+ gdbarch_core_read_x86_xsave_layout_p (m_core_gdbarch))
|
||||
+ {
|
||||
+ x86_xsave_layout layout;
|
||||
+ memset (&layout, 0, sizeof (x86_xsave_layout));
|
||||
+ if (!gdbarch_core_read_x86_xsave_layout (m_core_gdbarch, layout))
|
||||
+ return {};
|
||||
+
|
||||
+ return layout;
|
||||
+ }
|
||||
+
|
||||
+ return {};
|
||||
+}
|
||||
+
|
||||
/* Get a pointer to the current core target. If not connected to a
|
||||
core target, return NULL. */
|
||||
|
||||
diff --git a/gdb/gdbarch.c b/gdb/gdbarch.c
|
||||
--- a/gdb/gdbarch.c
|
||||
+++ b/gdb/gdbarch.c
|
||||
@@ -282,6 +282,7 @@ struct gdbarch
|
||||
gdbarch_core_pid_to_str_ftype *core_pid_to_str;
|
||||
gdbarch_core_thread_name_ftype *core_thread_name;
|
||||
gdbarch_core_xfer_siginfo_ftype *core_xfer_siginfo;
|
||||
+ gdbarch_core_read_x86_xsave_layout_ftype *core_read_x86_xsave_layout;
|
||||
const char * gcore_bfd_target;
|
||||
int vtable_function_descriptors;
|
||||
int vbit_in_delta;
|
||||
@@ -652,6 +653,7 @@ verify_gdbarch (struct gdbarch *gdbarch)
|
||||
/* Skip verify of core_pid_to_str, has predicate. */
|
||||
/* Skip verify of core_thread_name, has predicate. */
|
||||
/* Skip verify of core_xfer_siginfo, has predicate. */
|
||||
+ /* Skip verify of core_read_x86_xsave_layout, has predicate. */
|
||||
/* Skip verify of gcore_bfd_target, has predicate. */
|
||||
/* Skip verify of vtable_function_descriptors, invalid_p == 0 */
|
||||
/* Skip verify of vbit_in_delta, invalid_p == 0 */
|
||||
@@ -879,6 +881,12 @@ gdbarch_dump (struct gdbarch *gdbarch, struct ui_file *file)
|
||||
fprintf_unfiltered (file,
|
||||
"gdbarch_dump: core_read_description = <%s>\n",
|
||||
host_address_to_string (gdbarch->core_read_description));
|
||||
+ fprintf_unfiltered (file,
|
||||
+ "gdbarch_dump: gdbarch_core_read_x86_xsave_layout_p() = %d\n",
|
||||
+ gdbarch_core_read_x86_xsave_layout_p (gdbarch));
|
||||
+ fprintf_unfiltered (file,
|
||||
+ "gdbarch_dump: core_read_x86_xsave_layout = <%s>\n",
|
||||
+ host_address_to_string (gdbarch->core_read_x86_xsave_layout));
|
||||
fprintf_unfiltered (file,
|
||||
"gdbarch_dump: gdbarch_core_thread_name_p() = %d\n",
|
||||
gdbarch_core_thread_name_p (gdbarch));
|
||||
@@ -3861,6 +3869,30 @@ set_gdbarch_core_xfer_siginfo (struct gdbarch *gdbarch,
|
||||
gdbarch->core_xfer_siginfo = core_xfer_siginfo;
|
||||
}
|
||||
|
||||
+int
|
||||
+gdbarch_core_read_x86_xsave_layout_p (struct gdbarch *gdbarch)
|
||||
+{
|
||||
+ gdb_assert (gdbarch != NULL);
|
||||
+ return gdbarch->core_read_x86_xsave_layout != NULL;
|
||||
+}
|
||||
+
|
||||
+bool
|
||||
+gdbarch_core_read_x86_xsave_layout (struct gdbarch *gdbarch, x86_xsave_layout &xsave_layout)
|
||||
+{
|
||||
+ gdb_assert (gdbarch != NULL);
|
||||
+ gdb_assert (gdbarch->core_read_x86_xsave_layout != NULL);
|
||||
+ if (gdbarch_debug >= 2)
|
||||
+ fprintf_unfiltered (gdb_stdlog, "gdbarch_core_read_x86_xsave_layout called\n");
|
||||
+ return gdbarch->core_read_x86_xsave_layout (gdbarch, xsave_layout);
|
||||
+}
|
||||
+
|
||||
+void
|
||||
+set_gdbarch_core_read_x86_xsave_layout (struct gdbarch *gdbarch,
|
||||
+ gdbarch_core_read_x86_xsave_layout_ftype core_read_x86_xsave_layout)
|
||||
+{
|
||||
+ gdbarch->core_read_x86_xsave_layout = core_read_x86_xsave_layout;
|
||||
+}
|
||||
+
|
||||
int
|
||||
gdbarch_gcore_bfd_target_p (struct gdbarch *gdbarch)
|
||||
{
|
||||
diff --git a/gdb/gdbarch.h b/gdb/gdbarch.h
|
||||
--- a/gdb/gdbarch.h
|
||||
+++ b/gdb/gdbarch.h
|
||||
@@ -57,6 +57,7 @@ struct mem_range;
|
||||
struct syscalls_info;
|
||||
struct thread_info;
|
||||
struct ui_out;
|
||||
+struct x86_xsave_layout;
|
||||
|
||||
#include "regcache.h"
|
||||
|
||||
@@ -971,6 +972,15 @@ typedef LONGEST (gdbarch_core_xfer_siginfo_ftype) (struct gdbarch *gdbarch, gdb_
|
||||
extern LONGEST gdbarch_core_xfer_siginfo (struct gdbarch *gdbarch, gdb_byte *readbuf, ULONGEST offset, ULONGEST len);
|
||||
extern void set_gdbarch_core_xfer_siginfo (struct gdbarch *gdbarch, gdbarch_core_xfer_siginfo_ftype *core_xfer_siginfo);
|
||||
|
||||
+/* Read x86 XSAVE layout information from core file into XSAVE_LAYOUT.
|
||||
+ Returns true if the layout was read successfully. */
|
||||
+
|
||||
+extern int gdbarch_core_read_x86_xsave_layout_p (struct gdbarch *gdbarch);
|
||||
+
|
||||
+typedef bool (gdbarch_core_read_x86_xsave_layout_ftype) (struct gdbarch *gdbarch, x86_xsave_layout &xsave_layout);
|
||||
+extern bool gdbarch_core_read_x86_xsave_layout (struct gdbarch *gdbarch, x86_xsave_layout &xsave_layout);
|
||||
+extern void set_gdbarch_core_read_x86_xsave_layout (struct gdbarch *gdbarch, gdbarch_core_read_x86_xsave_layout_ftype *core_read_x86_xsave_layout);
|
||||
+
|
||||
/* BFD target to use when generating a core file. */
|
||||
|
||||
extern int gdbarch_gcore_bfd_target_p (struct gdbarch *gdbarch);
|
||||
diff --git a/gdb/gdbarch.sh b/gdb/gdbarch.sh
|
||||
--- a/gdb/gdbarch.sh
|
||||
+++ b/gdb/gdbarch.sh
|
||||
@@ -742,6 +742,10 @@ M;const char *;core_thread_name;struct thread_info *thr;thr
|
||||
# of bytes read (zero indicates EOF, a negative value indicates failure).
|
||||
M;LONGEST;core_xfer_siginfo;gdb_byte *readbuf, ULONGEST offset, ULONGEST len; readbuf, offset, len
|
||||
|
||||
+# Read x86 XSAVE layout information from core file into XSAVE_LAYOUT.
|
||||
+# Returns true if the layout was read successfully.
|
||||
+M;bool;core_read_x86_xsave_layout;x86_xsave_layout &xsave_layout;xsave_layout
|
||||
+
|
||||
# BFD target to use when generating a core file.
|
||||
V;const char *;gcore_bfd_target;;;0;0;;;pstring (gdbarch->gcore_bfd_target)
|
||||
|
||||
@@ -1297,6 +1301,7 @@ struct mem_range;
|
||||
struct syscalls_info;
|
||||
struct thread_info;
|
||||
struct ui_out;
|
||||
+struct x86_xsave_layout;
|
||||
|
||||
#include "regcache.h"
|
||||
|
||||
diff --git a/gdb/i387-tdep.c b/gdb/i387-tdep.c
|
||||
--- a/gdb/i387-tdep.c
|
||||
+++ b/gdb/i387-tdep.c
|
||||
@@ -893,6 +893,61 @@ static int xsave_pkeys_offset[] =
|
||||
(xsave + xsave_pkeys_offset[regnum - I387_PKRU_REGNUM (tdep)])
|
||||
|
||||
|
||||
+/* See i387-tdep.h. */
|
||||
+
|
||||
+bool
|
||||
+i387_guess_xsave_layout (uint64_t xcr0, size_t xsave_size,
|
||||
+ x86_xsave_layout &layout)
|
||||
+{
|
||||
+ if (HAS_PKRU (xcr0) && xsave_size == 2696)
|
||||
+ {
|
||||
+ /* Intel CPUs supporting PKRU. */
|
||||
+ layout.avx_offset = 576;
|
||||
+ layout.bndregs_offset = 960;
|
||||
+ layout.bndcfg_offset = 1024;
|
||||
+ layout.k_offset = 1088;
|
||||
+ layout.zmm_h_offset = 1152;
|
||||
+ layout.zmm_offset = 1664;
|
||||
+ layout.pkru_offset = 2688;
|
||||
+ }
|
||||
+ else if (HAS_PKRU (xcr0) && xsave_size == 2440)
|
||||
+ {
|
||||
+ /* AMD CPUs supporting PKRU. */
|
||||
+ layout.avx_offset = 576;
|
||||
+ layout.k_offset = 832;
|
||||
+ layout.zmm_h_offset = 896;
|
||||
+ layout.zmm_offset = 1408;
|
||||
+ layout.pkru_offset = 2432;
|
||||
+ }
|
||||
+ else if (HAS_AVX512 (xcr0) && xsave_size == 2688)
|
||||
+ {
|
||||
+ /* Intel CPUs supporting AVX512. */
|
||||
+ layout.avx_offset = 576;
|
||||
+ layout.bndregs_offset = 960;
|
||||
+ layout.bndcfg_offset = 1024;
|
||||
+ layout.k_offset = 1088;
|
||||
+ layout.zmm_h_offset = 1152;
|
||||
+ layout.zmm_offset = 1664;
|
||||
+ }
|
||||
+ else if (HAS_MPX (xcr0) && xsave_size == 1088)
|
||||
+ {
|
||||
+ /* Intel CPUs supporting MPX. */
|
||||
+ layout.avx_offset = 576;
|
||||
+ layout.bndregs_offset = 960;
|
||||
+ layout.bndcfg_offset = 1024;
|
||||
+ }
|
||||
+ else if (HAS_AVX (xcr0) && xsave_size == 832)
|
||||
+ {
|
||||
+ /* Intel and AMD CPUs supporting AVX. */
|
||||
+ layout.avx_offset = 576;
|
||||
+ }
|
||||
+ else
|
||||
+ return false;
|
||||
+
|
||||
+ layout.sizeof_xsave = xsave_size;
|
||||
+ return true;
|
||||
+}
|
||||
+
|
||||
/* Extract from XSAVE a bitset of the features that are available on the
|
||||
target, but which have not yet been enabled. */
|
||||
|
||||
diff --git a/gdb/i387-tdep.h b/gdb/i387-tdep.h
|
||||
--- a/gdb/i387-tdep.h
|
||||
+++ b/gdb/i387-tdep.h
|
||||
@@ -25,6 +25,7 @@ struct frame_info;
|
||||
struct regcache;
|
||||
struct type;
|
||||
struct ui_file;
|
||||
+struct x86_xsave_layout;
|
||||
|
||||
/* Number of i387 floating point registers. */
|
||||
#define I387_NUM_REGS 16
|
||||
@@ -138,6 +139,14 @@ extern void i387_collect_fsave (const struct regcache *regcache, int regnum,
|
||||
extern void i387_supply_fxsave (struct regcache *regcache, int regnum,
|
||||
const void *fxsave);
|
||||
|
||||
+/* Select an XSAVE layout based on the XCR0 bitmask and total XSAVE
|
||||
+ extended state size. Returns true if the bitmask and size matched
|
||||
+ a known layout. */
|
||||
+
|
||||
+extern bool i387_guess_xsave_layout (uint64_t xcr0, size_t xsave_size,
|
||||
+ x86_xsave_layout &layout);
|
||||
+
|
||||
+
|
||||
/* Similar to i387_supply_fxsave, but use XSAVE extended state. */
|
||||
|
||||
extern void i387_supply_xsave (struct regcache *regcache, int regnum,
|
79
gdb-rhel-10464-xsave-update-4of21.patch
Normal file
79
gdb-rhel-10464-xsave-update-4of21.patch
Normal file
@ -0,0 +1,79 @@
|
||||
From FEDORA_PATCHES Mon Sep 17 00:00:00 2001
|
||||
From: John Baldwin <jhb@FreeBSD.org>
|
||||
Date: Thu, 11 Apr 2024 14:05:43 -0700
|
||||
Subject: gdb-rhel-10464-xsave-update-4of21.patch
|
||||
|
||||
;; Backport "nat/x86--cpuid.h: Add x86_cpuid_count wrapper around
|
||||
;; __get_cpuid_count."
|
||||
;; (John Baldwin, RHEL-10464)
|
||||
|
||||
Approved-By: Simon Marchi <simon.marchi@efficios.com>
|
||||
|
||||
diff --git a/gdb/nat/x86-cpuid.h b/gdb/nat/x86-cpuid.h
|
||||
--- a/gdb/nat/x86-cpuid.h
|
||||
+++ b/gdb/nat/x86-cpuid.h
|
||||
@@ -22,6 +22,12 @@
|
||||
/* Always include the header for the cpu bit defines. */
|
||||
#include "x86-gcc-cpuid.h"
|
||||
|
||||
+#ifndef __cplusplus
|
||||
+/* This header file is also used in C code for some test-cases, so define
|
||||
+ nullptr in C terms to avoid a compilation error. */
|
||||
+#define nullptr ((void *) 0)
|
||||
+#endif
|
||||
+
|
||||
#if defined(__i386__) || defined(__x86_64__)
|
||||
|
||||
/* Return cpuid data for requested cpuid level, as found in returned
|
||||
@@ -48,6 +54,30 @@ x86_cpuid (unsigned int __level,
|
||||
return __get_cpuid (__level, __eax, __ebx, __ecx, __edx);
|
||||
}
|
||||
|
||||
+/* Return cpuid data for requested cpuid level and sub-level, as found
|
||||
+ in returned eax, ebx, ecx and edx registers. The function checks
|
||||
+ if cpuid is supported and returns 1 for valid cpuid information or
|
||||
+ 0 for unsupported cpuid level. Pointers may be non-null. */
|
||||
+
|
||||
+static __inline int
|
||||
+x86_cpuid_count (unsigned int __level, unsigned int __sublevel,
|
||||
+ unsigned int *__eax, unsigned int *__ebx,
|
||||
+ unsigned int *__ecx, unsigned int *__edx)
|
||||
+{
|
||||
+ unsigned int __scratch;
|
||||
+
|
||||
+ if (__eax == nullptr)
|
||||
+ __eax = &__scratch;
|
||||
+ if (__ebx == nullptr)
|
||||
+ __ebx = &__scratch;
|
||||
+ if (__ecx == nullptr)
|
||||
+ __ecx = &__scratch;
|
||||
+ if (__edx == nullptr)
|
||||
+ __edx = &__scratch;
|
||||
+
|
||||
+ return __get_cpuid_count (__level, __sublevel, __eax, __ebx, __ecx, __edx);
|
||||
+}
|
||||
+
|
||||
#else
|
||||
|
||||
static __inline int
|
||||
@@ -58,6 +88,20 @@ x86_cpuid (unsigned int __level,
|
||||
return 0;
|
||||
}
|
||||
|
||||
+static __inline int
|
||||
+x86_cpuid_count (unsigned int __level, unsigned int __sublevel,
|
||||
+ unsigned int *__eax, unsigned int *__ebx,
|
||||
+ unsigned int *__ecx, unsigned int *__edx)
|
||||
+{
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
#endif /* i386 && x86_64 */
|
||||
|
||||
+#ifndef __cplusplus
|
||||
+/* Avoid leaking this local definition beyond the scope of this header
|
||||
+ file. */
|
||||
+#undef nullptr
|
||||
+#endif
|
||||
+
|
||||
#endif /* NAT_X86_CPUID_H */
|
133
gdb-rhel-10464-xsave-update-5of21.patch
Normal file
133
gdb-rhel-10464-xsave-update-5of21.patch
Normal file
@ -0,0 +1,133 @@
|
||||
From FEDORA_PATCHES Mon Sep 17 00:00:00 2001
|
||||
From: John Baldwin <jhb@FreeBSD.org>
|
||||
Date: Thu, 11 Apr 2024 14:05:43 -0700
|
||||
Subject: gdb-rhel-10464-xsave-update-5of21.patch
|
||||
|
||||
;; Backport "x86 nat: Add helper functions to save the XSAVE layout for
|
||||
;; the host."
|
||||
;; (John Baldwin, RHEL-10464)
|
||||
|
||||
x86_xsave_length returns the total length of the XSAVE state area
|
||||
standard format as queried from CPUID.
|
||||
|
||||
x86_fetch_xsave_layout uses CPUID to query the offsets of XSAVE
|
||||
extended regions from the running host. The total length of the XSAVE
|
||||
state area can either be supplied by the caller if known (e.g. from
|
||||
FreeBSD's PT_GETXSTATEINFO) or it can be queried from the running host
|
||||
using x86_xsave_length.
|
||||
|
||||
Approved-By: Simon Marchi <simon.marchi@efficios.com>
|
||||
|
||||
diff --git a/gdb/nat/x86-xstate.c b/gdb/nat/x86-xstate.c
|
||||
new file mode 100644
|
||||
--- /dev/null
|
||||
+++ b/gdb/nat/x86-xstate.c
|
||||
@@ -0,0 +1,68 @@
|
||||
+/* x86 XSAVE extended state functions.
|
||||
+
|
||||
+ Copyright (C) 2022-2023 Free Software Foundation, Inc.
|
||||
+
|
||||
+ This file is part of GDB.
|
||||
+
|
||||
+ This program is free software; you can redistribute it and/or modify
|
||||
+ it under the terms of the GNU General Public License as published by
|
||||
+ the Free Software Foundation; either version 3 of the License, or
|
||||
+ (at your option) any later version.
|
||||
+
|
||||
+ This program is distributed in the hope that it will be useful,
|
||||
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
+ GNU General Public License for more details.
|
||||
+
|
||||
+ You should have received a copy of the GNU General Public License
|
||||
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
|
||||
+
|
||||
+#include "gdbsupport/common-defs.h"
|
||||
+#include "gdbsupport/x86-xstate.h"
|
||||
+#include "nat/x86-cpuid.h"
|
||||
+#include "nat/x86-xstate.h"
|
||||
+
|
||||
+/* Fetch the offset of a specific XSAVE extended region. */
|
||||
+
|
||||
+static int
|
||||
+xsave_feature_offset (uint64_t xcr0, int feature)
|
||||
+{
|
||||
+ uint32_t ebx;
|
||||
+
|
||||
+ if ((xcr0 & (1ULL << feature)) == 0)
|
||||
+ return 0;
|
||||
+
|
||||
+ if (!x86_cpuid_count (0xd, feature, nullptr, &ebx, nullptr, nullptr))
|
||||
+ return 0;
|
||||
+ return ebx;
|
||||
+}
|
||||
+
|
||||
+/* See x86-xstate.h. */
|
||||
+
|
||||
+int
|
||||
+x86_xsave_length ()
|
||||
+{
|
||||
+ uint32_t ecx;
|
||||
+
|
||||
+ if (!x86_cpuid_count (0xd, 0, nullptr, nullptr, &ecx, nullptr))
|
||||
+ return 0;
|
||||
+ return ecx;
|
||||
+}
|
||||
+
|
||||
+/* See x86-xstate.h. */
|
||||
+
|
||||
+x86_xsave_layout
|
||||
+x86_fetch_xsave_layout (uint64_t xcr0, int len)
|
||||
+{
|
||||
+ x86_xsave_layout layout;
|
||||
+ memset (&layout, 0, sizeof (x86_xsave_layout));
|
||||
+ layout.sizeof_xsave = len;
|
||||
+ layout.avx_offset = xsave_feature_offset (xcr0, X86_XSTATE_AVX_ID);
|
||||
+ layout.bndregs_offset = xsave_feature_offset (xcr0, X86_XSTATE_BNDREGS_ID);
|
||||
+ layout.bndcfg_offset = xsave_feature_offset (xcr0, X86_XSTATE_BNDCFG_ID);
|
||||
+ layout.k_offset = xsave_feature_offset (xcr0, X86_XSTATE_K_ID);
|
||||
+ layout.zmm_h_offset = xsave_feature_offset (xcr0, X86_XSTATE_ZMM_H_ID);
|
||||
+ layout.zmm_offset = xsave_feature_offset (xcr0, X86_XSTATE_ZMM_ID);
|
||||
+ layout.pkru_offset = xsave_feature_offset (xcr0, X86_XSTATE_PKRU_ID);
|
||||
+ return layout;
|
||||
+}
|
||||
diff --git a/gdb/nat/x86-xstate.h b/gdb/nat/x86-xstate.h
|
||||
new file mode 100644
|
||||
--- /dev/null
|
||||
+++ b/gdb/nat/x86-xstate.h
|
||||
@@ -0,0 +1,35 @@
|
||||
+/* x86 XSAVE extended state functions.
|
||||
+
|
||||
+ Copyright (C) 2022-2023 Free Software Foundation, Inc.
|
||||
+
|
||||
+ This file is part of GDB.
|
||||
+
|
||||
+ This program is free software; you can redistribute it and/or modify
|
||||
+ it under the terms of the GNU General Public License as published by
|
||||
+ the Free Software Foundation; either version 3 of the License, or
|
||||
+ (at your option) any later version.
|
||||
+
|
||||
+ This program is distributed in the hope that it will be useful,
|
||||
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
+ GNU General Public License for more details.
|
||||
+
|
||||
+ You should have received a copy of the GNU General Public License
|
||||
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
|
||||
+
|
||||
+#ifndef NAT_X86_XSTATE_H
|
||||
+#define NAT_X86_XSTATE_H
|
||||
+
|
||||
+#include "gdbsupport/x86-xstate.h"
|
||||
+
|
||||
+/* Return the size of the XSAVE extended state fetched via CPUID. */
|
||||
+
|
||||
+int x86_xsave_length ();
|
||||
+
|
||||
+/* Return the layout (size and offsets) of the XSAVE extended regions
|
||||
+ for the running host. Offsets of each of the enabled regions in
|
||||
+ XCR0 are fetched via CPUID. */
|
||||
+
|
||||
+x86_xsave_layout x86_fetch_xsave_layout (uint64_t xcr0, int len);
|
||||
+
|
||||
+#endif /* NAT_X86_XSTATE_H */
|
217
gdb-rhel-10464-xsave-update-6of21.patch
Normal file
217
gdb-rhel-10464-xsave-update-6of21.patch
Normal file
@ -0,0 +1,217 @@
|
||||
From FEDORA_PATCHES Mon Sep 17 00:00:00 2001
|
||||
From: John Baldwin <jhb@FreeBSD.org>
|
||||
Date: Thu, 11 Apr 2024 14:05:43 -0700
|
||||
Subject: gdb-rhel-10464-xsave-update-6of21.patch
|
||||
|
||||
;; Backport "gdb: Update x86 Linux architectures to support XSAVE layouts."
|
||||
;; (John Baldwin, RHEL-10464)
|
||||
|
||||
Refactor i386_linux_core_read_xcr0 to fetch and return a corresponding
|
||||
x86_xsave_layout as well as xcr0 using the size of an existing
|
||||
NT_X86_XSTATE core dump to determine the offsets via
|
||||
i387_guess_xsave_layout. Use this to add an implementation of
|
||||
gdbarch_core_xfer_x86_xsave_layout.
|
||||
|
||||
Use tdep->xsave_layout.sizeof_xsave as the size of the XSTATE register
|
||||
set.
|
||||
|
||||
Approved-By: Simon Marchi <simon.marchi@efficios.com>
|
||||
|
||||
diff --git a/gdb/amd64-linux-tdep.c b/gdb/amd64-linux-tdep.c
|
||||
--- a/gdb/amd64-linux-tdep.c
|
||||
+++ b/gdb/amd64-linux-tdep.c
|
||||
@@ -1608,7 +1608,11 @@ amd64_linux_core_read_description (struct gdbarch *gdbarch,
|
||||
bfd *abfd)
|
||||
{
|
||||
/* Linux/x86-64. */
|
||||
- uint64_t xcr0 = i386_linux_core_read_xcr0 (abfd);
|
||||
+ x86_xsave_layout layout;
|
||||
+ memset (&layout, 0, sizeof (x86_xsave_layout));
|
||||
+ uint64_t xcr0 = i386_linux_core_read_xsave_info (abfd, layout);
|
||||
+ if (xcr0 == 0)
|
||||
+ xcr0 = X86_XSTATE_SSE_MASK;
|
||||
|
||||
return amd64_linux_read_description (xcr0 & X86_XSTATE_ALL_MASK,
|
||||
gdbarch_ptr_bit (gdbarch) == 32);
|
||||
@@ -1653,8 +1657,10 @@ amd64_linux_iterate_over_regset_sections (struct gdbarch *gdbarch,
|
||||
|
||||
cb (".reg", 27 * 8, 27 * 8, &i386_gregset, NULL, cb_data);
|
||||
cb (".reg2", 512, 512, &amd64_fpregset, NULL, cb_data);
|
||||
- cb (".reg-xstate", X86_XSTATE_SIZE (tdep->xcr0), X86_XSTATE_SIZE (tdep->xcr0),
|
||||
- &amd64_linux_xstateregset, "XSAVE extended state", cb_data);
|
||||
+ if (tdep->xsave_layout.sizeof_xsave != 0)
|
||||
+ cb (".reg-xstate", tdep->xsave_layout.sizeof_xsave,
|
||||
+ tdep->xsave_layout.sizeof_xsave, &amd64_linux_xstateregset,
|
||||
+ "XSAVE extended state", cb_data);
|
||||
}
|
||||
|
||||
/* The instruction sequences used in x86_64 machines for a
|
||||
@@ -1807,6 +1813,8 @@ amd64_linux_init_abi_common(struct gdbarch_info info, struct gdbarch *gdbarch)
|
||||
tdep->sc_num_regs = ARRAY_SIZE (amd64_linux_sc_reg_offset);
|
||||
|
||||
tdep->xsave_xcr0_offset = I386_LINUX_XSAVE_XCR0_OFFSET;
|
||||
+ set_gdbarch_core_read_x86_xsave_layout
|
||||
+ (gdbarch, i386_linux_core_read_x86_xsave_layout);
|
||||
|
||||
/* Add the %orig_rax register used for syscall restarting. */
|
||||
set_gdbarch_write_pc (gdbarch, amd64_linux_write_pc);
|
||||
diff --git a/gdb/i386-linux-tdep.c b/gdb/i386-linux-tdep.c
|
||||
--- a/gdb/i386-linux-tdep.c
|
||||
+++ b/gdb/i386-linux-tdep.c
|
||||
@@ -637,45 +637,48 @@ static int i386_linux_sc_reg_offset[] =
|
||||
0 * 4 /* %gs */
|
||||
};
|
||||
|
||||
-/* Get XSAVE extended state xcr0 from core dump. */
|
||||
+/* See i386-linux-tdep.h. */
|
||||
|
||||
uint64_t
|
||||
-i386_linux_core_read_xcr0 (bfd *abfd)
|
||||
+i386_linux_core_read_xsave_info (bfd *abfd, x86_xsave_layout &layout)
|
||||
{
|
||||
asection *xstate = bfd_get_section_by_name (abfd, ".reg-xstate");
|
||||
- uint64_t xcr0;
|
||||
+ if (xstate == nullptr)
|
||||
+ return 0;
|
||||
|
||||
- if (xstate)
|
||||
- {
|
||||
- size_t size = bfd_section_size (xstate);
|
||||
+ /* Check extended state size. */
|
||||
+ size_t size = bfd_section_size (xstate);
|
||||
+ if (size < X86_XSTATE_AVX_SIZE)
|
||||
+ return 0;
|
||||
|
||||
- /* Check extended state size. */
|
||||
- if (size < X86_XSTATE_AVX_SIZE)
|
||||
- xcr0 = X86_XSTATE_SSE_MASK;
|
||||
- else
|
||||
- {
|
||||
- char contents[8];
|
||||
-
|
||||
- if (! bfd_get_section_contents (abfd, xstate, contents,
|
||||
- I386_LINUX_XSAVE_XCR0_OFFSET,
|
||||
- 8))
|
||||
- {
|
||||
- warning (_("Couldn't read `xcr0' bytes from "
|
||||
- "`.reg-xstate' section in core file."));
|
||||
- return 0;
|
||||
- }
|
||||
-
|
||||
- xcr0 = bfd_get_64 (abfd, contents);
|
||||
- }
|
||||
+ char contents[8];
|
||||
+ if (! bfd_get_section_contents (abfd, xstate, contents,
|
||||
+ I386_LINUX_XSAVE_XCR0_OFFSET, 8))
|
||||
+ {
|
||||
+ warning (_("Couldn't read `xcr0' bytes from "
|
||||
+ "`.reg-xstate' section in core file."));
|
||||
+ return 0;
|
||||
}
|
||||
- else
|
||||
- xcr0 = 0;
|
||||
+
|
||||
+ uint64_t xcr0 = bfd_get_64 (abfd, contents);
|
||||
+
|
||||
+ if (!i387_guess_xsave_layout (xcr0, size, layout))
|
||||
+ return 0;
|
||||
|
||||
return xcr0;
|
||||
}
|
||||
|
||||
/* See i386-linux-tdep.h. */
|
||||
|
||||
+bool
|
||||
+i386_linux_core_read_x86_xsave_layout (struct gdbarch *gdbarch,
|
||||
+ x86_xsave_layout &layout)
|
||||
+{
|
||||
+ return i386_linux_core_read_xsave_info (core_bfd, layout) != 0;
|
||||
+}
|
||||
+
|
||||
+/* See i386-linux-tdep.h. */
|
||||
+
|
||||
const struct target_desc *
|
||||
i386_linux_read_description (uint64_t xcr0)
|
||||
{
|
||||
@@ -707,7 +710,9 @@ i386_linux_core_read_description (struct gdbarch *gdbarch,
|
||||
bfd *abfd)
|
||||
{
|
||||
/* Linux/i386. */
|
||||
- uint64_t xcr0 = i386_linux_core_read_xcr0 (abfd);
|
||||
+ x86_xsave_layout layout;
|
||||
+ memset (&layout, 0, sizeof (x86_xsave_layout));
|
||||
+ uint64_t xcr0 = i386_linux_core_read_xsave_info (abfd, layout);
|
||||
const struct target_desc *tdesc = i386_linux_read_description (xcr0);
|
||||
|
||||
if (tdesc != NULL)
|
||||
@@ -766,9 +771,9 @@ i386_linux_iterate_over_regset_sections (struct gdbarch *gdbarch,
|
||||
|
||||
cb (".reg", 68, 68, &i386_gregset, NULL, cb_data);
|
||||
|
||||
- if (tdep->xcr0 & X86_XSTATE_AVX)
|
||||
- cb (".reg-xstate", X86_XSTATE_SIZE (tdep->xcr0),
|
||||
- X86_XSTATE_SIZE (tdep->xcr0), &i386_linux_xstateregset,
|
||||
+ if (tdep->xsave_layout.sizeof_xsave != 0)
|
||||
+ cb (".reg-xstate", tdep->xsave_layout.sizeof_xsave,
|
||||
+ tdep->xsave_layout.sizeof_xsave, &i386_linux_xstateregset,
|
||||
"XSAVE extended state", cb_data);
|
||||
else if (tdep->xcr0 & X86_XSTATE_SSE)
|
||||
cb (".reg-xfp", 512, 512, &i386_fpregset, "extended floating-point",
|
||||
@@ -870,6 +875,8 @@ i386_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
|
||||
tdep->sc_num_regs = ARRAY_SIZE (i386_linux_sc_reg_offset);
|
||||
|
||||
tdep->xsave_xcr0_offset = I386_LINUX_XSAVE_XCR0_OFFSET;
|
||||
+ set_gdbarch_core_read_x86_xsave_layout
|
||||
+ (gdbarch, i386_linux_core_read_x86_xsave_layout);
|
||||
|
||||
set_gdbarch_process_record (gdbarch, i386_process_record);
|
||||
set_gdbarch_process_record_signal (gdbarch, i386_linux_record_signal);
|
||||
diff --git a/gdb/i386-linux-tdep.h b/gdb/i386-linux-tdep.h
|
||||
--- a/gdb/i386-linux-tdep.h
|
||||
+++ b/gdb/i386-linux-tdep.h
|
||||
@@ -20,6 +20,8 @@
|
||||
#ifndef I386_LINUX_TDEP_H
|
||||
#define I386_LINUX_TDEP_H
|
||||
|
||||
+#include "gdbsupport/x86-xstate.h"
|
||||
+
|
||||
/* The Linux kernel pretends there is an additional "orig_eax"
|
||||
register. Since GDB needs access to that register to be able to
|
||||
properly restart system calls when necessary (see
|
||||
@@ -34,8 +36,18 @@
|
||||
/* Total number of registers for GNU/Linux. */
|
||||
#define I386_LINUX_NUM_REGS (I386_LINUX_ORIG_EAX_REGNUM + 1)
|
||||
|
||||
-/* Get XSAVE extended state xcr0 from core dump. */
|
||||
-extern uint64_t i386_linux_core_read_xcr0 (bfd *abfd);
|
||||
+/* Read the XSAVE extended state xcr0 value from the ABFD core file.
|
||||
+ If it appears to be valid, return it and fill LAYOUT with values
|
||||
+ inferred from that value.
|
||||
+
|
||||
+ Otherwise, return 0 to indicate no state was found and leave LAYOUT
|
||||
+ untouched. */
|
||||
+extern uint64_t i386_linux_core_read_xsave_info (bfd *abfd,
|
||||
+ x86_xsave_layout &layout);
|
||||
+
|
||||
+/* Implement the core_read_x86_xsave_layout gdbarch method. */
|
||||
+extern bool i386_linux_core_read_x86_xsave_layout (struct gdbarch *gdbarch,
|
||||
+ x86_xsave_layout &layout);
|
||||
|
||||
/* Handle and display information related to the MPX bound violation
|
||||
to the user. */
|
||||
@@ -52,14 +64,7 @@ extern const struct target_desc *i386_linux_read_description (uint64_t xcr0);
|
||||
fxsave_bytes[0..463]
|
||||
sw_usable_bytes[464..511]
|
||||
xstate_hdr_bytes[512..575]
|
||||
- avx_bytes[576..831]
|
||||
- mpx_bytes [960..1032]
|
||||
- avx512_k_regs[1088..1152]
|
||||
- avx512_zmmh_regs0-7[1153..1407]
|
||||
- avx512_zmmh_regs8-15[1408..1663]
|
||||
- avx512_zmm_regs16-31[1664..2687]
|
||||
- pkru[2688..2752]
|
||||
- future_state etc
|
||||
+ extended state regions (AVX, MPX, AVX512, PKRU, etc.)
|
||||
};
|
||||
|
||||
Same memory layout will be used for the coredump NT_X86_XSTATE
|
148
gdb-rhel-10464-xsave-update-7of21.patch
Normal file
148
gdb-rhel-10464-xsave-update-7of21.patch
Normal file
@ -0,0 +1,148 @@
|
||||
From FEDORA_PATCHES Mon Sep 17 00:00:00 2001
|
||||
From: John Baldwin <jhb@FreeBSD.org>
|
||||
Date: Thu, 11 Apr 2024 14:05:43 -0700
|
||||
Subject: gdb-rhel-10464-xsave-update-7of21.patch
|
||||
|
||||
;; Backport "gdb: Support XSAVE layouts for the current host in the Linux
|
||||
;; x86 targets."
|
||||
;; (John Baldwin, RHEL-10464)
|
||||
|
||||
Note that this uses the CPUID instruction to determine the total size
|
||||
of the XSAVE register set. If there is a way to fetch the register set
|
||||
size using ptrace that would probably be better.
|
||||
|
||||
Approved-By: Simon Marchi <simon.marchi@efficios.com>
|
||||
|
||||
diff --git a/gdb/amd64-linux-nat.c b/gdb/amd64-linux-nat.c
|
||||
--- a/gdb/amd64-linux-nat.c
|
||||
+++ b/gdb/amd64-linux-nat.c
|
||||
@@ -210,6 +210,7 @@ void
|
||||
amd64_linux_nat_target::fetch_registers (struct regcache *regcache, int regnum)
|
||||
{
|
||||
struct gdbarch *gdbarch = regcache->arch ();
|
||||
+ const struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
|
||||
int tid;
|
||||
|
||||
/* GNU/Linux LWP ID's are process ID's. */
|
||||
@@ -235,7 +236,7 @@ amd64_linux_nat_target::fetch_registers (struct regcache *regcache, int regnum)
|
||||
|
||||
if (have_ptrace_getregset == TRIBOOL_TRUE)
|
||||
{
|
||||
- char xstateregs[X86_XSTATE_MAX_SIZE];
|
||||
+ char xstateregs[tdep->xsave_layout.sizeof_xsave];
|
||||
struct iovec iov;
|
||||
|
||||
/* Pre-4.14 kernels have a bug (fixed by commit 0852b374173b
|
||||
@@ -270,6 +271,7 @@ void
|
||||
amd64_linux_nat_target::store_registers (struct regcache *regcache, int regnum)
|
||||
{
|
||||
struct gdbarch *gdbarch = regcache->arch ();
|
||||
+ const struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
|
||||
int tid;
|
||||
|
||||
/* GNU/Linux LWP ID's are process ID's. */
|
||||
@@ -299,7 +301,7 @@ amd64_linux_nat_target::store_registers (struct regcache *regcache, int regnum)
|
||||
|
||||
if (have_ptrace_getregset == TRIBOOL_TRUE)
|
||||
{
|
||||
- char xstateregs[X86_XSTATE_MAX_SIZE];
|
||||
+ char xstateregs[tdep->xsave_layout.sizeof_xsave];
|
||||
struct iovec iov;
|
||||
|
||||
iov.iov_base = xstateregs;
|
||||
diff --git a/gdb/configure.nat b/gdb/configure.nat
|
||||
--- a/gdb/configure.nat
|
||||
+++ b/gdb/configure.nat
|
||||
@@ -246,6 +246,7 @@ case ${gdb_host} in
|
||||
i386)
|
||||
# Host: Intel 386 running GNU/Linux.
|
||||
NATDEPFILES="${NATDEPFILES} x86-nat.o nat/x86-dregs.o \
|
||||
+ nat/x86-xstate.o \
|
||||
i386-linux-nat.o x86-linux-nat.o nat/linux-btrace.o \
|
||||
nat/x86-linux.o nat/x86-linux-dregs.o"
|
||||
;;
|
||||
@@ -303,7 +304,7 @@ case ${gdb_host} in
|
||||
i386)
|
||||
# Host: GNU/Linux x86-64
|
||||
NATDEPFILES="${NATDEPFILES} x86-nat.o nat/x86-dregs.o \
|
||||
- amd64-nat.o amd64-linux-nat.o x86-linux-nat.o \
|
||||
+ nat/x86-xstate.o amd64-nat.o amd64-linux-nat.o x86-linux-nat.o \
|
||||
nat/linux-btrace.o \
|
||||
nat/x86-linux.o nat/x86-linux-dregs.o \
|
||||
nat/amd64-linux-siginfo.o"
|
||||
diff --git a/gdb/i386-linux-nat.c b/gdb/i386-linux-nat.c
|
||||
--- a/gdb/i386-linux-nat.c
|
||||
+++ b/gdb/i386-linux-nat.c
|
||||
@@ -330,7 +330,9 @@ store_fpregs (const struct regcache *regcache, int tid, int regno)
|
||||
static int
|
||||
fetch_xstateregs (struct regcache *regcache, int tid)
|
||||
{
|
||||
- char xstateregs[X86_XSTATE_MAX_SIZE];
|
||||
+ struct gdbarch *gdbarch = regcache->arch ();
|
||||
+ const i386_gdbarch_tdep *tdep = gdbarch_tdep<i386_gdbarch_tdep> (gdbarch);
|
||||
+ char xstateregs[tdep->xsave_layout.sizeof_xsave];
|
||||
struct iovec iov;
|
||||
|
||||
if (have_ptrace_getregset != TRIBOOL_TRUE)
|
||||
@@ -353,7 +355,9 @@ fetch_xstateregs (struct regcache *regcache, int tid)
|
||||
static int
|
||||
store_xstateregs (const struct regcache *regcache, int tid, int regno)
|
||||
{
|
||||
- char xstateregs[X86_XSTATE_MAX_SIZE];
|
||||
+ struct gdbarch *gdbarch = regcache->arch ();
|
||||
+ const i386_gdbarch_tdep *tdep = gdbarch_tdep<i386_gdbarch_tdep> (gdbarch);
|
||||
+ char xstateregs[tdep->xsave_layout.sizeof_xsave];
|
||||
struct iovec iov;
|
||||
|
||||
if (have_ptrace_getregset != TRIBOOL_TRUE)
|
||||
diff --git a/gdb/x86-linux-nat.c b/gdb/x86-linux-nat.c
|
||||
--- a/gdb/x86-linux-nat.c
|
||||
+++ b/gdb/x86-linux-nat.c
|
||||
@@ -36,6 +36,7 @@
|
||||
#include "amd64-linux-tdep.h"
|
||||
#endif
|
||||
#include "gdbsupport/x86-xstate.h"
|
||||
+#include "nat/x86-xstate.h"
|
||||
#include "nat/linux-btrace.h"
|
||||
#include "nat/linux-nat.h"
|
||||
#include "nat/x86-linux.h"
|
||||
@@ -177,6 +178,8 @@ x86_linux_nat_target::read_description ()
|
||||
/* Get XCR0 from XSAVE extended state. */
|
||||
xcr0 = xstateregs[(I386_LINUX_XSAVE_XCR0_OFFSET
|
||||
/ sizeof (uint64_t))];
|
||||
+
|
||||
+ m_xsave_layout = x86_fetch_xsave_layout (xcr0, x86_xsave_length ());
|
||||
}
|
||||
}
|
||||
|
||||
diff --git a/gdb/x86-linux-nat.h b/gdb/x86-linux-nat.h
|
||||
--- a/gdb/x86-linux-nat.h
|
||||
+++ b/gdb/x86-linux-nat.h
|
||||
@@ -22,6 +22,7 @@
|
||||
|
||||
#include "gdb_proc_service.h" /* For ps_err_e. */
|
||||
#include "linux-nat.h"
|
||||
+#include "gdbsupport/x86-xstate.h"
|
||||
#include "x86-nat.h"
|
||||
#include "nat/x86-linux.h"
|
||||
|
||||
@@ -44,6 +45,9 @@ struct x86_linux_nat_target : public x86_nat_target<linux_nat_target>
|
||||
enum btrace_read_type type) override;
|
||||
const struct btrace_config *btrace_conf (const struct btrace_target_info *) override;
|
||||
|
||||
+ x86_xsave_layout fetch_x86_xsave_layout () override
|
||||
+ { return m_xsave_layout; }
|
||||
+
|
||||
/* These two are rewired to low_ versions. linux-nat.c queries
|
||||
stopped-by-watchpoint info as soon as an lwp stops (via the low_
|
||||
methods) and caches the result, to be returned via the normal
|
||||
@@ -73,6 +77,9 @@ struct x86_linux_nat_target : public x86_nat_target<linux_nat_target>
|
||||
|
||||
void low_delete_thread (struct arch_lwp_info *lwp) override
|
||||
{ x86_linux_delete_thread (lwp); }
|
||||
+
|
||||
+private:
|
||||
+ x86_xsave_layout m_xsave_layout;
|
||||
};
|
||||
|
||||
|
720
gdb-rhel-10464-xsave-update-8of21.patch
Normal file
720
gdb-rhel-10464-xsave-update-8of21.patch
Normal file
@ -0,0 +1,720 @@
|
||||
From FEDORA_PATCHES Mon Sep 17 00:00:00 2001
|
||||
From: John Baldwin <jhb@FreeBSD.org>
|
||||
Date: Thu, 11 Apr 2024 14:05:44 -0700
|
||||
Subject: gdb-rhel-10464-xsave-update-8of21.patch
|
||||
|
||||
;; Backport "gdb: Use x86_xstate_layout to parse the XSAVE extended state area."
|
||||
;; (John Baldwin, RHEL-10464)
|
||||
|
||||
All of the tables describing the offsets of individual registers for
|
||||
XSAVE state components now hold relative offsets rather than absolute
|
||||
offsets. Some tables (those for MPX registers and ZMMH registers) had
|
||||
to be split into separate tables as they held entries that spanned
|
||||
multiple state components.
|
||||
|
||||
Approved-By: Simon Marchi <simon.marchi@efficios.com>
|
||||
|
||||
diff --git a/gdb/i387-tdep.c b/gdb/i387-tdep.c
|
||||
--- a/gdb/i387-tdep.c
|
||||
+++ b/gdb/i387-tdep.c
|
||||
@@ -727,170 +727,204 @@ i387_collect_fxsave (const struct regcache *regcache, int regnum, void *fxsave)
|
||||
/* `xstate_bv' is at byte offset 512. */
|
||||
#define XSAVE_XSTATE_BV_ADDR(xsave) (xsave + 512)
|
||||
|
||||
-/* At xsave_avxh_offset[REGNUM] you'll find the offset to the location in
|
||||
- the upper 128bit of AVX register data structure used by the "xsave"
|
||||
- instruction where GDB register REGNUM is stored. */
|
||||
+/* At xsave_avxh_offset[REGNUM] you'll find the relative offset within
|
||||
+ the AVX region of the XSAVE extended state where the upper 128bits
|
||||
+ of GDB register YMM0 + REGNUM is stored. */
|
||||
|
||||
static int xsave_avxh_offset[] =
|
||||
{
|
||||
- 576 + 0 * 16, /* Upper 128bit of %ymm0 through ... */
|
||||
- 576 + 1 * 16,
|
||||
- 576 + 2 * 16,
|
||||
- 576 + 3 * 16,
|
||||
- 576 + 4 * 16,
|
||||
- 576 + 5 * 16,
|
||||
- 576 + 6 * 16,
|
||||
- 576 + 7 * 16,
|
||||
- 576 + 8 * 16,
|
||||
- 576 + 9 * 16,
|
||||
- 576 + 10 * 16,
|
||||
- 576 + 11 * 16,
|
||||
- 576 + 12 * 16,
|
||||
- 576 + 13 * 16,
|
||||
- 576 + 14 * 16,
|
||||
- 576 + 15 * 16 /* Upper 128bit of ... %ymm15 (128 bits each). */
|
||||
+ 0 * 16, /* Upper 128bit of %ymm0 through ... */
|
||||
+ 1 * 16,
|
||||
+ 2 * 16,
|
||||
+ 3 * 16,
|
||||
+ 4 * 16,
|
||||
+ 5 * 16,
|
||||
+ 6 * 16,
|
||||
+ 7 * 16,
|
||||
+ 8 * 16,
|
||||
+ 9 * 16,
|
||||
+ 10 * 16,
|
||||
+ 11 * 16,
|
||||
+ 12 * 16,
|
||||
+ 13 * 16,
|
||||
+ 14 * 16,
|
||||
+ 15 * 16 /* Upper 128bit of ... %ymm15 (128 bits each). */
|
||||
};
|
||||
|
||||
-#define XSAVE_AVXH_ADDR(tdep, xsave, regnum) \
|
||||
- (xsave + xsave_avxh_offset[regnum - I387_YMM0H_REGNUM (tdep)])
|
||||
+#define XSAVE_AVXH_ADDR(tdep, xsave, regnum) \
|
||||
+ (xsave + (tdep)->xsave_layout.avx_offset \
|
||||
+ + xsave_avxh_offset[regnum - I387_YMM0H_REGNUM (tdep)])
|
||||
|
||||
-/* At xsave_ymm_avx512_offset[REGNUM] you'll find the offset to the location in
|
||||
- the upper 128bit of ZMM register data structure used by the "xsave"
|
||||
- instruction where GDB register REGNUM is stored. */
|
||||
+/* At xsave_ymm_avx512_offset[REGNUM] you'll find the relative offset
|
||||
+ within the ZMM region of the XSAVE extended state where the second
|
||||
+ 128bits of GDB register YMM16 + REGNUM is stored. */
|
||||
|
||||
static int xsave_ymm_avx512_offset[] =
|
||||
{
|
||||
- /* HI16_ZMM_area + 16 bytes + regnum* 64 bytes. */
|
||||
- 1664 + 16 + 0 * 64, /* %ymm16 through... */
|
||||
- 1664 + 16 + 1 * 64,
|
||||
- 1664 + 16 + 2 * 64,
|
||||
- 1664 + 16 + 3 * 64,
|
||||
- 1664 + 16 + 4 * 64,
|
||||
- 1664 + 16 + 5 * 64,
|
||||
- 1664 + 16 + 6 * 64,
|
||||
- 1664 + 16 + 7 * 64,
|
||||
- 1664 + 16 + 8 * 64,
|
||||
- 1664 + 16 + 9 * 64,
|
||||
- 1664 + 16 + 10 * 64,
|
||||
- 1664 + 16 + 11 * 64,
|
||||
- 1664 + 16 + 12 * 64,
|
||||
- 1664 + 16 + 13 * 64,
|
||||
- 1664 + 16 + 14 * 64,
|
||||
- 1664 + 16 + 15 * 64 /* ... %ymm31 (128 bits each). */
|
||||
+ 16 + 0 * 64, /* %ymm16 through... */
|
||||
+ 16 + 1 * 64,
|
||||
+ 16 + 2 * 64,
|
||||
+ 16 + 3 * 64,
|
||||
+ 16 + 4 * 64,
|
||||
+ 16 + 5 * 64,
|
||||
+ 16 + 6 * 64,
|
||||
+ 16 + 7 * 64,
|
||||
+ 16 + 8 * 64,
|
||||
+ 16 + 9 * 64,
|
||||
+ 16 + 10 * 64,
|
||||
+ 16 + 11 * 64,
|
||||
+ 16 + 12 * 64,
|
||||
+ 16 + 13 * 64,
|
||||
+ 16 + 14 * 64,
|
||||
+ 16 + 15 * 64 /* ... %ymm31 (128 bits each). */
|
||||
};
|
||||
|
||||
-#define XSAVE_YMM_AVX512_ADDR(tdep, xsave, regnum) \
|
||||
- (xsave + xsave_ymm_avx512_offset[regnum - I387_YMM16H_REGNUM (tdep)])
|
||||
+#define XSAVE_YMM_AVX512_ADDR(tdep, xsave, regnum) \
|
||||
+ (xsave + (tdep)->xsave_layout.zmm_offset \
|
||||
+ + xsave_ymm_avx512_offset[regnum - I387_YMM16H_REGNUM (tdep)])
|
||||
+
|
||||
+/* At xsave_xmm_avx512_offset[REGNUM] you'll find the relative offset
|
||||
+ within the ZMM region of the XSAVE extended state where the first
|
||||
+ 128bits of GDB register XMM16 + REGNUM is stored. */
|
||||
|
||||
static int xsave_xmm_avx512_offset[] =
|
||||
{
|
||||
- 1664 + 0 * 64, /* %ymm16 through... */
|
||||
- 1664 + 1 * 64,
|
||||
- 1664 + 2 * 64,
|
||||
- 1664 + 3 * 64,
|
||||
- 1664 + 4 * 64,
|
||||
- 1664 + 5 * 64,
|
||||
- 1664 + 6 * 64,
|
||||
- 1664 + 7 * 64,
|
||||
- 1664 + 8 * 64,
|
||||
- 1664 + 9 * 64,
|
||||
- 1664 + 10 * 64,
|
||||
- 1664 + 11 * 64,
|
||||
- 1664 + 12 * 64,
|
||||
- 1664 + 13 * 64,
|
||||
- 1664 + 14 * 64,
|
||||
- 1664 + 15 * 64 /* ... %ymm31 (128 bits each). */
|
||||
+ 0 * 64, /* %xmm16 through... */
|
||||
+ 1 * 64,
|
||||
+ 2 * 64,
|
||||
+ 3 * 64,
|
||||
+ 4 * 64,
|
||||
+ 5 * 64,
|
||||
+ 6 * 64,
|
||||
+ 7 * 64,
|
||||
+ 8 * 64,
|
||||
+ 9 * 64,
|
||||
+ 10 * 64,
|
||||
+ 11 * 64,
|
||||
+ 12 * 64,
|
||||
+ 13 * 64,
|
||||
+ 14 * 64,
|
||||
+ 15 * 64 /* ... %xmm31 (128 bits each). */
|
||||
};
|
||||
|
||||
-#define XSAVE_XMM_AVX512_ADDR(tdep, xsave, regnum) \
|
||||
- (xsave + xsave_xmm_avx512_offset[regnum - I387_XMM16_REGNUM (tdep)])
|
||||
+#define XSAVE_XMM_AVX512_ADDR(tdep, xsave, regnum) \
|
||||
+ (xsave + (tdep)->xsave_layout.zmm_offset \
|
||||
+ + xsave_xmm_avx512_offset[regnum - I387_XMM16_REGNUM (tdep)])
|
||||
+
|
||||
+/* At xsave_bndregs_offset[REGNUM] you'll find the relative offset
|
||||
+ within the BNDREGS region of the XSAVE extended state where the GDB
|
||||
+ register BND0R + REGNUM is stored. */
|
||||
|
||||
-static int xsave_mpx_offset[] = {
|
||||
- 960 + 0 * 16, /* bnd0r...bnd3r registers. */
|
||||
- 960 + 1 * 16,
|
||||
- 960 + 2 * 16,
|
||||
- 960 + 3 * 16,
|
||||
- 1024 + 0 * 8, /* bndcfg ... bndstatus. */
|
||||
- 1024 + 1 * 8,
|
||||
+static int xsave_bndregs_offset[] = {
|
||||
+ 0 * 16, /* bnd0r...bnd3r registers. */
|
||||
+ 1 * 16,
|
||||
+ 2 * 16,
|
||||
+ 3 * 16
|
||||
};
|
||||
|
||||
-#define XSAVE_MPX_ADDR(tdep, xsave, regnum) \
|
||||
- (xsave + xsave_mpx_offset[regnum - I387_BND0R_REGNUM (tdep)])
|
||||
+#define XSAVE_BNDREGS_ADDR(tdep, xsave, regnum) \
|
||||
+ (xsave + (tdep)->xsave_layout.bndregs_offset \
|
||||
+ + xsave_bndregs_offset[regnum - I387_BND0R_REGNUM (tdep)])
|
||||
+
|
||||
+static int xsave_bndcfg_offset[] = {
|
||||
+ 0 * 8, /* bndcfg ... bndstatus. */
|
||||
+ 1 * 8,
|
||||
+};
|
||||
|
||||
- /* At xsave_avx512__h_offset[REGNUM] you find the offset to the location
|
||||
- of the AVX512 opmask register data structure used by the "xsave"
|
||||
- instruction where GDB register REGNUM is stored. */
|
||||
+#define XSAVE_BNDCFG_ADDR(tdep, xsave, regnum) \
|
||||
+ (xsave + (tdep)->xsave_layout.bndcfg_offset \
|
||||
+ + xsave_bndcfg_offset[regnum - I387_BNDCFGU_REGNUM (tdep)])
|
||||
+
|
||||
+/* At xsave_avx512_k_offset[REGNUM] you'll find the relative offset
|
||||
+ within the K region of the XSAVE extended state where the AVX512
|
||||
+ opmask register K0 + REGNUM is stored. */
|
||||
|
||||
static int xsave_avx512_k_offset[] =
|
||||
{
|
||||
- 1088 + 0 * 8, /* %k0 through... */
|
||||
- 1088 + 1 * 8,
|
||||
- 1088 + 2 * 8,
|
||||
- 1088 + 3 * 8,
|
||||
- 1088 + 4 * 8,
|
||||
- 1088 + 5 * 8,
|
||||
- 1088 + 6 * 8,
|
||||
- 1088 + 7 * 8 /* %k7 (64 bits each). */
|
||||
+ 0 * 8, /* %k0 through... */
|
||||
+ 1 * 8,
|
||||
+ 2 * 8,
|
||||
+ 3 * 8,
|
||||
+ 4 * 8,
|
||||
+ 5 * 8,
|
||||
+ 6 * 8,
|
||||
+ 7 * 8 /* %k7 (64 bits each). */
|
||||
+};
|
||||
+
|
||||
+#define XSAVE_AVX512_K_ADDR(tdep, xsave, regnum) \
|
||||
+ (xsave + (tdep)->xsave_layout.k_offset \
|
||||
+ + xsave_avx512_k_offset[regnum - I387_K0_REGNUM (tdep)])
|
||||
+
|
||||
+
|
||||
+/* At xsave_avx512_zmm0_h_offset[REGNUM] you find the relative offset
|
||||
+ within the ZMM_H region of the XSAVE extended state where the upper
|
||||
+ 256bits of the GDB register ZMM0 + REGNUM is stored. */
|
||||
+
|
||||
+static int xsave_avx512_zmm0_h_offset[] =
|
||||
+{
|
||||
+ 0 * 32, /* Upper 256bit of %zmmh0 through... */
|
||||
+ 1 * 32,
|
||||
+ 2 * 32,
|
||||
+ 3 * 32,
|
||||
+ 4 * 32,
|
||||
+ 5 * 32,
|
||||
+ 6 * 32,
|
||||
+ 7 * 32,
|
||||
+ 8 * 32,
|
||||
+ 9 * 32,
|
||||
+ 10 * 32,
|
||||
+ 11 * 32,
|
||||
+ 12 * 32,
|
||||
+ 13 * 32,
|
||||
+ 14 * 32,
|
||||
+ 15 * 32 /* Upper 256bit of... %zmmh15 (256 bits each). */
|
||||
};
|
||||
|
||||
-#define XSAVE_AVX512_K_ADDR(tdep, xsave, regnum) \
|
||||
- (xsave + xsave_avx512_k_offset[regnum - I387_K0_REGNUM (tdep)])
|
||||
+#define XSAVE_AVX512_ZMM0_H_ADDR(tdep, xsave, regnum) \
|
||||
+ (xsave + (tdep)->xsave_layout.zmm_h_offset \
|
||||
+ + xsave_avx512_zmm0_h_offset[regnum - I387_ZMM0H_REGNUM (tdep)])
|
||||
|
||||
-/* At xsave_avx512_zmm_h_offset[REGNUM] you find the offset to the location in
|
||||
- the upper 256bit of AVX512 ZMMH register data structure used by the "xsave"
|
||||
- instruction where GDB register REGNUM is stored. */
|
||||
+/* At xsave_avx512_zmm16_h_offset[REGNUM] you find the relative offset
|
||||
+ within the ZMM_H region of the XSAVE extended state where the upper
|
||||
+ 256bits of the GDB register ZMM16 + REGNUM is stored. */
|
||||
|
||||
-static int xsave_avx512_zmm_h_offset[] =
|
||||
+static int xsave_avx512_zmm16_h_offset[] =
|
||||
{
|
||||
- 1152 + 0 * 32,
|
||||
- 1152 + 1 * 32, /* Upper 256bit of %zmmh0 through... */
|
||||
- 1152 + 2 * 32,
|
||||
- 1152 + 3 * 32,
|
||||
- 1152 + 4 * 32,
|
||||
- 1152 + 5 * 32,
|
||||
- 1152 + 6 * 32,
|
||||
- 1152 + 7 * 32,
|
||||
- 1152 + 8 * 32,
|
||||
- 1152 + 9 * 32,
|
||||
- 1152 + 10 * 32,
|
||||
- 1152 + 11 * 32,
|
||||
- 1152 + 12 * 32,
|
||||
- 1152 + 13 * 32,
|
||||
- 1152 + 14 * 32,
|
||||
- 1152 + 15 * 32, /* Upper 256bit of... %zmmh15 (256 bits each). */
|
||||
- 1664 + 32 + 0 * 64, /* Upper 256bit of... %zmmh16 (256 bits each). */
|
||||
- 1664 + 32 + 1 * 64,
|
||||
- 1664 + 32 + 2 * 64,
|
||||
- 1664 + 32 + 3 * 64,
|
||||
- 1664 + 32 + 4 * 64,
|
||||
- 1664 + 32 + 5 * 64,
|
||||
- 1664 + 32 + 6 * 64,
|
||||
- 1664 + 32 + 7 * 64,
|
||||
- 1664 + 32 + 8 * 64,
|
||||
- 1664 + 32 + 9 * 64,
|
||||
- 1664 + 32 + 10 * 64,
|
||||
- 1664 + 32 + 11 * 64,
|
||||
- 1664 + 32 + 12 * 64,
|
||||
- 1664 + 32 + 13 * 64,
|
||||
- 1664 + 32 + 14 * 64,
|
||||
- 1664 + 32 + 15 * 64 /* Upper 256bit of... %zmmh31 (256 bits each). */
|
||||
+ 32 + 0 * 64, /* Upper 256bit of... %zmmh16 (256 bits each). */
|
||||
+ 32 + 1 * 64,
|
||||
+ 32 + 2 * 64,
|
||||
+ 32 + 3 * 64,
|
||||
+ 32 + 4 * 64,
|
||||
+ 32 + 5 * 64,
|
||||
+ 32 + 6 * 64,
|
||||
+ 32 + 7 * 64,
|
||||
+ 32 + 8 * 64,
|
||||
+ 32 + 9 * 64,
|
||||
+ 32 + 10 * 64,
|
||||
+ 32 + 11 * 64,
|
||||
+ 32 + 12 * 64,
|
||||
+ 32 + 13 * 64,
|
||||
+ 32 + 14 * 64,
|
||||
+ 32 + 15 * 64 /* Upper 256bit of... %zmmh31 (256 bits each). */
|
||||
};
|
||||
|
||||
-#define XSAVE_AVX512_ZMM_H_ADDR(tdep, xsave, regnum) \
|
||||
- (xsave + xsave_avx512_zmm_h_offset[regnum - I387_ZMM0H_REGNUM (tdep)])
|
||||
+#define XSAVE_AVX512_ZMM16_H_ADDR(tdep, xsave, regnum) \
|
||||
+ (xsave + (tdep)->xsave_layout.zmm_offset \
|
||||
+ + xsave_avx512_zmm16_h_offset[regnum - I387_ZMM16H_REGNUM (tdep)])
|
||||
|
||||
-/* At xsave_pkeys_offset[REGNUM] you find the offset to the location
|
||||
- of the PKRU register data structure used by the "xsave"
|
||||
- instruction where GDB register REGNUM is stored. */
|
||||
+/* At xsave_pkeys_offset[REGNUM] you'll find the relative offset
|
||||
+ within the PKEYS region of the XSAVE extended state where the PKRU
|
||||
+ register is stored. */
|
||||
|
||||
static int xsave_pkeys_offset[] =
|
||||
{
|
||||
-2688 + 0 * 8 /* %pkru (64 bits in XSTATE, 32-bit actually used by
|
||||
+ 0 * 8 /* %pkru (64 bits in XSTATE, 32-bit actually used by
|
||||
instructions and applications). */
|
||||
};
|
||||
|
||||
-#define XSAVE_PKEYS_ADDR(tdep, xsave, regnum) \
|
||||
- (xsave + xsave_pkeys_offset[regnum - I387_PKRU_REGNUM (tdep)])
|
||||
+#define XSAVE_PKEYS_ADDR(tdep, xsave, regnum) \
|
||||
+ (xsave + (tdep)->xsave_layout.pkru_offset \
|
||||
+ + xsave_pkeys_offset[regnum - I387_PKRU_REGNUM (tdep)])
|
||||
|
||||
|
||||
/* See i387-tdep.h. */
|
||||
@@ -993,14 +1027,16 @@ i387_supply_xsave (struct regcache *regcache, int regnum,
|
||||
x87 = 0x1,
|
||||
sse = 0x2,
|
||||
avxh = 0x4,
|
||||
- mpx = 0x8,
|
||||
- avx512_k = 0x10,
|
||||
- avx512_zmm_h = 0x20,
|
||||
- avx512_ymmh_avx512 = 0x40,
|
||||
- avx512_xmm_avx512 = 0x80,
|
||||
- pkeys = 0x100,
|
||||
- all = x87 | sse | avxh | mpx | avx512_k | avx512_zmm_h
|
||||
- | avx512_ymmh_avx512 | avx512_xmm_avx512 | pkeys
|
||||
+ bndregs = 0x8,
|
||||
+ bndcfg = 0x10,
|
||||
+ avx512_k = 0x20,
|
||||
+ avx512_zmm0_h = 0x40,
|
||||
+ avx512_zmm16_h = 0x80,
|
||||
+ avx512_ymmh_avx512 = 0x100,
|
||||
+ avx512_xmm_avx512 = 0x200,
|
||||
+ pkeys = 0x400,
|
||||
+ all = x87 | sse | avxh | bndregs | bndcfg | avx512_k | avx512_zmm0_h
|
||||
+ | avx512_zmm16_h | avx512_ymmh_avx512 | avx512_xmm_avx512 | pkeys
|
||||
} regclass;
|
||||
|
||||
gdb_assert (regs != NULL);
|
||||
@@ -1013,8 +1049,11 @@ i387_supply_xsave (struct regcache *regcache, int regnum,
|
||||
&& regnum < I387_PKEYSEND_REGNUM (tdep))
|
||||
regclass = pkeys;
|
||||
else if (regnum >= I387_ZMM0H_REGNUM (tdep)
|
||||
+ && regnum < I387_ZMM16H_REGNUM (tdep))
|
||||
+ regclass = avx512_zmm0_h;
|
||||
+ else if (regnum >= I387_ZMM16H_REGNUM (tdep)
|
||||
&& regnum < I387_ZMMENDH_REGNUM (tdep))
|
||||
- regclass = avx512_zmm_h;
|
||||
+ regclass = avx512_zmm16_h;
|
||||
else if (regnum >= I387_K0_REGNUM (tdep)
|
||||
&& regnum < I387_KEND_REGNUM (tdep))
|
||||
regclass = avx512_k;
|
||||
@@ -1028,8 +1067,11 @@ i387_supply_xsave (struct regcache *regcache, int regnum,
|
||||
&& regnum < I387_YMMENDH_REGNUM (tdep))
|
||||
regclass = avxh;
|
||||
else if (regnum >= I387_BND0R_REGNUM (tdep)
|
||||
+ && regnum < I387_BNDCFGU_REGNUM (tdep))
|
||||
+ regclass = bndregs;
|
||||
+ else if (regnum >= I387_BNDCFGU_REGNUM (tdep)
|
||||
&& regnum < I387_MPXEND_REGNUM (tdep))
|
||||
- regclass = mpx;
|
||||
+ regclass = bndcfg;
|
||||
else if (regnum >= I387_XMM0_REGNUM (tdep)
|
||||
&& regnum < I387_MXCSR_REGNUM (tdep))
|
||||
regclass = sse;
|
||||
@@ -1062,13 +1104,20 @@ i387_supply_xsave (struct regcache *regcache, int regnum,
|
||||
regcache->raw_supply (regnum, XSAVE_PKEYS_ADDR (tdep, regs, regnum));
|
||||
return;
|
||||
|
||||
- case avx512_zmm_h:
|
||||
- if ((clear_bv & (regnum < zmm_endlo_regnum ? X86_XSTATE_ZMM_H
|
||||
- : X86_XSTATE_ZMM)))
|
||||
+ case avx512_zmm0_h:
|
||||
+ if ((clear_bv & X86_XSTATE_ZMM_H))
|
||||
+ regcache->raw_supply (regnum, zero);
|
||||
+ else
|
||||
+ regcache->raw_supply (regnum,
|
||||
+ XSAVE_AVX512_ZMM0_H_ADDR (tdep, regs, regnum));
|
||||
+ return;
|
||||
+
|
||||
+ case avx512_zmm16_h:
|
||||
+ if ((clear_bv & X86_XSTATE_ZMM))
|
||||
regcache->raw_supply (regnum, zero);
|
||||
else
|
||||
regcache->raw_supply (regnum,
|
||||
- XSAVE_AVX512_ZMM_H_ADDR (tdep, regs, regnum));
|
||||
+ XSAVE_AVX512_ZMM16_H_ADDR (tdep, regs, regnum));
|
||||
return;
|
||||
|
||||
case avx512_k:
|
||||
@@ -1101,11 +1150,18 @@ i387_supply_xsave (struct regcache *regcache, int regnum,
|
||||
regcache->raw_supply (regnum, XSAVE_AVXH_ADDR (tdep, regs, regnum));
|
||||
return;
|
||||
|
||||
- case mpx:
|
||||
+ case bndcfg:
|
||||
+ if ((clear_bv & X86_XSTATE_BNDCFG))
|
||||
+ regcache->raw_supply (regnum, zero);
|
||||
+ else
|
||||
+ regcache->raw_supply (regnum, XSAVE_BNDCFG_ADDR (tdep, regs, regnum));
|
||||
+ return;
|
||||
+
|
||||
+ case bndregs:
|
||||
if ((clear_bv & X86_XSTATE_BNDREGS))
|
||||
regcache->raw_supply (regnum, zero);
|
||||
else
|
||||
- regcache->raw_supply (regnum, XSAVE_MPX_ADDR (tdep, regs, regnum));
|
||||
+ regcache->raw_supply (regnum, XSAVE_BNDREGS_ADDR (tdep, regs, regnum));
|
||||
return;
|
||||
|
||||
case sse:
|
||||
@@ -1154,7 +1210,7 @@ i387_supply_xsave (struct regcache *regcache, int regnum,
|
||||
{
|
||||
for (i = I387_ZMM0H_REGNUM (tdep); i < zmm_endlo_regnum; i++)
|
||||
regcache->raw_supply (i,
|
||||
- XSAVE_AVX512_ZMM_H_ADDR (tdep, regs, i));
|
||||
+ XSAVE_AVX512_ZMM0_H_ADDR (tdep, regs, i));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1182,7 +1238,8 @@ i387_supply_xsave (struct regcache *regcache, int regnum,
|
||||
{
|
||||
if ((clear_bv & X86_XSTATE_ZMM))
|
||||
{
|
||||
- for (i = zmm_endlo_regnum; i < I387_ZMMENDH_REGNUM (tdep); i++)
|
||||
+ for (i = I387_ZMM16H_REGNUM (tdep);
|
||||
+ i < I387_ZMMENDH_REGNUM (tdep); i++)
|
||||
regcache->raw_supply (i, zero);
|
||||
for (i = I387_YMM16H_REGNUM (tdep);
|
||||
i < I387_YMMH_AVX512_END_REGNUM (tdep);
|
||||
@@ -1195,9 +1252,10 @@ i387_supply_xsave (struct regcache *regcache, int regnum,
|
||||
}
|
||||
else
|
||||
{
|
||||
- for (i = zmm_endlo_regnum; i < I387_ZMMENDH_REGNUM (tdep); i++)
|
||||
+ for (i = I387_ZMM16H_REGNUM (tdep);
|
||||
+ i < I387_ZMMENDH_REGNUM (tdep); i++)
|
||||
regcache->raw_supply (i,
|
||||
- XSAVE_AVX512_ZMM_H_ADDR (tdep, regs, i));
|
||||
+ XSAVE_AVX512_ZMM16_H_ADDR (tdep, regs, i));
|
||||
for (i = I387_YMM16H_REGNUM (tdep);
|
||||
i < I387_YMMH_AVX512_END_REGNUM (tdep);
|
||||
i++)
|
||||
@@ -1240,7 +1298,7 @@ i387_supply_xsave (struct regcache *regcache, int regnum,
|
||||
{
|
||||
for (i = I387_BND0R_REGNUM (tdep);
|
||||
i < I387_BNDCFGU_REGNUM (tdep); i++)
|
||||
- regcache->raw_supply (i, XSAVE_MPX_ADDR (tdep, regs, i));
|
||||
+ regcache->raw_supply (i, XSAVE_BNDREGS_ADDR (tdep, regs, i));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1257,7 +1315,7 @@ i387_supply_xsave (struct regcache *regcache, int regnum,
|
||||
{
|
||||
for (i = I387_BNDCFGU_REGNUM (tdep);
|
||||
i < I387_MPXEND_REGNUM (tdep); i++)
|
||||
- regcache->raw_supply (i, XSAVE_MPX_ADDR (tdep, regs, i));
|
||||
+ regcache->raw_supply (i, XSAVE_BNDCFG_ADDR (tdep, regs, i));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1413,14 +1471,16 @@ i387_collect_xsave (const struct regcache *regcache, int regnum,
|
||||
x87 = 0x2,
|
||||
sse = 0x4,
|
||||
avxh = 0x8,
|
||||
- mpx = 0x10,
|
||||
- avx512_k = 0x20,
|
||||
- avx512_zmm_h = 0x40,
|
||||
- avx512_ymmh_avx512 = 0x80,
|
||||
- avx512_xmm_avx512 = 0x100,
|
||||
- pkeys = 0x200,
|
||||
- all = x87 | sse | avxh | mpx | avx512_k | avx512_zmm_h
|
||||
- | avx512_ymmh_avx512 | avx512_xmm_avx512 | pkeys
|
||||
+ bndregs = 0x10,
|
||||
+ bndcfg = 0x20,
|
||||
+ avx512_k = 0x40,
|
||||
+ avx512_zmm0_h = 0x80,
|
||||
+ avx512_zmm16_h = 0x100,
|
||||
+ avx512_ymmh_avx512 = 0x200,
|
||||
+ avx512_xmm_avx512 = 0x400,
|
||||
+ pkeys = 0x800,
|
||||
+ all = x87 | sse | avxh | bndregs | bndcfg | avx512_k | avx512_zmm0_h
|
||||
+ | avx512_zmm16_h | avx512_ymmh_avx512 | avx512_xmm_avx512 | pkeys
|
||||
} regclass;
|
||||
|
||||
gdb_assert (tdep->st0_regnum >= I386_ST0_REGNUM);
|
||||
@@ -1432,8 +1492,11 @@ i387_collect_xsave (const struct regcache *regcache, int regnum,
|
||||
&& regnum < I387_PKEYSEND_REGNUM (tdep))
|
||||
regclass = pkeys;
|
||||
else if (regnum >= I387_ZMM0H_REGNUM (tdep)
|
||||
+ && regnum < I387_ZMM16H_REGNUM (tdep))
|
||||
+ regclass = avx512_zmm0_h;
|
||||
+ else if (regnum >= I387_ZMM16H_REGNUM (tdep)
|
||||
&& regnum < I387_ZMMENDH_REGNUM (tdep))
|
||||
- regclass = avx512_zmm_h;
|
||||
+ regclass = avx512_zmm16_h;
|
||||
else if (regnum >= I387_K0_REGNUM (tdep)
|
||||
&& regnum < I387_KEND_REGNUM (tdep))
|
||||
regclass = avx512_k;
|
||||
@@ -1447,8 +1510,11 @@ i387_collect_xsave (const struct regcache *regcache, int regnum,
|
||||
&& regnum < I387_YMMENDH_REGNUM (tdep))
|
||||
regclass = avxh;
|
||||
else if (regnum >= I387_BND0R_REGNUM (tdep)
|
||||
+ && regnum < I387_BNDCFGU_REGNUM (tdep))
|
||||
+ regclass = bndregs;
|
||||
+ else if (regnum >= I387_BNDCFGU_REGNUM (tdep)
|
||||
&& regnum < I387_MPXEND_REGNUM (tdep))
|
||||
- regclass = mpx;
|
||||
+ regclass = bndcfg;
|
||||
else if (regnum >= I387_XMM0_REGNUM (tdep)
|
||||
&& regnum < I387_MXCSR_REGNUM (tdep))
|
||||
regclass = sse;
|
||||
@@ -1465,7 +1531,7 @@ i387_collect_xsave (const struct regcache *regcache, int regnum,
|
||||
if (gcore)
|
||||
{
|
||||
/* Clear XSAVE extended state. */
|
||||
- memset (regs, 0, X86_XSTATE_SIZE (tdep->xcr0));
|
||||
+ memset (regs, 0, tdep->xsave_layout.sizeof_xsave);
|
||||
|
||||
/* Update XCR0 and `xstate_bv' with XCR0 for gcore. */
|
||||
if (tdep->xsave_xcr0_offset != -1)
|
||||
@@ -1500,16 +1566,16 @@ i387_collect_xsave (const struct regcache *regcache, int regnum,
|
||||
if ((clear_bv & X86_XSTATE_BNDREGS))
|
||||
for (i = I387_BND0R_REGNUM (tdep);
|
||||
i < I387_BNDCFGU_REGNUM (tdep); i++)
|
||||
- memset (XSAVE_MPX_ADDR (tdep, regs, i), 0, 16);
|
||||
+ memset (XSAVE_BNDREGS_ADDR (tdep, regs, i), 0, 16);
|
||||
|
||||
if ((clear_bv & X86_XSTATE_BNDCFG))
|
||||
for (i = I387_BNDCFGU_REGNUM (tdep);
|
||||
i < I387_MPXEND_REGNUM (tdep); i++)
|
||||
- memset (XSAVE_MPX_ADDR (tdep, regs, i), 0, 8);
|
||||
+ memset (XSAVE_BNDCFG_ADDR (tdep, regs, i), 0, 8);
|
||||
|
||||
if ((clear_bv & X86_XSTATE_ZMM_H))
|
||||
for (i = I387_ZMM0H_REGNUM (tdep); i < zmm_endlo_regnum; i++)
|
||||
- memset (XSAVE_AVX512_ZMM_H_ADDR (tdep, regs, i), 0, 32);
|
||||
+ memset (XSAVE_AVX512_ZMM0_H_ADDR (tdep, regs, i), 0, 32);
|
||||
|
||||
if ((clear_bv & X86_XSTATE_K))
|
||||
for (i = I387_K0_REGNUM (tdep);
|
||||
@@ -1518,8 +1584,9 @@ i387_collect_xsave (const struct regcache *regcache, int regnum,
|
||||
|
||||
if ((clear_bv & X86_XSTATE_ZMM))
|
||||
{
|
||||
- for (i = zmm_endlo_regnum; i < I387_ZMMENDH_REGNUM (tdep); i++)
|
||||
- memset (XSAVE_AVX512_ZMM_H_ADDR (tdep, regs, i), 0, 32);
|
||||
+ for (i = I387_ZMM16H_REGNUM (tdep); i < I387_ZMMENDH_REGNUM (tdep);
|
||||
+ i++)
|
||||
+ memset (XSAVE_AVX512_ZMM16_H_ADDR (tdep, regs, i), 0, 32);
|
||||
for (i = I387_YMM16H_REGNUM (tdep);
|
||||
i < I387_YMMH_AVX512_END_REGNUM (tdep); i++)
|
||||
memset (XSAVE_YMM_AVX512_ADDR (tdep, regs, i), 0, 16);
|
||||
@@ -1582,15 +1649,27 @@ i387_collect_xsave (const struct regcache *regcache, int regnum,
|
||||
}
|
||||
|
||||
/* Check if any ZMMH registers are changed. */
|
||||
- if ((tdep->xcr0 & (X86_XSTATE_ZMM_H | X86_XSTATE_ZMM)))
|
||||
- for (i = I387_ZMM0H_REGNUM (tdep);
|
||||
+ if ((tdep->xcr0 & X86_XSTATE_ZMM))
|
||||
+ for (i = I387_ZMM16H_REGNUM (tdep);
|
||||
i < I387_ZMMENDH_REGNUM (tdep); i++)
|
||||
{
|
||||
regcache->raw_collect (i, raw);
|
||||
- p = XSAVE_AVX512_ZMM_H_ADDR (tdep, regs, i);
|
||||
+ p = XSAVE_AVX512_ZMM16_H_ADDR (tdep, regs, i);
|
||||
if (memcmp (raw, p, 32) != 0)
|
||||
{
|
||||
- xstate_bv |= (X86_XSTATE_ZMM_H | X86_XSTATE_ZMM);
|
||||
+ xstate_bv |= X86_XSTATE_ZMM;
|
||||
+ memcpy (p, raw, 32);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ if ((tdep->xcr0 & X86_XSTATE_ZMM_H))
|
||||
+ for (i = I387_ZMM0H_REGNUM (tdep); i < zmm_endlo_regnum; i++)
|
||||
+ {
|
||||
+ regcache->raw_collect (i, raw);
|
||||
+ p = XSAVE_AVX512_ZMM0_H_ADDR (tdep, regs, i);
|
||||
+ if (memcmp (raw, p, 32) != 0)
|
||||
+ {
|
||||
+ xstate_bv |= X86_XSTATE_ZMM_H;
|
||||
memcpy (p, raw, 32);
|
||||
}
|
||||
}
|
||||
@@ -1642,7 +1721,7 @@ i387_collect_xsave (const struct regcache *regcache, int regnum,
|
||||
i < I387_BNDCFGU_REGNUM (tdep); i++)
|
||||
{
|
||||
regcache->raw_collect (i, raw);
|
||||
- p = XSAVE_MPX_ADDR (tdep, regs, i);
|
||||
+ p = XSAVE_BNDREGS_ADDR (tdep, regs, i);
|
||||
if (memcmp (raw, p, 16))
|
||||
{
|
||||
xstate_bv |= X86_XSTATE_BNDREGS;
|
||||
@@ -1656,7 +1735,7 @@ i387_collect_xsave (const struct regcache *regcache, int regnum,
|
||||
i < I387_MPXEND_REGNUM (tdep); i++)
|
||||
{
|
||||
regcache->raw_collect (i, raw);
|
||||
- p = XSAVE_MPX_ADDR (tdep, regs, i);
|
||||
+ p = XSAVE_BNDCFG_ADDR (tdep, regs, i);
|
||||
if (memcmp (raw, p, 8))
|
||||
{
|
||||
xstate_bv |= X86_XSTATE_BNDCFG;
|
||||
@@ -1746,15 +1825,26 @@ i387_collect_xsave (const struct regcache *regcache, int regnum,
|
||||
}
|
||||
break;
|
||||
|
||||
- case avx512_zmm_h:
|
||||
- /* This is a ZMM register. */
|
||||
- p = XSAVE_AVX512_ZMM_H_ADDR (tdep, regs, regnum);
|
||||
+ case avx512_zmm16_h:
|
||||
+ /* This is a ZMM16-31 register. */
|
||||
+ p = XSAVE_AVX512_ZMM16_H_ADDR (tdep, regs, regnum);
|
||||
if (memcmp (raw, p, 32) != 0)
|
||||
{
|
||||
- xstate_bv |= (X86_XSTATE_ZMM_H | X86_XSTATE_ZMM);
|
||||
+ xstate_bv |= X86_XSTATE_ZMM;
|
||||
memcpy (p, raw, 32);
|
||||
}
|
||||
break;
|
||||
+
|
||||
+ case avx512_zmm0_h:
|
||||
+ /* This is a ZMM0-15 register. */
|
||||
+ p = XSAVE_AVX512_ZMM0_H_ADDR (tdep, regs, regnum);
|
||||
+ if (memcmp (raw, p, 32) != 0)
|
||||
+ {
|
||||
+ xstate_bv |= X86_XSTATE_ZMM_H;
|
||||
+ memcpy (p, raw, 32);
|
||||
+ }
|
||||
+ break;
|
||||
+
|
||||
case avx512_k:
|
||||
/* This is a AVX512 mask register. */
|
||||
p = XSAVE_AVX512_K_ADDR (tdep, regs, regnum);
|
||||
@@ -1795,25 +1885,22 @@ i387_collect_xsave (const struct regcache *regcache, int regnum,
|
||||
}
|
||||
break;
|
||||
|
||||
- case mpx:
|
||||
- if (regnum < I387_BNDCFGU_REGNUM (tdep))
|
||||
- {
|
||||
- regcache->raw_collect (regnum, raw);
|
||||
- p = XSAVE_MPX_ADDR (tdep, regs, regnum);
|
||||
- if (memcmp (raw, p, 16))
|
||||
- {
|
||||
- xstate_bv |= X86_XSTATE_BNDREGS;
|
||||
- memcpy (p, raw, 16);
|
||||
- }
|
||||
- }
|
||||
- else
|
||||
+ case bndregs:
|
||||
+ regcache->raw_collect (regnum, raw);
|
||||
+ p = XSAVE_BNDREGS_ADDR (tdep, regs, regnum);
|
||||
+ if (memcmp (raw, p, 16))
|
||||
{
|
||||
- p = XSAVE_MPX_ADDR (tdep, regs, regnum);
|
||||
- xstate_bv |= X86_XSTATE_BNDCFG;
|
||||
- memcpy (p, raw, 8);
|
||||
+ xstate_bv |= X86_XSTATE_BNDREGS;
|
||||
+ memcpy (p, raw, 16);
|
||||
}
|
||||
break;
|
||||
|
||||
+ case bndcfg:
|
||||
+ p = XSAVE_BNDCFG_ADDR (tdep, regs, regnum);
|
||||
+ xstate_bv |= X86_XSTATE_BNDCFG;
|
||||
+ memcpy (p, raw, 8);
|
||||
+ break;
|
||||
+
|
||||
case sse:
|
||||
/* This is an SSE register. */
|
||||
p = FXSAVE_ADDR (tdep, regs, regnum);
|
||||
diff --git a/gdb/i387-tdep.h b/gdb/i387-tdep.h
|
||||
--- a/gdb/i387-tdep.h
|
||||
+++ b/gdb/i387-tdep.h
|
||||
@@ -51,6 +51,7 @@ struct x86_xsave_layout;
|
||||
#define I387_K0_REGNUM(tdep) ((tdep)->k0_regnum)
|
||||
#define I387_NUM_ZMMH_REGS(tdep) ((tdep)->num_zmm_regs)
|
||||
#define I387_ZMM0H_REGNUM(tdep) ((tdep)->zmm0h_regnum)
|
||||
+#define I387_ZMM16H_REGNUM(tdep) ((tdep)->zmm0h_regnum + 16)
|
||||
#define I387_NUM_YMM_AVX512_REGS(tdep) ((tdep)->num_ymm_avx512_regs)
|
||||
#define I387_YMM16H_REGNUM(tdep) ((tdep)->ymm16h_regnum)
|
||||
|
168
gdb-rhel-10464-xsave-update-9of21.patch
Normal file
168
gdb-rhel-10464-xsave-update-9of21.patch
Normal file
@ -0,0 +1,168 @@
|
||||
From FEDORA_PATCHES Mon Sep 17 00:00:00 2001
|
||||
From: John Baldwin <jhb@FreeBSD.org>
|
||||
Date: Thu, 11 Apr 2024 14:05:44 -0700
|
||||
Subject: gdb-rhel-10464-xsave-update-9of21.patch
|
||||
|
||||
;; Backport "gdbserver: Add a function to set the XSAVE mask and size."
|
||||
;; (John Baldwin, RHEL-10464)
|
||||
|
||||
Make x86_xcr0 private to i387-fp.cc and use i387_set_xsave_mask to set
|
||||
the value instead. Add a static global instance of x86_xsave_layout
|
||||
and initialize it in the new function as well to be used in a future
|
||||
commit to parse XSAVE extended state regions.
|
||||
|
||||
Update the Linux port to use this function rather than setting
|
||||
x86_xcr0 directly. In the case that XML is not supported, don't
|
||||
bother setting x86_xcr0 to the default value but just omit the call to
|
||||
i387_set_xsave_mask as i387-fp.cc defaults to the SSE case used for
|
||||
non-XML.
|
||||
|
||||
In addition, use x86_xsave_length to determine the size of the XSAVE
|
||||
register set via CPUID.
|
||||
|
||||
Approved-By: Simon Marchi <simon.marchi@efficios.com>
|
||||
|
||||
diff --git a/gdbserver/configure.srv b/gdbserver/configure.srv
|
||||
--- a/gdbserver/configure.srv
|
||||
+++ b/gdbserver/configure.srv
|
||||
@@ -93,7 +93,8 @@ case "${gdbserver_host}" in
|
||||
i[34567]86-*-linux*) srv_tgtobj="${srv_tgtobj} arch/i386.o"
|
||||
srv_tgtobj="${srv_tgtobj} $srv_linux_obj"
|
||||
srv_tgtobj="${srv_tgtobj} linux-x86-low.o x86-low.o"
|
||||
- srv_tgtobj="${srv_tgtobj} nat/x86-dregs.o i387-fp.o"
|
||||
+ srv_tgtobj="${srv_tgtobj} nat/x86-dregs.o"
|
||||
+ srv_tgtobj="${srv_tgtobj} nat/x86-xstate.o i387-fp.o"
|
||||
srv_tgtobj="${srv_tgtobj} linux-x86-tdesc.o"
|
||||
srv_tgtobj="${srv_tgtobj} nat/linux-btrace.o"
|
||||
srv_tgtobj="${srv_tgtobj} nat/x86-linux.o"
|
||||
@@ -333,7 +334,8 @@ case "${gdbserver_host}" in
|
||||
srv_linux_thread_db=yes
|
||||
;;
|
||||
x86_64-*-linux*) srv_tgtobj="$srv_linux_obj linux-x86-low.o x86-low.o"
|
||||
- srv_tgtobj="${srv_tgtobj} nat/x86-dregs.o i387-fp.o"
|
||||
+ srv_tgtobj="${srv_tgtobj} nat/x86-dregs.o"
|
||||
+ srv_tgtobj="${srv_tgtobj} nat/x86-xstate.o i387-fp.o"
|
||||
srv_tgtobj="${srv_tgtobj} arch/i386.o arch/amd64.o"
|
||||
srv_tgtobj="${srv_tgtobj} linux-x86-tdesc.o"
|
||||
srv_tgtobj="${srv_tgtobj} nat/linux-btrace.o"
|
||||
@@ -348,14 +350,16 @@ case "${gdbserver_host}" in
|
||||
ipa_obj="${ipa_obj} arch/amd64-ipa.o"
|
||||
;;
|
||||
x86_64-*-mingw*) srv_regobj=""
|
||||
- srv_tgtobj="x86-low.o nat/x86-dregs.o i387-fp.o"
|
||||
+ srv_tgtobj="x86-low.o nat/x86-dregs.o"
|
||||
+ srv_tgtobj="${srv_tgtobj} nat/x86-xstate.o i387-fp.o"
|
||||
srv_tgtobj="${srv_tgtobj} win32-low.o win32-i386-low.o"
|
||||
srv_tgtobj="${srv_tgtobj} nat/windows-nat.o"
|
||||
srv_tgtobj="${srv_tgtobj} arch/amd64.o arch/i386.o"
|
||||
srv_mingw=yes
|
||||
;;
|
||||
x86_64-*-cygwin*) srv_regobj=""
|
||||
- srv_tgtobj="x86-low.o nat/x86-dregs.o i387-fp.o"
|
||||
+ srv_tgtobj="x86-low.o nat/x86-dregs.o"
|
||||
+ srv_tgtobj="${srv_tgtobj} nat/x86-xstate.o i387-fp.o"
|
||||
srv_tgtobj="${srv_tgtobj} win32-low.o win32-i386-low.o"
|
||||
srv_tgtobj="${srv_tgtobj} nat/windows-nat.o"
|
||||
srv_tgtobj="${srv_tgtobj} arch/amd64.o arch/i386.o"
|
||||
diff --git a/gdbserver/i387-fp.cc b/gdbserver/i387-fp.cc
|
||||
--- a/gdbserver/i387-fp.cc
|
||||
+++ b/gdbserver/i387-fp.cc
|
||||
@@ -19,6 +19,10 @@
|
||||
#include "server.h"
|
||||
#include "i387-fp.h"
|
||||
#include "gdbsupport/x86-xstate.h"
|
||||
+#include "nat/x86-xstate.h"
|
||||
+
|
||||
+/* Default to SSE. */
|
||||
+static unsigned long long x86_xcr0 = X86_XSTATE_SSE_MASK;
|
||||
|
||||
static const int num_mpx_bnd_registers = 4;
|
||||
static const int num_mpx_cfg_registers = 2;
|
||||
@@ -29,6 +33,8 @@ static const int num_avx512_ymmh_registers = 16;
|
||||
static const int num_avx512_xmm_registers = 16;
|
||||
static const int num_pkeys_registers = 1;
|
||||
|
||||
+static x86_xsave_layout xsave_layout;
|
||||
+
|
||||
/* Note: These functions preserve the reserved bits in control registers.
|
||||
However, gdbserver promptly throws away that information. */
|
||||
|
||||
@@ -950,5 +956,11 @@ i387_xsave_to_cache (struct regcache *regcache, const void *buf)
|
||||
}
|
||||
}
|
||||
|
||||
-/* Default to SSE. */
|
||||
-unsigned long long x86_xcr0 = X86_XSTATE_SSE_MASK;
|
||||
+/* See i387-fp.h. */
|
||||
+
|
||||
+void
|
||||
+i387_set_xsave_mask (uint64_t xcr0, int len)
|
||||
+{
|
||||
+ x86_xcr0 = xcr0;
|
||||
+ xsave_layout = x86_fetch_xsave_layout (xcr0, len);
|
||||
+}
|
||||
diff --git a/gdbserver/i387-fp.h b/gdbserver/i387-fp.h
|
||||
--- a/gdbserver/i387-fp.h
|
||||
+++ b/gdbserver/i387-fp.h
|
||||
@@ -28,6 +28,8 @@ void i387_fxsave_to_cache (struct regcache *regcache, const void *buf);
|
||||
void i387_cache_to_xsave (struct regcache *regcache, void *buf);
|
||||
void i387_xsave_to_cache (struct regcache *regcache, const void *buf);
|
||||
|
||||
-extern unsigned long long x86_xcr0;
|
||||
+/* Set the XSAVE mask and fetch the XSAVE layout via CPUID. */
|
||||
+
|
||||
+void i387_set_xsave_mask (uint64_t xcr0, int len);
|
||||
|
||||
#endif /* GDBSERVER_I387_FP_H */
|
||||
diff --git a/gdbserver/linux-x86-low.cc b/gdbserver/linux-x86-low.cc
|
||||
--- a/gdbserver/linux-x86-low.cc
|
||||
+++ b/gdbserver/linux-x86-low.cc
|
||||
@@ -25,6 +25,7 @@
|
||||
#include "i387-fp.h"
|
||||
#include "x86-low.h"
|
||||
#include "gdbsupport/x86-xstate.h"
|
||||
+#include "nat/x86-xstate.h"
|
||||
#include "nat/gdb_ptrace.h"
|
||||
|
||||
#ifdef __x86_64__
|
||||
@@ -871,6 +872,7 @@ x86_linux_read_description (void)
|
||||
int xcr0_features;
|
||||
int tid;
|
||||
static uint64_t xcr0;
|
||||
+ static int xsave_len;
|
||||
struct regset_info *regset;
|
||||
|
||||
tid = lwpid_of (current_thread);
|
||||
@@ -905,8 +907,6 @@ x86_linux_read_description (void)
|
||||
|
||||
if (!use_xml)
|
||||
{
|
||||
- x86_xcr0 = X86_XSTATE_SSE_MASK;
|
||||
-
|
||||
/* Don't use XML. */
|
||||
#ifdef __x86_64__
|
||||
if (machine == EM_X86_64)
|
||||
@@ -936,11 +936,13 @@ x86_linux_read_description (void)
|
||||
xcr0 = xstateregs[(I386_LINUX_XSAVE_XCR0_OFFSET
|
||||
/ sizeof (uint64_t))];
|
||||
|
||||
+ xsave_len = x86_xsave_length ();
|
||||
+
|
||||
/* Use PTRACE_GETREGSET if it is available. */
|
||||
for (regset = x86_regsets;
|
||||
regset->fill_function != NULL; regset++)
|
||||
if (regset->get_request == PTRACE_GETREGSET)
|
||||
- regset->size = X86_XSTATE_SIZE (xcr0);
|
||||
+ regset->size = xsave_len;
|
||||
else if (regset->type != GENERAL_REGS)
|
||||
regset->size = 0;
|
||||
}
|
||||
@@ -951,7 +953,7 @@ x86_linux_read_description (void)
|
||||
&& (xcr0 & X86_XSTATE_ALL_MASK));
|
||||
|
||||
if (xcr0_features)
|
||||
- x86_xcr0 = xcr0;
|
||||
+ i387_set_xsave_mask (xcr0, xsave_len);
|
||||
|
||||
if (machine == EM_X86_64)
|
||||
{
|
6
gdb.spec
6
gdb.spec
@ -37,7 +37,7 @@ Version: 10.2
|
||||
|
||||
# The release always contains a leading reserved number, start it at 1.
|
||||
# `upstream' is not a part of `name' to stay fully rpm dependencies compatible for the testing.
|
||||
Release: 13%{?dist}
|
||||
Release: 14%{?dist}
|
||||
|
||||
License: GPLv3+ and GPLv3+ with exceptions and GPLv2+ and GPLv2+ with exceptions and GPL+ and LGPLv2+ and LGPLv3+ and BSD and Public Domain and GFDL
|
||||
# Do not provide URL for snapshots as the file lasts there only for 2 days.
|
||||
@ -1158,12 +1158,14 @@ fi
|
||||
%endif
|
||||
|
||||
%changelog
|
||||
* Thu Apr 11 2024 Keith Seitz
|
||||
* Thu Apr 11 2024 Keith Seitz - 10.2-14.el9
|
||||
- Backport "Fix GDB internal error by using text (instead of data)
|
||||
section offset"
|
||||
(Kevin Buettner, RHEL-17399)
|
||||
- Backport "s390: Add arch14 record/replay support"
|
||||
(Andreas Arnaz, RHEL-10550)
|
||||
- Backport patches for x86 XSTATE update in gdb and gdbserver.
|
||||
(John Baldwin et al, RHEL-10464)
|
||||
|
||||
* Wed Dec 13 2023 Keith Seitz - 10.2-13.el9
|
||||
- Backport patches for "Fix undefined behaviour dereferencing empty string"
|
||||
|
Loading…
Reference in New Issue
Block a user