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 11 reaches down
9//! to these at rank 9, which is the direction `spec/18-package-layout.md` asks for.
10
11/// What a function is aligned to when nothing asked for more.
12///
13/// Sixteen because that is what every x86-64 toolchain puts a function at, and because it is what
14/// keeps the loop inside one from straddling one more cache line than it has to. Here rather than
15/// beside the assembler because the assembler pads to it and the writer records it, and two
16/// copies of one number is how the padding and the record come apart.
17pub const FUNC_ALIGN: u32 = 16;
18
19/// Whether each function and each variable gets a section to itself.
20///
21/// Design: `spec/11-asm-objects-debug.md` section 11.3, and `spec/04-driver-and-cli.md` section 4.7
22/// for the flags that ask for it.
23///
24/// A linker can drop a section nothing reaches and cannot drop half of one, so a file whose
25/// functions share a section keeps every function that file defines in the output as soon as any
26/// one of them is called. Splitting them is what makes `--gc-sections` do anything, which is how an
27/// embedded image or a kernel gets small, and it is the whole of what these two flags are for. The
28/// cost is a section header per name, which is why it is asked for rather than always done.
29///
30/// Not one flag, because gcc has two and a build that wants one of them and not the other is a
31/// build that measured something. Splitting the code is nearly free at link time; splitting the
32/// data can defeat the linker's ordering of what is next to what.
33#[derive(Debug, Clone, Copy, Default, PartialEq, Eq)]
34pub struct Sections {
35    /// `-ffunction-sections`. Each function in `.text.<name>` rather than all of them in `.text`.
36    pub functions: bool,
37    /// `-fdata-sections`. Each variable in a section named after it rather than in the one its
38    /// contents would otherwise have chosen.
39    pub data: bool,
40}
41
42impl Sections {
43    /// Whether either of them was asked for.
44    #[must_use]
45    pub const fn any(self) -> bool {
46        self.functions || self.data
47    }
48}
49
50/// What a file says it was built to have checked, which is what `-fcf-protection=` asks for.
51///
52/// Design: `spec/11-asm-objects-debug.md` section 11.3, and `spec/04-driver-and-cli.md` section 4.7
53/// for the flag.
54///
55/// A machine's control flow checks are turned on for a whole process or not at all, never for one
56/// function, so a program made of one object built with them and one built without has to be run
57/// one way or the other. What everybody settled on is that each object records what it was built
58/// for, the linker keeps only what every input agreed on, and the loader turns on what is left. So
59/// an object that records nothing turns the check off for every object it is linked with, which is
60/// why this is written even when the flag changed no instruction in the file.
61///
62/// One number rather than a pair of flags, because that is what the record holds: a word of bits
63/// whose meaning is the machine's, and a linker that has never heard of a bit still knows to drop
64/// it when one input does not have it.
65#[derive(Debug, Clone, Copy, Default, PartialEq, Eq)]
66pub struct Property {
67    /// The bits of the x86 feature word, which are [`Self::IBT`] and [`Self::SHSTK`].
68    pub features: u32,
69}
70
71impl Property {
72    /// Which property the feature word is, which is the key the record is written under.
73    pub const X86_FEATURES: u32 = 0xc000_0002;
74    /// Indirect branch tracking: every indirect call and jump in the file arrives at a landing
75    /// pad, so the machine may fault on one that does not.
76    pub const IBT: u32 = 1;
77    /// The shadow stack: every return in the file goes where a second copy of the return address
78    /// says it should, so the machine may fault when the two disagree.
79    pub const SHSTK: u32 = 2;
80
81    /// Whether anything is recorded at all, which is whether the record is written.
82    #[must_use]
83    pub const fn any(self) -> bool {
84        self.features != 0
85    }
86}
87
88/// What the command line decided about the file being written, as against what the code in it
89/// decided.
90///
91/// Two answers with nothing to do with each other, together because they arrive together: neither
92/// can be worked out from a function, and the listing and the byte writer have to be handed the
93/// same pair or the two outputs of one command line would not be the same file.
94#[derive(Debug, Clone, Copy, Default, PartialEq, Eq)]
95pub struct Output {
96    /// Whether each function and each variable gets a section to itself.
97    pub sections: Sections,
98    /// What the file says it was built to have checked.
99    pub property: Property,
100}
101
102/// A text section, and what the linker has to be told about it.
103#[derive(Debug, Clone, PartialEq, Eq)]
104pub struct Text {
105    /// The instructions, in the order they were laid out.
106    pub bytes: Vec<u8>,
107    /// Where each function starts and how long it is, in the order they were written.
108    pub funcs: Vec<Extent>,
109    /// Every place in the bytes that names something the linker has to find.
110    pub relocs: Vec<Reloc>,
111    /// Every place inside a function that has a name of its own, in the order they were written.
112    pub labels: Vec<Marker>,
113    /// What the whole section has to be aligned to, which is the largest alignment any function
114    /// in it asked for.
115    ///
116    /// A function is at a fixed offset inside the section, so a function at a multiple of two
117    /// hundred and fifty six is one only if the section itself is at one. The padding between the
118    /// functions is the assembler's half of the same job and this is the linker's.
119    pub align: u32,
120    /// What an unwinder is told about the functions, which is empty for a format that has no such
121    /// section or a build that asked for none.
122    pub unwind: Unwind,
123    /// The jump tables that are read rather than run, and so go in a read only section of data
124    /// rather than in these bytes. Empty on a format that keeps its tables after the function.
125    pub tables: Vec<Table>,
126}
127
128impl Default for Text {
129    fn default() -> Self {
130        Self {
131            bytes: Vec::new(),
132            funcs: Vec::new(),
133            relocs: Vec::new(),
134            labels: Vec::new(),
135            align: FUNC_ALIGN,
136            unwind: Unwind::default(),
137            tables: Vec::new(),
138        }
139    }
140}
141
142/// The unwind table, as the bytes of the section or two it goes in and what the linker has to be
143/// told about them.
144///
145/// Bytes rather than rows, because what a record is is the platform's answer rather than the object
146/// writer's, and the layer that knows what a frame did is the one that can say it in the fewest of
147/// them. What is left for the writer is where the sections go and what their relocations are.
148///
149/// Two of them, because the two platforms lay the same facts out differently. ELF writes one section
150/// of records, each a little program an unwinder runs to rebuild the frame at an address, and each
151/// carrying its own codes, so [`Self::info`] is empty there. Windows writes a table of fixed rows
152/// sorted by address, one per function, each pointing at the description of that function's prologue
153/// in a second section, which is what [`Self::info`] holds.
154///
155/// Every record says where its function is, and where a function is is a number no compilation
156/// knows: a function is at a fixed offset inside its own section and the section is placed by the
157/// linker. So there are relocations, and which kind they are is the format's answer too.
158#[derive(Debug, Clone, Default, PartialEq, Eq)]
159pub struct Unwind {
160    /// The records: one shared header and one per function on ELF, and one row per function on
161    /// Windows.
162    pub bytes: Vec<u8>,
163    /// Every place in them that names something the linker has to place, which is the functions
164    /// they are about and, where there is a second section, the description each row points at.
165    pub relocs: Vec<Reloc>,
166    /// What those records point at, on the format that keeps the two apart, and nothing at all on
167    /// the one whose records carry their own.
168    pub info: Vec<u8>,
169    /// The names inside [`Self::info`], one per function that has a description there, which are
170    /// what the relocations above ask for.
171    ///
172    /// Names rather than offsets because a relocation names a symbol, and the record and the thing
173    /// it points at are in two different sections, so there is no distance either of them can be
174    /// written with instead.
175    pub labels: Vec<Marker>,
176}
177
178/// The debug information, as the bytes of the sections it goes in.
179///
180/// Bytes rather than anything shaped like DWARF, for the reason [`Unwind`] is bytes: what a record
181/// is is the format's answer and the layer that knows what the program was doing is the one that
182/// can say it, and what is left for the writer is where the sections go and what their relocations
183/// are. The difference between the two is only that there are more than two sections here and that
184/// their names are not the writer's to choose, so each one carries its own.
185#[derive(Debug, Clone, Default, PartialEq, Eq)]
186pub struct Info {
187    /// One entry per section that has anything in it, in the order they are to be written.
188    ///
189    /// The order matters because a relocation in one of them can name another, and a name is
190    /// resolved against the sections this file already has. Writing them in the order the producer
191    /// hands them over keeps that a property of the list rather than of the writer.
192    pub chunks: Vec<Chunk>,
193}
194
195/// One debug section, with the name it goes in the file under.
196///
197/// A relocation here names either a function this file defines or another section in the same
198/// list, and the two are told apart by looking the name up among the sections first. That is safe
199/// rather than lucky: every section name in DWARF begins with `.debug_`, which is not the spelling
200/// of any name a C program can define.
201#[derive(Debug, Clone, PartialEq, Eq)]
202pub struct Chunk {
203    /// What the section is called, which is the name DWARF gives it.
204    pub name: String,
205    /// Its contents.
206    pub bytes: Vec<u8>,
207    /// Every place in them that names something this file does not place itself.
208    pub relocs: Vec<Reloc>,
209}
210
211/// Where the room a patcher was promised at the top of a function ended up.
212///
213/// What `-fpatchable-function-entry=` asks for, once it is bytes rather than instructions. Two
214/// numbers because the writer has two questions: where the address it records points, and how much
215/// of the function is in front of the symbol.
216///
217/// They are not the same number. The room can be split by the landing pad a function opens with,
218/// since the pad has to be the first instruction after the label and the room does not, so the part
219/// in front of the label and the part after it are not always next to each other. What is recorded
220/// is the front of the whole thing, which is the part in front of the label when there is one.
221#[derive(Debug, Clone, Copy, PartialEq, Eq)]
222pub struct Patch {
223    /// Where the room begins, as an offset into the same bytes [`Extent::start`] is one into.
224    pub at: usize,
225    /// How many bytes of the function are in front of [`Extent::start`], which is where its symbol
226    /// is and where an unwinder is told the function begins.
227    pub before: usize,
228}
229
230/// Where a place inside a function that has a name of its own ended up.
231///
232/// What asks for one is GNU's address of a label in the initializer of an object with static
233/// storage duration. A label is somewhere a jump goes and a jump is a distance the assembler works
234/// out, so no ordinary label is in the symbol table at all. An image is the other case: it is in
235/// another section, so what it holds is a relocation, and a relocation names a symbol.
236///
237/// The name is never one the program wrote, so nothing outside this file looks it up and it is
238/// always local: it is here for a relocation in this same file to resolve against, and a linker
239/// that offered it to another file would be offering the middle of a function.
240#[derive(Debug, Clone, PartialEq, Eq)]
241pub struct Marker {
242    /// The name, which is whatever the compiler minted for it.
243    pub name: String,
244    /// Where it is, as an offset into the same bytes [`Extent::start`] is one into.
245    pub at: usize,
246}
247
248/// One jump table of one function, kept out of the instructions.
249///
250/// A table is data the function reads, and gcc and clang put it in `.rodata` rather than in the
251/// code. Keeping it there keeps data out of the lines the instruction fetcher reads and keeps the
252/// executable sections to what is executed, which is also what a size counted by section is
253/// measuring. The cost is that the two ends of every cell are now in different sections, so each
254/// cell is a relocation the linker fills in rather than a number the assembler writes, which is
255/// what gas does with the same `.long .L3-.L4` when the `.L4` is in `.rodata`.
256///
257/// Each cell is still the distance from the front of the table to a block, so the code that reads
258/// one is the same code wherever the table is.
259#[derive(Debug, Clone, PartialEq, Eq)]
260pub struct Table {
261    /// The name the instruction that reads it gives it, which is local to this file.
262    pub name: String,
263    /// Which of [`Text::funcs`] it belongs to.
264    pub func: usize,
265    /// Where each cell's block is, counted from [`Extent::start`] of that function.
266    pub cells: Vec<usize>,
267}
268
269/// Where one function ended up.
270///
271/// How long a function is is a fact ELF records and Mach-O has no way to, so it is handed over
272/// rather than worked out again: the writer that wants it has it and the one that does not
273/// ignores it.
274#[derive(Debug, Clone, PartialEq, Eq)]
275pub struct Extent {
276    /// The function's name, as the C program spelled it. The underscore an Apple symbol carries
277    /// is the object writer's business, not this one's.
278    pub name: String,
279    /// Where its first instruction is.
280    pub start: usize,
281    /// How many bytes of instructions it is, not counting the padding in front of the next one.
282    pub len: usize,
283    /// What this one function asked to be aligned to, which is not always what the section it is
284    /// in was aligned to.
285    ///
286    /// The two are the same number only when this function is the one that asked for the most.
287    /// Under [`Sections::functions`] each function is a section of its own and this is what that
288    /// section is aligned to, so the number has to survive the trip rather than be recovered from
289    /// the offset, which says nothing once the function is at zero in a section of its own.
290    pub align: u32,
291    /// How the linker sees the name, which is what the C `static` reaches the object file as.
292    pub binding: Binding,
293    /// How far outside a shared library holding this the name reaches.
294    pub visibility: Visibility,
295    /// Where the room a patcher was promised is, or `None` in a function promised none, which is
296    /// every function on a command line that did not ask. See [`Patch`].
297    pub patch: Option<Patch>,
298}
299
300/// The variables a file defines, and what the linker has to be told about them.
301///
302/// One entry per variable rather than one section of everything, because where a variable goes is
303/// worked out from what it is and two of them that land in one section still have their own
304/// alignment, their own size and their own symbol. Putting them together is the writer's job and
305/// is the one part of it the three formats disagree about.
306#[derive(Debug, Clone, Default, PartialEq, Eq)]
307pub struct Data {
308    /// Every variable this file defines, in the order the module held them.
309    pub objects: Vec<Object>,
310    /// Every name this file declares weak and does not define, in the order the module held them.
311    ///
312    /// Each becomes an undefined symbol the linker is allowed to leave undefined, whose references
313    /// then read a zero address. A name here is not an object and carries no bytes, which is why
314    /// it is a list of names beside the objects rather than one of them.
315    pub weak: Vec<String>,
316    /// Every distance between two labels an image holds, which the writer fills in once it knows
317    /// where the labels are. See [`Apart`].
318    pub apart: Vec<Apart>,
319}
320
321/// How far one label is from another, written into a variable's image.
322///
323/// What `static int b[] = { &&l1 - &&l0 };` asks for. Neither label has an address until the
324/// link, and yet both are in the one function's code and the code moves as one piece, so the
325/// distance is known as soon as the code is laid out. That makes it a number the writer puts in
326/// the bytes itself rather than a relocation it asks the linker for, which is what gas does with
327/// `.long .L1-.L0` too, and it is why a label in another function is refused: the two could land
328/// in different sections and then no number is right.
329#[derive(Debug, Clone, PartialEq, Eq)]
330pub struct Apart {
331    /// Which of [`Data::objects`] the distance is written into.
332    pub object: usize,
333    /// How far into that object's image.
334    pub at: usize,
335    /// The label measured to, as the image named it.
336    pub to: String,
337    /// The label measured from.
338    pub from: String,
339    /// What to add to the distance.
340    pub addend: i64,
341    /// How many bytes the distance is written in.
342    pub bytes: u8,
343}
344
345/// A second name for something the same file defines.
346///
347/// Not a section and not a byte of anything, which is the whole point of it: an alias is a symbol
348/// table entry pointing at an address something else already occupies, so a file with one in it is
349/// no larger than the same file without. `.set b, a` is what an assembler is told and a second
350/// entry at the first one's section, value and size is what a writer produces, and the two say the
351/// same thing.
352///
353/// The target is a name rather than an index into anything above, because the two output paths
354/// find it in different places: a listing hands the name to an assembler that resolves it, and a
355/// writer looks it up among the symbols it has already added.
356#[derive(Debug, Clone, PartialEq, Eq)]
357pub struct Alias {
358    /// The name being defined, as the C program spelled it.
359    pub name: String,
360    /// The name it stands for, which has to be something this same file defines.
361    pub target: String,
362    /// How the linker sees the new name, which is not always how it sees the old one: the target
363    /// of `extern int b __attribute__((alias("a")))` may be a `static`.
364    pub binding: Binding,
365    /// How far outside a shared library holding this the new name reaches, which is its own
366    /// answer for the same reason the binding is: the attribute is written on the alias.
367    pub visibility: Visibility,
368}
369
370/// One global variable, laid out.
371#[derive(Debug, Clone, PartialEq, Eq)]
372pub struct Object {
373    /// Its name, as the C program spelled it. The underscore an Apple symbol carries is the
374    /// object writer's business, not this one's.
375    pub name: String,
376    /// Its image, and nothing at all when it is zero filled and the file carries none of it.
377    pub bytes: Vec<u8>,
378    /// How many bytes it occupies, which is the length of the image except when there is none.
379    pub size: u64,
380    /// What it has to be aligned to, always a power of two.
381    pub align: u64,
382    /// Which section it goes in.
383    pub place: Place,
384    /// How the linker sees the name.
385    pub binding: Binding,
386    /// How far outside a shared library holding this the name reaches.
387    pub visibility: Visibility,
388    /// Every place in its image that holds the address of a symbol, counted from the start of
389    /// the image rather than from the start of the section it lands in.
390    pub relocs: Vec<Reloc>,
391}
392
393/// Which section a variable goes in.
394///
395/// Worked out from what the variable is rather than named by it, except in the one case where the
396/// program named it. A reader who wants to know why a variable is in `.rodata` should be able to
397/// find the answer in the variable.
398#[derive(Debug, Clone, PartialEq, Eq)]
399pub enum Place {
400    /// Written to, and its image is not all zeros. `.data`.
401    Written,
402    /// Never written to, so it can go in a page the loader maps read only and every process
403    /// running the program can share. `.rodata`.
404    ReadOnly,
405    /// Never written to by the program, but written once by the dynamic linker, because its image
406    /// holds the address of something and an address is not known until the image is loaded.
407    /// `.data.rel.ro`.
408    ///
409    /// The section has to be writable for that one write and read only afterwards, which is what
410    /// the `PT_GNU_RELRO` segment is: the loader maps it, the relocations are applied, and then it
411    /// is turned read only before the program starts. Putting the variable in `.rodata` instead
412    /// means asking the linker to leave a relocation in a section that is never writable, and what
413    /// it does about that is give the whole image `DT_TEXTREL`, which gives up the protection the
414    /// section was for. Some hardened toolchains refuse the link outright.
415    RelocReadOnly {
416        /// Whether every address in the image is of something this file defines and does not
417        /// export, which means the link can resolve them all and none can be interposed.
418        ///
419        /// Those go in `.data.rel.ro.local`, which the linker puts in the first pages of the
420        /// segment, so the pages holding them are the ones the loader is done with soonest. It is
421        /// a hint about layout rather than a difference in what the section is.
422        local: bool,
423    },
424    /// All zeros, so the file says how big it is and carries none of it. `.bss`.
425    Zero,
426    /// One copy per thread rather than one copy per program. `.tdata` and `.tbss`.
427    ///
428    /// What the loader does with these two sections is what makes them different from every other
429    /// section here. Their contents are the template of a thread's own block of storage rather than
430    /// the storage itself: the image is laid out once, and every thread that starts gets a fresh
431    /// copy of it, so the address of a variable in one of them is a different address in every
432    /// thread and there is no single address for the link to write down. That is why a reference to
433    /// one is not the ordinary distance from the instruction pointer, and why the symbol is marked
434    /// as being of this kind so a linker refuses one that is.
435    ///
436    /// The pair is the same split as `.data` and `.bss` for the same reason, so an image that is
437    /// all zeros costs its size in the file and not its bytes.
438    Thread {
439        /// Whether the image is all zeros, which puts it in `.tbss` rather than `.tdata`.
440        zero: bool,
441    },
442    /// A tentative definition, which is not in a section at all: the linker is asked for that
443    /// much zeroed space and merges every definition of the name into one. `.comm`.
444    Merged,
445    /// The section the program named, from `__attribute__((section(...)))`.
446    Named(String),
447}
448
449impl Place {
450    /// What the section this variable goes in is called under [`Sections::data`], and nothing at
451    /// all for a variable that has no section of its own to be given.
452    ///
453    /// The name is the section it would otherwise have shared with a dot and the variable's name
454    /// after it, which is what gcc writes and is not merely a convention: `--gc-sections`, the
455    /// linker scripts a kernel and an embedded image are linked with, and the default placement
456    /// rules all match on the part in front of the dot, so a section called anything else would be
457    /// placed by whatever the catch all rule is.
458    ///
459    /// Two kinds of variable are left alone. A merged one is a request to the linker for that much
460    /// zeroed space rather than an image, so there is no section to split, and one the program put
461    /// a name on already has the answer the source gave, which this must not overrule.
462    ///
463    /// Here rather than beside either output path, so that the listing `-S` writes and the object
464    /// `-c` writes cannot come to disagree about where a variable went.
465    #[must_use]
466    pub fn split(&self, name: &str) -> Option<String> {
467        Some(format!("{}.{name}", self.base()?))
468    }
469
470    /// The section this variable goes in when nothing is being split up, and nothing at all for
471    /// the two kinds that are not in one.
472    #[must_use]
473    pub fn base(&self) -> Option<&'static str> {
474        Some(match self {
475            Place::Written => ".data",
476            Place::ReadOnly => ".rodata",
477            Place::RelocReadOnly { local: false } => ".data.rel.ro",
478            Place::RelocReadOnly { local: true } => ".data.rel.ro.local",
479            Place::Zero => ".bss",
480            Place::Thread { zero: false } => ".tdata",
481            Place::Thread { zero: true } => ".tbss",
482            Place::Merged | Place::Named(_) => return None,
483        })
484    }
485}
486
487/// A section holding function addresses for a C runtime to call rather than data for the program
488/// to read.
489///
490/// ELF has a type for each of the three, and a section of that type is what the startup code walks:
491/// the linker gathers every input section of the kind into one run and the CRT calls what it finds
492/// between the two ends. A section of the ordinary type with the same name would be gathered the
493/// same way and called by nothing, which is why the type is worth writing down rather than leaving
494/// to the default.
495///
496/// Only ELF says it this way. COFF sorts by what follows the `$` in a section name and Mach-O has
497/// a section attribute for it, so on those two the name carries the whole of the answer and there
498/// is nothing for this to be.
499#[derive(Debug, Clone, Copy, PartialEq, Eq)]
500pub enum Array {
501    /// Run on the way to `main`, in the order the linker sorted the sections into.
502    Init,
503    /// Run after `main` returns, in the reverse of that order.
504    Fini,
505    /// Run ahead of `.init_array` and ahead of the shared libraries a program is linked against,
506    /// which is a thing only the C library itself has a use for.
507    Preinit,
508}
509
510impl Array {
511    /// Which of them a section of this name is, and [`None`] for a name that is not one of them.
512    ///
513    /// The name itself or the name with a dot and a priority after it. A numbered `constructor` is
514    /// written as the second of those and is the same kind of section as the first: the number is
515    /// there so that the linker sorts it, not to make it a different thing.
516    #[must_use]
517    pub fn of(name: &str) -> Option<Array> {
518        let kinds = [
519            (".init_array", Array::Init),
520            (".fini_array", Array::Fini),
521            (".preinit_array", Array::Preinit),
522        ];
523        kinds.into_iter().find_map(|(base, array)| {
524            let rest = name.strip_prefix(base)?;
525            (rest.is_empty() || rest.starts_with('.')).then_some(array)
526        })
527    }
528
529    /// How the type is spelled in a `.section` directive.
530    #[must_use]
531    pub const fn asm(self) -> &'static str {
532        match self {
533            Array::Init => "@init_array",
534            Array::Fini => "@fini_array",
535            Array::Preinit => "@preinit_array",
536        }
537    }
538}
539
540/// How the linker sees a name.
541///
542/// Three of the five linkages the IR has, because that is how many an object file can say. Which
543/// of the two weak ones a symbol had is a fact the optimizer needs and the linker does not.
544#[derive(Debug, Clone, Copy, PartialEq, Eq)]
545pub enum Binding {
546    /// Visible to every other object, and the definition here is the definition.
547    Global,
548    /// Invisible outside this object, which is what `static` at file scope means.
549    Local,
550    /// Visible, and allowed to lose to a definition in another object.
551    Weak,
552}
553
554/// How far outside a shared library a name reaches.
555///
556/// A different question from [`Binding`] and asked of a different linker. The binding is what the
557/// static linker does with a name while it is building the output, and this is what the dynamic
558/// linker may do with it once the output is a shared library and is being loaded. A hidden name is
559/// still global to the static link, so two files in the same library can call each other by it; it
560/// is simply not in the dynamic symbol table afterwards, so nothing outside can name it.
561///
562/// Written down here as its own thing rather than folded into the binding because it is the
563/// mistake tamnd/rucc#733 was: a writer that has one word for both ends up saying something about
564/// visibility while it thinks it is saying something about linkage, and what it said was hidden.
565///
566/// It means nothing for a [`Binding::Local`] name. `static` is already invisible to the whole
567/// world outside the file, and ELF records `STV_DEFAULT` for one, which is what gcc writes.
568#[derive(Debug, Clone, Copy, Default, PartialEq, Eq)]
569pub enum Visibility {
570    /// In the dynamic symbol table, and a reference from inside the library may be satisfied by a
571    /// definition somewhere else, which is what makes `LD_PRELOAD` work. What a name gets when
572    /// nothing said otherwise.
573    #[default]
574    Default,
575    /// Not in the dynamic symbol table at all, so nothing outside the library can name it and
576    /// every reference to it from inside binds here. `__attribute__((visibility("hidden")))`.
577    Hidden,
578    /// In the dynamic symbol table, so something outside can name it, but a reference from inside
579    /// the library binds to the definition inside it and cannot be interposed.
580    Protected,
581}
582
583/// One reference to something this file does not contain.
584#[derive(Debug, Clone, PartialEq, Eq)]
585pub struct Reloc {
586    /// Where the bytes the linker writes over begin.
587    pub at: usize,
588    /// What is wanted, as the C program spelled it.
589    pub symbol: String,
590    /// What the linker is being asked for.
591    pub kind: Reference,
592    /// What to add to the distance, which is the constant the instruction already meant plus the
593    /// bytes between the hole and the end of the instruction, negated. An instruction counts from
594    /// where it ends and a relocation counts from where it starts, and this is the difference.
595    pub addend: i64,
596    /// How many bytes of the instruction come after the four the linker writes over, which is zero
597    /// for everything except an instruction carrying an immediate behind its displacement.
598    ///
599    /// Already inside [`Self::addend`] and written down again because the two formats disagree about
600    /// which of the two numbers they want. ELF takes the one number and counts from where the hole
601    /// starts, so the difference between that and where the instruction ends is the writer's to fold
602    /// in and nothing after it ever has to be told apart again. COFF counts from where the
603    /// instruction ends and says how far that is in the relocation type itself, which is what
604    /// `IMAGE_REL_AMD64_REL32_1` through `REL32_5` are, so it needs the two apart. A writer cannot
605    /// recover one from the other, since a displacement of minus four and no trailing bytes and a
606    /// displacement of zero and four of them are the same sum.
607    ///
608    /// Zero for a relocation in an image, where there is no instruction and the question does not
609    /// arise.
610    pub after: u8,
611}
612
613/// What kind of thing a relocation is asking the linker for.
614///
615/// The first four are the distance from the end of an instruction to something, which is what every
616/// reference the code makes is, because this compiler generates position independent code and
617/// nothing else. They are told apart by what the linker is allowed to do about each one. The last
618/// two are not distances from an instruction at all and are what a table of data asks for: the
619/// address itself, which is what an initializer holding the address of something holds, and how far
620/// something is from the front of the image, which is what a table the runtime reads holds.
621#[derive(Debug, Clone, Copy, PartialEq, Eq)]
622pub enum Reference {
623    /// A call, which the linker may satisfy with a stub that reaches further than the four bytes
624    /// would. `R_X86_64_PLT32` on ELF, and the same relocation a branch gets on the other two.
625    Call,
626    /// A datum, reached from the instruction pointer. `R_X86_64_PC32` on ELF.
627    Data,
628    /// A slot of the global offset table, reached from the instruction pointer, holding the
629    /// address of something another object may be the one that defines.
630    ///
631    /// The distance to the slot rather than to the thing, which is the whole difference: the
632    /// distance to the thing is a number only a link that puts the thing in this program can
633    /// work out, and a shared library is a link that does not. `R_X86_64_REX_GOTPCRELX` on ELF,
634    /// which says the instruction is a `mov` with a REX prefix and lets the linker turn it back
635    /// into the `lea` it would have been if the symbol had been here all along.
636    Got,
637    /// A slot of the global offset table, reached from the instruction pointer, holding how far
638    /// into a thread's own block of storage a thread-local variable sits.
639    ///
640    /// An offset and not an address, which is what makes it a different relocation from the one
641    /// above rather than the same one against a different symbol: a thread-local variable has one
642    /// copy per thread and therefore no address for a link to write down, and what every copy has
643    /// in common is where it sits inside the block. Adding the block's own address, which the
644    /// machine keeps in a segment register, is what turns one into the other, and that addition is
645    /// in the code rather than in the relocation. `R_X86_64_GOTTPOFF` on ELF, which the linker
646    /// turns into a constant in the instruction when it is making an executable and therefore
647    /// knows how the blocks are laid out.
648    Thread,
649    /// The address itself, written into an image. `int *p = &y;` and nothing else in C.
650    Address {
651        /// How many bytes of it are written, which is the pointer width except on a target with
652        /// a narrower relocation for it. `R_X86_64_64` and `R_X86_64_32` on ELF.
653        bytes: u8,
654    },
655    /// How far the thing is from where the four bytes holding the answer are, written into an
656    /// image rather than reached by an instruction. `.long target - .` in an `asm` at file scope,
657    /// which is how a table of places in a program says where each of them is in four bytes rather
658    /// than eight and says it without anything having to be written into the table at startup.
659    ///
660    /// The same relocation a load makes, with nothing after the hole, because what a load asks is
661    /// the same question about the same four bytes. It is a kind of its own here all the same, and
662    /// not [`Reference::Data`] with `after` left at zero, because the two formats count the answer
663    /// from different ends: ELF counts from the front of the hole, which is what this wants, and
664    /// COFF counts from the byte after it, which is what an instruction wants. Saying which is
665    /// meant is what lets each writer answer for itself rather than one of them be quietly four
666    /// out.
667    Away,
668    /// How far the thing is from the front of the loaded image, written into four bytes.
669    ///
670    /// What every field of a Windows unwind table is. The table is read at run time by code that
671    /// already has the image's own address, so four bytes of distance from it reach anything in an
672    /// image a linker will build, which eight bytes of address would have cost twice as much to say
673    /// and a distance from the table itself could not have said at all: a row is looked up by
674    /// address in a sorted table, and a row whose meaning depended on where the row was would not
675    /// sort. `IMAGE_REL_AMD64_ADDR32NB`.
676    ///
677    /// ELF has no relocation of this kind because nothing it writes asks the question. Its unwind
678    /// records are found by walking rather than by binary search, and what they hold is the ordinary
679    /// distance from the record to the function.
680    Image,
681}