Linker Scripts
Architecture-specific linker scripts for Multiboot2, Limine, UEFI, and custom boot protocols.
Overview
Every Helix kernel profile requires a linker script that controls how the kernel binary is laid out in memory. The linker script determines:
- Load address — where the bootloader places the kernel in physical memory
- Virtual address — the kernel's virtual memory mapping (for higher-half kernels)
- Section layout — ordering of
.text,.rodata,.data,.bss - Program headers — ELF segment permissions (R/W/X)
- Special sections — boot protocol headers, relocation tables, GOT
Helix provides four linker scripts for different boot protocols and memory models.
| Script | Boot Protocol | Memory Model | KASLR |
|---|---|---|---|
profiles/minimal/linker.ld | Multiboot2 | Flat physical, 1 MB | No |
profiles/minimal/linker_pie.ld | Multiboot2 | PIE, higher-half | Yes |
profiles/limine/linker.ld | Limine | PIE + HHDM | Yes |
profiles/common/linker_base.ld | Universal | PIE, higher-half | Yes |
Minimal — Multiboot2
The simplest linker script. Loads the kernel at physical address 1 MB with a flat memory model (no virtual addressing). Best for quick prototyping and embedded targets.
Minimal — PIE
Higher-half variant of the minimal linker script. Produces a Position-Independent Executable (PIE) that supports KASLR. The kernel runs at virtual address -2GB (0xFFFFFFFF80000000) while loaded at physical address 1 MB.
Limine — PIE + HHDM
The Limine linker script produces a PIE binary with Higher-Half Direct Mapping (HHDM). This is the recommended script for production kernels.
Common Base Script
The universal base linker script that other scripts can include. Defines the standard section layout, symbol exports, and program headers for a PIE higher-half kernel.
Exported Symbols
All linker scripts export symbols that the kernel uses at runtime for memory management, relocation, and section boundary detection.
| Symbol | Script | Description |
|---|---|---|
_start | All | Entry point — 32-bit trampoline to long mode |
__bss_start / __bss_end | All | Zero-initialized data — cleared to 0 during boot |
_kernel_end | minimal | End of all kernel sections |
__kernel_start / __kernel_end | limine, uefi, common | Kernel image boundaries |
__text_start / __text_end | limine, uefi, common | Code segment — R-X |
__rodata_start / __rodata_end | limine, uefi, common | Read-only data — R-- |
__data_start / __data_end | limine, uefi, common | Mutable data — RW- |
__rela_start / __rela_end | PIE scripts | Relocation entries for KASLR |
__got_start / __got_end | PIE scripts | Global Offset Table |
Writing Your Own Linker Script
When creating a custom linker script for your profile:
- Choose your base — Start from the closest existing script (minimal for flat, common for higher-half)
- Set the entry point — Must match your
helix.tomlboot.entryvalue - Align sections to 4K — Required for page-granular memory protection
- Export BSS symbols — The kernel zeroes
.bssduring early boot - Add boot protocol headers — Multiboot2 header, Limine requests, or UEFI entry
- Test with
objdump— Verify section layout withobjdump -h build/output/helix-kernel