Understanding sections header of ARM ELF binary file

We written simple helloworld.c and compiled using ARM gcc toolchain to generate executable file helloworld now in this post, we will understand what are the sections added to this ELF binary generated.

$ file helloworld 
hello_world: ELF 32-bit LSB executable, ARM, EABI5 version 1 (SYSV), statically linked, with debug_info, not stripped

The ELF header sections can be printed using readelf arm toolchain binary as,

$ arm-linux-gnueabihf-readelf -e helloworld
Section Headers:
  [Nr] Name              Type            Addr     Off    Size   ES Flg Lk Inf Al
  [ 0]                   NULL            00000000 000000 000000 00      0   0  0
  [ 1] .init             PROGBITS        00008000 008000 000018 00  AX  0   0  4
  [ 2] .text             PROGBITS        00008018 008018 00bf40 00  AX  0   0  8
  [ 3] .fini             PROGBITS        00013f58 013f58 000018 00  AX  0   0  4
  [ 4] .rodata           PROGBITS        00013f70 013f70 000484 00   A  0   0  8
  [ 5] .ARM.exidx        ARM_EXIDX       000143f4 0143f4 000008 00  AL  2   0  4
  [ 6] .eh_frame         PROGBITS        000143fc 0143fc 000004 00   A  0   0  4
  [ 7] .init_array       INIT_ARRAY      00024400 014400 000008 04  WA  0   0  4
  [ 8] .fini_array       FINI_ARRAY      00024408 014408 000004 04  WA  0   0  4
  [ 9] .data             PROGBITS        00024410 014410 0009c0 00  WA  0   0  8
  [10] .bss              NOBITS          00024dd0 014dd0 000080 00  WA  0   0  4
  [11] .stab             PROGBITS        00000000 014dd0 0000cc 0c     12   0  4
  [12] .stabstr          STRTAB          00000000 014e9c 0001b9 00      0   0  1
  [13] .comment          PROGBITS        00000000 015055 00004d 01  MS  0   0  1
  [14] .debug_aranges    PROGBITS        00000000 0150a2 000020 00      0   0  1
  [15] .debug_info       PROGBITS        00000000 0150c2 000090 00      0   0  1
  [16] .debug_abbrev     PROGBITS        00000000 015152 000044 00      0   0  1
  [17] .debug_line       PROGBITS        00000000 015196 00003e 00      0   0  1
  [18] .debug_frame      PROGBITS        00000000 0151d4 001c3c 00      0   0  4
  [19] .debug_str        PROGBITS        00000000 016e10 0000f4 01  MS  0   0  1
  [20] .ARM.attributes   ARM_ATTRIBUTES  00000000 016f04 000026 00      0   0  1
  [21] .noinit           PROGBITS        00024e50 016f2a 000000 00   W  0   0  1
  [22] .symtab           SYMTAB          00000000 016f2c 002b90 10     23 465  4
  [23] .strtab           STRTAB          00000000 019abc 00110b 00      0   0  1
  [24] .shstrtab         STRTAB          00000000 01abc7 0000ea 00      0   0  1

The Third Column in this header comes from linker script definations, for example,

.bss (NOLOAD):
    {
        . = ALIGN(4);
        __bss_start__ = .;
        *(.bss*)
        *(COMMON)
        . = ALIGN(4);
        __bss_end__ = .;
    } > ram

The NOLOAD attribute tells linker that .bss section does not consume any space in the image. The NOLOAD attribute changes the .bss type to NOBITS, and that makes linker to A) not allocate section in memory, and put information to clear the section with all zeros during application loading.

Without the NOLOAD attribute, the .bss section might get PROGBITS type. This makes linker to A) allocate zeroed section in memory, and B) copy this section to RAM during application loading.

Reference – cypress git at github

Leave a Comment