]> git.ipfire.org Git - thirdparty/binutils-gdb.git/commitdiff
Improve Morello feature detection
authorLuis Machado <luis.machado@arm.com>
Thu, 28 Jul 2022 01:09:04 +0000 (02:09 +0100)
committerJohn Baldwin <jhb@FreeBSD.org>
Thu, 1 Sep 2022 23:23:35 +0000 (16:23 -0700)
Given HWCAP2_MORELLO changed for Linux Kernel 5.18, this breaks Morello GDB's
heuristic for detecting the Morello feature.

When possible, switch to detecting the Morello feature through the availability
of the NT_ARM_MORELLO register set (which means PTRACE_PEEKCAP and
PTRACE_POKECAP are also available).  For corefiles, switch to using the presence
of the Morello register set section.

For extended-remote mode, check for the two possible values of HWCAP2_MORELLO.

gdb/aarch64-linux-nat.c
gdb/aarch64-linux-tdep.c
gdb/arch/aarch64-cap-linux.h
gdb/nat/aarch64-cap-linux.c
gdb/nat/aarch64-cap-linux.h
gdb/nat/linux-ptrace.c
gdb/nat/linux-ptrace.h
gdbserver/linux-aarch64-low.cc

index 386bd250443ed711639d310ba1898267a063aa1c..0be1cbfb6fcadf13a88cdddf0305ec437130016f 100644 (file)
@@ -829,7 +829,8 @@ aarch64_linux_nat_target::read_description ()
   features.pauth = hwcap & AARCH64_HWCAP_PACA;
   features.mte = hwcap2 & HWCAP2_MTE;
   features.tls = true;
-  features.capacity = hwcap2 & HWCAP2_MORELLO;
+  /* We cannot use HWCAP2_MORELLO to check for Morello support.  */
+  features.capability = aarch64_supports_morello (tid);
 
   return aarch64_read_description (features);
 }
index 83be5d52a6a1ca4e79e0129f688e04c80e61cba3..ea28ec044a911bb2928df8741311ddaebdaf2163 100644 (file)
@@ -897,7 +897,10 @@ aarch64_linux_core_read_description (struct gdbarch *gdbarch,
   features.pauth = hwcap & AARCH64_HWCAP_PACA;
   features.mte = hwcap2 & HWCAP2_MTE;
   features.tls = tls != nullptr;
-  features.capability = hwcap2 & HWCAP2_MORELLO;
+  /* We cannot use HWCAP2_MORELLO to check for Morello support.  Check if
+     we have a NT_ARM_MORELLO register set dump instead.  */
+  features.capability =
+    (bfd_get_section_by_name (abfd, ".reg-aarch-morello") != nullptr);
 
   return aarch64_read_description (features);
 }
index 7a9df0bffbafcb081d45eb1bc7fcf03f04c2bae4..d461f520cd641b2861493dfcdf727911d3181de2 100644 (file)
 #ifndef ARCH_AARCH64_CAP_LINUX_H
 #define ARCH_AARCH64_CAP_LINUX_H
 
-/* Morello HWCAP bit.  */
-#define HWCAP2_MORELLO (1 << 19)
+#include "gdbsupport/common-defs.h"
+#include "gdbsupport/byte-vector.h"
+
+/* The HWCAP values are not being used to identify Morello anymore, but are
+   kept here for reference in case someone has a need for them.  */
+/* Morello HWCAP bit V1, before Linux Kernel 5.18.  */
+#define HWCAP2_MORELLO_V1 (1 << 19)
+/* Morello HWCAP bit V2, after Linux Kernel 5.18.  */
+#define HWCAP2_MORELLO_V2 (1UL << 31)
 
 /* Size of the Capability register set.  */
 #define AARCH64_LINUX_CREGS_SIZE ((39 * 16) + (2 * 8))
index 62a4dcdff723702830c09521e229c38bef54022e..cff76de909a8fb365cfeeddd77065f13a459dc0d 100644 (file)
@@ -18,6 +18,8 @@
 #include "gdbsupport/common-defs.h"
 #include "gdb_ptrace.h"
 #include "aarch64-cap-linux.h"
+#include <sys/uio.h>
+#include "elf/common.h"
 
 /* Helper function to display various possible errors when reading
    Morello capabilities from memory.  */
@@ -98,3 +100,22 @@ aarch64_linux_write_capability (int tid, CORE_ADDR address,
 
   return true;
 }
+
+/* See aach64-cap-linux.h */
+
+bool
+aarch64_supports_morello (int tid)
+{
+  struct user_morello_state cregset;
+  struct iovec iovec;
+  iovec.iov_base = &cregset;
+  iovec.iov_len = sizeof (cregset);
+
+  /* Attempt to fetch NT_ARM_MORELLO.  If it is supported, that means Morello
+     features are supported and that PTRACE_PEEKCAP and PTRACE_POKECAP are
+     also supported.  */
+  if (ptrace (PTRACE_GETREGSET, tid, NT_ARM_MORELLO, &iovec) < 0)
+    return false;
+
+  return true;
+}
index ff38bccaf6e01148d16e49f15cfaaaa329e64c8a..8adfb9bfb39b09d32f42ee4561c1dc9e6458695d 100644 (file)
@@ -72,4 +72,14 @@ extern bool aarch64_linux_read_capability (int tid, CORE_ADDR address,
 
 extern bool aarch64_linux_write_capability (int tid, CORE_ADDR address,
                                            const user_cap &cap);
+
+/* Return true if the target supports Morello features (NT_ARM_MORELLO register
+   set, PTRACE_PEEKCAP and PTRACE_POKECAP).  If it does, it means we are
+   dealing with a Morello Linux Kernel.  This is needed because we can't
+   rely on the HWCAP2_MORELLO value anymore, given it has changed.
+
+   Return false otherwise.  */
+
+extern bool aarch64_supports_morello (int tid);
+
 #endif /* NAT_AARCH64_CAP_LINUX_H */
index 5b3086e76a6ce34efb316bbe9a6e357e01301bfa..e1601a3e03466f424bf36f96fb35285c172a537a 100644 (file)
@@ -81,8 +81,8 @@ EXTERN_C void linux_ptrace_test_ret_to_nx_instr (void);
 
 /* Kill CHILD.  WHO is used to report warnings.  */
 
-static void
-kill_child (pid_t child, const char *who)
+void
+linux_kill_child (pid_t child, const char *who)
 {
   pid_t got_pid;
   int kill_status;
@@ -202,7 +202,7 @@ linux_ptrace_test_ret_to_nx (void)
     {
       warning (_("linux_ptrace_test_ret_to_nx: status %d is not WIFSTOPPED!"),
               status);
-      kill_child (child, "linux_ptrace_test_ret_to_nx");
+      linux_kill_child (child, "linux_ptrace_test_ret_to_nx");
       return;
     }
 
@@ -212,7 +212,7 @@ linux_ptrace_test_ret_to_nx (void)
       warning (_("linux_ptrace_test_ret_to_nx: "
                 "WSTOPSIG %d is neither SIGTRAP nor SIGSEGV!"),
               (int) WSTOPSIG (status));
-      kill_child (child, "linux_ptrace_test_ret_to_nx");
+      linux_kill_child (child, "linux_ptrace_test_ret_to_nx");
       return;
     }
 
@@ -230,7 +230,7 @@ linux_ptrace_test_ret_to_nx (void)
 # error "!__i386__ && !__x86_64__"
 #endif
 
-  kill_child (child, "linux_ptrace_test_ret_to_nx");
+  linux_kill_child (child, "linux_ptrace_test_ret_to_nx");
 
   /* + 1 is there as x86* stops after the 'int3' instruction.  */
   if (WSTOPSIG (status) == SIGTRAP && pc == return_address + 1)
@@ -317,10 +317,10 @@ linux_child_function (void *child_stack)
 
 static void linux_test_for_exitkill (int child_pid);
 
-/* Determine ptrace features available on this target.  */
+/* Create a child for testing ptrace features and return its pid.  */
 
-void
-linux_check_ptrace_features (void)
+int
+linux_create_child_for_ptrace_testing ()
 {
   int child_pid, ret, status;
 
@@ -350,10 +350,21 @@ linux_check_ptrace_features (void)
     error (_("linux_check_ptrace_features: waitpid: unexpected status %d."),
           status);
 
+  return child_pid;
+}
+
+
+/* Determine ptrace features available on this target.  */
+
+void
+linux_check_ptrace_features (void)
+{
+  int child_pid = linux_create_child_for_ptrace_testing ();
+
   linux_test_for_exitkill (child_pid);
 
   /* Kill child_pid.  */
-  kill_child (child_pid, "linux_check_ptrace_features");
+  linux_kill_child (child_pid, "linux_check_ptrace_features");
 }
 
 /* Determine if PTRACE_O_EXITKILL can be used.  */
index 4694046e1e8da55cb1eecb7552c05f4bff44031f..e9b3290e65c12e32a4f92f2ec87759cc8596b2e6 100644 (file)
@@ -190,5 +190,6 @@ extern void linux_disable_event_reporting (pid_t pid);
 extern int linux_ptrace_get_extended_event (int wstat);
 extern int linux_is_extended_waitstatus (int wstat);
 extern int linux_wstatus_maybe_breakpoint (int wstat);
-
+extern void linux_kill_child (pid_t child, const char *who);
+extern int linux_create_child_for_ptrace_testing ();
 #endif /* NAT_LINUX_PTRACE_H */
index 8013edf0459b3687435a11ad8ca28ca509786c6f..9915fe5cc8ad2b932a550f2dd83f4c0788f50780 100644 (file)
@@ -946,8 +946,8 @@ aarch64_target::low_arch_setup ()
       /* A-profile MTE is 64-bit only.  */
       features.mte = linux_get_hwcap2 () & HWCAP2_MTE;
       features.tls = true;
-      /* Morello is 64-bit only.  */
-      features.capability = linux_get_hwcap2 () & HWCAP2_MORELLO;
+      /* We cannot use HWCAP2_MORELLO to check for Morello support.  */
+      features.capability = aarch64_supports_morello (tid);
 
       current_process ()->tdesc = aarch64_linux_read_description (features);
 
@@ -3542,14 +3542,24 @@ aarch64_target::store_memtags (CORE_ADDR address, size_t len,
   return false;
 }
 
+static bool
+aarch64_supports_morello_features ()
+{
+  /* Spawn a child for testing.  */
+  int child_pid = linux_create_child_for_ptrace_testing ();
+  bool ret = aarch64_supports_morello (child_pid);
+  /* Kill child_pid.  */
+  linux_kill_child (child_pid, "aarch64_check_ptrace_features");
+  return ret;
+}
+
 /* Implementation of targets ops method "supports_qxfer_capability.  */
 
 bool
 aarch64_target::supports_qxfer_capability ()
 {
-  unsigned long hwcap2 = linux_get_hwcap2 ();
-
-  return (hwcap2 & HWCAP2_MORELLO) != 0;
+  /* Do a live ptrace feature check instead of using HWCAP bits.  */
+  return aarch64_supports_morello_features ();
 }
 
 /* Implementation of targets ops method "qxfer_capability.  */