From 4f3681cc336158fbbbf3333a38eb9f324fdb9bf5 Mon Sep 17 00:00:00 2001 From: Thiago Jung Bauermann Date: Thu, 18 Aug 2022 13:42:55 +0100 Subject: Fix thread's gdbarch when SVE vector length changes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When the inferior program changes the SVE length, GDB can stop tracking some registers as it obtains the new gdbarch that corresponds to the updated length: Breakpoint 1, do_sve_ioctl_test () at sve-ioctls.c:44 44 res = prctl(PR_SVE_SET_VL, i, 0, 0, 0, 0); (gdb) print i $2 = 32 (gdb) info registers ⋮ [ snip registers x0 to x30 ] ⋮ sp 0xffffffffeff0 0xffffffffeff0 pc 0xaaaaaaaaa8ac 0xaaaaaaaaa8ac cpsr 0x60000000 [ EL=0 BTYPE=0 C Z ] fpsr 0x0 0 fpcr 0x0 0 vg 0x8 8 tpidr 0xfffff7fcb320 0xfffff7fcb320 (gdb) next 45 if (res < 0) { (gdb) info registers ⋮ [ snip registers x0 to x30 ] ⋮ sp 0xffffffffeff0 0xffffffffeff0 pc 0xaaaaaaaaa8cc 0xaaaaaaaaa8cc cpsr 0x200000 [ EL=0 BTYPE=0 SS ] fpsr 0x0 0 fpcr 0x0 0 vg 0x4 4 (gdb) Notice that register tpidr disappeared when vg (which holds the vector length) changed from 8 to 4. The tpidr register is provided by the org.gnu.gdb.aarch64.tls feature. This happens because the code that searches for a new gdbarch to match the new vector length in aarch64_linux_nat_target::thread_architecture doesn't take into account the features present in the target description associated with the previous gdbarch. This patch makes it do that. Since the id member of struct gdbarch_info is now unused, it's removed. --- gdb/aarch64-tdep.c | 41 ++++++++++++++++++++++++----------------- 1 file changed, 24 insertions(+), 17 deletions(-) (limited to 'gdb/aarch64-tdep.c') diff --git a/gdb/aarch64-tdep.c b/gdb/aarch64-tdep.c index f747ebd..ba9b2d8 100644 --- a/gdb/aarch64-tdep.c +++ b/gdb/aarch64-tdep.c @@ -3392,6 +3392,27 @@ aarch64_get_tdesc_vq (const struct target_desc *tdesc) return sve_vq_from_vl (vl); } +/* Get the AArch64 features present in the given target description. */ + +aarch64_features +aarch64_features_from_target_desc (const struct target_desc *tdesc) +{ + aarch64_features features; + + if (tdesc == nullptr) + return features; + + features.vq = aarch64_get_tdesc_vq (tdesc); + features.pauth + = (tdesc_find_feature (tdesc, "org.gnu.gdb.aarch64.pauth") != nullptr); + features.mte + = (tdesc_find_feature (tdesc, "org.gnu.gdb.aarch64.mte") != nullptr); + features.tls + = (tdesc_find_feature (tdesc, "org.gnu.gdb.aarch64.tls") != nullptr); + + return features; +} + /* Implement the "cannot_store_register" gdbarch method. */ static int @@ -3442,17 +3463,7 @@ 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, ra_sign_state_offset = -1; int first_mte_regnum = -1, tls_regnum = -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); + uint64_t vq = aarch64_get_tdesc_vq (info.target_desc); if (vq > AARCH64_MAX_SVE_VQ) internal_error (__FILE__, __LINE__, _("VQ out of bounds: %s (max %d)"), @@ -3472,12 +3483,8 @@ aarch64_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) /* 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) || vq != aarch64_get_tdesc_vq (tdesc)) - { - aarch64_features features; - features.vq = vq; - tdesc = aarch64_read_description (features); - } + if (!tdesc_has_registers (tdesc)) + tdesc = aarch64_read_description ({}); gdb_assert (tdesc); feature_core = tdesc_find_feature (tdesc,"org.gnu.gdb.aarch64.core"); -- cgit v1.1