xref: /llvm-project-15.0.7/lld/COFF/DLL.cpp (revision e3748b5a)
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 "Chunks.h"
22 #include "llvm/Object/COFF.h"
23 #include "llvm/Support/Endian.h"
24 #include "llvm/Support/Path.h"
25 
26 using namespace llvm;
27 using namespace llvm::object;
28 using namespace llvm::support::endian;
29 using namespace llvm::COFF;
30 
31 namespace lld {
32 namespace coff {
33 namespace {
34 
35 // Import table
36 
37 // A chunk for the import descriptor table.
38 class HintNameChunk : public Chunk {
39 public:
40   HintNameChunk(StringRef N, uint16_t H) : Name(N), Hint(H) {}
41 
42   size_t getSize() const override {
43     // Starts with 2 byte Hint field, followed by a null-terminated string,
44     // ends with 0 or 1 byte padding.
45     return alignTo(Name.size() + 3, 2);
46   }
47 
48   void writeTo(uint8_t *Buf) const override {
49     memset(Buf, 0, getSize());
50     write16le(Buf, Hint);
51     memcpy(Buf + 2, Name.data(), Name.size());
52   }
53 
54 private:
55   StringRef Name;
56   uint16_t Hint;
57 };
58 
59 // A chunk for the import descriptor table.
60 class LookupChunk : public Chunk {
61 public:
62   explicit LookupChunk(Chunk *C) : HintName(C) {
63     setAlignment(Config->Wordsize);
64   }
65   size_t getSize() const override { return Config->Wordsize; }
66 
67   void writeTo(uint8_t *Buf) const override {
68     if (Config->is64())
69       write64le(Buf, HintName->getRVA());
70     else
71       write32le(Buf, HintName->getRVA());
72   }
73 
74   Chunk *HintName;
75 };
76 
77 // A chunk for the import descriptor table.
78 // This chunk represent import-by-ordinal symbols.
79 // See Microsoft PE/COFF spec 7.1. Import Header for details.
80 class OrdinalOnlyChunk : public Chunk {
81 public:
82   explicit OrdinalOnlyChunk(uint16_t V) : Ordinal(V) {
83     setAlignment(Config->Wordsize);
84   }
85   size_t getSize() const override { return Config->Wordsize; }
86 
87   void writeTo(uint8_t *Buf) const override {
88     // An import-by-ordinal slot has MSB 1 to indicate that
89     // this is import-by-ordinal (and not import-by-name).
90     if (Config->is64()) {
91       write64le(Buf, (1ULL << 63) | Ordinal);
92     } else {
93       write32le(Buf, (1ULL << 31) | Ordinal);
94     }
95   }
96 
97   uint16_t Ordinal;
98 };
99 
100 // A chunk for the import descriptor table.
101 class ImportDirectoryChunk : public Chunk {
102 public:
103   explicit ImportDirectoryChunk(Chunk *N) : DLLName(N) {}
104   size_t getSize() const override { return sizeof(ImportDirectoryTableEntry); }
105 
106   void writeTo(uint8_t *Buf) const override {
107     memset(Buf, 0, getSize());
108 
109     auto *E = (coff_import_directory_table_entry *)(Buf);
110     E->ImportLookupTableRVA = LookupTab->getRVA();
111     E->NameRVA = DLLName->getRVA();
112     E->ImportAddressTableRVA = AddressTab->getRVA();
113   }
114 
115   Chunk *DLLName;
116   Chunk *LookupTab;
117   Chunk *AddressTab;
118 };
119 
120 // A chunk representing null terminator in the import table.
121 // Contents of this chunk is always null bytes.
122 class NullChunk : public Chunk {
123 public:
124   explicit NullChunk(size_t N) : Size(N) {}
125   bool hasData() const override { return false; }
126   size_t getSize() const override { return Size; }
127 
128   void writeTo(uint8_t *Buf) const override {
129     memset(Buf, 0, Size);
130   }
131 
132 private:
133   size_t Size;
134 };
135 
136 static std::vector<std::vector<DefinedImportData *>>
137 binImports(const std::vector<DefinedImportData *> &Imports) {
138   // Group DLL-imported symbols by DLL name because that's how
139   // symbols are layed out in the import descriptor table.
140   auto Less = [](const std::string &A, const std::string &B) {
141     return Config->DLLOrder[A] < Config->DLLOrder[B];
142   };
143   std::map<std::string, std::vector<DefinedImportData *>,
144            bool(*)(const std::string &, const std::string &)> M(Less);
145   for (DefinedImportData *Sym : Imports)
146     M[Sym->getDLLName().lower()].push_back(Sym);
147 
148   std::vector<std::vector<DefinedImportData *>> V;
149   for (auto &KV : M) {
150     // Sort symbols by name for each group.
151     std::vector<DefinedImportData *> &Syms = KV.second;
152     std::sort(Syms.begin(), Syms.end(),
153               [](DefinedImportData *A, DefinedImportData *B) {
154                 return A->getName() < B->getName();
155               });
156     V.push_back(std::move(Syms));
157   }
158   return V;
159 }
160 
161 // Export table
162 // See Microsoft PE/COFF spec 4.3 for details.
163 
164 // A chunk for the delay import descriptor table etnry.
165 class DelayDirectoryChunk : public Chunk {
166 public:
167   explicit DelayDirectoryChunk(Chunk *N) : DLLName(N) {}
168 
169   size_t getSize() const override {
170     return sizeof(delay_import_directory_table_entry);
171   }
172 
173   void writeTo(uint8_t *Buf) const override {
174     memset(Buf, 0, getSize());
175 
176     auto *E = (delay_import_directory_table_entry *)(Buf);
177     E->Attributes = 1;
178     E->Name = DLLName->getRVA();
179     E->ModuleHandle = ModuleHandle->getRVA();
180     E->DelayImportAddressTable = AddressTab->getRVA();
181     E->DelayImportNameTable = NameTab->getRVA();
182   }
183 
184   Chunk *DLLName;
185   Chunk *ModuleHandle;
186   Chunk *AddressTab;
187   Chunk *NameTab;
188 };
189 
190 // Initial contents for delay-loaded functions.
191 // This code calls __delayLoadHelper2 function to resolve a symbol
192 // and then overwrites its jump table slot with the result
193 // for subsequent function calls.
194 static const uint8_t ThunkX64[] = {
195     0x51,                               // push    rcx
196     0x52,                               // push    rdx
197     0x41, 0x50,                         // push    r8
198     0x41, 0x51,                         // push    r9
199     0x48, 0x83, 0xEC, 0x48,             // sub     rsp, 48h
200     0x66, 0x0F, 0x7F, 0x04, 0x24,       // movdqa  xmmword ptr [rsp], xmm0
201     0x66, 0x0F, 0x7F, 0x4C, 0x24, 0x10, // movdqa  xmmword ptr [rsp+10h], xmm1
202     0x66, 0x0F, 0x7F, 0x54, 0x24, 0x20, // movdqa  xmmword ptr [rsp+20h], xmm2
203     0x66, 0x0F, 0x7F, 0x5C, 0x24, 0x30, // movdqa  xmmword ptr [rsp+30h], xmm3
204     0x48, 0x8D, 0x15, 0, 0, 0, 0,       // lea     rdx, [__imp_<FUNCNAME>]
205     0x48, 0x8D, 0x0D, 0, 0, 0, 0,       // lea     rcx, [___DELAY_IMPORT_...]
206     0xE8, 0, 0, 0, 0,                   // call    __delayLoadHelper2
207     0x66, 0x0F, 0x6F, 0x04, 0x24,       // movdqa  xmm0, xmmword ptr [rsp]
208     0x66, 0x0F, 0x6F, 0x4C, 0x24, 0x10, // movdqa  xmm1, xmmword ptr [rsp+10h]
209     0x66, 0x0F, 0x6F, 0x54, 0x24, 0x20, // movdqa  xmm2, xmmword ptr [rsp+20h]
210     0x66, 0x0F, 0x6F, 0x5C, 0x24, 0x30, // movdqa  xmm3, xmmword ptr [rsp+30h]
211     0x48, 0x83, 0xC4, 0x48,             // add     rsp, 48h
212     0x41, 0x59,                         // pop     r9
213     0x41, 0x58,                         // pop     r8
214     0x5A,                               // pop     rdx
215     0x59,                               // pop     rcx
216     0xFF, 0xE0,                         // jmp     rax
217 };
218 
219 static const uint8_t ThunkX86[] = {
220     0x51,              // push  ecx
221     0x52,              // push  edx
222     0x68, 0, 0, 0, 0,  // push  offset ___imp__<FUNCNAME>
223     0x68, 0, 0, 0, 0,  // push  offset ___DELAY_IMPORT_DESCRIPTOR_<DLLNAME>_dll
224     0xE8, 0, 0, 0, 0,  // call  ___delayLoadHelper2@8
225     0x5A,              // pop   edx
226     0x59,              // pop   ecx
227     0xFF, 0xE0,        // jmp   eax
228 };
229 
230 static const uint8_t ThunkARM[] = {
231     0x40, 0xf2, 0x00, 0x0c, // mov.w   ip, #0 __imp_<FUNCNAME>
232     0xc0, 0xf2, 0x00, 0x0c, // mov.t   ip, #0 __imp_<FUNCNAME>
233     0x2d, 0xe9, 0x0f, 0x48, // push.w  {r0, r1, r2, r3, r11, lr}
234     0x0d, 0xf2, 0x10, 0x0b, // addw    r11, sp, #16
235     0x2d, 0xed, 0x10, 0x0b, // vpush   {d0, d1, d2, d3, d4, d5, d6, d7}
236     0x61, 0x46,             // mov     r1, ip
237     0x40, 0xf2, 0x00, 0x00, // mov.w   r0, #0 DELAY_IMPORT_DESCRIPTOR
238     0xc0, 0xf2, 0x00, 0x00, // mov.t   r0, #0 DELAY_IMPORT_DESCRIPTOR
239     0x00, 0xf0, 0x00, 0xd0, // bl      #0 __delayLoadHelper2
240     0x84, 0x46,             // mov     ip, r0
241     0xbd, 0xec, 0x10, 0x0b, // vpop    {d0, d1, d2, d3, d4, d5, d6, d7}
242     0xbd, 0xe8, 0x0f, 0x48, // pop.w   {r0, r1, r2, r3, r11, lr}
243     0x60, 0x47,             // bx      ip
244 };
245 
246 static const uint8_t ThunkARM64[] = {
247     0x11, 0x00, 0x00, 0x90, // adrp    x17, #0      __imp_<FUNCNAME>
248     0x31, 0x02, 0x00, 0x91, // add     x17, x17, #0 :lo12:__imp_<FUNCNAME>
249     0xfd, 0x7b, 0xb3, 0xa9, // stp     x29, x30, [sp, #-208]!
250     0xfd, 0x03, 0x00, 0x91, // mov     x29, sp
251     0xe0, 0x07, 0x01, 0xa9, // stp     x0, x1, [sp, #16]
252     0xe2, 0x0f, 0x02, 0xa9, // stp     x2, x3, [sp, #32]
253     0xe4, 0x17, 0x03, 0xa9, // stp     x4, x5, [sp, #48]
254     0xe6, 0x1f, 0x04, 0xa9, // stp     x6, x7, [sp, #64]
255     0xe0, 0x87, 0x02, 0xad, // stp     q0, q1, [sp, #80]
256     0xe2, 0x8f, 0x03, 0xad, // stp     q2, q3, [sp, #112]
257     0xe4, 0x97, 0x04, 0xad, // stp     q4, q5, [sp, #144]
258     0xe6, 0x9f, 0x05, 0xad, // stp     q6, q7, [sp, #176]
259     0xe1, 0x03, 0x11, 0xaa, // mov     x1, x17
260     0x00, 0x00, 0x00, 0x90, // adrp    x0, #0     DELAY_IMPORT_DESCRIPTOR
261     0x00, 0x00, 0x00, 0x91, // add     x0, x0, #0 :lo12:DELAY_IMPORT_DESCRIPTOR
262     0x00, 0x00, 0x00, 0x94, // bl      #0 __delayLoadHelper2
263     0xf0, 0x03, 0x00, 0xaa, // mov     x16, x0
264     0xe6, 0x9f, 0x45, 0xad, // ldp     q6, q7, [sp, #176]
265     0xe4, 0x97, 0x44, 0xad, // ldp     q4, q5, [sp, #144]
266     0xe2, 0x8f, 0x43, 0xad, // ldp     q2, q3, [sp, #112]
267     0xe0, 0x87, 0x42, 0xad, // ldp     q0, q1, [sp, #80]
268     0xe6, 0x1f, 0x44, 0xa9, // ldp     x6, x7, [sp, #64]
269     0xe4, 0x17, 0x43, 0xa9, // ldp     x4, x5, [sp, #48]
270     0xe2, 0x0f, 0x42, 0xa9, // ldp     x2, x3, [sp, #32]
271     0xe0, 0x07, 0x41, 0xa9, // ldp     x0, x1, [sp, #16]
272     0xfd, 0x7b, 0xcd, 0xa8, // ldp     x29, x30, [sp], #208
273     0x00, 0x02, 0x1f, 0xd6, // br      x16
274 };
275 
276 // A chunk for the delay import thunk.
277 class ThunkChunkX64 : public Chunk {
278 public:
279   ThunkChunkX64(Defined *I, Chunk *D, Defined *H)
280       : Imp(I), Desc(D), Helper(H) {}
281 
282   size_t getSize() const override { return sizeof(ThunkX64); }
283 
284   void writeTo(uint8_t *Buf) const override {
285     memcpy(Buf, ThunkX64, sizeof(ThunkX64));
286     write32le(Buf + 36, Imp->getRVA() - RVA - 40);
287     write32le(Buf + 43, Desc->getRVA() - RVA - 47);
288     write32le(Buf + 48, Helper->getRVA() - RVA - 52);
289   }
290 
291   Defined *Imp = nullptr;
292   Chunk *Desc = nullptr;
293   Defined *Helper = nullptr;
294 };
295 
296 class ThunkChunkX86 : public Chunk {
297 public:
298   ThunkChunkX86(Defined *I, Chunk *D, Defined *H)
299       : Imp(I), Desc(D), Helper(H) {}
300 
301   size_t getSize() const override { return sizeof(ThunkX86); }
302 
303   void writeTo(uint8_t *Buf) const override {
304     memcpy(Buf, ThunkX86, sizeof(ThunkX86));
305     write32le(Buf + 3, Imp->getRVA() + Config->ImageBase);
306     write32le(Buf + 8, Desc->getRVA() + Config->ImageBase);
307     write32le(Buf + 13, Helper->getRVA() - RVA - 17);
308   }
309 
310   void getBaserels(std::vector<Baserel> *Res) override {
311     Res->emplace_back(RVA + 3);
312     Res->emplace_back(RVA + 8);
313   }
314 
315   Defined *Imp = nullptr;
316   Chunk *Desc = nullptr;
317   Defined *Helper = nullptr;
318 };
319 
320 class ThunkChunkARM : public Chunk {
321 public:
322   ThunkChunkARM(Defined *I, Chunk *D, Defined *H)
323       : Imp(I), Desc(D), Helper(H) {}
324 
325   size_t getSize() const override { return sizeof(ThunkARM); }
326 
327   void writeTo(uint8_t *Buf) const override {
328     memcpy(Buf, ThunkARM, sizeof(ThunkARM));
329     applyMOV32T(Buf + 0, Imp->getRVA() + Config->ImageBase);
330     applyMOV32T(Buf + 22, Desc->getRVA() + Config->ImageBase);
331     applyBranch24T(Buf + 30, Helper->getRVA() - RVA - 34);
332   }
333 
334   void getBaserels(std::vector<Baserel> *Res) override {
335     Res->emplace_back(RVA + 0, IMAGE_REL_BASED_ARM_MOV32T);
336     Res->emplace_back(RVA + 22, IMAGE_REL_BASED_ARM_MOV32T);
337   }
338 
339   Defined *Imp = nullptr;
340   Chunk *Desc = nullptr;
341   Defined *Helper = nullptr;
342 };
343 
344 class ThunkChunkARM64 : public Chunk {
345 public:
346   ThunkChunkARM64(Defined *I, Chunk *D, Defined *H)
347       : Imp(I), Desc(D), Helper(H) {}
348 
349   size_t getSize() const override { return sizeof(ThunkARM64); }
350 
351   void writeTo(uint8_t *Buf) const override {
352     memcpy(Buf, ThunkARM64, sizeof(ThunkARM64));
353     applyArm64Addr(Buf + 0, Imp->getRVA(), RVA + 0, 12);
354     applyArm64Imm(Buf + 4, Imp->getRVA() & 0xfff, 0);
355     applyArm64Addr(Buf + 52, Desc->getRVA(), RVA + 52, 12);
356     applyArm64Imm(Buf + 56, Desc->getRVA() & 0xfff, 0);
357     applyArm64Branch26(Buf + 60, Helper->getRVA() - RVA - 60);
358   }
359 
360   Defined *Imp = nullptr;
361   Chunk *Desc = nullptr;
362   Defined *Helper = nullptr;
363 };
364 
365 // A chunk for the import descriptor table.
366 class DelayAddressChunk : public Chunk {
367 public:
368   explicit DelayAddressChunk(Chunk *C) : Thunk(C) {
369     setAlignment(Config->Wordsize);
370   }
371   size_t getSize() const override { return Config->Wordsize; }
372 
373   void writeTo(uint8_t *Buf) const override {
374     if (Config->is64()) {
375       write64le(Buf, Thunk->getRVA() + Config->ImageBase);
376     } else {
377       uint32_t Bit = 0;
378       // Pointer to thumb code must have the LSB set, so adjust it.
379       if (Config->Machine == ARMNT)
380         Bit = 1;
381       write32le(Buf, (Thunk->getRVA() + Config->ImageBase) | Bit);
382     }
383   }
384 
385   void getBaserels(std::vector<Baserel> *Res) override {
386     Res->emplace_back(RVA);
387   }
388 
389   Chunk *Thunk;
390 };
391 
392 // Export table
393 // Read Microsoft PE/COFF spec 5.3 for details.
394 
395 // A chunk for the export descriptor table.
396 class ExportDirectoryChunk : public Chunk {
397 public:
398   ExportDirectoryChunk(int I, int J, Chunk *D, Chunk *A, Chunk *N, Chunk *O)
399       : MaxOrdinal(I), NameTabSize(J), DLLName(D), AddressTab(A), NameTab(N),
400         OrdinalTab(O) {}
401 
402   size_t getSize() const override {
403     return sizeof(export_directory_table_entry);
404   }
405 
406   void writeTo(uint8_t *Buf) const override {
407     memset(Buf, 0, getSize());
408 
409     auto *E = (export_directory_table_entry *)(Buf);
410     E->NameRVA = DLLName->getRVA();
411     E->OrdinalBase = 0;
412     E->AddressTableEntries = MaxOrdinal + 1;
413     E->NumberOfNamePointers = NameTabSize;
414     E->ExportAddressTableRVA = AddressTab->getRVA();
415     E->NamePointerRVA = NameTab->getRVA();
416     E->OrdinalTableRVA = OrdinalTab->getRVA();
417   }
418 
419   uint16_t MaxOrdinal;
420   uint16_t NameTabSize;
421   Chunk *DLLName;
422   Chunk *AddressTab;
423   Chunk *NameTab;
424   Chunk *OrdinalTab;
425 };
426 
427 class AddressTableChunk : public Chunk {
428 public:
429   explicit AddressTableChunk(size_t MaxOrdinal) : Size(MaxOrdinal + 1) {}
430   size_t getSize() const override { return Size * 4; }
431 
432   void writeTo(uint8_t *Buf) const override {
433     memset(Buf, 0, getSize());
434 
435     for (const Export &E : Config->Exports) {
436       uint8_t *P = Buf + E.Ordinal * 4;
437       uint32_t Bit = 0;
438       // Pointer to thumb code must have the LSB set, so adjust it.
439       if (Config->Machine == ARMNT && !E.Data)
440         Bit = 1;
441       if (E.ForwardChunk) {
442         write32le(P, E.ForwardChunk->getRVA() | Bit);
443       } else {
444         write32le(P, cast<Defined>(E.Sym)->getRVA() | Bit);
445       }
446     }
447   }
448 
449 private:
450   size_t Size;
451 };
452 
453 class NamePointersChunk : public Chunk {
454 public:
455   explicit NamePointersChunk(std::vector<Chunk *> &V) : Chunks(V) {}
456   size_t getSize() const override { return Chunks.size() * 4; }
457 
458   void writeTo(uint8_t *Buf) const override {
459     for (Chunk *C : Chunks) {
460       write32le(Buf, C->getRVA());
461       Buf += 4;
462     }
463   }
464 
465 private:
466   std::vector<Chunk *> Chunks;
467 };
468 
469 class ExportOrdinalChunk : public Chunk {
470 public:
471   explicit ExportOrdinalChunk(size_t I) : Size(I) {}
472   size_t getSize() const override { return Size * 2; }
473 
474   void writeTo(uint8_t *Buf) const override {
475     for (Export &E : Config->Exports) {
476       if (E.Noname)
477         continue;
478       write16le(Buf, E.Ordinal);
479       Buf += 2;
480     }
481   }
482 
483 private:
484   size_t Size;
485 };
486 
487 } // anonymous namespace
488 
489 void IdataContents::create() {
490   std::vector<std::vector<DefinedImportData *>> V = binImports(Imports);
491 
492   // Create .idata contents for each DLL.
493   for (std::vector<DefinedImportData *> &Syms : V) {
494     // Create lookup and address tables. If they have external names,
495     // we need to create HintName chunks to store the names.
496     // If they don't (if they are import-by-ordinals), we store only
497     // ordinal values to the table.
498     size_t Base = Lookups.size();
499     for (DefinedImportData *S : Syms) {
500       uint16_t Ord = S->getOrdinal();
501       if (S->getExternalName().empty()) {
502         Lookups.push_back(make<OrdinalOnlyChunk>(Ord));
503         Addresses.push_back(make<OrdinalOnlyChunk>(Ord));
504         continue;
505       }
506       auto *C = make<HintNameChunk>(S->getExternalName(), Ord);
507       Lookups.push_back(make<LookupChunk>(C));
508       Addresses.push_back(make<LookupChunk>(C));
509       Hints.push_back(C);
510     }
511     // Terminate with null values.
512     Lookups.push_back(make<NullChunk>(Config->Wordsize));
513     Addresses.push_back(make<NullChunk>(Config->Wordsize));
514 
515     for (int I = 0, E = Syms.size(); I < E; ++I)
516       Syms[I]->setLocation(Addresses[Base + I]);
517 
518     // Create the import table header.
519     DLLNames.push_back(make<StringChunk>(Syms[0]->getDLLName()));
520     auto *Dir = make<ImportDirectoryChunk>(DLLNames.back());
521     Dir->LookupTab = Lookups[Base];
522     Dir->AddressTab = Addresses[Base];
523     Dirs.push_back(Dir);
524   }
525   // Add null terminator.
526   Dirs.push_back(make<NullChunk>(sizeof(ImportDirectoryTableEntry)));
527 }
528 
529 std::vector<Chunk *> DelayLoadContents::getChunks() {
530   std::vector<Chunk *> V;
531   V.insert(V.end(), Dirs.begin(), Dirs.end());
532   V.insert(V.end(), Names.begin(), Names.end());
533   V.insert(V.end(), HintNames.begin(), HintNames.end());
534   V.insert(V.end(), DLLNames.begin(), DLLNames.end());
535   return V;
536 }
537 
538 std::vector<Chunk *> DelayLoadContents::getDataChunks() {
539   std::vector<Chunk *> V;
540   V.insert(V.end(), ModuleHandles.begin(), ModuleHandles.end());
541   V.insert(V.end(), Addresses.begin(), Addresses.end());
542   return V;
543 }
544 
545 uint64_t DelayLoadContents::getDirSize() {
546   return Dirs.size() * sizeof(delay_import_directory_table_entry);
547 }
548 
549 void DelayLoadContents::create(Defined *H) {
550   Helper = H;
551   std::vector<std::vector<DefinedImportData *>> V = binImports(Imports);
552 
553   // Create .didat contents for each DLL.
554   for (std::vector<DefinedImportData *> &Syms : V) {
555     // Create the delay import table header.
556     DLLNames.push_back(make<StringChunk>(Syms[0]->getDLLName()));
557     auto *Dir = make<DelayDirectoryChunk>(DLLNames.back());
558 
559     size_t Base = Addresses.size();
560     for (DefinedImportData *S : Syms) {
561       Chunk *T = newThunkChunk(S, Dir);
562       auto *A = make<DelayAddressChunk>(T);
563       Addresses.push_back(A);
564       Thunks.push_back(T);
565       StringRef ExtName = S->getExternalName();
566       if (ExtName.empty()) {
567         Names.push_back(make<OrdinalOnlyChunk>(S->getOrdinal()));
568       } else {
569         auto *C = make<HintNameChunk>(ExtName, 0);
570         Names.push_back(make<LookupChunk>(C));
571         HintNames.push_back(C);
572       }
573     }
574     // Terminate with null values.
575     Addresses.push_back(make<NullChunk>(8));
576     Names.push_back(make<NullChunk>(8));
577 
578     for (int I = 0, E = Syms.size(); I < E; ++I)
579       Syms[I]->setLocation(Addresses[Base + I]);
580     auto *MH = make<NullChunk>(8);
581     MH->setAlignment(8);
582     ModuleHandles.push_back(MH);
583 
584     // Fill the delay import table header fields.
585     Dir->ModuleHandle = MH;
586     Dir->AddressTab = Addresses[Base];
587     Dir->NameTab = Names[Base];
588     Dirs.push_back(Dir);
589   }
590   // Add null terminator.
591   Dirs.push_back(make<NullChunk>(sizeof(delay_import_directory_table_entry)));
592 }
593 
594 Chunk *DelayLoadContents::newThunkChunk(DefinedImportData *S, Chunk *Dir) {
595   switch (Config->Machine) {
596   case AMD64:
597     return make<ThunkChunkX64>(S, Dir, Helper);
598   case I386:
599     return make<ThunkChunkX86>(S, Dir, Helper);
600   case ARMNT:
601     return make<ThunkChunkARM>(S, Dir, Helper);
602   case ARM64:
603     return make<ThunkChunkARM64>(S, Dir, Helper);
604   default:
605     llvm_unreachable("unsupported machine type");
606   }
607 }
608 
609 EdataContents::EdataContents() {
610   uint16_t MaxOrdinal = 0;
611   for (Export &E : Config->Exports)
612     MaxOrdinal = std::max(MaxOrdinal, E.Ordinal);
613 
614   auto *DLLName = make<StringChunk>(sys::path::filename(Config->OutputFile));
615   auto *AddressTab = make<AddressTableChunk>(MaxOrdinal);
616   std::vector<Chunk *> Names;
617   for (Export &E : Config->Exports)
618     if (!E.Noname)
619       Names.push_back(make<StringChunk>(E.ExportName));
620 
621   std::vector<Chunk *> Forwards;
622   for (Export &E : Config->Exports) {
623     if (E.ForwardTo.empty())
624       continue;
625     E.ForwardChunk = make<StringChunk>(E.ForwardTo);
626     Forwards.push_back(E.ForwardChunk);
627   }
628 
629   auto *NameTab = make<NamePointersChunk>(Names);
630   auto *OrdinalTab = make<ExportOrdinalChunk>(Names.size());
631   auto *Dir = make<ExportDirectoryChunk>(MaxOrdinal, Names.size(), DLLName,
632                                          AddressTab, NameTab, OrdinalTab);
633   Chunks.push_back(Dir);
634   Chunks.push_back(DLLName);
635   Chunks.push_back(AddressTab);
636   Chunks.push_back(NameTab);
637   Chunks.push_back(OrdinalTab);
638   Chunks.insert(Chunks.end(), Names.begin(), Names.end());
639   Chunks.insert(Chunks.end(), Forwards.begin(), Forwards.end());
640 }
641 
642 } // namespace coff
643 } // namespace lld
644