aboutsummaryrefslogtreecommitdiff
path: root/gdb/amd64fbsd-nat.c
diff options
context:
space:
mode:
authorJohn Baldwin <jhb@FreeBSD.org>2015-02-21 16:43:30 -0500
committerJohn Baldwin <jhb@FreeBSD.org>2015-04-13 16:07:01 -0400
commit97de3545ca6b690031cc00983346ed72f11e78a2 (patch)
tree15eca66ea0dd34d0a1d1555d9ef93a48e7015214 /gdb/amd64fbsd-nat.c
parent0d2a7a932244fab27d6c4ce211ea8f7708a1a9cc (diff)
downloadfsf-binutils-gdb-97de3545ca6b690031cc00983346ed72f11e78a2.zip
fsf-binutils-gdb-97de3545ca6b690031cc00983346ed72f11e78a2.tar.gz
fsf-binutils-gdb-97de3545ca6b690031cc00983346ed72f11e78a2.tar.bz2
Add support for the x86 XSAVE extended state on FreeBSD/x86.
Recognize NT_X86_XSTATE notes in FreeBSD process cores. Recent FreeBSD versions include a note containing the XSAVE state for each thread in the process when XSAVE is in use. The note stores a copy of the current XSAVE mask in a reserved section of the machine-defined XSAVE state at the same offset as Linux's NT_X86_XSTATE note. For native processes, use the PT_GETXSTATE_INFO ptrace request to determine if XSAVE is enabled, and if so the active XSAVE state mask (that is, the value of %xcr0 for the target process) as well as the size of XSAVE state area. Use the PT_GETXSTATE and PT_SETXSTATE requests to fetch and store the XSAVE state, respectively, in the BSD x86 native targets. In addition, the FreeBSD amd64 and i386 native targets now include "read_description" target methods to determine the correct x86 target description for the current XSAVE mask. On FreeBSD amd64 this also properly returns an i386 target description for 32-bit binaries which allows the 64-bit GDB to run 32-bit binaries. Note that the ptrace changes are in the BSD native targets, not the FreeBSD-specific native targets since that is where the other ptrace register accesses occur. Of the other BSDs, NetBSD and DragonFly use XSAVE in the kernel but do not currently export the extended state via ptrace(2). OpenBSD does not currently support XSAVE. bfd/ChangeLog: * elf.c (elfcore_grok_note): Recognize NT_X86_XSTATE on FreeBSD. (elfcore_write_xstatereg): Use correct note name on FreeBSD. gdb/ChangeLog: * 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.
Diffstat (limited to 'gdb/amd64fbsd-nat.c')
-rw-r--r--gdb/amd64fbsd-nat.c45
1 files changed, 45 insertions, 0 deletions
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;