我有一个STM32F4 Discovery板,OpenOCD调试服务器和armv7m-unknown-eabi-gdb,并希望我的主板运行我已经构建的裸机ELF。我启动gdb,给它target remote :3333
,load
,monitor reset halt
命令,然后尝试单步执行代码,但没有任何作用。经过一番调查后,我发现代码上传的地址错误。
readelf -S给出:
[ 1] vectors PROGBITS 00000000 000114 000040 00 A 0 0 1
[ 2] .interp PROGBITS 00000040 000154 000011 00 A 0 0 1
[ 3] .dynsym DYNSYM 00000054 000168 000030 10 A 4 3 4
[ 4] .dynstr STRTAB 00000084 000198 000001 00 A 0 0 1
[ 5] .hash HASH 00000088 00019c 000018 04 A 3 0 4
[ 6] .text PROGBITS 000000a0 0001b4 000134 00 WAX 0 0 4
你可以看到链接器放了两个3字节的填充:第一个在.interp和.dynsym之间,第二个在.dynstr和.hash部分之间。
但是当gdb将图像加载到电路板上时,它似乎忽略了这些间隙,并将这些部分一个接一个地放在一起(从不显示0x2xxxxxxx地址,CPU配置为将它们映射到0x0xxxxxxx区域):
(gdb) load
Loading section vectors, size 0x40 lma 0x20000000
Loading section .interp, size 0x11 lma 0x20000040
Loading section .dynsym, size 0x30 lma 0x20000051
Loading section .dynstr, size 0x1 lma 0x20000081
Loading section .hash, size 0x18 lma 0x20000082
Loading section .text, size 0x134 lma 0x2000009a
结果是代码在地址GDB期望它之前找到了6个字节,因此所有调试信息都不正确地应用于内存。我真的得到了疯狂的结果,因为我要执行的下一条指令(也就是GDB所指的那条)实际上是另一条指令(确切地说,它是当前指令+3个半字)
那么,有什么不对的?我是否错误地使用GDB?或者是错误构建的ELF?也许OpenOCD是罪魁祸首?或其他什么?
修改
看起来GDB根据ELF中的内容完成了它的工作。 .dynsym和.hash部分的LMA地址实际上没有对齐。
objdump -h给出:
Sections:
Idx Name Size VMA LMA File off Algn
0 vectors 00000040 00000000 20000000 00000114 2**0
CONTENTS, ALLOC, LOAD, READONLY, DATA
1 .interp 00000011 00000040 20000040 00000154 2**0
CONTENTS, ALLOC, LOAD, READONLY, DATA
2 .dynsym 00000030 00000054 20000051 00000168 2**2
CONTENTS, ALLOC, LOAD, READONLY, DATA
3 .dynstr 00000001 00000084 20000081 00000198 2**0
CONTENTS, ALLOC, LOAD, READONLY, DATA
4 .hash 00000018 00000088 20000082 0000019c 2**2
CONTENTS, ALLOC, LOAD, READONLY, DATA
5 .text 00000134 000000a0 2000009a 000001b4 2**2
CONTENTS, ALLOC, LOAD, CODE
事实证明.interp,.dynsym,.dynstr和.hash部分是由链接器生成的,因为GCC给它-pic标志。我没有在链接器脚本中提到这些部分。所以我需要理解为什么ld对齐VMA地址但不是LMA那些。