From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from simark.ca by simark.ca with LMTP id kZy4BmLQpWoiawUAWB0awg (envelope-from ) for ; Sat, 12 Sep 2026 18:21:22 -0400 Authentication-Results: simark.ca; dkim=pass (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.a=rsa-sha256 header.s=20251104 header.b=MwbM67Jj; dkim-atps=neutral Received: by simark.ca (Postfix, from userid 112) id 1106A1E167; Sat, 12 Sep 2026 18:21:22 -0400 (EDT) X-Spam-Checker-Version: SpamAssassin 4.0.1 (2024-03-25) on simark.ca X-Spam-Level: X-Spam-Status: No, score=-5.4 required=5.0 tests=ARC_SIGNED,ARC_VALID,BAYES_00, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,FREEMAIL_FROM,MAILING_LIST_MULTI, RCVD_IN_DNSWL_MED autolearn=ham autolearn_force=no version=4.0.1 Received: from vm01.sourceware.org (vm01.sourceware.org [IPv6:2620:52:6:3111::32]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange x25519 server-signature ECDSA (prime256v1) server-digest SHA256) (No client certificate requested) by simark.ca (Postfix) with ESMTPS id 163AC1E033 for ; Sat, 12 Sep 2026 18:21:21 -0400 (EDT) Received: from vm01.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 1D9AC4C900C0 for ; Sat, 12 Sep 2026 22:21:20 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 1D9AC4C900C0 Authentication-Results: sourceware.org; dkim=pass (2048-bit key, unprotected) header.d=gmail.com header.i=@gmail.com header.a=rsa-sha256 header.s=20251104 header.b=MwbM67Jj Received: from mail-wm2-x10.google.com (mail-wm2-x10.google.com [IPv6:2a00:1450:4864:31::10]) by sourceware.org (Postfix) with ESMTPS id 396E74BB8F4E for ; Sat, 12 Sep 2026 22:20:17 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 396E74BB8F4E Authentication-Results: sourceware.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=gmail.com ARC-Filter: OpenARC Filter v1.0.0 sourceware.org 396E74BB8F4E Authentication-Results: sourceware.org; arc=none smtp.remote-ip=2a00:1450:4864:31::10 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1789251617; cv=none; b=HLGNE1NBoEIqTkSIeU7DS5hQ+3q1XWs7JHB0ZYtYCECUvwmCAd+qRJtMYyL4pxzJErEhpt91hFLDscYubxWCEW52KvB7Y394DDNgJef+lJlToDvpXpGDNc4L13lj/Zo3BJ57ZzMCsLYQ7FDFqf9OJJs9oRW3JJLA75OgIqPJIwY= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1789251617; c=relaxed/simple; bh=uyDM6+oInca3P04HDglUKLg2udE1pn04JmSfEEfi5IE=; h=DKIM-Signature:From:To:Subject:Date:Message-ID:MIME-Version; b=LkTwgA2VMZTXJsCJCa9+kJMBdlW/rCACd6sgRmPHxRitQdIQXBV2+qv/HNNEMSIuzu+N2MUV6Q10qD+QjEy2HTKp/GAgi0OFvU+a5QV2cvLACySXy9LYTM4gRLVllk2vqNtSUvMliOpQCkQv3LKwKGfuiRkx+fa1HYMRkQAOtUQ= ARC-Authentication-Results: i=1; sourceware.org; dkim=pass (2048-bit key, unprotected) header.d=gmail.com header.i=@gmail.com header.a=rsa-sha256 header.s=20251104 header.b=MwbM67Jj DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 396E74BB8F4E Received: by mail-wm2-x10.google.com with SMTP id 5b1f17b1804b1-49cd38e0f79so4626825e9.3 for ; Sat, 12 Sep 2026 15:20:17 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1789251616; x=1789856416; darn=sourceware.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to:content-type; bh=6aMyS9m/S6UiWuQyxQjwACK2cfE36VoAyGfwpdqD5tw=; b=MwbM67JjGyUkHaO71Czlc0yOgtbqSx6/aRw7qePiMbZ3ye+16fU1obvNsScnKGO6Gi EvjSVzkJaENySXgXIOOn4TYlVYpY8qwmuM69C5GjstGCfQpfYLK3F4q2IsKM+8XM4NQL zqAivv0V1HcGjflozeKMgQNGda4IDO+2wP1X/gw9JHfnmqWVt3EtR0ZlC75Z8V+mS4sh Ihevtx0qN4Ise5WeF1wY3O0OJikmwK65NVKa53sU3ABa5G7SPvvOs+ghSOBldJq3GmKX /IQASbeTBlRsMigAlwG8r6K7AfXROMQEknx932paqKXKMLLSrXt/FJFX8suYfgUkPvi0 WE4A== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1789251616; x=1789856416; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to:content-type; bh=6aMyS9m/S6UiWuQyxQjwACK2cfE36VoAyGfwpdqD5tw=; b=Px/xgDh1VeRfZQaFyUwEgxDcTlCXJpv4WmuwqIhh+MeKwQtFLH9iE9jjpGfOxWWFyw rTg4IUeaLpcqWq7VeKRABWaZk0tAlfYw6LJbJ4vTumYHudwn0nSXGO1r6dfmDWTrj6vm FuUGDxlVVoSvGkUhuZ4TtkR+g7dDWYLvmTAgVnYeUOVJ4uGfbJkvFZTI6MheIYvAZrK7 +vqArKrEaMjK02NX7Ff0NKD4RUcsUoOdGWWRJ0qDflGVFjcp8koeVJEswPYZnCy/aA4e cafkLhgGSk8oRfNtBvmTk099Gy8DwlwDlRvCvOz9g0CTHXRZsli4qI+VaXMBJGHyI0Lb izVg== X-Gm-Message-State: AFuF++ld4QigeWJuwJSrkRYpjAwGV3N7qD6iNMv9GxmIXF6Mndi2bZCB E89P/Qs3p9jH65dhJ9si4SDXHsxM9EZIsyUSlcNMCrzID8AwK1YQlLPn8DgnIQ== X-Gm-Gg: AYBFou28fnAv727sddH8yqXOJis2/s+I8cAtCZyaYyZBXGkXJJlrefuuNaJ1Ie8HMuf cnm+DH1u4CCWbxjROqZfNQv0JcZp1gLtaEpSnbg8/5tp47qj86l0QsX7mD/+i7P9CBJzZUOX6Vk 9b3XyepjQuRRK3eIunr5g9AfbAiEUcT5lsRWmwY7Ud2JC+eJyf1QrL11jNmtsp4jHj66eVVok2c 3lSZwkj7B0MxpJTVfcOIl13FwpUpC+SFNYkUeqvQk/OzTbT7LAO+X9Mz4uJ0baJHYKMEBHetHnS olrtRV8aMs01bVd/Zbm3sVmCZMn4yuRKTrK0Zp9lzUrYKg6F6qHW27cPHXtfQkTfaQ9wVfpyzl5 fC1oLkOfJ710dZS5qz6dCRkzGSJv5hwG32gCXbs4fGV6X1Lw0GDGcf/1oXnBROmbWbT8hN+ufYV us+BMneOZ+s4N7J0DZYBi/ssFJNdQdC2p11ViYsI99rKlPumDtHoSzZyiasYGZEmArF3WjGqFg4 xxS X-Received: by 2002:a05:600c:4e0c:b0:49c:ed94:cdd8 with SMTP id 5b1f17b1804b1-49e6198734emr275607635e9.6.1789251616086; Sat, 12 Sep 2026 15:20:16 -0700 (PDT) Received: from jolana.. ([86.12.216.189]) by smtp.gmail.com with ESMTPSA id 5b1f17b1804b1-49e61a803c5sm112535845e9.1.2026.09.12.15.20.15 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 12 Sep 2026 15:20:15 -0700 (PDT) From: Luis Machado To: gdb-patches@sourceware.org Cc: thiago.bauermann@linaro.org Subject: [PATCH 1/2] gdb, aarch64: cache pointer authentication masks per inferior Date: Sat, 12 Sep 2026 23:20:10 +0100 Message-ID: <20260912222011.2395686-2-luis.machado.foss@gmail.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260912222011.2395686-1-luis.machado.foss@gmail.com> References: <20260912222011.2395686-1-luis.machado.foss@gmail.com> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-BeenThere: gdb-patches@sourceware.org X-Mailman-Version: 2.1.30 Precedence: list List-Id: Gdb-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: gdb-patches-bounces~public-inbox=simark.ca@sourceware.org aarch64_remove_non_address_bits recomputed the pointer authentication masks on every call by walking the current inferior's thread list, looking up its regcache, and reading the dmask/cmask registers from the target. This function is called from memory_xfer_partial for every memory transfer GDB performs, as well as from the watchpoint and breakpoint address-masking hooks, so the lookup happens far more often than the masks can possibly change. The masks are fixed for the life of a process, since they reflect the kernel's VA-size configuration at exec time, and are shared by all of a process' threads. Cache the computed mask per inferior (one slot each for the low and high VA ranges) instead of recomputing it on every call, only populating the cache when a thread is actually stopped so a transient "thread running" state never gets cached as a permanent answer. The cache is invalidated on inferior exit, inferior appeared, and exec, since those are the only points where a process' mask configuration could legitimately change. --- gdb/aarch64-tdep.c | 154 ++++++++++++++++++++++++++++++++------------- 1 file changed, 112 insertions(+), 42 deletions(-) diff --git a/gdb/aarch64-tdep.c b/gdb/aarch64-tdep.c index 950ad4f6aae..c7003687eab 100644 --- a/gdb/aarch64-tdep.c +++ b/gdb/aarch64-tdep.c @@ -57,6 +57,9 @@ /* For inferior_ptid and current_inferior (). */ #include "inferior.h" +/* For gdb::observers::inferior_exit et al, used to invalidate the pauth + mask cache. */ +#include "observable.h" /* For std::sqrt and std::pow. */ #include @@ -4333,6 +4336,47 @@ aarch64_memtag_to_string (struct gdbarch *gdbarch, struct value *tag_value) return string_printf ("0x%s", phex_nz (tag)); } +/* Cached pointer authentication masks for an inferior. The masks are + fixed for the life of a process (they reflect the kernel's VA-size + configuration at exec time) and are shared by all its threads. We only + need to compute them once per inferior instead of on every call to + aarch64_remove_non_address_bits. LOW is used for user-space (low VA + range) pointers, HIGH is used for kernel-space (high VA range) + pointers. HIGH is only ever populated on targets that provide the + high-range mask registers. */ + +struct aarch64_pauth_mask_cache +{ + std::optional low; + std::optional high; +}; + +/* Per-inferior pauth mask cache. */ + +static const registry::key + aarch64_pauth_mask_cache_data; + +/* Drop INF's cached pauth masks. */ + +static void +aarch64_invalidate_pauth_mask_cache (inferior *inf) +{ + aarch64_pauth_mask_cache_data.clear (inf); +} + +/* Drop the pauth mask cache of every inferior sharing PSPACE. This is + attached to the all_objfiles_removed observer, which fires on exec. + Exec is the only point after startup where a process' VA-size + configuration, and hence its masks, could legitimately change. */ + +static void +aarch64_pauth_mask_cache_objfiles_removed (program_space *pspace) +{ + for (inferior *inf : all_inferiors ()) + if (inf->pspace == pspace) + aarch64_invalidate_pauth_mask_cache (inf); +} + /* See aarch64-tdep.h. */ CORE_ADDR @@ -4353,54 +4397,72 @@ aarch64_remove_non_address_bits (struct gdbarch *gdbarch, CORE_ADDR pointer) momentarily), we use the inferior ptid. */ if (inferior_ptid != null_ptid) { - /* If we do have an inferior, attempt to fetch its thread's thread_info - struct. */ - thread_info *thread = current_inferior ()->find_thread (inferior_ptid); + inferior *inf = current_inferior (); + bool kernel_address = (pointer & VA_RANGE_SELECT_BIT_MASK) != 0; - /* 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); - - /* 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 ()); + aarch64_pauth_mask_cache *cache + = aarch64_pauth_mask_cache_data.get (inf); + if (cache == nullptr) + cache = &aarch64_pauth_mask_cache_data.emplace (inf); - /* Is there pointer authentication support? */ - if (tdep->has_pauth ()) + std::optional &cached_mask + = kernel_address ? cache->high : cache->low; + + if (cached_mask.has_value ()) + mask = *cached_mask; + else + { + /* If we do have an inferior, attempt to fetch its thread's + thread_info struct. */ + thread_info *thread = inf->find_thread (inferior_ptid); + + /* If the thread is running, we will not be able to fetch the mask + registers. Leave the cache empty for this slot, we'll get + another chance to compute and cache it once some thread of + this inferior is next stopped. */ + if (thread != nullptr && thread->state () != THREAD_RUNNING) { - CORE_ADDR cmask, dmask; - int dmask_regnum - = AARCH64_PAUTH_DMASK_REGNUM (tdep->pauth_reg_base); - int cmask_regnum - = AARCH64_PAUTH_CMASK_REGNUM (tdep->pauth_reg_base); - - /* If we have a kernel address and we have kernel-mode address - mask registers, use those instead. */ - if (tdep->pauth_reg_count > 2 - && pointer & VA_RANGE_SELECT_BIT_MASK) + /* Otherwise, fetch the register cache and the masks. */ + struct regcache *regs + = get_thread_regcache (inf->process_target (), inferior_ptid); + + /* 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 ()); + + /* Is there pointer authentication support? */ + if (tdep->has_pauth ()) { - dmask_regnum - = AARCH64_PAUTH_DMASK_HIGH_REGNUM (tdep->pauth_reg_base); - cmask_regnum - = AARCH64_PAUTH_CMASK_HIGH_REGNUM (tdep->pauth_reg_base); + CORE_ADDR cmask, dmask; + int dmask_regnum + = AARCH64_PAUTH_DMASK_REGNUM (tdep->pauth_reg_base); + int cmask_regnum + = AARCH64_PAUTH_CMASK_REGNUM (tdep->pauth_reg_base); + + /* If we have a kernel address and we have kernel-mode + address mask registers, use those instead. */ + if (tdep->pauth_reg_count > 2 && kernel_address) + { + dmask_regnum + = AARCH64_PAUTH_DMASK_HIGH_REGNUM (tdep->pauth_reg_base); + cmask_regnum + = AARCH64_PAUTH_CMASK_HIGH_REGNUM (tdep->pauth_reg_base); + } + + /* We have both a code mask and a data mask. For now they + are the same, but this may change in the future. */ + if (regs->cooked_read (dmask_regnum, &dmask) != REG_VALID) + dmask = mask; + + if (regs->cooked_read (cmask_regnum, &cmask) != REG_VALID) + cmask = mask; + + mask |= aarch64_mask_from_pac_registers (cmask, dmask); } - /* We have both a code mask and a data mask. For now they are - the same, but this may change in the future. */ - if (regs->cooked_read (dmask_regnum, &dmask) != REG_VALID) - dmask = mask; - - if (regs->cooked_read (cmask_regnum, &cmask) != REG_VALID) - cmask = mask; - - mask |= aarch64_mask_from_pac_registers (cmask, dmask); + cached_mask = mask; } } } @@ -5076,6 +5138,14 @@ INIT_GDB_FILE (aarch64_tdep) gdbarch_register (bfd_arch_aarch64, aarch64_gdbarch_init, aarch64_dump_tdep); + /* Keep the pauth mask cache in sync with the inferiors it describes. */ + gdb::observers::inferior_exit.attach + (aarch64_invalidate_pauth_mask_cache, "aarch64-tdep"); + gdb::observers::inferior_appeared.attach + (aarch64_invalidate_pauth_mask_cache, "aarch64-tdep"); + gdb::observers::all_objfiles_removed.attach + (aarch64_pauth_mask_cache_objfiles_removed, "aarch64-tdep"); + /* Debug this file's internals. */ add_setshow_boolean_cmd ("aarch64", class_maintenance, &aarch64_debug, _("\ Set AArch64 debugging."), _("\ -- 2.43.0