1 //===- DLL.cpp ------------------------------------------------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This file defines various types of chunks for the DLL import or export
10 // descriptor tables. They are inherently Windows-specific.
11 // You need to read Microsoft PE/COFF spec to understand details
12 // about the data structures.
13 //
14 // If you are not particularly interested in linking against Windows
15 // DLL, you can skip this file, and you should still be able to
16 // understand the rest of the linker.
17 //
18 //===----------------------------------------------------------------------===//
19
20 #include "DLL.h"
21 #include "COFFLinkerContext.h"
22 #include "Chunks.h"
23 #include "SymbolTable.h"
24 #include "llvm/ADT/STLExtras.h"
25 #include "llvm/Object/COFF.h"
26 #include "llvm/Support/Endian.h"
27 #include "llvm/Support/Path.h"
28
29 using namespace llvm;
30 using namespace llvm::object;
31 using namespace llvm::support::endian;
32 using namespace llvm::COFF;
33
34 namespace lld::coff {
35 namespace {
36
37 // Import table
38
39 // A chunk for the import descriptor table.
40 class HintNameChunk : public NonSectionChunk {
41 public:
HintNameChunk(StringRef n,uint16_t h)42 HintNameChunk(StringRef n, uint16_t h) : name(n), hint(h) {}
43
getSize() const44 size_t getSize() const override {
45 // Starts with 2 byte Hint field, followed by a null-terminated string,
46 // ends with 0 or 1 byte padding.
47 return alignTo(name.size() + 3, 2);
48 }
49
writeTo(uint8_t * buf) const50 void writeTo(uint8_t *buf) const override {
51 memset(buf, 0, getSize());
52 write16le(buf, hint);
53 memcpy(buf + 2, name.data(), name.size());
54 }
55
56 private:
57 StringRef name;
58 uint16_t hint;
59 };
60
61 // A chunk for the import descriptor table.
62 class LookupChunk : public NonSectionChunk {
63 public:
LookupChunk(COFFLinkerContext & ctx,Chunk * c)64 explicit LookupChunk(COFFLinkerContext &ctx, Chunk *c)
65 : hintName(c), ctx(ctx) {
66 setAlignment(ctx.config.wordsize);
67 }
getSize() const68 size_t getSize() const override { return ctx.config.wordsize; }
69
writeTo(uint8_t * buf) const70 void writeTo(uint8_t *buf) const override {
71 if (ctx.config.is64())
72 write64le(buf, hintName->getRVA());
73 else
74 write32le(buf, hintName->getRVA());
75 }
76
77 Chunk *hintName;
78
79 private:
80 COFFLinkerContext &ctx;
81 };
82
83 // A chunk for the import descriptor table.
84 // This chunk represent import-by-ordinal symbols.
85 // See Microsoft PE/COFF spec 7.1. Import Header for details.
86 class OrdinalOnlyChunk : public NonSectionChunk {
87 public:
OrdinalOnlyChunk(COFFLinkerContext & c,uint16_t v)88 explicit OrdinalOnlyChunk(COFFLinkerContext &c, uint16_t v)
89 : ordinal(v), ctx(c) {
90 setAlignment(ctx.config.wordsize);
91 }
getSize() const92 size_t getSize() const override { return ctx.config.wordsize; }
93
writeTo(uint8_t * buf) const94 void writeTo(uint8_t *buf) const override {
95 // An import-by-ordinal slot has MSB 1 to indicate that
96 // this is import-by-ordinal (and not import-by-name).
97 if (ctx.config.is64()) {
98 write64le(buf, (1ULL << 63) | ordinal);
99 } else {
100 write32le(buf, (1ULL << 31) | ordinal);
101 }
102 }
103
104 uint16_t ordinal;
105
106 private:
107 COFFLinkerContext &ctx;
108 };
109
110 // A chunk for the import descriptor table.
111 class ImportDirectoryChunk : public NonSectionChunk {
112 public:
ImportDirectoryChunk(Chunk * n)113 explicit ImportDirectoryChunk(Chunk *n) : dllName(n) {}
getSize() const114 size_t getSize() const override { return sizeof(ImportDirectoryTableEntry); }
115
writeTo(uint8_t * buf) const116 void writeTo(uint8_t *buf) const override {
117 memset(buf, 0, getSize());
118
119 auto *e = (coff_import_directory_table_entry *)(buf);
120 e->ImportLookupTableRVA = lookupTab->getRVA();
121 e->NameRVA = dllName->getRVA();
122 e->ImportAddressTableRVA = addressTab->getRVA();
123 }
124
125 Chunk *dllName;
126 Chunk *lookupTab;
127 Chunk *addressTab;
128 };
129
130 // A chunk representing null terminator in the import table.
131 // Contents of this chunk is always null bytes.
132 class NullChunk : public NonSectionChunk {
133 public:
NullChunk(size_t n)134 explicit NullChunk(size_t n) : size(n) { hasData = false; }
getSize() const135 size_t getSize() const override { return size; }
136
writeTo(uint8_t * buf) const137 void writeTo(uint8_t *buf) const override {
138 memset(buf, 0, size);
139 }
140
141 private:
142 size_t size;
143 };
144
145 static std::vector<std::vector<DefinedImportData *>>
binImports(COFFLinkerContext & ctx,const std::vector<DefinedImportData * > & imports)146 binImports(COFFLinkerContext &ctx,
147 const std::vector<DefinedImportData *> &imports) {
148 // Group DLL-imported symbols by DLL name because that's how
149 // symbols are laid out in the import descriptor table.
150 auto less = [&ctx](const std::string &a, const std::string &b) {
151 return ctx.config.dllOrder[a] < ctx.config.dllOrder[b];
152 };
153 std::map<std::string, std::vector<DefinedImportData *>, decltype(less)> m(
154 less);
155 for (DefinedImportData *sym : imports)
156 m[sym->getDLLName().lower()].push_back(sym);
157
158 std::vector<std::vector<DefinedImportData *>> v;
159 for (auto &kv : m) {
160 // Sort symbols by name for each group.
161 std::vector<DefinedImportData *> &syms = kv.second;
162 llvm::sort(syms, [](DefinedImportData *a, DefinedImportData *b) {
163 return a->getName() < b->getName();
164 });
165 v.push_back(std::move(syms));
166 }
167 return v;
168 }
169
170 // See Microsoft PE/COFF spec 4.3 for details.
171
172 // A chunk for the delay import descriptor table etnry.
173 class DelayDirectoryChunk : public NonSectionChunk {
174 public:
DelayDirectoryChunk(Chunk * n)175 explicit DelayDirectoryChunk(Chunk *n) : dllName(n) {}
176
getSize() const177 size_t getSize() const override {
178 return sizeof(delay_import_directory_table_entry);
179 }
180
writeTo(uint8_t * buf) const181 void writeTo(uint8_t *buf) const override {
182 memset(buf, 0, getSize());
183
184 auto *e = (delay_import_directory_table_entry *)(buf);
185 e->Attributes = 1;
186 e->Name = dllName->getRVA();
187 e->ModuleHandle = moduleHandle->getRVA();
188 e->DelayImportAddressTable = addressTab->getRVA();
189 e->DelayImportNameTable = nameTab->getRVA();
190 }
191
192 Chunk *dllName;
193 Chunk *moduleHandle;
194 Chunk *addressTab;
195 Chunk *nameTab;
196 };
197
198 // Initial contents for delay-loaded functions.
199 // This code calls __delayLoadHelper2 function to resolve a symbol
200 // which then overwrites its jump table slot with the result
201 // for subsequent function calls.
202 static const uint8_t thunkX64[] = {
203 0x48, 0x8D, 0x05, 0, 0, 0, 0, // lea rax, [__imp_<FUNCNAME>]
204 0xE9, 0, 0, 0, 0, // jmp __tailMerge_<lib>
205 };
206
207 static const uint8_t tailMergeX64[] = {
208 0x51, // push rcx
209 0x52, // push rdx
210 0x41, 0x50, // push r8
211 0x41, 0x51, // push r9
212 0x48, 0x83, 0xEC, 0x48, // sub rsp, 48h
213 0x66, 0x0F, 0x7F, 0x04, 0x24, // movdqa xmmword ptr [rsp], xmm0
214 0x66, 0x0F, 0x7F, 0x4C, 0x24, 0x10, // movdqa xmmword ptr [rsp+10h], xmm1
215 0x66, 0x0F, 0x7F, 0x54, 0x24, 0x20, // movdqa xmmword ptr [rsp+20h], xmm2
216 0x66, 0x0F, 0x7F, 0x5C, 0x24, 0x30, // movdqa xmmword ptr [rsp+30h], xmm3
217 0x48, 0x8B, 0xD0, // mov rdx, rax
218 0x48, 0x8D, 0x0D, 0, 0, 0, 0, // lea rcx, [___DELAY_IMPORT_...]
219 0xE8, 0, 0, 0, 0, // call __delayLoadHelper2
220 0x66, 0x0F, 0x6F, 0x04, 0x24, // movdqa xmm0, xmmword ptr [rsp]
221 0x66, 0x0F, 0x6F, 0x4C, 0x24, 0x10, // movdqa xmm1, xmmword ptr [rsp+10h]
222 0x66, 0x0F, 0x6F, 0x54, 0x24, 0x20, // movdqa xmm2, xmmword ptr [rsp+20h]
223 0x66, 0x0F, 0x6F, 0x5C, 0x24, 0x30, // movdqa xmm3, xmmword ptr [rsp+30h]
224 0x48, 0x83, 0xC4, 0x48, // add rsp, 48h
225 0x41, 0x59, // pop r9
226 0x41, 0x58, // pop r8
227 0x5A, // pop rdx
228 0x59, // pop rcx
229 0xFF, 0xE0, // jmp rax
230 };
231
232 static const uint8_t tailMergeUnwindInfoX64[] = {
233 0x01, // Version=1, Flags=UNW_FLAG_NHANDLER
234 0x0a, // Size of prolog
235 0x05, // Count of unwind codes
236 0x00, // No frame register
237 0x0a, 0x82, // Offset 0xa: UWOP_ALLOC_SMALL(0x48)
238 0x06, 0x02, // Offset 6: UWOP_ALLOC_SMALL(8)
239 0x04, 0x02, // Offset 4: UWOP_ALLOC_SMALL(8)
240 0x02, 0x02, // Offset 2: UWOP_ALLOC_SMALL(8)
241 0x01, 0x02, // Offset 1: UWOP_ALLOC_SMALL(8)
242 0x00, 0x00 // Padding to align on 32-bits
243 };
244
245 static const uint8_t thunkX86[] = {
246 0xB8, 0, 0, 0, 0, // mov eax, offset ___imp__<FUNCNAME>
247 0xE9, 0, 0, 0, 0, // jmp __tailMerge_<lib>
248 };
249
250 static const uint8_t tailMergeX86[] = {
251 0x51, // push ecx
252 0x52, // push edx
253 0x50, // push eax
254 0x68, 0, 0, 0, 0, // push offset ___DELAY_IMPORT_DESCRIPTOR_<DLLNAME>_dll
255 0xE8, 0, 0, 0, 0, // call ___delayLoadHelper2@8
256 0x5A, // pop edx
257 0x59, // pop ecx
258 0xFF, 0xE0, // jmp eax
259 };
260
261 static const uint8_t thunkARM[] = {
262 0x40, 0xf2, 0x00, 0x0c, // mov.w ip, #0 __imp_<FUNCNAME>
263 0xc0, 0xf2, 0x00, 0x0c, // mov.t ip, #0 __imp_<FUNCNAME>
264 0x00, 0xf0, 0x00, 0xb8, // b.w __tailMerge_<lib>
265 };
266
267 static const uint8_t tailMergeARM[] = {
268 0x2d, 0xe9, 0x0f, 0x48, // push.w {r0, r1, r2, r3, r11, lr}
269 0x0d, 0xf2, 0x10, 0x0b, // addw r11, sp, #16
270 0x2d, 0xed, 0x10, 0x0b, // vpush {d0, d1, d2, d3, d4, d5, d6, d7}
271 0x61, 0x46, // mov r1, ip
272 0x40, 0xf2, 0x00, 0x00, // mov.w r0, #0 DELAY_IMPORT_DESCRIPTOR
273 0xc0, 0xf2, 0x00, 0x00, // mov.t r0, #0 DELAY_IMPORT_DESCRIPTOR
274 0x00, 0xf0, 0x00, 0xd0, // bl #0 __delayLoadHelper2
275 0x84, 0x46, // mov ip, r0
276 0xbd, 0xec, 0x10, 0x0b, // vpop {d0, d1, d2, d3, d4, d5, d6, d7}
277 0xbd, 0xe8, 0x0f, 0x48, // pop.w {r0, r1, r2, r3, r11, lr}
278 0x60, 0x47, // bx ip
279 };
280
281 static const uint8_t thunkARM64[] = {
282 0x11, 0x00, 0x00, 0x90, // adrp x17, #0 __imp_<FUNCNAME>
283 0x31, 0x02, 0x00, 0x91, // add x17, x17, #0 :lo12:__imp_<FUNCNAME>
284 0x00, 0x00, 0x00, 0x14, // b __tailMerge_<lib>
285 };
286
287 static const uint8_t tailMergeARM64[] = {
288 0xfd, 0x7b, 0xb3, 0xa9, // stp x29, x30, [sp, #-208]!
289 0xfd, 0x03, 0x00, 0x91, // mov x29, sp
290 0xe0, 0x07, 0x01, 0xa9, // stp x0, x1, [sp, #16]
291 0xe2, 0x0f, 0x02, 0xa9, // stp x2, x3, [sp, #32]
292 0xe4, 0x17, 0x03, 0xa9, // stp x4, x5, [sp, #48]
293 0xe6, 0x1f, 0x04, 0xa9, // stp x6, x7, [sp, #64]
294 0xe0, 0x87, 0x02, 0xad, // stp q0, q1, [sp, #80]
295 0xe2, 0x8f, 0x03, 0xad, // stp q2, q3, [sp, #112]
296 0xe4, 0x97, 0x04, 0xad, // stp q4, q5, [sp, #144]
297 0xe6, 0x9f, 0x05, 0xad, // stp q6, q7, [sp, #176]
298 0xe1, 0x03, 0x11, 0xaa, // mov x1, x17
299 0x00, 0x00, 0x00, 0x90, // adrp x0, #0 DELAY_IMPORT_DESCRIPTOR
300 0x00, 0x00, 0x00, 0x91, // add x0, x0, #0 :lo12:DELAY_IMPORT_DESCRIPTOR
301 0x00, 0x00, 0x00, 0x94, // bl #0 __delayLoadHelper2
302 0xf0, 0x03, 0x00, 0xaa, // mov x16, x0
303 0xe6, 0x9f, 0x45, 0xad, // ldp q6, q7, [sp, #176]
304 0xe4, 0x97, 0x44, 0xad, // ldp q4, q5, [sp, #144]
305 0xe2, 0x8f, 0x43, 0xad, // ldp q2, q3, [sp, #112]
306 0xe0, 0x87, 0x42, 0xad, // ldp q0, q1, [sp, #80]
307 0xe6, 0x1f, 0x44, 0xa9, // ldp x6, x7, [sp, #64]
308 0xe4, 0x17, 0x43, 0xa9, // ldp x4, x5, [sp, #48]
309 0xe2, 0x0f, 0x42, 0xa9, // ldp x2, x3, [sp, #32]
310 0xe0, 0x07, 0x41, 0xa9, // ldp x0, x1, [sp, #16]
311 0xfd, 0x7b, 0xcd, 0xa8, // ldp x29, x30, [sp], #208
312 0x00, 0x02, 0x1f, 0xd6, // br x16
313 };
314
315 // A chunk for the delay import thunk.
316 class ThunkChunkX64 : public NonSectionChunk {
317 public:
ThunkChunkX64(Defined * i,Chunk * tm)318 ThunkChunkX64(Defined *i, Chunk *tm) : imp(i), tailMerge(tm) {}
319
getSize() const320 size_t getSize() const override { return sizeof(thunkX64); }
321
writeTo(uint8_t * buf) const322 void writeTo(uint8_t *buf) const override {
323 memcpy(buf, thunkX64, sizeof(thunkX64));
324 write32le(buf + 3, imp->getRVA() - rva - 7);
325 write32le(buf + 8, tailMerge->getRVA() - rva - 12);
326 }
327
328 Defined *imp = nullptr;
329 Chunk *tailMerge = nullptr;
330 };
331
332 class TailMergeChunkX64 : public NonSectionChunk {
333 public:
TailMergeChunkX64(Chunk * d,Defined * h)334 TailMergeChunkX64(Chunk *d, Defined *h) : desc(d), helper(h) {}
335
getSize() const336 size_t getSize() const override { return sizeof(tailMergeX64); }
337
writeTo(uint8_t * buf) const338 void writeTo(uint8_t *buf) const override {
339 memcpy(buf, tailMergeX64, sizeof(tailMergeX64));
340 write32le(buf + 39, desc->getRVA() - rva - 43);
341 write32le(buf + 44, helper->getRVA() - rva - 48);
342 }
343
344 Chunk *desc = nullptr;
345 Defined *helper = nullptr;
346 };
347
348 class TailMergePDataChunkX64 : public NonSectionChunk {
349 public:
TailMergePDataChunkX64(Chunk * tm,Chunk * unwind)350 TailMergePDataChunkX64(Chunk *tm, Chunk *unwind) : tm(tm), unwind(unwind) {
351 // See
352 // https://learn.microsoft.com/en-us/cpp/build/exception-handling-x64#struct-runtime_function
353 setAlignment(4);
354 }
355
getSize() const356 size_t getSize() const override { return 3 * sizeof(uint32_t); }
357
writeTo(uint8_t * buf) const358 void writeTo(uint8_t *buf) const override {
359 write32le(buf + 0, tm->getRVA()); // TailMergeChunk start RVA
360 write32le(buf + 4, tm->getRVA() + tm->getSize()); // TailMergeChunk stop RVA
361 write32le(buf + 8, unwind->getRVA()); // UnwindInfo RVA
362 }
363
364 Chunk *tm = nullptr;
365 Chunk *unwind = nullptr;
366 };
367
368 class TailMergeUnwindInfoX64 : public NonSectionChunk {
369 public:
TailMergeUnwindInfoX64()370 TailMergeUnwindInfoX64() {
371 // See
372 // https://learn.microsoft.com/en-us/cpp/build/exception-handling-x64#struct-unwind_info
373 setAlignment(4);
374 }
375
getSize() const376 size_t getSize() const override { return sizeof(tailMergeUnwindInfoX64); }
377
writeTo(uint8_t * buf) const378 void writeTo(uint8_t *buf) const override {
379 memcpy(buf, tailMergeUnwindInfoX64, sizeof(tailMergeUnwindInfoX64));
380 }
381 };
382
383 class ThunkChunkX86 : public NonSectionChunk {
384 public:
ThunkChunkX86(COFFLinkerContext & ctx,Defined * i,Chunk * tm)385 ThunkChunkX86(COFFLinkerContext &ctx, Defined *i, Chunk *tm)
386 : imp(i), tailMerge(tm), ctx(ctx) {}
387
getSize() const388 size_t getSize() const override { return sizeof(thunkX86); }
389
writeTo(uint8_t * buf) const390 void writeTo(uint8_t *buf) const override {
391 memcpy(buf, thunkX86, sizeof(thunkX86));
392 write32le(buf + 1, imp->getRVA() + ctx.config.imageBase);
393 write32le(buf + 6, tailMerge->getRVA() - rva - 10);
394 }
395
getBaserels(std::vector<Baserel> * res)396 void getBaserels(std::vector<Baserel> *res) override {
397 res->emplace_back(rva + 1, ctx.config.machine);
398 }
399
400 Defined *imp = nullptr;
401 Chunk *tailMerge = nullptr;
402
403 private:
404 const COFFLinkerContext &ctx;
405 };
406
407 class TailMergeChunkX86 : public NonSectionChunk {
408 public:
TailMergeChunkX86(COFFLinkerContext & ctx,Chunk * d,Defined * h)409 TailMergeChunkX86(COFFLinkerContext &ctx, Chunk *d, Defined *h)
410 : desc(d), helper(h), ctx(ctx) {}
411
getSize() const412 size_t getSize() const override { return sizeof(tailMergeX86); }
413
writeTo(uint8_t * buf) const414 void writeTo(uint8_t *buf) const override {
415 memcpy(buf, tailMergeX86, sizeof(tailMergeX86));
416 write32le(buf + 4, desc->getRVA() + ctx.config.imageBase);
417 write32le(buf + 9, helper->getRVA() - rva - 13);
418 }
419
getBaserels(std::vector<Baserel> * res)420 void getBaserels(std::vector<Baserel> *res) override {
421 res->emplace_back(rva + 4, ctx.config.machine);
422 }
423
424 Chunk *desc = nullptr;
425 Defined *helper = nullptr;
426
427 private:
428 const COFFLinkerContext &ctx;
429 };
430
431 class ThunkChunkARM : public NonSectionChunk {
432 public:
ThunkChunkARM(COFFLinkerContext & ctx,Defined * i,Chunk * tm)433 ThunkChunkARM(COFFLinkerContext &ctx, Defined *i, Chunk *tm)
434 : imp(i), tailMerge(tm), ctx(ctx) {
435 setAlignment(2);
436 }
437
getSize() const438 size_t getSize() const override { return sizeof(thunkARM); }
439
writeTo(uint8_t * buf) const440 void writeTo(uint8_t *buf) const override {
441 memcpy(buf, thunkARM, sizeof(thunkARM));
442 applyMOV32T(buf + 0, imp->getRVA() + ctx.config.imageBase);
443 applyBranch24T(buf + 8, tailMerge->getRVA() - rva - 12);
444 }
445
getBaserels(std::vector<Baserel> * res)446 void getBaserels(std::vector<Baserel> *res) override {
447 res->emplace_back(rva + 0, IMAGE_REL_BASED_ARM_MOV32T);
448 }
449
450 Defined *imp = nullptr;
451 Chunk *tailMerge = nullptr;
452
453 private:
454 const COFFLinkerContext &ctx;
455 };
456
457 class TailMergeChunkARM : public NonSectionChunk {
458 public:
TailMergeChunkARM(COFFLinkerContext & ctx,Chunk * d,Defined * h)459 TailMergeChunkARM(COFFLinkerContext &ctx, Chunk *d, Defined *h)
460 : desc(d), helper(h), ctx(ctx) {
461 setAlignment(2);
462 }
463
getSize() const464 size_t getSize() const override { return sizeof(tailMergeARM); }
465
writeTo(uint8_t * buf) const466 void writeTo(uint8_t *buf) const override {
467 memcpy(buf, tailMergeARM, sizeof(tailMergeARM));
468 applyMOV32T(buf + 14, desc->getRVA() + ctx.config.imageBase);
469 applyBranch24T(buf + 22, helper->getRVA() - rva - 26);
470 }
471
getBaserels(std::vector<Baserel> * res)472 void getBaserels(std::vector<Baserel> *res) override {
473 res->emplace_back(rva + 14, IMAGE_REL_BASED_ARM_MOV32T);
474 }
475
476 Chunk *desc = nullptr;
477 Defined *helper = nullptr;
478
479 private:
480 const COFFLinkerContext &ctx;
481 };
482
483 class ThunkChunkARM64 : public NonSectionChunk {
484 public:
ThunkChunkARM64(Defined * i,Chunk * tm)485 ThunkChunkARM64(Defined *i, Chunk *tm) : imp(i), tailMerge(tm) {
486 setAlignment(4);
487 }
488
getSize() const489 size_t getSize() const override { return sizeof(thunkARM64); }
490
writeTo(uint8_t * buf) const491 void writeTo(uint8_t *buf) const override {
492 memcpy(buf, thunkARM64, sizeof(thunkARM64));
493 applyArm64Addr(buf + 0, imp->getRVA(), rva + 0, 12);
494 applyArm64Imm(buf + 4, imp->getRVA() & 0xfff, 0);
495 applyArm64Branch26(buf + 8, tailMerge->getRVA() - rva - 8);
496 }
497
498 Defined *imp = nullptr;
499 Chunk *tailMerge = nullptr;
500 };
501
502 class TailMergeChunkARM64 : public NonSectionChunk {
503 public:
TailMergeChunkARM64(Chunk * d,Defined * h)504 TailMergeChunkARM64(Chunk *d, Defined *h) : desc(d), helper(h) {
505 setAlignment(4);
506 }
507
getSize() const508 size_t getSize() const override { return sizeof(tailMergeARM64); }
509
writeTo(uint8_t * buf) const510 void writeTo(uint8_t *buf) const override {
511 memcpy(buf, tailMergeARM64, sizeof(tailMergeARM64));
512 applyArm64Addr(buf + 44, desc->getRVA(), rva + 44, 12);
513 applyArm64Imm(buf + 48, desc->getRVA() & 0xfff, 0);
514 applyArm64Branch26(buf + 52, helper->getRVA() - rva - 52);
515 }
516
517 Chunk *desc = nullptr;
518 Defined *helper = nullptr;
519 };
520
521 // A chunk for the import descriptor table.
522 class DelayAddressChunk : public NonSectionChunk {
523 public:
DelayAddressChunk(COFFLinkerContext & ctx,Chunk * c)524 explicit DelayAddressChunk(COFFLinkerContext &ctx, Chunk *c)
525 : thunk(c), ctx(ctx) {
526 setAlignment(ctx.config.wordsize);
527 }
getSize() const528 size_t getSize() const override { return ctx.config.wordsize; }
529
writeTo(uint8_t * buf) const530 void writeTo(uint8_t *buf) const override {
531 if (ctx.config.is64()) {
532 write64le(buf, thunk->getRVA() + ctx.config.imageBase);
533 } else {
534 uint32_t bit = 0;
535 // Pointer to thumb code must have the LSB set, so adjust it.
536 if (ctx.config.machine == ARMNT)
537 bit = 1;
538 write32le(buf, (thunk->getRVA() + ctx.config.imageBase) | bit);
539 }
540 }
541
getBaserels(std::vector<Baserel> * res)542 void getBaserels(std::vector<Baserel> *res) override {
543 res->emplace_back(rva, ctx.config.machine);
544 }
545
546 Chunk *thunk;
547
548 private:
549 const COFFLinkerContext &ctx;
550 };
551
552 // Export table
553 // Read Microsoft PE/COFF spec 5.3 for details.
554
555 // A chunk for the export descriptor table.
556 class ExportDirectoryChunk : public NonSectionChunk {
557 public:
ExportDirectoryChunk(int i,int j,Chunk * d,Chunk * a,Chunk * n,Chunk * o)558 ExportDirectoryChunk(int i, int j, Chunk *d, Chunk *a, Chunk *n, Chunk *o)
559 : maxOrdinal(i), nameTabSize(j), dllName(d), addressTab(a), nameTab(n),
560 ordinalTab(o) {}
561
getSize() const562 size_t getSize() const override {
563 return sizeof(export_directory_table_entry);
564 }
565
writeTo(uint8_t * buf) const566 void writeTo(uint8_t *buf) const override {
567 memset(buf, 0, getSize());
568
569 auto *e = (export_directory_table_entry *)(buf);
570 e->NameRVA = dllName->getRVA();
571 e->OrdinalBase = 1;
572 e->AddressTableEntries = maxOrdinal;
573 e->NumberOfNamePointers = nameTabSize;
574 e->ExportAddressTableRVA = addressTab->getRVA();
575 e->NamePointerRVA = nameTab->getRVA();
576 e->OrdinalTableRVA = ordinalTab->getRVA();
577 }
578
579 uint16_t maxOrdinal;
580 uint16_t nameTabSize;
581 Chunk *dllName;
582 Chunk *addressTab;
583 Chunk *nameTab;
584 Chunk *ordinalTab;
585 };
586
587 class AddressTableChunk : public NonSectionChunk {
588 public:
AddressTableChunk(COFFLinkerContext & ctx,size_t maxOrdinal)589 explicit AddressTableChunk(COFFLinkerContext &ctx, size_t maxOrdinal)
590 : size(maxOrdinal), ctx(ctx) {}
getSize() const591 size_t getSize() const override { return size * 4; }
592
writeTo(uint8_t * buf) const593 void writeTo(uint8_t *buf) const override {
594 memset(buf, 0, getSize());
595
596 for (const Export &e : ctx.config.exports) {
597 assert(e.ordinal != 0 && "Export symbol has invalid ordinal");
598 // OrdinalBase is 1, so subtract 1 to get the index.
599 uint8_t *p = buf + (e.ordinal - 1) * 4;
600 uint32_t bit = 0;
601 // Pointer to thumb code must have the LSB set, so adjust it.
602 if (ctx.config.machine == ARMNT && !e.data)
603 bit = 1;
604 if (e.forwardChunk) {
605 write32le(p, e.forwardChunk->getRVA() | bit);
606 } else {
607 assert(cast<Defined>(e.sym)->getRVA() != 0 &&
608 "Exported symbol unmapped");
609 write32le(p, cast<Defined>(e.sym)->getRVA() | bit);
610 }
611 }
612 }
613
614 private:
615 size_t size;
616 const COFFLinkerContext &ctx;
617 };
618
619 class NamePointersChunk : public NonSectionChunk {
620 public:
NamePointersChunk(std::vector<Chunk * > & v)621 explicit NamePointersChunk(std::vector<Chunk *> &v) : chunks(v) {}
getSize() const622 size_t getSize() const override { return chunks.size() * 4; }
623
writeTo(uint8_t * buf) const624 void writeTo(uint8_t *buf) const override {
625 for (Chunk *c : chunks) {
626 write32le(buf, c->getRVA());
627 buf += 4;
628 }
629 }
630
631 private:
632 std::vector<Chunk *> chunks;
633 };
634
635 class ExportOrdinalChunk : public NonSectionChunk {
636 public:
ExportOrdinalChunk(const COFFLinkerContext & ctx,size_t i)637 explicit ExportOrdinalChunk(const COFFLinkerContext &ctx, size_t i)
638 : size(i), ctx(ctx) {}
getSize() const639 size_t getSize() const override { return size * 2; }
640
writeTo(uint8_t * buf) const641 void writeTo(uint8_t *buf) const override {
642 for (const Export &e : ctx.config.exports) {
643 if (e.noname)
644 continue;
645 assert(e.ordinal != 0 && "Export symbol has invalid ordinal");
646 // This table stores unbiased indices, so subtract 1 (OrdinalBase).
647 write16le(buf, e.ordinal - 1);
648 buf += 2;
649 }
650 }
651
652 private:
653 size_t size;
654 const COFFLinkerContext &ctx;
655 };
656
657 } // anonymous namespace
658
create(COFFLinkerContext & ctx)659 void IdataContents::create(COFFLinkerContext &ctx) {
660 std::vector<std::vector<DefinedImportData *>> v = binImports(ctx, imports);
661
662 // Create .idata contents for each DLL.
663 for (std::vector<DefinedImportData *> &syms : v) {
664 // Create lookup and address tables. If they have external names,
665 // we need to create hintName chunks to store the names.
666 // If they don't (if they are import-by-ordinals), we store only
667 // ordinal values to the table.
668 size_t base = lookups.size();
669 for (DefinedImportData *s : syms) {
670 uint16_t ord = s->getOrdinal();
671 if (s->getExternalName().empty()) {
672 lookups.push_back(make<OrdinalOnlyChunk>(ctx, ord));
673 addresses.push_back(make<OrdinalOnlyChunk>(ctx, ord));
674 continue;
675 }
676 auto *c = make<HintNameChunk>(s->getExternalName(), ord);
677 lookups.push_back(make<LookupChunk>(ctx, c));
678 addresses.push_back(make<LookupChunk>(ctx, c));
679 hints.push_back(c);
680 }
681 // Terminate with null values.
682 lookups.push_back(make<NullChunk>(ctx.config.wordsize));
683 addresses.push_back(make<NullChunk>(ctx.config.wordsize));
684
685 for (int i = 0, e = syms.size(); i < e; ++i)
686 syms[i]->setLocation(addresses[base + i]);
687
688 // Create the import table header.
689 dllNames.push_back(make<StringChunk>(syms[0]->getDLLName()));
690 auto *dir = make<ImportDirectoryChunk>(dllNames.back());
691 dir->lookupTab = lookups[base];
692 dir->addressTab = addresses[base];
693 dirs.push_back(dir);
694 }
695 // Add null terminator.
696 dirs.push_back(make<NullChunk>(sizeof(ImportDirectoryTableEntry)));
697 }
698
getChunks()699 std::vector<Chunk *> DelayLoadContents::getChunks() {
700 std::vector<Chunk *> v;
701 v.insert(v.end(), dirs.begin(), dirs.end());
702 v.insert(v.end(), names.begin(), names.end());
703 v.insert(v.end(), hintNames.begin(), hintNames.end());
704 v.insert(v.end(), dllNames.begin(), dllNames.end());
705 return v;
706 }
707
getDataChunks()708 std::vector<Chunk *> DelayLoadContents::getDataChunks() {
709 std::vector<Chunk *> v;
710 v.insert(v.end(), moduleHandles.begin(), moduleHandles.end());
711 v.insert(v.end(), addresses.begin(), addresses.end());
712 return v;
713 }
714
getDirSize()715 uint64_t DelayLoadContents::getDirSize() {
716 return dirs.size() * sizeof(delay_import_directory_table_entry);
717 }
718
create(Defined * h)719 void DelayLoadContents::create(Defined *h) {
720 helper = h;
721 std::vector<std::vector<DefinedImportData *>> v = binImports(ctx, imports);
722
723 Chunk *unwind = newTailMergeUnwindInfoChunk();
724
725 // Create .didat contents for each DLL.
726 for (std::vector<DefinedImportData *> &syms : v) {
727 // Create the delay import table header.
728 dllNames.push_back(make<StringChunk>(syms[0]->getDLLName()));
729 auto *dir = make<DelayDirectoryChunk>(dllNames.back());
730
731 size_t base = addresses.size();
732 Chunk *tm = newTailMergeChunk(dir);
733 Chunk *pdataChunk = unwind ? newTailMergePDataChunk(tm, unwind) : nullptr;
734 for (DefinedImportData *s : syms) {
735 Chunk *t = newThunkChunk(s, tm);
736 auto *a = make<DelayAddressChunk>(ctx, t);
737 addresses.push_back(a);
738 thunks.push_back(t);
739 StringRef extName = s->getExternalName();
740 if (extName.empty()) {
741 names.push_back(make<OrdinalOnlyChunk>(ctx, s->getOrdinal()));
742 } else {
743 auto *c = make<HintNameChunk>(extName, 0);
744 names.push_back(make<LookupChunk>(ctx, c));
745 hintNames.push_back(c);
746 // Add a synthetic symbol for this load thunk, using the "__imp___load"
747 // prefix, in case this thunk needs to be added to the list of valid
748 // call targets for Control Flow Guard.
749 StringRef symName = saver().save("__imp___load_" + extName);
750 s->loadThunkSym =
751 cast<DefinedSynthetic>(ctx.symtab.addSynthetic(symName, t));
752 }
753 }
754 thunks.push_back(tm);
755 if (pdataChunk)
756 pdata.push_back(pdataChunk);
757 StringRef tmName =
758 saver().save("__tailMerge_" + syms[0]->getDLLName().lower());
759 ctx.symtab.addSynthetic(tmName, tm);
760 // Terminate with null values.
761 addresses.push_back(make<NullChunk>(8));
762 names.push_back(make<NullChunk>(8));
763
764 for (int i = 0, e = syms.size(); i < e; ++i)
765 syms[i]->setLocation(addresses[base + i]);
766 auto *mh = make<NullChunk>(8);
767 mh->setAlignment(8);
768 moduleHandles.push_back(mh);
769
770 // Fill the delay import table header fields.
771 dir->moduleHandle = mh;
772 dir->addressTab = addresses[base];
773 dir->nameTab = names[base];
774 dirs.push_back(dir);
775 }
776
777 if (unwind)
778 unwindinfo.push_back(unwind);
779 // Add null terminator.
780 dirs.push_back(make<NullChunk>(sizeof(delay_import_directory_table_entry)));
781 }
782
newTailMergeChunk(Chunk * dir)783 Chunk *DelayLoadContents::newTailMergeChunk(Chunk *dir) {
784 switch (ctx.config.machine) {
785 case AMD64:
786 return make<TailMergeChunkX64>(dir, helper);
787 case I386:
788 return make<TailMergeChunkX86>(ctx, dir, helper);
789 case ARMNT:
790 return make<TailMergeChunkARM>(ctx, dir, helper);
791 case ARM64:
792 return make<TailMergeChunkARM64>(dir, helper);
793 default:
794 llvm_unreachable("unsupported machine type");
795 }
796 }
797
newTailMergeUnwindInfoChunk()798 Chunk *DelayLoadContents::newTailMergeUnwindInfoChunk() {
799 switch (ctx.config.machine) {
800 case AMD64:
801 return make<TailMergeUnwindInfoX64>();
802 // FIXME: Add support for other architectures.
803 default:
804 return nullptr; // Just don't generate unwind info.
805 }
806 }
newTailMergePDataChunk(Chunk * tm,Chunk * unwind)807 Chunk *DelayLoadContents::newTailMergePDataChunk(Chunk *tm, Chunk *unwind) {
808 switch (ctx.config.machine) {
809 case AMD64:
810 return make<TailMergePDataChunkX64>(tm, unwind);
811 // FIXME: Add support for other architectures.
812 default:
813 return nullptr; // Just don't generate unwind info.
814 }
815 }
816
newThunkChunk(DefinedImportData * s,Chunk * tailMerge)817 Chunk *DelayLoadContents::newThunkChunk(DefinedImportData *s,
818 Chunk *tailMerge) {
819 switch (ctx.config.machine) {
820 case AMD64:
821 return make<ThunkChunkX64>(s, tailMerge);
822 case I386:
823 return make<ThunkChunkX86>(ctx, s, tailMerge);
824 case ARMNT:
825 return make<ThunkChunkARM>(ctx, s, tailMerge);
826 case ARM64:
827 return make<ThunkChunkARM64>(s, tailMerge);
828 default:
829 llvm_unreachable("unsupported machine type");
830 }
831 }
832
EdataContents(COFFLinkerContext & ctx)833 EdataContents::EdataContents(COFFLinkerContext &ctx) : ctx(ctx) {
834 uint16_t maxOrdinal = 0;
835 for (Export &e : ctx.config.exports)
836 maxOrdinal = std::max(maxOrdinal, e.ordinal);
837
838 auto *dllName = make<StringChunk>(sys::path::filename(ctx.config.outputFile));
839 auto *addressTab = make<AddressTableChunk>(ctx, maxOrdinal);
840 std::vector<Chunk *> names;
841 for (Export &e : ctx.config.exports)
842 if (!e.noname)
843 names.push_back(make<StringChunk>(e.exportName));
844
845 std::vector<Chunk *> forwards;
846 for (Export &e : ctx.config.exports) {
847 if (e.forwardTo.empty())
848 continue;
849 e.forwardChunk = make<StringChunk>(e.forwardTo);
850 forwards.push_back(e.forwardChunk);
851 }
852
853 auto *nameTab = make<NamePointersChunk>(names);
854 auto *ordinalTab = make<ExportOrdinalChunk>(ctx, names.size());
855 auto *dir = make<ExportDirectoryChunk>(maxOrdinal, names.size(), dllName,
856 addressTab, nameTab, ordinalTab);
857 chunks.push_back(dir);
858 chunks.push_back(dllName);
859 chunks.push_back(addressTab);
860 chunks.push_back(nameTab);
861 chunks.push_back(ordinalTab);
862 chunks.insert(chunks.end(), names.begin(), names.end());
863 chunks.insert(chunks.end(), forwards.begin(), forwards.end());
864 }
865
866 } // namespace lld::coff
867