aboutsummaryrefslogtreecommitdiff
path: root/gdb
diff options
context:
space:
mode:
authorAlan Hayward <alan.hayward@arm.com>2019-04-15 12:29:40 +0100
committerAlan Hayward <alan.hayward@arm.com>2019-04-15 15:12:43 +0100
commit4da037ef9dba6c17089250d228efdbe6f7d830c9 (patch)
treed255e2f1b678fe4c1bef688cac9d5c4e1d6a6307 /gdb
parentccb8d7e8194b848a6c4aa43272540eec0f4f21f2 (diff)
downloadgdb-4da037ef9dba6c17089250d228efdbe6f7d830c9.zip
gdb-4da037ef9dba6c17089250d228efdbe6f7d830c9.tar.gz
gdb-4da037ef9dba6c17089250d228efdbe6f7d830c9.tar.bz2
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.
Diffstat (limited to 'gdb')
-rw-r--r--gdb/ChangeLog7
-rw-r--r--gdb/aarch64-linux-nat.c31
-rw-r--r--gdb/aarch64-tdep.c26
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;