1 //===- 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 // 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. 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/Object/COFF.h" 24 #include "llvm/Support/Endian.h" 25 #include "llvm/Support/Path.h" 26 27 using namespace llvm; 28 using namespace llvm::object; 29 using namespace llvm::support::endian; 30 using namespace llvm::COFF; 31 32 namespace lld { 33 namespace coff { 34 namespace { 35 36 // Import table 37 38 static int ptrSize() { return Config->is64() ? 8 : 4; } 39 40 // A chunk for the import descriptor table. 41 class HintNameChunk : public Chunk { 42 public: 43 HintNameChunk(StringRef N, uint16_t H) : Name(N), Hint(H) {} 44 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); 49 } 50 51 void writeTo(uint8_t *Buf) const override { 52 write16le(Buf + OutputSectionOff, Hint); 53 memcpy(Buf + OutputSectionOff + 2, Name.data(), Name.size()); 54 } 55 56 private: 57 StringRef Name; 58 uint16_t Hint; 59 }; 60 61 // A chunk for the import descriptor table. 62 class LookupChunk : public Chunk { 63 public: 64 explicit LookupChunk(Chunk *C) : HintName(C) {} 65 size_t getSize() const override { return ptrSize(); } 66 67 void writeTo(uint8_t *Buf) const override { 68 write32le(Buf + OutputSectionOff, HintName->getRVA()); 69 } 70 71 Chunk *HintName; 72 }; 73 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 { 78 public: 79 explicit OrdinalOnlyChunk(uint16_t V) : Ordinal(V) {} 80 size_t getSize() const override { return ptrSize(); } 81 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). 85 if (Config->is64()) { 86 write64le(Buf + OutputSectionOff, (1ULL << 63) | Ordinal); 87 } else { 88 write32le(Buf + OutputSectionOff, (1ULL << 31) | Ordinal); 89 } 90 } 91 92 uint16_t Ordinal; 93 }; 94 95 // A chunk for the import descriptor table. 96 class ImportDirectoryChunk : public Chunk { 97 public: 98 explicit ImportDirectoryChunk(Chunk *N) : DLLName(N) {} 99 size_t getSize() const override { return sizeof(ImportDirectoryTableEntry); } 100 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(); 106 } 107 108 Chunk *DLLName; 109 Chunk *LookupTab; 110 Chunk *AddressTab; 111 }; 112 113 // A chunk representing null terminator in the import table. 114 // Contents of this chunk is always null bytes. 115 class NullChunk : public Chunk { 116 public: 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; } 121 122 private: 123 size_t Size; 124 }; 125 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]; 132 }; 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); 137 138 std::vector<std::vector<DefinedImportData *>> V; 139 for (auto &P : M) { 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(); 145 }); 146 V.push_back(std::move(Syms)); 147 } 148 return V; 149 } 150 151 // Export table 152 // See Microsoft PE/COFF spec 4.3 for details. 153 154 // A chunk for the delay import descriptor table etnry. 155 class DelayDirectoryChunk : public Chunk { 156 public: 157 explicit DelayDirectoryChunk(Chunk *N) : DLLName(N) {} 158 159 size_t getSize() const override { 160 return sizeof(delay_import_directory_table_entry); 161 } 162 163 void writeTo(uint8_t *Buf) const override { 164 auto *E = (delay_import_directory_table_entry *)(Buf + OutputSectionOff); 165 E->Attributes = 1; 166 E->Name = DLLName->getRVA(); 167 E->ModuleHandle = ModuleHandle->getRVA(); 168 E->DelayImportAddressTable = AddressTab->getRVA(); 169 E->DelayImportNameTable = NameTab->getRVA(); 170 } 171 172 Chunk *DLLName; 173 Chunk *ModuleHandle; 174 Chunk *AddressTab; 175 Chunk *NameTab; 176 }; 177 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[] = { 183 0x51, // push rcx 184 0x52, // push rdx 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 202 0x5A, // pop rdx 203 0x59, // pop rcx 204 0xFF, 0xE0, // jmp rax 205 }; 206 207 static const uint8_t ThunkX86[] = { 208 0x51, // push ecx 209 0x52, // push edx 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 213 0x5A, // pop edx 214 0x59, // pop ecx 215 0xFF, 0xE0, // jmp eax 216 }; 217 218 // A chunk for the delay import thunk. 219 class ThunkChunkX64 : public Chunk { 220 public: 221 ThunkChunkX64(Defined *I, Chunk *D, Defined *H) 222 : Imp(I), Desc(D), Helper(H) {} 223 224 size_t getSize() const override { return sizeof(ThunkX64); } 225 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); 231 } 232 233 Defined *Imp = nullptr; 234 Chunk *Desc = nullptr; 235 Defined *Helper = nullptr; 236 }; 237 238 class ThunkChunkX86 : public Chunk { 239 public: 240 ThunkChunkX86(Defined *I, Chunk *D, Defined *H) 241 : Imp(I), Desc(D), Helper(H) {} 242 243 size_t getSize() const override { return sizeof(ThunkX86); } 244 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); 250 } 251 252 void getBaserels(std::vector<Baserel> *Res) override { 253 Res->emplace_back(RVA + 3); 254 Res->emplace_back(RVA + 8); 255 } 256 257 Defined *Imp = nullptr; 258 Chunk *Desc = nullptr; 259 Defined *Helper = nullptr; 260 }; 261 262 // A chunk for the import descriptor table. 263 class DelayAddressChunk : public Chunk { 264 public: 265 explicit DelayAddressChunk(Chunk *C) : Thunk(C) {} 266 size_t getSize() const override { return ptrSize(); } 267 268 void writeTo(uint8_t *Buf) const override { 269 if (Config->is64()) { 270 write64le(Buf + OutputSectionOff, Thunk->getRVA() + Config->ImageBase); 271 } else { 272 write32le(Buf + OutputSectionOff, Thunk->getRVA() + Config->ImageBase); 273 } 274 } 275 276 void getBaserels(std::vector<Baserel> *Res) override { 277 Res->emplace_back(RVA); 278 } 279 280 Chunk *Thunk; 281 }; 282 283 // Export table 284 // Read Microsoft PE/COFF spec 5.3 for details. 285 286 // A chunk for the export descriptor table. 287 class ExportDirectoryChunk : public Chunk { 288 public: 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), 291 OrdinalTab(O) {} 292 293 size_t getSize() const override { 294 return sizeof(export_directory_table_entry); 295 } 296 297 void writeTo(uint8_t *Buf) const override { 298 auto *E = (export_directory_table_entry *)(Buf + OutputSectionOff); 299 E->NameRVA = DLLName->getRVA(); 300 E->OrdinalBase = 0; 301 E->AddressTableEntries = MaxOrdinal + 1; 302 E->NumberOfNamePointers = NameTabSize; 303 E->ExportAddressTableRVA = AddressTab->getRVA(); 304 E->NamePointerRVA = NameTab->getRVA(); 305 E->OrdinalTableRVA = OrdinalTab->getRVA(); 306 } 307 308 uint16_t MaxOrdinal; 309 uint16_t NameTabSize; 310 Chunk *DLLName; 311 Chunk *AddressTab; 312 Chunk *NameTab; 313 Chunk *OrdinalTab; 314 }; 315 316 class AddressTableChunk : public Chunk { 317 public: 318 explicit AddressTableChunk(size_t MaxOrdinal) : Size(MaxOrdinal + 1) {} 319 size_t getSize() const override { return Size * 4; } 320 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()); 326 } else { 327 write32le(P, cast<Defined>(E.Sym)->getRVA()); 328 } 329 } 330 } 331 332 private: 333 size_t Size; 334 }; 335 336 class NamePointersChunk : public Chunk { 337 public: 338 explicit NamePointersChunk(std::vector<Chunk *> &V) : Chunks(V) {} 339 size_t getSize() const override { return Chunks.size() * 4; } 340 341 void writeTo(uint8_t *Buf) const override { 342 uint8_t *P = Buf + OutputSectionOff; 343 for (Chunk *C : Chunks) { 344 write32le(P, C->getRVA()); 345 P += 4; 346 } 347 } 348 349 private: 350 std::vector<Chunk *> Chunks; 351 }; 352 353 class ExportOrdinalChunk : public Chunk { 354 public: 355 explicit ExportOrdinalChunk(size_t I) : Size(I) {} 356 size_t getSize() const override { return Size * 2; } 357 358 void writeTo(uint8_t *Buf) const override { 359 uint8_t *P = Buf + OutputSectionOff; 360 for (Export &E : Config->Exports) { 361 if (E.Noname) 362 continue; 363 write16le(P, E.Ordinal); 364 P += 2; 365 } 366 } 367 368 private: 369 size_t Size; 370 }; 371 372 } // anonymous namespace 373 374 uint64_t IdataContents::getDirSize() { 375 return Dirs.size() * sizeof(ImportDirectoryTableEntry); 376 } 377 378 uint64_t IdataContents::getIATSize() { 379 return Addresses.size() * ptrSize(); 380 } 381 382 // Returns a list of .idata contents. 383 // See Microsoft PE/COFF spec 5.4 for details. 384 std::vector<Chunk *> IdataContents::getChunks() { 385 create(); 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()); 400 } 401 return V; 402 } 403 404 void IdataContents::create() { 405 std::vector<std::vector<DefinedImportData *>> V = binImports(Imports); 406 407 // Create .idata contents for each DLL. 408 for (std::vector<DefinedImportData *> &Syms : V) { 409 StringRef Name = Syms[0]->getDLLName(); 410 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)); 421 continue; 422 } 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)); 427 } 428 // Terminate with null values. 429 Lookups.push_back(make_unique<NullChunk>(ptrSize())); 430 Addresses.push_back(make_unique<NullChunk>(ptrSize())); 431 432 for (int I = 0, E = Syms.size(); I < E; ++I) 433 Syms[I]->setLocation(Addresses[Base + I].get()); 434 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)); 442 } 443 // Add null terminator. 444 Dirs.push_back(make_unique<NullChunk>(sizeof(ImportDirectoryTableEntry))); 445 } 446 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()); 458 } 459 return V; 460 } 461 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()); 468 return V; 469 } 470 471 uint64_t DelayLoadContents::getDirSize() { 472 return Dirs.size() * sizeof(delay_import_directory_table_entry); 473 } 474 475 void DelayLoadContents::create(Defined *H) { 476 Helper = H; 477 std::vector<std::vector<DefinedImportData *>> V = binImports(Imports); 478 479 // Create .didat contents for each DLL. 480 for (std::vector<DefinedImportData *> &Syms : V) { 481 StringRef Name = Syms[0]->getDLLName(); 482 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()); 487 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())); 497 } else { 498 auto C = make_unique<HintNameChunk>(ExtName, 0); 499 Names.push_back(make_unique<LookupChunk>(C.get())); 500 HintNames.push_back(std::move(C)); 501 } 502 } 503 // Terminate with null values. 504 Addresses.push_back(make_unique<NullChunk>(8)); 505 Names.push_back(make_unique<NullChunk>(8)); 506 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); 510 MH->setAlign(8); 511 ModuleHandles.push_back(std::unique_ptr<Chunk>(MH)); 512 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)); 518 } 519 // Add null terminator. 520 Dirs.push_back( 521 make_unique<NullChunk>(sizeof(delay_import_directory_table_entry))); 522 } 523 524 Chunk *DelayLoadContents::newThunkChunk(DefinedImportData *S, Chunk *Dir) { 525 switch (Config->Machine) { 526 case AMD64: 527 return new ThunkChunkX64(S, Dir, Helper); 528 case I386: 529 return new ThunkChunkX86(S, Dir, Helper); 530 default: 531 llvm_unreachable("unsupported machine type"); 532 } 533 } 534 535 EdataContents::EdataContents() { 536 uint16_t MaxOrdinal = 0; 537 for (Export &E : Config->Exports) 538 MaxOrdinal = std::max(MaxOrdinal, E.Ordinal); 539 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) 544 if (!E.Noname) 545 Names.push_back(new StringChunk(E.ExportName)); 546 547 std::vector<Chunk *> Forwards; 548 for (Export &E : Config->Exports) { 549 if (E.ForwardTo.empty()) 550 continue; 551 E.ForwardChunk = new StringChunk(E.ForwardTo); 552 Forwards.push_back(E.ForwardChunk); 553 } 554 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)); 568 } 569 570 } // namespace coff 571 } // namespace lld 572