aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--bfd/ChangeLog6
-rw-r--r--bfd/elf.c9
-rw-r--r--gdb/ChangeLog43
-rw-r--r--gdb/amd64-tdep.c20
-rw-r--r--gdb/amd64-tdep.h3
-rw-r--r--gdb/amd64bsd-nat.c36
-rw-r--r--gdb/amd64bsd-nat.h3
-rw-r--r--gdb/amd64fbsd-nat.c45
-rw-r--r--gdb/amd64fbsd-tdep.c65
-rw-r--r--gdb/i386-tdep.c19
-rw-r--r--gdb/i386-tdep.h3
-rw-r--r--gdb/i386bsd-nat.c51
-rw-r--r--gdb/i386bsd-nat.h3
-rw-r--r--gdb/i386fbsd-nat.c34
-rw-r--r--gdb/i386fbsd-tdep.c106
-rw-r--r--gdb/i386fbsd-tdep.h31
16 files changed, 470 insertions, 7 deletions
diff --git a/bfd/ChangeLog b/bfd/ChangeLog
index 729630d..55c37f0 100644
--- a/bfd/ChangeLog
+++ b/bfd/ChangeLog
@@ -1,3 +1,9 @@
+2015-04-13 John Baldwin <jhb@FreeBSD.org>
+
+ * elf.c (elfcore_grok_note): Recognize NT_X86_XSTATE on
+ FreeBSD.
+ (elfcore_write_xstatereg): Use correct note name on FreeBSD.
+
2015-04-13 H.J. Lu <hongjiu.lu@intel.com>
PR ld/18250
diff --git a/bfd/elf.c b/bfd/elf.c
index a031b9e..41fb023 100644
--- a/bfd/elf.c
+++ b/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 a/gdb/ChangeLog b/gdb/ChangeLog
index 8a14194e..1cd95c4 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,3 +1,46 @@
+2015-04-13 John Baldwin <jhb@FreeBSD.org>
+
+ * amd64-tdep.c (amd64_target_description): New function.
+ * amd64-tdep.h: Export amd64_target_description and tdesc_amd64.
+ * amd64bsd-nat.c [PT_GETXSTATE_INFO]: New variable amd64bsd_xsave_len.
+ (amd64bsd_fetch_inferior_registers) [PT_GETXSTATE_INFO]: Handle
+ x86 extended save area.
+ (amd64bsd_store_inferior_registers) [PT_GETXSTATE_INFO]: Likewise.
+ * amd64bsd-nat.h: Export amd64bsd_xsave_len.
+ * amd64fbsd-nat.c (amd64fbsd_read_description): New function.
+ (_initialize_amd64fbsd_nat): Set "to_read_description" to
+ "amd64fbsd_read_description".
+ * amd64fbsd-tdep.c (amd64fbsd_core_read_description): New function.
+ (amd64fbsd_supply_xstateregset): New function.
+ (amd64fbsd_collect_xstateregset): New function.
+ Add "amd64fbsd_xstateregset".
+ (amd64fbsd_iterate_over_regset_sections): New function.
+ (amd64fbsd_init_abi): Set "xsave_xcr0_offset" to
+ "I386_FBSD_XSAVE_XCR0_OFFSET".
+ Add "iterate_over_regset_sections" gdbarch method.
+ Add "core_read_description" gdbarch method.
+ * i386-tdep.c (i386_target_description): New function.
+ * i386-tdep.h: Export i386_target_description and tdesc_i386.
+ * i386bsd-nat.c [PT_GETXSTATE_INFO]: New variable i386bsd_xsave_len.
+ (i386bsd_fetch_inferior_registers) [PT_GETXSTATE_INFO]: Handle
+ x86 extended save area.
+ (i386bsd_store_inferior_registers) [PT_GETXSTATE_INFO]: Likewise.
+ * i386bsd-nat.h: Export i386bsd_xsave_len.
+ * i386fbsd-nat.c (i386fbsd_read_description): New function.
+ (_initialize_i386fbsd_nat): Set "to_read_description" to
+ "i386fbsd_read_description".
+ * i386fbsd-tdep.c (i386fbsd_core_read_xcr0): New function.
+ (i386fbsd_core_read_description): New function.
+ (i386fbsd_supply_xstateregset): New function.
+ (i386fbsd_collect_xstateregset): New function.
+ Add "i386fbsd_xstateregset".
+ (i386fbsd_iterate_over_regset_sections): New function.
+ (i386fbsd4_init_abi): Set "xsave_xcr0_offset" to
+ "I386_FBSD_XSAVE_XCR0_OFFSET".
+ Add "iterate_over_regset_sections" gdbarch method.
+ Add "core_read_description" gdbarch method.
+ * i386fbsd-tdep.h: New file.
+
2015-04-11 Jan Kratochvil <jan.kratochvil@redhat.com>
* NEWS (Changes since GDB 7.9): Add removed -xdb.
diff --git a/gdb/amd64-tdep.c b/gdb/amd64-tdep.c
index 3e5d1bd..461b701 100644
--- a/gdb/amd64-tdep.c
+++ b/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 a/gdb/amd64-tdep.h b/gdb/amd64-tdep.h
index 318fd43..704225e 100644
--- a/gdb/amd64-tdep.h
+++ b/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 a/gdb/amd64bsd-nat.c b/gdb/amd64bsd-nat.c
index 31060a123..66d4289 100644
--- a/gdb/amd64bsd-nat.c
+++ b/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 a/gdb/amd64bsd-nat.h b/gdb/amd64bsd-nat.h
index 167eb56..09776ee 100644
--- a/gdb/amd64bsd-nat.h
+++ b/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 a/gdb/amd64fbsd-nat.c b/gdb/amd64fbsd-nat.c
index b1b261c..a721f48 100644
--- a/gdb/amd64fbsd-nat.c
+++ b/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 a/gdb/amd64fbsd-tdep.c b/gdb/amd64fbsd-tdep.c
index 62dcb83..52705d9 100644
--- a/gdb/amd64fbsd-tdep.c
+++ b/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 a/gdb/i386-tdep.c b/gdb/i386-tdep.c
index 4d97915..0c7eb5a 100644
--- a/gdb/i386-tdep.c
+++ b/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 a/gdb/i386-tdep.h b/gdb/i386-tdep.h
index 8bfd412..7880f6c 100644
--- a/gdb/i386-tdep.h
+++ b/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 a/gdb/i386bsd-nat.c b/gdb/i386bsd-nat.c
index 16e0707..ac8a19b 100644
--- a/gdb/i386bsd-nat.c
+++ b/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 a/gdb/i386bsd-nat.h b/gdb/i386bsd-nat.h
index a11f554..2f50c32 100644
--- a/gdb/i386bsd-nat.h
+++ b/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 a/gdb/i386fbsd-nat.c b/gdb/i386fbsd-nat.c
index ad439e3..6c43f2c 100644
--- a/gdb/i386fbsd-nat.c
+++ b/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 a/gdb/i386fbsd-tdep.c b/gdb/i386fbsd-tdep.c
index ed41706..99e08cb 100644
--- a/gdb/i386fbsd-tdep.c
+++ b/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 a/gdb/i386fbsd-tdep.h b/gdb/i386fbsd-tdep.h
new file mode 100644
index 0000000..8d6f998
--- /dev/null
+++ b/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 */