1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
//! What COFF answers, where the two formats answer differently.
//!
//! Design: `spec/11-asm-objects-debug.md` section 11.3 and `spec/cross-compile/07-object-formats.md`
//! section 7.4. The sibling of [`crate::elf`], and the shape of a file is [`crate::file`]'s for both.
//!
//! # The relocation that counts from the other end
//!
//! Both formats write the distance from an instruction to something into four bytes, and they
//! disagree about where that distance is measured from. ELF counts from where the four bytes start
//! and lets the addend make up whatever else is wanted, so one relocation type covers every
//! instruction. COFF counts from where the instruction ends, which is not a number it can be told,
//! so it is in the relocation type instead: `IMAGE_REL_AMD64_REL32` is an instruction that ends at
//! the hole and `REL32_1` through `REL32_5` are one whose last one to five bytes come after it. That
//! is why [`crate::Reloc`] carries the count as well as the addend it is already inside.
//!
//! What is not here is anything about the addend, because the writer underneath does that part: it
//! reads the type, works out the same one to five, adds it to the addend it was handed and writes
//! the sum into the bytes, since a COFF relocation has no field to keep an addend in.
//!
//! # What this format has no answer for
//!
//! Three things, and each is refused by name rather than written as something close. A visibility is
//! the one that is not refused: `hidden` and `protected` are facts about a dynamic symbol table and
//! a COFF symbol has nowhere to put either, so a file built with `-fvisibility=hidden` for Windows
//! is a file where that flag changed nothing, which is what gcc does there too.
use RelocationFlags;
use pe;
use ;
use Fixup;
use crateReference;
/// Which relocation of this machine one reference is, given how many bytes of the instruction come
/// after the four the linker writes over.
///
/// The first two are the distance to something and are the same relocation here, because a call to
/// a name in another image is answered by an import stub the linker makes whether or not the
/// relocation asked for one, which is the difference ELF spends a second type on. The last two are
/// the address itself at the two widths this machine writes one at.
///
/// Nothing for the two table slots. A global offset table is not how this platform reaches a symbol
/// it does not define, and a thread-local variable is reached through its offset in `.tls` instead,
/// so a file wanting either is a file this cannot write and says so.
///
/// The last is the one relocation here that ELF has nothing to match: four bytes holding how far
/// something is from the front of the image, which is what every field of an unwind table is.
pub
/// The same, as the writer underneath wants it.
pub
/// Which relocation of an AArch64 file one reference is.
///
/// A field of an instruction is the same field ELF names, less the table slots, which are not how
/// this platform reaches anything, and the offsets from the thread pointer, which this platform
/// reaches through the offset from the start of `.tls` instead. The literal load has nothing either:
/// the format has no nineteen bit distance to data, only to code, and gas and clang never ask for
/// one. The six loads and stores are one relocation here, since the linker reads how far to shift
/// the low bits from the instruction rather than from the type.
///
/// The distance written as data is `REL32`, which counts from the byte after the four it fills,
/// and the writer underneath adds the four back to the addend the way it does for the x86 types,
/// so the linker's answer is the distance from the hole that ELF gives.
pub
/// Which relocation of an i386 file one reference is.
///
/// Fewer than x86-64 has, because the one relocation for a distance counts from the end of the four
/// bytes it fills and i386 keeps the addend in those bytes rather than in the type. Whatever else of
/// the instruction comes after the hole is already in the addend, so the count of bytes after it
/// that `REL32_1` through `REL32_5` exist to carry on x86-64 has nowhere to go here and nothing to
/// say. The writer underneath adds the four back, the same as it does for the other machines, so a
/// call carries nothing in its field and a distance written into an image carries four, which is
/// what gas for mingw writes for both.
///
/// An address is `DIR32`, the address from the front of the image is `DIR32NB` and the offset from
/// the start of a section is `SECREL`, which is what a debug section points into another with. An
/// address an instruction holds is `DIR32` too, even where the reader called it signed: the sign
/// extension x86-64 asks about has nothing wider to extend into here, which is why ELF for this
/// machine makes the same choice.
/// `SECTION` is the index of the section a name is in, which only the debug information asks for
/// and is two bytes wide.
///
/// Nothing for the global offset table in any of its forms or for a thread-local variable, which
/// are ELF's ways of reaching something this platform reaches through an import stub and the
/// offset into `.tls` instead. Nothing for eight bytes of anything either, which this machine does
/// not write.
pub
/// The name a symbol has in an i386 file, given the name C gave it.
///
/// Every C name on this machine gets an underscore in front, which is the one decoration the other
/// Windows machines dropped. A name that already starts with `@` is a `__fastcall` function and is
/// already all it is going to be: the `@` takes the place of the underscore rather than coming
/// after one, which is `@f@8`. The pointer the import library fills in for a function in a DLL is
/// `__imp_` in front of the decorated name, so its underscore goes after that prefix and not before
/// it, which makes `__imp__puts` rather than `___imp_puts`.
///
/// The other machines are left alone, and so is a name from a file of assembly, which is already
/// what it says.
/// What the pointer the import library fills in for a function in a DLL is called, in front of the
/// function's own name.
const IMPORT: &str = "__imp_";
/// An instruction with the addend of its relocation written into the field the linker fills, or
/// why it cannot be.
///
/// A COFF relocation has no addend, so the number added to the name goes where the linker will
/// find it, which for data is the bytes being relocated and for an instruction is the field. The
/// writer underneath does the first and refuses the second, so this is the second. What each field
/// holds is what lld and link.exe read back out of it. The page `adrp` names is counted from the
/// name plus the whole addend, so its field is the addend in bytes, all twenty one bits of it. The
/// low twelve bits are added to the low twelve bits of the name, which gives the low twelve bits of
/// the sum whatever the addend is, carried or not, since what is carried out of them is the page's
/// business. A load or store keeps its twelve bits shifted by the size of the access, so the addend
/// has to be a multiple of that size, which it is for any field of a variable the access is of.
///
/// A branch is refused. Its field is combined with the distance in a way that has changed between
/// linkers, and a branch to a name plus a number is not something a compiler writes. The two halves
/// of an offset into `.tls` are refused too, because the high half is worked out from the name
/// alone and a carry out of the low half, which the addend can cause, would be lost between them.
pub
/// Nothing, which is what this format has for a variable the loader writes into before anything
/// reads it and the linker was asked to keep apart from the rest.
///
/// `.data.rel.ro` and the `.local` half of it are an ELF answer to a problem this format solves
/// elsewhere. A Windows image has its fixups applied before the pages are given the protection the
/// section headers asked for, so a pointer that needs one lives in ordinary read only data and is
/// written to anyway, which is where the linker and every other compiler on the platform put it.
pub const REL_RO_LOCAL: = None;
/// What the unwind table is called here, and what it is aligned to.
///
/// One fixed row per function, which the linker sorts by address so that the runtime can find the
/// row for a return address by binary search. Four, because a row is three four byte fields.
///
/// The name is the platform's and the linker matches on it, so it is not a choice: the directory
/// entry telling the runtime where the table is is built out of whatever landed in `.pdata`.
pub const FUNCTIONS: = ;
/// What the second half of the unwind table is called, and what it is aligned to.
///
/// What the rows point at, which is the description of each prologue. A second section rather than
/// more fields, because a row is a fixed size and a description is as long as the prologue it is
/// about.
pub const CODES: = ;
/// Nothing about the stack, and on i386 the `@feat.00` that says the file is safe for SafeSEH.
///
/// A PE image says whether its stack may be run from in the header of the image rather than in a
/// note in every input, so there is no marker for an object to carry and no linker looking for one.
///
/// A 32 bit image linked with `/SAFESEH` carries a table of every exception handler in it, and the
/// linker builds that table from each input's `.sxdata`. It only trusts an input to have told it
/// about all of its handlers when the input says so, which is bit 0 of the absolute symbol
/// `@feat.00`, and without it `lld-link /safeseh` and Microsoft's linker refuse the file. Nothing
/// rucc writes installs a handler, so the list is empty and the claim is true for every file.
/// clang and MSVC write the same symbol with the same bit. A file that already has one, from an
/// assembly file that wrote it, keeps its own.
pub
/// The name of the symbol whose value is the list of features a Microsoft object says it has.
pub const FEAT_00: & = b"@feat.00";
/// The bit of `@feat.00` that says every exception handler in the file is listed in `.sxdata`.
pub const SAFE_SEH: u64 = 1;