From d4ec380f4ebba1a068b5eaf507bd2d90097c96f4 Mon Sep 17 00:00:00 2001
From: "Guanyou.Chen" <chenguanyou@xiaomi.com>
Date: Wed, 25 Dec 2024 23:50:28 +0800
Subject: [PATCH_v3] arm64: add pac mask to better support gdb stack unwind

Currently, gdb passthroughs of 'bt', 'frame', 'up', 'down',
'info, locals' don't work on arm64 machine enabled pauth.
This is due to gdb not knowing the lr register real values
to unwind the stack frames.

                                      ----------------------------
           gdb passthrough (eg. "bt") |                          |
   crash   -------------------------> |                          |
                                      |      gdb_interface       |
                                      |                          |
                                      |                          |
                                      |  ----------------------  |
                    unwind_pc         |  |                    |  |
crash_target<-------------------------+--|        gdb         |  |
            --------------------------+->|                    |  |
     arm64:   crash_decode_ptrauth_pc |  |                    |  |
     other:   origin_pc               |  |                    |  |
                                      |  ----------------------  |
                                      ----------------------------

With the patch:
    crash> gdb bt
    #0  __switch_to (prev=prev@entry=0xffffff8001af92c0, next=next@entry=0xffffff889da7a580) at /proc/self/cwd/common/arch/arm64/kernel/process.c:569
    #1  0xffffffd3602132c0 in context_switch (rq=0xffffff8a7295a080, prev=0xffffff8001af92c0, next=0xffffff889da7a580, rf=<optimized out>) at /proc/self/cwd/common/kernel/sched/core.c:5515
    #2  __schedule (sched_mode=<optimized out>, sched_mode@entry=2147859424) at /proc/self/cwd/common/kernel/sched/core.c:6843
    #3  0xffffffd3602136d8 in schedule () at /proc/self/cwd/common/kernel/sched/core.c:6917
    ...

Without the patch:
    crash> gdb bt
    #0  __switch_to (prev=0xffffff8001af92c0, next=0xffffff889da7a580) at /proc/self/cwd/common/arch/arm64/kernel/process.c:569
    #1  0x9fc5c5d3602132c0 in ?? ()
    Backtrace stopped: previous frame identical to this frame (corrupt stack?)

Signed-off-by: Guanyou.Chen <chenguanyou@xiaomi.com>
---
 gdb-10.2.patch  | 23 +++++++++++++++++++++++
 gdb_interface.c | 10 ++++++++++
 2 files changed, 33 insertions(+)

diff --git a/gdb-10.2.patch b/gdb-10.2.patch
index c867660..f7d4985 100644
--- a/gdb-10.2.patch
+++ b/gdb-10.2.patch
@@ -16216,3 +16216,26 @@ exit 0
  	    printf_filtered (_("Backtrace stopped: %s\n"),
  			     frame_stop_reason_string (trailing));
  	}
+--- gdb-10.2/gdb/frame.c.orig
++++ gdb-10.2/gdb/frame.c
+@@ -944,6 +944,10 @@ frame_find_by_id (struct frame_id id)
+   return NULL;
+ }
+
++#ifdef CRASH_MERGE
++extern "C" void crash_decode_ptrauth_pc(CORE_ADDR* pc);
++#endif
++
+ static CORE_ADDR
+ frame_unwind_pc (frame_info_ptr this_frame)
+ {
+@@ -974,6 +978,9 @@ frame_unwind_pc (struct frame_info_ptr *this_frame)
+       try
+	{
+	  pc = gdbarch_unwind_pc (prev_gdbarch, this_frame);
++#ifdef CRASH_MERGE
++	  crash_decode_ptrauth_pc(&pc);
++#endif
+	  pc_p = true;
+	}
+       catch (const gdb_exception_error &ex)
diff --git a/gdb_interface.c b/gdb_interface.c
index 315711e..e108d09 100644
--- a/gdb_interface.c
+++ b/gdb_interface.c
@@ -1083,3 +1083,13 @@ int crash_get_current_task_reg (int regno, const char *regname,
 	return machdep->get_current_task_reg(regno, regname, regsize, value);
 }
 
+/* arm64 kernel lr maybe has patuh */
+void crash_decode_ptrauth_pc(ulong *pc);
+void crash_decode_ptrauth_pc(ulong *pc)
+{
+#ifdef ARM64
+	struct machine_specific *ms = machdep->machspec;
+	if (is_kernel_text(*pc | ms->CONFIG_ARM64_KERNELPACMASK))
+		*pc |= ms->CONFIG_ARM64_KERNELPACMASK;
+#endif /* !ARM64 */
+}
-- 
2.34.1

