aboutsummaryrefslogtreecommitdiff
path: root/gdb
diff options
context:
space:
mode:
authorJohn Baldwin <jhb@FreeBSD.org>2023-08-28 14:18:19 -0700
committerJohn Baldwin <jhb@FreeBSD.org>2023-08-28 14:18:19 -0700
commit9848bf83750ba897090320137221977584405e06 (patch)
treeadbfd12b2c6f477c31549718500a2819f8c6fed3 /gdb
parentb42405a159450004f2e2497e2b2d81bcac85c947 (diff)
downloadgdb-9848bf83750ba897090320137221977584405e06.zip
gdb-9848bf83750ba897090320137221977584405e06.tar.gz
gdb-9848bf83750ba897090320137221977584405e06.tar.bz2
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 <simon.marchi@efficios.com>
Diffstat (limited to 'gdb')
-rw-r--r--gdb/amd64-linux-nat.c6
-rw-r--r--gdb/configure.nat3
-rw-r--r--gdb/i386-linux-nat.c8
-rw-r--r--gdb/x86-linux-nat.c3
-rw-r--r--gdb/x86-linux-nat.h7
5 files changed, 22 insertions, 5 deletions
diff --git a/gdb/amd64-linux-nat.c b/gdb/amd64-linux-nat.c
index b5b0703..6571be4 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<i386_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<i386_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 b371ad8..2739d14 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 a524fdc..7e0572e 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<i386_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<i386_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 ca4eaf5..cd8fd9c 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 fcb5f08..a99de6c 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<linux_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<linux_nat_target>
protected:
/* Override the GNU/Linux inferior startup hook. */
void post_startup_inferior (ptid_t) override;
+
+private:
+ x86_xsave_layout m_xsave_layout;
};