ELF Loader
Overview
The ELF (Executable and Linkable Format) loader is responsible for loading and executing ELF executables. It supports both 32-bit and 64-bit ELF files and handles program segment loading, stack setup, and entry point execution.
Components
1. ELF Parser
Location: kernel/loader/elf.asm
Parses ELF file headers and program segments:
- Header Parsing: Validates ELF magic, class, machine type, and file type
- 32-bit Support: Handles 32-bit ELF executables (ET_EXEC, ET_DYN)
- 64-bit Support: Handles 64-bit ELF executables (ET_EXEC, ET_DYN)
- Segment Loading: Loads PT_LOAD segments into memory
- BSS Handling: Zero-initializes BSS sections (when memsz > filesz)
Key Functions
elf_load_file()- Load ELF file from filesystemelf_parse_header()- Parse ELF header and validateelf_parse_header_32()- Parse 32-bit ELF headerelf_parse_header_64()- Parse 64-bit ELF headerelf_load_segments_32()- Load 32-bit program segmentself_load_segments_64()- Load 64-bit program segmentself_get_entry_point()- Get program entry point addresself_is_64bit_check()- Check if ELF is 64-bitelf_cleanup()- Clean up ELF loader state
2. Program Executor
Location: kernel/loader/elf_exec.asm
Sets up execution environment and runs programs:
- Stack Setup: Allocates and configures program stack
- Argument Passing: Sets up argc, argv, envp on stack
- Entry Point Execution: Transfers control to program entry point
- Cleanup: Handles program return and cleanup
Key Functions
elf_execute()- Execute loaded ELF programelf_execute_32bit()- Execute 32-bit programelf_setup_stack()- Set up program stack
ELF Format Support
Supported ELF Types
- ET_EXEC: Executable files
- ET_DYN: Shared objects (dynamic libraries)
Supported Architectures
- 32-bit: x86 (ELF_MACHINE_386)
- 64-bit: x86_64 (ELF_MACHINE_X86_64)
Supported Segment Types
- PT_LOAD: Loadable segments (code and data)
- Other segment types are skipped
Loading Process
Step 1: Load ELF File
// Load ELF file from filesystem
int result = elf_load_file("/usr/lib/nodejs/bin/node");
if (result != 0) {
// Error loading file
}
Step 2: Parse ELF Header
- Read first 16 bytes (ELF identification)
- Verify ELF magic number (0x7F 'E' 'L' 'F')
- Check ELF class (32-bit or 64-bit)
- Verify machine type (x86 or x86_64)
- Check file type (executable or shared object)
- Extract entry point address
- Get program header table location
Step 3: Load Program Segments
- Read program header table
- For each PT_LOAD segment:
- Allocate memory for segment
- Copy segment data from file
- Zero-initialize BSS section if needed
- Map segment to virtual address (TODO)
Step 4: Set Up Stack
- Allocate 1MB stack
- Push environment variables (envp)
- Push NULL terminator for envp
- Push command-line arguments (argv)
- Push NULL terminator for argv
- Push argument count (argc)
Step 5: Execute Program
- Set up registers (EAX=argc, EBX=argv, ECX=envp)
- Call program entry point
- Handle program return
- Clean up allocated memory
Stack Layout
The program stack is set up as follows (growing downward):
High Address
┌─────────────────┐
│ envp[0] │ ← Environment variable pointers
│ envp[1] │
│ ... │
│ envp[n] │
│ NULL │ ← NULL terminator for envp
├─────────────────┤
│ argv[0] │ ← Command-line argument pointers
│ argv[1] │
│ ... │
│ argv[n] │
│ NULL │ ← NULL terminator for argv
├─────────────────┤
│ argc │ ← Argument count
├─────────────────┤
│ return addr │ ← Return address (0 for main)
└─────────────────┘
Low Address
Memory Management
ELF File Buffer
The entire ELF file is loaded into memory for parsing. This is allocated via kmalloc().
Program Segments
Each PT_LOAD segment is allocated separately. Memory is allocated via kmalloc().
Stack
A 1MB stack is allocated for program execution via kmalloc().
Cleanup
All allocated memory is freed via kfree() after program execution or on error.
Error Handling
ELF_ERROR_NONE- SuccessELF_ERROR_INVALID_MAGIC- Not an ELF fileELF_ERROR_UNSUPPORTED_CLASS- Unsupported ELF classELF_ERROR_UNSUPPORTED_MACHINE- Unsupported architectureELF_ERROR_INVALID_TYPE- Unsupported file typeELF_ERROR_READ_FAILED- Failed to read file from filesystemELF_ERROR_MEMORY_ALLOC_FAILED- Out of memoryELF_ERROR_INVALID_SEGMENT- Invalid segment data
Integration Points
With Filesystem
The ELF loader uses the filesystem driver to read ELF files from disk.
With execve()
The execve() system call uses the ELF loader to load and execute programs.
With Process Management
Process creation uses the ELF loader to load program images.
Build System
The ELF loader is built as part of the kernel:
cd kernel/loader
make
This compiles:
elf.asm- ELF parser and loaderelf_exec.asm- Program executor
Future Enhancements
- Relocation handling
- Dynamic linking support
- Shared library loading
- Symbol resolution
- Virtual address space mapping
- Process isolation
Related Documentation
- File System - Reading ELF files from disk
- Process Management - execve() implementation
- System Calls - execve syscall
- Memory Management - Memory allocation for segments