arm-none-eabi-gdb无SDK裸机汇编中nexti执行bl指令未停步
ARM裸机汇编GDB调试异常问题排查
在无SDK的裸机汇编环境下使用arm-none-eabi-gdb调试时遇到异常:在main函数中对bl指令执行nexti操作,调试器未停步而是直接继续运行;但在main调用的子函数(比如init_pin_output内的函数调用)中执行nexti则完全正常。
相关代码片段
start.s
@ ... @ vector_table @ ... .thumb_func .global reset .align 4 reset: ldr r2, PPB_BASE ldr r1, VTOR_OFFSET add r1, r1, r2 ldr r0, =vector_table str r0, [r1] ldr r1, SRAM_STRIPED_END mov sp, r1 platform_entry: ldr r1, =main blx r1 mov r0, r0 bkpt #0 @ should not return
main.s
.thumb_func .global main .align 4 main: push {lr} @ ... .init_led: movs r0, #25 bl init_pin_output .init_lcd: bl init_screen @ ... @ delay loop @ ... pop {pc} .thumb_func .global init_pin_output .align 4 init_pin_output: push {lr} ldr r1, =out_pin str r0, [r1] ldr r0, out_pin movs r1, #5 @ 5 - SIO bl GPIO_function_select ldr r0, out_pin bl output_enable_pin pop {pc} .align 4 out_pin: .word 0
已尝试的排查操作
- 使用包装函数调用
main,问题依旧; - 执行
backtrace时,GDB输出:Backtrace stopped: previous frame identical to this frame (corrupt stack?); - 查看SDK生成的
.elf文件反汇编,未发现帧指针修改(Thumb模式下该操作无效)。
问题原因与解决方法
这个问题的核心是GDB无法正确识别main函数的栈帧结构,导致nexti指令无法正确跟踪函数调用的断点。
关键原因
- Thumb函数标记与地址对齐问题:虽然代码中添加了
.thumb_func,但main函数的地址可能未正确对齐(Thumb函数地址最低位必须为1),导致GDB无法准确识别其为Thumb函数,进而影响单步跟踪逻辑。 - 调试符号缺失:裸机汇编代码默认不生成足够的调试信息,GDB无法获取函数调用的栈帧元数据,导致跨函数的
nexti操作失效。 - 栈帧解析失败:
backtrace提示的栈损坏,说明GDB无法正确解析main的栈帧,这直接影响了单步调试时的断点预判。
具体修复步骤
确保Thumb函数的地址与标记正确
- 确认所有Thumb函数(包括
main)的定义前都有.thumb_func,且.align 4保证地址对齐(链接后需验证main的地址最低位为1)。 - 检查链接脚本是否正确处理Thumb函数的地址映射,避免地址被错误修正。
- 确认所有Thumb函数(包括
添加GDB可识别的栈帧调试伪指令
在main和子函数中添加调试帧信息,帮助GDB解析栈结构:.thumb_func .global main .align 4 main: push {lr} @ GDB调试帧信息 .cfi_startproc .cfi_def_cfa_offset 8 .cfi_offset lr, -8 @ ... 原有代码 pop {pc} .cfi_endproc编译时生成完整调试符号
编译汇编代码时添加-g选项保留调试信息:arm-none-eabi-as -g start.s -o start.o arm-none-eabi-as -g main.s -o main.o arm-none-eabi-ld start.o main.o -o program.elf链接时不要使用
-s选项剥离符号。明确指定GDB的目标架构
启动GDB时直接指定目标为Thumb架构(以ARMv7-M为例):arm-none-eabi-gdb --architecture=armv7-m program.elf或在GDB会话中执行:
set architecture armv7-m验证栈指针的有效性
确认SRAM_STRIPED_END是正确的栈顶地址,栈空间足够且未被其他代码覆盖,避免栈溢出导致的帧解析错误。
内容的提问来源于stack exchange,提问作者derASMCoder
相关产品推荐
相关产品推荐

