【问题标题】:Conversion from .elf to .bin increases file size从 .elf 到 .bin 的转换会增加文件大小
【发布时间】:2021-07-22 03:39:46
【问题描述】:

当我们将 arm-gcc 工具链生成的 .elf 文件转换为 .bin 文件时,其大小从 40kB 增加到 1.1Gb。

对于转换,我们使用: ./arm-none-eabi-objcopy -O binary test.elf test.bin

这可能是因为内存映射不连续,内存区域之间的间隙只是用零填充。

objcopy 中可以使用哪些选项?或者有没有其他方法可以转换?

以下是精灵信息:

  • 标签_CPU_名称:“Cortex-M7”标签_CPU_arch:v7E-M
    Tag_CPU_arch_profile:微控制器 Tag_THUMB_ISA_use:Thumb-2
    Tag_FP_arch:用于 ARMv8 的 FPv5/FP-D16 Tag_ABI_PCS_wchar_t:4
    Tag_ABI_FP_denormal:需要 Tag_ABI_FP_exceptions:需要
    Tag_ABI_FP_number_model:IEEE 754 Tag_ABI_align_needed:8 字节
    Tag_ABI_enum_size:小 Tag_ABI_VFP_args:VFP 寄存器
    Tag_ABI_optimization_goals:积极调试
    Tag_CPU_unaligned_access: v6

ELF 文件中包含的节列表是 - 有 25 个节头,从偏移量 0x3e982c 开始:

Section Headers:
  [Nr] Name
       Type            Addr     Off    Size   ES   Lk Inf Al
       Flags
  [ 0] 
       NULL            00000000 000000 000000 00   0   0  0
       [00000000]: 
  [ 1] .flash_config
       PROGBITS        60000000 020000 000200 00   0   0  4
       [00000002]: ALLOC
  [ 2] .ivt
       PROGBITS        60001000 021000 000030 00   0   0  4
       [00000002]: ALLOC
  [ 3] .interrupts
       PROGBITS        60002000 022000 000400 00   0   0  4
       [00000002]: ALLOC
  [ 4] .text
       PROGBITS        60002400 022400 312008 00   0   0 16
       [00000006]: ALLOC, EXEC
  [ 5] .ARM
       ARM_EXIDX       60314408 334408 000008 00   4   0  4
       [00000082]: ALLOC, LINK ORDER
  [ 6] .init_array
       INIT_ARRAY      60314410 334410 000004 04   0   0  4
       [00000003]: WRITE, ALLOC
  [ 7] .fini_array
       FINI_ARRAY      60314414 334414 000004 04   0   0  4
       [00000003]: WRITE, ALLOC
  [ 8] .interrupts_ram
       PROGBITS        20200000 380000 000000 00   0   0  1
       [00000001]: WRITE
  [ 9] .data
       PROGBITS        20200000 340000 014bd0 00   0   0  8
       [00000007]: WRITE, ALLOC, EXEC
  [10] .ncache.init
       PROGBITS        20214bd0 354bd0 011520 00   0   0  4
       [00000003]: WRITE, ALLOC
  [11] .ncache
       NOBITS          20226100 366100 0021d8 00   0   0 64
       [00000003]: WRITE, ALLOC
  [12] .bss
       NOBITS          20229000 369000 077ce8 00   0   0 4096
       [00000003]: WRITE, ALLOC
  [13] .NVM_TABLE
       PROGBITS        20000000 010000 00000c 00   0   0  4
       [00000003]: WRITE, ALLOC
  [14] .heap
       NOBITS          2000000c 01000c 000404 00   0   0  1
       [00000003]: WRITE, ALLOC
  [15] .stack
       NOBITS          20000410 01000c 000400 00   0   0  1
       [00000003]: WRITE, ALLOC
  [16] .NVM
       PROGBITS        60570000 370000 010000 00   0   0  1
       [00000003]: WRITE, ALLOC
  [17] .ARM.attributes
       ARM_ATTRIBUTES  00000000 380000 00002e 00   0   0  1
       [00000000]: 
  [18] .comment
       PROGBITS        00000000 38002e 00004c 01   0   0  1
       [00000030]: MERGE, STRINGS
  [19] .debug_frame
       PROGBITS        00000000 38007c 001174 00   0   0  4
       [00000000]: 
  [20] .stab
       PROGBITS        00000000 3811f0 0000cc 0c  21   0  4
       [00000000]: 
  [21] .stabstr
       STRTAB          00000000 3812bc 0001b9 00   0   0  1
       [00000000]: 
  [22] .symtab
       SYMTAB          00000000 381478 046620 10  23 13540  4
       [00000000]: 
  [23] .strtab
       STRTAB          00000000 3c7a98 021cb2 00   0   0  1
       [00000000]: 
  [24] .shstrtab
       STRTAB          00000000 3e974a 0000df 00   0   0  1
       [00000000]: 

【问题讨论】:

  • 您可能应该将您正在使用的链接器脚本加入到您的问题中。
  • 我没听明白,我没有使用链接器脚本进行 elf 到 bin 的转换,只是 objcopy
  • 不是直接的,你是对的,但你肯定是间接地使用一个,因为它的内容指导了在链接阶段在 .elf 文件中创建的部分的数量,以及它们的属性、大小和位置。您可能至少应该加入命令arm-none-eabi-readelf -t test.elf 的输出。
  • 这很常见,具体取决于您的内存映射,您的链接中可能有一些错误放置的 .data
  • 如果您的闪存定义在 0x00000000 并且您在 0x20000000 定义 .data 则转换为 -O 二进制文件将使文件至少有 0x20000000 字节长,即使整个二进制文件是两个字节的指令和一个数据字节...(是 obcopy 添加填充)

标签: gcc arm elf objcopy


【解决方案1】:

所以.s

.thumb
nop
.data
.word 0x11223344

so.ld

MEMORY
{
    one : ORIGIN = 0x00000000, LENGTH = 0x1000
    two : ORIGIN = 0x20000000, LENGTH = 0x1000
}

SECTIONS
{
    .text : { *(.text*) } > one
    .data : { *(.data*) } > two
}

构建

arm-none-eabi-as so.s -o so.o
arm-none-eabi-ld -T so.ld so.o -o so.elf
arm-none-eabi-objdump -D so.elf
arm-none-eabi-objcopy -O binary so.elf so.bin

536870916 Apr 28 15:23 so.bin
   131556 Apr 28 15:23 so.elf

来自读者

Program Headers:
  Type           Offset   VirtAddr   PhysAddr   FileSiz MemSiz  Flg Align
  LOAD           0x010000 0x00000000 0x00000000 0x00002 0x00002 R E 0x10000
  LOAD           0x020000 0x20000000 0x20000000 0x00004 0x00004 RW  0x10000

现在这样.ld

MEMORY
{
    one : ORIGIN = 0x00000000, LENGTH = 0x1000
    two : ORIGIN = 0x20000000, LENGTH = 0x1000
}

SECTIONS
{
    .text : { *(.text*) } > one
    .bss : { *(.bss*) } > two AT > one
    .data : { *(.data*) } > two AT > one
}

实际上是 .bss 在这里发挥了魔力,这是其他一些研究项目,我本来可以从 .C 文件开始,但尝试了 asm...

      6 Apr 28 15:30 so.bin
 131556 Apr 28 15:29 so.elf

现在它可能是没有填充的 6 个字节,但当然你必须在链接描述文件中添加标签并在引导代码中使用它们来将 .data 移动到 ram 和零 .bss 等。

Program Headers:
  Type           Offset   VirtAddr   PhysAddr   FileSiz MemSiz  Flg Align
  LOAD           0x010000 0x00000000 0x00000000 0x00002 0x00002 R E 0x10000
  LOAD           0x020000 0x20000000 0x00000002 0x00004 0x00004 RW  0x10000

注意现在物理在 0x00000000 范围内,它被添加到 .text 使用的空间的末尾。但是虚拟的(它想住的地方,需要住的地方,不要考虑这里的 mmu 或类似的东西,只考虑两个地址空间(在闪存上和使用它的地方))。

如果不清楚:

MEMORY
{
    one : ORIGIN = 0xE0000000, LENGTH = 0x1000
    two : ORIGIN = 0xE0000100, LENGTH = 0x1000
}

SECTIONS
{
    .text : { *(.text*) } > one
    .data : { *(.data*) } > two
}

   260 Apr 28 15:46 so.bin
 66276 Apr 28 15:46 so.elf

objcopy 从定义的最低(可加载)地址开始二进制文件,而不是零...文件大小是最低寻址字节和最高寻址字节的差值。

【讨论】:

  • 所以要达到 1.1GBytes,您可以通过数学计算来估计您在该范围内放置的地址空间,然后将其添加到您指定的最低地址。
猜你喜欢
  • 2011-05-23
  • 1970-01-01
  • 2016-10-28
  • 1970-01-01
  • 2010-12-02
  • 2013-05-29
  • 2011-08-22
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多