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}