diff --git a/gdb/aarch64-linux-tdep.c b/gdb/aarch64-linux-tdep.c index 20a041c599e..4b2915b8e99 100644 --- a/gdb/aarch64-linux-tdep.c +++ b/gdb/aarch64-linux-tdep.c @@ -57,6 +57,9 @@ #include "elf/common.h" #include "elf/aarch64.h" +/* For inferior_ptid and current_inferior (). */ +#include "inferior.h" + /* Signal frame handling. +------------+ ^ @@ -1986,29 +1989,60 @@ aarch64_linux_decode_memtag_section (struct gdbarch *gdbarch, static CORE_ADDR aarch64_remove_non_address_bits (struct gdbarch *gdbarch, CORE_ADDR pointer) { - aarch64_gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); - /* By default, we assume TBI and discard the top 8 bits plus the VA range - select bit (55). */ + select bit (55). Below we try to fetch information about pointer + authentication masks in order to make non-address removal more + precise. */ CORE_ADDR mask = AARCH64_TOP_BITS_MASK; - if (tdep->has_pauth ()) + /* Check if we have an inferior first. If not, just use the default + mask. + + We use the inferior_ptid here because the pointer authentication masks + should be the same across threads of a process. Since we may not have + access to the current thread (gdb may have switched to no inferiors + momentarily), we use the inferior ptid. */ + if (inferior_ptid != null_ptid) { - /* Fetch the PAC masks. These masks are per-process, so we can just - fetch data from whatever thread we have at the moment. + /* If we do have an inferior, attempt to fetch its thread's thread_info + struct. */ + thread_info *thread + = find_thread_ptid (current_inferior ()->process_target (), + inferior_ptid); - Also, we have both a code mask and a data mask. For now they are the - same, but this may change in the future. */ - struct regcache *regs = get_current_regcache (); - CORE_ADDR cmask, dmask; + /* If the thread is running, we will not be able to fetch the mask + registers. */ + if (thread != nullptr && thread->state != THREAD_RUNNING) + { + /* Otherwise, fetch the register cache and the masks. */ + struct regcache *regs + = get_thread_regcache (current_inferior ()->process_target (), + inferior_ptid); - if (regs->cooked_read (tdep->pauth_reg_base, &dmask) != REG_VALID) - dmask = mask; + /* Use the gdbarch from the register cache to check for pointer + authentication support, as it matches the features found in + that particular thread. */ + aarch64_gdbarch_tdep *tdep + = gdbarch_tdep (regs->arch ()); - if (regs->cooked_read (tdep->pauth_reg_base + 1, &cmask) != REG_VALID) - cmask = mask; + /* Is there pointer authentication support? */ + if (tdep->has_pauth ()) + { + /* We have both a code mask and a data mask. For now they are + the same, but this may change in the future. */ + CORE_ADDR cmask, dmask; - mask |= aarch64_mask_from_pac_registers (cmask, dmask); + if (regs->cooked_read (tdep->pauth_reg_base, &dmask) + != REG_VALID) + dmask = mask; + + if (regs->cooked_read (tdep->pauth_reg_base + 1, &cmask) + != REG_VALID) + cmask = mask; + + mask |= aarch64_mask_from_pac_registers (cmask, dmask); + } + } } return aarch64_remove_top_bits (pointer, mask);