Hi 李鹏飞,
Please Do NOT send the patches as email attachments, because this will
make us to inline comment on your code a lot harder.
Anyway, I will comment your patch by copy-paste your code as follows:
1) Please reword your patch commit log, it is too short and people
will lost key context after years returning back to your patch.
2)
@@ -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]; ........
and the next hunk:
@@ -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; .......
The 2 "else" block looks identical. Could you please extract it as a
function, so we can keep only one copy of the code?
3)
@@ -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++);
+ {
Why add the code into an empty block "{}"? Looks strange to me.
+ 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++)
Thanks,
Tao Liu
On Thu, Feb 12, 2026 at 10:23 PM 李鹏飞 <lipengfei28(a)xiaomi.com> wrote:
Hi Lianbo,
Thanks for the detailed explanation and for pointing out the frame N issue.
I agree with your assessment. GDB unwinding is driven by the register set we feed into
gdb, so the correct workflow is to unwind from each register snapshot (output1/2/3) by
switching threads (info threads / thread N) and then running gdb bt.
Based on your feedback, I’ve updated my patch and will send a v2 that includes only the
functional ARM64 fixes:
fix the out-of-bounds read in exception-frame handling
improve IRQ/process stack switching so unwinding can continue
avoid creating invalid/empty substacks (e.g. PC == 0)
No gdb output formatting changes will be included.
Test log:
crash> gdb bt
#0 0xffffffebfdfffb84 in crash_notes_save_regs (regs=0xffffffc00ceeaf00) at
arch/arm64/include/asm/crash_notes.h:61
#1 crash_notes_save_this_cpu (type=CRASH_NOTE_CRASHING, cpu=<optimized out>) at
kernel/crash_notes.c:56
#2 crash_notes_save_panic_cpu (this=<optimized out>, event=<optimized out>,
ptr=<optimized out>) at kernel/crash_notes.c:121
#3 0xffffffebfdf1178c in notifier_call_chain (nl=<optimized out>, nr_to_call=-13,
nr_calls=0x0, val=<optimized out>, v=<optimized out>) at kernel/notifier.c:87
#4 atomic_notifier_call_chain (nh=<optimized out>, val=0, v=0xffffffec0055d510
<panic[buf]>) at kernel/notifier.c:225
#5 0xffffffebfded26cc in panic (fmt=0xffffffebff2a7f50 "panic_on_taint set
...") at kernel/panic.c:368
#6 0xffffffebfded2b80 in add_taint (flag=5, lockdep_ok=<optimized out>) at
kernel/panic.c:552
#7 0xffffffebfe1d2d94 in kfence_report_error (address=<optimized out>,
is_write=<optimized out>, regs=0xffffffc00ceeb700, meta=0xffffffec009bade8
<kfence_metadata+54208>, type=<optimized out>) at mm/kfence/report.c:279
#8 0xffffffebfe1d1630 in kfence_handle_page_fault (addr=18446743558311194624,
is_write=false, regs=0xffffffc00ceeb700) at mm/kfence/core.c:1158
#9 0xffffffebfde6132c in __do_kernel_fault (addr=18446743558311194624, esr=2516582407,
regs=0xffffffc00ceeb700) at arch/arm64/mm/fault.c:414
#10 0xffffffebfde61030 in do_bad_area (far=18446743558311194624,
esr=18446743799048613632, regs=0x0) at arch/arm64/mm/fault.c:498
#11 0xffffffebfef41284 in do_translation_fault (far=18446743799048613632,
esr=18446743799048613632, regs=0x0) at arch/arm64/mm/fault.c:726
#12 0xffffffebfde609dc in do_mem_abort (far=18446743558311194624, esr=2516582407,
regs=0xffffffc00ceeb700) at arch/arm64/mm/fault.c:866
#13 0xffffffebfef28714 in el1_abort (regs=0xffffffc00ceeb700, esr=18446743799048613632)
at arch/arm64/kernel/entry-common.c:370
#14 0xffffffebfef2869c in el1h_64_sync_handler (regs=0xffffffc00ceeaf00) at
arch/arm64/kernel/entry-common.c:430
#15 0xffffffebfde11298 in el1h_64_sync () at arch/arm64/kernel/entry.S:580
crash> info threads
Id Target Id Frame
* 1 664 rpmsg-spi-cp (stack 0) 0xffffffebfdfffb84 in crash_notes_save_regs
(regs=0xffffffc00ceeaf00) at arch/arm64/include/asm/crash_notes.h:61
2 664 rpmsg-spi-cp (stack 1) ex_handler_load_unaligned_zeropad
(ex=0xffffffebff67e8a8, regs=0xffffffc00ceeb980) at arch/arm64/mm/extable.c:45
3 664 rpmsg-spi-cp (stack 2) load_unaligned_zeropad (addr=0xffffff87ffdd3000) at
arch/arm64/include/asm/word-at-a-time.h:61
crash> threads 2
crash: command not found: threads
crash> thread 2
[Switching to thread 2 (664 rpmsg-spi-cp)]
#0 ex_handler_load_unaligned_zeropad (ex=0xffffffebff67e8a8, regs=0xffffffc00ceeb980) at
arch/arm64/mm/extable.c:45
warning: 45 arch/arm64/mm/extable.c: 没有那个文件或目录
crash> gdb bt
#0 ex_handler_load_unaligned_zeropad (ex=0xffffffebff67e8a8, regs=0xffffffc00ceeb980) at
arch/arm64/mm/extable.c:45
#1 fixup_exception (regs=0xffffffc00ceeb980) at arch/arm64/mm/extable.c:74
#2 0xffffffebfde611ac in __do_kernel_fault (addr=18446743558311194624, esr=2516582407,
regs=0xffffffc00ceeb980) at arch/arm64/mm/fault.c:388
#3 0xffffffebfde61030 in do_bad_area (far=18446743558311194624,
esr=18446743987800238248, regs=0x419) at arch/arm64/mm/fault.c:498
#4 0xffffffebfef41284 in do_translation_fault (far=18446743987800238248,
esr=18446743987800238248, regs=0x419) at arch/arm64/mm/fault.c:726
#5 0xffffffebfde609dc in do_mem_abort (far=18446743558311194624, esr=2516582407,
regs=0xffffffc00ceeb980) at arch/arm64/mm/fault.c:866
#6 0xffffffebfef28714 in el1_abort (regs=0xffffffc00ceeb980, esr=18446743987800238248)
at arch/arm64/kernel/entry-common.c:370
#7 0xffffffebfef2869c in el1h_64_sync_handler (regs=0xffffffebff67e8a8) at
arch/arm64/kernel/entry-common.c:430
#8 0xffffffebfde11298 in el1h_64_sync () at arch/arm64/kernel/entry.S:580
Thanks,
Pengfei
-----邮件原件-----
发件人: Tao Liu <ltao(a)redhat.com>
发送时间: 2026年2月12日 16:33
收件人: 李鹏飞 <lipengfei28(a)xiaomi.com>
抄送: lijiang <lijiang(a)redhat.com>; devel(a)lists.crash-utility.osci.io
主题: Re: [Crash-utility] 回复: [External Mail]Re: [PATCH] arm64: Fix broken/incomplete gdb
backtrace and unify output format
[外部邮件] 此邮件来源于小米公司外部,请谨慎处理。若对邮件安全性存疑,请将邮件转发给misec(a)xiaomi.xn--com-iw3ew31vyqjqpq
Hi 李鹏飞,
Thanks for share your outputs, which makes it more clear for me to
understand what is going on.
On Fri, Feb 6, 2026 at 10:53 PM 李鹏飞 <lipengfei28(a)xiaomi.com> wrote:
>
> HI Lianbo
>
>
>
> without the patch:
>
> crash> PID: 664 TASK: ffffff8022d30040 CPU: 3 COMMAND:
"rpmsg-spi-cp"
>
> #0 [ffffffc00ceeb1b0] crash_notes_save_panic_cpu at ffffffebfdfffb80
>
> #1 [ffffffc00ceeb1e0] atomic_notifier_call_chain at ffffffebfdf11788
>
> #2 [ffffffc00ceeb2a0] panic at ffffffebfded26c8
>
> #3 [ffffffc00ceeb2f0] add_taint at ffffffebfded2b7c
>
> #4 [ffffffc00ceeb540] kfence_report_error at ffffffebfe1d2d90
>
> #5 [ffffffc00ceeb5a0] kfence_handle_page_fault at ffffffebfe1d162c
>
> #6 [ffffffc00ceeb5f0] __do_kernel_fault at ffffffebfde61328
>
> #7 [ffffffc00ceeb640] do_bad_area at ffffffebfde6102c
>
> #8 [ffffffc00ceeb670] do_translation_fault at ffffffebfef41280
>
> #9 [ffffffc00ceeb680] do_mem_abort at ffffffebfde609d8
>
> #10 [ffffffc00ceeb6c0] el1_abort at ffffffebfef28710
>
> #11 [ffffffc00ceeb6f0] el1h_64_sync_handler at ffffffebfef28698
>
> #12 [ffffffc00ceeb830] el1h_64_sync at ffffffebfde11294
>
> #13 [ffffffc00ceeb850] fixup_exception at ffffffebfde60850
>
> #14 [ffffffc00ceeb870] __do_kernel_fault at ffffffebfde611a8
>
> #15 [ffffffc00ceeb8c0] do_bad_area at ffffffebfde6102c
>
> #16 [ffffffc00ceeb8f0] do_translation_fault at ffffffebfef41280
>
> #17 [ffffffc00ceeb900] do_mem_abort at ffffffebfde609d8
>
> #18 [ffffffc00ceeb940] el1_abort at ffffffebfef28710
>
> #19 [ffffffc00ceeb970] el1h_64_sync_handler at ffffffebfef28698
>
> #20 [ffffffc00ceebab0] el1h_64_sync at ffffffebfde11294
>
> #21 [ffffffc00ceebad0] strscpy at ffffffebfef1bbc0
>
> #22 [ffffffc00ceebb50] f2fs_fill_dentries at ffffffebfe3f7b9c
>
> #23 [ffffffc00ceebbe0] f2fs_read_inline_dir at ffffffebfe429670
>
> #24 [ffffffc00ceebca0] f2fs_readdir at ffffffebfe3f7f70
>
> #25 [ffffffc00ceebd00] iterate_dir at ffffffebfe232814
>
> #26 [ffffffc00ceebd70] rpmsgfs_readdir_handler at ffffffec0226ed78
[rpmsg_fs_server]
>
> #27 [ffffffc00ceebda0] rpmsgfs_callback at ffffffec0226e1fc [rpmsg_fs_server]
>
> #28 [ffffffc00ceebdd0] rpmsg_port_rx_callback at ffffffec019f7954 [rpmsg_port]
>
> #29 [ffffffc00ceebe10] rpmsg_port_spi_thread at ffffffec01ee6d1c [rpmsg_port_spi]
>
> #30 [ffffffc00ceebe70] kthread at ffffffebfdf100a8
>
> crash: input line exceeds maximum of 1500 bytes
>
> crash> gdb bt
>
> #0 0xffffffebfdfffb84 in crash_notes_save_regs (regs=0xffffffc00ceeaf00) at
arch/arm64/include/asm/crash_notes.h:61
>
> #1 crash_notes_save_this_cpu (type=CRASH_NOTE_CRASHING, cpu=<optimized out>)
at kernel/crash_notes.c:56
>
> #2 crash_notes_save_panic_cpu (this=<optimized out>, event=<optimized
out>, ptr=<optimized out>) at kernel/crash_notes.c:121
>
> #3 0xffffffebfdf1178c in notifier_call_chain (nl=<optimized out>,
nr_to_call=-13, nr_calls=0x0, val=<optimized out>, v=<optimized out>) at
kernel/notifier.c:87
>
> #4 atomic_notifier_call_chain (nh=<optimized out>, val=0,
v=0xffffffec0055d510 <panic[buf]>) at kernel/notifier.c:225
>
> #5 0xffffffebfded26cc in panic (fmt=0xffffffebff2a7f50 "panic_on_taint set
...") at kernel/panic.c:368
>
> #6 0xffffffebfded2b80 in add_taint (flag=5, lockdep_ok=<optimized out>) at
kernel/panic.c:552
>
> #7 0xffffffebfe1d2d94 in kfence_report_error (address=<optimized out>,
is_write=<optimized out>, regs=0xffffffc00ceeb700, meta=0xffffffec009bade8
<kfence_metadata+54208>, type=<optimized out>) at mm/kfence/report.c:279
>
> #8 0xffffffebfe1d1630 in kfence_handle_page_fault (addr=18446743558311194624,
is_write=false, regs=0xffffffc00ceeb700) at mm/kfence/core.c:1158
>
> #9 0xffffffebfde6132c in __do_kernel_fault (addr=18446743558311194624,
esr=2516582407, regs=0xffffffc00ceeb700) at arch/arm64/mm/fault.c:414
>
> #10 0xffffffebfde61030 in do_bad_area (far=18446743558311194624,
esr=18446743799048613632, regs=0x0) at arch/arm64/mm/fault.c:498
>
> #11 0xffffffebfef41284 in do_translation_fault (far=18446743799048613632,
esr=18446743799048613632, regs=0x0) at arch/arm64/mm/fault.c:726
>
> #12 0xffffffebfde609dc in do_mem_abort (far=18446743558311194624, esr=2516582407,
regs=0xffffffc00ceeb700) at arch/arm64/mm/fault.c:866
>
> #13 0xffffffebfef28714 in el1_abort (regs=0xffffffc00ceeb700,
esr=18446743799048613632) at arch/arm64/kernel/entry-common.c:370
>
> #14 0xffffffebfef2869c in el1h_64_sync_handler (regs=0xffffffc00ceeaf00) at
arch/arm64/kernel/entry-common.c:430
>
> #15 0xffffffebfde11298 in el1h_64_sync () at arch/arm64/kernel/entry.S:580
>
>
>
> with the patch:
>
> bt
>
> PID: 664 TASK: ffffff8022d30040 CPU: 3 COMMAND: "rpmsg-spi-cp"
>
> #0 [ffffffc00ceeb1b0] crash_notes_save_panic_cpu at ffffffebfdfffb80
>
> PC: ffffffebfdfffb84 [crash_notes_save_panic_cpu+376]
>
> LR: ffffffebfdfffa3c [crash_notes_save_panic_cpu+48]
>
> SP: ffffffc00ceeaf00 PSTATE: 800000c5
>
> X29: ffffffc00ceeb1b0 X28: ffffff8022d30040 X27: ffffff87ffdd3000
>
> X26: 0000000000000000 X25: ffffffebff229900 X24: 000000000000002c
>
> X23: 0000000000000000 X22: 000000000000000e X21: 0000000000000000
>
> X20: 0000000000000298 X19: fffffffdefe10568 X18: ffffffc00bf550e8
>
> X17: 000000002a4cec24 X16: 000000002a4cec24 X15: 00000000b53ba18c
>
> X14: 000000002d3b6348 X13: ffffffc00ceeaf58 X12: ffffffc00ceeaf50
>
> X11: ffffffc00ceeaf48 X10: ffffffc00ceeaf40 X9: ffffffc00ceeaf60
>
> X8: ffffffc00ceeaf00 X7: 0000000000000000 X6: 000000000000003f
>
> X5: 0000000000000040 X4: 0000000000000000 X3: 0000000000000010
>
> X2: 0000000000000000 X1: ffffffc00ceeaf00 X0: ffffffc00ceeaf00
>
> #1 [ffffffc00ceeb1e0] atomic_notifier_call_chain at ffffffebfdf11788
>
> #2 [ffffffc00ceeb2a0] panic at ffffffebfded26c8
>
> #3 [ffffffc00ceeb2f0] add_taint at ffffffebfded2b7c
>
> #4 [ffffffc00ceeb540] kfence_report_error at ffffffebfe1d2d90
>
> #5 [ffffffc00ceeb5a0] kfence_handle_page_fault at ffffffebfe1d162c
>
> #6 [ffffffc00ceeb5f0] __do_kernel_fault at ffffffebfde61328
>
> #7 [ffffffc00ceeb640] do_bad_area at ffffffebfde6102c
>
> #8 [ffffffc00ceeb670] do_translation_fault at ffffffebfef41280
>
> #9 [ffffffc00ceeb680] do_mem_abort at ffffffebfde609d8
>
> #10 [ffffffc00ceeb6c0] el1_abort at ffffffebfef28710
>
> #11 [ffffffc00ceeb6f0] el1h_64_sync_handler at ffffffebfef28698
>
> #12 [ffffffc00ceeb830] el1h_64_sync at ffffffebfde11294
>
> PC: ffffffebfde60854 [fixup_exception+176]
>
> LR: ffffffebfde607c0 [fixup_exception+28]
>
> SP: ffffffc00ceeb850 PSTATE: 80400005
>
> X29: ffffffc00ceeb850 X28: ffffff8022d30040 X27: 0000000000000001
>
> X26: 0000000000000004 X25: 0000000000000002 X24: 0000000000000001
>
> X23: ffffffebff323a28 X22: 0000000094000000 X21: 0000000096000007
>
> X20: ffffffc00ceeb980 X19: ffffffc00ceeb980 X18: ffffffc00bf55088
>
> X17: 0000000016c516ce X16: 0000000016c516ce X15: 000000000d5a9aa6
>
> X14: 0000000000000196 X13: ffffffc00cee8000 X12: ffffffc00ceec000
>
> X11: f2a803cac12a3900 X10: ffffff87ffdd3000 X9: 0000000000000000
>
> X8: 000000000000000a X7: 0000000000000000 X6: ffffffebfde24574
>
> X5: 0000000000000004 X4: ffffffebfeefe7f4 X3: 000000000000000c
>
> X2: 0000000000000419 X1: ffffffebff67e8a8 X0: ffffffebff67e8a8
>
> #13 [ffffffc00ceeb850] fixup_exception at ffffffebfde60850
>
> #14 [ffffffc00ceeb870] __do_kernel_fault at ffffffebfde611a8
>
> #15 [ffffffc00ceeb8c0] do_bad_area at ffffffebfde6102c
>
> #16 [ffffffc00ceeb8f0] do_translation_fault at ffffffebfef41280
>
> #17 [ffffffc00ceeb900] do_mem_abort at ffffffebfde609d8
>
> #18 [ffffffc00ceeb940] el1_abort at ffffffebfef28710
>
> #19 [ffffffc00ceeb970] el1h_64_sync_handler at ffffffebfef28698
>
> #20 [ffffffc00ceebab0] el1h_64_sync at ffffffebfde11294
>
> PC: ffffffebfef1bbc4 [strscpy+40]
>
> LR: ffffffec0226f63c [rpmsgfs_filldir+80]
>
> SP: ffffffc00ceebad0 PSTATE: 20400005
>
> X29: ffffffc00ceebad0 X28: 0000000000000001 X27: 0000000000000001
>
> X26: 0000000000000004 X25: 0000000000000002 X24: 0000000000000001
>
> X23: ffffffc00ceebbb0 X22: 0000000000000000 X21: ffffff805aeae1bb
>
> X20: 0000000000000000 X19: ffffffc00ceebd48 X18: ffffffc00bf55050
>
> X17: 00000000b1edbef0 X16: 00000000b1edbef0 X15: 000000000d5a9aa6
>
> X14: 0000000000000196 X13: ffffff805aeae1a7 X12: 0000000000001378
>
> X11: ffffff87ffdd3000 X10: adacafaea9a8abaa X9: 0000000000000100
>
> X8: fefefefefefefeff X7: 0000000000000000 X6: ffffffebfde24574
>
> X5: 0000000000000004 X4: 0000000000000192 X3: 0000000000000001
>
> X2: 00000000000006c0 X1: ffffff87ffdd2f00 X0: ffffff80299f9030
>
> #21 [ffffffc00ceebad0] strscpy at ffffffebfef1bbc0
>
> #22 [ffffffc00ceebb50] f2fs_fill_dentries at ffffffebfe3f7b9c
>
> #23 [ffffffc00ceebbe0] f2fs_read_inline_dir at ffffffebfe429670
>
> #24 [ffffffc00ceebca0] f2fs_readdir at ffffffebfe3f7f70
>
> #25 [ffffffc00ceebd00] iterate_dir at ffffffebfe232814
>
> #26 [ffffffc00ceebd70] rpmsgfs_readdir_handler at ffffffec0226ed78
[rpmsg_fs_server]
>
> #27 [ffffffc00ceebda0] rpmsgfs_callback at ffffffec0226e1fc [rpmsg_fs_server]
>
> #28 [ffffffc00ceebdd0] rpmsg_port_rx_callback at ffffffec019f7954 [rpmsg_port]
>
> #29 [ffffffc00ceebe10] rpmsg_port_spi_thread at ffffffec01ee6d1c [rpmsg_port_spi]
>
> #30 [ffffffc00ceebe70] kthread at ffffffebfdf100a8
>
From your "crash bt" outputs, there are 3 registers outputs:
output 1) PC: ffffffebfdfffb84 [crash_notes_save_panic_cpu+376] ...
X29:<some_value> X28:<some_value>...
output 2) PC: ffffffebfde60854 [fixup_exception+176] ...
X29:<some_value> X28:<some_value>...
output 3) PC: ffffffebfef1bbc4 [strscpy+40] ... X29:<some_value>
X28:<some_value>...
For gdb stack unwinding (gdb bt), we do it by feeding the registers
values into gdb, and ask it to unwind all the stacks. So if we feed
the register values of output 1, aka the "PC: ffffffebfdfffb84
[crash_notes_save_panic_cpu+376] ... X29:<some_value>
X28:<some_value>..." one, gdb will unwind the stacks from there and we
will get the following as you posted:
crash> gdb bt
#0 0xffffffebfdfffb84 in crash_notes_save_regs
(regs=0xffffffc00ceeaf00) at arch/arm64/include/asm/crash_notes.h:61
#1 crash_notes_save_this_cpu (type=CRASH_NOTE_CRASHING,
cpu=<optimized out>) at kernel/crash_notes.c:56
...
#14 0xffffffebfef2869c in el1h_64_sync_handler
(regs=0xffffffc00ceeaf00) at arch/arm64/kernel/entry-common.c:430
#15 0xffffffebfde11298 in el1h_64_sync () at arch/arm64/kernel/entry.S:580
This is totally fine because that's all the stacks we can get from
register output 1. If you want further stacks, just feed the register
output 2 to gdb and ask it to unwind, and you can get all other
stacks.
Currenlty we do it by switching to stacks of output 2 or 3 as:
crash> info threads
crash> thread 2
crash> gdb bt
then you can view the stacks of register output 2, similar as output 3.
>
>
> crash> gdb bt
>
> #0 0xffffffebfdfffb84 in crash_notes_save_regs (regs=0xffffffc00ceeaf00) at
arch/arm64/include/asm/crash_notes.h:61
>
> #1 crash_notes_save_this_cpu (type=CRASH_NOTE_CRASHING,
cpu=<optimized out>) at kernel/crash_notes.c:56
>
> #2 crash_notes_save_panic_cpu (this=<optimized out>,
event=<optimized out>, ptr=<optimized out>) at kernel/crash_notes.c:121
>
> #3 0xffffffebfdf1178c in notifier_call_chain (nl=<optimized out>,
nr_to_call=-13, nr_calls=0x0, val=<optimized out>, v=<optimized out>) at
kernel/notifier.c:87
>
> #4 atomic_notifier_call_chain (nh=<optimized out>,
val=0, v=0xffffffec0055d510 <panic[buf]>) at kernel/notifier.c:225
>
> #5 0xffffffebfded26cc in panic (fmt=0xffffffebff2a7f50 "panic_on_taint set
...") at kernel/panic.c:368
>
> #6 0xffffffebfded2b80 in add_taint (flag=5, lockdep_ok=<optimized out>) at
kernel/panic.c:552
>
> #7 0xffffffebfe1d2d94 in kfence_report_error (address=<optimized out>,
is_write=<optimized out>, regs=0xffffffc00ceeb700, meta=0xffffffec009bade8
<kfence_metadata+54208>, type=<optimized out>) at mm/kfence/report.c:279
>
> #8 0xffffffebfe1d1630 in kfence_handle_page_fault (addr=18446743558311194624,
is_write=false, regs=0xffffffc00ceeb700) at mm/kfence/core.c:1158
>
> #9 0xffffffebfde6132c in __do_kernel_fault (addr=18446743558311194624,
esr=2516582407, regs=0xffffffc00ceeb700) at arch/arm64/mm/fault.c:414
>
> #10 0xffffffebfde61030 in do_bad_area (far=18446743558311194624,
esr=18446743799048613632, regs=0x0) at arch/arm64/mm/fault.c:498
>
> #11 0xffffffebfef41284 in do_translation_fault (far=18446743799048613632,
esr=18446743799048613632, regs=0x0) at arch/arm64/mm/fault.c:726
>
> #12 0xffffffebfde609dc in do_mem_abort (far=18446743558311194624, esr=2516582407,
regs=0xffffffc00ceeb700) at arch/arm64/mm/fault.c:866
>
> #13 0xffffffebfef28714 in el1_abort (regs=0xffffffc00ceeb700,
esr=18446743799048613632) at arch/arm64/kernel/entry-common.c:370
>
> #14 0xffffffebfef2869c in el1h_64_sync_handler (regs=0xffffffc00ceeaf00) at
arch/arm64/kernel/entry-common.c:430
>
> #15 0xffffffebfde11298 in el1h_64_sync () at arch/arm64/kernel/entry.S:580
>
> #16 ex_handler_load_unaligned_zeropad
(ex=0xffffffebff67e8a8, regs=0xffffffc00ceeb980) at arch/arm64/mm/extable.c:45
>
> #17 fixup_exception (regs=0xffffffc00ceeb980) at
arch/arm64/mm/extable.c:74
>
> #18 0xffffffebfde611ac in __do_kernel_fault (addr=18446743558311194624,
esr=2516582407, regs=0xffffffc00ceeb980) at arch/arm64/mm/fault.c:388
>
> #19 0xffffffebfde61030 in do_bad_area (far=18446743558311194624,
esr=18446743987800238248, regs=0x419) at arch/arm64/mm/fault.c:498
>
> #20 0xffffffebfef41284 in do_translation_fault (far=18446743987800238248,
esr=18446743987800238248, regs=0x419) at arch/arm64/mm/fault.c:726
>
> #21 0xffffffebfde609dc in do_mem_abort (far=18446743558311194624, esr=2516582407,
regs=0xffffffc00ceeb980) at arch/arm64/mm/fault.c:866
>
> #22 0xffffffebfef28714 in el1_abort (regs=0xffffffc00ceeb980,
esr=18446743987800238248) at arch/arm64/kernel/entry-common.c:370
>
> #23 0xffffffebfef2869c in el1h_64_sync_handler (regs=0xffffffebff67e8a8) at
arch/arm64/kernel/entry-common.c:430
>
> #24 0xffffffebfde11298 in el1h_64_sync () at arch/arm64/kernel/entry.S:580
>
>
>
> #25 load_unaligned_zeropad (addr=0xffffff87ffdd3000) at
arch/arm64/include/asm/word-at-a-time.h:61
>
> #26 strscpy (dest=0xffffff80299f9030
"..\250\251\256\257\254\255\252\253\250\251\256\257\254\255\252\253\250\251\256\257\254\255\252\253\250\251\256\257\254\255\252\253\250\251\256\257\254\255\252\253\250\251\256\257\254\255\252\253\250\251\256\257\254\255\252\253\250\251\256\257\254\255\252\253\250\251\256\257\254\255\252\253\250\251\256\257\254\255\252\253\250\251\256\257\254\255\252\253\250\251\256\257\254\255\252\253\250\251\256\257\254\255\252\253\250\251\256\257\254\255\252\253\250\251\256\257\254\255\252\253\250\251\256\257\254\255\252\253\250\251\256\257\254\255\252\253\250\251\256\257\254\255\252\253\250\251\256\257\254\255\252\253\250\251\256\257\254\255\252\253\250\251\256\257\254\255\252\253\250\251\256\257\254\255\252\253\250\251\256\257\254\255\252\253\250\251\256\257\254\255\252\253\250\251\256\257\254\255\252\253\250\251\256\257\254\255\252\253\250\251\256\257\254\255\252\253\250\251\256\257\254\255\252\253\250\251\256\257\254\255\252\253\250\251\256\257\254\255\252\253\250\251\256\257\254\255\252\253\250\251\256\257\254\255"...,
src=0xffffff87ffdd2f00
"..\250\251\256\257\254\255\252\253\250\251\256\257\254\255\252\253\250\251\256\257\254\255\252\253\250\251\256\257\254\255\252\253\250\251\256\257\254\255\252\253\250\251\256\257\254\255\252\253\250\251\256\257\254\255\252\253\250\251\256\257\254\255\252\253\250\251\256\257\254\255\252\253\250\251\256\257\254\255\252\253\250\251\256\257\254\255\252\253\250\251\256\257\254\255\252\253\250\251\256\257\254\255\252\253\250\251\256\257\254\255\252\253\250\251\256\257\254\255\252\253\250\251\256\257\254\255\252\253\250\251\256\257\254\255\252\253\250\251\256\257\254\255\252\253\250\251\256\257\254\255\252\253\250\251\256\257\254\255\252\253\250\251\256\257\254\255\252\253\250\251\256\257\254\255\252\253\250\251\256\257\254\255\252\253\250\251\256\257\254\255\252\253\250\251\256\257\254\255\252\253\250\251\256\257\254\255\252\253\250\251\256\257\254\255\252\253\250\251\256\257\254\255\252\253\250\251\256\257\254\255\252\253\250\251\256\257\254\255\252\253\250\251\256\257\254\255\252\253\250\251\256\257\254\255",
count=1728) at lib/string.c:215
>
> #27 0xffffffec0226f63c in _Z7strscpyPcU17pass_object_size1PKcU17pass_object_size1m
(p=0xffffff80299f9030
"..\250\251\256\257\254\255\252\253\250\251\256\257\254\255\252\253\250\251\256\257\254\255\252\253\250\251\256\257\254\255\252\253\250\251\256\257\254\255\252\253\250\251\256\257\254\255\252\253\250\251\256\257\254\255\252\253\250\251\256\257\254\255\252\253\250\251\256\257\254\255\252\253\250\251\256\257\254\255\252\253\250\251\256\257\254\255\252\253\250\251\256\257\254\255\252\253\250\251\256\257\254\255\252\253\250\251\256\257\254\255\252\253\250\251\256\257\254\255\252\253\250\251\256\257\254\255\252\253\250\251\256\257\254\255\252\253\250\251\256\257\254\255\252\253\250\251\256\257\254\255\252\253\250\251\256\257\254\255\252\253\250\251\256\257\254\255\252\253\250\251\256\257\254\255\252\253\250\251\256\257\254\255\252\253\250\251\256\257\254\255\252\253\250\251\256\257\254\255\252\253\250\251\256\257\254\255\252\253\250\251\256\257\254\255\252\253\250\251\256\257\254\255\252\253\250\251\256\257\254\255\252\253\250\251\256\257\254\255\252\253\250\251\256\257\254\255\252\253\250\251\256\257\254\255"...,
q=0xffffff87ffdd2f00
"..\250\251\256\257\254\255\252\253\250\251\256\257\254\255\252\253\250\251\256\257\254\255\252\253\250\251\256\257\254\255\252\253\250\251\256\257\254\255\252\253\250\251\256\257\254\255\252\253\250\251\256\257\254\255\252\253\250\251\256\257\254\255\252\253\250\251\256\257\254\255\252\253\250\251\256\257\254\255\252\253\250\251\256\257\254\255\252\253\250\251\256\257\254\255\252\253\250\251\256\257\254\255\252\253\250\251\256\257\254\255\252\253\250\251\256\257\254\255\252\253\250\251\256\257\254\255\252\253\250\251\256\257\254\255\252\253\250\251\256\257\254\255\252\253\250\251\256\257\254\255\252\253\250\251\256\257\254\255\252\253\250\251\256\257\254\255\252\253\250\251\256\257\254\255\252\253\250\251\256\257\254\255\252\253\250\251\256\257\254\255\252\253\250\251\256\257\254\255\252\253\250\251\256\257\254\255\252\253\250\251\256\257\254\255\252\253\250\251\256\257\254\255\252\253\250\251\256\257\254\255\252\253\250\251\256\257\254\255\252\253\250\251\256\257\254\255\252\253\250\251\256\257\254\255",
size=<optimized out>) at ../kernel-modules/fs/rpmsgfs/rpmsg_fs_server.c:602
>
> #28 rpmsgfs_filldir (ctx=0xffffffc00ceebd48,
name=0xffffff87ffdd2f00
"..\250\251\256\257\254\255\252\253\250\251\256\257\254\255\252\253\250\251\256\257\254\255\252\253\250\251\256\257\254\255\252\253\250\251\256\257\254\255\252\253\250\251\256\257\254\255\252\253\250\251\256\257\254\255\252\253\250\251\256\257\254\255\252\253\250\251\256\257\254\255\252\253\250\251\256\257\254\255\252\253\250\251\256\257\254\255\252\253\250\251\256\257\254\255\252\253\250\251\256\257\254\255\252\253\250\251\256\257\254\255\252\253\250\251\256\257\254\255\252\253\250\251\256\257\254\255\252\253\250\251\256\257\254\255\252\253\250\251\256\257\254\255\252\253\250\251\256\257\254\255\252\253\250\251\256\257\254\255\252\253\250\251\256\257\254\255\252\253\250\251\256\257\254\255\252\253\250\251\256\257\254\255\252\253\250\251\256\257\254\255\252\253\250\251\256\257\254\255\252\253\250\251\256\257\254\255\252\253\250\251\256\257\254\255\252\253\250\251\256\257\254\255\252\253\250\251\256\257\254\255\252\253\250\251\256\257\254\255\252\253\250\251\256\257\254\255\252\253\250\251\256\257\254\255",
namelen=<optimized out>, offset=<optimized out>, ino=<optimized out>,
d_type=4) at ../kernel-modules/fs/rpmsgfs/rpmsg_fs_server.c:605
I see what you were doing, is to merge all stacks into one, so all
been outputted with a single "gdb bt". This looks cleaner though, but
it will break the function of "frame X". Without your patch, we can
ask gdb to move frame as:
crash> gdb bt
#0 0xffffffff972021a2 in crash_setup_regs
(newregs=0xffffa97dc0bbfc18, oldregs=0x0) at
./arch/x86/include/asm/kexec.h:114
#1 __crash_kexec (regs=regs@entry=0x0) at
kernel/crash_core.c:119
#2 0xffffffff980fe85d in panic (fmt=fmt@entry=0xffffffff98b8a823
"sysrq triggered crash\n") at kernel/panic.c:373
#3 0xffffffff97abe1ba in sysrq_handle_crash (key=<optimized out>)
at drivers/tty/sysrq.c:154
#4 0xffffffff98176980 in __handle_sysrq (key=<optimized out>,
check_mask=check_mask@entry=false) at drivers/tty/sysrq.c:612
#5 0xffffffff97abee79 in write_sysrq_trigger (file=<optimized out>,
buf=<optimized out>, count=2, ppos=<optimized out>) at
drivers/tty/sysrq.c:1181
#6 0xffffffff975680ba in pde_write (pde=0xffff96b7d1563bc0,
file=0xffffa97dc0bbfcc0, buf=<optimized out>, count=<optimized out>,
ppos=<optimized out>) at fs/proc/inode.c:334
...
#12 0xffffffff9820012f in entry_SYSCALL_64 () at arch/x86/entry/entry_64.S:121
crash> frame 2
#2 0xffffffff980fe85d in panic (fmt=fmt@entry=0xffffffff98b8a823
"sysrq triggered crash\n") at kernel/panic.c:373
373 __crash_kexec(NULL);
crash> p fmt
$1 = 0xffffffff98b8a823 "sysrq triggered crash\n"
With your patch, all stacks been merged together and frames are
re-numbered, so we get a longer stacks:
#0 0xffffffff972021a2 in crash_setup_regs
(newregs=0xffffa97dc0bbfc18, oldregs=0x0) at
./arch/x86/include/asm/kexec.h:114
#1 __crash_kexec (regs=regs@entry=0x0) at
kernel/crash_core.c:119
#2 0xffffffff980fe85d in panic (fmt=fmt@entry=0xffffffff98b8a823
"sysrq triggered crash\n") at kernel/panic.c:373
#3 0xffffffff97abe1ba in sysrq_handle_crash (key=<optimized out>)
at drivers/tty/sysrq.c:154
#4 0xffffffff98176980 in __handle_sysrq (key=<optimized out>,
check_mask=check_mask@entry=false) at drivers/tty/sysrq.c:612
#5 0xffffffff97abee79 in write_sysrq_trigger (file=<optimized out>,
buf=<optimized out>, count=2, ppos=<optimized out>) at
drivers/tty/sysrq.c:1181
#6 0xffffffff975680ba in pde_write (pde=0xffff96b7d1563bc0,
file=0xffffa97dc0bbfcc0, buf=<optimized out>, count=<optimized out>,
ppos=<optimized out>) at fs/proc/inode.c:334
...
#12 0xffffffff9820012f in entry_SYSCALL_64 () at arch/x86/entry/entry_64.S:121
#13 0xffffffff9709e025 in machine_kexec (image=0xffff96b7d2600c00)
at arch/x86/kernel/machine_kexec_64.c:391
...
#23 0xffffffff981b4982 in do_syscall_x64 (regs=0xffffa97dc0bbff58,
nr=1) at arch/x86/entry/common.c:52
#24 do_syscall_64 (regs=0xffffa97dc0bbff58,
nr=1) at arch/x86/entry/common.c:83
#25 0xffffffff9820012f in entry_SYSCALL_64 () at arch/x86/entry/entry_64.S:121
crash> frame 23
gdb: gdb request failed: frame 23
crash> p regs
p: gdb request failed: p regs
The failing is expected, because gdb internally doesn't know there is
a frame 23, it is re-numbered by your hacking at a upper level. Please
see gdb bt multi-stack support in [1].
[1]:
https://www.mail-archive.com/devel@lists.crash-utility.osci.io/msg01491.html
Thanks,
Tao Liu
>
>
>
> This patch addresses an issue where the GDB backtrace obtained from crash dumps is
incomplete in certain panic scenarios.
>
> Without this patch, the backtrace stops early in the exception handling path. With
the patch applied, additional frames are preserved, allowing the full call chain to be
reconstructed, which makes root-cause analysis significantly easier.
>
> I have verified the behavior by comparing crash> gdb bt outputs with and without
the patch. With the patch applied, the stack trace correctly includes the exception fixup
path and the original faulting context.
>
> Thanks for your time and review.
>
> Best regards,
> Li Pengfei
>
>
>
>
>
> 发件人: lijiang <lijiang(a)redhat.com>
> 发送时间: 2026年2月4日 17:09
> 收件人: devel(a)lists.crash-utility.osci.io
> 抄送: 李鹏飞 <lipengfei28(a)xiaomi.com>
> 主题: [External Mail]Re: [PATCH] arm64: Fix broken/incomplete gdb backtrace and unify
output format
>
>
>
> [外部邮件] 此邮件来源于小米公司外部,请谨慎处理。若对邮件安全性存疑,请将邮件转发给misec(a)xiaomi.xn--com-iw3ew31vyqjqpq
>
> Hi, Pengfei
>
>
>
> I did the test with your patch, and got an incorrect back trace, Can you also help
double check?
>
>
>
> crash> gdb bt
> #0 0xffffc8c40b0d9b14 in crash_setup_regs
(newregs=newregs@entry=0xffff80008862b638, oldregs=oldregs@entry=0x0) at
./arch/arm64/include/asm/kexec.h:45
> #1 0xffffc8c40b0d9dc4 in __crash_kexec (regs=regs@entry=0x0) at
kernel/crash_core.c:119
> #2 0xffffc8c40aed6a44 in vpanic (fmt=fmt@entry=0xffffc8c40c527558 "sysrq
triggered crash\n", args=<error reading variable: Cannot access memory at address
0x0>) at kernel/panic.c:369
> #3 0xffffc8c40aed6cd0 in panic (fmt=fmt@entry=0xffffc8c40c527558 "sysrq
triggered crash\n") at kernel/panic.c:484
> #4 0xffffc8c40b82a594 in sysrq_handle_crash (key=<optimized out>) at
drivers/tty/sysrq.c:154
> #5 0xffffc8c40b82aee0 in __handle_sysrq (key=99 'c', check_mask=false) at
drivers/tty/sysrq.c:613
> #6 0xffffc8c40b82b6b0 in write_sysrq_trigger (file=<optimized out>,
buf=<optimized out>, count=2, ppos=<optimized out>) at
drivers/tty/sysrq.c:1183
> #7 0xffffc8c40b46bcec in pde_write (pde=0xffff0000c7fa6a80, file=<optimized
out>, buf=<optimized out>, count=<optimized out>, ppos=<optimized
out>) at fs/proc/inode.c:330
> #8 proc_reg_write (file=<optimized out>,
buf=<optimized out>, count=<optimized out>, ppos=<optimized out>) at
fs/proc/inode.c:342
> #9 0xffffc8c40b3ad52c in vfs_write (file=file@entry=0xffff0000c86aff00,
buf=buf@entry=0xaaab1a0c37f0 <error: Cannot access memory at address
0xaaab1a0c37f0>, count=count@entry=2, pos=pos@entry=0xffff80008862ba20) at
fs/read_write.c:681
> #10 0xffffc8c40b3ad9a4 in ksys_write (fd=<optimized out>, buf=0xaaab1a0c37f0
<error: Cannot access memory at address 0xaaab1a0c37f0>, count=2) at
fs/read_write.c:736
> #11 0xffffc8c40b3ada6c in __do_sys_write (fd=<optimized out>,
buf=<optimized out>, count=<optimized out>) at fs/read_write.c:748
> #12 __se_sys_write (fd=<optimized out>,
buf=<optimized out>, count=<optimized out>) at fs/read_write.c:745
> #13 __arm64_sys_write (regs=<optimized out>) at
fs/read_write.c:745
> #14 0xffffc8c40af0cc7c in __invoke_syscall (regs=0xffff80008862beb0,
syscall_fn=<optimized out>) at arch/arm64/kernel/syscall.c:35
> #15 invoke_syscall (regs=regs@entry=0xffff80008862beb0,
scno=<optimized out>, sc_nr=sc_nr@entry=463, syscall_table=<optimized out>) at
arch/arm64/kernel/syscall.c:49
> #16 0xffffc8c40af0cd88 in el0_svc_common (sc_nr=463, syscall_table=<optimized
out>, regs=0xffff80008862beb0, scno=<optimized out>) at
arch/arm64/kernel/syscall.c:132
> #17 do_el0_svc (regs=regs@entry=0xffff80008862beb0) at
arch/arm64/kernel/syscall.c:151
> #18 0xffffc8c40beb9e2c in el0_svc (regs=0xffff80008862beb0) at
arch/arm64/kernel/entry-common.c:879
> #19 0xffffc8c40beba2b0 in el0t_64_sync_handler (regs=<optimized out>) at
arch/arm64/kernel/entry-common.c:898
> #20 0xffffc8c40aed1684 in el0t_64_sync () at arch/arm64/kernel/entry.S:596
> #21 machine_kexec (kimage=<unavailable>) at
arch/arm64/kernel/machine_kexec.c:194
> #22 0xffffc8c40b0d9dd8 in __crash_kexec (regs=regs@entry=0x0) at
kernel/crash_core.c:122
> #23 0xffffc8c40aed6a44 in vpanic (fmt=fmt@entry=0xffffc8c40c527558 "sysrq
triggered crash\n", args=<error reading variable: Cannot access memory at address
0x0>) at kernel/panic.c:369
> #24 0xffffc8c40aed6cd0 in panic (fmt=fmt@entry=0xffffc8c40c527558 "sysrq
triggered crash\n") at kernel/panic.c:484
> #25 0xffffc8c40b82a594 in sysrq_handle_crash (key=<optimized out>) at
drivers/tty/sysrq.c:154
> #26 0xffffc8c40b82aee0 in __handle_sysrq (key=99 'c',
check_mask=<unavailable>) at drivers/tty/sysrq.c:613
> #27 0xffffc8c40b82b6b0 in write_sysrq_trigger (file=<optimized out>,
buf=<optimized out>, count=2, ppos=<optimized out>) at
drivers/tty/sysrq.c:1183
> #28 0xffffc8c40b46bcec in pde_write (pde=0xffff0000c7fa6a80, file=<optimized
out>, buf=<optimized out>, count=<optimized out>, ppos=<optimized
out>) at fs/proc/inode.c:330
> #29 proc_reg_write (file=<optimized out>,
buf=<optimized out>, count=<optimized out>, ppos=<optimized out>) at
fs/proc/inode.c:342
> #30 0xffffc8c40b3ad52c in vfs_write (file=file@entry=0xffff0000c86aff00,
buf=buf@entry=0xaaab1a0c37f0 <error: Cannot access memory at address
0xaaab1a0c37f0>, count=count@entry=2, pos=pos@entry=0xffff80008862ba20) at
fs/read_write.c:681
> #31 0xffffc8c40b3ad9a4 in ksys_write (fd=<optimized out>, buf=0xaaab1a0c37f0
<error: Cannot access memory at address 0xaaab1a0c37f0>, count=2) at
fs/read_write.c:736
> #32 0xffffc8c40b3ada6c in __do_sys_write (fd=<optimized out>,
buf=<optimized out>, count=<optimized out>) at fs/read_write.c:748
> #33 __se_sys_write (fd=<optimized out>,
buf=<optimized out>, count=<optimized out>) at fs/read_write.c:745
> #34 __arm64_sys_write (regs=<optimized out>) at
fs/read_write.c:745
> #35 0xffffc8c40af0cc7c in __invoke_syscall (regs=0xffff80008862beb0,
syscall_fn=<optimized out>) at arch/arm64/kernel/syscall.c:35
> #36 invoke_syscall (regs=regs@entry=0xffff80008862beb0,
scno=<optimized out>, sc_nr=sc_nr@entry=463, syscall_table=<optimized out>) at
arch/arm64/kernel/syscall.c:49
> #37 0xffffc8c40af0cd88 in el0_svc_common (sc_nr=463, syscall_table=<optimized
out>, regs=0xffff80008862beb0, scno=<optimized out>) at
arch/arm64/kernel/syscall.c:132
> #38 do_el0_svc (regs=regs@entry=0xffff80008862beb0) at
arch/arm64/kernel/syscall.c:151
> #39 0xffffc8c40beb9e2c in el0_svc (regs=0xffff80008862beb0) at
arch/arm64/kernel/entry-common.c:879
> #40 0xffffc8c40beba2b0 in el0t_64_sync_handler (regs=<optimized out>) at
arch/arm64/kernel/entry-common.c:898
> #41 0xffffc8c40aed1684 in el0t_64_sync () at arch/arm64/kernel/entry.S:596
>
>
>
>
>
> I can get the correct back trace without the patch:
>
> crash> gdb bt
> #0 0xffffc8c40b0d9b14 in crash_setup_regs
(newregs=newregs@entry=0xffff80008862b638, oldregs=oldregs@entry=0x0) at
./arch/arm64/include/asm/kexec.h:45
> #1 0xffffc8c40b0d9dc4 in __crash_kexec (regs=regs@entry=0x0) at
kernel/crash_core.c:119
> #2 0xffffc8c40aed6a44 in vpanic (fmt=fmt@entry=0xffffc8c40c527558 "sysrq
triggered crash\n", args=<error reading variable: Cannot access memory at address
0x0>) at kernel/panic.c:369
> #3 0xffffc8c40aed6cd0 in panic (fmt=fmt@entry=0xffffc8c40c527558 "sysrq
triggered crash\n") at kernel/panic.c:484
> #4 0xffffc8c40b82a594 in sysrq_handle_crash (key=<optimized out>) at
drivers/tty/sysrq.c:154
> #5 0xffffc8c40b82aee0 in __handle_sysrq (key=99 'c', check_mask=false) at
drivers/tty/sysrq.c:613
> #6 0xffffc8c40b82b6b0 in write_sysrq_trigger (file=<optimized out>,
buf=<optimized out>, count=2, ppos=<optimized out>) at
drivers/tty/sysrq.c:1183
> #7 0xffffc8c40b46bcec in pde_write (pde=0xffff0000c7fa6a80, file=<optimized
out>, buf=<optimized out>, count=<optimized out>, ppos=<optimized
out>) at fs/proc/inode.c:330
> #8 proc_reg_write (file=<optimized out>, buf=<optimized out>,
count=<optimized out>, ppos=<optimized out>) at fs/proc/inode.c:342
> #9 0xffffc8c40b3ad52c in vfs_write (file=file@entry=0xffff0000c86aff00,
buf=buf@entry=0xaaab1a0c37f0 <error: Cannot access memory at address
0xaaab1a0c37f0>, count=count@entry=2, pos=pos@entry=0xffff80008862ba20) at
fs/read_write.c:681
> #10 0xffffc8c40b3ad9a4 in ksys_write (fd=<optimized out>, buf=0xaaab1a0c37f0
<error: Cannot access memory at address 0xaaab1a0c37f0>, count=2) at
fs/read_write.c:736
> #11 0xffffc8c40b3ada6c in __do_sys_write (fd=<optimized out>,
buf=<optimized out>, count=<optimized out>) at fs/read_write.c:748
> #12 __se_sys_write (fd=<optimized out>, buf=<optimized out>,
count=<optimized out>) at fs/read_write.c:745
> #13 __arm64_sys_write (regs=<optimized out>) at fs/read_write.c:745
> #14 0xffffc8c40af0cc7c in __invoke_syscall (regs=0xffff80008862beb0,
syscall_fn=<optimized out>) at arch/arm64/kernel/syscall.c:35
> #15 invoke_syscall (regs=regs@entry=0xffff80008862beb0, scno=<optimized out>,
sc_nr=sc_nr@entry=463, syscall_table=<optimized out>) at
arch/arm64/kernel/syscall.c:49
> #16 0xffffc8c40af0cd88 in el0_svc_common (sc_nr=463, syscall_table=<optimized
out>, regs=0xffff80008862beb0, scno=<optimized out>) at
arch/arm64/kernel/syscall.c:132
> #17 do_el0_svc (regs=regs@entry=0xffff80008862beb0) at
arch/arm64/kernel/syscall.c:151
> #18 0xffffc8c40beb9e2c in el0_svc (regs=0xffff80008862beb0) at
arch/arm64/kernel/entry-common.c:879
> #19 0xffffc8c40beba2b0 in el0t_64_sync_handler (regs=<optimized out>) at
arch/arm64/kernel/entry-common.c:898
> #20 0xffffc8c40aed1684 in el0t_64_sync () at arch/arm64/kernel/entry.S:596
>
>
>
> Anyway, I haven't checked the patch carefully, just tried to test it and found
this error.
>
>
>
> In addition, I would suggest splitting this patch into smaller patches, and each
patch should only do one thing(keep its functionality independent), which will help us to
review it easily.
>
>
>
> Thanks
>
> Lianbo
>
>
>
> On Fri, Jan 30, 2026 at 5:21 PM <devel-request(a)lists.crash-utility.osci.io>
wrote:
>
> Date: Mon, 26 Jan 2026 11:43:42 -0000
> From: lipengfei28(a)xiaomi.com
> Subject: [Crash-utility] [PATCH] arm64: Fix broken/incomplete gdb
> backtrace and unify output format
> To: devel(a)lists.crash-utility.osci.io
> Message-ID: <20260126114342.13119.56270(a)lists.crash-utility.osci.io>
> Content-Type: text/plain; charset="utf-8"
>
> >From 4d832a33ebd80bd109cc5a47f98c6b35fdcbd956 Mon Sep 17 00:00:00 2001
> From: lipengfei28 <lipengfei28(a)xiaomi.com>
> Date: Fri, 23 Jan 2026 16:24:07 +0800
> Subject: [PATCH] arm64: Fix broken/incomplete gdb backtrace and unify output
> format
>
> This patch fixes multiple issues with 'gdb bt' on ARM64, where the
backtrace
> would be interrupted, contain garbage threads, or display fragmented output.
>
> 1. Fix Out-of-Bounds Read in Exception Frame Handling:
> In `arm64_print_exception_frame`, the code previously used `memcpy` to copy
> `sizeof(struct arm64_pt_regs)` bytes from a `struct arm64_stackframe *` source.
> Since `stackframe` is significantly smaller than `pt_regs`, this caused an
> out-of-bounds read, populating the GDB thread registers with stack garbage
> (often resulting in invalid addresses like -3/0xff...fd).
> This is fixed by manually copying only the valid registers (PC, SP, FP, etc.)
> and properly initializing the bitmap.
>
> 2. Bridge the Gap Between IRQ and Process Stacks:
> Previously, GDB unwinding would stop at `call_on_irq_stack` because it could
> not automatically unwind through the assembly trampoline back to the process
> stack.
> Modified `arm64_switch_stack` (and the overflow variant) to "peek" one
frame
> ahead (reading the saved FP/PC of the caller) before registering the new
> GDB substack. This effectively bridges the discontinuity, allowing GDB to
> show frames like `do_interrupt_handler` that were previously missing.
>
> 3. Unify and Format GDB Output:
> Modified `gdb_interface.c` to:
> - Strip "Thread <id>" headers to present a continuous backtrace
similar to
> the native `crash bt`.
> - Renumber stack frames sequentially (e.g., #0 to #30) instead of resetting
> at each stack switch.
> - Add indentation/alignment for frames where GDB omits the address (e.g.,
> inline functions) to improve readability.
>
> 4. Prevent Invalid Thread Creation:
> Added checks to ensure a GDB substack is only created if the Program Counter
> (PC) is non-zero, preventing the display of "corrupt" or empty
threads.
>
> Tested on: Android 6.x ARM64
>
> Signed-off-by: lipengfei28 <lipengfei28(a)xiaomi.com>
> ---
> arm64.c | 117 +++++++++++++++++++++++++++++++++++++------
> gdb_interface.c | 130 +++++++++++++++++++++++++++++++++++++++++++++++-
> 2 files changed, 229 insertions(+), 18 deletions(-)
>
> diff --git a/arm64.c b/arm64.c
> index c125655..f842739 100644
> --- a/arm64.c
> +++ b/arm64.c
> @@ -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,12 @@ 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->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 +3934,12 @@ 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->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 +4273,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 +4342,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 +4630,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++);
> + }
> }
> }
> }
> diff --git a/gdb_interface.c b/gdb_interface.c
> index 9f76f85..d14144e 100644
> --- a/gdb_interface.c
> +++ b/gdb_interface.c
> @@ -16,6 +16,7 @@
> */
>
> #include "defs.h"
> +#include <ctype.h>
>
> #if !defined(GDB_10_2) && !defined(GDB_16_2)
> static void exit_after_gdb_info(void);
> @@ -779,22 +780,53 @@ strip_redirection(char *buf)
> /*
> * Command for passing strings directly to gdb.
> */
> +static void format_and_print_gdb_bt(FILE *input_fp);
> +
> void
> cmd_gdb(void)
> {
> char buf[BUFSIZE];
> char **argv;
> + int i;
>
> argv = STREQ(args[0], "gdb") ? &args[1] : &args[0];
>
> if (*argv == NULL)
> cmd_usage(pc->curcmd, SYNOPSIS);
>
> + if (STREQ(*argv, "bt")) {
> + FILE *tmp_fp;
> +
> + if ((tmp_fp = tmpfile()) == NULL) {
> + error(FATAL, "cannot create temporary file for GDB
output\n");
> + }
> +
> + strcpy(buf, "thread apply all bt");
> + /* Append any arguments that were passed to 'bt' */
> + /* args[0] is "gdb", args[1] is "bt", so options
start at index 2 */
> + for (i = 2; i < argcnt; i++) {
> + strcat(buf, " ");
> + strcat(buf, args[i]);
> + }
> +
> + if (!gdb_pass_through(buf, tmp_fp, GNU_RETURN_ON_ERROR)) {
> + fclose(tmp_fp);
> + error(INFO, "gdb request failed: %s\n", buf);
> + return;
> + }
> +
> + rewind(tmp_fp);
> + format_and_print_gdb_bt(tmp_fp);
> +
> + fclose(tmp_fp);
> + return;
> + }
> +
> if (STREQ(*argv, "set") && argv[1]) {
> /*
> * Intercept set commands in case something has to be done
> - * here or elsewhere.
> - */
> + * here or elsewhere.
> + */
> if (STREQ(argv[1], "gdb")) {
> cmd_set();
> return;
> @@ -821,6 +853,100 @@ cmd_gdb(void)
> }
> }
>
> +#define MAX_BT_LINES 1024
> +#define MAX_THREAD_BLOCKS 64
> +
> +/*
> + * Helper function to parse 'thread apply all bt' output, reverse the
> + * thread blocks, and print the result.
> + */
> +static void format_and_print_gdb_bt(FILE *input_fp)
> +{
> + char *lines[MAX_BT_LINES];
> + int line_count = 0;
> + int thread_starts[MAX_THREAD_BLOCKS];
> + int thread_count = 0;
> + char line_buffer[BUFSIZE];
> + int i, j;
> + int global_frame_cnt = 0;
> +
> + // Read all lines into memory
> + while (fgets(line_buffer, BUFSIZE, input_fp) && line_count <
MAX_BT_LINES) {
> + if (strstr(line_buffer, "Thread ") == line_buffer) {
> + if (thread_count < MAX_THREAD_BLOCKS) {
> + thread_starts[thread_count++] = line_count;
> + }
> + }
> + lines[line_count] = strdup(line_buffer);
> + if (!lines[line_count]) {
> + error(FATAL, "strdup failed while reading gdb output\n");
> + }
> + line_count++;
> + }
> +
> + if (thread_count == 0) { // If no threads, just print everything as is.
> + for (i = 0; i < line_count; i++) {
> + fputs(lines[i], fp);
> + }
> + } else {
> + // Iterate threads in reverse order to fix the display order
> + for (i = thread_count - 1; i >= 0; i--) {
> + int start_line = thread_starts[i];
> + int end_line = (i == thread_count - 1) ? line_count :
thread_starts[i+1];
> +
> + // Print thread frames, stripping header and renumbering
> + for (j = start_line; j < end_line; j++) {
> + char *line = lines[j];
> + // Skip "Thread " line
> + if (strncmp(line, "Thread ", 7) == 0) continue;
> + // Skip "Backtrace stopped" or similar noise if desired,
> + // but usually GDB prints "Backtrace stopped" at the very
end.
> + // We'll keep it for info unless it's in the middle of our
merge.
> + // Actually, duplicate frames or stops might appear.
> + // For now, simple renumbering.
> +
> + char *ptr = line;
> + while (*ptr == ' ' || *ptr == '\t') ptr++;
> +
> + if (*ptr == '#') {
> + // Frame line: #0 0x...
> + char *rest = ptr + 1;
> + while (isdigit(*rest)) rest++; // Skip old number
> +
> + // Parse content to check for address
> + char *p = rest;
> + while (*p == ' ' || *p == '\t') p++;
> +
> + int has_addr = (strncmp(p, "0x", 2) == 0);
> +
> + // Print number
> + fprintf(fp, "#%-3d", global_frame_cnt++);
> +
> + // Align if address is missing
> + if (!has_addr) {
> + // Align function name with frames that have addresses
> + // 64-bit: 0x... (18 chars) + " in " (4 chars) =
22 chars
> + // 32-bit: 0x... (10 chars) + " in " (4 chars) =
14 chars
> + int width = (machdep->bits == 64) ? 22 : 14;
> + for (int k = 0; k < width; k++) fputc(' ', fp);
> + }
> +
> + fputs(rest, fp);
> + } else {
> + // Other lines (e.g. variable info, code)
> + fputs(line, fp);
> + }
> + }
> + }
> + }
> +
> + // Cleanup
> + for (i = 0; i < line_count; i++) {
> + free(lines[i]);
> + }
> +}
> +
> +
> /*
> * The gdb target_xfer_memory() has a hook installed to re-route
> * all memory accesses back here; reads of 1 or 4 bytes come primarily
> --
> 2.34.1
>
>
#/******本邮件及其附件含有小米公司的保密信息,仅限于发送给上面地址中列出的个人或群组。禁止任何其他人以任何形式使用(包括但不限于全部或部分地泄露、复制、或散发)本邮件中的信息。如果您错收了本邮件,请您立即电话或邮件通知发件人并删除本邮件!
This e-mail and its attachments contain confidential information from XIAOMI, which is
intended only for the person or entity whose address is listed above. Any use of the
information contained herein in any way (including, but not limited to, total or partial
disclosure, reproduction, or dissemination) by persons other than the intended
recipient(s) is prohibited. If you receive this e-mail in error, please notify the sender
by phone or email immediately and delete it!******/#
> --
> Crash-utility mailing list -- devel(a)lists.crash-utility.osci.io
> To unsubscribe send an email to devel-leave(a)lists.crash-utility.osci.io
> https://${domain_name}/admin/lists/devel.lists.crash-utility.osci.io/
> Contribution Guidelines:
https://github.com/crash-utility/crash/wiki
#/******本邮件及其附件含有小米公司的保密信息,仅限于发送给上面地址中列出的个人或群组。禁止任何其他人以任何形式使用(包括但不限于全部或部分地泄露、复制、或散发)本邮件中的信息。如果您错收了本邮件,请您立即电话或邮件通知发件人并删除本邮件!
This e-mail and its attachments contain confidential information from XIAOMI, which is
intended only for the person or entity whose address is listed above. Any use of the
information contained herein in any way (including, but not limited to, total or partial
disclosure, reproduction, or dissemination) by persons other than the intended
recipient(s) is prohibited. If you receive this e-mail in error, please notify the sender
by phone or email immediately and delete it!******/#