From 5dbb055486455206440bd0122589d0171895078d Mon Sep 17 00:00:00 2001
From: lipengfei28 <lipengfei28@xiaomi.com>
Date: Thu, 12 Feb 2026 17:08:51 +0800
Subject: [PATCH 1/2] arm64: fix gdb backtrace regs handling and stack
 switching

Split from previous combined change: keep the functional fixes (OOB read in exception frame handling, IRQ/process stack bridging, and guard against invalid/empty substacks).
---
 arm64.c | 121 ++++++++++++++++++++++++++++++++++++++++++++++++--------
 1 file changed, 104 insertions(+), 17 deletions(-)

diff --git a/arm64.c b/arm64.c
index c125655..a758e3c 100644
--- a/arm64.c
+++ b/arm64.c
@@ -228,7 +228,7 @@ arm64_get_current_task_reg(int regno, const char *name,
 		return FALSE;
 
 	if (sid && sid <= extra_stacks_idx) {
-		ur_bitmap = extra_stacks_regs[extra_stacks_idx - 1];
+		ur_bitmap = extra_stacks_regs[sid - 1];
 		goto get_sub;
 	}
 
@@ -3026,6 +3026,9 @@ static char *arm64_exception_functions[] = {
         "do_el0_irq_bp_hardening",
         "do_sp_pc_abort",
         "handle_bad_stack",
+        "el1h_64_sync",
+        "el1h_64_irq",
+        "el1h_64_error",
         NULL
 };
 
@@ -3123,6 +3126,11 @@ arm64_print_stackframe_entry(struct bt_info *bt, int level, struct arm64_stackfr
 
 	fprintf(ofp, "\n");
 
+	if (STREQ(name, "el1h_64_irq") || STREQ(name, "el1h_64_sync"))
+		if (arm64_is_kernel_exception_frame(bt, frame->sp)) {
+			arm64_print_exception_frame(bt, frame->sp, KERNEL_MODE, ofp);
+		}
+
 	if (bt->flags & BT_LINE_NUMBERS) {
 		get_line_number(branch_pc, buf, FALSE);
 		if (strlen(buf))
@@ -3775,11 +3783,13 @@ arm64_back_trace_cmd(struct bt_info *bt)
 			REG_SEQ(arm64_pt_regs, pc));
 		SET_BIT(extra_stacks_regs[extra_stacks_idx]->bitmap,
 			REG_SEQ(arm64_pt_regs, sp));
-		if (!bt->machdep ||
+		if (extra_stacks_regs[extra_stacks_idx]->ur.pc &&
+		    (bt->task != tt->panic_task) &&
+		    (!bt->machdep ||
 		     (extra_stacks_regs[extra_stacks_idx]->ur.sp !=
 		      ((struct user_regs_bitmap_struct *)(bt->machdep))->ur.sp &&
 		      extra_stacks_regs[extra_stacks_idx]->ur.pc !=
-		      ((struct user_regs_bitmap_struct *)(bt->machdep))->ur.pc)) {
+		      ((struct user_regs_bitmap_struct *)(bt->machdep))->ur.pc))) {
 			gdb_add_substack (extra_stacks_idx++);
 		}
 	}
@@ -3925,11 +3935,13 @@ arm64_back_trace_cmd_v2(struct bt_info *bt)
 			REG_SEQ(arm64_pt_regs, pc));
 		SET_BIT(extra_stacks_regs[extra_stacks_idx]->bitmap,
 			REG_SEQ(arm64_pt_regs, sp));
-		if (!bt->machdep ||
+		if (extra_stacks_regs[extra_stacks_idx]->ur.pc &&
+		    (bt->task != tt->panic_task) &&
+		    (!bt->machdep ||
 		     (extra_stacks_regs[extra_stacks_idx]->ur.sp !=
 		      ((struct user_regs_bitmap_struct *)(bt->machdep))->ur.sp &&
 		      extra_stacks_regs[extra_stacks_idx]->ur.pc !=
-		      ((struct user_regs_bitmap_struct *)(bt->machdep))->ur.pc)) {
+		      ((struct user_regs_bitmap_struct *)(bt->machdep))->ur.pc))) {
 			gdb_add_substack (extra_stacks_idx++);
 		}		
 	}
@@ -4263,8 +4275,40 @@ arm64_switch_stack(struct bt_info *bt, struct arm64_stackframe *frame, FILE *ofp
 	if (frame->fp == 0)
 		return USER_MODE;
 
-	if (!(machdep->flags & UNW_4_14))
+	if (!(machdep->flags & UNW_4_14)) {
 		arm64_print_exception_frame(bt, frame->sp, KERNEL_MODE, ofp);
+	} else {
+		if (!extra_stacks_regs[extra_stacks_idx]) {
+			extra_stacks_regs[extra_stacks_idx] = (struct user_regs_bitmap_struct *)
+				malloc(sizeof(struct user_regs_bitmap_struct));
+		}
+		memset(extra_stacks_regs[extra_stacks_idx], 0, sizeof(struct user_regs_bitmap_struct));
+		struct user_regs_bitmap_struct *ur_ptr = extra_stacks_regs[extra_stacks_idx];
+
+		ulong next_fp = GET_STACK_ULONG(frame->fp);
+		ulong next_pc = GET_STACK_ULONG(frame->fp + 8);
+		ulong next_sp = frame->fp + 16;
+
+		if (is_kernel_text(next_pc | ms->CONFIG_ARM64_KERNELPACMASK))
+			next_pc |= ms->CONFIG_ARM64_KERNELPACMASK;
+
+		ur_ptr->ur.pc = next_pc;
+		ur_ptr->ur.sp = next_sp;
+		ur_ptr->ur.regs[29] = next_fp;
+
+		SET_BIT(ur_ptr->bitmap, REG_SEQ(arm64_pt_regs, pc));
+		SET_BIT(ur_ptr->bitmap, REG_SEQ(arm64_pt_regs, sp));
+		SET_BIT(ur_ptr->bitmap, REG_SEQ(arm64_pt_regs, regs[0]) + 29);
+
+		if (ur_ptr->ur.pc &&
+		    (!bt->machdep ||
+		     (ur_ptr->ur.sp !=
+		      ((struct user_regs_bitmap_struct *)(bt->machdep))->ur.sp &&
+		      ur_ptr->ur.pc !=
+		      ((struct user_regs_bitmap_struct *)(bt->machdep))->ur.pc))) {
+			gdb_add_substack (extra_stacks_idx++);
+		}
+	}
 
 	return KERNEL_MODE;
 }
@@ -4300,8 +4344,40 @@ arm64_switch_stack_from_overflow(struct bt_info *bt, struct arm64_stackframe *fr
 	if (frame->fp == 0)
 		return USER_MODE;
 
-	if (!(machdep->flags & UNW_4_14))
+	if (!(machdep->flags & UNW_4_14)) {
 		arm64_print_exception_frame(bt, frame->sp, KERNEL_MODE, ofp);
+	} else {
+		if (!extra_stacks_regs[extra_stacks_idx]) {
+			extra_stacks_regs[extra_stacks_idx] = (struct user_regs_bitmap_struct *)
+				malloc(sizeof(struct user_regs_bitmap_struct));
+		}
+		memset(extra_stacks_regs[extra_stacks_idx], 0, sizeof(struct user_regs_bitmap_struct));
+		struct user_regs_bitmap_struct *ur_ptr = extra_stacks_regs[extra_stacks_idx];
+
+		ulong next_fp = GET_STACK_ULONG(frame->fp);
+		ulong next_pc = GET_STACK_ULONG(frame->fp + 8);
+		ulong next_sp = frame->fp + 16;
+
+		if (is_kernel_text(next_pc | ms->CONFIG_ARM64_KERNELPACMASK))
+			next_pc |= ms->CONFIG_ARM64_KERNELPACMASK;
+
+		ur_ptr->ur.pc = next_pc;
+		ur_ptr->ur.sp = next_sp;
+		ur_ptr->ur.regs[29] = next_fp;
+
+		SET_BIT(ur_ptr->bitmap, REG_SEQ(arm64_pt_regs, pc));
+		SET_BIT(ur_ptr->bitmap, REG_SEQ(arm64_pt_regs, sp));
+		SET_BIT(ur_ptr->bitmap, REG_SEQ(arm64_pt_regs, regs[0]) + 29);
+
+		if (ur_ptr->ur.pc &&
+		    (!bt->machdep ||
+		     (ur_ptr->ur.sp !=
+		      ((struct user_regs_bitmap_struct *)(bt->machdep))->ur.sp &&
+		      ur_ptr->ur.pc !=
+		      ((struct user_regs_bitmap_struct *)(bt->machdep))->ur.pc))) {
+			gdb_add_substack (extra_stacks_idx++);
+		}
+	}
 
 	return KERNEL_MODE;
 }
@@ -4556,16 +4632,27 @@ arm64_print_exception_frame(struct bt_info *bt, ulong pt_regs, int mode, FILE *o
 			}
 			memset(extra_stacks_regs[extra_stacks_idx], 0,
 				sizeof(struct user_regs_bitmap_struct));
-			memcpy(&extra_stacks_regs[extra_stacks_idx]->ur, regs,
-				sizeof(struct arm64_pt_regs));
-			for (int i = 0; i < sizeof(struct arm64_pt_regs)/sizeof(long); i++)
-				SET_BIT(extra_stacks_regs[extra_stacks_idx]->bitmap, i);
-			if (!bt->machdep ||
-			     (extra_stacks_regs[extra_stacks_idx]->ur.sp !=
-			      ((struct user_regs_bitmap_struct *)(bt->machdep))->ur.sp &&
-			      extra_stacks_regs[extra_stacks_idx]->ur.pc !=
-			      ((struct user_regs_bitmap_struct *)(bt->machdep))->ur.pc)) {
-				gdb_add_substack (extra_stacks_idx++);
+			{
+				struct user_regs_bitmap_struct *ur_ptr = extra_stacks_regs[extra_stacks_idx];
+				int i;
+
+				ur_ptr->ur.pc = regs->pc;
+				ur_ptr->ur.sp = regs->sp;
+				ur_ptr->ur.pstate = regs->pstate;
+				for (i = 0; i < 31; i++)
+					ur_ptr->ur.regs[i] = regs->regs[i];
+
+				for (i = 0; i < 34; i++)
+					SET_BIT(ur_ptr->bitmap, i);
+
+				if (ur_ptr->ur.pc &&
+				    (!bt->machdep ||
+				     (ur_ptr->ur.sp !=
+				      ((struct user_regs_bitmap_struct *)(bt->machdep))->ur.sp &&
+				      ur_ptr->ur.pc !=
+				      ((struct user_regs_bitmap_struct *)(bt->machdep))->ur.pc))) {
+					gdb_add_substack (extra_stacks_idx++);
+				}
 			}			
 		}
 	}
-- 
2.34.1

