Logo
Articles Compilers Libraries Books MiniBooklets Assembly C++ Linux Others Videos
Advertisement

Article by Ayman Alheraki on January 11 2026 10:37 AM

Object File Generation ELF Format Deep Dive - Section Headers .text, .data, .bss

Object File Generation: ELF Format Deep Dive -> Section Headers: .text, .data, .bss

In the ELF object file format, section headers define the organization of the binary’s data into logically distinct regions. Each section header provides metadata about a region of the file or memory, including its size, location, alignment, and purpose. For assemblers targeting the x86-64 architecture, three standard sections are typically used: .text, .data, and .bss. These correspond respectively to executable code, initialized data, and uninitialized data.

This section discusses their purpose, header structure, and how an assembler generates these headers correctly.

1. Role and Purpose of Standard Sections

.text Section

  • Contains the machine instructions (i.e., assembled code).

  • Marked as executable and typically read-only.

  • The linker will place this section in an executable memory segment during program loading.

.data Section

  • Contains initialized global and static variables.

  • It is writable and used for storing variables with known initial values at compile-time.

.bss Section

  • Represents uninitialized data.

  • It does not occupy space in the file but will be allocated and zero-initialized in memory at runtime.

  • Typically used for variables that are declared globally or statically without initialization.

2. Section Header Table Overview

Each ELF file has a section header table that begins at the file offset specified by e_shoff in the ELF header. Every entry in the table is 64 bytes in 64-bit ELF and corresponds to a specific section, including metadata such as name, type, flags, and location.

The relevant C structure is:

Each field must be filled appropriately by the assembler.

3. .text Section Header

This section is responsible for holding executable machine instructions.

Key Fields:

  • sh_name: Offset into the section header string table pointing to the name ".text".

  • sh_type: SHT_PROGBITS (value = 1), as it contains actual program data.

  • sh_flags: SHF_ALLOC | SHF_EXECINSTR (values = 0x6), making the section allocatable and executable.

  • sh_addr: Set to 0 in relocatable object files.

  • sh_offset: File offset where the .text section begins.

  • sh_size: Total size of code in bytes.

  • sh_addralign: Typically 16 for x86-64 instructions to satisfy CPU alignment requirements.

  • sh_entsize: 0 unless the section holds fixed-size entries (not the case here).

4. .data Section Header

Holds initialized writable data.

Key Fields:

  • sh_name: Offset to ".data" in the string table.

  • sh_type: SHT_PROGBITS

  • sh_flags: SHF_ALLOC | SHF_WRITE (values = 0x3)

  • sh_addr: 0 (relocatable object)

  • sh_offset: Offset in the file where .data starts.

  • sh_size: Number of bytes of initialized data.

  • sh_addralign: Often 8 for general data alignment.

  • sh_entsize: 0

5. .bss Section Header

Holds uninitialized data that will be zero-filled by the loader.

Key Fields:

  • sh_name: Offset to ".bss" in the string table.

  • sh_type: SHT_NOBITS (value = 8)

  • sh_flags: SHF_ALLOC | SHF_WRITE

  • sh_addr: 0

  • sh_offset: File offset where the section would begin (not used since no file space is allocated).

  • sh_size: Size of zero-initialized space.

  • sh_addralign: Typically 8

  • sh_entsize: 0

Although .bss does not occupy file space, it must still be described in the section header table to ensure the linker and loader allocate the correct space in memory.

6. Generating Section Headers in an Assembler

During assembler output generation, the following actions are required:

  1. Emit actual section contents:

    • Write the .text and .data contents to the file buffer first.

    • Keep track of each section's starting file offset and size.

    • For .bss, track size only, as no bytes are written.

  2. Construct section name string table:

    • Contains null-terminated strings like .text, .data, .bss, etc.

    • The assembler must record the offset of each name for use in sh_name.

  3. Construct section headers:

    • Create a section header entry for each section.

    • Include an additional header for the section string table itself.

    • Populate each field precisely, using tracked offsets, sizes, and alignment values.

  4. Update ELF Header:

    • After all section headers are created, update the e_shoff, e_shnum, and e_shstrndx fields of the ELF header.

7. Order and Indexing

The standard order in the section header table (excluding the null section) typically follows:

  1. .text

  2. .data

  3. .bss

  4. .shstrtab (section string table)

The .shstrtab section must be referenced via e_shstrndx in the ELF header to link section names.

Indexing begins from 1, as the first entry (index 0) is reserved and must be all zero bytes to represent the undefined section.

8. Alignment Considerations

Proper alignment of sections is critical. Modern CPUs expect code and data to be aligned to specific boundaries for optimal performance and correctness. The assembler must ensure:

  • .text: 16-byte alignment

  • .data: 8 or 16 bytes depending on structure usage

  • .bss: 8 bytes or higher

This is enforced through padding in the file and section header sh_addralign fields.

9. Summary

The .text, .data, and .bss sections form the core of the ELF file’s content for code and static data. Properly generating their section headers ensures that the object file is compliant, linkable, and correctly interpretable by the linker and loader. An assembler must not only write section contents but also build complete and accurate metadata reflecting size, location, and usage semantics, all of which are encoded in the section headers.

Advertisements

Responsive Counter
General Counter
1001267
Daily Counter
467