在arm-none-eabi-gdb模拟器中,程序入口点的ldr似乎给出了荒谬的结果

时间:2019-02-26 03:01:55

标签: assembly arm gdb

我正在学习为裸机树莓派编写ARM汇编程序。
我在x86机器上运行arm-none-eabi-gdb进行调试。
arm-none-eabi-gdb随附的模拟器的行为不像我在以下简单程序上预期的那样:

.section ".text.startup"

.global _start

_start:
    nop
    nop
    nop
    ldr     r0, =_start
    ldr     r2, [r0]
    ldr     r3, [r0, #4]
    ldr     r4, [r0, #8]

我希望将nop的代码加载到寄存器r2r3r4中。但是,当我编译程序时

$ arm-none-eabi-gcc -mfloat-abi=hard -nostartfiles -mfpu=neon-vfpv4 -march=armv7-a -mtune=cortex-a7 -O0 test.S -o kernel.elf

获得

$ arm-none-eabi-objdump -S kernel.elf

kernel.elf:     file format elf32-littlearm


Disassembly of section .text:

00004000 <_start>:
    4000:   e320f000    nop {0}
    4004:   e320f000    nop {0}
    4008:   e320f000    nop {0}
    400c:   e59f0008    ldr r0, [pc, #8]    ; 401c <_start+0x1c>
    4010:   e5902000    ldr r2, [r0]
    4014:   e5903004    ldr r3, [r0, #4]
    4018:   e5904008    ldr r4, [r0, #8]
    401c:   00004000    .word   0x00004000

并在arm-none-eabi-gdb中的模拟器中运行它,寄存器r3r4装入了0xe320f000,这是正确的。
但是r2已加载0xe7ffdefe,似乎并非来自任何地方。

我有arm-none-eabi-gdb版本7.8.1和arm-none-eabi-gcc版本4.8.3。这是模拟器中的错误还是我遗漏了一些明显的东西?

P.s。我试图在链接脚本中将入口点更改为0x4000,而不是默认的0x8000。问题仍然存在,因此模拟器无法从入口点内存地址正确加载吗?

1 个答案:

答案 0 :(得分:1)

您在_start:处设置了断点吗? 0xe7ffdefe可能是GDB覆盖了第一个nop的软件断点的机器指令,以实现断点。

您可以使用_start: mov edi, [rel _start]在x86上重现它,RDI的低字节将为0xccint3)或0x8b({{1的操作码}}),具体取决于您是否在mov r32, r/m32处设置了断点。


GDB不会伪造自己读取的代码以阻止其看到软件断点。您可以让GDB使用硬件断点来解决此问题。使用_start代替hbreakhttps://sourceware.org/gdb/onlinedocs/gdb/Set-Breaks.html

但是GDB确实从breakx /i GDB命令中隐藏了这一点,呈现出未修改的代码字节的错觉。


顺便说一句,您可以使用disas运行程序,但在执行第一条指令之前就停止。 (即,在入口点设置一个临时断点,其优点是即使入口点没有标签也可以使用。)

然后,您可以单步执行(也无需设置SW断点),您的代码将按预期执行。