Article by Ayman Alheraki in January 24 2025 01:40 PM
Executable headers are a fundamental part of any executable file in various operating systems. These headers contain vital information that helps the operating system understand how to load and execute the program. These headers differ across operating systems, such as Windows, Linux, and macOS, and play a crucial role in defining the structure of the executable file and how it interacts with the system.
In this article, we will explore the types of executable headers, the differences between them, their mechanisms of operation, how they are integrated with compiled programs, and the tools required for their creation. We will also provide illustrative examples for each type of header.
PE Header (Portable Executable)
Operating System: Windows
Description: The Windows operating system uses the PE format for executable files such as .exe
and .dll
. The PE header contains information such as entry points, program sections, imports, and exports.
Structure: The PE header consists of several parts, including the DOS Header, PE Header, Optional Header, and data sections.
ELF Header (Executable and Linkable Format)
Operating System: Linux and Unix-like systems
Description: The Linux operating system uses the ELF format for executable files and shared libraries. The ELF header contains information such as the file type (executable, library, etc.), architecture, and entry points.
Structure: The ELF header consists of the ELF Header, Program Headers, and Section Headers.
Mach-O Header (Mach Object)
Operating System: macOS and iOS
Description: The macOS operating system uses the Mach-O format for executable files and libraries. The Mach-O header contains information such as the file type, number of commands, and command sizes.
Structure: The Mach-O header consists of the Mach Header, Load Commands, and Segment Commands.
Structure and Format
PE: Relies on a complex binary format with multiple sections.
ELF: More flexible and used in Unix-like systems.
Mach-O: Specifically designed for Apple systems and relies on the concept of commands.
Entry Points
PE: Contains a specific entry point in the Optional Header.
ELF: Contains an entry point in the ELF Header.
Mach-O: Contains an entry point in the Load Commands.
Memory Management
PE: Uses sections like .text
and .data
for memory management.
ELF: Uses Program Headers for memory management.
Mach-O: Uses Segment Commands for memory management.
DOS Header: Contains basic information such as the file signature and a small stub program that runs when the file is executed in DOS.
PE Header: Contains information such as the file type, number of sections, and timestamps.
Optional Header: Contains vital information such as the entry point, memory addresses, image size, and data directories.
Sections: The actual parts of the program, such as .text
(executable code), .data
(initialized data), and .rdata
(read-only data).
Example of PE Header:
DOS Header:
- Signature: "MZ"
- Stub Program: Displays "This program cannot be run in DOS mode."
PE Header:
- Signature: "PE\0\0"
- Machine: x86
- Number of Sections: 3
- Timestamp: 0x5F4A3B2C
Optional Header:
- Magic: 0x10B (PE32)
- Entry Point: 0x1000
- Base of Code: 0x1000
- Base of Data: 0x2000
- Image Base: 0x400000
- Data Directories:
- Import Table: RVA 0x3000, Size 0x200
- Export Table: RVA 0x4000, Size 0x100
Sections:
- .text: Contains executable code
- .data: Contains initialized data
- .rdata: Contains read-only data
ELF Header: Contains general information such as the file signature, file type, architecture, and entry point.
Program Headers: Describe how segments are loaded into memory.
Section Headers: Describe sections such as .text
(executable code), .data
(initialized data), and .bss
(uninitialized data).
Example of ELF Header:
ELF Header:
- Magic: 0x7F 0x45 0x4C 0x46
- Class: 64-bit
- Data: Little-endian
- Type: Executable
- Machine: x86-64
- Entry Point: 0x400000
Program Headers:
- Type: LOAD
- Virtual Address: 0x400000
- Physical Address: 0x400000
- File Size: 0x1000
- Memory Size: 0x1000
- Type: LOAD
- Virtual Address: 0x600000
- Physical Address: 0x600000
- File Size: 0x200
- Memory Size: 0x200
Section Headers:
- .text: Executable code, Address: 0x400000
- .data: Initialized data, Address: 0x600000
- .bss: Uninitialized data, Address: 0x600200
Mach Header: Contains information such as the file signature, CPU type, file type, and number of commands.
Load Commands: Describe how the file is loaded into memory.
Segment Commands: Describe segments such as __TEXT
(executable code) and __DATA
(data).
Example of Mach-O Header:
Mach Header:
- Magic: 0xFEEDFACF (64-bit)
- CPU Type: x86_64
- File Type: Executable
- Number of Load Commands: 3
- Size of Load Commands: 0x200
Load Commands:
- Type: LC_SEGMENT_64
- Segment Name: __TEXT
- Virtual Address: 0x100000000
- File Size: 0x1000
- Memory Size: 0x1000
- Type: LC_SEGMENT_64
- Segment Name: __DATA
- Virtual Address: 0x100001000
- File Size: 0x200
- Memory Size: 0x200
- Type: LC_MAIN
- Entry Point: 0x100000000
First Stage: Assembly
The source code is converted into machine code using an assembler. In this stage, program sections such as .text
(for code) and .data
(for data) are created.
Second Stage: Linking
The compiled code is linked with libraries and imports using a linker. In this stage, the executable header is created, and necessary information such as entry points and sections is added.
Third Stage: Loading
When the program is run, the operating system loads the executable file into memory using the information in the header. The entry point location is determined, and the program is executed.
Assembler
Windows: MASM
(Microsoft Macro Assembler)
Linux: as
(GNU Assembler)
macOS: as
(GNU Assembler)
Linker
Windows: link.exe
(Microsoft Linker)
Linux: ld
(GNU Linker)
macOS: ld
(GNU Linker)
Compiler
Windows: cl.exe
(Microsoft C/C++ Compiler)
Linux: gcc
(GNU Compiler Collection)
macOS: clang
(LLVM Compiler)
Analysis Tools
PE: PEview
, CFF Explorer
ELF: readelf
, objdump
Mach-O: otool
, MachOView
Executable headers are a critical component of any operating system, providing the necessary information for loading and executing programs. These headers vary across operating systems, each with its own structure and format. By understanding these headers and the tools used to create them, developers can optimize program performance and ensure compatibility across different operating systems. The detailed knowledge of PE, ELF, and Mach-O headers, along with the tools for assembly, linking, and analysis, empowers developers to create robust and efficient executable files tailored to specific operating environments.