]> git.ipfire.org Git - thirdparty/elfutils.git/commitdiff
libdwfl, aarch64: Demangle return addresses using a PAC mask
authorGerman Gomez <german.gomez@arm.com>
Mon, 26 Aug 2024 10:52:55 +0000 (11:52 +0100)
committerMark Wielaard <mark@klomp.org>
Fri, 30 Aug 2024 13:00:59 +0000 (15:00 +0200)
Demangle mangled return addresses on AARCH64. The value of the masks is
stored in the struct Dwfl_Thread.

Signed-off-by: German Gomez <german.gomez@arm.com>
[SteveC: remove dwfl_thread_state_aarch64_pauth]
Signed-off-by: Steve Capper <steve.capper@arm.com>
libdwfl/dwfl_frame.c
libdwfl/frame_unwind.c
libdwfl/libdwflP.h

index 5ee71dd4c0110a210b536e016b126efd535fd4c2..8af8843fd7db3d58f1330e1e0d6eeb12ee786cad 100644 (file)
@@ -269,6 +269,8 @@ dwfl_getthreads (Dwfl *dwfl, int (*callback) (Dwfl_Thread *thread, void *arg),
   thread.process = process;
   thread.unwound = NULL;
   thread.callbacks_arg = NULL;
+  thread.aarch64.pauth_insn_mask = 0;
+
   for (;;)
     {
       thread.tid = process->callbacks->next_thread (dwfl,
@@ -339,6 +341,7 @@ getthread (Dwfl *dwfl, pid_t tid,
       thread.process = process;
       thread.unwound = NULL;
       thread.callbacks_arg = NULL;
+      thread.aarch64.pauth_insn_mask = 0;
 
       if (process->callbacks->get_thread (dwfl, tid, process->callbacks_arg,
                                          &thread.callbacks_arg))
index 1e2f02553298df693f3790b286dffffaea209049..ab444d25a7faa3f99af0f1febac0451cfd98b366 100644 (file)
@@ -599,7 +599,19 @@ handle_cfi (Dwfl_Frame *state, Dwarf_Addr pc, Dwarf_CFI *cfi, Dwarf_Addr bias)
 
       /* Some architectures encode some extra info in the return address.  */
       if (regno == frame->fde->cie->return_address_register)
-       regval &= ebl_func_addr_mask (ebl);
+       {
+         regval &= ebl_func_addr_mask (ebl);
+
+         /* In aarch64, pseudo-register RA_SIGN_STATE indicates whether the
+            return address needs demangling using the PAC mask from the
+            thread. */
+         if (cfi->e_machine == EM_AARCH64 &&
+             frame->nregs > DW_AARCH64_RA_SIGN_STATE &&
+             frame->regs[DW_AARCH64_RA_SIGN_STATE].value & 0x1)
+           {
+             regval &= ~(state->thread->aarch64.pauth_insn_mask);
+           }
+       }
 
       /* This is another strange PPC[64] case.  There are two
         registers numbers that can represent the same DWARF return
index e0055d65590c9f1280e37f25e557e555d81a9507..d0a5f0567b2f4fda2e4cbb5aeb94e1d7e9a1a9a3 100644 (file)
@@ -244,6 +244,12 @@ struct Dwfl_Thread
   /* Bottom (innermost) frame while we're initializing, NULL afterwards.  */
   Dwfl_Frame *unwound;
   void *callbacks_arg;
+
+  /* Data for handling AARCH64 (currently limited to demangling PAC from
+     return addresses). */
+  struct {
+    Dwarf_Addr pauth_insn_mask;
+  } aarch64;
 };
 
 /* See its typedef in libdwfl.h.  */