This is the mail archive of the gdb-cvs@sourceware.org mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[binutils-gdb] AArch64 SVE: Check for vector length change when getting gdbarch


https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=4da037ef9dba6c17089250d228efdbe6f7d830c9

commit 4da037ef9dba6c17089250d228efdbe6f7d830c9
Author: Alan Hayward <alan.hayward@arm.com>
Date:   Mon Apr 15 12:29:40 2019 +0100

    AArch64 SVE: Check for vector length change when getting gdbarch
    
    Override the thread_architecture method, similar to SPU.  If the vector
    length has changed, then find the arch using info, making sure the vector
    length is passed down to the init routine.
    
    In the init routine, ensure the arch has the correct vector length.
    
    Example output. Program is stopped in thread 2, just before it calls prctl
    to change the vector length
    
    (gdb) info threads
      Id   Target Id                                     Frame
      1    Thread 0xffffbf6f4000 (LWP 3188) "sve_change" 0x0000ffffbf6ae130 in pthread_join ()
    * 2    Thread 0xffffbf55e200 (LWP 3189) "sve_change" thread1 (arg=0xfeedface) at sve_change_size.c:28
    (gdb) print $vg
    $1 = 8
    (gdb) print $z0.s.u
    $2 = {623191333, 623191333, 623191333, 623191333, 0 <repeats 12 times>}
    (gdb) n
    29	  int ret = prctl(PR_SVE_SET_VL, vl/2);
    (gdb) n
    30	  printf ("Changed: ret\n", ret);
    (gdb) print $vg
    $4 = 4
    (gdb) print $z0.s.u
    $5 = {623191333, 623191333, 623191333, 623191333, 0, 0, 0, 0}
    (gdb) thr 1
    [Switching to thread 1 (Thread 0xffffbf6f4000 (LWP 3181))]
    (gdb) print $vg
    $6 = 8
    (gdb) print $z0.s.u
    $7 = {623191333, 623191333, 623191333, 623191333, 0 <repeats 12 times>}
    
    gdb/ChangeLog:
    
    	* aarch64-linux-nat.c
    	(aarch64_linux_nat_target::thread_architecture): Add override.
    	* aarch64-tdep.c (aarch64_gdbarch_init): Ensure different tdesc for
    	each VQ.

Diff:
---
 gdb/ChangeLog           |  7 +++++++
 gdb/aarch64-linux-nat.c | 31 +++++++++++++++++++++++++++++++
 gdb/aarch64-tdep.c      | 26 +++++++++++++++++++++-----
 3 files changed, 59 insertions(+), 5 deletions(-)

diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index 02e8fea..b3155ad 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,5 +1,12 @@
 2019-04-15  Alan Hayward  <alan.hayward@arm.com>
 
+	* aarch64-linux-nat.c
+	(aarch64_linux_nat_target::thread_architecture): Add override.
+	* aarch64-tdep.c (aarch64_gdbarch_init): Ensure different tdesc for
+	each VQ.
+
+2019-04-15  Alan Hayward  <alan.hayward@arm.com>
+
 	* aarch64-tdep.c (aarch64_gdbarch_init): Move gdbarch lookup.
 
 2019-04-13  Andrew Burgess  <andrew.burgess@embecosm.com>
diff --git a/gdb/aarch64-linux-nat.c b/gdb/aarch64-linux-nat.c
index 6d43eb7..c5070c8 100644
--- a/gdb/aarch64-linux-nat.c
+++ b/gdb/aarch64-linux-nat.c
@@ -46,6 +46,7 @@
 
 /* Defines ps_err_e, struct ps_prochandle.  */
 #include "gdb_proc_service.h"
+#include "arch-utils.h"
 
 #ifndef TRAP_HWBKPT
 #define TRAP_HWBKPT 0x0004
@@ -95,6 +96,8 @@ public:
   /* Add our siginfo layout converter.  */
   bool low_siginfo_fixup (siginfo_t *ptrace, gdb_byte *inf, int direction)
     override;
+
+  struct gdbarch *thread_architecture (ptid_t) override;
 };
 
 static aarch64_linux_nat_target the_aarch64_linux_nat_target;
@@ -939,6 +942,34 @@ aarch64_linux_nat_target::can_do_single_step ()
   return 1;
 }
 
+/* Implement the "thread_architecture" target_ops method.  */
+
+struct gdbarch *
+aarch64_linux_nat_target::thread_architecture (ptid_t ptid)
+{
+  /* Return the gdbarch for the current thread.  If the vector length has
+     changed since the last time this was called, then do a further lookup.  */
+
+  uint64_t vq = aarch64_sve_get_vq (ptid.lwp ());
+
+  /* Find the current gdbarch the same way as process_stratum_target.  Only
+     return it if the current vector length matches the one in the tdep.  */
+  inferior *inf = find_inferior_ptid (ptid);
+  gdb_assert (inf != NULL);
+  if (vq == gdbarch_tdep (inf->gdbarch)->vq)
+    return inf->gdbarch;
+
+  /* We reach here if the vector length for the thread is different from its
+     value at process start.  Lookup gdbarch via info (potentially creating a
+     new one), stashing the vector length inside id.  Use -1 for when SVE
+     unavailable, to distinguish from an unset value of 0.  */
+  struct gdbarch_info info;
+  gdbarch_info_init (&info);
+  info.bfd_arch_info = bfd_lookup_arch (bfd_arch_spu, bfd_mach_spu);
+  info.id = (int *) (vq == 0 ? -1 : vq);
+  return gdbarch_find_by_info (info);
+}
+
 /* Define AArch64 maintenance commands.  */
 
 static void
diff --git a/gdb/aarch64-tdep.c b/gdb/aarch64-tdep.c
index ea3f5ec..cb185ee 100644
--- a/gdb/aarch64-tdep.c
+++ b/gdb/aarch64-tdep.c
@@ -3198,20 +3198,36 @@ aarch64_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
   int i, num_regs = 0, num_pseudo_regs = 0;
   int first_pauth_regnum = -1, pauth_ra_state_offset = -1;
 
+  /* Use the vector length passed via the target info.  Here -1 is used for no
+     SVE, and 0 is unset.  If unset then use the vector length from the existing
+     tdesc.  */
+  uint64_t vq = 0;
+  if (info.id == (int *) -1)
+    vq = 0;
+  else if (info.id != 0)
+    vq = (uint64_t) info.id;
+  else
+    vq = aarch64_get_tdesc_vq (info.target_desc);
+
+  if (vq > AARCH64_MAX_SVE_VQ)
+    internal_error (__FILE__, __LINE__, _("VQ out of bounds: %ld (max %d)"),
+		    vq, AARCH64_MAX_SVE_VQ);
+
   /* If there is already a candidate, use it.  */
   for (gdbarch_list *best_arch = gdbarch_list_lookup_by_info (arches, &info);
        best_arch != nullptr;
        best_arch = gdbarch_list_lookup_by_info (best_arch->next, &info))
     {
       struct gdbarch_tdep *tdep = gdbarch_tdep (best_arch->gdbarch);
-      if (tdep)
+      if (tdep && tdep->vq == vq)
 	return best_arch->gdbarch;
     }
 
-  /* Ensure we always have a target description.  */
+  /* Ensure we always have a target descriptor, and that it is for the given VQ
+     value.  */
   const struct target_desc *tdesc = info.target_desc;
-  if (!tdesc_has_registers (tdesc))
-    tdesc = aarch64_read_description (0, false);
+  if (!tdesc_has_registers (tdesc) || vq != aarch64_get_tdesc_vq (tdesc))
+    tdesc = aarch64_read_description (vq, false);
   gdb_assert (tdesc);
 
   feature_core = tdesc_find_feature (tdesc,"org.gnu.gdb.aarch64.core");
@@ -3304,7 +3320,7 @@ aarch64_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
   tdep->lowest_pc = 0x20;
   tdep->jb_pc = -1;		/* Longjump support not enabled by default.  */
   tdep->jb_elt_size = 8;
-  tdep->vq = aarch64_get_tdesc_vq (tdesc);
+  tdep->vq = vq;
   tdep->pauth_reg_base = first_pauth_regnum;
   tdep->pauth_ra_state_regnum = (feature_pauth == NULL) ? -1
 				: pauth_ra_state_offset + num_regs;


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]