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) {}
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) {}
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; }
120 void setAlign(size_t N) { Align = N; }
126 static std::vector<std::vector<DefinedImportData *>>
127 binImports(const std::vector<DefinedImportData *> &Imports) {
128 // Group DLL-imported symbols by DLL name because that's how
129 // symbols are layed out in the import descriptor table.
130 auto Less = [](const std::string &A, const std::string &B) {
131 return Config->DLLOrder[A] < Config->DLLOrder[B];
133 std::map<std::string, std::vector<DefinedImportData *>,
134 bool(*)(const std::string &, const std::string &)> M(Less);
135 for (DefinedImportData *Sym : Imports)
136 M[Sym->getDLLName().lower()].push_back(Sym);
138 std::vector<std::vector<DefinedImportData *>> V;
140 // Sort symbols by name for each group.
141 std::vector<DefinedImportData *> &Syms = P.second;
142 std::sort(Syms.begin(), Syms.end(),
143 [](DefinedImportData *A, DefinedImportData *B) {
144 return A->getName() < B->getName();
146 V.push_back(std::move(Syms));
152 // See Microsoft PE/COFF spec 4.3 for details.
154 // A chunk for the delay import descriptor table etnry.
155 class DelayDirectoryChunk : public Chunk {
157 explicit DelayDirectoryChunk(Chunk *N) : DLLName(N) {}
159 size_t getSize() const override {
160 return sizeof(delay_import_directory_table_entry);
163 void writeTo(uint8_t *Buf) const override {
164 auto *E = (delay_import_directory_table_entry *)(Buf + OutputSectionOff);
166 E->Name = DLLName->getRVA();
167 E->ModuleHandle = ModuleHandle->getRVA();
168 E->DelayImportAddressTable = AddressTab->getRVA();
169 E->DelayImportNameTable = NameTab->getRVA();
178 // Initial contents for delay-loaded functions.
179 // This code calls __delayLoadHelper2 function to resolve a symbol
180 // and then overwrites its jump table slot with the result
181 // for subsequent function calls.
182 static const uint8_t ThunkX64[] = {
185 0x41, 0x50, // push r8
186 0x41, 0x51, // push r9
187 0x48, 0x83, 0xEC, 0x48, // sub rsp, 48h
188 0x66, 0x0F, 0x7F, 0x04, 0x24, // movdqa xmmword ptr [rsp], xmm0
189 0x66, 0x0F, 0x7F, 0x4C, 0x24, 0x10, // movdqa xmmword ptr [rsp+10h], xmm1
190 0x66, 0x0F, 0x7F, 0x54, 0x24, 0x20, // movdqa xmmword ptr [rsp+20h], xmm2
191 0x66, 0x0F, 0x7F, 0x5C, 0x24, 0x30, // movdqa xmmword ptr [rsp+30h], xmm3
192 0x48, 0x8D, 0x15, 0, 0, 0, 0, // lea rdx, [__imp_<FUNCNAME>]
193 0x48, 0x8D, 0x0D, 0, 0, 0, 0, // lea rcx, [___DELAY_IMPORT_...]
194 0xE8, 0, 0, 0, 0, // call __delayLoadHelper2
195 0x66, 0x0F, 0x6F, 0x04, 0x24, // movdqa xmm0, xmmword ptr [rsp]
196 0x66, 0x0F, 0x6F, 0x4C, 0x24, 0x10, // movdqa xmm1, xmmword ptr [rsp+10h]
197 0x66, 0x0F, 0x6F, 0x54, 0x24, 0x20, // movdqa xmm2, xmmword ptr [rsp+20h]
198 0x66, 0x0F, 0x6F, 0x5C, 0x24, 0x30, // movdqa xmm3, xmmword ptr [rsp+30h]
199 0x48, 0x83, 0xC4, 0x48, // add rsp, 48h
200 0x41, 0x59, // pop r9
201 0x41, 0x58, // pop r8
204 0xFF, 0xE0, // jmp rax
207 static const uint8_t ThunkX86[] = {
210 0x68, 0, 0, 0, 0, // push offset ___imp__<FUNCNAME>
211 0x68, 0, 0, 0, 0, // push offset ___DELAY_IMPORT_DESCRIPTOR_<DLLNAME>_dll
212 0xE8, 0, 0, 0, 0, // call ___delayLoadHelper2@8
215 0xFF, 0xE0, // jmp eax
218 // A chunk for the delay import thunk.
219 class ThunkChunkX64 : public Chunk {
221 ThunkChunkX64(Defined *I, Chunk *D, Defined *H)
222 : Imp(I), Desc(D), Helper(H) {}
224 size_t getSize() const override { return sizeof(ThunkX64); }
226 void writeTo(uint8_t *Buf) const override {
227 memcpy(Buf + OutputSectionOff, ThunkX64, sizeof(ThunkX64));
228 write32le(Buf + OutputSectionOff + 36, Imp->getRVA() - RVA - 40);
229 write32le(Buf + OutputSectionOff + 43, Desc->getRVA() - RVA - 47);
230 write32le(Buf + OutputSectionOff + 48, Helper->getRVA() - RVA - 52);
233 Defined *Imp = nullptr;
234 Chunk *Desc = nullptr;
235 Defined *Helper = nullptr;
238 class ThunkChunkX86 : public Chunk {
240 ThunkChunkX86(Defined *I, Chunk *D, Defined *H)
241 : Imp(I), Desc(D), Helper(H) {}
243 size_t getSize() const override { return sizeof(ThunkX86); }
245 void writeTo(uint8_t *Buf) const override {
246 memcpy(Buf + OutputSectionOff, ThunkX86, sizeof(ThunkX86));
247 write32le(Buf + OutputSectionOff + 3, Imp->getRVA() + Config->ImageBase);
248 write32le(Buf + OutputSectionOff + 8, Desc->getRVA() + Config->ImageBase);
249 write32le(Buf + OutputSectionOff + 13, Helper->getRVA() - RVA - 17);
252 void getBaserels(std::vector<Baserel> *Res) override {
253 Res->emplace_back(RVA + 3);
254 Res->emplace_back(RVA + 8);
257 Defined *Imp = nullptr;
258 Chunk *Desc = nullptr;
259 Defined *Helper = nullptr;
262 // A chunk for the import descriptor table.
263 class DelayAddressChunk : public Chunk {
265 explicit DelayAddressChunk(Chunk *C) : Thunk(C) {}
266 size_t getSize() const override { return ptrSize(); }
268 void writeTo(uint8_t *Buf) const override {
269 if (Config->is64()) {
270 write64le(Buf + OutputSectionOff, Thunk->getRVA() + Config->ImageBase);
272 write32le(Buf + OutputSectionOff, Thunk->getRVA() + Config->ImageBase);
276 void getBaserels(std::vector<Baserel> *Res) override {
277 Res->emplace_back(RVA);
284 // Read Microsoft PE/COFF spec 5.3 for details.
286 // A chunk for the export descriptor table.
287 class ExportDirectoryChunk : public Chunk {
289 ExportDirectoryChunk(int I, int J, Chunk *D, Chunk *A, Chunk *N, Chunk *O)
290 : MaxOrdinal(I), NameTabSize(J), DLLName(D), AddressTab(A), NameTab(N),
293 size_t getSize() const override {
294 return sizeof(export_directory_table_entry);
297 void writeTo(uint8_t *Buf) const override {
298 auto *E = (export_directory_table_entry *)(Buf + OutputSectionOff);
299 E->NameRVA = DLLName->getRVA();
301 E->AddressTableEntries = MaxOrdinal + 1;
302 E->NumberOfNamePointers = NameTabSize;
303 E->ExportAddressTableRVA = AddressTab->getRVA();
304 E->NamePointerRVA = NameTab->getRVA();
305 E->OrdinalTableRVA = OrdinalTab->getRVA();
309 uint16_t NameTabSize;
316 class AddressTableChunk : public Chunk {
318 explicit AddressTableChunk(size_t MaxOrdinal) : Size(MaxOrdinal + 1) {}
319 size_t getSize() const override { return Size * 4; }
321 void writeTo(uint8_t *Buf) const override {
322 for (Export &E : Config->Exports) {
323 uint8_t *P = Buf + OutputSectionOff + E.Ordinal * 4;
324 if (E.ForwardChunk) {
325 write32le(P, E.ForwardChunk->getRVA());
327 write32le(P, cast<Defined>(E.Sym)->getRVA());
336 class NamePointersChunk : public Chunk {
338 explicit NamePointersChunk(std::vector<Chunk *> &V) : Chunks(V) {}
339 size_t getSize() const override { return Chunks.size() * 4; }
341 void writeTo(uint8_t *Buf) const override {
342 uint8_t *P = Buf + OutputSectionOff;
343 for (Chunk *C : Chunks) {
344 write32le(P, C->getRVA());
350 std::vector<Chunk *> Chunks;
353 class ExportOrdinalChunk : public Chunk {
355 explicit ExportOrdinalChunk(size_t I) : Size(I) {}
356 size_t getSize() const override { return Size * 2; }
358 void writeTo(uint8_t *Buf) const override {
359 uint8_t *P = Buf + OutputSectionOff;
360 for (Export &E : Config->Exports) {
363 write16le(P, E.Ordinal);
372 } // anonymous namespace
374 uint64_t IdataContents::getDirSize() {
375 return Dirs.size() * sizeof(ImportDirectoryTableEntry);
378 uint64_t IdataContents::getIATSize() {
379 return Addresses.size() * ptrSize();
382 // Returns a list of .idata contents.
383 // See Microsoft PE/COFF spec 5.4 for details.
384 std::vector<Chunk *> IdataContents::getChunks() {
386 std::vector<Chunk *> V;
387 // The loader assumes a specific order of data.
388 // Add each type in the correct order.
389 for (std::unique_ptr<Chunk> &C : Dirs)
390 V.push_back(C.get());
391 for (std::unique_ptr<Chunk> &C : Lookups)
392 V.push_back(C.get());
393 for (std::unique_ptr<Chunk> &C : Addresses)
394 V.push_back(C.get());
395 for (std::unique_ptr<Chunk> &C : Hints)
396 V.push_back(C.get());
397 for (auto &P : DLLNames) {
398 std::unique_ptr<Chunk> &C = P.second;
399 V.push_back(C.get());
404 void IdataContents::create() {
405 std::vector<std::vector<DefinedImportData *>> V = binImports(Imports);
407 // Create .idata contents for each DLL.
408 for (std::vector<DefinedImportData *> &Syms : V) {
409 StringRef Name = Syms[0]->getDLLName();
411 // Create lookup and address tables. If they have external names,
412 // we need to create HintName chunks to store the names.
413 // If they don't (if they are import-by-ordinals), we store only
414 // ordinal values to the table.
415 size_t Base = Lookups.size();
416 for (DefinedImportData *S : Syms) {
417 uint16_t Ord = S->getOrdinal();
418 if (S->getExternalName().empty()) {
419 Lookups.push_back(make_unique<OrdinalOnlyChunk>(Ord));
420 Addresses.push_back(make_unique<OrdinalOnlyChunk>(Ord));
423 auto C = make_unique<HintNameChunk>(S->getExternalName(), Ord);
424 Lookups.push_back(make_unique<LookupChunk>(C.get()));
425 Addresses.push_back(make_unique<LookupChunk>(C.get()));
426 Hints.push_back(std::move(C));
428 // Terminate with null values.
429 Lookups.push_back(make_unique<NullChunk>(ptrSize()));
430 Addresses.push_back(make_unique<NullChunk>(ptrSize()));
432 for (int I = 0, E = Syms.size(); I < E; ++I)
433 Syms[I]->setLocation(Addresses[Base + I].get());
435 // Create the import table header.
436 if (!DLLNames.count(Name))
437 DLLNames[Name] = make_unique<StringChunk>(Name);
438 auto Dir = make_unique<ImportDirectoryChunk>(DLLNames[Name].get());
439 Dir->LookupTab = Lookups[Base].get();
440 Dir->AddressTab = Addresses[Base].get();
441 Dirs.push_back(std::move(Dir));
443 // Add null terminator.
444 Dirs.push_back(make_unique<NullChunk>(sizeof(ImportDirectoryTableEntry)));
447 std::vector<Chunk *> DelayLoadContents::getChunks() {
448 std::vector<Chunk *> V;
449 for (std::unique_ptr<Chunk> &C : Dirs)
450 V.push_back(C.get());
451 for (std::unique_ptr<Chunk> &C : Names)
452 V.push_back(C.get());
453 for (std::unique_ptr<Chunk> &C : HintNames)
454 V.push_back(C.get());
455 for (auto &P : DLLNames) {
456 std::unique_ptr<Chunk> &C = P.second;
457 V.push_back(C.get());
462 std::vector<Chunk *> DelayLoadContents::getDataChunks() {
463 std::vector<Chunk *> V;
464 for (std::unique_ptr<Chunk> &C : ModuleHandles)
465 V.push_back(C.get());
466 for (std::unique_ptr<Chunk> &C : Addresses)
467 V.push_back(C.get());
471 uint64_t DelayLoadContents::getDirSize() {
472 return Dirs.size() * sizeof(delay_import_directory_table_entry);
475 void DelayLoadContents::create(Defined *H) {
477 std::vector<std::vector<DefinedImportData *>> V = binImports(Imports);
479 // Create .didat contents for each DLL.
480 for (std::vector<DefinedImportData *> &Syms : V) {
481 StringRef Name = Syms[0]->getDLLName();
483 // Create the delay import table header.
484 if (!DLLNames.count(Name))
485 DLLNames[Name] = make_unique<StringChunk>(Name);
486 auto Dir = make_unique<DelayDirectoryChunk>(DLLNames[Name].get());
488 size_t Base = Addresses.size();
489 for (DefinedImportData *S : Syms) {
490 Chunk *T = newThunkChunk(S, Dir.get());
491 auto A = make_unique<DelayAddressChunk>(T);
492 Addresses.push_back(std::move(A));
493 Thunks.push_back(std::unique_ptr<Chunk>(T));
494 StringRef ExtName = S->getExternalName();
495 if (ExtName.empty()) {
496 Names.push_back(make_unique<OrdinalOnlyChunk>(S->getOrdinal()));
498 auto C = make_unique<HintNameChunk>(ExtName, 0);
499 Names.push_back(make_unique<LookupChunk>(C.get()));
500 HintNames.push_back(std::move(C));
503 // Terminate with null values.
504 Addresses.push_back(make_unique<NullChunk>(8));
505 Names.push_back(make_unique<NullChunk>(8));
507 for (int I = 0, E = Syms.size(); I < E; ++I)
508 Syms[I]->setLocation(Addresses[Base + I].get());
509 auto *MH = new NullChunk(8);
511 ModuleHandles.push_back(std::unique_ptr<Chunk>(MH));
513 // Fill the delay import table header fields.
514 Dir->ModuleHandle = MH;
515 Dir->AddressTab = Addresses[Base].get();
516 Dir->NameTab = Names[Base].get();
517 Dirs.push_back(std::move(Dir));
519 // Add null terminator.
521 make_unique<NullChunk>(sizeof(delay_import_directory_table_entry)));
524 Chunk *DelayLoadContents::newThunkChunk(DefinedImportData *S, Chunk *Dir) {
525 switch (Config->Machine) {
527 return new ThunkChunkX64(S, Dir, Helper);
529 return new ThunkChunkX86(S, Dir, Helper);
531 llvm_unreachable("unsupported machine type");
535 EdataContents::EdataContents() {
536 uint16_t MaxOrdinal = 0;
537 for (Export &E : Config->Exports)
538 MaxOrdinal = std::max(MaxOrdinal, E.Ordinal);
540 auto *DLLName = new StringChunk(sys::path::filename(Config->OutputFile));
541 auto *AddressTab = new AddressTableChunk(MaxOrdinal);
542 std::vector<Chunk *> Names;
543 for (Export &E : Config->Exports)
545 Names.push_back(new StringChunk(E.ExportName));
547 std::vector<Chunk *> Forwards;
548 for (Export &E : Config->Exports) {
549 if (E.ForwardTo.empty())
551 E.ForwardChunk = new StringChunk(E.ForwardTo);
552 Forwards.push_back(E.ForwardChunk);
555 auto *NameTab = new NamePointersChunk(Names);
556 auto *OrdinalTab = new ExportOrdinalChunk(Names.size());
557 auto *Dir = new ExportDirectoryChunk(MaxOrdinal, Names.size(), DLLName,
558 AddressTab, NameTab, OrdinalTab);
559 Chunks.push_back(std::unique_ptr<Chunk>(Dir));
560 Chunks.push_back(std::unique_ptr<Chunk>(DLLName));
561 Chunks.push_back(std::unique_ptr<Chunk>(AddressTab));
562 Chunks.push_back(std::unique_ptr<Chunk>(NameTab));
563 Chunks.push_back(std::unique_ptr<Chunk>(OrdinalTab));
564 for (Chunk *C : Names)
565 Chunks.push_back(std::unique_ptr<Chunk>(C));
566 for (Chunk *C : Forwards)
567 Chunks.push_back(std::unique_ptr<Chunk>(C));