diff options
-rw-r--r-- | gdb/Makefile.in | 3 | ||||
-rw-r--r-- | gdb/amd64-linux-tdep.c | 1 | ||||
-rw-r--r-- | gdb/amd64-linux-tdep.h | 6 | ||||
-rw-r--r-- | gdb/arch/amd64-linux-tdesc.h | 30 | ||||
-rw-r--r-- | gdb/arch/i386-linux-tdesc.h | 29 | ||||
-rw-r--r-- | gdb/configure.nat | 5 | ||||
-rw-r--r-- | gdb/i386-linux-tdep.c | 1 | ||||
-rw-r--r-- | gdb/i386-linux-tdep.h | 3 | ||||
-rw-r--r-- | gdb/nat/x86-linux-tdesc.c | 133 | ||||
-rw-r--r-- | gdb/nat/x86-linux-tdesc.h | 51 | ||||
-rw-r--r-- | gdb/x86-linux-nat.c | 88 | ||||
-rw-r--r-- | gdbserver/configure.srv | 2 | ||||
-rw-r--r-- | gdbserver/i387-fp.cc | 9 | ||||
-rw-r--r-- | gdbserver/i387-fp.h | 4 | ||||
-rw-r--r-- | gdbserver/linux-amd64-ipa.cc | 1 | ||||
-rw-r--r-- | gdbserver/linux-i386-ipa.cc | 1 | ||||
-rw-r--r-- | gdbserver/linux-x86-low.cc | 142 | ||||
-rw-r--r-- | gdbserver/linux-x86-tdesc.cc | 2 | ||||
-rw-r--r-- | gdbserver/linux-x86-tdesc.h | 7 |
19 files changed, 309 insertions, 209 deletions
diff --git a/gdb/Makefile.in b/gdb/Makefile.in index 277f878..949f104 100644 --- a/gdb/Makefile.in +++ b/gdb/Makefile.in @@ -1550,8 +1550,10 @@ HFILES_NO_SRCDIR = \ arch/aarch64-insn.h \ arch/aarch64-mte-linux.h \ arch/aarch64-scalable-linux.h \ + arch/amd64-linux-tdesc.h \ arch/arc.h \ arch/arm.h \ + arch/i386-linux-tdesc.h \ arch/i386.h \ arch/loongarch.h \ arch/ppc-linux-common.h \ @@ -1608,6 +1610,7 @@ HFILES_NO_SRCDIR = \ nat/x86-gcc-cpuid.h \ nat/x86-linux.h \ nat/x86-linux-dregs.h \ + nat/x86-linux-tdesc.h \ python/py-event.h \ python/py-events.h \ python/py-stopevent.h \ diff --git a/gdb/amd64-linux-tdep.c b/gdb/amd64-linux-tdep.c index c52b043..f9647dc 100644 --- a/gdb/amd64-linux-tdep.c +++ b/gdb/amd64-linux-tdep.c @@ -42,6 +42,7 @@ #include "arch/amd64.h" #include "target-descriptions.h" #include "expop.h" +#include "arch/amd64-linux-tdesc.h" /* The syscall's XML filename for i386. */ #define XML_SYSCALL_FILENAME_AMD64 "syscalls/amd64-linux.xml" diff --git a/gdb/amd64-linux-tdep.h b/gdb/amd64-linux-tdep.h index 6617025..6f5b55a 100644 --- a/gdb/amd64-linux-tdep.h +++ b/gdb/amd64-linux-tdep.h @@ -31,12 +31,6 @@ /* Total number of registers for GNU/Linux. */ #define AMD64_LINUX_NUM_REGS (AMD64_LINUX_ORIG_RAX_REGNUM + 1) -/* Return the right amd64-linux target descriptions according to - XCR0_FEATURES_BIT and IS_X32. */ - -const target_desc *amd64_linux_read_description (uint64_t xcr0_features_bit, - bool is_x32); - /* Enum that defines the syscall identifiers for amd64 linux. Used for process record/replay, these will be translated into a gdb-canonical set of syscall ids in linux-record.c. */ diff --git a/gdb/arch/amd64-linux-tdesc.h b/gdb/arch/amd64-linux-tdesc.h new file mode 100644 index 0000000..db425b6 --- /dev/null +++ b/gdb/arch/amd64-linux-tdesc.h @@ -0,0 +1,30 @@ +/* Target description related code for GNU/Linux x86-64. + + Copyright (C) 2024 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 ARCH_AMD64_LINUX_TDESC_H +#define ARCH_AMD64_LINUX_TDESC_H + +struct target_desc; + +/* Return the AMD64 target descriptions corresponding to XCR0 and IS_X32. */ + +extern const target_desc *amd64_linux_read_description (uint64_t xcr0, + bool is_x32); + +#endif /* ARCH_AMD64_LINUX_TDESC_H */ diff --git a/gdb/arch/i386-linux-tdesc.h b/gdb/arch/i386-linux-tdesc.h new file mode 100644 index 0000000..0b73633 --- /dev/null +++ b/gdb/arch/i386-linux-tdesc.h @@ -0,0 +1,29 @@ +/* Target description related code for GNU/Linux i386. + + Copyright (C) 2024 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 ARCH_I386_LINUX_TDESC_H +#define ARCH_I386_LINUX_TDESC_H + +struct target_desc; + +/* Return the i386 target description corresponding to XCR0. */ + +extern const struct target_desc *i386_linux_read_description (uint64_t xcr0); + +#endif /* ARCH_I386_LINUX_TDESC_H */ diff --git a/gdb/configure.nat b/gdb/configure.nat index 25268bb..a30b07e 100644 --- a/gdb/configure.nat +++ b/gdb/configure.nat @@ -256,7 +256,8 @@ case ${gdb_host} in NATDEPFILES="${NATDEPFILES} x86-nat.o nat/x86-dregs.o \ nat/x86-xstate.o \ i386-linux-nat.o x86-linux-nat.o nat/linux-btrace.o \ - nat/x86-linux.o nat/x86-linux-dregs.o nat/i386-linux.o" + nat/x86-linux.o nat/x86-linux-dregs.o nat/i386-linux.o \ + nat/x86-linux-tdesc.o" ;; ia64) # Host: Intel IA-64 running GNU/Linux @@ -322,7 +323,7 @@ case ${gdb_host} in NATDEPFILES="${NATDEPFILES} x86-nat.o nat/x86-dregs.o \ nat/x86-xstate.o amd64-nat.o amd64-linux-nat.o x86-linux-nat.o \ nat/linux-btrace.o \ - nat/x86-linux.o nat/x86-linux-dregs.o \ + nat/x86-linux.o nat/x86-linux-dregs.o nat/x86-linux-tdesc.o \ nat/amd64-linux-siginfo.o" ;; sparc) diff --git a/gdb/i386-linux-tdep.c b/gdb/i386-linux-tdep.c index 511e43f..6a74906 100644 --- a/gdb/i386-linux-tdep.c +++ b/gdb/i386-linux-tdep.c @@ -40,6 +40,7 @@ #include "i387-tdep.h" #include "gdbsupport/x86-xstate.h" +#include "arch/i386-linux-tdesc.h" /* The syscall's XML filename for i386. */ #define XML_SYSCALL_FILENAME_I386 "syscalls/i386-linux.xml" diff --git a/gdb/i386-linux-tdep.h b/gdb/i386-linux-tdep.h index 07593c6..e8691cd 100644 --- a/gdb/i386-linux-tdep.h +++ b/gdb/i386-linux-tdep.h @@ -55,9 +55,6 @@ extern void i386_linux_report_signal_info (struct gdbarch *gdbarch, struct ui_out *uiout, enum gdb_signal siggnal); -/* Return the target description according to XCR0. */ -extern const struct target_desc *i386_linux_read_description (uint64_t xcr0); - extern int i386_linux_gregset_reg_offset[]; /* Return x86 siginfo type. */ diff --git a/gdb/nat/x86-linux-tdesc.c b/gdb/nat/x86-linux-tdesc.c new file mode 100644 index 0000000..05aa75d --- /dev/null +++ b/gdb/nat/x86-linux-tdesc.c @@ -0,0 +1,133 @@ +/* Target description related code for GNU/Linux x86 (i386 and x86-64). + + Copyright (C) 2024 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/>. */ + +#include "nat/x86-linux-tdesc.h" +#ifdef __x86_64__ +#include "arch/amd64.h" +#include "arch/amd64-linux-tdesc.h" +#endif +#include "arch/i386.h" +#include "arch/i386-linux-tdesc.h" + +#include "nat/x86-linux.h" +#include "nat/gdb_ptrace.h" +#include "nat/x86-xstate.h" +#include "gdbsupport/x86-xstate.h" + +#ifndef __x86_64__ +#include <sys/procfs.h> +#include "nat/i386-linux.h" +#endif + +#include <sys/uio.h> +#include <elf.h> + +#ifndef IN_PROCESS_AGENT + +/* See nat/x86-linux-tdesc.h. */ + +const target_desc * +x86_linux_tdesc_for_tid (int tid, uint64_t *xcr0_storage, + x86_xsave_layout *xsave_layout_storage) +{ +#ifdef __x86_64__ + x86_linux_arch_size arch_size = x86_linux_ptrace_get_arch_size (tid); + bool is_64bit = arch_size.is_64bit (); + bool is_x32 = arch_size.is_x32 (); + + if (sizeof (void *) == 4 && is_64bit && !is_x32) + { +#ifdef GDBSERVER + error (_("Can't debug 64-bit process with 32-bit GDBserver")); +#else + error (_("Can't debug 64-bit process with 32-bit GDB")); +#endif + } + +#elif HAVE_PTRACE_GETFPXREGS + if (have_ptrace_getfpxregs == TRIBOOL_UNKNOWN) + { + elf_fpxregset_t fpxregs; + + if (ptrace (PTRACE_GETFPXREGS, tid, 0, (int) &fpxregs) < 0) + { + have_ptrace_getfpxregs = TRIBOOL_FALSE; + have_ptrace_getregset = TRIBOOL_FALSE; + } + else + have_ptrace_getfpxregs = TRIBOOL_TRUE; + } + + if (have_ptrace_getfpxregs == TRIBOOL_FALSE) + return i386_linux_read_description (X86_XSTATE_X87_MASK); +#endif + + if (have_ptrace_getregset == TRIBOOL_UNKNOWN) + { + uint64_t xstateregs[(X86_XSTATE_SSE_SIZE / sizeof (uint64_t))]; + struct iovec iov; + + iov.iov_base = xstateregs; + iov.iov_len = sizeof (xstateregs); + + /* Check if PTRACE_GETREGSET works. */ + if (ptrace (PTRACE_GETREGSET, tid, + (unsigned int) NT_X86_XSTATE, &iov) < 0) + { + have_ptrace_getregset = TRIBOOL_FALSE; + *xcr0_storage = 0; + } + else + { + have_ptrace_getregset = TRIBOOL_TRUE; + + /* Get XCR0 from XSAVE extended state. */ + *xcr0_storage = xstateregs[(I386_LINUX_XSAVE_XCR0_OFFSET + / sizeof (uint64_t))]; + +#ifdef __x86_64__ + /* No MPX on x32. */ + if (is_64bit && is_x32) + *xcr0_storage &= ~X86_XSTATE_MPX; +#endif /* __x86_64__ */ + + *xsave_layout_storage + = x86_fetch_xsave_layout (*xcr0_storage, x86_xsave_length ()); + } + } + + /* Check the native XCR0 only if PTRACE_GETREGSET is available. If + PTRACE_GETREGSET is not available then set xcr0_features_bits to + zero so that the "no-features" descriptions are returned by the + code below. */ + uint64_t xcr0_features_bits; + if (have_ptrace_getregset == TRIBOOL_TRUE) + xcr0_features_bits = *xcr0_storage & X86_XSTATE_ALL_MASK; + else + xcr0_features_bits = 0; + +#ifdef __x86_64__ + if (is_64bit) + return amd64_linux_read_description (xcr0_features_bits, is_x32); + else +#endif + return i386_linux_read_description (xcr0_features_bits); +} + +#endif /* !IN_PROCESS_AGENT */ diff --git a/gdb/nat/x86-linux-tdesc.h b/gdb/nat/x86-linux-tdesc.h new file mode 100644 index 0000000..b7a4649 --- /dev/null +++ b/gdb/nat/x86-linux-tdesc.h @@ -0,0 +1,51 @@ +/* Target description related code for GNU/Linux x86 (i386 and x86-64). + + Copyright (C) 2024 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 NAT_X86_LINUX_TDESC_H +#define NAT_X86_LINUX_TDESC_H + +#include "gdbsupport/function-view.h" + +struct target_desc; +struct x86_xsave_layout; + +/* Return the target description for Linux thread TID. + + The storage pointed to by XCR0_STORAGE and XSAVE_LAYOUT_STORAGE must + exist until the program (GDB or gdbserver) terminates, this storage is + used to cache the xcr0 and xsave layout values. The values pointed to + by these arguments are only updated at most once, the first time this + function is called if the have_ptrace_getregset global is set to + TRIBOOL_UNKNOWN. + + This function returns a target description based on the extracted xcr0 + value along with other characteristics of the thread identified by TID. + + This function can return nullptr if we encounter a machine configuration + for which a target_desc cannot be created. Ideally this would not be + the case, we should be able to create a target description for every + possible machine configuration. See amd64_linux_read_description and + i386_linux_read_description for cases when nullptr might be + returned. */ + +extern const target_desc * +x86_linux_tdesc_for_tid (int tid, uint64_t *xcr0_storage, + x86_xsave_layout *xsave_layout_storage); + +#endif /* NAT_X86_LINUX_TDESC_H */ diff --git a/gdb/x86-linux-nat.c b/gdb/x86-linux-nat.c index ed76c17..2afa04f 100644 --- a/gdb/x86-linux-nat.c +++ b/gdb/x86-linux-nat.c @@ -41,6 +41,7 @@ #include "nat/x86-linux.h" #include "nat/x86-linux-dregs.h" #include "nat/linux-ptrace.h" +#include "nat/x86-linux-tdesc.h" /* linux_nat_target::low_new_fork implementation. */ @@ -95,93 +96,16 @@ x86_linux_nat_target::post_startup_inferior (ptid_t ptid) const struct target_desc * x86_linux_nat_target::read_description () { - int tid; - int is_64bit = 0; -#ifdef __x86_64__ - int is_x32; -#endif - static uint64_t xcr0; - uint64_t xcr0_features_bits; + /* The x86_linux_tdesc_for_tid call only reads xcr0 the first time it is + called, the xcr0 value is stored here and reused on subsequent calls. */ + static uint64_t xcr0_storage; if (inferior_ptid == null_ptid) return this->beneath ()->read_description (); - tid = inferior_ptid.pid (); - -#ifdef __x86_64__ - - x86_linux_arch_size arch_size = x86_linux_ptrace_get_arch_size (tid); - is_64bit = arch_size.is_64bit (); - is_x32 = arch_size.is_x32 (); - - if (sizeof (void *) == 4 && is_64bit && !is_x32) - error (_("Can't debug 64-bit process with 32-bit GDB")); - -#elif HAVE_PTRACE_GETFPXREGS - if (have_ptrace_getfpxregs == TRIBOOL_UNKNOWN) - { - elf_fpxregset_t fpxregs; - - if (ptrace (PTRACE_GETFPXREGS, tid, 0, (int) &fpxregs) < 0) - { - have_ptrace_getfpxregs = TRIBOOL_FALSE; - have_ptrace_getregset = TRIBOOL_FALSE; - return i386_linux_read_description (X86_XSTATE_X87_MASK); - } - } -#endif - - if (have_ptrace_getregset == TRIBOOL_UNKNOWN) - { - uint64_t xstateregs[(X86_XSTATE_SSE_SIZE / sizeof (uint64_t))]; - struct iovec iov; - - iov.iov_base = xstateregs; - iov.iov_len = sizeof (xstateregs); - - /* Check if PTRACE_GETREGSET works. */ - if (ptrace (PTRACE_GETREGSET, tid, - (unsigned int) NT_X86_XSTATE, &iov) < 0) - have_ptrace_getregset = TRIBOOL_FALSE; - else - { - have_ptrace_getregset = TRIBOOL_TRUE; - - /* Get XCR0 from XSAVE extended state. */ - xcr0 = xstateregs[(I386_LINUX_XSAVE_XCR0_OFFSET - / sizeof (uint64_t))]; - - m_xsave_layout = x86_fetch_xsave_layout (xcr0, x86_xsave_length ()); - } - } - - /* Check the native XCR0 only if PTRACE_GETREGSET is available. If - PTRACE_GETREGSET is not available then set xcr0_features_bits to - zero so that the "no-features" descriptions are returned by the - switches below. */ - if (have_ptrace_getregset == TRIBOOL_TRUE) - xcr0_features_bits = xcr0 & X86_XSTATE_ALL_MASK; - else - xcr0_features_bits = 0; - - if (is_64bit) - { -#ifdef __x86_64__ - return amd64_linux_read_description (xcr0_features_bits, is_x32); -#endif - } - else - { - const struct target_desc * tdesc - = i386_linux_read_description (xcr0_features_bits); - - if (tdesc == NULL) - tdesc = i386_linux_read_description (X86_XSTATE_SSE_MASK); - - return tdesc; - } + int tid = inferior_ptid.pid (); - gdb_assert_not_reached ("failed to return tdesc"); + return x86_linux_tdesc_for_tid (tid, &xcr0_storage, &this->m_xsave_layout); } diff --git a/gdbserver/configure.srv b/gdbserver/configure.srv index 8e882d2..538845b 100644 --- a/gdbserver/configure.srv +++ b/gdbserver/configure.srv @@ -110,6 +110,7 @@ case "${gdbserver_host}" in srv_tgtobj="${srv_tgtobj} nat/x86-linux.o" srv_tgtobj="${srv_tgtobj} nat/x86-linux-dregs.o" srv_tgtobj="${srv_tgtobj} nat/i386-linux.o" + srv_tgtobj="${srv_tgtobj} nat/x86-linux-tdesc.o" srv_linux_usrregs=yes srv_linux_regsets=yes srv_linux_thread_db=yes @@ -372,6 +373,7 @@ case "${gdbserver_host}" in srv_tgtobj="${srv_tgtobj} nat/linux-btrace.o" srv_tgtobj="${srv_tgtobj} nat/x86-linux.o" srv_tgtobj="${srv_tgtobj} nat/x86-linux-dregs.o" + srv_tgtobj="${srv_tgtobj} nat/x86-linux-tdesc.o" srv_tgtobj="${srv_tgtobj} nat/amd64-linux-siginfo.o" srv_linux_usrregs=yes # This is for i386 progs. srv_linux_regsets=yes diff --git a/gdbserver/i387-fp.cc b/gdbserver/i387-fp.cc index 62cafd8..4d8bcb5 100644 --- a/gdbserver/i387-fp.cc +++ b/gdbserver/i387-fp.cc @@ -21,7 +21,7 @@ #include "nat/x86-xstate.h" /* Default to SSE. */ -static unsigned long long x86_xcr0 = X86_XSTATE_SSE_MASK; +static uint64_t x86_xcr0 = X86_XSTATE_SSE_MASK; static const int num_mpx_bnd_registers = 4; static const int num_mpx_cfg_registers = 2; @@ -944,9 +944,8 @@ i387_xsave_to_cache (struct regcache *regcache, const void *buf) /* See i387-fp.h. */ -void -i387_set_xsave_mask (uint64_t xcr0, int len) +std::pair<uint64_t *, x86_xsave_layout *> +i387_get_xsave_storage () { - x86_xcr0 = xcr0; - xsave_layout = x86_fetch_xsave_layout (xcr0, len); + return { &x86_xcr0, &xsave_layout }; } diff --git a/gdbserver/i387-fp.h b/gdbserver/i387-fp.h index 450466e..4ee21da 100644 --- a/gdbserver/i387-fp.h +++ b/gdbserver/i387-fp.h @@ -19,6 +19,8 @@ #ifndef GDBSERVER_I387_FP_H #define GDBSERVER_I387_FP_H +struct x86_xsave_layout; + void i387_cache_to_fsave (struct regcache *regcache, void *buf); void i387_fsave_to_cache (struct regcache *regcache, const void *buf); @@ -30,6 +32,6 @@ void i387_xsave_to_cache (struct regcache *regcache, const void *buf); /* Set the XSAVE mask and fetch the XSAVE layout via CPUID. */ -void i387_set_xsave_mask (uint64_t xcr0, int len); +std::pair<uint64_t *, x86_xsave_layout *> i387_get_xsave_storage (); #endif /* GDBSERVER_I387_FP_H */ diff --git a/gdbserver/linux-amd64-ipa.cc b/gdbserver/linux-amd64-ipa.cc index a634675..df5e6ac 100644 --- a/gdbserver/linux-amd64-ipa.cc +++ b/gdbserver/linux-amd64-ipa.cc @@ -22,6 +22,7 @@ #include "tracepoint.h" #include "linux-x86-tdesc.h" #include "gdbsupport/x86-xstate.h" +#include "arch/amd64-linux-tdesc.h" /* fast tracepoints collect registers. */ diff --git a/gdbserver/linux-i386-ipa.cc b/gdbserver/linux-i386-ipa.cc index 8f14e09..aa346fc 100644 --- a/gdbserver/linux-i386-ipa.cc +++ b/gdbserver/linux-i386-ipa.cc @@ -22,6 +22,7 @@ #include "tracepoint.h" #include "linux-x86-tdesc.h" #include "gdbsupport/x86-xstate.h" +#include "arch/i386-linux-tdesc.h" /* GDB register numbers. */ diff --git a/gdbserver/linux-x86-low.cc b/gdbserver/linux-x86-low.cc index 2d99a82..efb6797 100644 --- a/gdbserver/linux-x86-low.cc +++ b/gdbserver/linux-x86-low.cc @@ -29,10 +29,13 @@ #ifdef __x86_64__ #include "nat/amd64-linux-siginfo.h" +#include "arch/amd64-linux-tdesc.h" #else #include "nat/i386-linux.h" #endif +#include "arch/i386-linux-tdesc.h" + #include "gdb_proc_service.h" /* Don't include elf/common.h if linux/elf.h got included by gdb_proc_service.h. */ @@ -48,6 +51,7 @@ #include "nat/x86-linux.h" #include "nat/x86-linux-dregs.h" #include "linux-x86-tdesc.h" +#include "nat/x86-linux-tdesc.h" #ifdef __x86_64__ static target_desc_up tdesc_amd64_linux_no_xml; @@ -836,29 +840,9 @@ static int use_xml; /* Get Linux/x86 target description from running target. */ static const struct target_desc * -x86_linux_read_description (void) +x86_linux_read_description () { - unsigned int machine; - int is_elf64; - int xcr0_features; - int tid; - static uint64_t xcr0; - static int xsave_len; - struct regset_info *regset; - - tid = lwpid_of (current_thread); - - is_elf64 = linux_pid_exe_is_elf_64_file (tid, &machine); - - if (sizeof (void *) == 4) - { - if (is_elf64 > 0) - error (_("Can't debug 64-bit process with 32-bit GDBserver")); -#ifndef __x86_64__ - else if (machine == EM_X86_64) - error (_("Can't debug x86-64 process with 32-bit GDBserver")); -#endif - } + int tid = lwpid_of (current_thread); /* If we are not allowed to send an XML target description then we need to use the hard-wired target descriptions. This corresponds to GDB's @@ -868,103 +852,55 @@ x86_linux_read_description (void) generate some alternative target descriptions. */ if (!use_xml) { + x86_linux_arch_size arch_size = x86_linux_ptrace_get_arch_size (tid); + bool is_64bit = arch_size.is_64bit (); + bool is_x32 = arch_size.is_x32 (); + + if (sizeof (void *) == 4 && is_64bit && !is_x32) + error (_("Can't debug 64-bit process with 32-bit GDBserver")); + #ifdef __x86_64__ - if (machine == EM_X86_64) + if (is_64bit && !is_x32) return tdesc_amd64_linux_no_xml.get (); else #endif return tdesc_i386_linux_no_xml.get (); } -#if !defined __x86_64__ && defined HAVE_PTRACE_GETFPXREGS - if (machine == EM_386 && have_ptrace_getfpxregs == TRIBOOL_UNKNOWN) - { - elf_fpxregset_t fpxregs; - - if (ptrace (PTRACE_GETFPXREGS, tid, 0, (long) &fpxregs) < 0) - { - have_ptrace_getfpxregs = TRIBOOL_FALSE; - have_ptrace_getregset = TRIBOOL_FALSE; - return i386_linux_read_description (X86_XSTATE_X87); - } - else - have_ptrace_getfpxregs = TRIBOOL_TRUE; - } -#endif - - if (have_ptrace_getregset == TRIBOOL_UNKNOWN) - { - uint64_t xstateregs[(X86_XSTATE_SSE_SIZE / sizeof (uint64_t))]; - struct iovec iov; - - iov.iov_base = xstateregs; - iov.iov_len = sizeof (xstateregs); - - /* Check if PTRACE_GETREGSET works. */ - if (ptrace (PTRACE_GETREGSET, tid, - (unsigned int) NT_X86_XSTATE, (long) &iov) < 0) - have_ptrace_getregset = TRIBOOL_FALSE; - else - { - have_ptrace_getregset = TRIBOOL_TRUE; - - /* Get XCR0 from XSAVE extended state. */ - xcr0 = xstateregs[(I386_LINUX_XSAVE_XCR0_OFFSET - / sizeof (uint64_t))]; - - /* No MPX on x32. */ - if (machine == EM_X86_64 && !is_elf64) - xcr0 &= ~X86_XSTATE_MPX; - - xsave_len = x86_xsave_length (); - - /* Use PTRACE_GETREGSET if it is available. */ - for (regset = x86_regsets; - regset->fill_function != NULL; regset++) - if (regset->get_request == PTRACE_GETREGSET) - regset->size = xsave_len; - else if (regset->type != GENERAL_REGS) - regset->size = 0; - } - } + /* If have_ptrace_getregset is changed to true by calling + x86_linux_tdesc_for_tid then we will perform some additional + initialisation. */ + bool have_ptrace_getregset_was_unknown + = have_ptrace_getregset == TRIBOOL_UNKNOWN; - /* Check the native XCR0 only if PTRACE_GETREGSET is available. */ - xcr0_features = (have_ptrace_getregset == TRIBOOL_TRUE - && (xcr0 & X86_XSTATE_ALL_MASK)); + /* Get pointers to where we should store the xcr0 and xsave_layout + values. These will be filled in by x86_linux_tdesc_for_tid the first + time that the function is called. Subsequent calls will not modify + the stored values. */ + std::pair<uint64_t *, x86_xsave_layout *> storage + = i387_get_xsave_storage (); - if (xcr0_features) - i387_set_xsave_mask (xcr0, xsave_len); + const target_desc *tdesc + = x86_linux_tdesc_for_tid (tid, storage.first, storage.second); - if (machine == EM_X86_64) + if (have_ptrace_getregset_was_unknown + && have_ptrace_getregset == TRIBOOL_TRUE) { -#ifdef __x86_64__ - const target_desc *tdesc = NULL; + int xsave_len = x86_xsave_length (); - if (xcr0_features) + /* Use PTRACE_GETREGSET if it is available. */ + for (regset_info *regset = x86_regsets; + regset->fill_function != nullptr; + regset++) { - tdesc = amd64_linux_read_description (xcr0 & X86_XSTATE_ALL_MASK, - !is_elf64); + if (regset->get_request == PTRACE_GETREGSET) + regset->size = xsave_len; + else if (regset->type != GENERAL_REGS) + regset->size = 0; } - - if (tdesc == NULL) - tdesc = amd64_linux_read_description (X86_XSTATE_SSE_MASK, !is_elf64); - return tdesc; -#endif - } - else - { - const target_desc *tdesc = NULL; - - if (xcr0_features) - tdesc = i386_linux_read_description (xcr0 & X86_XSTATE_ALL_MASK); - - if (tdesc == NULL) - tdesc = i386_linux_read_description (X86_XSTATE_SSE); - - return tdesc; } - gdb_assert_not_reached ("failed to return tdesc"); + return tdesc; } /* Update all the target description of all processes; a new GDB diff --git a/gdbserver/linux-x86-tdesc.cc b/gdbserver/linux-x86-tdesc.cc index cd3b5d8..af3735a 100644 --- a/gdbserver/linux-x86-tdesc.cc +++ b/gdbserver/linux-x86-tdesc.cc @@ -23,8 +23,10 @@ #include "gdbsupport/x86-xstate.h" #ifdef __x86_64__ #include "arch/amd64.h" +#include "arch/amd64-linux-tdesc.h" #endif #include "x86-tdesc.h" +#include "arch/i386-linux-tdesc.h" /* Return the right x86_linux_tdesc index for a given XCR0. Return X86_TDESC_LAST if can't find a match. */ diff --git a/gdbserver/linux-x86-tdesc.h b/gdbserver/linux-x86-tdesc.h index f9561b1..576aaf5 100644 --- a/gdbserver/linux-x86-tdesc.h +++ b/gdbserver/linux-x86-tdesc.h @@ -46,11 +46,4 @@ int amd64_get_ipa_tdesc_idx (const struct target_desc *tdesc); const struct target_desc *i386_get_ipa_tdesc (int idx); -#ifdef __x86_64__ -const struct target_desc *amd64_linux_read_description (uint64_t xcr0, - bool is_x32); -#endif - -const struct target_desc *i386_linux_read_description (uint64_t xcr0); - #endif /* GDBSERVER_LINUX_X86_TDESC_H */ |