Skip to main content

rucc_object/
section.rs

1//! What an object writer is given, which is a section of bytes and what the linker has to be
2//! told about them.
3//!
4//! Design: `spec/11-asm-objects-debug.md` sections 11.1 and 11.3.
5//!
6//! These types are here rather than beside the assembler that fills them in because they are what
7//! an object file is made of, and because a writer cannot depend on the thing that produces its
8//! input without the graph going the wrong way round. The assembler at layer rank 10 reaches down
9//! to these at rank 8, which is the direction `spec/18-package-layout.md` asks for.
10
11/// A text section, and what the linker has to be told about it.
12#[derive(Debug, Clone, Default, PartialEq, Eq)]
13pub struct Text {
14    /// The instructions, in the order they were laid out.
15    pub bytes: Vec<u8>,
16    /// Where each function starts and how long it is, in the order they were written.
17    pub funcs: Vec<Extent>,
18    /// Every place in the bytes that names something the linker has to find.
19    pub relocs: Vec<Reloc>,
20}
21
22/// Where one function ended up.
23///
24/// How long a function is is a fact ELF records and Mach-O has no way to, so it is handed over
25/// rather than worked out again: the writer that wants it has it and the one that does not
26/// ignores it.
27#[derive(Debug, Clone, PartialEq, Eq)]
28pub struct Extent {
29    /// The function's name, as the C program spelled it. The underscore an Apple symbol carries
30    /// is the object writer's business, not this one's.
31    pub name: String,
32    /// Where its first instruction is.
33    pub start: usize,
34    /// How many bytes of instructions it is, not counting the padding in front of the next one.
35    pub len: usize,
36}
37
38/// One reference to something this file does not contain.
39#[derive(Debug, Clone, PartialEq, Eq)]
40pub struct Reloc {
41    /// Where the four bytes the linker writes over begin.
42    pub at: usize,
43    /// What is wanted, as the C program spelled it.
44    pub symbol: String,
45    /// What the linker is being asked for.
46    pub kind: Reference,
47    /// What to add to the distance, which is the constant the instruction already meant plus the
48    /// bytes between the hole and the end of the instruction, negated. An instruction counts from
49    /// where it ends and a relocation counts from where it starts, and this is the difference.
50    pub addend: i64,
51}
52
53/// What kind of thing a relocation is asking the linker for.
54///
55/// Both are the distance from the end of an instruction to something, which is what every
56/// reference this compiler makes is, because it generates position independent code and nothing
57/// else. They are told apart because the linker may answer one of them with a stub and may not
58/// answer the other one that way.
59#[derive(Debug, Clone, Copy, PartialEq, Eq)]
60pub enum Reference {
61    /// A call, which the linker may satisfy with a stub that reaches further than the four bytes
62    /// would. `R_X86_64_PLT32` on ELF, and the same relocation a branch gets on the other two.
63    Call,
64    /// A datum, reached from the instruction pointer. `R_X86_64_PC32` on ELF.
65    Data,
66}