aboutsummaryrefslogtreecommitdiff
path: root/gdbserver/linux-x86-low.cc
diff options
context:
space:
mode:
authorAndrew Burgess <aburgess@redhat.com>2024-03-26 18:52:44 +0000
committerAndrew Burgess <aburgess@redhat.com>2024-03-26 18:52:44 +0000
commit49a7660fb50cc3c68e7830eb098905d068a3ccbf (patch)
tree8471a0dcc41846551322f58510aa9aea098356c5 /gdbserver/linux-x86-low.cc
parent0991b56074af7e6b106015c67925fdcfe039f077 (diff)
downloadbinutils-49a7660fb50cc3c68e7830eb098905d068a3ccbf.zip
binutils-49a7660fb50cc3c68e7830eb098905d068a3ccbf.tar.gz
binutils-49a7660fb50cc3c68e7830eb098905d068a3ccbf.tar.bz2
Revert "gdb/gdbserver: share some code relating to target description creation"
This reverts commit cd9b374ffe372dcaf7e4c15548cf53a301d8dcdd.
Diffstat (limited to 'gdbserver/linux-x86-low.cc')
-rw-r--r--gdbserver/linux-x86-low.cc148
1 files changed, 104 insertions, 44 deletions
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