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
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
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@redhat.com>
发送时间: 2026年2月4日
17:09
收件人: devel@lists.crash-utility.osci.io
抄送: 李鹏飞 <lipengfei28@xiaomi.com>
主题: [External Mail]Re: [PATCH] arm64: Fix broken/incomplete gdb backtrace and unify output format
[外部邮件]
此邮件来源于小米公司外部,请谨慎处理。若对邮件安全性存疑,请将邮件转发给misec@xiaomi.com进行反馈
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@lists.crash-utility.osci.io>
wrote:
Date: Mon, 26 Jan 2026 11:43:42 -0000
From: lipengfei28@xiaomi.com
Subject: [Crash-utility] [PATCH] arm64: Fix broken/incomplete gdb
backtrace and unify output format
To: devel@lists.crash-utility.osci.io
Message-ID: <20260126114342.13119.56270@lists.crash-utility.osci.io>
Content-Type: text/plain; charset="utf-8"
>From 4d832a33ebd80bd109cc5a47f98c6b35fdcbd956 Mon Sep 17 00:00:00 2001
From: lipengfei28 <lipengfei28@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@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