如何将二进制固件转储转换为.elf以进行汇编语言调试?

时间:2017-09-01 01:48:36

标签: arm gdb embedded elf objcopy

我有ARM Cortex M的二进制固件映像,我知道应该在0x20000000加载。我想将它转换为我可以用于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命令中添加架构选项吗?

1 个答案:

答案 0 :(得分: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指令现在正确。

祝你好运。