From e47193471ed00cbcd2fd65e4096a6b04d86ad57e Mon Sep 17 00:00:00 2001
From: "Guanyou.Chen" <chenguanyou@xiaomi.com>
Date: Wed, 25 Dec 2024 23:50:28 +0800
Subject: [PATCH_v4] 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..0513623 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 (struct frame_info *this_frame)
+ {
+@@ -974,6 +978,9 @@ frame_unwind_pc (struct frame_info *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.43.0

