From FEDORA_PATCHES Mon Sep 17 00:00:00 2001 From: John Baldwin 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 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 (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 --- 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 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 void low_delete_thread (struct arch_lwp_info *lwp) override { x86_linux_delete_thread (lwp); } + +private: + x86_xsave_layout m_xsave_layout; };