-1

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]: 
Frant
  • 5,382
  • 1
  • 16
  • 22
dfordevy
  • 161
  • 1
  • 15
  • You should probably join the linker script you are using to your question. – Frant Apr 28 '21 at 18:41
  • I didnt get you, I am not using linker script for elf to bin conversion, just objcopy – dfordevy Apr 28 '21 at 18:44
  • Not directly, you are right, but you are definitively using one indirectly, since its content guided the number of sections that were created in the .elf file during the linking phase, along as their attributes, sizes and locations.You should probably at least join the output for command `arm-none-eabi-readelf -t test.elf`. – Frant Apr 28 '21 at 18:50
  • this is pretty common depending on your memory map, you probably have some incorrectly placed .data in your link – old_timer Apr 28 '21 at 18:51
  • if your flash is defined at 0x00000000 and you define .data at 0x20000000 then converting to a -O binary will make the file at least 0x20000000 bytes long even if the whole binary is two bytes of instruction and one byte of data...(yes obcopy adds padding) – old_timer Apr 28 '21 at 18:53
  • if you have properly defined the read/write items then they will not be loadable into 0x20000000 and the binary will be just what is in flash/rom. actually 1gb then you have something going on at 0x40000000 too. – old_timer Apr 28 '21 at 18:53
  • so as pointed out the linker script, readelf, objdump, etc tell the whole story here – old_timer Apr 28 '21 at 18:54
  • How do I attach the output for readelf? Also yes I agree it might be due to non-contagious locations. – dfordevy Apr 28 '21 at 19:02
  • cut and paste from the command line window – old_timer Apr 28 '21 at 19:07
  • or just look at the output – old_timer Apr 28 '21 at 19:07
  • https://pastebin.com/atCq6ivN - here is the output – dfordevy Apr 28 '21 at 19:10
  • @Frant have saved the edit now. Also rechecked the CMakeFile for .elf generation using armgcc toolchain, could not find any Linker. It is present for IAR and MCUXpresso build environment. – dfordevy Apr 28 '21 at 19:25
  • @dfordevy : You just copy/paste it into your question, and format it into the code format using the `{}` button. I prepended `` since this output is not in a language supported by the syntax highlighter. – Frant Apr 28 '21 at 19:44

2 Answers2

0

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.

old_timer
  • 69,149
  • 8
  • 89
  • 168
  • so to get to 1.1GBytes you can do the math to estimate the address space you placed something in for the range then add that to the lowest address you specified. – old_timer Apr 28 '21 at 19:37
0

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