1 //===- DLL.cpp ------------------------------------------------------------===//
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
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.
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.
19 //===----------------------------------------------------------------------===//
23 #include "llvm/Object/COFF.h"
24 #include "llvm/Support/Endian.h"
25 #include "llvm/Support/Path.h"
28 using namespace llvm::object;
29 using namespace llvm::support::endian;
30 using namespace llvm::COFF;
38 static int ptrSize() { return Config->is64() ? 8 : 4; }
40 // A chunk for the import descriptor table.
41 class HintNameChunk : public Chunk {
43 HintNameChunk(StringRef N, uint16_t H) : Name(N), Hint(H) {}
45 size_t getSize() const override {
46 // Starts with 2 byte Hint field, followed by a null-terminated string,
47 // ends with 0 or 1 byte padding.
48 return alignTo(Name.size() + 3, 2);
51 void writeTo(uint8_t *Buf) const override {
52 write16le(Buf + OutputSectionOff, Hint);
53 memcpy(Buf + OutputSectionOff + 2, Name.data(), Name.size());
61 // A chunk for the import descriptor table.
62 class LookupChunk : public Chunk {
64 explicit LookupChunk(Chunk *C) : HintName(C) { Alignment = ptrSize(); }
65 size_t getSize() const override { return ptrSize(); }
67 void writeTo(uint8_t *Buf) const override {
68 write32le(Buf + OutputSectionOff, HintName->getRVA());
74 // A chunk for the import descriptor table.
75 // This chunk represent import-by-ordinal symbols.
76 // See Microsoft PE/COFF spec 7.1. Import Header for details.
77 class OrdinalOnlyChunk : public Chunk {
79 explicit OrdinalOnlyChunk(uint16_t V) : Ordinal(V) { Alignment = ptrSize(); }
80 size_t getSize() const override { return ptrSize(); }
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).
86 write64le(Buf + OutputSectionOff, (1ULL << 63) | Ordinal);
88 write32le(Buf + OutputSectionOff, (1ULL << 31) | Ordinal);
95 // A chunk for the import descriptor table.
96 class ImportDirectoryChunk : public Chunk {
98 explicit ImportDirectoryChunk(Chunk *N) : DLLName(N) {}
99 size_t getSize() const override { return sizeof(ImportDirectoryTableEntry); }
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();
113 // A chunk representing null terminator in the import table.
114 // Contents of this chunk is always null bytes.
115 class NullChunk : public Chunk {
117 explicit NullChunk(size_t N) : Size(N) {}
118 bool hasData() const override { return false; }
119 size_t getSize() const override { return Size; }
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];
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);
137 std::vector<std::vector<DefinedImportData *>> V;
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();
145 V.push_back(std::move(Syms));
151 // See Microsoft PE/COFF spec 4.3 for details.
153 // A chunk for the delay import descriptor table etnry.
154 class DelayDirectoryChunk : public Chunk {
156 explicit DelayDirectoryChunk(Chunk *N) : DLLName(N) {}
158 size_t getSize() const override {
159 return sizeof(delay_import_directory_table_entry);
162 void writeTo(uint8_t *Buf) const override {
163 auto *E = (delay_import_directory_table_entry *)(Buf + OutputSectionOff);
165 E->Name = DLLName->getRVA();
166 E->ModuleHandle = ModuleHandle->getRVA();
167 E->DelayImportAddressTable = AddressTab->getRVA();
168 E->DelayImportNameTable = NameTab->getRVA();
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[] = {
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
203 0xFF, 0xE0, // jmp rax
206 static const uint8_t ThunkX86[] = {
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
214 0xFF, 0xE0, // jmp eax
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}
233 // A chunk for the delay import thunk.
234 class ThunkChunkX64 : public Chunk {
236 ThunkChunkX64(Defined *I, Chunk *D, Defined *H)
237 : Imp(I), Desc(D), Helper(H) {}
239 size_t getSize() const override { return sizeof(ThunkX64); }
241 void writeTo(uint8_t *Buf) const override {
242 memcpy(Buf + OutputSectionOff, ThunkX64, sizeof(ThunkX64));
243 write32le(Buf + OutputSectionOff + 36, Imp->getRVA() - RVA - 40);
244 write32le(Buf + OutputSectionOff + 43, Desc->getRVA() - RVA - 47);
245 write32le(Buf + OutputSectionOff + 48, Helper->getRVA() - RVA - 52);
248 Defined *Imp = nullptr;
249 Chunk *Desc = nullptr;
250 Defined *Helper = nullptr;
253 class ThunkChunkX86 : public Chunk {
255 ThunkChunkX86(Defined *I, Chunk *D, Defined *H)
256 : Imp(I), Desc(D), Helper(H) {}
258 size_t getSize() const override { return sizeof(ThunkX86); }
260 void writeTo(uint8_t *Buf) const override {
261 memcpy(Buf + OutputSectionOff, ThunkX86, sizeof(ThunkX86));
262 write32le(Buf + OutputSectionOff + 3, Imp->getRVA() + Config->ImageBase);
263 write32le(Buf + OutputSectionOff + 8, Desc->getRVA() + Config->ImageBase);
264 write32le(Buf + OutputSectionOff + 13, Helper->getRVA() - RVA - 17);
267 void getBaserels(std::vector<Baserel> *Res) override {
268 Res->emplace_back(RVA + 3);
269 Res->emplace_back(RVA + 8);
272 Defined *Imp = nullptr;
273 Chunk *Desc = nullptr;
274 Defined *Helper = nullptr;
277 class ThunkChunkARM : public Chunk {
279 ThunkChunkARM(Defined *I, Chunk *D, Defined *H)
280 : Imp(I), Desc(D), Helper(H) {}
282 size_t getSize() const override { return sizeof(ThunkARM); }
284 void writeTo(uint8_t *Buf) const override {
285 memcpy(Buf + OutputSectionOff, ThunkARM, sizeof(ThunkARM));
286 applyMOV32T(Buf + OutputSectionOff + 0, Imp->getRVA() + Config->ImageBase);
287 applyMOV32T(Buf + OutputSectionOff + 22, Desc->getRVA() + Config->ImageBase);
288 applyBranch24T(Buf + OutputSectionOff + 30, Helper->getRVA() - RVA - 34);
291 void getBaserels(std::vector<Baserel> *Res) override {
292 Res->emplace_back(RVA + 0, IMAGE_REL_BASED_ARM_MOV32T);
293 Res->emplace_back(RVA + 22, IMAGE_REL_BASED_ARM_MOV32T);
296 Defined *Imp = nullptr;
297 Chunk *Desc = nullptr;
298 Defined *Helper = nullptr;
301 // A chunk for the import descriptor table.
302 class DelayAddressChunk : public Chunk {
304 explicit DelayAddressChunk(Chunk *C) : Thunk(C) { Alignment = ptrSize(); }
305 size_t getSize() const override { return ptrSize(); }
307 void writeTo(uint8_t *Buf) const override {
308 if (Config->is64()) {
309 write64le(Buf + OutputSectionOff, Thunk->getRVA() + Config->ImageBase);
312 // Pointer to thumb code must have the LSB set, so adjust it.
313 if (Config->Machine == ARMNT)
315 write32le(Buf + OutputSectionOff, (Thunk->getRVA() + Config->ImageBase) | Bit);
319 void getBaserels(std::vector<Baserel> *Res) override {
320 Res->emplace_back(RVA);
327 // Read Microsoft PE/COFF spec 5.3 for details.
329 // A chunk for the export descriptor table.
330 class ExportDirectoryChunk : public Chunk {
332 ExportDirectoryChunk(int I, int J, Chunk *D, Chunk *A, Chunk *N, Chunk *O)
333 : MaxOrdinal(I), NameTabSize(J), DLLName(D), AddressTab(A), NameTab(N),
336 size_t getSize() const override {
337 return sizeof(export_directory_table_entry);
340 void writeTo(uint8_t *Buf) const override {
341 auto *E = (export_directory_table_entry *)(Buf + OutputSectionOff);
342 E->NameRVA = DLLName->getRVA();
344 E->AddressTableEntries = MaxOrdinal + 1;
345 E->NumberOfNamePointers = NameTabSize;
346 E->ExportAddressTableRVA = AddressTab->getRVA();
347 E->NamePointerRVA = NameTab->getRVA();
348 E->OrdinalTableRVA = OrdinalTab->getRVA();
352 uint16_t NameTabSize;
359 class AddressTableChunk : public Chunk {
361 explicit AddressTableChunk(size_t MaxOrdinal) : Size(MaxOrdinal + 1) {}
362 size_t getSize() const override { return Size * 4; }
364 void writeTo(uint8_t *Buf) const override {
365 for (const Export &E : Config->Exports) {
366 uint8_t *P = Buf + OutputSectionOff + E.Ordinal * 4;
368 // Pointer to thumb code must have the LSB set, so adjust it.
369 if (Config->Machine == ARMNT && !E.Data)
371 if (E.ForwardChunk) {
372 write32le(P, E.ForwardChunk->getRVA() | Bit);
374 write32le(P, cast<Defined>(E.Sym)->getRVA() | Bit);
383 class NamePointersChunk : public Chunk {
385 explicit NamePointersChunk(std::vector<Chunk *> &V) : Chunks(V) {}
386 size_t getSize() const override { return Chunks.size() * 4; }
388 void writeTo(uint8_t *Buf) const override {
389 uint8_t *P = Buf + OutputSectionOff;
390 for (Chunk *C : Chunks) {
391 write32le(P, C->getRVA());
397 std::vector<Chunk *> Chunks;
400 class ExportOrdinalChunk : public Chunk {
402 explicit ExportOrdinalChunk(size_t I) : Size(I) {}
403 size_t getSize() const override { return Size * 2; }
405 void writeTo(uint8_t *Buf) const override {
406 uint8_t *P = Buf + OutputSectionOff;
407 for (Export &E : Config->Exports) {
410 write16le(P, E.Ordinal);
419 } // anonymous namespace
421 uint64_t IdataContents::getDirSize() {
422 return Dirs.size() * sizeof(ImportDirectoryTableEntry);
425 uint64_t IdataContents::getIATSize() {
426 return Addresses.size() * ptrSize();
429 // Returns a list of .idata contents.
430 // See Microsoft PE/COFF spec 5.4 for details.
431 std::vector<Chunk *> IdataContents::getChunks() {
434 // The loader assumes a specific order of data.
435 // Add each type in the correct order.
436 std::vector<Chunk *> V;
437 V.insert(V.end(), Dirs.begin(), Dirs.end());
438 V.insert(V.end(), Lookups.begin(), Lookups.end());
439 V.insert(V.end(), Addresses.begin(), Addresses.end());
440 V.insert(V.end(), Hints.begin(), Hints.end());
441 V.insert(V.end(), DLLNames.begin(), DLLNames.end());
445 void IdataContents::create() {
446 std::vector<std::vector<DefinedImportData *>> V = binImports(Imports);
448 // Create .idata contents for each DLL.
449 for (std::vector<DefinedImportData *> &Syms : V) {
450 // Create lookup and address tables. If they have external names,
451 // we need to create HintName chunks to store the names.
452 // If they don't (if they are import-by-ordinals), we store only
453 // ordinal values to the table.
454 size_t Base = Lookups.size();
455 for (DefinedImportData *S : Syms) {
456 uint16_t Ord = S->getOrdinal();
457 if (S->getExternalName().empty()) {
458 Lookups.push_back(make<OrdinalOnlyChunk>(Ord));
459 Addresses.push_back(make<OrdinalOnlyChunk>(Ord));
462 auto *C = make<HintNameChunk>(S->getExternalName(), Ord);
463 Lookups.push_back(make<LookupChunk>(C));
464 Addresses.push_back(make<LookupChunk>(C));
467 // Terminate with null values.
468 Lookups.push_back(make<NullChunk>(ptrSize()));
469 Addresses.push_back(make<NullChunk>(ptrSize()));
471 for (int I = 0, E = Syms.size(); I < E; ++I)
472 Syms[I]->setLocation(Addresses[Base + I]);
474 // Create the import table header.
475 DLLNames.push_back(make<StringChunk>(Syms[0]->getDLLName()));
476 auto *Dir = make<ImportDirectoryChunk>(DLLNames.back());
477 Dir->LookupTab = Lookups[Base];
478 Dir->AddressTab = Addresses[Base];
481 // Add null terminator.
482 Dirs.push_back(make<NullChunk>(sizeof(ImportDirectoryTableEntry)));
485 std::vector<Chunk *> DelayLoadContents::getChunks() {
486 std::vector<Chunk *> V;
487 V.insert(V.end(), Dirs.begin(), Dirs.end());
488 V.insert(V.end(), Names.begin(), Names.end());
489 V.insert(V.end(), HintNames.begin(), HintNames.end());
490 V.insert(V.end(), DLLNames.begin(), DLLNames.end());
494 std::vector<Chunk *> DelayLoadContents::getDataChunks() {
495 std::vector<Chunk *> V;
496 V.insert(V.end(), ModuleHandles.begin(), ModuleHandles.end());
497 V.insert(V.end(), Addresses.begin(), Addresses.end());
501 uint64_t DelayLoadContents::getDirSize() {
502 return Dirs.size() * sizeof(delay_import_directory_table_entry);
505 void DelayLoadContents::create(Defined *H) {
507 std::vector<std::vector<DefinedImportData *>> V = binImports(Imports);
509 // Create .didat contents for each DLL.
510 for (std::vector<DefinedImportData *> &Syms : V) {
511 // Create the delay import table header.
512 DLLNames.push_back(make<StringChunk>(Syms[0]->getDLLName()));
513 auto *Dir = make<DelayDirectoryChunk>(DLLNames.back());
515 size_t Base = Addresses.size();
516 for (DefinedImportData *S : Syms) {
517 Chunk *T = newThunkChunk(S, Dir);
518 auto *A = make<DelayAddressChunk>(T);
519 Addresses.push_back(A);
521 StringRef ExtName = S->getExternalName();
522 if (ExtName.empty()) {
523 Names.push_back(make<OrdinalOnlyChunk>(S->getOrdinal()));
525 auto *C = make<HintNameChunk>(ExtName, 0);
526 Names.push_back(make<LookupChunk>(C));
527 HintNames.push_back(C);
530 // Terminate with null values.
531 Addresses.push_back(make<NullChunk>(8));
532 Names.push_back(make<NullChunk>(8));
534 for (int I = 0, E = Syms.size(); I < E; ++I)
535 Syms[I]->setLocation(Addresses[Base + I]);
536 auto *MH = make<NullChunk>(8);
538 ModuleHandles.push_back(MH);
540 // Fill the delay import table header fields.
541 Dir->ModuleHandle = MH;
542 Dir->AddressTab = Addresses[Base];
543 Dir->NameTab = Names[Base];
546 // Add null terminator.
547 Dirs.push_back(make<NullChunk>(sizeof(delay_import_directory_table_entry)));
550 Chunk *DelayLoadContents::newThunkChunk(DefinedImportData *S, Chunk *Dir) {
551 switch (Config->Machine) {
553 return make<ThunkChunkX64>(S, Dir, Helper);
555 return make<ThunkChunkX86>(S, Dir, Helper);
557 return make<ThunkChunkARM>(S, Dir, Helper);
559 llvm_unreachable("unsupported machine type");
563 EdataContents::EdataContents() {
564 uint16_t MaxOrdinal = 0;
565 for (Export &E : Config->Exports)
566 MaxOrdinal = std::max(MaxOrdinal, E.Ordinal);
568 auto *DLLName = make<StringChunk>(sys::path::filename(Config->OutputFile));
569 auto *AddressTab = make<AddressTableChunk>(MaxOrdinal);
570 std::vector<Chunk *> Names;
571 for (Export &E : Config->Exports)
573 Names.push_back(make<StringChunk>(E.ExportName));
575 std::vector<Chunk *> Forwards;
576 for (Export &E : Config->Exports) {
577 if (E.ForwardTo.empty())
579 E.ForwardChunk = make<StringChunk>(E.ForwardTo);
580 Forwards.push_back(E.ForwardChunk);
583 auto *NameTab = make<NamePointersChunk>(Names);
584 auto *OrdinalTab = make<ExportOrdinalChunk>(Names.size());
585 auto *Dir = make<ExportDirectoryChunk>(MaxOrdinal, Names.size(), DLLName,
586 AddressTab, NameTab, OrdinalTab);
587 Chunks.push_back(Dir);
588 Chunks.push_back(DLLName);
589 Chunks.push_back(AddressTab);
590 Chunks.push_back(NameTab);
591 Chunks.push_back(OrdinalTab);
592 Chunks.insert(Chunks.end(), Names.begin(), Names.end());
593 Chunks.insert(Chunks.end(), Forwards.begin(), Forwards.end());