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