rucc_object/lib.rs
1//! ELF, Mach-O and COFF object writers.
2//!
3//! Design: `spec/11-asm-objects-debug.md`. Layer rank 9, see `spec/18-package-layout.md`.
4//!
5//! # Status
6//!
7//! ELF, which is what Linux and the freestanding targets want and what M3 needs. A text section,
8//! the symbols that say where each function in it is and how long it is, the names it wanted that
9//! are not in it, the relocations that ask a linker to find them, and the marker whose absence
10//! makes the stack executable. An object this writes links with the system linker and runs.
11//!
12//! The variables a file defines are written too: the section each one goes in, the symbol that
13//! says where it is and how long it is, the binding that says who can see it, and the relocations
14//! an image asks for when it holds the address of something. A tentative definition is asked of
15//! the linker rather than put in a section, which is the one case where a variable has a symbol
16//! and no bytes anywhere.
17//!
18//! An [`Alias`] is written as a second symbol at the first one's section, value and size, with a
19//! binding of its own and no second copy of the bytes, which is what a file gets from
20//! `__attribute__((alias("target")))` and what makes one name reach another at no cost.
21//!
22//! [`Sections`] says whether each function and each variable gets a section to itself, which is
23//! what `-ffunction-sections` and `-fdata-sections` ask for and what makes `--gc-sections` able to
24//! drop anything: a linker can leave out a section nothing reaches and cannot leave out half of
25//! one. The names and the offsets are the same either way, so the only thing that moves is which
26//! section header a symbol points at.
27//!
28//! [`Array`] is what a section of function addresses for the startup code to call is, which is what
29//! the `constructor` and `destructor` attributes produce. ELF has a section type for each of the
30//! three kinds, and a section of the ordinary type under one of those names is gathered by the
31//! linker in the same run and called by nobody, so the type is written out rather than left to the
32//! default.
33//!
34//! [`Property`] is what the file says it was built to have checked, which is what
35//! `-fcf-protection=` asks for. It is written as a note the linker keeps only the agreed part of
36//! and the loader reads out of the result, which is why a file that says nothing about it turns
37//! the check off for the whole program rather than only for itself.
38//!
39//! [`defines`] says which names a linker can find in what [`write()`] wrote, which is what the symbol
40//! index of an archive is built from. It is here rather than worked out by whoever writes the
41//! archive because the index has to agree with the member, and the writer is the only thing that
42//! knows what it put in one.
43//!
44//! What it is given is [`Text`], [`Data`] and the aliases between them, which are here rather than
45//! beside the assembler that fills them in because they are what an object file is made of and
46//! because a writer cannot depend on the thing that produces its input without the layer graph
47//! going the wrong way round.
48//!
49//! Mach-O and COFF are not written yet. Both wait on the target that needs them.
50//!
51//! Every crate in the workspace is published, and publishing implies a promise. This one is
52//! tier 3: its Rust API is explicitly unstable and will change without a major version bump.
53//! Depend on the `rucc` binary's behaviour, not on this.
54
55#![doc(html_root_url = "https://docs.rs/rucc-object/0.10.45")]
56
57mod elf;
58mod section;
59
60pub use crate::elf::{Error, defines, write};
61pub use crate::section::{
62 Alias, Array, Binding, Data, Extent, FUNC_ALIGN, Marker, Object, Output, Patch, Place,
63 Property, Reference, Reloc, Sections, Text, Unwind, Visibility,
64};
65
66/// The milestone in `spec/17-milestones.md` that fills this crate in.
67pub const MILESTONE: &str = "M3";
68
69#[cfg(test)]
70mod tests {
71 #[test]
72 fn milestone_is_recorded() {
73 assert!(super::MILESTONE.starts_with('M'));
74 }
75}