gdb: Update x86 FreeBSD architectures to support XSAVE layouts.

Refactor i386fbsd_core_read_xcr0 to fetch and return a corresponding
x86_xsave_layout as well as xcr0 using the size of an existing
NT_X86_XSTATE core dump to determine the offsets via
i387_guess_xsave_layout.  Use this to add an implementation of
gdbarch_core_xfer_x86_xsave_layout.

Use tdep->xsave_layout.sizeof_xsave as the size of the XSTATE register
set and only fetch/store the register set if this size is non-zero.

Approved-By: Simon Marchi <simon.marchi@efficios.com>
This commit is contained in:
John Baldwin 2023-08-28 14:18:19 -07:00
parent 2e639674c5
commit 22ca5c1027
3 changed files with 64 additions and 36 deletions

View File

@ -224,7 +224,12 @@ amd64fbsd_core_read_description (struct gdbarch *gdbarch,
struct target_ops *target,
bfd *abfd)
{
return amd64_target_description (i386fbsd_core_read_xcr0 (abfd), true);
x86_xsave_layout layout;
uint64_t xcr0 = i386_fbsd_core_read_xsave_info (abfd, layout);
if (xcr0 == 0)
xcr0 = X86_XSTATE_SSE_MASK;
return amd64_target_description (xcr0, true);
}
/* Similar to amd64_supply_fpregset, but use XSAVE extended state. */
@ -271,8 +276,10 @@ amd64fbsd_iterate_over_regset_sections (struct gdbarch *gdbarch,
cb (".reg-x86-segbases", AMD64_FBSD_SIZEOF_SEGBASES_REGSET,
AMD64_FBSD_SIZEOF_SEGBASES_REGSET, &amd64_fbsd_segbases_regset,
"segment bases", cb_data);
cb (".reg-xstate", X86_XSTATE_SIZE (tdep->xcr0), X86_XSTATE_SIZE (tdep->xcr0),
&amd64fbsd_xstateregset, "XSAVE extended state", cb_data);
if (tdep->xsave_layout.sizeof_xsave != 0)
cb (".reg-xstate", tdep->xsave_layout.sizeof_xsave,
tdep->xsave_layout.sizeof_xsave, &amd64fbsd_xstateregset,
"XSAVE extended state", cb_data);
}
/* Implement the get_thread_local_address gdbarch method. */
@ -313,6 +320,8 @@ amd64fbsd_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
tramp_frame_prepend_unwinder (gdbarch, &amd64_fbsd_sigframe);
tdep->xsave_xcr0_offset = I386_FBSD_XSAVE_XCR0_OFFSET;
set_gdbarch_core_read_x86_xsave_layout
(gdbarch, i386_fbsd_core_read_x86_xsave_layout);
/* Iterate over core file register note sections. */
set_gdbarch_iterate_over_regset_sections

View File

@ -18,13 +18,13 @@
along with this program. If not, see <http://www.gnu.org/licenses/>. */
#include "defs.h"
#include "gdbcore.h"
#include "osabi.h"
#include "regcache.h"
#include "regset.h"
#include "trad-frame.h"
#include "tramp-frame.h"
#include "i386-fbsd-tdep.h"
#include "gdbsupport/x86-xstate.h"
#include "i386-tdep.h"
#include "i387-tdep.h"
@ -241,43 +241,46 @@ static const struct tramp_frame i386_fbsd64_sigframe =
i386_fbsd_sigframe_init
};
/* Get XSAVE extended state xcr0 from core dump. */
/* See i386-fbsd-tdep.h. */
uint64_t
i386fbsd_core_read_xcr0 (bfd *abfd)
i386_fbsd_core_read_xsave_info (bfd *abfd, x86_xsave_layout &layout)
{
asection *xstate = bfd_get_section_by_name (abfd, ".reg-xstate");
uint64_t xcr0;
if (xstate == nullptr)
return 0;
if (xstate)
/* Check extended state size. */
size_t size = bfd_section_size (xstate);
if (size < X86_XSTATE_AVX_SIZE)
return 0;
char contents[8];
if (! bfd_get_section_contents (abfd, xstate, contents,
I386_FBSD_XSAVE_XCR0_OFFSET, 8))
{
size_t size = bfd_section_size (xstate);
/* Check extended state size. */
if (size < X86_XSTATE_AVX_SIZE)
xcr0 = X86_XSTATE_SSE_MASK;
else
{
char contents[8];
if (! bfd_get_section_contents (abfd, xstate, contents,
I386_FBSD_XSAVE_XCR0_OFFSET,
8))
{
warning (_("Couldn't read `xcr0' bytes from "
"`.reg-xstate' section in core file."));
return X86_XSTATE_SSE_MASK;
}
xcr0 = bfd_get_64 (abfd, contents);
}
warning (_("Couldn't read `xcr0' bytes from "
"`.reg-xstate' section in core file."));
return 0;
}
else
xcr0 = X86_XSTATE_SSE_MASK;
uint64_t xcr0 = bfd_get_64 (abfd, contents);
if (!i387_guess_xsave_layout (xcr0, size, layout))
return 0;
return xcr0;
}
/* See i386-fbsd-tdep.h. */
bool
i386_fbsd_core_read_x86_xsave_layout (struct gdbarch *gdbarch,
x86_xsave_layout &layout)
{
return i386_fbsd_core_read_xsave_info (core_bfd, layout) != 0;
}
/* Implement the core_read_description gdbarch method. */
static const struct target_desc *
@ -285,7 +288,11 @@ i386fbsd_core_read_description (struct gdbarch *gdbarch,
struct target_ops *target,
bfd *abfd)
{
return i386_target_description (i386fbsd_core_read_xcr0 (abfd), true);
x86_xsave_layout layout;
uint64_t xcr0 = i386_fbsd_core_read_xsave_info (abfd, layout);
if (xcr0 == 0)
xcr0 = X86_XSTATE_X87_MASK;
return i386_target_description (xcr0, true);
}
/* Similar to i386_supply_fpregset, but use XSAVE extended state. */
@ -335,9 +342,9 @@ i386fbsd_iterate_over_regset_sections (struct gdbarch *gdbarch,
I386_FBSD_SIZEOF_SEGBASES_REGSET, &i386_fbsd_segbases_regset,
"segment bases", cb_data);
if (tdep->xcr0 & X86_XSTATE_AVX)
cb (".reg-xstate", X86_XSTATE_SIZE (tdep->xcr0),
X86_XSTATE_SIZE (tdep->xcr0), &i386fbsd_xstateregset,
if (tdep->xsave_layout.sizeof_xsave != 0)
cb (".reg-xstate", tdep->xsave_layout.sizeof_xsave,
tdep->xsave_layout.sizeof_xsave, &i386fbsd_xstateregset,
"XSAVE extended state", cb_data);
}
@ -386,6 +393,8 @@ i386fbsd_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
i386_elf_init_abi (info, gdbarch);
tdep->xsave_xcr0_offset = I386_FBSD_XSAVE_XCR0_OFFSET;
set_gdbarch_core_read_x86_xsave_layout
(gdbarch, i386_fbsd_core_read_x86_xsave_layout);
/* Iterate over core file register note sections. */
set_gdbarch_iterate_over_regset_sections

View File

@ -20,10 +20,20 @@
#ifndef I386_FBSD_TDEP_H
#define I386_FBSD_TDEP_H
#include "gdbsupport/x86-xstate.h"
#include "regset.h"
/* Get XSAVE extended state xcr0 from core dump. */
extern uint64_t i386fbsd_core_read_xcr0 (bfd *abfd);
/* Read the XSAVE extended state xcr0 value from the ABFD core file.
If it appears to be valid, return it and fill LAYOUT with values
inferred from that value.
Otherwise, return 0 to indicate no state was found and leave LAYOUT
untouched. */
uint64_t i386_fbsd_core_read_xsave_info (bfd *abfd, x86_xsave_layout &layout);
/* Implement the core_read_x86_xsave_layout gdbarch method. */
bool i386_fbsd_core_read_x86_xsave_layout (struct gdbarch *gdbarch,
x86_xsave_layout &layout);
/* The format of the XSAVE extended area is determined by hardware.
Cores store the XSAVE extended area in a NT_X86_XSTATE note that