pub struct Object { /* private fields */ }Expand description
One compilation unit handed to the linker: named byte sections, the symbols defined in them, and the relocations still to be patched.
An object is the linker’s input island — the form a backend or an object-file reader
produces. Build one with new, append bytes with
section, mark addresses with define, and
record holes to fill with relocate. The object carries no
addresses of its own; link assigns them when it lays every object out
together.
Sections are addressed by name. Appending to a name that already exists extends that section rather than starting a new one, so an object holds at most one section per name.
§Examples
Build an object with a .text section and a symbol at its start:
use linker_lang::Object;
let mut obj = Object::new("greeter");
obj.section(".text", b"\xc3".to_vec()); // a one-byte `ret`
obj.define("greet", ".text", 0);
assert_eq!(obj.name(), "greeter");Implementations§
Source§impl Object
impl Object
Sourcepub fn new(name: impl Into<String>) -> Self
pub fn new(name: impl Into<String>) -> Self
Creates an empty object with the given name.
The name identifies the object in diagnostics — for example, which object a
RelocationOutOfRange came from — and is
not otherwise linked into the image.
§Examples
use linker_lang::Object;
let obj = Object::new("module.o");
assert_eq!(obj.name(), "module.o");Sourcepub fn section(
&mut self,
name: impl Into<String>,
data: impl Into<Vec<u8>>,
) -> u64
pub fn section( &mut self, name: impl Into<String>, data: impl Into<Vec<u8>>, ) -> u64
Appends data to the section named name, creating the section if it is new, and
returns the offset within that section where data begins.
The returned offset is the natural anchor for a symbol or relocation you place next:
it is 0 for a fresh section and the previous length when extending one. Sections
with the same name across objects merge at link time in object order.
§Examples
Two appends build one section; the second starts where the first ended:
use linker_lang::Object;
let mut obj = Object::new("data");
assert_eq!(obj.section(".data", [1, 2, 3, 4]), 0);
assert_eq!(obj.section(".data", [5, 6]), 4); // appended after the first chunkSourcepub fn define(
&mut self,
name: impl Into<String>,
section: impl Into<String>,
offset: u64,
)
pub fn define( &mut self, name: impl Into<String>, section: impl Into<String>, offset: u64, )
Defines a symbol named name at offset bytes into the section section.
The symbol resolves to an absolute address once the image is laid out. Defining the
same name in two objects is a DuplicateSymbol
error at link time; naming a section the object never created is an
InvalidSection error.
§Examples
use linker_lang::Object;
let mut obj = Object::new("code");
obj.section(".text", [0u8; 16]);
obj.define("entry", ".text", 0);
obj.define("helper", ".text", 8);Sourcepub fn relocate(
&mut self,
section: impl Into<String>,
offset: u64,
target: impl Into<String>,
width: Width,
addend: i64,
)
pub fn relocate( &mut self, section: impl Into<String>, offset: u64, target: impl Into<String>, width: Width, addend: i64, )
Records a relocation: the width bytes at offset in section hold the address of
target, plus addend.
At link time the target is resolved to its address, addend is added, and the
result is written into the section’s bytes little-endian. A target no object defines
is an UndefinedSymbol; a slot that runs past
the section’s bytes is a RelocationOutOfRange;
a resolved value too large for width is a
RelocationOverflow.
§Examples
A pointer slot that should hold the address of entry, and a second that should
hold the address eight bytes past it:
use linker_lang::{Object, Width};
let mut obj = Object::new("vectors");
obj.section(".data", [0u8; 16]);
obj.relocate(".data", 0, "entry", Width::U64, 0);
obj.relocate(".data", 8, "entry", Width::U64, 8);