Skip to main content

Crate linker_lang

Crate linker_lang 

Source
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 section is 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 symbol names 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 relocation is 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 requested Width.

§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 only alloc.
  • serde — derives Serialize and Deserialize for Image and LinkError, 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.
OutputSection
One laid-out section in a linked Image: a name, the address it begins at, and its merged, relocated bytes.

Enums§

LinkError
The reason a link could not be completed.
Width
The size of the address a relocation patches in.

Functions§

link
Links objects into an Image with the default configuration.