[PATCH v6 07/15] gdb: Support XSAVE layouts for the current host in the FreeBSD x86 targets.

John Baldwin
2023-07-14T15:56:43Z

Use the CPUID instruction to fetch the offsets of supported state
components.
---
gdb/amd64-fbsd-nat.c | 40 ++++++++++------------------------------
gdb/configure.nat | 5 +++--
gdb/i386-fbsd-nat.c | 39 +++++++++------------------------------
gdb/x86-fbsd-nat.c | 21 +++++++++++++++++++++
gdb/x86-fbsd-nat.h | 19 +++++++++++++++++++
5 files changed, 62 insertions(+), 62 deletions(-)

diff --git a/gdb/amd64-fbsd-nat.c b/gdb/amd64-fbsd-nat.c
index 43e83ff2485..5821d94e27e 100644
--- a/gdb/amd64-fbsd-nat.c
+++ b/gdb/amd64-fbsd-nat.c
@@ -31,9 +31,9 @@

#include "amd64-tdep.h"
#include "amd64-fbsd-tdep.h"
+#include "i387-tdep.h"
#include "amd64-nat.h"
#include "x86-nat.h"
-#include "gdbsupport/x86-xstate.h"
#include "x86-fbsd-nat.h"

class amd64_fbsd_nat_target final : public x86_fbsd_nat_target
@@ -47,10 +47,6 @@ class amd64_fbsd_nat_target final : public x86_fbsd_nat_target

static amd64_fbsd_nat_target the_amd64_fbsd_nat_target;

-#ifdef PT_GETXSTATE_INFO
-static size_t xsave_len;
-#endif
-
/* This is a layout of the amd64 'struct reg' but with i386
registers. */

@@ -146,9 +142,9 @@ amd64_fbsd_nat_target::fetch_registers (struct regcache *regcache, int regnum)
fetching the FPU/XSAVE state unnecessarily. */

#ifdef PT_GETXSTATE_INFO
- if (xsave_len != 0)
+ if (m_xsave_info.xsave_len != 0)
{
- void *xstateregs = alloca (xsave_len);
+ void *xstateregs = alloca (m_xsave_info.xsave_len);

if (ptrace (PT_GETXSTATE, pid, (PTRACE_TYPE_ARG3) xstateregs, 0) == -1)
perror_with_name (_("Couldn't get extended state status"));
@@ -223,9 +219,9 @@ amd64_fbsd_nat_target::store_registers (struct regcache *regcache, int regnum)
fetching the FPU/XSAVE state unnecessarily. */

#ifdef PT_GETXSTATE_INFO
- if (xsave_len != 0)
+ if (m_xsave_info.xsave_len != 0)
{
- void *xstateregs = alloca (xsave_len);
+ void *xstateregs = alloca (m_xsave_info.xsave_len);

if (ptrace (PT_GETXSTATE, pid, (PTRACE_TYPE_ARG3) xstateregs, 0) == -1)
perror_with_name (_("Couldn't get extended state status"));
@@ -233,7 +229,7 @@ amd64_fbsd_nat_target::store_registers (struct regcache *regcache, int regnum)
amd64_collect_xsave (regcache, regnum, xstateregs, 0);

if (ptrace (PT_SETXSTATE, pid, (PTRACE_TYPE_ARG3) xstateregs,
- xsave_len) == -1)
+ m_xsave_info.xsave_len) == -1)
perror_with_name (_("Couldn't write extended state status"));
return;
}
@@ -303,10 +299,6 @@ amd64fbsd_supply_pcb (struct regcache *regcache, struct pcb *pcb)
const struct target_desc *
amd64_fbsd_nat_target::read_description ()
{
-#ifdef PT_GETXSTATE_INFO
- static int xsave_probed;
- static uint64_t xcr0;
-#endif
struct reg regs;
int is64;

@@ -318,25 +310,13 @@ amd64_fbsd_nat_target::read_description ()
perror_with_name (_("Couldn't get registers"));
is64 = (regs.r_cs == GSEL (GUCODE_SEL, SEL_UPL));
#ifdef PT_GETXSTATE_INFO
- if (!xsave_probed)
- {
- struct ptrace_xstate_info info;
-
- if (ptrace (PT_GETXSTATE_INFO, inferior_ptid.pid (),
- (PTRACE_TYPE_ARG3) &info, sizeof (info)) == 0)
- {
- xsave_len = info.xsave_len;
- xcr0 = info.xsave_mask;
- }
- xsave_probed = 1;
- }
-
- if (xsave_len != 0)
+ probe_xsave_layout (inferior_ptid.pid ());
+ if (m_xsave_info.xsave_len != 0)
{
if (is64)
- return amd64_target_description (xcr0, true);
+ return amd64_target_description (m_xsave_info.xsave_mask, true);
else
- return i386_target_description (xcr0, true);
+ return i386_target_description (m_xsave_info.xsave_mask, true);
}
#endif
if (is64)
diff --git a/gdb/configure.nat b/gdb/configure.nat
index aabcdeff989..b371ad89afe 100644
--- a/gdb/configure.nat
+++ b/gdb/configure.nat
@@ -166,7 +166,8 @@ case ${gdb_host} in
i386)
# Host: FreeBSD/i386
NATDEPFILES="${NATDEPFILES} x86-nat.o nat/x86-dregs.o \
- x86-bsd-nat.o x86-fbsd-nat.o i386-fbsd-nat.o bsd-kvm.o"
+ nat/x86-xstate.o x86-bsd-nat.o x86-fbsd-nat.o i386-fbsd-nat.o \
+ bsd-kvm.o"
;;
mips)
# Host: FreeBSD/mips
@@ -195,7 +196,7 @@ case ${gdb_host} in
# Host: FreeBSD/amd64
NATDEPFILES="${NATDEPFILES} amd64-nat.o \
amd64-fbsd-nat.o bsd-kvm.o x86-nat.o nat/x86-dregs.o \
- x86-bsd-nat.o x86-fbsd-nat.o"
+ nat/x86-xstate.o x86-bsd-nat.o x86-fbsd-nat.o"
;;
esac
;;
diff --git a/gdb/i386-fbsd-nat.c b/gdb/i386-fbsd-nat.c
index a2255c3c26b..e2c0e611717 100644
--- a/gdb/i386-fbsd-nat.c
+++ b/gdb/i386-fbsd-nat.c
@@ -31,7 +31,6 @@
#include "i386-fbsd-tdep.h"
#include "i387-tdep.h"
#include "x86-nat.h"
-#include "gdbsupport/x86-xstate.h"
#include "x86-fbsd-nat.h"

class i386_fbsd_nat_target final : public x86_fbsd_nat_target
@@ -47,10 +46,6 @@ class i386_fbsd_nat_target final : public x86_fbsd_nat_target

static i386_fbsd_nat_target the_i386_fbsd_nat_target;

-#ifdef PT_GETXSTATE_INFO
-static size_t xsave_len;
-#endif
-
static int have_ptrace_xmmregs;

/* Fetch register REGNUM from the inferior. If REGNUM is -1, do this
@@ -102,9 +97,9 @@ i386_fbsd_nat_target::fetch_registers (struct regcache *regcache, int regnum)
fetching the FPU/XSAVE state unnecessarily. */

#ifdef PT_GETXSTATE_INFO
- if (xsave_len != 0)
+ if (m_xsave_info.xsave_len != 0)
{
- void *xstateregs = alloca (xsave_len);
+ void *xstateregs = alloca (m_xsave_info.xsave_len);

if (ptrace (PT_GETXSTATE, pid, (PTRACE_TYPE_ARG3) xstateregs, 0) == -1)
perror_with_name (_("Couldn't get extended state status"));
@@ -181,17 +176,17 @@ i386_fbsd_nat_target::store_registers (struct regcache *regcache, int regnum)
fetching the FPU/XSAVE state unnecessarily. */

#ifdef PT_GETXSTATE_INFO
- if (xsave_len != 0)
+ if (m_xsave_info.xsave_len != 0)
{
- void *xstateregs = alloca (xsave_len);
+ void *xstateregs = alloca (m_xsave_info.xsave_len);

if (ptrace (PT_GETXSTATE, pid, (PTRACE_TYPE_ARG3) xstateregs, 0) == -1)
perror_with_name (_("Couldn't get extended state status"));

i387_collect_xsave (regcache, regnum, xstateregs, 0);

- if (ptrace (PT_SETXSTATE, pid, (PTRACE_TYPE_ARG3) xstateregs, xsave_len)
- == -1)
+ if (ptrace (PT_SETXSTATE, pid, (PTRACE_TYPE_ARG3) xstateregs,
+ m_xsave_info.xsave_len) == -1)
perror_with_name (_("Couldn't write extended state status"));
return;
}
@@ -309,31 +304,15 @@ i386fbsd_supply_pcb (struct regcache *regcache, struct pcb *pcb)
const struct target_desc *
i386_fbsd_nat_target::read_description ()
{
-#ifdef PT_GETXSTATE_INFO
- static int xsave_probed;
- static uint64_t xcr0;
-#endif
static int xmm_probed;

if (inferior_ptid == null_ptid)
return this->beneath ()->read_description ();

#ifdef PT_GETXSTATE_INFO
- if (!xsave_probed)
- {
- struct ptrace_xstate_info info;
-
- if (ptrace (PT_GETXSTATE_INFO, inferior_ptid.pid (),
- (PTRACE_TYPE_ARG3) &info, sizeof (info)) == 0)
- {
- xsave_len = info.xsave_len;
- xcr0 = info.xsave_mask;
- }
- xsave_probed = 1;
- }
-
- if (xsave_len != 0)
- return i386_target_description (xcr0, true);
+ probe_xsave_layout (inferior_ptid.pid ());
+ if (m_xsave_info.xsave_len != 0)
+ return i386_target_description (m_xsave_info.xsave_mask, true);
#endif

if (!xmm_probed)
diff --git a/gdb/x86-fbsd-nat.c b/gdb/x86-fbsd-nat.c
index 5d1c9fc7665..240e228976c 100644
--- a/gdb/x86-fbsd-nat.c
+++ b/gdb/x86-fbsd-nat.c
@@ -19,6 +19,9 @@

#include "defs.h"
#include "x86-fbsd-nat.h"
+#ifdef PT_GETXSTATE_INFO
+#include "nat/x86-xstate.h"
+#endif

/* Implement the virtual fbsd_nat_target::low_new_fork method. */

@@ -43,3 +46,21 @@ x86_fbsd_nat_target::low_new_fork (ptid_t parent, pid_t child)
child_state = x86_debug_reg_state (child);
*child_state = *parent_state;
}
+
+#ifdef PT_GETXSTATE_INFO
+void
+x86_fbsd_nat_target::probe_xsave_layout (pid_t pid)
+{
+ if (m_xsave_probed)
+ return;
+
+ m_xsave_probed = true;
+
+ if (ptrace (PT_GETXSTATE_INFO, pid, (PTRACE_TYPE_ARG3) &m_xsave_info,
+ sizeof (m_xsave_info)) != 0)
+ return;
+ if (m_xsave_info.xsave_len != 0)
+ m_xsave_layout = x86_fetch_xsave_layout (m_xsave_info.xsave_mask,
+ m_xsave_info.xsave_len);
+}
+#endif
diff --git a/gdb/x86-fbsd-nat.h b/gdb/x86-fbsd-nat.h
index a424323f399..723bb6cf305 100644
--- a/gdb/x86-fbsd-nat.h
+++ b/gdb/x86-fbsd-nat.h
@@ -20,6 +20,11 @@
#ifndef X86_FBSD_NAT_H
#define X86_FBSD_NAT_H

+#include <sys/ptrace.h>
+
+#ifdef PT_GETXSTATE_INFO
+#include "gdbsupport/x86-xstate.h"
+#endif
#include "fbsd-nat.h"
#include "x86-bsd-nat.h"

@@ -32,6 +37,20 @@ class x86_fbsd_nat_target : public x86bsd_nat_target<fbsd_nat_target>
{ return true; }

void low_new_fork (ptid_t parent, pid_t child) override;
+
+#ifdef PT_GETXSTATE_INFO
+ x86_xsave_layout fetch_x86_xsave_layout () override
+ { return m_xsave_layout; }
+
+protected:
+ void probe_xsave_layout (pid_t pid);
+
+ struct ptrace_xstate_info m_xsave_info;
+ x86_xsave_layout m_xsave_layout;
+
+private:
+ bool m_xsave_probed;
+#endif
};

#endif /* x86-bsd-nat.h */
--
2.40.0