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->NameRVA = DLLName->getRVA();
105 // The import descriptor table contains two pointers to
106 // the tables describing dllimported symbols. But the
107 // Windows loader actually uses only one. So we create
108 // only one table and set both fields to its address.
109 E->ImportLookupTableRVA = AddressTab->getRVA();
110 E->ImportAddressTableRVA = AddressTab->getRVA();
117 // A chunk representing null terminator in the import table.
118 // Contents of this chunk is always null bytes.
119 class NullChunk : public Chunk {
121 explicit NullChunk(size_t N) : Size(N) {}
122 bool hasData() const override { return false; }
123 size_t getSize() const override { return Size; }
124 void setAlign(size_t N) { Align = N; }
130 static std::vector<std::vector<DefinedImportData *>>
131 binImports(const std::vector<DefinedImportData *> &Imports) {
132 // Group DLL-imported symbols by DLL name because that's how
133 // symbols are layed out in the import descriptor table.
134 auto Less = [](const std::string &A, const std::string &B) {
135 return Config->DLLOrder[A] < Config->DLLOrder[B];
137 std::map<std::string, std::vector<DefinedImportData *>,
138 bool(*)(const std::string &, const std::string &)> M(Less);
139 for (DefinedImportData *Sym : Imports)
140 M[Sym->getDLLName().lower()].push_back(Sym);
142 std::vector<std::vector<DefinedImportData *>> V;
144 // Sort symbols by name for each group.
145 std::vector<DefinedImportData *> &Syms = KV.second;
146 std::sort(Syms.begin(), Syms.end(),
147 [](DefinedImportData *A, DefinedImportData *B) {
148 return A->getName() < B->getName();
150 V.push_back(std::move(Syms));
156 // See Microsoft PE/COFF spec 4.3 for details.
158 // A chunk for the delay import descriptor table etnry.
159 class DelayDirectoryChunk : public Chunk {
161 explicit DelayDirectoryChunk(Chunk *N) : DLLName(N) {}
163 size_t getSize() const override {
164 return sizeof(delay_import_directory_table_entry);
167 void writeTo(uint8_t *Buf) const override {
168 auto *E = (delay_import_directory_table_entry *)(Buf + OutputSectionOff);
170 E->Name = DLLName->getRVA();
171 E->ModuleHandle = ModuleHandle->getRVA();
172 E->DelayImportAddressTable = AddressTab->getRVA();
173 E->DelayImportNameTable = NameTab->getRVA();
182 // Initial contents for delay-loaded functions.
183 // This code calls __delayLoadHelper2 function to resolve a symbol
184 // and then overwrites its jump table slot with the result
185 // for subsequent function calls.
186 static const uint8_t ThunkX64[] = {
189 0x41, 0x50, // push r8
190 0x41, 0x51, // push r9
191 0x48, 0x83, 0xEC, 0x48, // sub rsp, 48h
192 0x66, 0x0F, 0x7F, 0x04, 0x24, // movdqa xmmword ptr [rsp], xmm0
193 0x66, 0x0F, 0x7F, 0x4C, 0x24, 0x10, // movdqa xmmword ptr [rsp+10h], xmm1
194 0x66, 0x0F, 0x7F, 0x54, 0x24, 0x20, // movdqa xmmword ptr [rsp+20h], xmm2
195 0x66, 0x0F, 0x7F, 0x5C, 0x24, 0x30, // movdqa xmmword ptr [rsp+30h], xmm3
196 0x48, 0x8D, 0x15, 0, 0, 0, 0, // lea rdx, [__imp_<FUNCNAME>]
197 0x48, 0x8D, 0x0D, 0, 0, 0, 0, // lea rcx, [___DELAY_IMPORT_...]
198 0xE8, 0, 0, 0, 0, // call __delayLoadHelper2
199 0x66, 0x0F, 0x6F, 0x04, 0x24, // movdqa xmm0, xmmword ptr [rsp]
200 0x66, 0x0F, 0x6F, 0x4C, 0x24, 0x10, // movdqa xmm1, xmmword ptr [rsp+10h]
201 0x66, 0x0F, 0x6F, 0x54, 0x24, 0x20, // movdqa xmm2, xmmword ptr [rsp+20h]
202 0x66, 0x0F, 0x6F, 0x5C, 0x24, 0x30, // movdqa xmm3, xmmword ptr [rsp+30h]
203 0x48, 0x83, 0xC4, 0x48, // add rsp, 48h
204 0x41, 0x59, // pop r9
205 0x41, 0x58, // pop r8
208 0xFF, 0xE0, // jmp rax
211 static const uint8_t ThunkX86[] = {
214 0x68, 0, 0, 0, 0, // push offset ___imp__<FUNCNAME>
215 0x68, 0, 0, 0, 0, // push offset ___DELAY_IMPORT_DESCRIPTOR_<DLLNAME>_dll
216 0xE8, 0, 0, 0, 0, // call ___delayLoadHelper2@8
219 0xFF, 0xE0, // jmp eax
222 // A chunk for the delay import thunk.
223 class ThunkChunkX64 : public Chunk {
225 ThunkChunkX64(Defined *I, Chunk *D, Defined *H)
226 : Imp(I), Desc(D), Helper(H) {}
228 size_t getSize() const override { return sizeof(ThunkX64); }
230 void writeTo(uint8_t *Buf) const override {
231 memcpy(Buf + OutputSectionOff, ThunkX64, sizeof(ThunkX64));
232 write32le(Buf + OutputSectionOff + 36, Imp->getRVA() - RVA - 40);
233 write32le(Buf + OutputSectionOff + 43, Desc->getRVA() - RVA - 47);
234 write32le(Buf + OutputSectionOff + 48, Helper->getRVA() - RVA - 52);
237 Defined *Imp = nullptr;
238 Chunk *Desc = nullptr;
239 Defined *Helper = nullptr;
242 class ThunkChunkX86 : public Chunk {
244 ThunkChunkX86(Defined *I, Chunk *D, Defined *H)
245 : Imp(I), Desc(D), Helper(H) {}
247 size_t getSize() const override { return sizeof(ThunkX86); }
249 void writeTo(uint8_t *Buf) const override {
250 memcpy(Buf + OutputSectionOff, ThunkX86, sizeof(ThunkX86));
251 write32le(Buf + OutputSectionOff + 3, Imp->getRVA() + Config->ImageBase);
252 write32le(Buf + OutputSectionOff + 8, Desc->getRVA() + Config->ImageBase);
253 write32le(Buf + OutputSectionOff + 13, Helper->getRVA() - RVA - 17);
256 void getBaserels(std::vector<Baserel> *Res) override {
257 Res->emplace_back(RVA + 3);
258 Res->emplace_back(RVA + 8);
261 Defined *Imp = nullptr;
262 Chunk *Desc = nullptr;
263 Defined *Helper = nullptr;
266 // A chunk for the import descriptor table.
267 class DelayAddressChunk : public Chunk {
269 explicit DelayAddressChunk(Chunk *C) : Thunk(C) {}
270 size_t getSize() const override { return ptrSize(); }
272 void writeTo(uint8_t *Buf) const override {
273 if (Config->is64()) {
274 write64le(Buf + OutputSectionOff, Thunk->getRVA() + Config->ImageBase);
276 write32le(Buf + OutputSectionOff, Thunk->getRVA() + Config->ImageBase);
280 void getBaserels(std::vector<Baserel> *Res) override {
281 Res->emplace_back(RVA);
288 // Read Microsoft PE/COFF spec 5.3 for details.
290 // A chunk for the export descriptor table.
291 class ExportDirectoryChunk : public Chunk {
293 ExportDirectoryChunk(int I, int J, Chunk *D, Chunk *A, Chunk *N, Chunk *O)
294 : MaxOrdinal(I), NameTabSize(J), DLLName(D), AddressTab(A), NameTab(N),
297 size_t getSize() const override {
298 return sizeof(export_directory_table_entry);
301 void writeTo(uint8_t *Buf) const override {
302 auto *E = (export_directory_table_entry *)(Buf + OutputSectionOff);
303 E->NameRVA = DLLName->getRVA();
305 E->AddressTableEntries = MaxOrdinal + 1;
306 E->NumberOfNamePointers = NameTabSize;
307 E->ExportAddressTableRVA = AddressTab->getRVA();
308 E->NamePointerRVA = NameTab->getRVA();
309 E->OrdinalTableRVA = OrdinalTab->getRVA();
313 uint16_t NameTabSize;
320 class AddressTableChunk : public Chunk {
322 explicit AddressTableChunk(size_t MaxOrdinal) : Size(MaxOrdinal + 1) {}
323 size_t getSize() const override { return Size * 4; }
325 void writeTo(uint8_t *Buf) const override {
326 for (Export &E : Config->Exports) {
327 uint8_t *P = Buf + OutputSectionOff + E.Ordinal * 4;
328 if (E.ForwardChunk) {
329 write32le(P, E.ForwardChunk->getRVA());
331 write32le(P, cast<Defined>(E.Sym)->getRVA());
340 class NamePointersChunk : public Chunk {
342 explicit NamePointersChunk(std::vector<Chunk *> &V) : Chunks(V) {}
343 size_t getSize() const override { return Chunks.size() * 4; }
345 void writeTo(uint8_t *Buf) const override {
346 uint8_t *P = Buf + OutputSectionOff;
347 for (Chunk *C : Chunks) {
348 write32le(P, C->getRVA());
354 std::vector<Chunk *> Chunks;
357 class ExportOrdinalChunk : public Chunk {
359 explicit ExportOrdinalChunk(size_t I) : Size(I) {}
360 size_t getSize() const override { return Size * 2; }
362 void writeTo(uint8_t *Buf) const override {
363 uint8_t *P = Buf + OutputSectionOff;
364 for (Export &E : Config->Exports) {
367 write16le(P, E.Ordinal);
376 } // anonymous namespace
378 uint64_t IdataContents::getDirSize() {
379 return Dirs.size() * sizeof(ImportDirectoryTableEntry);
382 uint64_t IdataContents::getIATSize() {
383 return Addresses.size() * ptrSize();
386 // Returns a list of .idata contents.
387 // See Microsoft PE/COFF spec 5.4 for details.
388 std::vector<Chunk *> IdataContents::getChunks() {
391 // The loader assumes a specific order of data.
392 // Add each type in the correct order.
393 std::vector<Chunk *> V;
394 V.insert(V.end(), Dirs.begin(), Dirs.end());
395 V.insert(V.end(), Addresses.begin(), Addresses.end());
396 V.insert(V.end(), Hints.begin(), Hints.end());
397 V.insert(V.end(), DLLNames.begin(), DLLNames.end());
401 void IdataContents::create() {
402 std::vector<std::vector<DefinedImportData *>> V = binImports(Imports);
404 // Create .idata contents for each DLL.
405 for (std::vector<DefinedImportData *> &Syms : V) {
406 // Create lookup and address tables. If they have external names,
407 // we need to create HintName chunks to store the names.
408 // If they don't (if they are import-by-ordinals), we store only
409 // ordinal values to the table.
410 size_t Base = Addresses.size();
411 for (DefinedImportData *S : Syms) {
412 uint16_t Ord = S->getOrdinal();
413 if (S->getExternalName().empty()) {
414 Addresses.push_back(make<OrdinalOnlyChunk>(Ord));
417 auto *C = make<HintNameChunk>(S->getExternalName(), Ord);
418 Addresses.push_back(make<LookupChunk>(C));
421 // Terminate with null values.
422 Addresses.push_back(make<NullChunk>(ptrSize()));
424 for (int I = 0, E = Syms.size(); I < E; ++I)
425 Syms[I]->setLocation(Addresses[Base + I]);
427 // Create the import table header.
428 DLLNames.push_back(make<StringChunk>(Syms[0]->getDLLName()));
429 auto *Dir = make<ImportDirectoryChunk>(DLLNames.back());
430 Dir->AddressTab = Addresses[Base];
433 // Add null terminator.
434 Dirs.push_back(make<NullChunk>(sizeof(ImportDirectoryTableEntry)));
437 std::vector<Chunk *> DelayLoadContents::getChunks() {
438 std::vector<Chunk *> V;
439 V.insert(V.end(), Dirs.begin(), Dirs.end());
440 V.insert(V.end(), Names.begin(), Names.end());
441 V.insert(V.end(), HintNames.begin(), HintNames.end());
442 V.insert(V.end(), DLLNames.begin(), DLLNames.end());
446 std::vector<Chunk *> DelayLoadContents::getDataChunks() {
447 std::vector<Chunk *> V;
448 V.insert(V.end(), ModuleHandles.begin(), ModuleHandles.end());
449 V.insert(V.end(), Addresses.begin(), Addresses.end());
453 uint64_t DelayLoadContents::getDirSize() {
454 return Dirs.size() * sizeof(delay_import_directory_table_entry);
457 void DelayLoadContents::create(Defined *H) {
459 std::vector<std::vector<DefinedImportData *>> V = binImports(Imports);
461 // Create .didat contents for each DLL.
462 for (std::vector<DefinedImportData *> &Syms : V) {
463 // Create the delay import table header.
464 DLLNames.push_back(make<StringChunk>(Syms[0]->getDLLName()));
465 auto *Dir = make<DelayDirectoryChunk>(DLLNames.back());
467 size_t Base = Addresses.size();
468 for (DefinedImportData *S : Syms) {
469 Chunk *T = newThunkChunk(S, Dir);
470 auto *A = make<DelayAddressChunk>(T);
471 Addresses.push_back(A);
473 StringRef ExtName = S->getExternalName();
474 if (ExtName.empty()) {
475 Names.push_back(make<OrdinalOnlyChunk>(S->getOrdinal()));
477 auto *C = make<HintNameChunk>(ExtName, 0);
478 Names.push_back(make<LookupChunk>(C));
479 HintNames.push_back(C);
482 // Terminate with null values.
483 Addresses.push_back(make<NullChunk>(8));
484 Names.push_back(make<NullChunk>(8));
486 for (int I = 0, E = Syms.size(); I < E; ++I)
487 Syms[I]->setLocation(Addresses[Base + I]);
488 auto *MH = make<NullChunk>(8);
490 ModuleHandles.push_back(MH);
492 // Fill the delay import table header fields.
493 Dir->ModuleHandle = MH;
494 Dir->AddressTab = Addresses[Base];
495 Dir->NameTab = Names[Base];
498 // Add null terminator.
499 Dirs.push_back(make<NullChunk>(sizeof(delay_import_directory_table_entry)));
502 Chunk *DelayLoadContents::newThunkChunk(DefinedImportData *S, Chunk *Dir) {
503 switch (Config->Machine) {
505 return make<ThunkChunkX64>(S, Dir, Helper);
507 return make<ThunkChunkX86>(S, Dir, Helper);
509 llvm_unreachable("unsupported machine type");
513 EdataContents::EdataContents() {
514 uint16_t MaxOrdinal = 0;
515 for (Export &E : Config->Exports)
516 MaxOrdinal = std::max(MaxOrdinal, E.Ordinal);
518 auto *DLLName = make<StringChunk>(sys::path::filename(Config->OutputFile));
519 auto *AddressTab = make<AddressTableChunk>(MaxOrdinal);
520 std::vector<Chunk *> Names;
521 for (Export &E : Config->Exports)
523 Names.push_back(make<StringChunk>(E.ExportName));
525 std::vector<Chunk *> Forwards;
526 for (Export &E : Config->Exports) {
527 if (E.ForwardTo.empty())
529 E.ForwardChunk = make<StringChunk>(E.ForwardTo);
530 Forwards.push_back(E.ForwardChunk);
533 auto *NameTab = make<NamePointersChunk>(Names);
534 auto *OrdinalTab = make<ExportOrdinalChunk>(Names.size());
535 auto *Dir = make<ExportDirectoryChunk>(MaxOrdinal, Names.size(), DLLName,
536 AddressTab, NameTab, OrdinalTab);
537 Chunks.push_back(Dir);
538 Chunks.push_back(DLLName);
539 Chunks.push_back(AddressTab);
540 Chunks.push_back(NameTab);
541 Chunks.push_back(OrdinalTab);
542 Chunks.insert(Chunks.end(), Names.begin(), Names.end());
543 Chunks.insert(Chunks.end(), Forwards.begin(), Forwards.end());