blob: 479e643a80e539a2c2b88e28572e7fe5b2ab89c5 [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;
32using llvm::RoundUpToAlignment;
33
Rui Ueyama94df7132015-06-07 03:55:28 +000034static const size_t LookupChunkSize = sizeof(uint64_t);
Rui Ueyama4b22fa72015-06-07 01:15:04 +000035
36namespace lld {
37namespace coff {
38
Rui Ueyama97dff9e2015-06-17 00:16:33 +000039// Import table
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 {
53 write16le(Buf + FileOff, Hint);
54 memcpy(Buf + FileOff + 2, Name.data(), Name.size());
55 }
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) {}
66 size_t getSize() const override { return LookupChunkSize; }
67
68 void writeTo(uint8_t *Buf) override {
69 write32le(Buf + FileOff, HintName->getRVA());
70 }
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) {}
81 size_t getSize() const override { return sizeof(uint64_t); }
82
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).
86 write64le(Buf + FileOff, (uint64_t(1) << 63) | Ordinal);
87 }
88
89 uint16_t Ordinal;
90};
91
92// A chunk for the import descriptor table.
Rui Ueyama97dff9e2015-06-17 00:16:33 +000093class ImportDirectoryChunk : public Chunk {
Rui Ueyama4b22fa72015-06-07 01:15:04 +000094public:
Rui Ueyama97dff9e2015-06-17 00:16:33 +000095 explicit ImportDirectoryChunk(Chunk *N) : DLLName(N) {}
96 size_t getSize() const override { return sizeof(ImportDirectoryTableEntry); }
Rui Ueyama4b22fa72015-06-07 01:15:04 +000097
98 void writeTo(uint8_t *Buf) override {
99 auto *E = (coff_import_directory_table_entry *)(Buf + FileOff);
100 E->ImportLookupTableRVA = LookupTab->getRVA();
101 E->NameRVA = DLLName->getRVA();
102 E->ImportAddressTableRVA = AddressTab->getRVA();
103 }
104
105 Chunk *DLLName;
106 Chunk *LookupTab;
107 Chunk *AddressTab;
108};
109
110// A chunk representing null terminator in the import table.
111// Contents of this chunk is always null bytes.
112class NullChunk : public Chunk {
113public:
114 explicit NullChunk(size_t N) : Size(N) {}
115 bool hasData() const override { return false; }
116 size_t getSize() const override { return Size; }
Rui Ueyamaa77336b2015-06-21 22:31:52 +0000117 void setAlign(size_t N) { Align = N; }
Rui Ueyama4b22fa72015-06-07 01:15:04 +0000118
119private:
120 size_t Size;
121};
122
123uint64_t IdataContents::getDirSize() {
Rui Ueyama97dff9e2015-06-17 00:16:33 +0000124 return Dirs.size() * sizeof(ImportDirectoryTableEntry);
Rui Ueyama4b22fa72015-06-07 01:15:04 +0000125}
126
127uint64_t IdataContents::getIATSize() {
128 return Addresses.size() * LookupChunkSize;
129}
130
131// Returns a list of .idata contents.
132// See Microsoft PE/COFF spec 5.4 for details.
133std::vector<Chunk *> IdataContents::getChunks() {
134 create();
135 std::vector<Chunk *> V;
136 // The loader assumes a specific order of data.
137 // Add each type in the correct order.
138 for (std::unique_ptr<Chunk> &C : Dirs)
139 V.push_back(C.get());
140 for (std::unique_ptr<Chunk> &C : Lookups)
141 V.push_back(C.get());
142 for (std::unique_ptr<Chunk> &C : Addresses)
143 V.push_back(C.get());
144 for (std::unique_ptr<Chunk> &C : Hints)
145 V.push_back(C.get());
146 for (auto &P : DLLNames) {
147 std::unique_ptr<Chunk> &C = P.second;
148 V.push_back(C.get());
149 }
150 return V;
151}
152
Rui Ueyamaa77336b2015-06-21 22:31:52 +0000153static std::map<StringRef, std::vector<DefinedImportData *>>
154binImports(const std::vector<DefinedImportData *> &Imports) {
Rui Ueyama4b22fa72015-06-07 01:15:04 +0000155 // Group DLL-imported symbols by DLL name because that's how
156 // symbols are layed out in the import descriptor table.
Rui Ueyamaa77336b2015-06-21 22:31:52 +0000157 std::map<StringRef, std::vector<DefinedImportData *>> M;
Rui Ueyama4b22fa72015-06-07 01:15:04 +0000158 for (DefinedImportData *Sym : Imports)
Rui Ueyamaa77336b2015-06-21 22:31:52 +0000159 M[Sym->getDLLName()].push_back(Sym);
160
161 for (auto &P : M) {
162 // Sort symbols by name for each group.
163 std::vector<DefinedImportData *> &Syms = P.second;
164 std::sort(Syms.begin(), Syms.end(),
165 [](DefinedImportData *A, DefinedImportData *B) {
166 return A->getName() < B->getName();
167 });
168 }
169 return M;
170}
171
172void IdataContents::create() {
173 std::map<StringRef, std::vector<DefinedImportData *>> Map =
174 binImports(Imports);
Rui Ueyama4b22fa72015-06-07 01:15:04 +0000175
176 // Create .idata contents for each DLL.
177 for (auto &P : Map) {
178 StringRef Name = P.first;
179 std::vector<DefinedImportData *> &Syms = P.second;
180
Rui Ueyama4b22fa72015-06-07 01:15:04 +0000181 // Create lookup and address tables. If they have external names,
182 // we need to create HintName chunks to store the names.
183 // If they don't (if they are import-by-ordinals), we store only
184 // ordinal values to the table.
185 size_t Base = Lookups.size();
186 for (DefinedImportData *S : Syms) {
187 uint16_t Ord = S->getOrdinal();
188 if (S->getExternalName().empty()) {
189 Lookups.push_back(make_unique<OrdinalOnlyChunk>(Ord));
190 Addresses.push_back(make_unique<OrdinalOnlyChunk>(Ord));
191 continue;
192 }
193 auto C = make_unique<HintNameChunk>(S->getExternalName(), Ord);
194 Lookups.push_back(make_unique<LookupChunk>(C.get()));
195 Addresses.push_back(make_unique<LookupChunk>(C.get()));
196 Hints.push_back(std::move(C));
197 }
198 // Terminate with null values.
Rui Ueyamac6b87362015-06-07 22:00:28 +0000199 Lookups.push_back(make_unique<NullChunk>(LookupChunkSize));
200 Addresses.push_back(make_unique<NullChunk>(LookupChunkSize));
Rui Ueyama4b22fa72015-06-07 01:15:04 +0000201
202 for (int I = 0, E = Syms.size(); I < E; ++I)
203 Syms[I]->setLocation(Addresses[Base + I].get());
204
205 // Create the import table header.
206 if (!DLLNames.count(Name))
207 DLLNames[Name] = make_unique<StringChunk>(Name);
Rui Ueyama97dff9e2015-06-17 00:16:33 +0000208 auto Dir = make_unique<ImportDirectoryChunk>(DLLNames[Name].get());
Rui Ueyama4b22fa72015-06-07 01:15:04 +0000209 Dir->LookupTab = Lookups[Base].get();
210 Dir->AddressTab = Addresses[Base].get();
211 Dirs.push_back(std::move(Dir));
212 }
213 // Add null terminator.
Rui Ueyama97dff9e2015-06-17 00:16:33 +0000214 Dirs.push_back(make_unique<NullChunk>(sizeof(ImportDirectoryTableEntry)));
215}
216
217// Export table
Rui Ueyamaa77336b2015-06-21 22:31:52 +0000218// See Microsoft PE/COFF spec 4.3 for details.
219
220// A chunk for the delay import descriptor table etnry.
221class DelayDirectoryChunk : public Chunk {
222public:
223 explicit DelayDirectoryChunk(Chunk *N) : DLLName(N) {}
224
225 size_t getSize() const override {
226 return sizeof(delay_import_directory_table_entry);
227 }
228
229 void writeTo(uint8_t *Buf) override {
230 auto *E = (delay_import_directory_table_entry *)(Buf + FileOff);
Rui Ueyama382dc962015-06-26 21:40:15 +0000231 E->Attributes = 1;
Rui Ueyamaa77336b2015-06-21 22:31:52 +0000232 E->Name = DLLName->getRVA();
233 E->ModuleHandle = ModuleHandle->getRVA();
234 E->DelayImportAddressTable = AddressTab->getRVA();
235 E->DelayImportNameTable = NameTab->getRVA();
236 }
237
238 Chunk *DLLName;
239 Chunk *ModuleHandle;
240 Chunk *AddressTab;
241 Chunk *NameTab;
242};
243
244// Initial contents for delay-loaded functions.
Rui Ueyama61096202015-06-22 17:26:27 +0000245// This code calls __delayLoadHelper2 function to resolve a symbol
Rui Ueyamaa77336b2015-06-21 22:31:52 +0000246// and then overwrites its jump table slot with the result
247// for subsequent function calls.
248static const uint8_t Thunk[] = {
249 0x51, // push rcx
250 0x52, // push rdx
251 0x41, 0x50, // push r8
252 0x41, 0x51, // push r9
253 0x48, 0x83, 0xEC, 0x48, // sub rsp, 48h
254 0x66, 0x0F, 0x7F, 0x04, 0x24, // movdqa xmmword ptr [rsp], xmm0
255 0x66, 0x0F, 0x7F, 0x4C, 0x24, 0x10, // movdqa xmmword ptr [rsp+10h], xmm1
256 0x66, 0x0F, 0x7F, 0x54, 0x24, 0x20, // movdqa xmmword ptr [rsp+20h], xmm2
257 0x66, 0x0F, 0x7F, 0x5C, 0x24, 0x30, // movdqa xmmword ptr [rsp+30h], xmm3
258 0x48, 0x8D, 0x15, 0, 0, 0, 0, // lea rdx, [__imp_<FUNCNAME>]
259 0x48, 0x8D, 0x0D, 0, 0, 0, 0, // lea rcx, [___DELAY_IMPORT_...]
260 0xE8, 0, 0, 0, 0, // call __delayLoadHelper2
261 0x66, 0x0F, 0x6F, 0x04, 0x24, // movdqa xmm0, xmmword ptr [rsp]
262 0x66, 0x0F, 0x6F, 0x4C, 0x24, 0x10, // movdqa xmm1, xmmword ptr [rsp+10h]
263 0x66, 0x0F, 0x6F, 0x54, 0x24, 0x20, // movdqa xmm2, xmmword ptr [rsp+20h]
264 0x66, 0x0F, 0x6F, 0x5C, 0x24, 0x30, // movdqa xmm3, xmmword ptr [rsp+30h]
265 0x48, 0x83, 0xC4, 0x48, // add rsp, 48h
266 0x41, 0x59, // pop r9
267 0x41, 0x58, // pop r8
268 0x5A, // pop rdx
269 0x59, // pop rcx
270 0xFF, 0xE0, // jmp rax
271};
272
273// A chunk for the delay import thunk.
274class ThunkChunk : public Chunk {
275public:
Rui Ueyama382dc962015-06-26 21:40:15 +0000276 ThunkChunk(Defined *I, Chunk *D, Defined *H) : Imp(I), Desc(D), Helper(H) {}
Rui Ueyamaa77336b2015-06-21 22:31:52 +0000277 size_t getSize() const override { return sizeof(Thunk); }
278
279 void writeTo(uint8_t *Buf) override {
280 memcpy(Buf + FileOff, Thunk, sizeof(Thunk));
Rui Ueyama382dc962015-06-26 21:40:15 +0000281 write32le(Buf + FileOff + 36, Imp->getRVA() - RVA - 40);
282 write32le(Buf + FileOff + 43, Desc->getRVA() - RVA - 47);
283 write32le(Buf + FileOff + 48, Helper->getRVA() - RVA - 52);
Rui Ueyamaa77336b2015-06-21 22:31:52 +0000284 }
285
286 Defined *Imp = nullptr;
287 Chunk *Desc = nullptr;
288 Defined *Helper = nullptr;
289};
290
Rui Ueyama382dc962015-06-26 21:40:15 +0000291std::vector<Chunk *> DelayLoadContents::getChunks() {
Rui Ueyamaa77336b2015-06-21 22:31:52 +0000292 std::vector<Chunk *> V;
293 for (std::unique_ptr<Chunk> &C : Dirs)
294 V.push_back(C.get());
Rui Ueyamaa77336b2015-06-21 22:31:52 +0000295 for (std::unique_ptr<Chunk> &C : Names)
296 V.push_back(C.get());
297 for (std::unique_ptr<Chunk> &C : HintNames)
298 V.push_back(C.get());
299 for (auto &P : DLLNames) {
300 std::unique_ptr<Chunk> &C = P.second;
301 V.push_back(C.get());
302 }
303 return V;
304}
305
Rui Ueyama382dc962015-06-26 21:40:15 +0000306std::vector<Chunk *> DelayLoadContents::getDataChunks() {
307 std::vector<Chunk *> V;
308 for (std::unique_ptr<Chunk> &C : ModuleHandles)
309 V.push_back(C.get());
310 for (std::unique_ptr<Chunk> &C : Addresses)
311 V.push_back(C.get());
312 return V;
313}
314
Rui Ueyamaa77336b2015-06-21 22:31:52 +0000315uint64_t DelayLoadContents::getDirSize() {
316 return Dirs.size() * sizeof(delay_import_directory_table_entry);
317}
318
Rui Ueyama382dc962015-06-26 21:40:15 +0000319// A chunk for the import descriptor table.
320class DelayAddressChunk : public Chunk {
321public:
322 explicit DelayAddressChunk(Chunk *C) : Thunk(C) {}
323 size_t getSize() const override { return 8; }
324
325 void writeTo(uint8_t *Buf) override {
326 write64le(Buf + FileOff, Thunk->getRVA() + Config->ImageBase);
327 }
328
Rui Ueyama810551a2015-06-26 22:05:32 +0000329 void getBaserels(std::vector<uint32_t> *Res, Defined *ImageBase) override {
330 Res->push_back(RVA);
331 }
332
Rui Ueyama382dc962015-06-26 21:40:15 +0000333 Chunk *Thunk;
334};
335
336void DelayLoadContents::create(Defined *H) {
337 Helper = H;
Rui Ueyamaa77336b2015-06-21 22:31:52 +0000338 std::map<StringRef, std::vector<DefinedImportData *>> Map =
339 binImports(Imports);
340
341 // Create .didat contents for each DLL.
342 for (auto &P : Map) {
343 StringRef Name = P.first;
344 std::vector<DefinedImportData *> &Syms = P.second;
345
Rui Ueyama382dc962015-06-26 21:40:15 +0000346 // Create the delay import table header.
347 if (!DLLNames.count(Name))
348 DLLNames[Name] = make_unique<StringChunk>(Name);
349 auto Dir = make_unique<DelayDirectoryChunk>(DLLNames[Name].get());
350
Rui Ueyamaa77336b2015-06-21 22:31:52 +0000351 size_t Base = Addresses.size();
352 for (DefinedImportData *S : Syms) {
Rui Ueyama382dc962015-06-26 21:40:15 +0000353 auto T = make_unique<ThunkChunk>(S, Dir.get(), Helper);
354 auto A = make_unique<DelayAddressChunk>(T.get());
Rui Ueyamaa77336b2015-06-21 22:31:52 +0000355 Addresses.push_back(std::move(A));
356 Thunks.push_back(std::move(T));
357 auto C =
358 make_unique<HintNameChunk>(S->getExternalName(), S->getOrdinal());
359 Names.push_back(make_unique<LookupChunk>(C.get()));
360 HintNames.push_back(std::move(C));
361 }
362 // Terminate with null values.
Rui Ueyama382dc962015-06-26 21:40:15 +0000363 Addresses.push_back(make_unique<NullChunk>(8));
364 Names.push_back(make_unique<NullChunk>(8));
Rui Ueyamaa77336b2015-06-21 22:31:52 +0000365
366 for (int I = 0, E = Syms.size(); I < E; ++I)
367 Syms[I]->setLocation(Addresses[Base + I].get());
368 auto *MH = new NullChunk(8);
369 MH->setAlign(8);
370 ModuleHandles.push_back(std::unique_ptr<Chunk>(MH));
371
Rui Ueyama382dc962015-06-26 21:40:15 +0000372 // Fill the delay import table header fields.
Rui Ueyamaa77336b2015-06-21 22:31:52 +0000373 Dir->ModuleHandle = MH;
374 Dir->AddressTab = Addresses[Base].get();
375 Dir->NameTab = Names[Base].get();
376 Dirs.push_back(std::move(Dir));
377 }
378 // Add null terminator.
379 Dirs.push_back(
380 make_unique<NullChunk>(sizeof(delay_import_directory_table_entry)));
381}
382
383// Export table
Rui Ueyama97dff9e2015-06-17 00:16:33 +0000384// Read Microsoft PE/COFF spec 5.3 for details.
385
386// A chunk for the export descriptor table.
387class ExportDirectoryChunk : public Chunk {
388public:
389 ExportDirectoryChunk(int I, int J, Chunk *D, Chunk *A, Chunk *N, Chunk *O)
390 : MaxOrdinal(I), NameTabSize(J), DLLName(D), AddressTab(A), NameTab(N),
391 OrdinalTab(O) {}
392
393 size_t getSize() const override {
394 return sizeof(export_directory_table_entry);
395 }
396
397 void writeTo(uint8_t *Buf) override {
398 auto *E = (export_directory_table_entry *)(Buf + FileOff);
399 E->NameRVA = DLLName->getRVA();
400 E->OrdinalBase = 0;
401 E->AddressTableEntries = MaxOrdinal + 1;
402 E->NumberOfNamePointers = NameTabSize;
403 E->ExportAddressTableRVA = AddressTab->getRVA();
404 E->NamePointerRVA = NameTab->getRVA();
405 E->OrdinalTableRVA = OrdinalTab->getRVA();
406 }
407
408 uint16_t MaxOrdinal;
409 uint16_t NameTabSize;
410 Chunk *DLLName;
411 Chunk *AddressTab;
412 Chunk *NameTab;
413 Chunk *OrdinalTab;
414};
415
416class AddressTableChunk : public Chunk {
417public:
418 explicit AddressTableChunk(size_t MaxOrdinal) : Size(MaxOrdinal + 1) {}
419 size_t getSize() const override { return Size * 4; }
420
421 void writeTo(uint8_t *Buf) override {
Rui Ueyamaf5313b32015-06-28 22:16:41 +0000422 for (Export &E : Config->Exports) {
Rui Ueyama6bf638e2015-07-02 00:04:14 +0000423 auto *D = cast<Defined>(E.Sym->getReplacement());
Rui Ueyamaf5313b32015-06-28 22:16:41 +0000424 write32le(Buf + FileOff + E.Ordinal * 4, D->getRVA());
425 }
Rui Ueyama97dff9e2015-06-17 00:16:33 +0000426 }
427
428private:
429 size_t Size;
430};
431
432class NamePointersChunk : public Chunk {
433public:
434 explicit NamePointersChunk(std::vector<Chunk *> &V) : Chunks(V) {}
435 size_t getSize() const override { return Chunks.size() * 4; }
436
437 void writeTo(uint8_t *Buf) override {
438 uint8_t *P = Buf + FileOff;
439 for (Chunk *C : Chunks) {
440 write32le(P, C->getRVA());
441 P += 4;
442 }
443 }
444
445private:
446 std::vector<Chunk *> Chunks;
447};
448
449class ExportOrdinalChunk : public Chunk {
450public:
451 explicit ExportOrdinalChunk(size_t I) : Size(I) {}
452 size_t getSize() const override { return Size * 2; }
453
454 void writeTo(uint8_t *Buf) override {
455 uint8_t *P = Buf + FileOff;
456 for (Export &E : Config->Exports) {
457 if (E.Noname)
458 continue;
459 write16le(P, E.Ordinal);
460 P += 2;
461 }
462 }
463
464private:
465 size_t Size;
466};
467
468EdataContents::EdataContents() {
469 uint16_t MaxOrdinal = 0;
470 for (Export &E : Config->Exports)
471 MaxOrdinal = std::max(MaxOrdinal, E.Ordinal);
472
473 auto *DLLName = new StringChunk(sys::path::filename(Config->OutputFile));
474 auto *AddressTab = new AddressTableChunk(MaxOrdinal);
475 std::vector<Chunk *> Names;
476 for (Export &E : Config->Exports)
477 if (!E.Noname)
478 Names.push_back(new StringChunk(E.ExtName));
479 auto *NameTab = new NamePointersChunk(Names);
480 auto *OrdinalTab = new ExportOrdinalChunk(Names.size());
481 auto *Dir = new ExportDirectoryChunk(MaxOrdinal, Names.size(), DLLName,
482 AddressTab, NameTab, OrdinalTab);
483 Chunks.push_back(std::unique_ptr<Chunk>(Dir));
484 Chunks.push_back(std::unique_ptr<Chunk>(DLLName));
485 Chunks.push_back(std::unique_ptr<Chunk>(AddressTab));
486 Chunks.push_back(std::unique_ptr<Chunk>(NameTab));
487 Chunks.push_back(std::unique_ptr<Chunk>(OrdinalTab));
488 for (Chunk *C : Names)
489 Chunks.push_back(std::unique_ptr<Chunk>(C));
Rui Ueyama4b22fa72015-06-07 01:15:04 +0000490}
491
492} // namespace coff
493} // namespace lld