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 /// The bits of the word that says what the file needs of the link, which is
70 /// [`Self::INDIRECT_EXTERN_ACCESS`] and nothing else yet. That one is about the code rather
71 /// than the command line: gcc writes it once `nodirect_extern_access` was said of a name the
72 /// file defines or uses.
73 pub needed: u32,
74}
75
76impl Property {
77 /// Which property the feature word is, which is the key the record is written under.
78 pub const X86_FEATURES: u32 = 0xc000_0002;
79 /// Indirect branch tracking: every indirect call and jump in the file arrives at a landing
80 /// pad, so the machine may fault on one that does not.
81 pub const IBT: u32 = 1;
82 /// The shadow stack: every return in the file goes where a second copy of the return address
83 /// says it should, so the machine may fault when the two disagree.
84 pub const SHSTK: u32 = 2;
85 /// Which property the word of needs is, `GNU_PROPERTY_1_NEEDED`. Not the machine's, so it is
86 /// the same key on every machine, though only x86 writes it.
87 pub const NEEDED: u32 = 0xb000_8000;
88 /// The file reaches a name another object defines only through the global offset table, so the
89 /// linker must not copy a protected variable into an executable it is part of, and the loader
90 /// must not bind a protected name in a library to a copy somewhere else.
91 pub const INDIRECT_EXTERN_ACCESS: u32 = 1;
92
93 /// Whether anything is recorded at all, which is whether the record is written.
94 #[must_use]
95 pub const fn any(self) -> bool {
96 self.features != 0 || self.needed != 0
97 }
98
99 /// Each property there is something to record for, as its key and its word, in the order gcc
100 /// writes them, which is one note each.
101 pub fn each(self) -> impl Iterator<Item = (u32, u32)> {
102 [(Self::X86_FEATURES, self.features), (Self::NEEDED, self.needed)]
103 .into_iter()
104 .filter(|&(_, word)| word != 0)
105 }
106}
107
108/// What the command line decided about the file being written, as against what the code in it
109/// decided.
110///
111/// Answers with nothing to do with each other, together because they arrive together: none of
112/// them can be worked out from a function, and the listing and the byte writer have to be handed
113/// the same ones or the two outputs of one command line would not be the same file.
114#[derive(Debug, Clone, Copy, Default, PartialEq, Eq)]
115pub struct Output {
116 /// Whether each function and each variable gets a section to itself.
117 pub sections: Sections,
118 /// What the file says it was built to have checked.
119 pub property: Property,
120 /// The extensions the unit is built for, which is what `-march=` said. Only the listing reads
121 /// it, since an assembler reading the file has to be told about an extension whose
122 /// instructions are in it, and bytes need no telling.
123 pub isa: rucc_target::Isa,
124 /// What the file says made it, which ELF keeps in `.comment` and gcc writes as `.ident`.
125 /// Nothing under `-fno-ident`, and nothing on the formats with no such section.
126 pub ident: Option<&'static str>,
127}
128
129/// A text section, and what the linker has to be told about it.
130#[derive(Debug, Clone, PartialEq, Eq)]
131pub struct Text {
132 /// The instructions, in the order they were laid out.
133 pub bytes: Vec<u8>,
134 /// Where each function starts and how long it is, in the order they were written.
135 pub funcs: Vec<Extent>,
136 /// Every place in the bytes that names something the linker has to find.
137 pub relocs: Vec<Reloc>,
138 /// Every place inside a function that has a name of its own, in the order they were written.
139 pub labels: Vec<Marker>,
140 /// What the whole section has to be aligned to, which is the largest alignment any function
141 /// in it asked for.
142 ///
143 /// A function is at a fixed offset inside the section, so a function at a multiple of two
144 /// hundred and fifty six is one only if the section itself is at one. The padding between the
145 /// functions is the assembler's half of the same job and this is the linker's.
146 pub align: u32,
147 /// What an unwinder is told about the functions, which is empty for a format that has no such
148 /// section or a build that asked for none.
149 pub unwind: Unwind,
150 /// The jump tables that are read rather than run, and so go in a read only section of data
151 /// rather than in these bytes. Empty on a format that keeps its tables after the function.
152 pub tables: Vec<Table>,
153 /// Where each call to the profiler's hook that `-mrecord-mcount` lists is, in the order they
154 /// were written, as offsets into [`Text::bytes`], with the section each is listed in. Empty
155 /// unless the flag was given or a function asked with `fentry_section`.
156 ///
157 /// The writer puts one eight byte address per call in a section called `__mcount_loc`, which
158 /// is what gcc writes and what a kernel before objtool took this over reads at boot to find
159 /// every call it can turn into a nop, or in the section `-mfentry-section=` or a function's
160 /// `fentry_section` named instead.
161 pub mcount: Vec<(usize, String)>,
162}
163
164/// The section `-mrecord-mcount` lists the calls in. See [`Text::mcount`].
165pub const MCOUNT_LOC: &str = "__mcount_loc";
166
167impl Default for Text {
168 fn default() -> Self {
169 Self {
170 bytes: Vec::new(),
171 funcs: Vec::new(),
172 relocs: Vec::new(),
173 labels: Vec::new(),
174 align: FUNC_ALIGN,
175 unwind: Unwind::default(),
176 tables: Vec::new(),
177 mcount: Vec::new(),
178 }
179 }
180}
181
182/// The unwind table, as the bytes of the section or two it goes in and what the linker has to be
183/// told about them.
184///
185/// Bytes rather than rows, because what a record is is the platform's answer rather than the object
186/// writer's, and the layer that knows what a frame did is the one that can say it in the fewest of
187/// them. What is left for the writer is where the sections go and what their relocations are.
188///
189/// Two of them, because the two platforms lay the same facts out differently. ELF writes one section
190/// of records, each a little program an unwinder runs to rebuild the frame at an address, and each
191/// carrying its own codes, so [`Self::info`] is empty there. Windows writes a table of fixed rows
192/// sorted by address, one per function, each pointing at the description of that function's prologue
193/// in a second section, which is what [`Self::info`] holds.
194///
195/// Every record says where its function is, and where a function is is a number no compilation
196/// knows: a function is at a fixed offset inside its own section and the section is placed by the
197/// linker. So there are relocations, and which kind they are is the format's answer too.
198#[derive(Debug, Clone, Default, PartialEq, Eq)]
199pub struct Unwind {
200 /// The records: one shared header and one per function on ELF, and one row per function on
201 /// Windows.
202 pub bytes: Vec<u8>,
203 /// Every place in them that names something the linker has to place, which is the functions
204 /// they are about and, where there is a second section, the description each row points at.
205 pub relocs: Vec<Reloc>,
206 /// What those records point at, on the format that keeps the two apart, and nothing at all on
207 /// the one whose records carry their own.
208 pub info: Vec<u8>,
209 /// The names inside [`Self::info`], one per function that has a description there, which are
210 /// what the relocations above ask for.
211 ///
212 /// Names rather than offsets because a relocation names a symbol, and the record and the thing
213 /// it points at are in two different sections, so there is no distance either of them can be
214 /// written with instead.
215 pub labels: Vec<Marker>,
216 /// The table of where each call an unwind lands from goes, which is `.gcc_except_table` and
217 /// is empty in a file with no landing pad in it. One header per function that has any, each
218 /// found by the record of its function through a relocation against this section, which is
219 /// what the name [`EXCEPT_TABLE`] in a relocation of [`Self::relocs`] stands for.
220 pub except: Vec<u8>,
221}
222
223/// The name of the section the call site tables go in, which is also what a relocation against it
224/// names. See [`Unwind::except`].
225pub const EXCEPT_TABLE: &str = ".gcc_except_table";
226
227/// The debug information, as the bytes of the sections it goes in.
228///
229/// Bytes rather than anything shaped like DWARF, for the reason [`Unwind`] is bytes: what a record
230/// is is the format's answer and the layer that knows what the program was doing is the one that
231/// can say it, and what is left for the writer is where the sections go and what their relocations
232/// are. The difference between the two is only that there are more than two sections here and that
233/// their names are not the writer's to choose, so each one carries its own.
234#[derive(Debug, Clone, Default, PartialEq, Eq)]
235pub struct Info {
236 /// One entry per section that has anything in it, in the order they are to be written.
237 ///
238 /// The order matters because a relocation in one of them can name another, and a name is
239 /// resolved against the sections this file already has. Writing them in the order the producer
240 /// hands them over keeps that a property of the list rather than of the writer.
241 pub chunks: Vec<Chunk>,
242 /// How the sections are stored in an ELF file, which is what `-gz` asks. Every other format
243 /// gets them as they are.
244 pub compress: Compress,
245}
246
247/// How an ELF file stores its debug sections.
248///
249/// A debug section is much larger than the code it describes and is read by a debugger rather than
250/// by the program, so it can be stored compressed and unpacked by whatever reads it. A section
251/// that would come out no smaller is left as it is, the way gas leaves one.
252#[derive(Debug, Clone, Copy, Default, PartialEq, Eq)]
253pub enum Compress {
254 /// As they are.
255 #[default]
256 None,
257 /// `-gz=zlib`: the section keeps its name, gains `SHF_COMPRESSED`, and starts with an
258 /// `Elf_Chdr` saying it is zlib and how large it was.
259 Zlib,
260 /// `-gz=zlib-gnu`: the older layout, where `.debug_info` becomes `.zdebug_info` and starts with
261 /// `ZLIB` and its size as eight big endian bytes.
262 ZlibGnu,
263 /// `-gz=zstd`: as `Zlib`, with the `Elf_Chdr` saying zstd and a zstd frame after it.
264 Zstd,
265}
266
267/// One debug section, with the name it goes in the file under.
268///
269/// A relocation here names either a function this file defines or another section in the same
270/// list, and the two are told apart by looking the name up among the sections first. That is safe
271/// rather than lucky: every section name in DWARF begins with `.debug_`, which is not the spelling
272/// of any name a C program can define.
273#[derive(Debug, Clone, PartialEq, Eq)]
274pub struct Chunk {
275 /// What the section is called, which is the name DWARF gives it.
276 pub name: String,
277 /// Its contents.
278 pub bytes: Vec<u8>,
279 /// Every place in them that names something this file does not place itself.
280 pub relocs: Vec<Reloc>,
281}
282
283/// Where the room a patcher was promised at the top of a function ended up.
284///
285/// What `-fpatchable-function-entry=` asks for, once it is bytes rather than instructions. Two
286/// numbers because the writer has two questions: where the address it records points, and how much
287/// of the function is in front of the symbol.
288///
289/// They are not the same number. The room can be split by the landing pad a function opens with,
290/// since the pad has to be the first instruction after the label and the room does not, so the part
291/// in front of the label and the part after it are not always next to each other. What is recorded
292/// is the front of the whole thing, which is the part in front of the label when there is one.
293#[derive(Debug, Clone, Copy, PartialEq, Eq)]
294pub struct Patch {
295 /// Where the room begins, as an offset into the same bytes [`Extent::start`] is one into.
296 pub at: usize,
297 /// How many bytes of the function are in front of [`Extent::start`], which is where its symbol
298 /// is and where an unwinder is told the function begins.
299 pub before: usize,
300}
301
302/// Where a place inside a function that has a name of its own ended up.
303///
304/// What asks for one is GNU's address of a label in the initializer of an object with static
305/// storage duration. A label is somewhere a jump goes and a jump is a distance the assembler works
306/// out, so no ordinary label is in the symbol table at all. An image is the other case: it is in
307/// another section, so what it holds is a relocation, and a relocation names a symbol.
308///
309/// The name is never one the program wrote, so nothing outside this file looks it up and it is
310/// always local: it is here for a relocation in this same file to resolve against, and a linker
311/// that offered it to another file would be offering the middle of a function.
312#[derive(Debug, Clone, PartialEq, Eq)]
313pub struct Marker {
314 /// The name, which is whatever the compiler minted for it.
315 pub name: String,
316 /// Where it is, as an offset into the same bytes [`Extent::start`] is one into.
317 pub at: usize,
318}
319
320/// One jump table of one function, kept out of the instructions.
321///
322/// A table is data the function reads, and gcc and clang put it in `.rodata` rather than in the
323/// code. Keeping it there keeps data out of the lines the instruction fetcher reads and keeps the
324/// executable sections to what is executed, which is also what a size counted by section is
325/// measuring. The cost is that the two ends of every cell are now in different sections, so each
326/// cell is a relocation the linker fills in rather than a number the assembler writes, which is
327/// what gas does with the same `.long .L3-.L4` when the `.L4` is in `.rodata`.
328///
329/// Each cell is still the distance from the front of the table to a block, so the code that reads
330/// one is the same code wherever the table is.
331#[derive(Debug, Clone, PartialEq, Eq)]
332pub struct Table {
333 /// The name the instruction that reads it gives it, which is local to this file.
334 pub name: String,
335 /// Which of [`Text::funcs`] it belongs to.
336 pub func: usize,
337 /// Where each cell's block is, counted from [`Extent::start`] of that function.
338 pub cells: Vec<usize>,
339 /// Whether each cell is the block's address in eight bytes rather than its distance from the
340 /// table in four, which is the table the kernel code model reads.
341 pub absolute: bool,
342}
343
344/// Where one function ended up.
345///
346/// How long a function is is a fact ELF records and Mach-O has no way to, so it is handed over
347/// rather than worked out again: the writer that wants it has it and the one that does not
348/// ignores it.
349#[derive(Debug, Clone, PartialEq, Eq)]
350pub struct Extent {
351 /// The function's name, as the C program spelled it. The underscore an Apple symbol carries
352 /// is the object writer's business, not this one's.
353 pub name: String,
354 /// Where its first instruction is.
355 pub start: usize,
356 /// How many bytes of instructions it is, not counting the padding in front of the next one.
357 pub len: usize,
358 /// What this one function asked to be aligned to, which is not always what the section it is
359 /// in was aligned to.
360 ///
361 /// The two are the same number only when this function is the one that asked for the most.
362 /// Under [`Sections::functions`] each function is a section of its own and this is what that
363 /// section is aligned to, so the number has to survive the trip rather than be recovered from
364 /// the offset, which says nothing once the function is at zero in a section of its own.
365 pub align: u32,
366 /// How the linker sees the name, which is what the C `static` reaches the object file as.
367 pub binding: Binding,
368 /// How far outside a shared library holding this the name reaches.
369 pub visibility: Visibility,
370 /// Where the room a patcher was promised is, or `None` in a function promised none, which is
371 /// every function on a command line that did not ask. See [`Patch`].
372 pub patch: Option<Patch>,
373 /// How many bytes of `int3` a hot patcher was promised in front of [`Extent::start`], from
374 /// `__attribute__((ms_hook_prologue))`, which are in front of the room [`Patch`] says is there
375 /// too. Zero in every other function.
376 pub hooked: usize,
377 /// Each call an unwind lands somewhere from, in the order they are in the function, which is
378 /// empty in every function with no cleanup handler to run on the way out. See [`Site`].
379 pub landings: Vec<Site>,
380}
381
382impl Extent {
383 /// How many of the function's bytes are in front of [`Self::start`], which is where its own
384 /// section begins under [`Sections::functions`] rather than where its symbol is.
385 #[must_use]
386 pub fn ahead(&self) -> usize {
387 self.patch.map_or(0, |patch| patch.before) + self.hooked
388 }
389}
390
391/// One call an unwind out of lands in a pad, as distances from [`Extent::start`].
392///
393/// What a row of the call site table in `.gcc_except_table` says, which is the bytes of the call
394/// and where the pad is. An unwinder looking up a return address finds the call it is the end of,
395/// so the range is the call's own bytes and nothing around it.
396#[derive(Debug, Clone, Copy, PartialEq, Eq)]
397pub struct Site {
398 /// Where the call begins.
399 pub start: usize,
400 /// How many bytes it is.
401 pub len: usize,
402 /// Where the pad begins.
403 pub pad: usize,
404}
405
406/// The variables a file defines, and what the linker has to be told about them.
407///
408/// One entry per variable rather than one section of everything, because where a variable goes is
409/// worked out from what it is and two of them that land in one section still have their own
410/// alignment, their own size and their own symbol. Putting them together is the writer's job and
411/// is the one part of it the three formats disagree about.
412#[derive(Debug, Clone, Default, PartialEq, Eq)]
413pub struct Data {
414 /// Every variable this file defines, in the order the module held them.
415 pub objects: Vec<Object>,
416 /// Every name this file declares weak and does not define, in the order the module held them.
417 ///
418 /// Each becomes an undefined symbol the linker is allowed to leave undefined, whose references
419 /// then read a zero address. A name here is not an object and carries no bytes, which is why
420 /// it is a list of names beside the objects rather than one of them.
421 pub weak: Vec<String>,
422 /// Every distance between two labels an image holds, which the writer fills in once it knows
423 /// where the labels are. See [`Apart`].
424 pub apart: Vec<Apart>,
425 /// Every name this file offers to other DLLs, functions first and then variables, each in the
426 /// order the module held them. Only COFF has anywhere to say it and every other format is
427 /// handed an empty list. See [`Export`].
428 pub exports: Vec<Export>,
429}
430
431/// One name the DLL this file is linked into offers to others, which is `dllexport`, or one it
432/// is told to keep to itself, which is a hidden definition.
433///
434/// What a COFF object says either with is an option for the linker, ` -export:name`, in a section
435/// called `.drectve` that holds nothing but options and that the linker reads and then drops. A
436/// variable is ` -export:name,data`, which keeps the import library from writing a stub under the
437/// plain name for it, since a jump is no use to somebody reading a variable. The list is in the
438/// order clang writes it and the options are spelled the way it spells them, which is also what
439/// gcc's are, apart from the quotes gcc puts round each name.
440#[derive(Debug, Clone, PartialEq, Eq)]
441pub struct Export {
442 /// The name as the linker sees it.
443 pub name: String,
444 /// What the linker is told about it.
445 pub kind: Offer,
446}
447
448/// What an [`Export`] tells the linker about its name.
449#[derive(Debug, Clone, Copy, PartialEq, Eq)]
450pub enum Offer {
451 /// A function other DLLs may call.
452 Function,
453 /// A variable other DLLs may read.
454 Variable,
455 /// A name that is left out when the linker exports every name a DLL defines, which is what it
456 /// does for a DLL with no `dllexport` and no `.def` file. `-exclude-symbols:name`, which clang
457 /// writes for a hidden definition on a mingw-w64 target and which both lld and GNU ld read.
458 /// gcc ignores hidden visibility there. This is how the runtime routines of our own that a
459 /// DLL links in stay out of its export table, the way libgcc's do by being named libgcc.
460 Hidden,
461 /// Not a name at all but a whole option, which [`Export::name`] holds as the linker reads it.
462 /// What `#pragma comment(lib)` and `#pragma comment(linker)` ask for, such as
463 /// `/DEFAULTLIB:ws2_32.lib`, which goes in the same section for the same linker to read.
464 Verbatim,
465}
466
467impl Export {
468 /// The option the linker is handed for it, with the space in front that holds it apart from
469 /// the one before.
470 #[must_use]
471 pub fn option(&self) -> String {
472 match self.kind {
473 Offer::Function => format!(" -export:{}", self.name),
474 Offer::Variable => format!(" -export:{},data", self.name),
475 Offer::Hidden => format!(" -exclude-symbols:{}", self.name),
476 Offer::Verbatim => format!(" {}", self.name),
477 }
478 }
479}
480
481/// How far one label is from another, written into a variable's image.
482///
483/// What `static int b[] = { &&l1 - &&l0 };` asks for. Neither label has an address until the
484/// link, and yet both are in the one function's code and the code moves as one piece, so the
485/// distance is known as soon as the code is laid out. That makes it a number the writer puts in
486/// the bytes itself rather than a relocation it asks the linker for, which is what gas does with
487/// `.long .L1-.L0` too, and it is why a label in another function is refused: the two could land
488/// in different sections and then no number is right.
489#[derive(Debug, Clone, PartialEq, Eq)]
490pub struct Apart {
491 /// Which of [`Data::objects`] the distance is written into.
492 pub object: usize,
493 /// How far into that object's image.
494 pub at: usize,
495 /// The label measured to, as the image named it.
496 pub to: String,
497 /// The label measured from.
498 pub from: String,
499 /// What to add to the distance.
500 pub addend: i64,
501 /// How many bytes the distance is written in.
502 pub bytes: u8,
503}
504
505/// A second name for something the same file defines.
506///
507/// Not a section and not a byte of anything, which is the whole point of it: an alias is a symbol
508/// table entry pointing at an address something else already occupies, so a file with one in it is
509/// no larger than the same file without. `.set b, a` is what an assembler is told and a second
510/// entry at the first one's section, value and size is what a writer produces, and the two say the
511/// same thing.
512///
513/// The target is a name rather than an index into anything above, because the two output paths
514/// find it in different places: a listing hands the name to an assembler that resolves it, and a
515/// writer looks it up among the symbols it has already added.
516#[derive(Debug, Clone, PartialEq, Eq)]
517pub struct Alias {
518 /// The name being defined, as the C program spelled it.
519 pub name: String,
520 /// The name it stands for, which has to be something this same file defines.
521 pub target: String,
522 /// How the linker sees the new name, which is not always how it sees the old one: the target
523 /// of `extern int b __attribute__((alias("a")))` may be a `static`.
524 pub binding: Binding,
525 /// How far outside a shared library holding this the new name reaches, which is its own
526 /// answer for the same reason the binding is: the attribute is written on the alias.
527 pub visibility: Visibility,
528 /// Whether the new name is an indirect function, `STT_GNU_IFUNC`, rather than a second name
529 /// for the target. The target is then a resolver, which the dynamic loader calls once and
530 /// whose answer is the address every call to the new name reaches. ELF is the only format with
531 /// the type, and a writer for another one refuses it rather than write an ordinary name.
532 pub ifunc: bool,
533}
534
535/// One global variable, laid out.
536#[derive(Debug, Clone, PartialEq, Eq)]
537pub struct Object {
538 /// Its name, as the C program spelled it. The underscore an Apple symbol carries is the
539 /// object writer's business, not this one's.
540 pub name: String,
541 /// Its image, and nothing at all when it is zero filled and the file carries none of it.
542 pub bytes: Vec<u8>,
543 /// How many bytes it occupies, which is the length of the image except when there is none.
544 pub size: u64,
545 /// What it has to be aligned to, always a power of two.
546 pub align: u64,
547 /// Which section it goes in.
548 pub place: Place,
549 /// How the linker sees the name.
550 pub binding: Binding,
551 /// How far outside a shared library holding this the name reaches.
552 pub visibility: Visibility,
553 /// Every place in its image that holds the address of a symbol, counted from the start of
554 /// the image rather than from the start of the section it lands in.
555 pub relocs: Vec<Reloc>,
556}
557
558/// Which section a variable goes in.
559///
560/// Worked out from what the variable is rather than named by it, except in the one case where the
561/// program named it. A reader who wants to know why a variable is in `.rodata` should be able to
562/// find the answer in the variable.
563#[derive(Debug, Clone, PartialEq, Eq)]
564pub enum Place {
565 /// Written to, and its image is not all zeros. `.data`.
566 Written,
567 /// Never written to, so it can go in a page the loader maps read only and every process
568 /// running the program can share. `.rodata`.
569 ReadOnly,
570 /// Never written to by the program, but written once by the dynamic linker, because its image
571 /// holds the address of something and an address is not known until the image is loaded.
572 /// `.data.rel.ro`.
573 ///
574 /// The section has to be writable for that one write and read only afterwards, which is what
575 /// the `PT_GNU_RELRO` segment is: the loader maps it, the relocations are applied, and then it
576 /// is turned read only before the program starts. Putting the variable in `.rodata` instead
577 /// means asking the linker to leave a relocation in a section that is never writable, and what
578 /// it does about that is give the whole image `DT_TEXTREL`, which gives up the protection the
579 /// section was for. Some hardened toolchains refuse the link outright.
580 RelocReadOnly {
581 /// Whether every address in the image is of something this file defines and does not
582 /// export, which means the link can resolve them all and none can be interposed.
583 ///
584 /// Those go in `.data.rel.ro.local`, which the linker puts in the first pages of the
585 /// segment, so the pages holding them are the ones the loader is done with soonest. It is
586 /// a hint about layout rather than a difference in what the section is.
587 local: bool,
588 },
589 /// All zeros, so the file says how big it is and carries none of it. `.bss`.
590 Zero,
591 /// One copy per thread rather than one copy per program. `.tdata` and `.tbss`.
592 ///
593 /// What the loader does with these two sections is what makes them different from every other
594 /// section here. Their contents are the template of a thread's own block of storage rather than
595 /// the storage itself: the image is laid out once, and every thread that starts gets a fresh
596 /// copy of it, so the address of a variable in one of them is a different address in every
597 /// thread and there is no single address for the link to write down. That is why a reference to
598 /// one is not the ordinary distance from the instruction pointer, and why the symbol is marked
599 /// as being of this kind so a linker refuses one that is.
600 ///
601 /// The pair is the same split as `.data` and `.bss` for the same reason, so an image that is
602 /// all zeros costs its size in the file and not its bytes.
603 Thread {
604 /// Whether the image is all zeros, which puts it in `.tbss` rather than `.tdata`.
605 zero: bool,
606 },
607 /// A tentative definition, which is not in a section at all: the linker is asked for that
608 /// much zeroed space and merges every definition of the name into one. `.comm`.
609 Merged,
610 /// The section the program named, from `__attribute__((section(...)))`, and what the
611 /// variable put there holds, which is what the section's flags have to say.
612 Named(String, Holds),
613 /// A pointer to a variable this file only declares, in a read only section of its own that
614 /// the linker keeps one copy of whichever objects wrote it. COFF only, where it is called
615 /// `.rdata$` and the pointer's name, and every object that reads the variable writes the same
616 /// one with the same name, which is why a copy has to be allowed to lose to another.
617 ///
618 /// What the pointer is for is `rucc_codegen::elsewhere::Slot::Referred`. The runtime may write
619 /// it once the DLL the variable turns out to be in is loaded, which is why the section is not
620 /// merely read only: the runtime unprotects the page for that one write.
621 Pointer,
622 /// A string literal, in the section of them the linker keeps one copy of each string in,
623 /// whichever objects it came from. `.rodata.str1.` and the alignment, which is where gcc puts
624 /// one, flagged `SHF_MERGE` and `SHF_STRINGS` with entries a byte wide.
625 ///
626 /// Only for a literal of one byte characters whose first zero is its last byte. The linker
627 /// reads the section as a run of strings each ended by a zero, so one with a zero inside it
628 /// would be cut in two, and a wide one is entries of a different width, which goes in a
629 /// section of its own name that nothing here writes yet.
630 Strings {
631 /// What it is aligned to, which is in the name because two literals aligned differently
632 /// cannot be in one run the linker merges.
633 align: u64,
634 },
635 /// A variable written `noinit` with no initializer, in the section the startup code never
636 /// clears, so what a program left in it is still there after a warm reset. `.noinit`, with no
637 /// bytes in the file, `"aw",@nobits`. ELF only, as gcc has it.
638 NoInit,
639 /// A variable written `persistent` with an initializer, in the section the loader fills and
640 /// the startup code never copies into again. `.persistent`, `"aw"`. ELF only.
641 Persistent,
642}
643
644/// What a variable in a section the program named holds, which is the one thing about the section
645/// the name does not say.
646///
647/// The answers are the ones gcc gives, which a kernel's linker script and `readelf` both see: a
648/// section is writable unless the variable is constant and holds no address, and it carries no
649/// bytes only when its name is one of the names that always mean zeros and the variable is zeros.
650#[derive(Debug, Clone, Copy, PartialEq, Eq)]
651pub enum Holds {
652 /// Bytes the program or the loader may write. `"aw"` on ELF.
653 Written,
654 /// Bytes nothing writes, which a loader maps read only. `"a"` on ELF.
655 ReadOnly,
656 /// Zeros, in a section named for holding nothing else, so the file carries none of them.
657 /// `"aw",@nobits` on ELF.
658 Zero,
659}
660
661impl Holds {
662 /// Whether a section of this name is one gcc makes carry no bytes, which is `.bss` and the
663 /// names under it, the small data one and the old COMDAT spellings of both, and `.noinit`,
664 /// which gas has made `@nobits` by its name since binutils 2.36. A kernel puts its page
665 /// aligned zeros in `.bss..page_aligned` and relies on this.
666 #[must_use]
667 pub fn nobits(name: &str) -> bool {
668 name == ".bss"
669 || name.starts_with(".bss.")
670 || name.starts_with(".gnu.linkonce.b.")
671 || name == ".sbss"
672 || name.starts_with(".sbss.")
673 || name.starts_with(".gnu.linkonce.sb.")
674 || name == ".noinit"
675 || name.starts_with(".noinit.")
676 }
677}
678
679impl Place {
680 /// What the section this variable goes in is called under [`Sections::data`], and nothing at
681 /// all for a variable that has no section of its own to be given.
682 ///
683 /// The name is the section it would otherwise have shared with a dot and the variable's name
684 /// after it, which is what gcc writes and is not merely a convention: `--gc-sections`, the
685 /// linker scripts a kernel and an embedded image are linked with, and the default placement
686 /// rules all match on the part in front of the dot, so a section called anything else would be
687 /// placed by whatever the catch all rule is.
688 ///
689 /// Two kinds of variable are left alone. A merged one is a request to the linker for that much
690 /// zeroed space rather than an image, so there is no section to split, and one the program put
691 /// a name on already has the answer the source gave, which this must not overrule.
692 /// A string literal is left alone too, as gcc leaves it: the linker merges the strings of the
693 /// section they share, and a section per literal would give it nothing to merge them with.
694 ///
695 /// Here rather than beside either output path, so that the listing `-S` writes and the object
696 /// `-c` writes cannot come to disagree about where a variable went.
697 #[must_use]
698 pub fn split(&self, name: &str) -> Option<String> {
699 Some(format!("{}.{name}", self.base()?))
700 }
701
702 /// The section this variable goes in when nothing is being split up, and nothing at all for
703 /// the two kinds that are not in one.
704 #[must_use]
705 pub fn base(&self) -> Option<&'static str> {
706 Some(match self {
707 Place::Written => ".data",
708 Place::ReadOnly => ".rodata",
709 Place::RelocReadOnly { local: false } => ".data.rel.ro",
710 Place::RelocReadOnly { local: true } => ".data.rel.ro.local",
711 Place::Zero => ".bss",
712 Place::Thread { zero: false } => ".tdata",
713 Place::Thread { zero: true } => ".tbss",
714 Place::NoInit => ".noinit",
715 Place::Persistent => ".persistent",
716 Place::Merged | Place::Named(..) | Place::Pointer | Place::Strings { .. } => {
717 return None;
718 }
719 })
720 }
721
722 /// The section a string literal of that alignment goes in.
723 #[must_use]
724 pub fn strings(align: u64) -> String {
725 format!(".rodata.str1.{align}")
726 }
727}
728
729/// A section holding function addresses for a C runtime to call rather than data for the program
730/// to read.
731///
732/// ELF has a type for each of the three, and a section of that type is what the startup code walks:
733/// the linker gathers every input section of the kind into one run and the CRT calls what it finds
734/// between the two ends. A section of the ordinary type with the same name would be gathered the
735/// same way and called by nothing, which is why the type is worth writing down rather than leaving
736/// to the default.
737///
738/// Only ELF says it this way. COFF sorts by what follows the `$` in a section name and Mach-O has
739/// a section attribute for it, so on those two the name carries the whole of the answer and there
740/// is nothing for this to be.
741#[derive(Debug, Clone, Copy, PartialEq, Eq)]
742pub enum Array {
743 /// Run on the way to `main`, in the order the linker sorted the sections into.
744 Init,
745 /// Run after `main` returns, in the reverse of that order.
746 Fini,
747 /// Run ahead of `.init_array` and ahead of the shared libraries a program is linked against,
748 /// which is a thing only the C library itself has a use for.
749 Preinit,
750}
751
752impl Array {
753 /// Which of them a section of this name is, and [`None`] for a name that is not one of them.
754 ///
755 /// The name itself or the name with a dot and a priority after it. A numbered `constructor` is
756 /// written as the second of those and is the same kind of section as the first: the number is
757 /// there so that the linker sorts it, not to make it a different thing.
758 #[must_use]
759 pub fn of(name: &str) -> Option<Array> {
760 let kinds = [
761 (".init_array", Array::Init),
762 (".fini_array", Array::Fini),
763 (".preinit_array", Array::Preinit),
764 ];
765 kinds.into_iter().find_map(|(base, array)| {
766 let rest = name.strip_prefix(base)?;
767 (rest.is_empty() || rest.starts_with('.')).then_some(array)
768 })
769 }
770
771 /// How the type is spelled in a `.section` directive.
772 #[must_use]
773 pub const fn asm(self) -> &'static str {
774 match self {
775 Array::Init => "@init_array",
776 Array::Fini => "@fini_array",
777 Array::Preinit => "@preinit_array",
778 }
779 }
780}
781
782/// How the linker sees a name.
783///
784/// Three of the five linkages the IR has, because that is how many an object file can say. Which
785/// of the two weak ones a symbol had is a fact the optimizer needs and the linker does not.
786#[derive(Debug, Clone, Copy, PartialEq, Eq)]
787pub enum Binding {
788 /// Visible to every other object, and the definition here is the definition.
789 Global,
790 /// Invisible outside this object, which is what `static` at file scope means.
791 Local,
792 /// Visible, and allowed to lose to a definition in another object.
793 Weak,
794}
795
796/// How far outside a shared library a name reaches.
797///
798/// A different question from [`Binding`] and asked of a different linker. The binding is what the
799/// static linker does with a name while it is building the output, and this is what the dynamic
800/// linker may do with it once the output is a shared library and is being loaded. A hidden name is
801/// still global to the static link, so two files in the same library can call each other by it; it
802/// is simply not in the dynamic symbol table afterwards, so nothing outside can name it.
803///
804/// Written down here as its own thing rather than folded into the binding because it is the
805/// mistake tamnd/rucc#733 was: a writer that has one word for both ends up saying something about
806/// visibility while it thinks it is saying something about linkage, and what it said was hidden.
807///
808/// It means nothing for a [`Binding::Local`] name. `static` is already invisible to the whole
809/// world outside the file, and ELF records `STV_DEFAULT` for one, which is what gcc writes.
810#[derive(Debug, Clone, Copy, Default, PartialEq, Eq)]
811pub enum Visibility {
812 /// In the dynamic symbol table, and a reference from inside the library may be satisfied by a
813 /// definition somewhere else, which is what makes `LD_PRELOAD` work. What a name gets when
814 /// nothing said otherwise.
815 #[default]
816 Default,
817 /// Not in the dynamic symbol table at all, so nothing outside the library can name it and
818 /// every reference to it from inside binds here. `__attribute__((visibility("hidden")))`.
819 Hidden,
820 /// In the dynamic symbol table, so something outside can name it, but a reference from inside
821 /// the library binds to the definition inside it and cannot be interposed.
822 Protected,
823}
824
825/// One reference to something this file does not contain.
826#[derive(Debug, Clone, PartialEq, Eq)]
827pub struct Reloc {
828 /// Where the bytes the linker writes over begin.
829 pub at: usize,
830 /// What is wanted, as the C program spelled it.
831 pub symbol: String,
832 /// What the linker is being asked for.
833 pub kind: Reference,
834 /// What to add to the distance, which is the constant the instruction already meant plus the
835 /// bytes between the hole and the end of the instruction, negated. An instruction counts from
836 /// where it ends and a relocation counts from where it starts, and this is the difference.
837 pub addend: i64,
838 /// How many bytes of the instruction come after the four the linker writes over, which is zero
839 /// for everything except an instruction carrying an immediate behind its displacement.
840 ///
841 /// Already inside [`Self::addend`] and written down again because the two formats disagree about
842 /// which of the two numbers they want. ELF takes the one number and counts from where the hole
843 /// starts, so the difference between that and where the instruction ends is the writer's to fold
844 /// in and nothing after it ever has to be told apart again. COFF counts from where the
845 /// instruction ends and says how far that is in the relocation type itself, which is what
846 /// `IMAGE_REL_AMD64_REL32_1` through `REL32_5` are, so it needs the two apart. A writer cannot
847 /// recover one from the other, since a displacement of minus four and no trailing bytes and a
848 /// displacement of zero and four of them are the same sum.
849 ///
850 /// Zero for a relocation in an image, where there is no instruction and the question does not
851 /// arise.
852 pub after: u8,
853}
854
855/// Which of the i386 thread-local relocations a [`Reference::Tls`] is, named after what the four
856/// bytes end up holding.
857///
858/// The suffix gcc writes for each is beside it. The linker may rewrite the instruction around the
859/// first three into a cheaper model once it knows where the variable ends up, which is why each
860/// kind is kept apart from the others rather than folded into an address or an offset.
861#[derive(Debug, Clone, Copy, PartialEq, Eq)]
862pub enum Tls {
863 /// The pair of slots of the global offset table `___tls_get_addr` takes, as a distance from the
864 /// table. `@TLSGD`, `R_386_TLS_GD`.
865 General,
866 /// The same pair for the module as a whole rather than one variable. `@TLSLDM`,
867 /// `R_386_TLS_LDM`.
868 Module,
869 /// How far into its module's block a variable is, which is what goes with the address
870 /// [`Tls::Module`] found. `@DTPOFF`, `R_386_TLS_LDO_32`.
871 InModule,
872 /// A slot of the global offset table holding where the variable is from the thread pointer, as
873 /// a distance from the table. `@GOTNTPOFF`, `R_386_TLS_GOTIE`.
874 Slot,
875 /// The same slot by its address, for code that is not position independent. `@INDNTPOFF`,
876 /// `R_386_TLS_IE`.
877 SlotAddress,
878 /// A slot holding the distance the other way round, from the variable up to the thread
879 /// pointer, as a distance from the table. `@GOTTPOFF`, `R_386_TLS_IE_32`.
880 SlotNegated,
881 /// Where the variable is from the thread pointer, which is below it and so negative.
882 /// `@NTPOFF`, `R_386_TLS_LE`.
883 Offset,
884 /// The same distance the other way round, which is positive. `@TPOFF`, `R_386_TLS_LE_32`.
885 Negated,
886}
887
888/// What kind of thing a relocation is asking the linker for.
889///
890/// The first four are the distance from the end of an instruction to something, which is what every
891/// reference the code makes is, because this compiler generates position independent code and
892/// nothing else. They are told apart by what the linker is allowed to do about each one. The last
893/// two are not distances from an instruction at all and are what a table of data asks for: the
894/// address itself, which is what an initializer holding the address of something holds, and how far
895/// something is from the front of the image, which is what a table the runtime reads holds.
896#[derive(Debug, Clone, Copy, PartialEq, Eq)]
897pub enum Reference {
898 /// A call, which the linker may satisfy with a stub that reaches further than the four bytes
899 /// would. `R_X86_64_PLT32` on ELF, and the same relocation a branch gets on the other two.
900 Call,
901 /// A datum, reached from the instruction pointer. `R_X86_64_PC32` on ELF.
902 Data,
903 /// A slot of the global offset table, reached from the instruction pointer, holding the
904 /// address of something another object may be the one that defines.
905 ///
906 /// The distance to the slot rather than to the thing, which is the whole difference: the
907 /// distance to the thing is a number only a link that puts the thing in this program can
908 /// work out, and a shared library is a link that does not. `R_X86_64_REX_GOTPCRELX` on ELF,
909 /// which says the instruction is a `mov` with a REX prefix and lets the linker turn it back
910 /// into the `lea` it would have been if the symbol had been here all along.
911 Got,
912 /// A slot of the global offset table read by an instruction the linker may rewrite that has
913 /// no REX prefix, `call *f@GOTPCREL(%rip)` or a 32 bit `mov`. `R_X86_64_GOTPCRELX` on ELF.
914 GotBare,
915 /// A slot of the global offset table read by an instruction the linker has to leave as it is,
916 /// because it is not one of the few it knows how to rewrite: a store into the slot, or a load
917 /// into a vector register. `R_X86_64_GOTPCREL` on ELF.
918 GotKept,
919 /// A slot of the global offset table, reached from the instruction pointer, holding how far
920 /// into a thread's own block of storage a thread-local variable sits.
921 ///
922 /// An offset and not an address, which is what makes it a different relocation from the one
923 /// above rather than the same one against a different symbol: a thread-local variable has one
924 /// copy per thread and therefore no address for a link to write down, and what every copy has
925 /// in common is where it sits inside the block. Adding the block's own address, which the
926 /// machine keeps in a segment register, is what turns one into the other, and that addition is
927 /// in the code rather than in the relocation. `R_X86_64_GOTTPOFF` on ELF, which the linker
928 /// turns into a constant in the instruction when it is making an executable and therefore
929 /// knows how the blocks are laid out.
930 Thread,
931 /// The address itself, written into an image. `int *p = &y;` and nothing else in C.
932 Address {
933 /// How many bytes of it are written, which is the pointer width except on a target with
934 /// a narrower relocation for it. `R_X86_64_64` and `R_X86_64_32` on ELF.
935 bytes: u8,
936 },
937 /// The address itself in four bytes of an x86-64 instruction that sign extends them to eight,
938 /// which is an immediate on sixty four bits and a displacement. `R_X86_64_32S` on ELF, which
939 /// is what code that is not position independent reaches its data with: `table(,%rax,4)` and
940 /// `movq $.LC0, %rdi`. The linker checks the address fits in the lower two gigabytes, where
941 /// `R_X86_64_32` would let one between two and four through to come out negative.
942 Signed,
943 /// How far the thing is from where the four bytes holding the answer are, written into an
944 /// image rather than reached by an instruction. `.long target - .` in an `asm` at file scope,
945 /// which is how a table of places in a program says where each of them is in four bytes rather
946 /// than eight and says it without anything having to be written into the table at startup.
947 ///
948 /// The same relocation a load makes, with nothing after the hole, because what a load asks is
949 /// the same question about the same four bytes. It is a kind of its own here all the same, and
950 /// not [`Reference::Data`] with `after` left at zero, because the two formats count the answer
951 /// from different ends: ELF counts from the front of the hole, which is what this wants, and
952 /// COFF counts from the byte after it, which is what an instruction wants. Saying which is
953 /// meant is what lets each writer answer for itself rather than one of them be quietly four
954 /// out.
955 Away,
956 /// How far the thing is from the end of two bytes holding the answer, which is a jump or a call
957 /// in sixteen bit code to somewhere in another section. `R_386_PC16` on ELF, and nothing on
958 /// the other formats, which have no sixteen bit code to write it for.
959 Short,
960 /// The same in one byte, which is `.byte target - 1f` in front of `1:`. The kernel's boot
961 /// header starts with a short jump written out byte by byte that way, to a label in another
962 /// section. `R_386_PC8` and `R_X86_64_PC8` on ELF, and nothing on the other formats.
963 Tiny,
964 /// The same distance written into eight bytes, which is `.quad target - .`. The kernel's jump
965 /// label table says where each key is that way on x86-64, and the key is in another section
966 /// from the table, so it is a relocation. `R_X86_64_PC64` on ELF.
967 AwayWide,
968 /// How far the thing is from the front of the loaded image, written into four bytes.
969 ///
970 /// What every field of a Windows unwind table is. The table is read at run time by code that
971 /// already has the image's own address, so four bytes of distance from it reach anything in an
972 /// image a linker will build, which eight bytes of address would have cost twice as much to say
973 /// and a distance from the table itself could not have said at all: a row is looked up by
974 /// address in a sorted table, and a row whose meaning depended on where the row was would not
975 /// sort. `IMAGE_REL_AMD64_ADDR32NB`.
976 ///
977 /// ELF has no relocation of this kind because nothing it writes asks the question. Its unwind
978 /// records are found by walking rather than by binary search, and what they hold is the ordinary
979 /// distance from the record to the function.
980 Image,
981 /// How far the thing is from the front of the section it is in, written into the four bytes
982 /// of displacement of an address that is counted from a register.
983 ///
984 /// What a Windows thread finds its copy of a thread-local variable with. Every thread has a
985 /// copy of the image's `.tls` section, the register holds where this thread's copy is, and the
986 /// variable is as far into the copy as it is into the section. `IMAGE_REL_AMD64_SECREL`, and
987 /// nothing on ELF or Mach-O, which reach thread-local storage through a table slot instead.
988 Section,
989 /// How far the thing is from the front of the global offset table, in four bytes.
990 ///
991 /// What position independent code on i386 reaches its own data with. That machine has no
992 /// addressing from the instruction pointer, so a function finds the table once, keeps its
993 /// address in a register, and reaches everything this file defines as that register plus a
994 /// constant: `leal .LC0@GOTOFF(%ebx), %eax`. `R_386_GOTOFF` on ELF.
995 GotOffset,
996 /// How far the front of the global offset table is from the four bytes themselves, which is how
997 /// i386 code finds the table in the first place.
998 ///
999 /// `addl $_GLOBAL_OFFSET_TABLE_, %ebx` straight after a call that left its own return address
1000 /// in `%ebx`. The addend makes up the difference between where the four bytes are and where the
1001 /// instruction starts, which is the address the call left behind. `R_386_GOTPC` on ELF.
1002 GotFront,
1003 /// Where a slot of the global offset table is, as a distance from the front of the table, read
1004 /// by an instruction the linker may rewrite into one that does not go through the slot at all.
1005 ///
1006 /// The i386 counterpart of [`Reference::Got`], counted from the register holding the table
1007 /// rather than from the instruction pointer: `movl foo@GOT(%ebx), %eax` and
1008 /// `call *foo@GOT(%ebx)`. `R_386_GOT32X` on ELF.
1009 Slot,
1010 /// The same slot read or written by an instruction the linker has to leave as it is, because it
1011 /// is not one of the few it knows how to rewrite. `R_386_GOT32` on ELF.
1012 SlotKept,
1013 /// One of the ways i386 code reaches a thread-local variable, which the model says which.
1014 ///
1015 /// Apart from [`Reference::Thread`] because this machine has a relocation for each step of each
1016 /// model rather than the one x86-64 needs from a compiler that only writes one of them, and a
1017 /// file of assembly may use any of them. See [`Tls`].
1018 Tls(Tls),
1019 /// Some bits of an AArch64 instruction, which the fixup says which and how to fill in.
1020 ///
1021 /// Its own kind rather than one of the above, because on this machine a reference is not four
1022 /// bytes of distance: it is a field of a word, and a name takes two instructions to reach,
1023 /// `adrp` for its page and an `add` or a load for the low twelve bits of it. Each of those is
1024 /// its own relocation, and the fixup is already the name of one.
1025 Field(rucc_target::aarch64::Fixup),
1026}
1027
1028impl Reference {
1029 /// The same reference with the linker not allowed to rewrite the instruction, which is what
1030 /// gas writes under `-mrelax-relocations=no`: a slot of the global offset table is read through
1031 /// the slot whatever the instruction is. Every other reference is itself.
1032 #[must_use]
1033 pub const fn kept(self) -> Reference {
1034 match self {
1035 Reference::Got | Reference::GotBare => Reference::GotKept,
1036 Reference::Slot => Reference::SlotKept,
1037 other => other,
1038 }
1039 }
1040}