Skip to main content

linker_lang/
lib.rs

1//! # linker_lang
2//!
3//! A small static linker: it combines independently compiled [`Object`]s into a single
4//! laid-out [`Image`].
5//!
6//! Each compilation unit a backend produces is its own island — a few named byte
7//! [sections](Object::section), a set of [symbols](Object::define) that mark addresses
8//! inside them, and [relocations](Object::relocate) that still need an address filled in.
9//! Linking is the step that joins those islands: it lays the sections of every object end
10//! to end, resolves each symbol to its final address in that layout, and patches the
11//! relocations with the addresses they were waiting for. The result is an [`Image`] whose
12//! bytes are ready to load and whose symbol table says where everything ended up.
13//!
14//! [`link`] is the one-call entry point; [`Linker`] is the same thing with a base address
15//! and an entry point to configure. The model is format-agnostic — an ELF or PE reader
16//! feeds the same [`Object`], and a writer turns an [`Image`] back into a file — so the
17//! crate carries the linking logic without committing to one container format.
18//!
19//! ## Linking model
20//!
21//! - A [`section`](Object::section) is a named run of bytes (`.text`, `.data`, …).
22//!   Sections that share a name across objects are concatenated into one output section,
23//!   in the order the objects are given.
24//! - A [`symbol`](Object::define) names an offset inside a section. After layout it
25//!   resolves to an absolute address — its section's address plus the object's place in
26//!   that section plus the offset.
27//! - A [`relocation`](Object::relocate) is a hole at some offset in a section that must
28//!   hold the address of a named symbol (plus an addend). The linker resolves the target
29//!   and writes the address into the section bytes, little-endian, in the requested
30//!   [`Width`].
31//!
32//! ## Example
33//!
34//! Link two objects where a `.data` slot must point at a symbol defined in `.text`:
35//!
36//! ```
37//! use linker_lang::{link, Width};
38//!
39//! // The code: a symbol `start` at the top of `.text`.
40//! let mut code = linker_lang::Object::new("code");
41//! code.section(".text", [0x90, 0x90, 0x90, 0x90]);
42//! code.define("start", ".text", 0);
43//!
44//! // The data: an 8-byte slot that should hold the address of `start`.
45//! let mut data = linker_lang::Object::new("data");
46//! data.section(".data", [0; 8]);
47//! data.relocate(".data", 0, "start", Width::U64, 0);
48//!
49//! let image = link(&[code, data]).expect("symbols resolve");
50//!
51//! // `.text` is laid out first at address 0, so `start` resolves there, and the slot in
52//! // `.data` was patched with that address.
53//! assert_eq!(image.symbol("start"), Some(0));
54//! let slot = &image.section(".data").unwrap().data()[..8];
55//! assert_eq!(u64::from_le_bytes(slot.try_into().unwrap()), 0);
56//! ```
57//!
58//! ## Features
59//!
60//! - `std` (default) — links the standard library. Without it the crate is `#![no_std]`
61//!   and needs only `alloc`.
62//! - `serde` — derives `Serialize` and `Deserialize` for [`Image`] and [`LinkError`], so a
63//!   linked image or a failure can be cached, logged, or moved between tools.
64//!
65//! ## Stability
66//!
67//! The public surface is frozen and stable as of `1.0.0`: it follows Semantic Versioning,
68//! with no breaking changes before `2.0`. [`LinkError`] is `#[non_exhaustive]`, so a linker
69//! reporting a new kind of failure is an additive, non-breaking change. The full surface and
70//! the SemVer promise are catalogued in
71//! [`docs/API.md`](https://github.com/jamesgober/linker-lang/blob/main/docs/API.md#semver-promise).
72
73#![cfg_attr(not(feature = "std"), no_std)]
74#![cfg_attr(docsrs, feature(doc_cfg))]
75#![deny(missing_docs)]
76#![forbid(unsafe_code)]
77#![deny(
78    clippy::unwrap_used,
79    clippy::expect_used,
80    clippy::panic,
81    clippy::todo,
82    clippy::unimplemented,
83    clippy::unreachable,
84    clippy::dbg_macro,
85    clippy::print_stdout,
86    clippy::print_stderr
87)]
88
89extern crate alloc;
90
91mod error;
92mod image;
93mod link;
94mod object;
95
96pub use error::LinkError;
97pub use image::{Image, OutputSection};
98pub use link::{Linker, link};
99pub use object::{Object, Width};