mirror of
https://github.com/bminor/binutils-gdb.git
synced 2025-12-05 15:15:42 +00:00
FreeBSD x86 nat: Use register maps for GP register sets.
Rather than using the x86-specific register offset tables, use register maps to describe the layout of the general purpose registers fetched via PT_GETREGS. The sole user-visible difference is that FreeBSD/amd64 will now report additional segment registers ($ds, $es, $fs, and $gs) for both 32-bit and 64-bit processes. As part of these changes, the FreeBSD x86 native targets no longer use amd64-bsd-nat.c or i386-bsd-nat.c. Remove FreeBSD-specific register handling (for $fs_base, $gs_base, and XSAVE state) from these files. Similarly, remove the global x86bsd_xsave_len from x86-bsd-nat.c. The FreeBSD x86 native targets use a static xsave_len instead. While here, rework the probing of PT_GETXMMREGS on FreeBSD/i386. Probe the ptrace op once in the target read_description method and cache the result for the future similar to the way the status of XSAVE support is probed in the read_description method. In addition, return the proper xcr0 mask (X87-only) for old kernels or systems without either XSAVE or XMM support.
This commit is contained in:
@@ -59,9 +59,6 @@ amd64bsd_fetch_inferior_registers (struct regcache *regcache, int regnum)
|
|||||||
{
|
{
|
||||||
struct gdbarch *gdbarch = regcache->arch ();
|
struct gdbarch *gdbarch = regcache->arch ();
|
||||||
ptid_t ptid = regcache->ptid ();
|
ptid_t ptid = regcache->ptid ();
|
||||||
#if defined(PT_GETFSBASE) || defined(PT_GETGSBASE)
|
|
||||||
i386_gdbarch_tdep *tdep = (i386_gdbarch_tdep *) gdbarch_tdep (gdbarch);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (regnum == -1 || amd64_native_gregset_supplies_p (gdbarch, regnum))
|
if (regnum == -1 || amd64_native_gregset_supplies_p (gdbarch, regnum))
|
||||||
{
|
{
|
||||||
@@ -75,50 +72,9 @@ amd64bsd_fetch_inferior_registers (struct regcache *regcache, int regnum)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef PT_GETFSBASE
|
|
||||||
if (regnum == -1 || regnum == tdep->fsbase_regnum)
|
|
||||||
{
|
|
||||||
register_t base;
|
|
||||||
|
|
||||||
if (gdb_ptrace (PT_GETFSBASE, ptid, (PTRACE_TYPE_ARG3) &base, 0) == -1)
|
|
||||||
perror_with_name (_("Couldn't get segment register fs_base"));
|
|
||||||
|
|
||||||
regcache->raw_supply (tdep->fsbase_regnum, &base);
|
|
||||||
if (regnum != -1)
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
#ifdef PT_GETGSBASE
|
|
||||||
if (regnum == -1 || regnum == tdep->fsbase_regnum + 1)
|
|
||||||
{
|
|
||||||
register_t base;
|
|
||||||
|
|
||||||
if (gdb_ptrace (PT_GETGSBASE, ptid, (PTRACE_TYPE_ARG3) &base, 0) == -1)
|
|
||||||
perror_with_name (_("Couldn't get segment register gs_base"));
|
|
||||||
|
|
||||||
regcache->raw_supply (tdep->fsbase_regnum + 1, &base);
|
|
||||||
if (regnum != -1)
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (regnum == -1 || !amd64_native_gregset_supplies_p (gdbarch, regnum))
|
if (regnum == -1 || !amd64_native_gregset_supplies_p (gdbarch, regnum))
|
||||||
{
|
{
|
||||||
struct fpreg fpregs;
|
struct fpreg fpregs;
|
||||||
#ifdef PT_GETXSTATE_INFO
|
|
||||||
void *xstateregs;
|
|
||||||
|
|
||||||
if (x86bsd_xsave_len != 0)
|
|
||||||
{
|
|
||||||
xstateregs = alloca (x86bsd_xsave_len);
|
|
||||||
if (gdb_ptrace (PT_GETXSTATE, ptid, (PTRACE_TYPE_ARG3) xstateregs, 0)
|
|
||||||
== -1)
|
|
||||||
perror_with_name (_("Couldn't get extended state status"));
|
|
||||||
|
|
||||||
amd64_supply_xsave (regcache, -1, xstateregs);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (gdb_ptrace (PT_GETFPREGS, ptid, (PTRACE_TYPE_ARG3) &fpregs, 0) == -1)
|
if (gdb_ptrace (PT_GETFPREGS, ptid, (PTRACE_TYPE_ARG3) &fpregs, 0) == -1)
|
||||||
perror_with_name (_("Couldn't get floating point status"));
|
perror_with_name (_("Couldn't get floating point status"));
|
||||||
@@ -135,9 +91,6 @@ amd64bsd_store_inferior_registers (struct regcache *regcache, int regnum)
|
|||||||
{
|
{
|
||||||
struct gdbarch *gdbarch = regcache->arch ();
|
struct gdbarch *gdbarch = regcache->arch ();
|
||||||
ptid_t ptid = regcache->ptid ();
|
ptid_t ptid = regcache->ptid ();
|
||||||
#if defined(PT_SETFSBASE) || defined(PT_SETGSBASE)
|
|
||||||
i386_gdbarch_tdep *tdep = (i386_gdbarch_tdep *) gdbarch_tdep (gdbarch);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (regnum == -1 || amd64_native_gregset_supplies_p (gdbarch, regnum))
|
if (regnum == -1 || amd64_native_gregset_supplies_p (gdbarch, regnum))
|
||||||
{
|
{
|
||||||
@@ -155,58 +108,9 @@ amd64bsd_store_inferior_registers (struct regcache *regcache, int regnum)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef PT_SETFSBASE
|
|
||||||
if (regnum == -1 || regnum == tdep->fsbase_regnum)
|
|
||||||
{
|
|
||||||
register_t base;
|
|
||||||
|
|
||||||
/* Clear the full base value to support 32-bit targets. */
|
|
||||||
base = 0;
|
|
||||||
regcache->raw_collect (tdep->fsbase_regnum, &base);
|
|
||||||
|
|
||||||
if (gdb_ptrace (PT_SETFSBASE, ptid, (PTRACE_TYPE_ARG3) &base, 0) == -1)
|
|
||||||
perror_with_name (_("Couldn't write segment register fs_base"));
|
|
||||||
if (regnum != -1)
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
#ifdef PT_SETGSBASE
|
|
||||||
if (regnum == -1 || regnum == tdep->fsbase_regnum + 1)
|
|
||||||
{
|
|
||||||
register_t base;
|
|
||||||
|
|
||||||
/* Clear the full base value to support 32-bit targets. */
|
|
||||||
base = 0;
|
|
||||||
regcache->raw_collect (tdep->fsbase_regnum + 1, &base);
|
|
||||||
|
|
||||||
if (gdb_ptrace (PT_SETGSBASE, ptid, (PTRACE_TYPE_ARG3) &base, 0) == -1)
|
|
||||||
perror_with_name (_("Couldn't write segment register gs_base"));
|
|
||||||
if (regnum != -1)
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (regnum == -1 || !amd64_native_gregset_supplies_p (gdbarch, regnum))
|
if (regnum == -1 || !amd64_native_gregset_supplies_p (gdbarch, regnum))
|
||||||
{
|
{
|
||||||
struct fpreg fpregs;
|
struct fpreg fpregs;
|
||||||
#ifdef PT_GETXSTATE_INFO
|
|
||||||
void *xstateregs;
|
|
||||||
|
|
||||||
if (x86bsd_xsave_len != 0)
|
|
||||||
{
|
|
||||||
xstateregs = alloca (x86bsd_xsave_len);
|
|
||||||
if (gdb_ptrace (PT_GETXSTATE, ptid, (PTRACE_TYPE_ARG3) xstateregs, 0)
|
|
||||||
== -1)
|
|
||||||
perror_with_name (_("Couldn't get extended state status"));
|
|
||||||
|
|
||||||
amd64_collect_xsave (regcache, regnum, xstateregs, 0);
|
|
||||||
|
|
||||||
if (gdb_ptrace (PT_SETXSTATE, ptid, (PTRACE_TYPE_ARG3) xstateregs,
|
|
||||||
x86bsd_xsave_len) == -1)
|
|
||||||
perror_with_name (_("Couldn't write extended state status"));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (gdb_ptrace (PT_GETFPREGS, ptid, (PTRACE_TYPE_ARG3) &fpregs, 0) == -1)
|
if (gdb_ptrace (PT_GETFPREGS, ptid, (PTRACE_TYPE_ARG3) &fpregs, 0) == -1)
|
||||||
perror_with_name (_("Couldn't get floating point status"));
|
perror_with_name (_("Couldn't get floating point status"));
|
||||||
|
|||||||
@@ -31,17 +31,19 @@
|
|||||||
|
|
||||||
#include "fbsd-nat.h"
|
#include "fbsd-nat.h"
|
||||||
#include "amd64-tdep.h"
|
#include "amd64-tdep.h"
|
||||||
|
#include "amd64-fbsd-tdep.h"
|
||||||
#include "amd64-nat.h"
|
#include "amd64-nat.h"
|
||||||
#include "amd64-bsd-nat.h"
|
|
||||||
#include "x86-nat.h"
|
#include "x86-nat.h"
|
||||||
#include "gdbsupport/x86-xstate.h"
|
#include "gdbsupport/x86-xstate.h"
|
||||||
|
#include "x86-bsd-nat.h"
|
||||||
|
|
||||||
class amd64_fbsd_nat_target final
|
class amd64_fbsd_nat_target final
|
||||||
: public amd64_bsd_nat_target<fbsd_nat_target>
|
: public x86bsd_nat_target<fbsd_nat_target>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
/* Add some extra features to the common *BSD/amd64 target. */
|
void fetch_registers (struct regcache *, int) override;
|
||||||
|
void store_registers (struct regcache *, int) override;
|
||||||
|
|
||||||
const struct target_desc *read_description () override;
|
const struct target_desc *read_description () override;
|
||||||
|
|
||||||
#if defined(HAVE_PT_GETDBREGS) && defined(USE_SIGTRAP_SIGINFO)
|
#if defined(HAVE_PT_GETDBREGS) && defined(USE_SIGTRAP_SIGINFO)
|
||||||
@@ -51,61 +53,208 @@ public:
|
|||||||
|
|
||||||
static amd64_fbsd_nat_target the_amd64_fbsd_nat_target;
|
static amd64_fbsd_nat_target the_amd64_fbsd_nat_target;
|
||||||
|
|
||||||
/* Offset in `struct reg' where MEMBER is stored. */
|
#ifdef PT_GETXSTATE_INFO
|
||||||
#define REG_OFFSET(member) offsetof (struct reg, member)
|
static size_t xsave_len;
|
||||||
|
#endif
|
||||||
|
|
||||||
/* At amd64fbsd64_r_reg_offset[REGNUM] you'll find the offset in
|
/* This is a layout of the amd64 'struct reg' but with i386
|
||||||
`struct reg' location where the GDB register REGNUM is stored.
|
registers. */
|
||||||
Unsupported registers are marked with `-1'. */
|
|
||||||
static int amd64fbsd64_r_reg_offset[] =
|
static const struct regcache_map_entry amd64_fbsd32_gregmap[] =
|
||||||
{
|
{
|
||||||
REG_OFFSET (r_rax),
|
{ 8, REGCACHE_MAP_SKIP, 8 },
|
||||||
REG_OFFSET (r_rbx),
|
{ 1, I386_EDI_REGNUM, 8 },
|
||||||
REG_OFFSET (r_rcx),
|
{ 1, I386_ESI_REGNUM, 8 },
|
||||||
REG_OFFSET (r_rdx),
|
{ 1, I386_EBP_REGNUM, 8 },
|
||||||
REG_OFFSET (r_rsi),
|
{ 1, I386_EBX_REGNUM, 8 },
|
||||||
REG_OFFSET (r_rdi),
|
{ 1, I386_EDX_REGNUM, 8 },
|
||||||
REG_OFFSET (r_rbp),
|
{ 1, I386_ECX_REGNUM, 8 },
|
||||||
REG_OFFSET (r_rsp),
|
{ 1, I386_EAX_REGNUM, 8 },
|
||||||
REG_OFFSET (r_r8),
|
{ 1, REGCACHE_MAP_SKIP, 4 }, /* trapno */
|
||||||
REG_OFFSET (r_r9),
|
{ 1, I386_FS_REGNUM, 2 },
|
||||||
REG_OFFSET (r_r10),
|
{ 1, I386_GS_REGNUM, 2 },
|
||||||
REG_OFFSET (r_r11),
|
{ 1, REGCACHE_MAP_SKIP, 4 }, /* err */
|
||||||
REG_OFFSET (r_r12),
|
{ 1, I386_ES_REGNUM, 2 },
|
||||||
REG_OFFSET (r_r13),
|
{ 1, I386_DS_REGNUM, 2 },
|
||||||
REG_OFFSET (r_r14),
|
{ 1, I386_EIP_REGNUM, 8 },
|
||||||
REG_OFFSET (r_r15),
|
{ 1, I386_CS_REGNUM, 8 },
|
||||||
REG_OFFSET (r_rip),
|
{ 1, I386_EFLAGS_REGNUM, 8 },
|
||||||
REG_OFFSET (r_rflags),
|
{ 1, I386_ESP_REGNUM, 0 },
|
||||||
REG_OFFSET (r_cs),
|
{ 1, I386_SS_REGNUM, 8 },
|
||||||
REG_OFFSET (r_ss),
|
{ 0 }
|
||||||
-1,
|
|
||||||
-1,
|
|
||||||
-1,
|
|
||||||
-1
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
/* Mapping between the general-purpose registers in FreeBSD/amd64
|
static const struct regset amd64_fbsd32_gregset =
|
||||||
`struct reg' format and GDB's register cache layout for
|
|
||||||
FreeBSD/i386.
|
|
||||||
|
|
||||||
Note that most FreeBSD/amd64 registers are 64-bit, while the
|
|
||||||
FreeBSD/i386 registers are all 32-bit, but since we're
|
|
||||||
little-endian we get away with that. */
|
|
||||||
|
|
||||||
/* From <machine/reg.h>. */
|
|
||||||
static int amd64fbsd32_r_reg_offset[I386_NUM_GREGS] =
|
|
||||||
{
|
{
|
||||||
14 * 8, 13 * 8, /* %eax, %ecx */
|
amd64_fbsd32_gregmap, regcache_supply_regset, regcache_collect_regset
|
||||||
12 * 8, 11 * 8, /* %edx, %ebx */
|
|
||||||
20 * 8, 10 * 8, /* %esp, %ebp */
|
|
||||||
9 * 8, 8 * 8, /* %esi, %edi */
|
|
||||||
17 * 8, 19 * 8, /* %eip, %eflags */
|
|
||||||
18 * 8, 21 * 8, /* %cs, %ss */
|
|
||||||
-1, -1, -1, -1 /* %ds, %es, %fs, %gs */
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* Return the regset to use for 'struct reg' for the GDBARCH. */
|
||||||
|
|
||||||
|
static const struct regset *
|
||||||
|
find_gregset (struct gdbarch *gdbarch)
|
||||||
|
{
|
||||||
|
if (gdbarch_bfd_arch_info (gdbarch)->bits_per_word == 32)
|
||||||
|
return &amd64_fbsd32_gregset;
|
||||||
|
else
|
||||||
|
return &amd64_fbsd_gregset;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Fetch register REGNUM from the inferior. If REGNUM is -1, do this
|
||||||
|
for all registers. */
|
||||||
|
|
||||||
|
void
|
||||||
|
amd64_fbsd_nat_target::fetch_registers (struct regcache *regcache, int regnum)
|
||||||
|
{
|
||||||
|
struct gdbarch *gdbarch = regcache->arch ();
|
||||||
|
#if defined(PT_GETFSBASE) || defined(PT_GETGSBASE)
|
||||||
|
const i386_gdbarch_tdep *tdep = (i386_gdbarch_tdep *) gdbarch_tdep (gdbarch);
|
||||||
|
#endif
|
||||||
|
pid_t pid = get_ptrace_pid (regcache->ptid ());
|
||||||
|
const struct regset *gregset = find_gregset (gdbarch);
|
||||||
|
|
||||||
|
if (fetch_register_set<struct reg> (regcache, regnum, PT_GETREGS, gregset))
|
||||||
|
{
|
||||||
|
if (regnum != -1)
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef PT_GETFSBASE
|
||||||
|
if (regnum == -1 || regnum == tdep->fsbase_regnum)
|
||||||
|
{
|
||||||
|
register_t base;
|
||||||
|
|
||||||
|
if (ptrace (PT_GETFSBASE, pid, (PTRACE_TYPE_ARG3) &base, 0) == -1)
|
||||||
|
perror_with_name (_("Couldn't get segment register fs_base"));
|
||||||
|
|
||||||
|
regcache->raw_supply (tdep->fsbase_regnum, &base);
|
||||||
|
if (regnum != -1)
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#ifdef PT_GETGSBASE
|
||||||
|
if (regnum == -1 || regnum == tdep->fsbase_regnum + 1)
|
||||||
|
{
|
||||||
|
register_t base;
|
||||||
|
|
||||||
|
if (ptrace (PT_GETGSBASE, pid, (PTRACE_TYPE_ARG3) &base, 0) == -1)
|
||||||
|
perror_with_name (_("Couldn't get segment register gs_base"));
|
||||||
|
|
||||||
|
regcache->raw_supply (tdep->fsbase_regnum + 1, &base);
|
||||||
|
if (regnum != -1)
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* There is no amd64_fxsave_supplies or amd64_xsave_supplies.
|
||||||
|
Instead, the earlier register sets return early if the request
|
||||||
|
was for a specific register that was already satisified to avoid
|
||||||
|
fetching the FPU/XSAVE state unnecessarily. */
|
||||||
|
|
||||||
|
#ifdef PT_GETXSTATE_INFO
|
||||||
|
if (xsave_len != 0)
|
||||||
|
{
|
||||||
|
void *xstateregs = alloca (xsave_len);
|
||||||
|
|
||||||
|
if (ptrace (PT_GETXSTATE, pid, (PTRACE_TYPE_ARG3) xstateregs, 0) == -1)
|
||||||
|
perror_with_name (_("Couldn't get extended state status"));
|
||||||
|
|
||||||
|
amd64_supply_xsave (regcache, regnum, xstateregs);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
struct fpreg fpregs;
|
||||||
|
|
||||||
|
if (ptrace (PT_GETFPREGS, pid, (PTRACE_TYPE_ARG3) &fpregs, 0) == -1)
|
||||||
|
perror_with_name (_("Couldn't get floating point status"));
|
||||||
|
|
||||||
|
amd64_supply_fxsave (regcache, regnum, &fpregs);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Store register REGNUM back into the inferior. If REGNUM is -1, do
|
||||||
|
this for all registers. */
|
||||||
|
|
||||||
|
void
|
||||||
|
amd64_fbsd_nat_target::store_registers (struct regcache *regcache, int regnum)
|
||||||
|
{
|
||||||
|
struct gdbarch *gdbarch = regcache->arch ();
|
||||||
|
#if defined(PT_GETFSBASE) || defined(PT_GETGSBASE)
|
||||||
|
const i386_gdbarch_tdep *tdep = (i386_gdbarch_tdep *) gdbarch_tdep (gdbarch);
|
||||||
|
#endif
|
||||||
|
pid_t pid = get_ptrace_pid (regcache->ptid ());
|
||||||
|
const struct regset *gregset = find_gregset (gdbarch);
|
||||||
|
|
||||||
|
if (store_register_set<struct reg> (regcache, regnum, PT_GETREGS, PT_SETREGS,
|
||||||
|
gregset))
|
||||||
|
{
|
||||||
|
if (regnum != -1)
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef PT_SETFSBASE
|
||||||
|
if (regnum == -1 || regnum == tdep->fsbase_regnum)
|
||||||
|
{
|
||||||
|
register_t base;
|
||||||
|
|
||||||
|
/* Clear the full base value to support 32-bit targets. */
|
||||||
|
base = 0;
|
||||||
|
regcache->raw_collect (tdep->fsbase_regnum, &base);
|
||||||
|
|
||||||
|
if (ptrace (PT_SETFSBASE, pid, (PTRACE_TYPE_ARG3) &base, 0) == -1)
|
||||||
|
perror_with_name (_("Couldn't write segment register fs_base"));
|
||||||
|
if (regnum != -1)
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#ifdef PT_SETGSBASE
|
||||||
|
if (regnum == -1 || regnum == tdep->fsbase_regnum + 1)
|
||||||
|
{
|
||||||
|
register_t base;
|
||||||
|
|
||||||
|
/* Clear the full base value to support 32-bit targets. */
|
||||||
|
base = 0;
|
||||||
|
regcache->raw_collect (tdep->fsbase_regnum + 1, &base);
|
||||||
|
|
||||||
|
if (ptrace (PT_SETGSBASE, pid, (PTRACE_TYPE_ARG3) &base, 0) == -1)
|
||||||
|
perror_with_name (_("Couldn't write segment register gs_base"));
|
||||||
|
if (regnum != -1)
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* There is no amd64_fxsave_supplies or amd64_xsave_supplies.
|
||||||
|
Instead, the earlier register sets return early if the request
|
||||||
|
was for a specific register that was already satisified to avoid
|
||||||
|
fetching the FPU/XSAVE state unnecessarily. */
|
||||||
|
|
||||||
|
#ifdef PT_GETXSTATE_INFO
|
||||||
|
if (xsave_len != 0)
|
||||||
|
{
|
||||||
|
void *xstateregs = alloca (xsave_len);
|
||||||
|
|
||||||
|
if (ptrace (PT_GETXSTATE, pid, (PTRACE_TYPE_ARG3) xstateregs, 0) == -1)
|
||||||
|
perror_with_name (_("Couldn't get extended state status"));
|
||||||
|
|
||||||
|
amd64_collect_xsave (regcache, regnum, xstateregs, 0);
|
||||||
|
|
||||||
|
if (ptrace (PT_SETXSTATE, pid, (PTRACE_TYPE_ARG3) xstateregs,
|
||||||
|
xsave_len) == -1)
|
||||||
|
perror_with_name (_("Couldn't write extended state status"));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
struct fpreg fpregs;
|
||||||
|
|
||||||
|
if (ptrace (PT_GETFPREGS, pid, (PTRACE_TYPE_ARG3) &fpregs, 0) == -1)
|
||||||
|
perror_with_name (_("Couldn't get floating point status"));
|
||||||
|
|
||||||
|
amd64_collect_fxsave (regcache, regnum, &fpregs);
|
||||||
|
|
||||||
|
if (ptrace (PT_SETFPREGS, pid, (PTRACE_TYPE_ARG3) &fpregs, 0) == -1)
|
||||||
|
perror_with_name (_("Couldn't write floating point status"));
|
||||||
|
}
|
||||||
|
|
||||||
/* Support for debugging kernel virtual memory images. */
|
/* Support for debugging kernel virtual memory images. */
|
||||||
|
|
||||||
@@ -179,13 +328,13 @@ amd64_fbsd_nat_target::read_description ()
|
|||||||
if (ptrace (PT_GETXSTATE_INFO, inferior_ptid.pid (),
|
if (ptrace (PT_GETXSTATE_INFO, inferior_ptid.pid (),
|
||||||
(PTRACE_TYPE_ARG3) &info, sizeof (info)) == 0)
|
(PTRACE_TYPE_ARG3) &info, sizeof (info)) == 0)
|
||||||
{
|
{
|
||||||
x86bsd_xsave_len = info.xsave_len;
|
xsave_len = info.xsave_len;
|
||||||
xcr0 = info.xsave_mask;
|
xcr0 = info.xsave_mask;
|
||||||
}
|
}
|
||||||
xsave_probed = 1;
|
xsave_probed = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (x86bsd_xsave_len != 0)
|
if (xsave_len != 0)
|
||||||
{
|
{
|
||||||
if (is64)
|
if (is64)
|
||||||
return amd64_target_description (xcr0, true);
|
return amd64_target_description (xcr0, true);
|
||||||
@@ -213,9 +362,6 @@ void _initialize_amd64fbsd_nat ();
|
|||||||
void
|
void
|
||||||
_initialize_amd64fbsd_nat ()
|
_initialize_amd64fbsd_nat ()
|
||||||
{
|
{
|
||||||
amd64_native_gregset32_reg_offset = amd64fbsd32_r_reg_offset;
|
|
||||||
amd64_native_gregset64_reg_offset = amd64fbsd64_r_reg_offset;
|
|
||||||
|
|
||||||
add_inf_child_target (&the_amd64_fbsd_nat_target);
|
add_inf_child_target (&the_amd64_fbsd_nat_target);
|
||||||
|
|
||||||
/* Support debugging kernel virtual memory images. */
|
/* Support debugging kernel virtual memory images. */
|
||||||
|
|||||||
@@ -27,6 +27,7 @@
|
|||||||
#include "gdbsupport/x86-xstate.h"
|
#include "gdbsupport/x86-xstate.h"
|
||||||
|
|
||||||
#include "amd64-tdep.h"
|
#include "amd64-tdep.h"
|
||||||
|
#include "amd64-fbsd-tdep.h"
|
||||||
#include "fbsd-tdep.h"
|
#include "fbsd-tdep.h"
|
||||||
#include "solib-svr4.h"
|
#include "solib-svr4.h"
|
||||||
#include "inferior.h"
|
#include "inferior.h"
|
||||||
|
|||||||
27
gdb/amd64-fbsd-tdep.h
Normal file
27
gdb/amd64-fbsd-tdep.h
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
/* FreeBSD/amd64 target support, prototypes.
|
||||||
|
|
||||||
|
Copyright (C) 2021 Free Software Foundation, Inc.
|
||||||
|
|
||||||
|
This file is part of GDB.
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>. */
|
||||||
|
|
||||||
|
#ifndef AMD64_FBSD_TDEP_H
|
||||||
|
#define AMD64_FBSD_TDEP_H
|
||||||
|
|
||||||
|
#include "regset.h"
|
||||||
|
|
||||||
|
extern const struct regset amd64_fbsd_gregset;
|
||||||
|
|
||||||
|
#endif /* AMD64_FBSD_TDEP_H */
|
||||||
@@ -165,7 +165,7 @@ case ${gdb_host} in
|
|||||||
i386)
|
i386)
|
||||||
# Host: FreeBSD/i386
|
# Host: FreeBSD/i386
|
||||||
NATDEPFILES="${NATDEPFILES} x86-nat.o nat/x86-dregs.o \
|
NATDEPFILES="${NATDEPFILES} x86-nat.o nat/x86-dregs.o \
|
||||||
x86-bsd-nat.o i386-bsd-nat.o i386-fbsd-nat.o bsd-kvm.o"
|
x86-bsd-nat.o i386-fbsd-nat.o bsd-kvm.o"
|
||||||
;;
|
;;
|
||||||
mips)
|
mips)
|
||||||
# Host: FreeBSD/mips
|
# Host: FreeBSD/mips
|
||||||
@@ -192,7 +192,7 @@ case ${gdb_host} in
|
|||||||
case ${gdb_host_cpu} in
|
case ${gdb_host_cpu} in
|
||||||
i386)
|
i386)
|
||||||
# Host: FreeBSD/amd64
|
# Host: FreeBSD/amd64
|
||||||
NATDEPFILES="${NATDEPFILES} amd64-nat.o amd64-bsd-nat.o \
|
NATDEPFILES="${NATDEPFILES} amd64-nat.o \
|
||||||
amd64-fbsd-nat.o bsd-kvm.o x86-nat.o nat/x86-dregs.o \
|
amd64-fbsd-nat.o bsd-kvm.o x86-nat.o nat/x86-dregs.o \
|
||||||
x86-bsd-nat.o"
|
x86-bsd-nat.o"
|
||||||
;;
|
;;
|
||||||
|
|||||||
@@ -159,56 +159,12 @@ i386bsd_fetch_inferior_registers (struct regcache *regcache, int regnum)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef PT_GETFSBASE
|
|
||||||
if (regnum == -1 || regnum == I386_FSBASE_REGNUM)
|
|
||||||
{
|
|
||||||
register_t base;
|
|
||||||
|
|
||||||
if (gdb_ptrace (PT_GETFSBASE, ptid, (PTRACE_TYPE_ARG3) &base, 0) == -1)
|
|
||||||
perror_with_name (_("Couldn't get segment register fs_base"));
|
|
||||||
|
|
||||||
regcache->raw_supply (I386_FSBASE_REGNUM, &base);
|
|
||||||
if (regnum != -1)
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
#ifdef PT_GETGSBASE
|
|
||||||
if (regnum == -1 || regnum == I386_GSBASE_REGNUM)
|
|
||||||
{
|
|
||||||
register_t base;
|
|
||||||
|
|
||||||
if (gdb_ptrace (PT_GETGSBASE, ptid, (PTRACE_TYPE_ARG3) &base, 0) == -1)
|
|
||||||
perror_with_name (_("Couldn't get segment register gs_base"));
|
|
||||||
|
|
||||||
regcache->raw_supply (I386_GSBASE_REGNUM, &base);
|
|
||||||
if (regnum != -1)
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (regnum == -1 || regnum >= I386_ST0_REGNUM)
|
if (regnum == -1 || regnum >= I386_ST0_REGNUM)
|
||||||
{
|
{
|
||||||
struct fpreg fpregs;
|
struct fpreg fpregs;
|
||||||
#ifdef HAVE_PT_GETXMMREGS
|
#ifdef HAVE_PT_GETXMMREGS
|
||||||
char xmmregs[512];
|
char xmmregs[512];
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef PT_GETXSTATE_INFO
|
|
||||||
if (x86bsd_xsave_len != 0)
|
|
||||||
{
|
|
||||||
void *xstateregs;
|
|
||||||
|
|
||||||
xstateregs = alloca (x86bsd_xsave_len);
|
|
||||||
if (gdb_ptrace (PT_GETXSTATE, ptid,
|
|
||||||
(PTRACE_TYPE_ARG3) xstateregs, 0) == -1)
|
|
||||||
perror_with_name (_("Couldn't get extended state status"));
|
|
||||||
|
|
||||||
i387_supply_xsave (regcache, -1, xstateregs);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef HAVE_PT_GETXMMREGS
|
|
||||||
if (have_ptrace_xmmregs != 0
|
if (have_ptrace_xmmregs != 0
|
||||||
&& gdb_ptrace(PT_GETXMMREGS, ptid,
|
&& gdb_ptrace(PT_GETXMMREGS, ptid,
|
||||||
(PTRACE_TYPE_ARG3) xmmregs, 0) == 0)
|
(PTRACE_TYPE_ARG3) xmmregs, 0) == 0)
|
||||||
@@ -255,60 +211,12 @@ i386bsd_store_inferior_registers (struct regcache *regcache, int regnum)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef PT_SETFSBASE
|
|
||||||
if (regnum == -1 || regnum == I386_FSBASE_REGNUM)
|
|
||||||
{
|
|
||||||
register_t base;
|
|
||||||
|
|
||||||
regcache->raw_collect (I386_FSBASE_REGNUM, &base);
|
|
||||||
|
|
||||||
if (gdb_ptrace (PT_SETFSBASE, ptid, (PTRACE_TYPE_ARG3) &base, 0) == -1)
|
|
||||||
perror_with_name (_("Couldn't write segment register fs_base"));
|
|
||||||
if (regnum != -1)
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
#ifdef PT_SETGSBASE
|
|
||||||
if (regnum == -1 || regnum == I386_GSBASE_REGNUM)
|
|
||||||
{
|
|
||||||
register_t base;
|
|
||||||
|
|
||||||
regcache->raw_collect (I386_GSBASE_REGNUM, &base);
|
|
||||||
|
|
||||||
if (gdb_ptrace (PT_SETGSBASE, ptid, (PTRACE_TYPE_ARG3) &base, 0) == -1)
|
|
||||||
perror_with_name (_("Couldn't write segment register gs_base"));
|
|
||||||
if (regnum != -1)
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (regnum == -1 || regnum >= I386_ST0_REGNUM)
|
if (regnum == -1 || regnum >= I386_ST0_REGNUM)
|
||||||
{
|
{
|
||||||
struct fpreg fpregs;
|
struct fpreg fpregs;
|
||||||
#ifdef HAVE_PT_GETXMMREGS
|
#ifdef HAVE_PT_GETXMMREGS
|
||||||
char xmmregs[512];
|
char xmmregs[512];
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef PT_GETXSTATE_INFO
|
|
||||||
if (x86bsd_xsave_len != 0)
|
|
||||||
{
|
|
||||||
void *xstateregs;
|
|
||||||
|
|
||||||
xstateregs = alloca (x86bsd_xsave_len);
|
|
||||||
if (gdb_ptrace (PT_GETXSTATE, ptid,
|
|
||||||
(PTRACE_TYPE_ARG3) xstateregs, 0) == -1)
|
|
||||||
perror_with_name (_("Couldn't get extended state status"));
|
|
||||||
|
|
||||||
i387_collect_xsave (regcache, -1, xstateregs, 0);
|
|
||||||
|
|
||||||
if (gdb_ptrace (PT_SETXSTATE, ptid, (PTRACE_TYPE_ARG3) xstateregs,
|
|
||||||
x86bsd_xsave_len) == -1)
|
|
||||||
perror_with_name (_("Couldn't write extended state status"));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef HAVE_PT_GETXMMREGS
|
|
||||||
if (have_ptrace_xmmregs != 0
|
if (have_ptrace_xmmregs != 0
|
||||||
&& gdb_ptrace(PT_GETXMMREGS, ptid,
|
&& gdb_ptrace(PT_GETXMMREGS, ptid,
|
||||||
(PTRACE_TYPE_ARG3) xmmregs, 0) == 0)
|
(PTRACE_TYPE_ARG3) xmmregs, 0) == 0)
|
||||||
|
|||||||
@@ -29,17 +29,20 @@
|
|||||||
|
|
||||||
#include "fbsd-nat.h"
|
#include "fbsd-nat.h"
|
||||||
#include "i386-tdep.h"
|
#include "i386-tdep.h"
|
||||||
|
#include "i386-fbsd-tdep.h"
|
||||||
|
#include "i387-tdep.h"
|
||||||
#include "x86-nat.h"
|
#include "x86-nat.h"
|
||||||
#include "gdbsupport/x86-xstate.h"
|
#include "gdbsupport/x86-xstate.h"
|
||||||
#include "x86-bsd-nat.h"
|
#include "x86-bsd-nat.h"
|
||||||
#include "i386-bsd-nat.h"
|
|
||||||
|
|
||||||
class i386_fbsd_nat_target final
|
class i386_fbsd_nat_target final
|
||||||
: public i386_bsd_nat_target<fbsd_nat_target>
|
: public x86bsd_nat_target<fbsd_nat_target>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
/* Add some extra features to the common *BSD/i386 target. */
|
void fetch_registers (struct regcache *, int) override;
|
||||||
#ifdef PT_GETXSTATE_INFO
|
void store_registers (struct regcache *, int) override;
|
||||||
|
|
||||||
|
#if defined(PT_GETXMMREGS) || defined(PT_GETXSTATE_INFO)
|
||||||
const struct target_desc *read_description () override;
|
const struct target_desc *read_description () override;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -52,6 +55,192 @@ public:
|
|||||||
|
|
||||||
static i386_fbsd_nat_target the_i386_fbsd_nat_target;
|
static i386_fbsd_nat_target the_i386_fbsd_nat_target;
|
||||||
|
|
||||||
|
#ifdef PT_GETXSTATE_INFO
|
||||||
|
static size_t xsave_len;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef HAVE_PT_GETXMMREGS
|
||||||
|
static int have_ptrace_xmmregs;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Fetch register REGNUM from the inferior. If REGNUM is -1, do this
|
||||||
|
for all registers. */
|
||||||
|
|
||||||
|
void
|
||||||
|
i386_fbsd_nat_target::fetch_registers (struct regcache *regcache, int regnum)
|
||||||
|
{
|
||||||
|
struct gdbarch *gdbarch = regcache->arch ();
|
||||||
|
#if defined(PT_GETFSBASE) || defined(PT_GETGSBASE)
|
||||||
|
const struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
|
||||||
|
#endif
|
||||||
|
pid_t pid = get_ptrace_pid (regcache->ptid ());
|
||||||
|
|
||||||
|
if (fetch_register_set<struct reg> (regcache, regnum, PT_GETREGS,
|
||||||
|
&i386_fbsd_gregset))
|
||||||
|
{
|
||||||
|
if (regnum != -1)
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef PT_GETFSBASE
|
||||||
|
if (regnum == -1 || regnum == I386_FSBASE_REGNUM)
|
||||||
|
{
|
||||||
|
register_t base;
|
||||||
|
|
||||||
|
if (ptrace (PT_GETFSBASE, pid, (PTRACE_TYPE_ARG3) &base, 0) == -1)
|
||||||
|
perror_with_name (_("Couldn't get segment register fs_base"));
|
||||||
|
|
||||||
|
regcache->raw_supply (I386_FSBASE_REGNUM, &base);
|
||||||
|
if (regnum != -1)
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#ifdef PT_GETGSBASE
|
||||||
|
if (regnum == -1 || regnum == I386_GSBASE_REGNUM)
|
||||||
|
{
|
||||||
|
register_t base;
|
||||||
|
|
||||||
|
if (ptrace (PT_GETGSBASE, pid, (PTRACE_TYPE_ARG3) &base, 0) == -1)
|
||||||
|
perror_with_name (_("Couldn't get segment register gs_base"));
|
||||||
|
|
||||||
|
regcache->raw_supply (I386_GSBASE_REGNUM, &base);
|
||||||
|
if (regnum != -1)
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* There is no i386_fxsave_supplies or i386_xsave_supplies.
|
||||||
|
Instead, the earlier register sets return early if the request
|
||||||
|
was for a specific register that was already satisified to avoid
|
||||||
|
fetching the FPU/XSAVE state unnecessarily. */
|
||||||
|
|
||||||
|
#ifdef PT_GETXSTATE_INFO
|
||||||
|
if (xsave_len != 0)
|
||||||
|
{
|
||||||
|
void *xstateregs = alloca (xsave_len);
|
||||||
|
|
||||||
|
if (ptrace (PT_GETXSTATE, pid, (PTRACE_TYPE_ARG3) xstateregs, 0) == -1)
|
||||||
|
perror_with_name (_("Couldn't get extended state status"));
|
||||||
|
|
||||||
|
i387_supply_xsave (regcache, regnum, xstateregs);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_PT_GETXMMREGS
|
||||||
|
if (have_ptrace_xmmregs != 0)
|
||||||
|
{
|
||||||
|
char xmmregs[I387_SIZEOF_FXSAVE];
|
||||||
|
|
||||||
|
if (ptrace(PT_GETXMMREGS, pid, (PTRACE_TYPE_ARG3) xmmregs, 0) == -1)
|
||||||
|
perror_with_name (_("Couldn't get XMM registers"));
|
||||||
|
|
||||||
|
i387_supply_fxsave (regcache, regnum, xmmregs);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
struct fpreg fpregs;
|
||||||
|
|
||||||
|
if (ptrace (PT_GETFPREGS, pid, (PTRACE_TYPE_ARG3) &fpregs, 0) == -1)
|
||||||
|
perror_with_name (_("Couldn't get floating point status"));
|
||||||
|
|
||||||
|
i387_supply_fsave (regcache, regnum, &fpregs);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Store register REGNUM back into the inferior. If REGNUM is -1, do
|
||||||
|
this for all registers. */
|
||||||
|
|
||||||
|
void
|
||||||
|
i386_fbsd_nat_target::store_registers (struct regcache *regcache, int regnum)
|
||||||
|
{
|
||||||
|
struct gdbarch *gdbarch = regcache->arch ();
|
||||||
|
#if defined(PT_GETFSBASE) || defined(PT_GETGSBASE)
|
||||||
|
const struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
|
||||||
|
#endif
|
||||||
|
pid_t pid = get_ptrace_pid (regcache->ptid ());
|
||||||
|
|
||||||
|
if (store_register_set<struct reg> (regcache, regnum, PT_GETREGS, PT_SETREGS,
|
||||||
|
&i386_fbsd_gregset))
|
||||||
|
{
|
||||||
|
if (regnum != -1)
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef PT_SETFSBASE
|
||||||
|
if (regnum == -1 || regnum == I386_FSBASE_REGNUM)
|
||||||
|
{
|
||||||
|
register_t base;
|
||||||
|
|
||||||
|
regcache->raw_collect (I386_FSBASE_REGNUM, &base);
|
||||||
|
|
||||||
|
if (ptrace (PT_SETFSBASE, pid, (PTRACE_TYPE_ARG3) &base, 0) == -1)
|
||||||
|
perror_with_name (_("Couldn't write segment register fs_base"));
|
||||||
|
if (regnum != -1)
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#ifdef PT_SETGSBASE
|
||||||
|
if (regnum == -1 || regnum == I386_GSBASE_REGNUM)
|
||||||
|
{
|
||||||
|
register_t base;
|
||||||
|
|
||||||
|
regcache->raw_collect (I386_GSBASE_REGNUM, &base);
|
||||||
|
|
||||||
|
if (ptrace (PT_SETGSBASE, pid, (PTRACE_TYPE_ARG3) &base, 0) == -1)
|
||||||
|
perror_with_name (_("Couldn't write segment register gs_base"));
|
||||||
|
if (regnum != -1)
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* There is no i386_fxsave_supplies or i386_xsave_supplies.
|
||||||
|
Instead, the earlier register sets return early if the request
|
||||||
|
was for a specific register that was already satisified to avoid
|
||||||
|
fetching the FPU/XSAVE state unnecessarily. */
|
||||||
|
|
||||||
|
#ifdef PT_GETXSTATE_INFO
|
||||||
|
if (xsave_len != 0)
|
||||||
|
{
|
||||||
|
void *xstateregs = alloca (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)
|
||||||
|
perror_with_name (_("Couldn't write extended state status"));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_PT_GETXMMREGS
|
||||||
|
if (have_ptrace_xmmregs != 0)
|
||||||
|
{
|
||||||
|
char xmmregs[I387_SIZEOF_FXSAVE];
|
||||||
|
|
||||||
|
if (ptrace(PT_GETXMMREGS, pid, (PTRACE_TYPE_ARG3) xmmregs, 0) == -1)
|
||||||
|
perror_with_name (_("Couldn't get XMM registers"));
|
||||||
|
|
||||||
|
i387_collect_fxsave (regcache, regnum, xmmregs);
|
||||||
|
|
||||||
|
if (ptrace (PT_SETXMMREGS, pid, (PTRACE_TYPE_ARG3) xmmregs, 0) == -1)
|
||||||
|
perror_with_name (_("Couldn't write XMM registers"));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
struct fpreg fpregs;
|
||||||
|
|
||||||
|
if (ptrace (PT_GETFPREGS, pid, (PTRACE_TYPE_ARG3) &fpregs, 0) == -1)
|
||||||
|
perror_with_name (_("Couldn't get floating point status"));
|
||||||
|
|
||||||
|
i387_collect_fsave (regcache, regnum, &fpregs);
|
||||||
|
|
||||||
|
if (ptrace (PT_SETFPREGS, pid, (PTRACE_TYPE_ARG3) &fpregs, 0) == -1)
|
||||||
|
perror_with_name (_("Couldn't write floating point status"));
|
||||||
|
}
|
||||||
|
|
||||||
/* Resume execution of the inferior process. If STEP is nonzero,
|
/* Resume execution of the inferior process. If STEP is nonzero,
|
||||||
single-step it. If SIGNAL is nonzero, give it that signal. */
|
single-step it. If SIGNAL is nonzero, give it that signal. */
|
||||||
|
|
||||||
@@ -135,15 +324,21 @@ i386fbsd_supply_pcb (struct regcache *regcache, struct pcb *pcb)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#ifdef PT_GETXSTATE_INFO
|
#if defined(PT_GETXMMREGS) || defined(PT_GETXSTATE_INFO)
|
||||||
/* Implement the read_description method. */
|
/* Implement the read_description method. */
|
||||||
|
|
||||||
const struct target_desc *
|
const struct target_desc *
|
||||||
i386_fbsd_nat_target::read_description ()
|
i386_fbsd_nat_target::read_description ()
|
||||||
{
|
{
|
||||||
|
#ifdef PT_GETXSTATE_INFO
|
||||||
static int xsave_probed;
|
static int xsave_probed;
|
||||||
static uint64_t xcr0;
|
static uint64_t xcr0;
|
||||||
|
#endif
|
||||||
|
#ifdef PT_GETXMMREGS
|
||||||
|
static int xmm_probed;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef PT_GETXSTATE_INFO
|
||||||
if (!xsave_probed)
|
if (!xsave_probed)
|
||||||
{
|
{
|
||||||
struct ptrace_xstate_info info;
|
struct ptrace_xstate_info info;
|
||||||
@@ -151,16 +346,32 @@ i386_fbsd_nat_target::read_description ()
|
|||||||
if (ptrace (PT_GETXSTATE_INFO, inferior_ptid.pid (),
|
if (ptrace (PT_GETXSTATE_INFO, inferior_ptid.pid (),
|
||||||
(PTRACE_TYPE_ARG3) &info, sizeof (info)) == 0)
|
(PTRACE_TYPE_ARG3) &info, sizeof (info)) == 0)
|
||||||
{
|
{
|
||||||
x86bsd_xsave_len = info.xsave_len;
|
xsave_len = info.xsave_len;
|
||||||
xcr0 = info.xsave_mask;
|
xcr0 = info.xsave_mask;
|
||||||
}
|
}
|
||||||
xsave_probed = 1;
|
xsave_probed = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (x86bsd_xsave_len == 0)
|
if (xsave_len != 0)
|
||||||
xcr0 = X86_XSTATE_SSE_MASK;
|
|
||||||
|
|
||||||
return i386_target_description (xcr0, true);
|
return i386_target_description (xcr0, true);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef PT_GETXMMREGS
|
||||||
|
if (!xmm_probed)
|
||||||
|
{
|
||||||
|
char xmmregs[I387_SIZEOF_FXSAVE];
|
||||||
|
|
||||||
|
if (ptrace (PT_GETXMMREGS, inferior_ptid.pid (),
|
||||||
|
(PTRACE_TYPE_ARG3) xmmregs, 0) == 0)
|
||||||
|
have_ptrace_xmmregs = 1;
|
||||||
|
xmm_probed = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (have_ptrace_xmmregs)
|
||||||
|
return i386_target_description (X86_XSTATE_SSE_MASK, true);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return i386_target_description (X86_XSTATE_X87_MASK, true);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|||||||
@@ -20,6 +20,8 @@
|
|||||||
#ifndef I386_FBSD_TDEP_H
|
#ifndef I386_FBSD_TDEP_H
|
||||||
#define I386_FBSD_TDEP_H
|
#define I386_FBSD_TDEP_H
|
||||||
|
|
||||||
|
#include "regset.h"
|
||||||
|
|
||||||
/* Get XSAVE extended state xcr0 from core dump. */
|
/* Get XSAVE extended state xcr0 from core dump. */
|
||||||
extern uint64_t i386fbsd_core_read_xcr0 (bfd *abfd);
|
extern uint64_t i386fbsd_core_read_xcr0 (bfd *abfd);
|
||||||
|
|
||||||
@@ -28,4 +30,6 @@ extern uint64_t i386fbsd_core_read_xcr0 (bfd *abfd);
|
|||||||
matches the layout on Linux. */
|
matches the layout on Linux. */
|
||||||
#define I386_FBSD_XSAVE_XCR0_OFFSET 464
|
#define I386_FBSD_XSAVE_XCR0_OFFSET 464
|
||||||
|
|
||||||
|
extern const struct regset i386_fbsd_gregset;
|
||||||
|
|
||||||
#endif /* i386-fbsd-tdep.h */
|
#endif /* i386-fbsd-tdep.h */
|
||||||
|
|||||||
@@ -33,10 +33,6 @@
|
|||||||
#include "inf-ptrace.h"
|
#include "inf-ptrace.h"
|
||||||
|
|
||||||
|
|
||||||
#ifdef PT_GETXSTATE_INFO
|
|
||||||
size_t x86bsd_xsave_len;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Support for debug registers. */
|
/* Support for debug registers. */
|
||||||
|
|
||||||
#ifdef HAVE_PT_GETDBREGS
|
#ifdef HAVE_PT_GETDBREGS
|
||||||
|
|||||||
@@ -22,9 +22,6 @@
|
|||||||
|
|
||||||
#include "x86-nat.h"
|
#include "x86-nat.h"
|
||||||
|
|
||||||
/* Low level x86 XSAVE info. */
|
|
||||||
extern size_t x86bsd_xsave_len;
|
|
||||||
|
|
||||||
/* A prototype *BSD/x86 target. */
|
/* A prototype *BSD/x86 target. */
|
||||||
|
|
||||||
#ifdef HAVE_PT_GETDBREGS
|
#ifdef HAVE_PT_GETDBREGS
|
||||||
|
|||||||
Reference in New Issue
Block a user