From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: by sourceware.org (Postfix, from userid 1936) id 0D6683947C3D; Fri, 28 Jan 2022 19:16:45 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 0D6683947C3D Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable From: John Baldwin To: gdb-cvs@sourceware.org Subject: [binutils-gdb] FreeBSD x86 nat: Use register maps for GP register sets. X-Act-Checkin: binutils-gdb X-Git-Author: John Baldwin X-Git-Refname: refs/heads/master X-Git-Oldrev: b95a31ed5d2b34f1a4072d701f5cd51075e61c01 X-Git-Newrev: 00d7af046f12f18759b5b2c909d0b4527ac1857e Message-Id: <20220128191645.0D6683947C3D@sourceware.org> Date: Fri, 28 Jan 2022 19:16:45 +0000 (GMT) X-BeenThere: gdb-cvs@sourceware.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Gdb-cvs mailing list List-Unsubscribe: , List-Archive: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 28 Jan 2022 19:16:45 -0000 https://sourceware.org/git/gitweb.cgi?p=3Dbinutils-gdb.git;h=3D00d7af046f12= f18759b5b2c909d0b4527ac1857e commit 00d7af046f12f18759b5b2c909d0b4527ac1857e Author: John Baldwin Date: Fri Jan 28 11:14:37 2022 -0800 FreeBSD x86 nat: Use register maps for GP register sets. =20 Rather than using the x86-specific register offset tables, use register maps to describe the layout of the general purpose registers fetched via PT_GETREGS. The sole user-visible difference is that FreeBSD/amd64 will now report additional segment registers ($ds, $es, $fs, and $gs) for both 32-bit and 64-bit processes. =20 As part of these changes, the FreeBSD x86 native targets no longer use amd64-bsd-nat.c or i386-bsd-nat.c. Remove FreeBSD-specific register handling (for $fs_base, $gs_base, and XSAVE state) from these files. Similarly, remove the global x86bsd_xsave_len from x86-bsd-nat.c. The FreeBSD x86 native targets use a static xsave_len instead. =20 While here, rework the probing of PT_GETXMMREGS on FreeBSD/i386. Probe the ptrace op once in the target read_description method and cache the result for the future similar to the way the status of XSAVE support is probed in the read_description method. In addition, return the proper xcr0 mask (X87-only) for old kernels or systems without either XSAVE or XMM support. Diff: --- gdb/amd64-bsd-nat.c | 96 ------------------- gdb/amd64-fbsd-nat.c | 260 +++++++++++++++++++++++++++++++++++++++-------= ---- gdb/amd64-fbsd-tdep.c | 1 + gdb/amd64-fbsd-tdep.h | 27 ++++++ gdb/configure.nat | 4 +- gdb/i386-bsd-nat.c | 92 ------------------ gdb/i386-fbsd-nat.c | 229 ++++++++++++++++++++++++++++++++++++++++++-- gdb/i386-fbsd-tdep.h | 4 + gdb/x86-bsd-nat.c | 4 - gdb/x86-bsd-nat.h | 3 - 10 files changed, 457 insertions(+), 263 deletions(-) diff --git a/gdb/amd64-bsd-nat.c b/gdb/amd64-bsd-nat.c index 52730ba276e..77dc4c935ca 100644 --- a/gdb/amd64-bsd-nat.c +++ b/gdb/amd64-bsd-nat.c @@ -59,9 +59,6 @@ amd64bsd_fetch_inferior_registers (struct regcache *regca= che, int regnum) { struct gdbarch *gdbarch =3D regcache->arch (); ptid_t ptid =3D regcache->ptid (); -#if defined(PT_GETFSBASE) || defined(PT_GETGSBASE) - i386_gdbarch_tdep *tdep =3D (i386_gdbarch_tdep *) gdbarch_tdep (gdbarch); -#endif =20 if (regnum =3D=3D -1 || amd64_native_gregset_supplies_p (gdbarch, regnum= )) { @@ -75,50 +72,9 @@ amd64bsd_fetch_inferior_registers (struct regcache *regc= ache, int regnum) return; } =20 -#ifdef PT_GETFSBASE - if (regnum =3D=3D -1 || regnum =3D=3D tdep->fsbase_regnum) - { - register_t base; - - if (gdb_ptrace (PT_GETFSBASE, ptid, (PTRACE_TYPE_ARG3) &base, 0) =3D= =3D -1) - perror_with_name (_("Couldn't get segment register fs_base")); - - regcache->raw_supply (tdep->fsbase_regnum, &base); - if (regnum !=3D -1) - return; - } -#endif -#ifdef PT_GETGSBASE - if (regnum =3D=3D -1 || regnum =3D=3D tdep->fsbase_regnum + 1) - { - register_t base; - - if (gdb_ptrace (PT_GETGSBASE, ptid, (PTRACE_TYPE_ARG3) &base, 0) =3D= =3D -1) - perror_with_name (_("Couldn't get segment register gs_base")); - - regcache->raw_supply (tdep->fsbase_regnum + 1, &base); - if (regnum !=3D -1) - return; - } -#endif - if (regnum =3D=3D -1 || !amd64_native_gregset_supplies_p (gdbarch, regnu= m)) { struct fpreg fpregs; -#ifdef PT_GETXSTATE_INFO - void *xstateregs; - - if (x86bsd_xsave_len !=3D 0) - { - xstateregs =3D alloca (x86bsd_xsave_len); - if (gdb_ptrace (PT_GETXSTATE, ptid, (PTRACE_TYPE_ARG3) xstateregs, 0) - =3D=3D -1) - perror_with_name (_("Couldn't get extended state status")); - - amd64_supply_xsave (regcache, -1, xstateregs); - return; - } -#endif =20 if (gdb_ptrace (PT_GETFPREGS, ptid, (PTRACE_TYPE_ARG3) &fpregs, 0) = =3D=3D -1) perror_with_name (_("Couldn't get floating point status")); @@ -135,9 +91,6 @@ amd64bsd_store_inferior_registers (struct regcache *regc= ache, int regnum) { struct gdbarch *gdbarch =3D regcache->arch (); ptid_t ptid =3D regcache->ptid (); -#if defined(PT_SETFSBASE) || defined(PT_SETGSBASE) - i386_gdbarch_tdep *tdep =3D (i386_gdbarch_tdep *) gdbarch_tdep (gdbarch); -#endif =20 if (regnum =3D=3D -1 || amd64_native_gregset_supplies_p (gdbarch, regnum= )) { @@ -155,58 +108,9 @@ amd64bsd_store_inferior_registers (struct regcache *re= gcache, int regnum) return; } =20 -#ifdef PT_SETFSBASE - if (regnum =3D=3D -1 || regnum =3D=3D tdep->fsbase_regnum) - { - register_t base; - - /* Clear the full base value to support 32-bit targets. */ - base =3D 0; - regcache->raw_collect (tdep->fsbase_regnum, &base); - - if (gdb_ptrace (PT_SETFSBASE, ptid, (PTRACE_TYPE_ARG3) &base, 0) =3D= =3D -1) - perror_with_name (_("Couldn't write segment register fs_base")); - if (regnum !=3D -1) - return; - } -#endif -#ifdef PT_SETGSBASE - if (regnum =3D=3D -1 || regnum =3D=3D tdep->fsbase_regnum + 1) - { - register_t base; - - /* Clear the full base value to support 32-bit targets. */ - base =3D 0; - regcache->raw_collect (tdep->fsbase_regnum + 1, &base); - - if (gdb_ptrace (PT_SETGSBASE, ptid, (PTRACE_TYPE_ARG3) &base, 0) =3D= =3D -1) - perror_with_name (_("Couldn't write segment register gs_base")); - if (regnum !=3D -1) - return; - } -#endif - if (regnum =3D=3D -1 || !amd64_native_gregset_supplies_p (gdbarch, regnu= m)) { struct fpreg fpregs; -#ifdef PT_GETXSTATE_INFO - void *xstateregs; - - if (x86bsd_xsave_len !=3D 0) - { - xstateregs =3D alloca (x86bsd_xsave_len); - if (gdb_ptrace (PT_GETXSTATE, ptid, (PTRACE_TYPE_ARG3) xstateregs, 0) - =3D=3D -1) - perror_with_name (_("Couldn't get extended state status")); - - amd64_collect_xsave (regcache, regnum, xstateregs, 0); - - if (gdb_ptrace (PT_SETXSTATE, ptid, (PTRACE_TYPE_ARG3) xstateregs, - x86bsd_xsave_len) =3D=3D -1) - perror_with_name (_("Couldn't write extended state status")); - return; - } -#endif =20 if (gdb_ptrace (PT_GETFPREGS, ptid, (PTRACE_TYPE_ARG3) &fpregs, 0) = =3D=3D -1) perror_with_name (_("Couldn't get floating point status")); diff --git a/gdb/amd64-fbsd-nat.c b/gdb/amd64-fbsd-nat.c index f9bd45de455..98a1af03a66 100644 --- a/gdb/amd64-fbsd-nat.c +++ b/gdb/amd64-fbsd-nat.c @@ -31,17 +31,19 @@ =20 #include "fbsd-nat.h" #include "amd64-tdep.h" +#include "amd64-fbsd-tdep.h" #include "amd64-nat.h" -#include "amd64-bsd-nat.h" #include "x86-nat.h" #include "gdbsupport/x86-xstate.h" -=0C +#include "x86-bsd-nat.h" =20 class amd64_fbsd_nat_target final - : public amd64_bsd_nat_target + : public x86bsd_nat_target { public: - /* Add some extra features to the common *BSD/amd64 target. */ + void fetch_registers (struct regcache *, int) override; + void store_registers (struct regcache *, int) override; + const struct target_desc *read_description () override; =20 #if defined(HAVE_PT_GETDBREGS) && defined(USE_SIGTRAP_SIGINFO) @@ -51,61 +53,208 @@ public: =20 static amd64_fbsd_nat_target the_amd64_fbsd_nat_target; =20 -/* Offset in `struct reg' where MEMBER is stored. */ -#define REG_OFFSET(member) offsetof (struct reg, member) +#ifdef PT_GETXSTATE_INFO +static size_t xsave_len; +#endif + +/* This is a layout of the amd64 'struct reg' but with i386 + registers. */ =20 -/* At amd64fbsd64_r_reg_offset[REGNUM] you'll find the offset in - `struct reg' location where the GDB register REGNUM is stored. - Unsupported registers are marked with `-1'. */ -static int amd64fbsd64_r_reg_offset[] =3D +static const struct regcache_map_entry amd64_fbsd32_gregmap[] =3D { - REG_OFFSET (r_rax), - REG_OFFSET (r_rbx), - REG_OFFSET (r_rcx), - REG_OFFSET (r_rdx), - REG_OFFSET (r_rsi), - REG_OFFSET (r_rdi), - REG_OFFSET (r_rbp), - REG_OFFSET (r_rsp), - REG_OFFSET (r_r8), - REG_OFFSET (r_r9), - REG_OFFSET (r_r10), - REG_OFFSET (r_r11), - REG_OFFSET (r_r12), - REG_OFFSET (r_r13), - REG_OFFSET (r_r14), - REG_OFFSET (r_r15), - REG_OFFSET (r_rip), - REG_OFFSET (r_rflags), - REG_OFFSET (r_cs), - REG_OFFSET (r_ss), - -1, - -1, - -1, - -1 + { 8, REGCACHE_MAP_SKIP, 8 }, + { 1, I386_EDI_REGNUM, 8 }, + { 1, I386_ESI_REGNUM, 8 }, + { 1, I386_EBP_REGNUM, 8 }, + { 1, I386_EBX_REGNUM, 8 }, + { 1, I386_EDX_REGNUM, 8 }, + { 1, I386_ECX_REGNUM, 8 }, + { 1, I386_EAX_REGNUM, 8 }, + { 1, REGCACHE_MAP_SKIP, 4 }, /* trapno */ + { 1, I386_FS_REGNUM, 2 }, + { 1, I386_GS_REGNUM, 2 }, + { 1, REGCACHE_MAP_SKIP, 4 }, /* err */ + { 1, I386_ES_REGNUM, 2 }, + { 1, I386_DS_REGNUM, 2 }, + { 1, I386_EIP_REGNUM, 8 }, + { 1, I386_CS_REGNUM, 8 }, + { 1, I386_EFLAGS_REGNUM, 8 }, + { 1, I386_ESP_REGNUM, 0 }, + { 1, I386_SS_REGNUM, 8 }, + { 0 } }; -=0C =20 -/* Mapping between the general-purpose registers in FreeBSD/amd64 - `struct reg' format and GDB's register cache layout for - FreeBSD/i386. +static const struct regset amd64_fbsd32_gregset =3D +{ + amd64_fbsd32_gregmap, regcache_supply_regset, regcache_collect_regset +}; =20 - Note that most FreeBSD/amd64 registers are 64-bit, while the - FreeBSD/i386 registers are all 32-bit, but since we're - little-endian we get away with that. */ +/* Return the regset to use for 'struct reg' for the GDBARCH. */ =20 -/* From . */ -static int amd64fbsd32_r_reg_offset[I386_NUM_GREGS] =3D +static const struct regset * +find_gregset (struct gdbarch *gdbarch) { - 14 * 8, 13 * 8, /* %eax, %ecx */ - 12 * 8, 11 * 8, /* %edx, %ebx */ - 20 * 8, 10 * 8, /* %esp, %ebp */ - 9 * 8, 8 * 8, /* %esi, %edi */ - 17 * 8, 19 * 8, /* %eip, %eflags */ - 18 * 8, 21 * 8, /* %cs, %ss */ - -1, -1, -1, -1 /* %ds, %es, %fs, %gs */ -}; -=0C + if (gdbarch_bfd_arch_info (gdbarch)->bits_per_word =3D=3D 32) + return &amd64_fbsd32_gregset; + else + return &amd64_fbsd_gregset; +} + +/* Fetch register REGNUM from the inferior. If REGNUM is -1, do this + for all registers. */ + +void +amd64_fbsd_nat_target::fetch_registers (struct regcache *regcache, int reg= num) +{ + struct gdbarch *gdbarch =3D regcache->arch (); +#if defined(PT_GETFSBASE) || defined(PT_GETGSBASE) + const i386_gdbarch_tdep *tdep =3D (i386_gdbarch_tdep *) gdbarch_tdep (gd= barch); +#endif + pid_t pid =3D get_ptrace_pid (regcache->ptid ()); + const struct regset *gregset =3D find_gregset (gdbarch); + + if (fetch_register_set (regcache, regnum, PT_GETREGS, gregse= t)) + { + if (regnum !=3D -1) + return; + } + +#ifdef PT_GETFSBASE + if (regnum =3D=3D -1 || regnum =3D=3D tdep->fsbase_regnum) + { + register_t base; + + if (ptrace (PT_GETFSBASE, pid, (PTRACE_TYPE_ARG3) &base, 0) =3D=3D -= 1) + perror_with_name (_("Couldn't get segment register fs_base")); + + regcache->raw_supply (tdep->fsbase_regnum, &base); + if (regnum !=3D -1) + return; + } +#endif +#ifdef PT_GETGSBASE + if (regnum =3D=3D -1 || regnum =3D=3D tdep->fsbase_regnum + 1) + { + register_t base; + + if (ptrace (PT_GETGSBASE, pid, (PTRACE_TYPE_ARG3) &base, 0) =3D=3D -= 1) + perror_with_name (_("Couldn't get segment register gs_base")); + + regcache->raw_supply (tdep->fsbase_regnum + 1, &base); + if (regnum !=3D -1) + return; + } +#endif + + /* There is no amd64_fxsave_supplies or amd64_xsave_supplies. + Instead, the earlier register sets return early if the request + was for a specific register that was already satisified to avoid + fetching the FPU/XSAVE state unnecessarily. */ + +#ifdef PT_GETXSTATE_INFO + if (xsave_len !=3D 0) + { + void *xstateregs =3D alloca (xsave_len); + + if (ptrace (PT_GETXSTATE, pid, (PTRACE_TYPE_ARG3) xstateregs, 0) =3D= =3D -1) + perror_with_name (_("Couldn't get extended state status")); + + amd64_supply_xsave (regcache, regnum, xstateregs); + return; + } +#endif + + struct fpreg fpregs; + + if (ptrace (PT_GETFPREGS, pid, (PTRACE_TYPE_ARG3) &fpregs, 0) =3D=3D -1) + perror_with_name (_("Couldn't get floating point status")); + + amd64_supply_fxsave (regcache, regnum, &fpregs); +} + +/* Store register REGNUM back into the inferior. If REGNUM is -1, do + this for all registers. */ + +void +amd64_fbsd_nat_target::store_registers (struct regcache *regcache, int reg= num) +{ + struct gdbarch *gdbarch =3D regcache->arch (); +#if defined(PT_GETFSBASE) || defined(PT_GETGSBASE) + const i386_gdbarch_tdep *tdep =3D (i386_gdbarch_tdep *) gdbarch_tdep (gd= barch); +#endif + pid_t pid =3D get_ptrace_pid (regcache->ptid ()); + const struct regset *gregset =3D find_gregset (gdbarch); + + if (store_register_set (regcache, regnum, PT_GETREGS, PT_SET= REGS, + gregset)) + { + if (regnum !=3D -1) + return; + } + +#ifdef PT_SETFSBASE + if (regnum =3D=3D -1 || regnum =3D=3D tdep->fsbase_regnum) + { + register_t base; + + /* Clear the full base value to support 32-bit targets. */ + base =3D 0; + regcache->raw_collect (tdep->fsbase_regnum, &base); + + if (ptrace (PT_SETFSBASE, pid, (PTRACE_TYPE_ARG3) &base, 0) =3D=3D -= 1) + perror_with_name (_("Couldn't write segment register fs_base")); + if (regnum !=3D -1) + return; + } +#endif +#ifdef PT_SETGSBASE + if (regnum =3D=3D -1 || regnum =3D=3D tdep->fsbase_regnum + 1) + { + register_t base; + + /* Clear the full base value to support 32-bit targets. */ + base =3D 0; + regcache->raw_collect (tdep->fsbase_regnum + 1, &base); + + if (ptrace (PT_SETGSBASE, pid, (PTRACE_TYPE_ARG3) &base, 0) =3D=3D -= 1) + perror_with_name (_("Couldn't write segment register gs_base")); + if (regnum !=3D -1) + return; + } +#endif + + /* There is no amd64_fxsave_supplies or amd64_xsave_supplies. + Instead, the earlier register sets return early if the request + was for a specific register that was already satisified to avoid + fetching the FPU/XSAVE state unnecessarily. */ + +#ifdef PT_GETXSTATE_INFO + if (xsave_len !=3D 0) + { + void *xstateregs =3D alloca (xsave_len); + + if (ptrace (PT_GETXSTATE, pid, (PTRACE_TYPE_ARG3) xstateregs, 0) =3D= =3D -1) + perror_with_name (_("Couldn't get extended state status")); + + amd64_collect_xsave (regcache, regnum, xstateregs, 0); + + if (ptrace (PT_SETXSTATE, pid, (PTRACE_TYPE_ARG3) xstateregs, + xsave_len) =3D=3D -1) + perror_with_name (_("Couldn't write extended state status")); + return; + } +#endif + + struct fpreg fpregs; + + if (ptrace (PT_GETFPREGS, pid, (PTRACE_TYPE_ARG3) &fpregs, 0) =3D=3D -1) + perror_with_name (_("Couldn't get floating point status")); + + amd64_collect_fxsave (regcache, regnum, &fpregs); + + if (ptrace (PT_SETFPREGS, pid, (PTRACE_TYPE_ARG3) &fpregs, 0) =3D=3D -1) + perror_with_name (_("Couldn't write floating point status")); +} =20 /* Support for debugging kernel virtual memory images. */ =20 @@ -179,13 +328,13 @@ amd64_fbsd_nat_target::read_description () if (ptrace (PT_GETXSTATE_INFO, inferior_ptid.pid (), (PTRACE_TYPE_ARG3) &info, sizeof (info)) =3D=3D 0) { - x86bsd_xsave_len =3D info.xsave_len; + xsave_len =3D info.xsave_len; xcr0 =3D info.xsave_mask; } xsave_probed =3D 1; } =20 - if (x86bsd_xsave_len !=3D 0) + if (xsave_len !=3D 0) { if (is64) return amd64_target_description (xcr0, true); @@ -213,9 +362,6 @@ void _initialize_amd64fbsd_nat (); void _initialize_amd64fbsd_nat () { - amd64_native_gregset32_reg_offset =3D amd64fbsd32_r_reg_offset; - amd64_native_gregset64_reg_offset =3D amd64fbsd64_r_reg_offset; - add_inf_child_target (&the_amd64_fbsd_nat_target); =20 /* Support debugging kernel virtual memory images. */ diff --git a/gdb/amd64-fbsd-tdep.c b/gdb/amd64-fbsd-tdep.c index fa363776fc0..f87c976dd61 100644 --- a/gdb/amd64-fbsd-tdep.c +++ b/gdb/amd64-fbsd-tdep.c @@ -27,6 +27,7 @@ #include "gdbsupport/x86-xstate.h" =20 #include "amd64-tdep.h" +#include "amd64-fbsd-tdep.h" #include "fbsd-tdep.h" #include "solib-svr4.h" #include "inferior.h" diff --git a/gdb/amd64-fbsd-tdep.h b/gdb/amd64-fbsd-tdep.h new file mode 100644 index 00000000000..0a18dbcbfd7 --- /dev/null +++ b/gdb/amd64-fbsd-tdep.h @@ -0,0 +1,27 @@ +/* FreeBSD/amd64 target support, prototypes. + + Copyright (C) 2021 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 AMD64_FBSD_TDEP_H +#define AMD64_FBSD_TDEP_H + +#include "regset.h" + +extern const struct regset amd64_fbsd_gregset; + +#endif /* AMD64_FBSD_TDEP_H */ diff --git a/gdb/configure.nat b/gdb/configure.nat index 6fc3978a77e..20ce8050a96 100644 --- a/gdb/configure.nat +++ b/gdb/configure.nat @@ -165,7 +165,7 @@ case ${gdb_host} in i386) # Host: FreeBSD/i386 NATDEPFILES=3D"${NATDEPFILES} x86-nat.o nat/x86-dregs.o \ - x86-bsd-nat.o i386-bsd-nat.o i386-fbsd-nat.o bsd-kvm.o" + x86-bsd-nat.o i386-fbsd-nat.o bsd-kvm.o" ;; mips) # Host: FreeBSD/mips @@ -192,7 +192,7 @@ case ${gdb_host} in case ${gdb_host_cpu} in i386) # Host: FreeBSD/amd64 - NATDEPFILES=3D"${NATDEPFILES} amd64-nat.o amd64-bsd-nat.o \ + NATDEPFILES=3D"${NATDEPFILES} amd64-nat.o \ amd64-fbsd-nat.o bsd-kvm.o x86-nat.o nat/x86-dregs.o \ x86-bsd-nat.o" ;; diff --git a/gdb/i386-bsd-nat.c b/gdb/i386-bsd-nat.c index c112b02c2e1..bd9655c9ef9 100644 --- a/gdb/i386-bsd-nat.c +++ b/gdb/i386-bsd-nat.c @@ -159,56 +159,12 @@ i386bsd_fetch_inferior_registers (struct regcache *re= gcache, int regnum) return; } =20 -#ifdef PT_GETFSBASE - if (regnum =3D=3D -1 || regnum =3D=3D I386_FSBASE_REGNUM) - { - register_t base; - - if (gdb_ptrace (PT_GETFSBASE, ptid, (PTRACE_TYPE_ARG3) &base, 0) =3D= =3D -1) - perror_with_name (_("Couldn't get segment register fs_base")); - - regcache->raw_supply (I386_FSBASE_REGNUM, &base); - if (regnum !=3D -1) - return; - } -#endif -#ifdef PT_GETGSBASE - if (regnum =3D=3D -1 || regnum =3D=3D I386_GSBASE_REGNUM) - { - register_t base; - - if (gdb_ptrace (PT_GETGSBASE, ptid, (PTRACE_TYPE_ARG3) &base, 0) =3D= =3D -1) - perror_with_name (_("Couldn't get segment register gs_base")); - - regcache->raw_supply (I386_GSBASE_REGNUM, &base); - if (regnum !=3D -1) - return; - } -#endif - if (regnum =3D=3D -1 || regnum >=3D I386_ST0_REGNUM) { struct fpreg fpregs; #ifdef HAVE_PT_GETXMMREGS char xmmregs[512]; -#endif - -#ifdef PT_GETXSTATE_INFO - if (x86bsd_xsave_len !=3D 0) - { - void *xstateregs; =20 - xstateregs =3D alloca (x86bsd_xsave_len); - if (gdb_ptrace (PT_GETXSTATE, ptid, - (PTRACE_TYPE_ARG3) xstateregs, 0) =3D=3D -1) - perror_with_name (_("Couldn't get extended state status")); - - i387_supply_xsave (regcache, -1, xstateregs); - return; - } -#endif - =20 -#ifdef HAVE_PT_GETXMMREGS if (have_ptrace_xmmregs !=3D 0 && gdb_ptrace(PT_GETXMMREGS, ptid, (PTRACE_TYPE_ARG3) xmmregs, 0) =3D=3D 0) @@ -255,60 +211,12 @@ i386bsd_store_inferior_registers (struct regcache *re= gcache, int regnum) return; } =20 -#ifdef PT_SETFSBASE - if (regnum =3D=3D -1 || regnum =3D=3D I386_FSBASE_REGNUM) - { - register_t base; - - regcache->raw_collect (I386_FSBASE_REGNUM, &base); - - if (gdb_ptrace (PT_SETFSBASE, ptid, (PTRACE_TYPE_ARG3) &base, 0) =3D= =3D -1) - perror_with_name (_("Couldn't write segment register fs_base")); - if (regnum !=3D -1) - return; - } -#endif -#ifdef PT_SETGSBASE - if (regnum =3D=3D -1 || regnum =3D=3D I386_GSBASE_REGNUM) - { - register_t base; - - regcache->raw_collect (I386_GSBASE_REGNUM, &base); - - if (gdb_ptrace (PT_SETGSBASE, ptid, (PTRACE_TYPE_ARG3) &base, 0) =3D= =3D -1) - perror_with_name (_("Couldn't write segment register gs_base")); - if (regnum !=3D -1) - return; - } -#endif - if (regnum =3D=3D -1 || regnum >=3D I386_ST0_REGNUM) { struct fpreg fpregs; #ifdef HAVE_PT_GETXMMREGS char xmmregs[512]; -#endif - -#ifdef PT_GETXSTATE_INFO - if (x86bsd_xsave_len !=3D 0) - { - void *xstateregs; - - xstateregs =3D alloca (x86bsd_xsave_len); - if (gdb_ptrace (PT_GETXSTATE, ptid, - (PTRACE_TYPE_ARG3) xstateregs, 0) =3D=3D -1) - perror_with_name (_("Couldn't get extended state status")); =20 - i387_collect_xsave (regcache, -1, xstateregs, 0); - - if (gdb_ptrace (PT_SETXSTATE, ptid, (PTRACE_TYPE_ARG3) xstateregs, - x86bsd_xsave_len) =3D=3D -1) - perror_with_name (_("Couldn't write extended state status")); - return; - } -#endif - -#ifdef HAVE_PT_GETXMMREGS if (have_ptrace_xmmregs !=3D 0 && gdb_ptrace(PT_GETXMMREGS, ptid, (PTRACE_TYPE_ARG3) xmmregs, 0) =3D=3D 0) diff --git a/gdb/i386-fbsd-nat.c b/gdb/i386-fbsd-nat.c index 75fe5e78f20..6fb67434a2d 100644 --- a/gdb/i386-fbsd-nat.c +++ b/gdb/i386-fbsd-nat.c @@ -29,17 +29,20 @@ =20 #include "fbsd-nat.h" #include "i386-tdep.h" +#include "i386-fbsd-tdep.h" +#include "i387-tdep.h" #include "x86-nat.h" #include "gdbsupport/x86-xstate.h" #include "x86-bsd-nat.h" -#include "i386-bsd-nat.h" =20 class i386_fbsd_nat_target final - : public i386_bsd_nat_target + : public x86bsd_nat_target { public: - /* Add some extra features to the common *BSD/i386 target. */ -#ifdef PT_GETXSTATE_INFO + void fetch_registers (struct regcache *, int) override; + void store_registers (struct regcache *, int) override; + +#if defined(PT_GETXMMREGS) || defined(PT_GETXSTATE_INFO) const struct target_desc *read_description () override; #endif =20 @@ -52,6 +55,192 @@ public: =20 static i386_fbsd_nat_target the_i386_fbsd_nat_target; =20 +#ifdef PT_GETXSTATE_INFO +static size_t xsave_len; +#endif + +#ifdef HAVE_PT_GETXMMREGS +static int have_ptrace_xmmregs; +#endif + +/* Fetch register REGNUM from the inferior. If REGNUM is -1, do this + for all registers. */ + +void +i386_fbsd_nat_target::fetch_registers (struct regcache *regcache, int regn= um) +{ + struct gdbarch *gdbarch =3D regcache->arch (); +#if defined(PT_GETFSBASE) || defined(PT_GETGSBASE) + const struct gdbarch_tdep *tdep =3D gdbarch_tdep (gdbarch); +#endif + pid_t pid =3D get_ptrace_pid (regcache->ptid ()); + + if (fetch_register_set (regcache, regnum, PT_GETREGS, + &i386_fbsd_gregset)) + { + if (regnum !=3D -1) + return; + } + +#ifdef PT_GETFSBASE + if (regnum =3D=3D -1 || regnum =3D=3D I386_FSBASE_REGNUM) + { + register_t base; + + if (ptrace (PT_GETFSBASE, pid, (PTRACE_TYPE_ARG3) &base, 0) =3D=3D -= 1) + perror_with_name (_("Couldn't get segment register fs_base")); + + regcache->raw_supply (I386_FSBASE_REGNUM, &base); + if (regnum !=3D -1) + return; + } +#endif +#ifdef PT_GETGSBASE + if (regnum =3D=3D -1 || regnum =3D=3D I386_GSBASE_REGNUM) + { + register_t base; + + if (ptrace (PT_GETGSBASE, pid, (PTRACE_TYPE_ARG3) &base, 0) =3D=3D -= 1) + perror_with_name (_("Couldn't get segment register gs_base")); + + regcache->raw_supply (I386_GSBASE_REGNUM, &base); + if (regnum !=3D -1) + return; + } +#endif + + /* There is no i386_fxsave_supplies or i386_xsave_supplies. + Instead, the earlier register sets return early if the request + was for a specific register that was already satisified to avoid + fetching the FPU/XSAVE state unnecessarily. */ + +#ifdef PT_GETXSTATE_INFO + if (xsave_len !=3D 0) + { + void *xstateregs =3D alloca (xsave_len); + + if (ptrace (PT_GETXSTATE, pid, (PTRACE_TYPE_ARG3) xstateregs, 0) =3D= =3D -1) + perror_with_name (_("Couldn't get extended state status")); + + i387_supply_xsave (regcache, regnum, xstateregs); + return; + } +#endif +#ifdef HAVE_PT_GETXMMREGS + if (have_ptrace_xmmregs !=3D 0) + { + char xmmregs[I387_SIZEOF_FXSAVE]; + + if (ptrace(PT_GETXMMREGS, pid, (PTRACE_TYPE_ARG3) xmmregs, 0) =3D=3D= -1) + perror_with_name (_("Couldn't get XMM registers")); + + i387_supply_fxsave (regcache, regnum, xmmregs); + return; + } +#endif + + struct fpreg fpregs; + + if (ptrace (PT_GETFPREGS, pid, (PTRACE_TYPE_ARG3) &fpregs, 0) =3D=3D -1) + perror_with_name (_("Couldn't get floating point status")); + + i387_supply_fsave (regcache, regnum, &fpregs); +} + +/* Store register REGNUM back into the inferior. If REGNUM is -1, do + this for all registers. */ + +void +i386_fbsd_nat_target::store_registers (struct regcache *regcache, int regn= um) +{ + struct gdbarch *gdbarch =3D regcache->arch (); +#if defined(PT_GETFSBASE) || defined(PT_GETGSBASE) + const struct gdbarch_tdep *tdep =3D gdbarch_tdep (gdbarch); +#endif + pid_t pid =3D get_ptrace_pid (regcache->ptid ()); + + if (store_register_set (regcache, regnum, PT_GETREGS, PT_SET= REGS, + &i386_fbsd_gregset)) + { + if (regnum !=3D -1) + return; + } + +#ifdef PT_SETFSBASE + if (regnum =3D=3D -1 || regnum =3D=3D I386_FSBASE_REGNUM) + { + register_t base; + + regcache->raw_collect (I386_FSBASE_REGNUM, &base); + + if (ptrace (PT_SETFSBASE, pid, (PTRACE_TYPE_ARG3) &base, 0) =3D=3D -= 1) + perror_with_name (_("Couldn't write segment register fs_base")); + if (regnum !=3D -1) + return; + } +#endif +#ifdef PT_SETGSBASE + if (regnum =3D=3D -1 || regnum =3D=3D I386_GSBASE_REGNUM) + { + register_t base; + + regcache->raw_collect (I386_GSBASE_REGNUM, &base); + + if (ptrace (PT_SETGSBASE, pid, (PTRACE_TYPE_ARG3) &base, 0) =3D=3D -= 1) + perror_with_name (_("Couldn't write segment register gs_base")); + if (regnum !=3D -1) + return; + } +#endif + + /* There is no i386_fxsave_supplies or i386_xsave_supplies. + Instead, the earlier register sets return early if the request + was for a specific register that was already satisified to avoid + fetching the FPU/XSAVE state unnecessarily. */ + +#ifdef PT_GETXSTATE_INFO + if (xsave_len !=3D 0) + { + void *xstateregs =3D alloca (xsave_len); + + if (ptrace (PT_GETXSTATE, pid, (PTRACE_TYPE_ARG3) xstateregs, 0) =3D= =3D -1) + perror_with_name (_("Couldn't get extended state status")); + + i387_collect_xsave (regcache, regnum, xstateregs, 0); + + if (ptrace (PT_SETXSTATE, pid, (PTRACE_TYPE_ARG3) xstateregs, xsave_= len) + =3D=3D -1) + perror_with_name (_("Couldn't write extended state status")); + return; + } +#endif +#ifdef HAVE_PT_GETXMMREGS + if (have_ptrace_xmmregs !=3D 0) + { + char xmmregs[I387_SIZEOF_FXSAVE]; + + if (ptrace(PT_GETXMMREGS, pid, (PTRACE_TYPE_ARG3) xmmregs, 0) =3D=3D= -1) + perror_with_name (_("Couldn't get XMM registers")); + + i387_collect_fxsave (regcache, regnum, xmmregs); + + if (ptrace (PT_SETXMMREGS, pid, (PTRACE_TYPE_ARG3) xmmregs, 0) =3D= =3D -1) + perror_with_name (_("Couldn't write XMM registers")); + return; + } +#endif + + struct fpreg fpregs; + + if (ptrace (PT_GETFPREGS, pid, (PTRACE_TYPE_ARG3) &fpregs, 0) =3D=3D -1) + perror_with_name (_("Couldn't get floating point status")); + + i387_collect_fsave (regcache, regnum, &fpregs); + + if (ptrace (PT_SETFPREGS, pid, (PTRACE_TYPE_ARG3) &fpregs, 0) =3D=3D -1) + perror_with_name (_("Couldn't write floating point status")); +} + /* Resume execution of the inferior process. If STEP is nonzero, single-step it. If SIGNAL is nonzero, give it that signal. */ =20 @@ -135,15 +324,21 @@ i386fbsd_supply_pcb (struct regcache *regcache, struc= t pcb *pcb) } =0C =20 -#ifdef PT_GETXSTATE_INFO +#if defined(PT_GETXMMREGS) || defined(PT_GETXSTATE_INFO) /* Implement the read_description method. */ =20 const struct target_desc * i386_fbsd_nat_target::read_description () { +#ifdef PT_GETXSTATE_INFO static int xsave_probed; static uint64_t xcr0; +#endif +#ifdef PT_GETXMMREGS + static int xmm_probed; +#endif =20 +#ifdef PT_GETXSTATE_INFO if (!xsave_probed) { struct ptrace_xstate_info info; @@ -151,16 +346,32 @@ i386_fbsd_nat_target::read_description () if (ptrace (PT_GETXSTATE_INFO, inferior_ptid.pid (), (PTRACE_TYPE_ARG3) &info, sizeof (info)) =3D=3D 0) { - x86bsd_xsave_len =3D info.xsave_len; + xsave_len =3D info.xsave_len; xcr0 =3D info.xsave_mask; } xsave_probed =3D 1; } =20 - if (x86bsd_xsave_len =3D=3D 0) - xcr0 =3D X86_XSTATE_SSE_MASK; + if (xsave_len !=3D 0) + return i386_target_description (xcr0, true); +#endif + +#ifdef PT_GETXMMREGS + if (!xmm_probed) + { + char xmmregs[I387_SIZEOF_FXSAVE]; + + if (ptrace (PT_GETXMMREGS, inferior_ptid.pid (), + (PTRACE_TYPE_ARG3) xmmregs, 0) =3D=3D 0) + have_ptrace_xmmregs =3D 1; + xmm_probed =3D 1; + } + + if (have_ptrace_xmmregs) + return i386_target_description (X86_XSTATE_SSE_MASK, true); +#endif =20 - return i386_target_description (xcr0, true); + return i386_target_description (X86_XSTATE_X87_MASK, true); } #endif =20 diff --git a/gdb/i386-fbsd-tdep.h b/gdb/i386-fbsd-tdep.h index 583f49f84f2..76f4c20f657 100644 --- a/gdb/i386-fbsd-tdep.h +++ b/gdb/i386-fbsd-tdep.h @@ -20,6 +20,8 @@ #ifndef I386_FBSD_TDEP_H #define I386_FBSD_TDEP_H =20 +#include "regset.h" + /* Get XSAVE extended state xcr0 from core dump. */ extern uint64_t i386fbsd_core_read_xcr0 (bfd *abfd); =20 @@ -28,4 +30,6 @@ extern uint64_t i386fbsd_core_read_xcr0 (bfd *abfd); matches the layout on Linux. */ #define I386_FBSD_XSAVE_XCR0_OFFSET 464 =20 +extern const struct regset i386_fbsd_gregset; + #endif /* i386-fbsd-tdep.h */ diff --git a/gdb/x86-bsd-nat.c b/gdb/x86-bsd-nat.c index 06da979f83b..099059a5e0b 100644 --- a/gdb/x86-bsd-nat.c +++ b/gdb/x86-bsd-nat.c @@ -33,10 +33,6 @@ #include "inf-ptrace.h" =0C =20 -#ifdef PT_GETXSTATE_INFO -size_t x86bsd_xsave_len; -#endif - /* Support for debug registers. */ =20 #ifdef HAVE_PT_GETDBREGS diff --git a/gdb/x86-bsd-nat.h b/gdb/x86-bsd-nat.h index a545ee33306..8b6760e7169 100644 --- a/gdb/x86-bsd-nat.h +++ b/gdb/x86-bsd-nat.h @@ -22,9 +22,6 @@ =20 #include "x86-nat.h" =20 -/* Low level x86 XSAVE info. */ -extern size_t x86bsd_xsave_len; - /* A prototype *BSD/x86 target. */ =20 #ifdef HAVE_PT_GETDBREGS