3

我有一个我知道应该在 0x20000000 加载的 ARM Cortex M 的二进制固件映像。我想将其转换为可用于使用 gdb 进行汇编级调试的格式,我认为这意味着转换为 .elf。但是我还没有弄清楚如何向 .elf 添加足够的元数据来实现这一点。这是我到目前为止所尝试的。

arm-none-eabi-objcopy -I binary -O elf32-littlearm --set-section-flags \
    .data=alloc,contents,load,readonly \
    --change-section-address .data=0x20000000 efr32.bin efr32.elf

efr32.elf:     file format elf32-little
efr32.elf
architecture: UNKNOWN!, flags 0x00000010:
HAS_SYMS
start address 0x00000000

Sections:
Idx Name          Size      VMA       LMA       File off  Algn
  0 .data         00000168  20000000  20000000  00000034  2**0
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
SYMBOL TABLE:
20000000 l    d  .data  00000000 .data
20000000 g       .data  00000000 _binary_efr32_bin_start
20000168 g       .data  00000000 _binary_efr32_bin_end
00000168 g       *ABS*  00000000 _binary_efr32_bin_size

我是否需要首先将二进制文件转换为 .o 并编写一个简单的链接器脚本?我应该向 objcopy 命令添加架构选项吗?

4

1 回答 1

3

一个小实验...

  58:   480a        ldr r0, [pc, #40]   ; (84 <spi_write_byte+0x38>)
  5a:   bf08        it  eq
  5c:   4809        ldreq   r0, [pc, #36]   ; (84 <spi_write_byte+0x38>)
  5e:   f04f 01ff   mov.w   r1, #255    ; 0xff

你当然没有,但你可以阅读二进制文件并用它来做:

.thumb
.globl _start
_start:
.inst.n 0x480a
.inst.n 0xbf08
.inst.n 0x4809
.inst.n 0xf04f
.inst.n 0x01ff

然后看看会发生什么。

arm-none-eabi-as test.s -o test.o
arm-none-eabi-ld -Ttext=0x58 test.o -o test.elf
arm-none-eabi-objdump -D test.elf

test.elf:     file format elf32-littlearm


Disassembly of section .text:

00000058 <_start>:
  58:   480a        ldr r0, [pc, #40]   ; (84 <_start+0x2c>)
  5a:   bf08        it  eq
  5c:   4809        ldreq   r0, [pc, #36]   ; (84 <_start+0x2c>)
  5e:   f04f 01ff   mov.w   r1, #255    ; 0xff

但现实情况是它不会工作......如果这个二进制文件有任何 thumb2 扩展它不会工作,你不能线性反汇编可变长度指令。您必须按执行顺序处理它们。因此,要正确执行此操作,您必须编写一个反汇编程序,按执行顺序遍历代码,确定您可以找出的指令,将它们标记为指令......

  80:   d1e8        bne.n   54 <spi_write_byte+0x8>
  82:   bd70        pop {r4, r5, r6, pc}
  84:   40005200
  88:   F7FF4000
  8c:   e92d 41f0   stmdb   sp!, {r4, r5, r6, r7, r8, lr}
  90:   4887        ldr r0, [pc, #540]  ; (2b0 <notmain+0x224>)
.thumb
.globl _start
_start:
.inst.n 0xd1e8
.inst.n 0xbd70
.inst.n 0x5200
.inst.n 0x4000
.inst.n 0x4000
.inst.n 0xF7FF
.inst.n 0xe92d
.inst.n 0x41f0
.inst.n 0x4887

  80:   d1e8        bne.n   54 <_start-0x2c>
  82:   bd70        pop {r4, r5, r6, pc}
  84:   5200        strh    r0, [r0, r0]
  86:   4000        ands    r0, r0
  88:   4000        ands    r0, r0
  8a:   f7ff e92d           ; <UNDEFINED> instruction: 0xf7ffe92d
  8e:   41f0        rors    r0, r6
  90:   4887        ldr r0, [pc, #540]  ; (2b0 <_start+0x230>)

它会恢复,并打破和恢复,等等......

相反,您必须编写一个遍历代码的反汇编程序(不一定必须反汇编为汇编语言,但足以遍历代码并递归所有可能的分支路径)。所有未确定为指令的数据都标记为指令

.thumb
.globl _start
_start:
.inst.n 0xd1e8
.inst.n 0xbd70
.word 0x40005200
.word 0xF7FF4000
.inst.n 0xe92d
.inst.n 0x41f0
.inst.n 0x4887

00000080 <_start>:
  80:   d1e8        bne.n   54 <_start-0x2c>
  82:   bd70        pop {r4, r5, r6, pc}
  84:   40005200    andmi   r5, r0, r0, lsl #4
  88:   f7ff4000            ; <UNDEFINED> instruction: 0xf7ff4000
  8c:   e92d 41f0   stmdb   sp!, {r4, r5, r6, r7, r8, lr}
  90:   4887        ldr r0, [pc, #540]  ; (2b0 <_start+0x230>)

我们的 stmdb 指令现在是正确的。

祝你好运。

于 2017-09-01T03:55:07.747 回答