From: John Baldwin Date: Mon, 28 Aug 2023 21:18:19 +0000 (-0700) Subject: gdb: Support XSAVE layouts for the current host in the Linux x86 targets. X-Git-Tag: gdb-14-branchpoint~436 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=9848bf83750ba897090320137221977584405e06;p=thirdparty%2Fbinutils-gdb.git gdb: Support XSAVE layouts for the current host in the Linux x86 targets. 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 --- diff --git a/gdb/amd64-linux-nat.c b/gdb/amd64-linux-nat.c index b5b0703879b..6571be40bb5 100644 --- 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 i386_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 i386_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 index b371ad89afe..2739d14a1c4 100644 --- a/gdb/configure.nat +++ b/gdb/configure.nat @@ -254,6 +254,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" ;; @@ -319,7 +320,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 index a524fdc9a1d..7e0572e1907 100644 --- 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 (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 (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 index ca4eaf5b645..cd8fd9c1dcd 100644 --- 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" @@ -179,6 +180,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 index fcb5f08d251..a99de6c29ea 100644 --- 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" @@ -41,6 +42,9 @@ struct x86_linux_nat_target : public x86_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 @@ -74,6 +78,9 @@ struct x86_linux_nat_target : public x86_nat_target protected: /* Override the GNU/Linux inferior startup hook. */ void post_startup_inferior (ptid_t) override; + +private: + x86_xsave_layout m_xsave_layout; };