Conversion from .elf to .bin increases file size

1.9k Views Asked by At

When we covert a .elf file generated from arm-gcc toolchain to .bin file, its size increases from 40kB to 1.1Gb.

For conversion we are using : ./arm-none-eabi-objcopy -O binary test.elf test.bin

It might be because of non-contiguous memory map and the gaps between the memory regions are just being filled with zeros.

What options can be used in objcopy? Or is there any other method to convert?

Following is the elf information:

  • Tag_CPU_name: "Cortex-M7" Tag_CPU_arch: v7E-M
    Tag_CPU_arch_profile: Microcontroller Tag_THUMB_ISA_use: Thumb-2
    Tag_FP_arch: FPv5/FP-D16 for ARMv8 Tag_ABI_PCS_wchar_t: 4
    Tag_ABI_FP_denormal: Needed Tag_ABI_FP_exceptions: Needed
    Tag_ABI_FP_number_model: IEEE 754 Tag_ABI_align_needed: 8-byte
    Tag_ABI_enum_size: small Tag_ABI_VFP_args: VFP registers
    Tag_ABI_optimization_goals: Aggressive Debug
    Tag_CPU_unaligned_access: v6

The listing of sections contained in the ELF file is - there are 25 section headers, starting at offset 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]: 
2

There are 2 best solutions below

1
On

so.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
}

build

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

from readelf

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

now so.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
}

it is actually .bss that is doing the magic here, that is some other research project, I could have started with a .C file but tried asm...

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

and now it is the possibly desired 6 bytes without padding, but of course you have to add labels in the linker script and use them in the bootstrap code to move .data to ram and zero .bss and such.

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

Notice how now the physical is in the 0x00000000 range, it was tacked at the end of the space used by .text. but the virtual (where it wants to live, needs to live, do not think mmu here or anything like that just think the two address spaces (on flash and where it is used)).

In case this is not clear:

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 starts the binary file at the lowest defined (loadable) address and not zero...The file size is the difference, inclusive, of the lowest addressed byte and the highest.

0
On

I have same problem with you, and I finally find it's not objcopy's problem, I just change my compile command and it work. At first, I just use gcc only, and I face the problem like you, then I try use gcc -c and ld(just separate this two steps), and the file is smaller in magically. so maybe the problem is in gcc, not objcopy. you can try like me, and my compile command now is:

gcc-4.8 -g -e boot_start -fno-builtin -Ttext 0x7C00 -nostdlib -m32 -c bootloader.S -o bootasm.o
gcc-4.8 -Os -fno-builtin -nostdlib -m32 -c bootloader.c -o bootc.o
ld -m elf_i386 -e boot_start -nostdlib -N bootasm.o bootc.o -o bootloader.o

objcopy -S -O binary bootloader.o bootloader.bin

hope it can help you...