Expand description
§linker_lang
A small static linker: it combines independently compiled Objects into a single
laid-out Image.
Each compilation unit a backend produces is its own island — a few named byte
sections, a set of symbols that mark addresses
inside them, and relocations that still need an address filled in.
Linking is the step that joins those islands: it lays the sections of every object end
to end, resolves each symbol to its final address in that layout, and patches the
relocations with the addresses they were waiting for. The result is an Image whose
bytes are ready to load and whose symbol table says where everything ended up.
link is the one-call entry point; Linker is the same thing with a base address
and an entry point to configure. The model is format-agnostic — an ELF or PE reader
feeds the same Object, and a writer turns an Image back into a file — so the
crate carries the linking logic without committing to one container format.
§Linking model
- A
sectionis a named run of bytes (.text,.data, …). Sections that share a name across objects are concatenated into one output section, in the order the objects are given. - A
symbolnames an offset inside a section. After layout it resolves to an absolute address — its section’s address plus the object’s place in that section plus the offset. - A
relocationis a hole at some offset in a section that must hold the address of a named symbol (plus an addend). The linker resolves the target and writes the address into the section bytes, little-endian, in the requestedWidth.
§Example
Link two objects where a .data slot must point at a symbol defined in .text:
use linker_lang::{link, Width};
// The code: a symbol `start` at the top of `.text`.
let mut code = linker_lang::Object::new("code");
code.section(".text", [0x90, 0x90, 0x90, 0x90]);
code.define("start", ".text", 0);
// The data: an 8-byte slot that should hold the address of `start`.
let mut data = linker_lang::Object::new("data");
data.section(".data", [0; 8]);
data.relocate(".data", 0, "start", Width::U64, 0);
let image = link(&[code, data]).expect("symbols resolve");
// `.text` is laid out first at address 0, so `start` resolves there, and the slot in
// `.data` was patched with that address.
assert_eq!(image.symbol("start"), Some(0));
let slot = &image.section(".data").unwrap().data()[..8];
assert_eq!(u64::from_le_bytes(slot.try_into().unwrap()), 0);§Features
std(default) — links the standard library. Without it the crate is#![no_std]and needs onlyalloc.serde— derivesSerializeandDeserializeforImageandLinkError, so a linked image or a failure can be cached, logged, or moved between tools.
§Stability
The public surface is frozen and stable as of 1.0.0: it follows Semantic Versioning,
with no breaking changes before 2.0. LinkError is #[non_exhaustive], so a linker
reporting a new kind of failure is an additive, non-breaking change. The full surface and
the SemVer promise are catalogued in
docs/API.md.
Structs§
- Image
- A linked image: the laid-out sections, the resolved symbol table, and the entry point.
- Linker
- A configured linker: a base address and an optional entry point.
- Object
- One compilation unit handed to the linker: named byte sections, the symbols defined in them, and the relocations still to be patched.
- Output
Section - One laid-out section in a linked
Image: a name, the address it begins at, and its merged, relocated bytes.
Enums§
- Link
Error - The reason a
linkcould not be completed. - Width
- The size of the address a relocation patches in.