blob: 79e201a9af1b329ee806f63471a75a71ecc28558 [file] [log] [blame]
Rui Ueyama4b22fa72015-06-07 01:15:04 +00001//===- 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//
Rui Ueyamaa77336b2015-06-21 22:31:52 +000010// This file defines various types of chunks for the DLL import or export
11// descriptor tables. They are inherently Windows-specific.
Rui Ueyama4b22fa72015-06-07 01:15:04 +000012// 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 "Chunks.h"
22#include "DLL.h"
23#include "llvm/ADT/STLExtras.h"
24#include "llvm/Object/COFF.h"
25#include "llvm/Support/Endian.h"
Rui Ueyama97dff9e2015-06-17 00:16:33 +000026#include "llvm/Support/Path.h"
Rui Ueyama4b22fa72015-06-07 01:15:04 +000027
28using namespace llvm;
29using namespace llvm::object;
30using namespace llvm::support::endian;
31using namespace llvm::COFF;
Rui Ueyama4b22fa72015-06-07 01:15:04 +000032
Rui Ueyama4b22fa72015-06-07 01:15:04 +000033namespace lld {
34namespace coff {
Rui Ueyama857b3032015-08-10 23:02:57 +000035namespace {
Rui Ueyama4b22fa72015-06-07 01:15:04 +000036
Rui Ueyama97dff9e2015-06-17 00:16:33 +000037// Import table
38
Rui Ueyama25522f52015-07-09 00:45:50 +000039static int ptrSize() { return Config->is64() ? 8 : 4; }
40
Rui Ueyama4b22fa72015-06-07 01:15:04 +000041// A chunk for the import descriptor table.
42class HintNameChunk : public Chunk {
43public:
44 HintNameChunk(StringRef N, uint16_t H) : Name(N), Hint(H) {}
45
46 size_t getSize() const override {
47 // Starts with 2 byte Hint field, followed by a null-terminated string,
48 // ends with 0 or 1 byte padding.
49 return RoundUpToAlignment(Name.size() + 3, 2);
50 }
51
52 void writeTo(uint8_t *Buf) override {
Rafael Espindola5c546a12015-08-14 03:30:59 +000053 write16le(Buf + OutputSectionOff, Hint);
54 memcpy(Buf + OutputSectionOff + 2, Name.data(), Name.size());
Rui Ueyama4b22fa72015-06-07 01:15:04 +000055 }
56
57private:
58 StringRef Name;
59 uint16_t Hint;
60};
61
62// A chunk for the import descriptor table.
63class LookupChunk : public Chunk {
64public:
65 explicit LookupChunk(Chunk *C) : HintName(C) {}
Rui Ueyama25522f52015-07-09 00:45:50 +000066 size_t getSize() const override { return ptrSize(); }
Rui Ueyama4b22fa72015-06-07 01:15:04 +000067
68 void writeTo(uint8_t *Buf) override {
Rafael Espindola5c546a12015-08-14 03:30:59 +000069 write32le(Buf + OutputSectionOff, HintName->getRVA());
Rui Ueyama4b22fa72015-06-07 01:15:04 +000070 }
71
72 Chunk *HintName;
73};
74
75// A chunk for the import descriptor table.
76// This chunk represent import-by-ordinal symbols.
77// See Microsoft PE/COFF spec 7.1. Import Header for details.
78class OrdinalOnlyChunk : public Chunk {
79public:
80 explicit OrdinalOnlyChunk(uint16_t V) : Ordinal(V) {}
Rui Ueyama25522f52015-07-09 00:45:50 +000081 size_t getSize() const override { return ptrSize(); }
Rui Ueyama4b22fa72015-06-07 01:15:04 +000082
83 void writeTo(uint8_t *Buf) override {
84 // An import-by-ordinal slot has MSB 1 to indicate that
85 // this is import-by-ordinal (and not import-by-name).
Rui Ueyama25522f52015-07-09 00:45:50 +000086 if (Config->is64()) {
Rafael Espindola5c546a12015-08-14 03:30:59 +000087 write64le(Buf + OutputSectionOff, (1ULL << 63) | Ordinal);
Rui Ueyama25522f52015-07-09 00:45:50 +000088 } else {
Rafael Espindola5c546a12015-08-14 03:30:59 +000089 write32le(Buf + OutputSectionOff, (1ULL << 31) | Ordinal);
Rui Ueyama25522f52015-07-09 00:45:50 +000090 }
Rui Ueyama4b22fa72015-06-07 01:15:04 +000091 }
92
93 uint16_t Ordinal;
94};
95
96// A chunk for the import descriptor table.
Rui Ueyama97dff9e2015-06-17 00:16:33 +000097class ImportDirectoryChunk : public Chunk {
Rui Ueyama4b22fa72015-06-07 01:15:04 +000098public:
Rui Ueyama97dff9e2015-06-17 00:16:33 +000099 explicit ImportDirectoryChunk(Chunk *N) : DLLName(N) {}
100 size_t getSize() const override { return sizeof(ImportDirectoryTableEntry); }
Rui Ueyama4b22fa72015-06-07 01:15:04 +0000101
102 void writeTo(uint8_t *Buf) override {
Rafael Espindola5c546a12015-08-14 03:30:59 +0000103 auto *E = (coff_import_directory_table_entry *)(Buf + OutputSectionOff);
Rui Ueyama4b22fa72015-06-07 01:15:04 +0000104 E->ImportLookupTableRVA = LookupTab->getRVA();
105 E->NameRVA = DLLName->getRVA();
106 E->ImportAddressTableRVA = AddressTab->getRVA();
107 }
108
109 Chunk *DLLName;
110 Chunk *LookupTab;
111 Chunk *AddressTab;
112};
113
114// A chunk representing null terminator in the import table.
115// Contents of this chunk is always null bytes.
116class NullChunk : public Chunk {
117public:
118 explicit NullChunk(size_t N) : Size(N) {}
119 bool hasData() const override { return false; }
120 size_t getSize() const override { return Size; }
Rui Ueyamaa77336b2015-06-21 22:31:52 +0000121 void setAlign(size_t N) { Align = N; }
Rui Ueyama4b22fa72015-06-07 01:15:04 +0000122
123private:
124 size_t Size;
125};
126
Rui Ueyamad1570882015-08-17 08:30:31 +0000127static std::vector<std::vector<DefinedImportData *>>
Rui Ueyamaa77336b2015-06-21 22:31:52 +0000128binImports(const std::vector<DefinedImportData *> &Imports) {
Rui Ueyama4b22fa72015-06-07 01:15:04 +0000129 // Group DLL-imported symbols by DLL name because that's how
130 // symbols are layed out in the import descriptor table.
Rui Ueyamabfbd2772015-09-02 07:27:31 +0000131 auto Less = [](const std::string &A, const std::string &B) {
Rui Ueyamad1570882015-08-17 08:30:31 +0000132 return Config->DLLOrder[A] < Config->DLLOrder[B];
133 };
Rui Ueyamabfbd2772015-09-02 07:27:31 +0000134 std::map<std::string, std::vector<DefinedImportData *>,
135 bool(*)(const std::string &, const std::string &)> M(Less);
Rui Ueyama4b22fa72015-06-07 01:15:04 +0000136 for (DefinedImportData *Sym : Imports)
Rui Ueyamabfbd2772015-09-02 07:27:31 +0000137 M[Sym->getDLLName().lower()].push_back(Sym);
Rui Ueyamaa77336b2015-06-21 22:31:52 +0000138
Rui Ueyamad1570882015-08-17 08:30:31 +0000139 std::vector<std::vector<DefinedImportData *>> V;
Rui Ueyamaa77336b2015-06-21 22:31:52 +0000140 for (auto &P : M) {
141 // Sort symbols by name for each group.
142 std::vector<DefinedImportData *> &Syms = P.second;
143 std::sort(Syms.begin(), Syms.end(),
144 [](DefinedImportData *A, DefinedImportData *B) {
145 return A->getName() < B->getName();
146 });
Rui Ueyamad1570882015-08-17 08:30:31 +0000147 V.push_back(std::move(Syms));
Rui Ueyamaa77336b2015-06-21 22:31:52 +0000148 }
Rui Ueyamad1570882015-08-17 08:30:31 +0000149 return V;
Rui Ueyamaa77336b2015-06-21 22:31:52 +0000150}
151
Rui Ueyama97dff9e2015-06-17 00:16:33 +0000152// Export table
Rui Ueyamaa77336b2015-06-21 22:31:52 +0000153// See Microsoft PE/COFF spec 4.3 for details.
154
155// A chunk for the delay import descriptor table etnry.
156class DelayDirectoryChunk : public Chunk {
157public:
158 explicit DelayDirectoryChunk(Chunk *N) : DLLName(N) {}
159
160 size_t getSize() const override {
161 return sizeof(delay_import_directory_table_entry);
162 }
163
164 void writeTo(uint8_t *Buf) override {
Rafael Espindola5c546a12015-08-14 03:30:59 +0000165 auto *E = (delay_import_directory_table_entry *)(Buf + OutputSectionOff);
Rui Ueyama382dc962015-06-26 21:40:15 +0000166 E->Attributes = 1;
Rui Ueyamaa77336b2015-06-21 22:31:52 +0000167 E->Name = DLLName->getRVA();
168 E->ModuleHandle = ModuleHandle->getRVA();
169 E->DelayImportAddressTable = AddressTab->getRVA();
170 E->DelayImportNameTable = NameTab->getRVA();
171 }
172
173 Chunk *DLLName;
174 Chunk *ModuleHandle;
175 Chunk *AddressTab;
176 Chunk *NameTab;
177};
178
179// Initial contents for delay-loaded functions.
Rui Ueyama61096202015-06-22 17:26:27 +0000180// This code calls __delayLoadHelper2 function to resolve a symbol
Rui Ueyamaa77336b2015-06-21 22:31:52 +0000181// and then overwrites its jump table slot with the result
182// for subsequent function calls.
Rui Ueyamaef0e6472015-07-15 22:26:57 +0000183static const uint8_t ThunkX64[] = {
Rui Ueyamaa77336b2015-06-21 22:31:52 +0000184 0x51, // push rcx
185 0x52, // push rdx
186 0x41, 0x50, // push r8
187 0x41, 0x51, // push r9
188 0x48, 0x83, 0xEC, 0x48, // sub rsp, 48h
189 0x66, 0x0F, 0x7F, 0x04, 0x24, // movdqa xmmword ptr [rsp], xmm0
190 0x66, 0x0F, 0x7F, 0x4C, 0x24, 0x10, // movdqa xmmword ptr [rsp+10h], xmm1
191 0x66, 0x0F, 0x7F, 0x54, 0x24, 0x20, // movdqa xmmword ptr [rsp+20h], xmm2
192 0x66, 0x0F, 0x7F, 0x5C, 0x24, 0x30, // movdqa xmmword ptr [rsp+30h], xmm3
193 0x48, 0x8D, 0x15, 0, 0, 0, 0, // lea rdx, [__imp_<FUNCNAME>]
194 0x48, 0x8D, 0x0D, 0, 0, 0, 0, // lea rcx, [___DELAY_IMPORT_...]
195 0xE8, 0, 0, 0, 0, // call __delayLoadHelper2
196 0x66, 0x0F, 0x6F, 0x04, 0x24, // movdqa xmm0, xmmword ptr [rsp]
197 0x66, 0x0F, 0x6F, 0x4C, 0x24, 0x10, // movdqa xmm1, xmmword ptr [rsp+10h]
198 0x66, 0x0F, 0x6F, 0x54, 0x24, 0x20, // movdqa xmm2, xmmword ptr [rsp+20h]
199 0x66, 0x0F, 0x6F, 0x5C, 0x24, 0x30, // movdqa xmm3, xmmword ptr [rsp+30h]
200 0x48, 0x83, 0xC4, 0x48, // add rsp, 48h
201 0x41, 0x59, // pop r9
202 0x41, 0x58, // pop r8
203 0x5A, // pop rdx
204 0x59, // pop rcx
205 0xFF, 0xE0, // jmp rax
206};
207
Rui Ueyamaef0e6472015-07-15 22:26:57 +0000208static const uint8_t ThunkX86[] = {
209 0x51, // push ecx
210 0x52, // push edx
211 0x68, 0, 0, 0, 0, // push offset ___imp__<FUNCNAME>
212 0x68, 0, 0, 0, 0, // push offset ___DELAY_IMPORT_DESCRIPTOR_<DLLNAME>_dll
213 0xE8, 0, 0, 0, 0, // call ___delayLoadHelper2@8
214 0x5A, // pop edx
215 0x59, // pop ecx
216 0xFF, 0xE0, // jmp eax
217};
218
Rui Ueyamaa77336b2015-06-21 22:31:52 +0000219// A chunk for the delay import thunk.
Rui Ueyamaef0e6472015-07-15 22:26:57 +0000220class ThunkChunkX64 : public Chunk {
Rui Ueyamaa77336b2015-06-21 22:31:52 +0000221public:
Rui Ueyamaef0e6472015-07-15 22:26:57 +0000222 ThunkChunkX64(Defined *I, Chunk *D, Defined *H)
223 : Imp(I), Desc(D), Helper(H) {}
224
225 size_t getSize() const override { return sizeof(ThunkX64); }
Rui Ueyamaa77336b2015-06-21 22:31:52 +0000226
227 void writeTo(uint8_t *Buf) override {
Rafael Espindola5c546a12015-08-14 03:30:59 +0000228 memcpy(Buf + OutputSectionOff, ThunkX64, sizeof(ThunkX64));
229 write32le(Buf + OutputSectionOff + 36, Imp->getRVA() - RVA - 40);
230 write32le(Buf + OutputSectionOff + 43, Desc->getRVA() - RVA - 47);
231 write32le(Buf + OutputSectionOff + 48, Helper->getRVA() - RVA - 52);
Rui Ueyamaa77336b2015-06-21 22:31:52 +0000232 }
233
234 Defined *Imp = nullptr;
235 Chunk *Desc = nullptr;
236 Defined *Helper = nullptr;
237};
238
Rui Ueyamaef0e6472015-07-15 22:26:57 +0000239class ThunkChunkX86 : public Chunk {
240public:
241 ThunkChunkX86(Defined *I, Chunk *D, Defined *H)
242 : Imp(I), Desc(D), Helper(H) {}
243
244 size_t getSize() const override { return sizeof(ThunkX86); }
245
246 void writeTo(uint8_t *Buf) override {
Rafael Espindola5c546a12015-08-14 03:30:59 +0000247 memcpy(Buf + OutputSectionOff, ThunkX86, sizeof(ThunkX86));
248 write32le(Buf + OutputSectionOff + 3, Imp->getRVA() + Config->ImageBase);
249 write32le(Buf + OutputSectionOff + 8, Desc->getRVA() + Config->ImageBase);
250 write32le(Buf + OutputSectionOff + 13, Helper->getRVA() - RVA - 17);
Rui Ueyamaef0e6472015-07-15 22:26:57 +0000251 }
252
Rui Ueyama3afd5bf2015-07-25 01:44:32 +0000253 void getBaserels(std::vector<Baserel> *Res) override {
254 Res->emplace_back(RVA + 3);
255 Res->emplace_back(RVA + 8);
Rui Ueyamaef0e6472015-07-15 22:26:57 +0000256 }
257
258 Defined *Imp = nullptr;
259 Chunk *Desc = nullptr;
260 Defined *Helper = nullptr;
261};
262
Rui Ueyama382dc962015-06-26 21:40:15 +0000263// A chunk for the import descriptor table.
264class DelayAddressChunk : public Chunk {
265public:
266 explicit DelayAddressChunk(Chunk *C) : Thunk(C) {}
Rui Ueyama7e387a62015-07-28 02:54:18 +0000267 size_t getSize() const override { return ptrSize(); }
Rui Ueyama382dc962015-06-26 21:40:15 +0000268
269 void writeTo(uint8_t *Buf) override {
Rui Ueyama7e387a62015-07-28 02:54:18 +0000270 if (Config->is64()) {
Rafael Espindola5c546a12015-08-14 03:30:59 +0000271 write64le(Buf + OutputSectionOff, Thunk->getRVA() + Config->ImageBase);
Rui Ueyama7e387a62015-07-28 02:54:18 +0000272 } else {
Rafael Espindola5c546a12015-08-14 03:30:59 +0000273 write32le(Buf + OutputSectionOff, Thunk->getRVA() + Config->ImageBase);
Rui Ueyama7e387a62015-07-28 02:54:18 +0000274 }
Rui Ueyama382dc962015-06-26 21:40:15 +0000275 }
276
Rui Ueyama3afd5bf2015-07-25 01:44:32 +0000277 void getBaserels(std::vector<Baserel> *Res) override {
278 Res->emplace_back(RVA);
Rui Ueyama810551a2015-06-26 22:05:32 +0000279 }
280
Rui Ueyama382dc962015-06-26 21:40:15 +0000281 Chunk *Thunk;
282};
283
Rui Ueyamaa77336b2015-06-21 22:31:52 +0000284// Export table
Rui Ueyama97dff9e2015-06-17 00:16:33 +0000285// Read Microsoft PE/COFF spec 5.3 for details.
286
287// A chunk for the export descriptor table.
288class ExportDirectoryChunk : public Chunk {
289public:
290 ExportDirectoryChunk(int I, int J, Chunk *D, Chunk *A, Chunk *N, Chunk *O)
291 : MaxOrdinal(I), NameTabSize(J), DLLName(D), AddressTab(A), NameTab(N),
292 OrdinalTab(O) {}
293
294 size_t getSize() const override {
295 return sizeof(export_directory_table_entry);
296 }
297
298 void writeTo(uint8_t *Buf) override {
Rafael Espindola5c546a12015-08-14 03:30:59 +0000299 auto *E = (export_directory_table_entry *)(Buf + OutputSectionOff);
Rui Ueyama97dff9e2015-06-17 00:16:33 +0000300 E->NameRVA = DLLName->getRVA();
301 E->OrdinalBase = 0;
302 E->AddressTableEntries = MaxOrdinal + 1;
303 E->NumberOfNamePointers = NameTabSize;
304 E->ExportAddressTableRVA = AddressTab->getRVA();
305 E->NamePointerRVA = NameTab->getRVA();
306 E->OrdinalTableRVA = OrdinalTab->getRVA();
307 }
308
309 uint16_t MaxOrdinal;
310 uint16_t NameTabSize;
311 Chunk *DLLName;
312 Chunk *AddressTab;
313 Chunk *NameTab;
314 Chunk *OrdinalTab;
315};
316
317class AddressTableChunk : public Chunk {
318public:
319 explicit AddressTableChunk(size_t MaxOrdinal) : Size(MaxOrdinal + 1) {}
320 size_t getSize() const override { return Size * 4; }
321
322 void writeTo(uint8_t *Buf) override {
Rui Ueyamaf5313b32015-06-28 22:16:41 +0000323 for (Export &E : Config->Exports) {
Rui Ueyama0744e872015-07-02 00:21:11 +0000324 auto *D = cast<Defined>(E.Sym->repl());
Rafael Espindola5c546a12015-08-14 03:30:59 +0000325 write32le(Buf + OutputSectionOff + E.Ordinal * 4, D->getRVA());
Rui Ueyamaf5313b32015-06-28 22:16:41 +0000326 }
Rui Ueyama97dff9e2015-06-17 00:16:33 +0000327 }
328
329private:
330 size_t Size;
331};
332
333class NamePointersChunk : public Chunk {
334public:
335 explicit NamePointersChunk(std::vector<Chunk *> &V) : Chunks(V) {}
336 size_t getSize() const override { return Chunks.size() * 4; }
337
338 void writeTo(uint8_t *Buf) override {
Rafael Espindola5c546a12015-08-14 03:30:59 +0000339 uint8_t *P = Buf + OutputSectionOff;
Rui Ueyama97dff9e2015-06-17 00:16:33 +0000340 for (Chunk *C : Chunks) {
341 write32le(P, C->getRVA());
342 P += 4;
343 }
344 }
345
346private:
347 std::vector<Chunk *> Chunks;
348};
349
350class ExportOrdinalChunk : public Chunk {
351public:
352 explicit ExportOrdinalChunk(size_t I) : Size(I) {}
353 size_t getSize() const override { return Size * 2; }
354
355 void writeTo(uint8_t *Buf) override {
Rafael Espindola5c546a12015-08-14 03:30:59 +0000356 uint8_t *P = Buf + OutputSectionOff;
Rui Ueyama97dff9e2015-06-17 00:16:33 +0000357 for (Export &E : Config->Exports) {
358 if (E.Noname)
359 continue;
360 write16le(P, E.Ordinal);
361 P += 2;
362 }
363 }
364
365private:
366 size_t Size;
367};
368
Rui Ueyama857b3032015-08-10 23:02:57 +0000369} // anonymous namespace
370
371uint64_t IdataContents::getDirSize() {
372 return Dirs.size() * sizeof(ImportDirectoryTableEntry);
373}
374
375uint64_t IdataContents::getIATSize() {
376 return Addresses.size() * ptrSize();
377}
378
379// Returns a list of .idata contents.
380// See Microsoft PE/COFF spec 5.4 for details.
381std::vector<Chunk *> IdataContents::getChunks() {
382 create();
383 std::vector<Chunk *> V;
384 // The loader assumes a specific order of data.
385 // Add each type in the correct order.
386 for (std::unique_ptr<Chunk> &C : Dirs)
387 V.push_back(C.get());
388 for (std::unique_ptr<Chunk> &C : Lookups)
389 V.push_back(C.get());
390 for (std::unique_ptr<Chunk> &C : Addresses)
391 V.push_back(C.get());
392 for (std::unique_ptr<Chunk> &C : Hints)
393 V.push_back(C.get());
394 for (auto &P : DLLNames) {
395 std::unique_ptr<Chunk> &C = P.second;
396 V.push_back(C.get());
397 }
398 return V;
399}
400
401void IdataContents::create() {
Rui Ueyamad1570882015-08-17 08:30:31 +0000402 std::vector<std::vector<DefinedImportData *>> V = binImports(Imports);
Rui Ueyama857b3032015-08-10 23:02:57 +0000403
404 // Create .idata contents for each DLL.
Rui Ueyamad1570882015-08-17 08:30:31 +0000405 for (std::vector<DefinedImportData *> &Syms : V) {
406 StringRef Name = Syms[0]->getDLLName();
Rui Ueyama857b3032015-08-10 23:02:57 +0000407
408 // Create lookup and address tables. If they have external names,
409 // we need to create HintName chunks to store the names.
410 // If they don't (if they are import-by-ordinals), we store only
411 // ordinal values to the table.
412 size_t Base = Lookups.size();
413 for (DefinedImportData *S : Syms) {
414 uint16_t Ord = S->getOrdinal();
415 if (S->getExternalName().empty()) {
416 Lookups.push_back(make_unique<OrdinalOnlyChunk>(Ord));
417 Addresses.push_back(make_unique<OrdinalOnlyChunk>(Ord));
418 continue;
419 }
420 auto C = make_unique<HintNameChunk>(S->getExternalName(), Ord);
421 Lookups.push_back(make_unique<LookupChunk>(C.get()));
422 Addresses.push_back(make_unique<LookupChunk>(C.get()));
423 Hints.push_back(std::move(C));
424 }
425 // Terminate with null values.
426 Lookups.push_back(make_unique<NullChunk>(ptrSize()));
427 Addresses.push_back(make_unique<NullChunk>(ptrSize()));
428
429 for (int I = 0, E = Syms.size(); I < E; ++I)
430 Syms[I]->setLocation(Addresses[Base + I].get());
431
432 // Create the import table header.
433 if (!DLLNames.count(Name))
434 DLLNames[Name] = make_unique<StringChunk>(Name);
435 auto Dir = make_unique<ImportDirectoryChunk>(DLLNames[Name].get());
436 Dir->LookupTab = Lookups[Base].get();
437 Dir->AddressTab = Addresses[Base].get();
438 Dirs.push_back(std::move(Dir));
439 }
440 // Add null terminator.
441 Dirs.push_back(make_unique<NullChunk>(sizeof(ImportDirectoryTableEntry)));
442}
443
444std::vector<Chunk *> DelayLoadContents::getChunks() {
445 std::vector<Chunk *> V;
446 for (std::unique_ptr<Chunk> &C : Dirs)
447 V.push_back(C.get());
448 for (std::unique_ptr<Chunk> &C : Names)
449 V.push_back(C.get());
450 for (std::unique_ptr<Chunk> &C : HintNames)
451 V.push_back(C.get());
452 for (auto &P : DLLNames) {
453 std::unique_ptr<Chunk> &C = P.second;
454 V.push_back(C.get());
455 }
456 return V;
457}
458
459std::vector<Chunk *> DelayLoadContents::getDataChunks() {
460 std::vector<Chunk *> V;
461 for (std::unique_ptr<Chunk> &C : ModuleHandles)
462 V.push_back(C.get());
463 for (std::unique_ptr<Chunk> &C : Addresses)
464 V.push_back(C.get());
465 return V;
466}
467
468uint64_t DelayLoadContents::getDirSize() {
469 return Dirs.size() * sizeof(delay_import_directory_table_entry);
470}
471
472void DelayLoadContents::create(Defined *H) {
473 Helper = H;
Rui Ueyamad1570882015-08-17 08:30:31 +0000474 std::vector<std::vector<DefinedImportData *>> V = binImports(Imports);
Rui Ueyama857b3032015-08-10 23:02:57 +0000475
476 // Create .didat contents for each DLL.
Rui Ueyamad1570882015-08-17 08:30:31 +0000477 for (std::vector<DefinedImportData *> &Syms : V) {
478 StringRef Name = Syms[0]->getDLLName();
Rui Ueyama857b3032015-08-10 23:02:57 +0000479
480 // Create the delay import table header.
481 if (!DLLNames.count(Name))
482 DLLNames[Name] = make_unique<StringChunk>(Name);
483 auto Dir = make_unique<DelayDirectoryChunk>(DLLNames[Name].get());
484
485 size_t Base = Addresses.size();
486 for (DefinedImportData *S : Syms) {
487 Chunk *T = newThunkChunk(S, Dir.get());
488 auto A = make_unique<DelayAddressChunk>(T);
489 Addresses.push_back(std::move(A));
490 Thunks.push_back(std::unique_ptr<Chunk>(T));
491 StringRef ExtName = S->getExternalName();
492 if (ExtName.empty()) {
493 Names.push_back(make_unique<OrdinalOnlyChunk>(S->getOrdinal()));
494 } else {
495 auto C = make_unique<HintNameChunk>(ExtName, 0);
496 Names.push_back(make_unique<LookupChunk>(C.get()));
497 HintNames.push_back(std::move(C));
498 }
499 }
500 // Terminate with null values.
501 Addresses.push_back(make_unique<NullChunk>(8));
502 Names.push_back(make_unique<NullChunk>(8));
503
504 for (int I = 0, E = Syms.size(); I < E; ++I)
505 Syms[I]->setLocation(Addresses[Base + I].get());
506 auto *MH = new NullChunk(8);
507 MH->setAlign(8);
508 ModuleHandles.push_back(std::unique_ptr<Chunk>(MH));
509
510 // Fill the delay import table header fields.
511 Dir->ModuleHandle = MH;
512 Dir->AddressTab = Addresses[Base].get();
513 Dir->NameTab = Names[Base].get();
514 Dirs.push_back(std::move(Dir));
515 }
516 // Add null terminator.
517 Dirs.push_back(
518 make_unique<NullChunk>(sizeof(delay_import_directory_table_entry)));
519}
520
521Chunk *DelayLoadContents::newThunkChunk(DefinedImportData *S, Chunk *Dir) {
522 switch (Config->Machine) {
523 case AMD64:
524 return new ThunkChunkX64(S, Dir, Helper);
525 case I386:
526 return new ThunkChunkX86(S, Dir, Helper);
527 default:
528 llvm_unreachable("unsupported machine type");
529 }
530}
531
Rui Ueyama97dff9e2015-06-17 00:16:33 +0000532EdataContents::EdataContents() {
533 uint16_t MaxOrdinal = 0;
534 for (Export &E : Config->Exports)
535 MaxOrdinal = std::max(MaxOrdinal, E.Ordinal);
536
537 auto *DLLName = new StringChunk(sys::path::filename(Config->OutputFile));
538 auto *AddressTab = new AddressTableChunk(MaxOrdinal);
539 std::vector<Chunk *> Names;
540 for (Export &E : Config->Exports)
541 if (!E.Noname)
Rui Ueyamaf10a3202015-08-31 08:43:21 +0000542 Names.push_back(new StringChunk(E.ExportName));
Rui Ueyama97dff9e2015-06-17 00:16:33 +0000543 auto *NameTab = new NamePointersChunk(Names);
544 auto *OrdinalTab = new ExportOrdinalChunk(Names.size());
545 auto *Dir = new ExportDirectoryChunk(MaxOrdinal, Names.size(), DLLName,
546 AddressTab, NameTab, OrdinalTab);
547 Chunks.push_back(std::unique_ptr<Chunk>(Dir));
548 Chunks.push_back(std::unique_ptr<Chunk>(DLLName));
549 Chunks.push_back(std::unique_ptr<Chunk>(AddressTab));
550 Chunks.push_back(std::unique_ptr<Chunk>(NameTab));
551 Chunks.push_back(std::unique_ptr<Chunk>(OrdinalTab));
552 for (Chunk *C : Names)
553 Chunks.push_back(std::unique_ptr<Chunk>(C));
Rui Ueyama4b22fa72015-06-07 01:15:04 +0000554}
555
556} // namespace coff
557} // namespace lld