【问题标题】:How do I convert a binary firmware dump to an .elf for assembly language debugging?如何将二进制固件转储转换为 .elf 以进行汇编语言调试?
【发布时间】:2018-02-10 01:13:09
【问题描述】:

我有一个 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 命令添加架构选项吗?

【问题讨论】:

  • 有 objcopy 方法可以做到这一点,但你需要一个固定长度的指令集,没有 thumb2 的拇指(虽然这可能不适用于 gnu),没有拇指的手臂,只有 mips 32 位(没有 16 位说明),而不是 x86,而不是其他一些。

标签: arm gdb embedded elf objcopy


【解决方案1】:

一个小实验……

  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 指令现在是正确的。

祝你好运。

【讨论】:

  • 您使用了哪些 objdump 选项来显示 .inst.n 行?
  • 在这种情况下是手工创建的,您将编写一个读取二进制文件并创建类似文件的工具。
  • 请注意,当我将 thumb2 扩展而不是一个 32 位 inst.w 作为两个 16 位 inst.n 反汇编器时,我演示了即使我说它是一个 thumb 指令 inst.n发现这是一个拇指...
  • 我不知道您使用的是什么核心/指令集,但如果它是 cortex-m,那么 armv6-m 和 arm7-m(和 armv-8m)有必须处理的 thumb2 扩展可能,但是这个二进制文件是使用它们中的任何一个构建的,还是纯粹的拇指?我还省略了向量表,它非常简单,可以通过视觉方式将 .words 放入该部分的二进制文件中。
  • 它有一些 32 位的分支指令
猜你喜欢
  • 1970-01-01
  • 2017-04-07
  • 1970-01-01
  • 1970-01-01
  • 2019-05-16
  • 2015-11-07
  • 2015-07-17
  • 1970-01-01
  • 2015-09-15
相关资源
最近更新 更多