aboutsummaryrefslogtreecommitdiff
path: root/gdbserver
diff options
context:
space:
mode:
Diffstat (limited to 'gdbserver')
-rw-r--r--gdbserver/configure.srv2
-rw-r--r--gdbserver/linux-amd64-ipa.cc1
-rw-r--r--gdbserver/linux-i386-ipa.cc1
-rw-r--r--gdbserver/linux-x86-low.cc148
-rw-r--r--gdbserver/linux-x86-tdesc.cc1
-rw-r--r--gdbserver/linux-x86-tdesc.h7
6 files changed, 111 insertions, 49 deletions
diff --git a/gdbserver/configure.srv b/gdbserver/configure.srv
index 7a2702d..9e861a7 100644
--- a/gdbserver/configure.srv
+++ b/gdbserver/configure.srv
@@ -109,7 +109,6 @@ 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_linux_usrregs=yes
srv_linux_regsets=yes
srv_linux_thread_db=yes
@@ -372,7 +371,6 @@ 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/linux-amd64-ipa.cc b/gdbserver/linux-amd64-ipa.cc
index f97b0d6..54e4c98 100644
--- a/gdbserver/linux-amd64-ipa.cc
+++ b/gdbserver/linux-amd64-ipa.cc
@@ -23,7 +23,6 @@
#include "tracepoint.h"
#include "linux-x86-tdesc.h"
#include "gdbsupport/x86-xstate.h"
-#include "nat/x86-linux-tdesc.h"
/* Defined in auto-generated file amd64-linux.c. */
void init_registers_amd64_linux (void);
diff --git a/gdbserver/linux-i386-ipa.cc b/gdbserver/linux-i386-ipa.cc
index 459b805..2e4646f 100644
--- a/gdbserver/linux-i386-ipa.cc
+++ b/gdbserver/linux-i386-ipa.cc
@@ -23,7 +23,6 @@
#include "tracepoint.h"
#include "linux-x86-tdesc.h"
#include "gdbsupport/x86-xstate.h"
-#include "nat/x86-linux-tdesc.h"
/* GDB register numbers. */
diff --git a/gdbserver/linux-x86-low.cc b/gdbserver/linux-x86-low.cc
index 9bf369f..30d876e 100644
--- a/gdbserver/linux-x86-low.cc
+++ b/gdbserver/linux-x86-low.cc
@@ -48,7 +48,6 @@
#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;
@@ -845,20 +844,32 @@ int have_ptrace_getfpxregs =
#endif
;
-/* Cached xcr0 value. This is initialised the first time
- x86_linux_read_description is called. */
-
-static uint64_t xcr0_storage;
-
/* Get Linux/x86 target description from running target. */
static const struct target_desc *
x86_linux_read_description (void)
{
- int tid = lwpid_of (current_thread);
+ 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);
- const char *error_msg
- = _("Can't debug 64-bit process with 32-bit GDBserver");
+ 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
+ }
/* 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,54 +879,103 @@ 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 ("%s", error_msg);
-
#ifdef __x86_64__
- if (is_64bit && !is_x32)
+ if (machine == EM_X86_64)
return tdesc_amd64_linux_no_xml.get ();
else
#endif
return tdesc_i386_linux_no_xml.get ();
}
- /* Callback that is triggered the first time x86_linux_tdesc_for_tid
- reads the xcr0 register. Setup other bits of state */
- auto cb = [] (uint64_t xcr0)
- {
- i387_set_xsave_mask (xcr0, x86_xsave_length ());
- };
+#if !defined __x86_64__ && defined HAVE_PTRACE_GETFPXREGS
+ if (machine == EM_386 && have_ptrace_getfpxregs == -1)
+ {
+ elf_fpxregset_t fpxregs;
- /* 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_is_unknown
- = have_ptrace_getregset == TRIBOOL_UNKNOWN;
+ if (ptrace (PTRACE_GETFPXREGS, tid, 0, (long) &fpxregs) < 0)
+ {
+ have_ptrace_getfpxregs = 0;
+ have_ptrace_getregset = TRIBOOL_FALSE;
+ return i386_linux_read_description (X86_XSTATE_X87);
+ }
+ else
+ have_ptrace_getfpxregs = 1;
+ }
+#endif
- const target_desc *tdesc
- = x86_linux_tdesc_for_tid (tid, &have_ptrace_getregset, cb, error_msg,
- &xcr0_storage);
+ if (have_ptrace_getregset == TRIBOOL_UNKNOWN)
+ {
+ uint64_t xstateregs[(X86_XSTATE_SSE_SIZE / sizeof (uint64_t))];
+ struct iovec iov;
- if (have_ptrace_getregset_is_unknown
- && have_ptrace_getregset == TRIBOOL_TRUE)
+ 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;
+ }
+ }
+
+ /* Check the native XCR0 only if PTRACE_GETREGSET is available. */
+ xcr0_features = (have_ptrace_getregset == TRIBOOL_TRUE
+ && (xcr0 & X86_XSTATE_ALL_MASK));
+
+ if (xcr0_features)
+ i387_set_xsave_mask (xcr0, xsave_len);
+
+ if (machine == EM_X86_64)
+ {
+#ifdef __x86_64__
+ const target_desc *tdesc = NULL;
+
+ if (xcr0_features)
+ {
+ tdesc = amd64_linux_read_description (xcr0 & X86_XSTATE_ALL_MASK,
+ !is_elf64);
+ }
+
+ if (tdesc == NULL)
+ tdesc = amd64_linux_read_description (X86_XSTATE_SSE_MASK, !is_elf64);
+ return tdesc;
+#endif
+ }
+ else
{
- int xsave_len = x86_xsave_length ();
-
- /* Use PTRACE_GETREGSET if it is available. */
- for (regset_info *regset = x86_regsets;
- regset->fill_function != nullptr;
- regset++)
- if (regset->get_request == PTRACE_GETREGSET)
- regset->size = xsave_len;
- else if (regset->type != GENERAL_REGS)
- regset->size = 0;
+ 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;
}
- return tdesc;
+ gdb_assert_not_reached ("failed to 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 9fd64d8..626207f 100644
--- a/gdbserver/linux-x86-tdesc.cc
+++ b/gdbserver/linux-x86-tdesc.cc
@@ -26,7 +26,6 @@
#include "arch/amd64.h"
#endif
#include "x86-tdesc.h"
-#include "nat/x86-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 576aaf5..f9561b1 100644
--- a/gdbserver/linux-x86-tdesc.h
+++ b/gdbserver/linux-x86-tdesc.h
@@ -46,4 +46,11 @@ 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 */