From 08271e45e4ea6263fc2957d1e876becd6cfc1a0d Mon Sep 17 00:00:00 2001 From: Tao Liu Date: Wed, 25 Jun 2025 16:02:02 +1200 Subject: [PATCH 6/9] arm64: Add gdb multi-stack unwind support Co-developed-by: Alexey Makhalov Co-developed-by: Tao Liu Signed-off-by: Tao Liu --- arm64.c | 96 ++++++++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 92 insertions(+), 4 deletions(-) diff --git a/arm64.c b/arm64.c index 8291301..354d17a 100644 --- a/arm64.c +++ b/arm64.c @@ -226,6 +226,12 @@ arm64_get_current_task_reg(int regno, const char *name, tc = CURRENT_CONTEXT(); if (!tc) return FALSE; + + if (sid && sid <= extra_stacks_idx) { + ur_bitmap = extra_stacks_regs[extra_stacks_idx - 1]; + goto get_sub; + } + BZERO(&bt_setup, sizeof(struct bt_info)); clone_bt_info(&bt_setup, &bt_info, tc); fill_stackbuf(&bt_info); @@ -241,25 +247,29 @@ arm64_get_current_task_reg(int regno, const char *name, goto get_all; } +get_sub: switch (regno) { case X0_REGNUM ... X30_REGNUM: if (!NUM_IN_BITMAP(ur_bitmap->bitmap, REG_SEQ(arm64_pt_regs, regs[0]) + regno - X0_REGNUM)) { - FREEBUF(ur_bitmap); + if (!sid) + FREEBUF(ur_bitmap); return FALSE; } break; case SP_REGNUM: if (!NUM_IN_BITMAP(ur_bitmap->bitmap, REG_SEQ(arm64_pt_regs, sp))) { - FREEBUF(ur_bitmap); + if (!sid) + FREEBUF(ur_bitmap); return FALSE; } break; case PC_REGNUM: if (!NUM_IN_BITMAP(ur_bitmap->bitmap, REG_SEQ(arm64_pt_regs, pc))) { - FREEBUF(ur_bitmap); + if (!sid) + FREEBUF(ur_bitmap); return FALSE; } break; @@ -287,7 +297,7 @@ get_all: break; } - if (bt_info.need_free) { + if (!sid && bt_info.need_free) { FREEBUF(ur_bitmap); bt_info.need_free = FALSE; } @@ -3680,6 +3690,7 @@ arm64_back_trace_cmd(struct bt_info *bt) int level; ulong exception_frame; FILE *ofp; + extra_stacks_idx = 0; if (bt->flags & BT_OPT_BACK_TRACE) { if (machdep->flags & UNW_4_14) { @@ -3733,6 +3744,35 @@ arm64_back_trace_cmd(struct bt_info *bt) stackframe.fp = bt->frameptr; } + if (is_task_active(bt->task)) { + 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)); + if (bt->task != tt->panic_task && stackframe.sp) { + readmem(stackframe.sp - 8, KVADDR, &extra_stacks_regs[extra_stacks_idx]->ur.pc, + sizeof(ulong), "extra_stacks_regs.pc", RETURN_ON_ERROR); + readmem(stackframe.sp - 16, KVADDR, &extra_stacks_regs[extra_stacks_idx]->ur.sp, + sizeof(ulong), "extra_stacks_regs.sp", RETURN_ON_ERROR); + } else { + extra_stacks_regs[extra_stacks_idx]->ur.pc = stackframe.pc; + extra_stacks_regs[extra_stacks_idx]->ur.sp = stackframe.sp; + } + SET_BIT(extra_stacks_regs[extra_stacks_idx]->bitmap, + REG_SEQ(arm64_pt_regs, pc)); + SET_BIT(extra_stacks_regs[extra_stacks_idx]->bitmap, + REG_SEQ(arm64_pt_regs, sp)); + 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++); + } + } + if (bt->flags & BT_TEXT_SYMBOLS) { arm64_print_text_symbols(bt, &stackframe, ofp); if (BT_REFERENCE_FOUND(bt)) { @@ -3854,6 +3894,35 @@ arm64_back_trace_cmd_v2(struct bt_info *bt) stackframe.fp = bt->frameptr; } + if (is_task_active(bt->task)) { + 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)); + if (bt->task != tt->panic_task && stackframe.sp) { + readmem(stackframe.sp - 8, KVADDR, &extra_stacks_regs[extra_stacks_idx]->ur.pc, + sizeof(ulong), "extra_stacks_regs.pc", RETURN_ON_ERROR); + readmem(stackframe.sp - 16, KVADDR, &extra_stacks_regs[extra_stacks_idx]->ur.sp, + sizeof(ulong), "extra_stacks_regs.sp", RETURN_ON_ERROR); + } else { + extra_stacks_regs[extra_stacks_idx]->ur.pc = stackframe.pc; + extra_stacks_regs[extra_stacks_idx]->ur.sp = stackframe.sp; + } + SET_BIT(extra_stacks_regs[extra_stacks_idx]->bitmap, + REG_SEQ(arm64_pt_regs, pc)); + SET_BIT(extra_stacks_regs[extra_stacks_idx]->bitmap, + REG_SEQ(arm64_pt_regs, sp)); + 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++); + } + } + if (bt->flags & BT_TEXT_SYMBOLS) { arm64_print_text_symbols(bt, &stackframe, ofp); if (BT_REFERENCE_FOUND(bt)) { @@ -4468,6 +4537,25 @@ arm64_print_exception_frame(struct bt_info *bt, ulong pt_regs, int mode, FILE *o fprintf(ofp, "ORIG_X0: %016lx SYSCALLNO: %lx", (ulong)regs->orig_x0, (ulong)regs->syscallno); fprintf(ofp, " PSTATE: %08lx\n", (ulong)regs->pstate); + } else if (!(bt->flags & BT_EFRAME_SEARCH)) { + 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)); + 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++); + } } } -- 2.47.0