public inbox for elfutils@sourceware.org
 help / color / mirror / Atom feed
From: German Gomez <german.gomez@arm.com>
To: elfutils-devel@sourceware.org
Subject: [PATCH 4/4] libdwfl, eu-stack, aarch64: Add API for setting AARCH64 PAC mask.
Date: Mon, 25 Apr 2022 14:03:11 +0000	[thread overview]
Message-ID: <20220425140311.95231-5-german.gomez@arm.com> (raw)
In-Reply-To: <20220425140311.95231-1-german.gomez@arm.com>

Add user API for setting the PAC mask.
The function is intended to be called in Dwfl_Thread_Callbacks.set_initial_registers.

Testing notes:

 ... consider the following program.c

 | int a = 0;
 | void leaf(void) {
 |   for (;;)
 |     a += a;
 | }
 | void parent(void) {
 |   leaf();
 | }
 | int main(void) {
 |   parent();
 |   return 0;
 | }

 ... compiled with "gcc-10 -O0 -g -mbranch-protection=pac-ret+leaf program.c"
 ... should yield the correct call stack, without mangled addresses:

 | $ eu-stack -p <PID>
 |
 | PID 760267 - process
 | TID 760267:
 | #0  0x0000aaaaaebd0804 leaf
 | #1  0x0000aaaaaebd0818 parent
 | #2  0x0000aaaaaebd0838 main
 | #3  0x0000ffffbd52ad50 __libc_start_main
 | #4  0x0000aaaaaebd0694 $x

Signed-off-by: German Gomez <german.gomez@arm.com>
---
 libdw/libdw.map            |  5 +++++
 libdwfl/dwfl_frame_regs.c  | 10 ++++++++++
 libdwfl/libdwfl.h          |  6 ++++++
 libdwfl/linux-pid-attach.c | 34 ++++++++++++++++++++++++++++++++--
 4 files changed, 53 insertions(+), 2 deletions(-)

diff --git a/libdw/libdw.map b/libdw/libdw.map
index 4f530378..469c72ab 100644
--- a/libdw/libdw.map
+++ b/libdw/libdw.map
@@ -366,3 +366,8 @@ ELFUTILS_0.186 {
     dwarf_linecontext;
     dwarf_linefunctionname;
 } ELFUTILS_0.177;
+
+ELFUTILS_0.188 {
+  global:
+    dwfl_thread_state_aarch64_pauth;
+} ELFUTILS_0.186;
diff --git a/libdwfl/dwfl_frame_regs.c b/libdwfl/dwfl_frame_regs.c
index 83b1abef..f8baf6d3 100644
--- a/libdwfl/dwfl_frame_regs.c
+++ b/libdwfl/dwfl_frame_regs.c
@@ -59,3 +59,13 @@ dwfl_thread_state_register_pc (Dwfl_Thread *thread, Dwarf_Word pc)
   state->pc_state = DWFL_FRAME_STATE_PC_SET;
 }
 INTDEF(dwfl_thread_state_register_pc)
+
+void
+dwfl_thread_state_aarch64_pauth(Dwfl_Thread *thread, Dwarf_Word insn_mask)
+{
+  Dwfl_Frame *state = thread->unwound;
+  assert (state && state->unwound == NULL);
+  assert (state->initial_frame);
+  thread->aarch64.pauth_insn_mask = insn_mask;
+}
+INTDEF(dwfl_thread_state_aarch64_pauth)
diff --git a/libdwfl/libdwfl.h b/libdwfl/libdwfl.h
index f98f1d52..9eef703c 100644
--- a/libdwfl/libdwfl.h
+++ b/libdwfl/libdwfl.h
@@ -753,6 +753,12 @@ bool dwfl_thread_state_registers (Dwfl_Thread *thread, int firstreg,
 void dwfl_thread_state_register_pc (Dwfl_Thread *thread, Dwarf_Word pc)
   __nonnull_attribute__ (1);
 
+/* Called by Dwfl_Thread_Callbacks.set_initial_registers implementation.
+   On AARCH64 platforms with Pointer Authentication, the bits from this mask
+   indicate the position of the PAC bits in return addresses. */
+void dwfl_thread_state_aarch64_pauth (Dwfl_Thread *thread, Dwarf_Word insn_mask)
+  __nonnull_attribute__ (1);
+
 /* Iterate through the threads for a process.  Returns zero if all threads have
    been processed by the callback, returns -1 on error, or the value of the
    callback when not DWARF_CB_OK.  -1 returned on error will set dwfl_errno ().
diff --git a/libdwfl/linux-pid-attach.c b/libdwfl/linux-pid-attach.c
index 09cba07b..bf50a5bc 100644
--- a/libdwfl/linux-pid-attach.c
+++ b/libdwfl/linux-pid-attach.c
@@ -321,6 +321,28 @@ pid_thread_state_registers_cb (int firstreg, unsigned nregs,
   return INTUSE(dwfl_thread_state_registers) (thread, firstreg, nregs, regs);
 }
 
+#if defined(__aarch64__)
+
+#include <linux/ptrace.h> /* struct user_pac_mask */
+
+static void
+pid_set_aarch64_pauth(Dwfl_Thread *thread, pid_t tid)
+{
+  struct user_pac_mask pac_mask;
+  struct iovec iovec;
+
+  iovec.iov_base = &pac_mask;
+  iovec.iov_len = sizeof (pac_mask);
+
+  /* If the ptrace returns an error, the system may not support pointer
+     authentication. In that case, set the masks to 0 (no PAC bits). */
+  if (ptrace(PTRACE_GETREGSET, tid, NT_ARM_PAC_MASK, &iovec))
+    pac_mask.insn_mask = 0;
+
+  INTUSE(dwfl_thread_state_aarch64_pauth) (thread, pac_mask.insn_mask);
+}
+#endif /* __aarch64__ */
+
 static bool
 pid_set_initial_registers (Dwfl_Thread *thread, void *thread_arg)
 {
@@ -333,8 +355,16 @@ pid_set_initial_registers (Dwfl_Thread *thread, void *thread_arg)
   pid_arg->tid_attached = tid;
   Dwfl_Process *process = thread->process;
   Ebl *ebl = process->ebl;
-  return ebl_set_initial_registers_tid (ebl, tid,
-					pid_thread_state_registers_cb, thread);
+  if (!ebl_set_initial_registers_tid (ebl, tid,
+				      pid_thread_state_registers_cb, thread))
+    return false;
+
+#if defined(__aarch64__)
+  /* Set aarch64 pointer authentication data. */
+  pid_set_aarch64_pauth(thread, tid);
+#endif
+
+  return true;
 }
 
 static void
-- 
2.25.1


  parent reply	other threads:[~2022-04-25 14:03 UTC|newest]

Thread overview: 11+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-04-25 14:03 [PATCH 0/4] Add AARCH64 pointer authentication support German Gomez
2022-04-25 14:03 ` [PATCH 1/4] aarch64: Create definitions for AARCH64_RA_SIGN_STATE register German Gomez
2023-02-23 16:22   ` Mark Wielaard
2022-04-25 14:03 ` [PATCH 2/4] libdw, aarch64: Implement DW_CFA_AARCH64_negate_ra_state CFI instruction German Gomez
2023-02-23 16:27   ` Mark Wielaard
2022-04-25 14:03 ` [PATCH 3/4] libdwfl, aarch64: Demangle return addresses using a PAC mask German Gomez
2022-04-25 14:03 ` German Gomez [this message]
2022-04-28 19:56 ` [PATCH 0/4] Add AARCH64 pointer authentication support Mark Wielaard
2022-05-19 13:30   ` German Gomez
2022-05-19 14:20     ` German Gomez
2023-02-24  0:17     ` Mark Wielaard

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20220425140311.95231-5-german.gomez@arm.com \
    --to=german.gomez@arm.com \
    --cc=elfutils-devel@sourceware.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).