如何用arm-none-eabi-ld生成带调试信息的ELF?汇编符号丢失问题
问题分析与解决方案
核心问题定位
- 链接脚本调试段处理错误:你手动将所有
.debug_*调试段强制定位到地址0,导致调试符号记录的地址与代码实际加载地址(从0x10000开始)完全不匹配,GDB无法映射符号到正确内存位置,甚至可能让链接器丢弃部分调试信息。 - 汇编目标文件调试符号未被保留:仅链接汇编生成的
ts.o时,链接器未正确保留其调试符号;加入C生成的t.o时能保留C符号,是因为GCC生成的调试信息格式更符合链接器默认处理逻辑,而汇编的调试符号需要额外配置。
修复步骤
1. 修正链接脚本的调试段处理
无需手动指定调试段地址,让链接器自动处理即可,修改后的t.ld如下:
ENTRY(start) SECTIONS { . = 0x10000; .text : { ts.o(.text) /* 明确指定ts.o的text段 */ *(.text) /* 其他目标文件的text段 */ } .data : { *(.data) } .bss : { *(.bss) } . = ALIGN(8); . = . + 0x1000; /* 4kB栈内存 */ stack_top = .; /* 丢弃无用段,无需手动处理调试段 */ /DISCARD/ : { *(.note.GNU-stack) } }
2. 链接时强制保留调试符号
使用arm-none-eabi-ld时添加-g选项,确保链接器保留所有目标文件的调试符号:
$ARM-ld -g -T t.ld -o t.elf ts.o
3. 让QEMU直接加载ELF文件
QEMU支持直接加载ELF文件,自动处理段地址映射,无需转成二进制文件:
修改mk脚本中的QEMU启动命令:
$QEMU -s -S -M realview-pbx-a9 -kernel t.elf -nographic -serial /dev/null
4. 正确的GDB调试流程
启动GDB并连接QEMU:
arm-none-eabi-gdb t.elf (gdb) target remote :1234 (gdb) b start # 现在可直接用符号设置断点 (gdb) c
验证方法
链接完成后,可通过以下命令确认调试符号是否存在:
arm-none-eabi-readelf --debug-dump=info t.elf
或在GDB中执行info functions,查看是否能列出汇编代码中的所有符号(如start、loop等)。
内容的提问来源于stack exchange,提问作者shino
相关产品推荐
相关产品推荐

