diff --git a/bfd/ChangeLog b/bfd/ChangeLog index 729630d410..55c37f0395 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,3 +1,9 @@ +2015-04-13 John Baldwin + + * 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 PR ld/18250 diff --git a/bfd/elf.c b/bfd/elf.c index a031b9e11b..41fb023c49 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 8a14194e19..1cd95c478c 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,46 @@ +2015-04-13 John Baldwin + + * 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 * NEWS (Changes since GDB 7.9): Add removed -xdb. diff --git a/gdb/amd64-tdep.c b/gdb/amd64-tdep.c index 3e5d1bd8a7..461b701ac4 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 318fd436f5..704225e6f3 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 31060a123d..66d42894bd 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 167eb56156..09776ee305 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 b1b261c196..a721f48ede 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) ®s, 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 62dcb83d6d..52705d9e30 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 4d979159cc..0c7eb5afbe 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 8bfd4129ca..7880f6ca59 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 16e0707336..ac8a19bb50 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 a11f5547d4..2f50c32545 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 ad439e3d44..6c43f2c4e8 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 ed41706364..99e08cbded 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 0000000000..8d6f9985f8 --- /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 . */ + +#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 */