* [PATCH 0/2] gdb, aarch64: cache pointer authentication masks per inferior
@ 2026-09-12 22:20 Luis Machado
2026-09-12 22:20 ` [PATCH 1/2] " Luis Machado
2026-09-12 22:20 ` [PATCH 2/2] gdb, aarch64: add selftest for the pauth mask cache Luis Machado
0 siblings, 2 replies; 4+ messages in thread
From: Luis Machado @ 2026-09-12 22:20 UTC (permalink / raw)
To: gdb-patches; +Cc: thiago.bauermann
aarch64_remove_non_address_bits recomputes the pointer authentication
dmask/cmask on every call by walking the current inferior's thread
list, looking up its regcache, and reading the masks 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 (they are fixed for the life of a process
and shared by all of its threads).
Patch 1 caches the computed mask per inferior instead of recomputing
it on every call, only populating the cache when a thread is stopped
so a transient "thread running" state never gets cached as a
permanent answer, and invalidates the cache on inferior exit,
inferior appeared, and exec.
Patch 2 adds a selftest that verifies the cache actually avoids
redundant target register fetches across a simulated resume/stop
cycle.
Tested on aarch64-linux with no regressions, though the testing was
done on a target without PAC support. It would be good to also
validate on a PAC-enabled target to be sure.
Luis Machado (2):
gdb, aarch64: cache pointer authentication masks per inferior
gdb, aarch64: add selftest for the pauth mask cache
gdb/aarch64-tdep.c | 224 ++++++++++++++++++++++++++++++++++++---------
1 file changed, 182 insertions(+), 42 deletions(-)
--
2.43.0
^ permalink raw reply [flat|nested] 4+ messages in thread
* [PATCH 1/2] gdb, aarch64: cache pointer authentication masks per inferior
2026-09-12 22:20 [PATCH 0/2] gdb, aarch64: cache pointer authentication masks per inferior Luis Machado
@ 2026-09-12 22:20 ` Luis Machado
2026-09-14 15:24 ` Simon Marchi
2026-09-12 22:20 ` [PATCH 2/2] gdb, aarch64: add selftest for the pauth mask cache Luis Machado
1 sibling, 1 reply; 4+ messages in thread
From: Luis Machado @ 2026-09-12 22:20 UTC (permalink / raw)
To: gdb-patches; +Cc: thiago.bauermann
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 <cmath>
@@ -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<CORE_ADDR> low;
+ std::optional<CORE_ADDR> high;
+};
+
+/* Per-inferior pauth mask cache. */
+
+static const registry<inferior>::key<aarch64_pauth_mask_cache>
+ 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<aarch64_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<CORE_ADDR> &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<aarch64_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
^ permalink raw reply [flat|nested] 4+ messages in thread
* [PATCH 2/2] gdb, aarch64: add selftest for the pauth mask cache
2026-09-12 22:20 [PATCH 0/2] gdb, aarch64: cache pointer authentication masks per inferior Luis Machado
2026-09-12 22:20 ` [PATCH 1/2] " Luis Machado
@ 2026-09-12 22:20 ` Luis Machado
1 sibling, 0 replies; 4+ messages in thread
From: Luis Machado @ 2026-09-12 22:20 UTC (permalink / raw)
To: gdb-patches; +Cc: thiago.bauermann
Add aarch64_remove_non_address_bits_test, a selftest that builds an
aarch64 gdbarch with the pauth feature, installs a mock target that
counts fetch_registers calls, and calls
aarch64_remove_non_address_bits repeatedly while invalidating the
regcache between calls to simulate a resume/stop cycle. It checks
that the target is only ever asked for the dmask/cmask registers
once each, rather than once per stop, verifying the per-inferior
cache added in the previous commit.
---
gdb/aarch64-tdep.c | 70 ++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 70 insertions(+)
diff --git a/gdb/aarch64-tdep.c b/gdb/aarch64-tdep.c
index c7003687eab..fb046d12c8e 100644
--- a/gdb/aarch64-tdep.c
+++ b/gdb/aarch64-tdep.c
@@ -42,6 +42,9 @@
#include "user-regs.h"
#include "ax-gdb.h"
#include "gdbsupport/selftest.h"
+#include "gdbthread.h"
+#include "test-target.h"
+#include "scoped-mock-context.h"
#include "aarch64-tdep.h"
#include "aarch64-ravenscar-thread.h"
@@ -4470,6 +4473,71 @@ aarch64_remove_non_address_bits (struct gdbarch *gdbarch, CORE_ADDR pointer)
return aarch64_remove_top_bits (pointer, mask);
}
+#if GDB_SELF_TEST
+namespace selftests {
+
+/* A mock target that supplies zeroed pauth mask registers and counts
+ how many times fetch_registers is called, so tests can tell how many
+ times a mask value was actually fetched from the target as opposed to
+ reused from a cache. */
+
+class pac_mask_counting_target : public test_target_ops
+{
+public:
+ void fetch_registers (regcache *regs, int regno) override
+ {
+ fetch_registers_called++;
+ regs->raw_supply_zeroed (regno);
+ }
+
+ unsigned int fetch_registers_called = 0;
+};
+
+/* Verify that aarch64_remove_non_address_bits does not re-fetch the
+ pauth mask registers from the target on every call, since those masks
+ are constant for the lifetime of the inferior (see the comment in
+ aarch64_remove_non_address_bits). We simulate one call per stop by
+ invalidating the regcache (via registers_changed) between calls, the
+ same way a resume/stop cycle (e.g. stepi) would. */
+
+static void
+aarch64_remove_non_address_bits_test ()
+{
+ aarch64_features features;
+ features.pauth = true;
+
+ struct gdbarch_info info;
+ info.bfd_arch_info = bfd_scan_arch ("aarch64");
+ info.target_desc = aarch64_read_description (features);
+
+ struct gdbarch *gdbarch = gdbarch_find_by_info (info);
+ SELF_CHECK (gdbarch != nullptr);
+
+ aarch64_gdbarch_tdep *tdep = gdbarch_tdep<aarch64_gdbarch_tdep> (gdbarch);
+ SELF_CHECK (tdep->has_pauth ());
+
+ scoped_mock_context<pac_mask_counting_target> ctx (gdbarch);
+
+ const int n_calls = 20;
+ for (int i = 0; i < n_calls; i++)
+ {
+ aarch64_remove_non_address_bits (gdbarch, 0x1234);
+
+ /* Invalidate the regcache, as would happen after a resume/stop
+ cycle, so that a naive implementation is forced to re-fetch the
+ mask registers on the next call. */
+ registers_changed ();
+ }
+
+ /* The masks never change for the life of the inferior. Each of the two
+ mask registers (dmask, cmask) should only ever need to be fetched
+ from the target once, not once per stop. */
+ SELF_CHECK (ctx.mock_target.fetch_registers_called == 2);
+}
+
+} /* namespace selftests */
+#endif /* GDB_SELF_TEST */
+
/* Given NAMES, a vector of strings, initialize it with all the SME
pseudo-register names for the current streaming vector length. */
@@ -5160,6 +5228,8 @@ When on, AArch64 specific debugging is enabled."),
selftests::aarch64_analyze_prologue_test);
selftests::register_test ("aarch64-process-record",
selftests::aarch64_process_record_test);
+ selftests::register_test ("aarch64-remove-non-address-bits",
+ selftests::aarch64_remove_non_address_bits_test);
#endif
}
--
2.43.0
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [PATCH 1/2] gdb, aarch64: cache pointer authentication masks per inferior
2026-09-12 22:20 ` [PATCH 1/2] " Luis Machado
@ 2026-09-14 15:24 ` Simon Marchi
0 siblings, 0 replies; 4+ messages in thread
From: Simon Marchi @ 2026-09-14 15:24 UTC (permalink / raw)
To: Luis Machado, gdb-patches; +Cc: thiago.bauermann
On 9/12/26 6:20 PM, Luis Machado wrote:
> 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.
Not against this patch, but just a precision: after the first read (and
until the thread resumes), the registers are cached in the regcache, so
a read wouldn't have to read the registers from the target again (which
is probably the most expensive part).
And just wondering, do you see a real world impact with this patch, is
there some measurable improvement?
> 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"
IMO these comments are useless.
> /* For std::sqrt and std::pow. */
> #include <cmath>
>
> @@ -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<CORE_ADDR> low;
> + std::optional<CORE_ADDR> high;
> +};
> +
> +/* Per-inferior pauth mask cache. */
> +
> +static const registry<inferior>::key<aarch64_pauth_mask_cache>
> + aarch64_pauth_mask_cache_data;
To follow the conventions used elsewhere, I would suggest make a
per-inferior object, with a pauth mask field in it:
struct aarch64_per_inferior
{
struct pauth_mask
{
std::optional<CORE_ADDR> low;
std::optional<CORE_ADDR> high;
};
};
The registry key variable would be called "aarch64_per_inferior_data",
"aarch64_per_inferior_key", or something like that.
Then you'd have a function "get_aarch64_per_inferior" that uses
try_emplace to abstract the "create if needed" operation.
> +
> +/* 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);
> +}
We have an observable inferior_execd, can't you use that?
When we need to reset some cached inferior state, we often use the trio
of observables:
- inferior created/appeared
- inferior execd
- inferior exited
I never remember the different between created and appeared, it might be
related to run vs attach, not sure. There is probably one more correct
that the other.
> +
> /* 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<aarch64_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<CORE_ADDR> &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)
I know it's pre-existing, but checking for THREAD_RUNNING seems wrong to
me. The thread can be running from the point of view of the user by
really stopped at the ptrace level. It happens for instance when
evaluating a breakpoint condition, since we haven't decided yet if the
breakpoint should cause a user visible stop or not. I
> {
> - 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<aarch64_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;
This function becomes a bit complicated, I wouldn't find if you wanted
to move this scope (fetch the masks from the inferior for real) to a
helper function.
Simon
^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2026-09-14 15:25 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-09-12 22:20 [PATCH 0/2] gdb, aarch64: cache pointer authentication masks per inferior Luis Machado
2026-09-12 22:20 ` [PATCH 1/2] " Luis Machado
2026-09-14 15:24 ` Simon Marchi
2026-09-12 22:20 ` [PATCH 2/2] gdb, aarch64: add selftest for the pauth mask cache Luis Machado
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox