summaryrefslogtreecommitdiff
path: root/devel/gdb/files/commit-97de354
diff options
context:
space:
mode:
Diffstat (limited to 'devel/gdb/files/commit-97de354')
-rw-r--r--devel/gdb/files/commit-97de354690
1 files changed, 690 insertions, 0 deletions
diff --git a/devel/gdb/files/commit-97de354 b/devel/gdb/files/commit-97de354
new file mode 100644
index 000000000000..5709edb1da9e
--- /dev/null
+++ b/devel/gdb/files/commit-97de354
@@ -0,0 +1,690 @@
+diff --git bfd/elf.c bfd/elf.c
+index a031b9e..41fb023 100644
+--- bfd/elf.c
++++ bfd/elf.c
+@@ -8737,6 +8737,9 @@ elfcore_grok_note (bfd *abfd, Elf_Internal_Note *note)
+ if (note->namesz == 6
+ && strcmp (note->namedata, "LINUX") == 0)
+ return elfcore_grok_xstatereg (abfd, note);
++ else if (note->namesz == 8
++ && strcmp (note->namedata, "FreeBSD") == 0)
++ return elfcore_grok_xstatereg (abfd, note);
+ else
+ return TRUE;
+
+@@ -9556,7 +9559,11 @@ char *
+ elfcore_write_xstatereg (bfd *abfd, char *buf, int *bufsiz,
+ const void *xfpregs, int size)
+ {
+- char *note_name = "LINUX";
++ char *note_name;
++ if (get_elf_backend_data (abfd)->elf_osabi == ELFOSABI_FREEBSD)
++ note_name = "FreeBSD";
++ else
++ note_name = "LINUX";
+ return elfcore_write_note (abfd, buf, bufsiz,
+ note_name, NT_X86_XSTATE, xfpregs, size);
+ }
+diff --git gdb/amd64-tdep.c gdb/amd64-tdep.c
+index 3e5d1bd..461b701 100644
+--- gdb/amd64-tdep.c
++++ gdb/amd64-tdep.c
+@@ -39,6 +39,7 @@
+ #include "disasm.h"
+ #include "amd64-tdep.h"
+ #include "i387-tdep.h"
++#include "x86-xstate.h"
+
+ #include "features/i386/amd64.c"
+ #include "features/i386/amd64-avx.c"
+@@ -3118,6 +3119,25 @@ amd64_x32_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
+ set_gdbarch_ptr_bit (gdbarch, 32);
+ }
+
++/* Return the target description for a specified XSAVE feature mask. */
++
++const struct target_desc *
++amd64_target_description (uint64_t xcr0)
++{
++ switch (xcr0 & X86_XSTATE_ALL_MASK)
++ {
++ case X86_XSTATE_MPX_AVX512_MASK:
++ case X86_XSTATE_AVX512_MASK:
++ return tdesc_amd64_avx512;
++ case X86_XSTATE_MPX_MASK:
++ return tdesc_amd64_mpx;
++ case X86_XSTATE_AVX_MASK:
++ return tdesc_amd64_avx;
++ default:
++ return tdesc_amd64;
++ }
++}
++
+ /* Provide a prototype to silence -Wmissing-prototypes. */
+ void _initialize_amd64_tdep (void);
+
+diff --git gdb/amd64-tdep.h gdb/amd64-tdep.h
+index 318fd43..704225e 100644
+--- gdb/amd64-tdep.h
++++ gdb/amd64-tdep.h
+@@ -84,6 +84,8 @@ enum amd64_regnum
+
+ #define AMD64_NUM_REGS (AMD64_ZMM31H_REGNUM + 1)
+
++extern struct target_desc *tdesc_amd64;
++
+ extern struct displaced_step_closure *amd64_displaced_step_copy_insn
+ (struct gdbarch *gdbarch, CORE_ADDR from, CORE_ADDR to,
+ struct regcache *regs);
+@@ -95,6 +97,7 @@ extern void amd64_displaced_step_fixup (struct gdbarch *gdbarch,
+ extern void amd64_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch);
+ extern void amd64_x32_init_abi (struct gdbarch_info info,
+ struct gdbarch *gdbarch);
++extern const struct target_desc *amd64_target_description (uint64_t xcr0);
+
+ /* Fill register REGNUM in REGCACHE with the appropriate
+ floating-point or SSE register value from *FXSAVE. If REGNUM is
+diff --git gdb/amd64bsd-nat.c gdb/amd64bsd-nat.c
+index 31060a123..66d4289 100644
+--- gdb/amd64bsd-nat.c
++++ gdb/amd64bsd-nat.c
+@@ -35,6 +35,10 @@
+ #include "inf-ptrace.h"
+
+
++#ifdef PT_GETXSTATE_INFO
++size_t amd64bsd_xsave_len;
++#endif
++
+ /* Fetch register REGNUM from the inferior. If REGNUM is -1, do this
+ for all registers (including the floating-point registers). */
+
+@@ -60,6 +64,20 @@ amd64bsd_fetch_inferior_registers (struct target_ops *ops,
+ if (regnum == -1 || !amd64_native_gregset_supplies_p (gdbarch, regnum))
+ {
+ struct fpreg fpregs;
++#ifdef PT_GETXSTATE_INFO
++ char *xstateregs;
++
++ if (amd64bsd_xsave_len != 0)
++ {
++ xstateregs = alloca (amd64bsd_xsave_len);
++ if (ptrace (PT_GETXSTATE, ptid_get_pid (inferior_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 (ptrace (PT_GETFPREGS, ptid_get_pid (inferior_ptid),
+ (PTRACE_TYPE_ARG3) &fpregs, 0) == -1)
+@@ -99,6 +117,24 @@ amd64bsd_store_inferior_registers (struct target_ops *ops,
+ if (regnum == -1 || !amd64_native_gregset_supplies_p (gdbarch, regnum))
+ {
+ struct fpreg fpregs;
++#ifdef PT_GETXSTATE_INFO
++ char *xstateregs;
++
++ if (amd64bsd_xsave_len != 0)
++ {
++ xstateregs = alloca (amd64bsd_xsave_len);
++ if (ptrace (PT_GETXSTATE, ptid_get_pid (inferior_ptid),
++ (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, ptid_get_pid (inferior_ptid),
++ (PTRACE_TYPE_ARG3) xstateregs, amd64bsd_xsave_len) == -1)
++ perror_with_name (_("Couldn't write extended state status"));
++ return;
++ }
++#endif
+
+ if (ptrace (PT_GETFPREGS, ptid_get_pid (inferior_ptid),
+ (PTRACE_TYPE_ARG3) &fpregs, 0) == -1)
+diff --git gdb/amd64bsd-nat.h gdb/amd64bsd-nat.h
+index 167eb56..09776ee 100644
+--- gdb/amd64bsd-nat.h
++++ gdb/amd64bsd-nat.h
+@@ -20,6 +20,9 @@
+ #ifndef AMD64BSD_NAT_H
+ #define AMD64BSD_NAT_H
+
++/* Low level amd64 XSAVE info. */
++extern size_t amd64bsd_xsave_len;
++
+ /* Low level amd64 debug register functions. */
+
+ extern void amd64bsd_dr_set_control (unsigned long control);
+diff --git gdb/amd64fbsd-nat.c gdb/amd64fbsd-nat.c
+index b1b261c..a721f48 100644
+--- gdb/amd64fbsd-nat.c
++++ gdb/amd64fbsd-nat.c
+@@ -151,6 +151,50 @@ amd64fbsd_mourn_inferior (struct target_ops *ops)
+ super_mourn_inferior (ops);
+ }
+
++/* Implement the to_read_description method. */
++
++static const struct target_desc *
++amd64fbsd_read_description (struct target_ops *ops)
++{
++#ifdef PT_GETXSTATE_INFO
++ static int xsave_probed;
++ static uint64_t xcr0;
++#endif
++ struct reg regs;
++ int is64;
++
++ if (ptrace (PT_GETREGS, ptid_get_pid (inferior_ptid),
++ (PTRACE_TYPE_ARG3) &regs, 0) == -1)
++ 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, ptid_get_pid (inferior_ptid),
++ (PTRACE_TYPE_ARG3) &info, sizeof (info)) == 0)
++ {
++ amd64bsd_xsave_len = info.xsave_len;
++ xcr0 = info.xsave_mask;
++ }
++ xsave_probed = 1;
++ }
++
++ if (amd64bsd_xsave_len != 0)
++ {
++ if (is64)
++ return amd64_target_description (xcr0);
++ else
++ return i386_target_description (xcr0);
++ }
++#endif
++ if (is64)
++ return tdesc_amd64;
++ else
++ return tdesc_i386;
++}
++
+ /* Provide a prototype to silence -Wmissing-prototypes. */
+ void _initialize_amd64fbsd_nat (void);
+
+@@ -181,6 +225,7 @@ _initialize_amd64fbsd_nat (void)
+
+ super_mourn_inferior = t->to_mourn_inferior;
+ t->to_mourn_inferior = amd64fbsd_mourn_inferior;
++ t->to_read_description = amd64fbsd_read_description;
+
+ t->to_pid_to_exec_file = fbsd_pid_to_exec_file;
+ t->to_find_memory_regions = fbsd_find_memory_regions;
+diff --git gdb/amd64fbsd-tdep.c gdb/amd64fbsd-tdep.c
+index 62dcb83..52705d9 100644
+--- gdb/amd64fbsd-tdep.c
++++ gdb/amd64fbsd-tdep.c
+@@ -23,6 +23,9 @@
+ #include "gdbcore.h"
+ #include "regcache.h"
+ #include "osabi.h"
++#include "regset.h"
++#include "i386fbsd-tdep.h"
++#include "x86-xstate.h"
+
+ #include "amd64-tdep.h"
+ #include "bsd-uthread.h"
+@@ -169,6 +172,59 @@ static int amd64fbsd_jmp_buf_reg_offset[] =
+ 0 * 8 /* %rip */
+ };
+
++/* Implement the core_read_description gdbarch method. */
++
++static const struct target_desc *
++amd64fbsd_core_read_description (struct gdbarch *gdbarch,
++ struct target_ops *target,
++ bfd *abfd)
++{
++ return amd64_target_description (i386fbsd_core_read_xcr0 (abfd));
++}
++
++/* Similar to amd64_supply_fpregset, but use XSAVE extended state. */
++
++static void
++amd64fbsd_supply_xstateregset (const struct regset *regset,
++ struct regcache *regcache, int regnum,
++ const void *xstateregs, size_t len)
++{
++ amd64_supply_xsave (regcache, regnum, xstateregs);
++}
++
++/* Similar to amd64_collect_fpregset, but use XSAVE extended state. */
++
++static void
++amd64fbsd_collect_xstateregset (const struct regset *regset,
++ const struct regcache *regcache,
++ int regnum, void *xstateregs, size_t len)
++{
++ amd64_collect_xsave (regcache, regnum, xstateregs, 1);
++}
++
++static const struct regset amd64fbsd_xstateregset =
++ {
++ NULL,
++ amd64fbsd_supply_xstateregset,
++ amd64fbsd_collect_xstateregset
++ };
++
++/* Iterate over core file register note sections. */
++
++static void
++amd64fbsd_iterate_over_regset_sections (struct gdbarch *gdbarch,
++ iterate_over_regset_sections_cb *cb,
++ void *cb_data,
++ const struct regcache *regcache)
++{
++ struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
++
++ cb (".reg", tdep->sizeof_gregset, &i386_gregset, NULL, cb_data);
++ cb (".reg2", tdep->sizeof_fpregset, &amd64_fpregset, NULL, cb_data);
++ cb (".reg-xstate", X86_XSTATE_SIZE(tdep->xcr0),
++ &amd64fbsd_xstateregset, "XSAVE extended state", cb_data);
++}
++
+ static void
+ amd64fbsd_supply_uthread (struct regcache *regcache,
+ int regnum, CORE_ADDR addr)
+@@ -233,6 +289,15 @@ amd64fbsd_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
+ tdep->sc_reg_offset = amd64fbsd_sc_reg_offset;
+ tdep->sc_num_regs = ARRAY_SIZE (amd64fbsd_sc_reg_offset);
+
++ tdep->xsave_xcr0_offset = I386_FBSD_XSAVE_XCR0_OFFSET;
++
++ /* Iterate over core file register note sections. */
++ set_gdbarch_iterate_over_regset_sections
++ (gdbarch, amd64fbsd_iterate_over_regset_sections);
++
++ set_gdbarch_core_read_description (gdbarch,
++ amd64fbsd_core_read_description);
++
+ /* FreeBSD provides a user-level threads implementation. */
+ bsd_uthread_set_supply_uthread (gdbarch, amd64fbsd_supply_uthread);
+ bsd_uthread_set_collect_uthread (gdbarch, amd64fbsd_collect_uthread);
+diff --git gdb/i386-tdep.c gdb/i386-tdep.c
+index 4d97915..0c7eb5a 100644
+--- gdb/i386-tdep.c
++++ gdb/i386-tdep.c
+@@ -8598,6 +8598,25 @@ i386_coff_osabi_sniffer (bfd *abfd)
+ }
+
+
++/* Return the target description for a specified XSAVE feature mask. */
++
++const struct target_desc *
++i386_target_description (uint64_t xcr0)
++{
++ switch (xcr0 & X86_XSTATE_ALL_MASK)
++ {
++ case X86_XSTATE_MPX_AVX512_MASK:
++ case X86_XSTATE_AVX512_MASK:
++ return tdesc_i386_avx512;
++ case X86_XSTATE_MPX_MASK:
++ return tdesc_i386_mpx;
++ case X86_XSTATE_AVX_MASK:
++ return tdesc_i386_avx;
++ default:
++ return tdesc_i386;
++ }
++}
++
+ /* Provide a prototype to silence -Wmissing-prototypes. */
+ void _initialize_i386_tdep (void);
+
+diff --git gdb/i386-tdep.h gdb/i386-tdep.h
+index 8bfd412..7880f6c 100644
+--- gdb/i386-tdep.h
++++ gdb/i386-tdep.h
+@@ -328,6 +328,8 @@ enum record_i386_regnum
+ /* Size of the largest register. */
+ #define I386_MAX_REGISTER_SIZE 64
+
++extern struct target_desc *tdesc_i386;
++
+ /* Types for i386-specific registers. */
+ extern struct type *i387_ext_type (struct gdbarch *gdbarch);
+
+@@ -416,6 +418,7 @@ extern void i386_svr4_init_abi (struct gdbarch_info, struct gdbarch *);
+
+ extern int i386_process_record (struct gdbarch *gdbarch,
+ struct regcache *regcache, CORE_ADDR addr);
++extern const struct target_desc *i386_target_description (uint64_t xcr0);
+
+
+
+diff --git gdb/i386bsd-nat.c gdb/i386bsd-nat.c
+index 16e0707..ac8a19b 100644
+--- gdb/i386bsd-nat.c
++++ gdb/i386bsd-nat.c
+@@ -81,6 +81,10 @@ static int i386bsd_r_reg_offset[] =
+ so that we try PT_GETXMMREGS the first time around. */
+ static int have_ptrace_xmmregs = -1;
+ #endif
++
++#ifdef PT_GETXSTATE_INFO
++size_t i386bsd_xsave_len;
++#endif
+
+
+ /* Supply the general-purpose registers in GREGS, to REGCACHE. */
+@@ -148,7 +152,24 @@ i386bsd_fetch_inferior_registers (struct target_ops *ops,
+ struct fpreg fpregs;
+ #ifdef HAVE_PT_GETXMMREGS
+ char xmmregs[512];
++#endif
++
++#ifdef PT_GETXSTATE_INFO
++ if (i386bsd_xsave_len != 0)
++ {
++ char *xstateregs;
++
++ xstateregs = alloca (i386bsd_xsave_len);
++ if (ptrace (PT_GETXSTATE, ptid_get_pid (inferior_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
+ && ptrace(PT_GETXMMREGS, ptid_get_pid (inferior_ptid),
+ (PTRACE_TYPE_ARG3) xmmregs, 0) == 0)
+@@ -158,18 +179,15 @@ i386bsd_fetch_inferior_registers (struct target_ops *ops,
+ }
+ else
+ {
++ have_ptrace_xmmregs = 0;
++#endif
+ if (ptrace (PT_GETFPREGS, ptid_get_pid (inferior_ptid),
+ (PTRACE_TYPE_ARG3) &fpregs, 0) == -1)
+ perror_with_name (_("Couldn't get floating point status"));
+
+ i387_supply_fsave (regcache, -1, &fpregs);
++#ifdef HAVE_PT_GETXMMREGS
+ }
+-#else
+- if (ptrace (PT_GETFPREGS, ptid_get_pid (inferior_ptid),
+- (PTRACE_TYPE_ARG3) &fpregs, 0) == -1)
+- perror_with_name (_("Couldn't get floating point status"));
+-
+- i387_supply_fsave (regcache, -1, &fpregs);
+ #endif
+ }
+ }
+@@ -204,7 +222,28 @@ i386bsd_store_inferior_registers (struct target_ops *ops,
+ struct fpreg fpregs;
+ #ifdef HAVE_PT_GETXMMREGS
+ char xmmregs[512];
++#endif
++
++#ifdef PT_GETXSTATE_INFO
++ if (i386bsd_xsave_len != 0)
++ {
++ char *xstateregs;
++
++ xstateregs = alloca (i386bsd_xsave_len);
++ if (ptrace (PT_GETXSTATE, ptid_get_pid (inferior_ptid),
++ (PTRACE_TYPE_ARG3) xstateregs, 0) == -1)
++ perror_with_name (_("Couldn't get extended state status"));
+
++ i387_collect_xsave (regcache, -1, xstateregs, 0);
++
++ if (ptrace (PT_SETXSTATE, ptid_get_pid (inferior_ptid),
++ (PTRACE_TYPE_ARG3) xstateregs, i386bsd_xsave_len) == -1)
++ perror_with_name (_("Couldn't write extended state status"));
++ return;
++ }
++#endif
++
++#ifdef HAVE_PT_GETXMMREGS
+ if (have_ptrace_xmmregs != 0
+ && ptrace(PT_GETXMMREGS, ptid_get_pid (inferior_ptid),
+ (PTRACE_TYPE_ARG3) xmmregs, 0) == 0)
+diff --git gdb/i386bsd-nat.h gdb/i386bsd-nat.h
+index a11f554..2f50c32 100644
+--- gdb/i386bsd-nat.h
++++ gdb/i386bsd-nat.h
+@@ -25,6 +25,9 @@
+
+ extern struct target_ops *i386bsd_target (void);
+
++/* Low level i386 XSAVE info. */
++extern size_t i386bsd_xsave_len;
++
+ /* low level i386 debug register functions used in i386fbsd-nat.c. */
+
+ extern void i386bsd_dr_set_control (unsigned long control);
+diff --git gdb/i386fbsd-nat.c gdb/i386fbsd-nat.c
+index ad439e3..6c43f2c 100644
+--- gdb/i386fbsd-nat.c
++++ gdb/i386fbsd-nat.c
+@@ -116,6 +116,37 @@ i386fbsd_supply_pcb (struct regcache *regcache, struct pcb *pcb)
+ }
+
+
++#ifdef PT_GETXSTATE_INFO
++/* Implement the to_read_description method. */
++
++static const struct target_desc *
++i386fbsd_read_description (struct target_ops *ops)
++{
++ static int xsave_probed;
++ static uint64_t xcr0;
++
++ if (!xsave_probed)
++ {
++ struct ptrace_xstate_info info;
++
++ if (ptrace (PT_GETXSTATE_INFO, ptid_get_pid (inferior_ptid),
++ (PTRACE_TYPE_ARG3) &info, sizeof (info)) == 0)
++ {
++ i386bsd_xsave_len = info.xsave_len;
++ xcr0 = info.xsave_mask;
++ }
++ xsave_probed = 1;
++ }
++
++ if (i386bsd_xsave_len != 0)
++ {
++ return i386_target_description (xcr0);
++ }
++ else
++ return tdesc_i386;
++}
++#endif
++
+ /* Prevent warning from -Wmissing-prototypes. */
+ void _initialize_i386fbsd_nat (void);
+
+@@ -140,6 +171,9 @@ _initialize_i386fbsd_nat (void)
+
+ #endif /* HAVE_PT_GETDBREGS */
+
++#ifdef PT_GETXSTATE_INFO
++ t->to_read_description = i386fbsd_read_description;
++#endif
+
+ t->to_resume = i386fbsd_resume;
+ t->to_pid_to_exec_file = fbsd_pid_to_exec_file;
+diff --git gdb/i386fbsd-tdep.c gdb/i386fbsd-tdep.c
+index ed41706..99e08cb 100644
+--- gdb/i386fbsd-tdep.c
++++ gdb/i386fbsd-tdep.c
+@@ -22,6 +22,9 @@
+ #include "gdbcore.h"
+ #include "osabi.h"
+ #include "regcache.h"
++#include "regset.h"
++#include "i386fbsd-tdep.h"
++#include "x86-xstate.h"
+
+ #include "i386-tdep.h"
+ #include "i387-tdep.h"
+@@ -235,6 +238,100 @@ static int i386fbsd_jmp_buf_reg_offset[] =
+ 0 * 4 /* %eip */
+ };
+
++/* Get XSAVE extended state xcr0 from core dump. */
++
++uint64_t
++i386fbsd_core_read_xcr0 (bfd *abfd)
++{
++ asection *xstate = bfd_get_section_by_name (abfd, ".reg-xstate");
++ uint64_t xcr0;
++
++ if (xstate)
++ {
++ size_t size = bfd_section_size (abfd, 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 0;
++ }
++
++ xcr0 = bfd_get_64 (abfd, contents);
++ }
++ }
++ else
++ xcr0 = 0;
++
++ return xcr0;
++}
++
++/* Implement the core_read_description gdbarch method. */
++
++static const struct target_desc *
++i386fbsd_core_read_description (struct gdbarch *gdbarch,
++ struct target_ops *target,
++ bfd *abfd)
++{
++ return i386_target_description (i386fbsd_core_read_xcr0 (abfd));
++}
++
++/* Similar to i386_supply_fpregset, but use XSAVE extended state. */
++
++static void
++i386fbsd_supply_xstateregset (const struct regset *regset,
++ struct regcache *regcache, int regnum,
++ const void *xstateregs, size_t len)
++{
++ i387_supply_xsave (regcache, regnum, xstateregs);
++}
++
++/* Similar to i386_collect_fpregset, but use XSAVE extended state. */
++
++static void
++i386fbsd_collect_xstateregset (const struct regset *regset,
++ const struct regcache *regcache,
++ int regnum, void *xstateregs, size_t len)
++{
++ i387_collect_xsave (regcache, regnum, xstateregs, 1);
++}
++
++/* Register set definitions. */
++
++static const struct regset i386fbsd_xstateregset =
++ {
++ NULL,
++ i386fbsd_supply_xstateregset,
++ i386fbsd_collect_xstateregset
++ };
++
++/* Iterate over core file register note sections. */
++
++static void
++i386fbsd_iterate_over_regset_sections (struct gdbarch *gdbarch,
++ iterate_over_regset_sections_cb *cb,
++ void *cb_data,
++ const struct regcache *regcache)
++{
++ struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
++
++ cb (".reg", tdep->sizeof_gregset, &i386_gregset, NULL, cb_data);
++ cb (".reg2", tdep->sizeof_fpregset, &i386_fpregset, NULL, cb_data);
++
++ if (tdep->xcr0 & X86_XSTATE_AVX)
++ cb (".reg-xstate", X86_XSTATE_SIZE(tdep->xcr0),
++ &i386fbsd_xstateregset, "XSAVE extended state", cb_data);
++}
++
+ static void
+ i386fbsd_supply_uthread (struct regcache *regcache,
+ int regnum, CORE_ADDR addr)
+@@ -376,6 +473,15 @@ i386fbsd4_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
+ /* FreeBSD 4.0 introduced a new `struct sigcontext'. */
+ tdep->sc_reg_offset = i386fbsd4_sc_reg_offset;
+ tdep->sc_num_regs = ARRAY_SIZE (i386fbsd4_sc_reg_offset);
++
++ tdep->xsave_xcr0_offset = I386_FBSD_XSAVE_XCR0_OFFSET;
++
++ /* Iterate over core file register note sections. */
++ set_gdbarch_iterate_over_regset_sections
++ (gdbarch, i386fbsd_iterate_over_regset_sections);
++
++ set_gdbarch_core_read_description (gdbarch,
++ i386fbsd_core_read_description);
+ }
+
+
+diff --git gdb/i386fbsd-tdep.h gdb/i386fbsd-tdep.h
+new file mode 100644
+index 0000000..8d6f998
+--- /dev/null
++++ gdb/i386fbsd-tdep.h
+@@ -0,0 +1,31 @@
++/* Target-dependent code for FreeBSD x86.
++
++ Copyright (C) 2015 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 I386FBSD_TDEP_H
++#define I386FBSD_TDEP_H
++
++/* Get XSAVE extended state xcr0 from core dump. */
++extern uint64_t i386fbsd_core_read_xcr0 (bfd *abfd);
++
++/* The format of the XSAVE extended area is determined by hardware.
++ Cores store the XSAVE extended area in a NT_X86_XSTATE note that
++ matches the layout on Linux. */
++#define I386_FBSD_XSAVE_XCR0_OFFSET 464
++
++#endif /* i386fbsd-tdep.h */