aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gdb/corelow.c21
-rw-r--r--gdb/gdbarch-gen.h9
-rw-r--r--gdb/gdbarch.c32
-rw-r--r--gdb/gdbarch.h1
-rw-r--r--gdb/gdbarch_components.py11
-rw-r--r--gdb/i387-tdep.c55
-rw-r--r--gdb/i387-tdep.h8
7 files changed, 137 insertions, 0 deletions
diff --git a/gdb/corelow.c b/gdb/corelow.c
index 4d692dc..439270f 100644
--- a/gdb/corelow.c
+++ b/gdb/corelow.c
@@ -47,6 +47,7 @@
#include "build-id.h"
#include "gdbsupport/pathstuff.h"
#include "gdbsupport/scoped_fd.h"
+#include "gdbsupport/x86-xstate.h"
#include "debuginfod-support.h"
#include <unordered_map>
#include <unordered_set>
@@ -109,6 +110,8 @@ public:
bool fetch_memtags (CORE_ADDR address, size_t len,
gdb::byte_vector &tags, int type) override;
+ x86_xsave_layout fetch_x86_xsave_layout () override;
+
/* A few helpers. */
/* Getter, see variable definition. */
@@ -1387,6 +1390,24 @@ core_target::fetch_memtags (CORE_ADDR address, size_t len,
return false;
}
+/* 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;
+ 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-gen.h b/gdb/gdbarch-gen.h
index 101b1b7..d62eefa 100644
--- a/gdb/gdbarch-gen.h
+++ b/gdb/gdbarch-gen.h
@@ -1013,6 +1013,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 bool 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 bool gdbarch_gcore_bfd_target_p (struct gdbarch *gdbarch);
diff --git a/gdb/gdbarch.c b/gdb/gdbarch.c
index 30199a0..1fc254d 100644
--- a/gdb/gdbarch.c
+++ b/gdb/gdbarch.c
@@ -182,6 +182,7 @@ struct gdbarch
gdbarch_core_pid_to_str_ftype *core_pid_to_str = nullptr;
gdbarch_core_thread_name_ftype *core_thread_name = nullptr;
gdbarch_core_xfer_siginfo_ftype *core_xfer_siginfo = nullptr;
+ gdbarch_core_read_x86_xsave_layout_ftype *core_read_x86_xsave_layout = nullptr;
const char * gcore_bfd_target = 0;
int vtable_function_descriptors = 0;
int vbit_in_delta = 0;
@@ -443,6 +444,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 */
@@ -1072,6 +1074,12 @@ gdbarch_dump (struct gdbarch *gdbarch, struct ui_file *file)
"gdbarch_dump: core_xfer_siginfo = <%s>\n",
host_address_to_string (gdbarch->core_xfer_siginfo));
gdb_printf (file,
+ "gdbarch_dump: gdbarch_core_read_x86_xsave_layout_p() = %d\n",
+ gdbarch_core_read_x86_xsave_layout_p (gdbarch));
+ gdb_printf (file,
+ "gdbarch_dump: core_read_x86_xsave_layout = <%s>\n",
+ host_address_to_string (gdbarch->core_read_x86_xsave_layout));
+ gdb_printf (file,
"gdbarch_dump: gdbarch_gcore_bfd_target_p() = %d\n",
gdbarch_gcore_bfd_target_p (gdbarch));
gdb_printf (file,
@@ -3959,6 +3967,30 @@ set_gdbarch_core_xfer_siginfo (struct gdbarch *gdbarch,
}
bool
+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)
+ gdb_printf (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;
+}
+
+bool
gdbarch_gcore_bfd_target_p (struct gdbarch *gdbarch)
{
gdb_assert (gdbarch != NULL);
diff --git a/gdb/gdbarch.h b/gdb/gdbarch.h
index 3d97919..a9d6a4b 100644
--- a/gdb/gdbarch.h
+++ b/gdb/gdbarch.h
@@ -57,6 +57,7 @@ struct syscalls_info;
struct thread_info;
struct ui_out;
struct inferior;
+struct x86_xsave_layout;
#include "regcache.h"
diff --git a/gdb/gdbarch_components.py b/gdb/gdbarch_components.py
index 23e5789..846467b 100644
--- a/gdb/gdbarch_components.py
+++ b/gdb/gdbarch_components.py
@@ -1709,6 +1709,17 @@ of bytes read (zero indicates EOF, a negative value indicates failure).
predicate=True,
)
+Method(
+ comment="""
+Read x86 XSAVE layout information from core file into XSAVE_LAYOUT.
+Returns true if the layout was read successfully.
+""",
+ type="bool",
+ name="core_read_x86_xsave_layout",
+ params=[("x86_xsave_layout &", "xsave_layout")],
+ predicate=True,
+)
+
Value(
comment="""
BFD target to use when generating a core file.
diff --git a/gdb/i387-tdep.c b/gdb/i387-tdep.c
index df0a605..462e6a3 100644
--- a/gdb/i387-tdep.c
+++ b/gdb/i387-tdep.c
@@ -898,6 +898,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
index 2e890e7..f7557b0 100644
--- a/gdb/i387-tdep.h
+++ b/gdb/i387-tdep.h
@@ -25,6 +25,7 @@ class frame_info_ptr;
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,13 @@ 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,