diff options
-rw-r--r-- | gdb/corelow.c | 21 | ||||
-rw-r--r-- | gdb/gdbarch-gen.h | 9 | ||||
-rw-r--r-- | gdb/gdbarch.c | 32 | ||||
-rw-r--r-- | gdb/gdbarch.h | 1 | ||||
-rw-r--r-- | gdb/gdbarch_components.py | 11 | ||||
-rw-r--r-- | gdb/i387-tdep.c | 55 | ||||
-rw-r--r-- | gdb/i387-tdep.h | 8 |
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, |