270 lines
9.5 KiB
Diff
270 lines
9.5 KiB
Diff
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,
|