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->NameRVA = DLLName->getRVA(); 104 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(); 111 } 112 113 Chunk *DLLName; 114 Chunk *AddressTab; 115 }; 116 117 // A chunk representing null terminator in the import table. 118 // Contents of this chunk is always null bytes. 119 class NullChunk : public Chunk { 120 public: 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; } 125 126 private: 127 size_t Size; 128 }; 129 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]; 136 }; 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); 141 142 std::vector<std::vector<DefinedImportData *>> V; 143 for (auto &KV : M) { 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(); 149 }); 150 V.push_back(std::move(Syms)); 151 } 152 return V; 153 } 154 155 // Export table 156 // See Microsoft PE/COFF spec 4.3 for details. 157 158 // A chunk for the delay import descriptor table etnry. 159 class DelayDirectoryChunk : public Chunk { 160 public: 161 explicit DelayDirectoryChunk(Chunk *N) : DLLName(N) {} 162 163 size_t getSize() const override { 164 return sizeof(delay_import_directory_table_entry); 165 } 166 167 void writeTo(uint8_t *Buf) const override { 168 auto *E = (delay_import_directory_table_entry *)(Buf + OutputSectionOff); 169 E->Attributes = 1; 170 E->Name = DLLName->getRVA(); 171 E->ModuleHandle = ModuleHandle->getRVA(); 172 E->DelayImportAddressTable = AddressTab->getRVA(); 173 E->DelayImportNameTable = NameTab->getRVA(); 174 } 175 176 Chunk *DLLName; 177 Chunk *ModuleHandle; 178 Chunk *AddressTab; 179 Chunk *NameTab; 180 }; 181 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[] = { 187 0x51, // push rcx 188 0x52, // push rdx 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 206 0x5A, // pop rdx 207 0x59, // pop rcx 208 0xFF, 0xE0, // jmp rax 209 }; 210 211 static const uint8_t ThunkX86[] = { 212 0x51, // push ecx 213 0x52, // push edx 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 217 0x5A, // pop edx 218 0x59, // pop ecx 219 0xFF, 0xE0, // jmp eax 220 }; 221 222 // A chunk for the delay import thunk. 223 class ThunkChunkX64 : public Chunk { 224 public: 225 ThunkChunkX64(Defined *I, Chunk *D, Defined *H) 226 : Imp(I), Desc(D), Helper(H) {} 227 228 size_t getSize() const override { return sizeof(ThunkX64); } 229 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); 235 } 236 237 Defined *Imp = nullptr; 238 Chunk *Desc = nullptr; 239 Defined *Helper = nullptr; 240 }; 241 242 class ThunkChunkX86 : public Chunk { 243 public: 244 ThunkChunkX86(Defined *I, Chunk *D, Defined *H) 245 : Imp(I), Desc(D), Helper(H) {} 246 247 size_t getSize() const override { return sizeof(ThunkX86); } 248 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); 254 } 255 256 void getBaserels(std::vector<Baserel> *Res) override { 257 Res->emplace_back(RVA + 3); 258 Res->emplace_back(RVA + 8); 259 } 260 261 Defined *Imp = nullptr; 262 Chunk *Desc = nullptr; 263 Defined *Helper = nullptr; 264 }; 265 266 // A chunk for the import descriptor table. 267 class DelayAddressChunk : public Chunk { 268 public: 269 explicit DelayAddressChunk(Chunk *C) : Thunk(C) {} 270 size_t getSize() const override { return ptrSize(); } 271 272 void writeTo(uint8_t *Buf) const override { 273 if (Config->is64()) { 274 write64le(Buf + OutputSectionOff, Thunk->getRVA() + Config->ImageBase); 275 } else { 276 write32le(Buf + OutputSectionOff, Thunk->getRVA() + Config->ImageBase); 277 } 278 } 279 280 void getBaserels(std::vector<Baserel> *Res) override { 281 Res->emplace_back(RVA); 282 } 283 284 Chunk *Thunk; 285 }; 286 287 // Export table 288 // Read Microsoft PE/COFF spec 5.3 for details. 289 290 // A chunk for the export descriptor table. 291 class ExportDirectoryChunk : public Chunk { 292 public: 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), 295 OrdinalTab(O) {} 296 297 size_t getSize() const override { 298 return sizeof(export_directory_table_entry); 299 } 300 301 void writeTo(uint8_t *Buf) const override { 302 auto *E = (export_directory_table_entry *)(Buf + OutputSectionOff); 303 E->NameRVA = DLLName->getRVA(); 304 E->OrdinalBase = 0; 305 E->AddressTableEntries = MaxOrdinal + 1; 306 E->NumberOfNamePointers = NameTabSize; 307 E->ExportAddressTableRVA = AddressTab->getRVA(); 308 E->NamePointerRVA = NameTab->getRVA(); 309 E->OrdinalTableRVA = OrdinalTab->getRVA(); 310 } 311 312 uint16_t MaxOrdinal; 313 uint16_t NameTabSize; 314 Chunk *DLLName; 315 Chunk *AddressTab; 316 Chunk *NameTab; 317 Chunk *OrdinalTab; 318 }; 319 320 class AddressTableChunk : public Chunk { 321 public: 322 explicit AddressTableChunk(size_t MaxOrdinal) : Size(MaxOrdinal + 1) {} 323 size_t getSize() const override { return Size * 4; } 324 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()); 330 } else { 331 write32le(P, cast<Defined>(E.Sym)->getRVA()); 332 } 333 } 334 } 335 336 private: 337 size_t Size; 338 }; 339 340 class NamePointersChunk : public Chunk { 341 public: 342 explicit NamePointersChunk(std::vector<Chunk *> &V) : Chunks(V) {} 343 size_t getSize() const override { return Chunks.size() * 4; } 344 345 void writeTo(uint8_t *Buf) const override { 346 uint8_t *P = Buf + OutputSectionOff; 347 for (Chunk *C : Chunks) { 348 write32le(P, C->getRVA()); 349 P += 4; 350 } 351 } 352 353 private: 354 std::vector<Chunk *> Chunks; 355 }; 356 357 class ExportOrdinalChunk : public Chunk { 358 public: 359 explicit ExportOrdinalChunk(size_t I) : Size(I) {} 360 size_t getSize() const override { return Size * 2; } 361 362 void writeTo(uint8_t *Buf) const override { 363 uint8_t *P = Buf + OutputSectionOff; 364 for (Export &E : Config->Exports) { 365 if (E.Noname) 366 continue; 367 write16le(P, E.Ordinal); 368 P += 2; 369 } 370 } 371 372 private: 373 size_t Size; 374 }; 375 376 } // anonymous namespace 377 378 uint64_t IdataContents::getDirSize() { 379 return Dirs.size() * sizeof(ImportDirectoryTableEntry); 380 } 381 382 uint64_t IdataContents::getIATSize() { 383 return Addresses.size() * ptrSize(); 384 } 385 386 // Returns a list of .idata contents. 387 // See Microsoft PE/COFF spec 5.4 for details. 388 std::vector<Chunk *> IdataContents::getChunks() { 389 create(); 390 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()); 398 return V; 399 } 400 401 void IdataContents::create() { 402 std::vector<std::vector<DefinedImportData *>> V = binImports(Imports); 403 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)); 415 continue; 416 } 417 auto *C = make<HintNameChunk>(S->getExternalName(), Ord); 418 Addresses.push_back(make<LookupChunk>(C)); 419 Hints.push_back(C); 420 } 421 // Terminate with null values. 422 Addresses.push_back(make<NullChunk>(ptrSize())); 423 424 for (int I = 0, E = Syms.size(); I < E; ++I) 425 Syms[I]->setLocation(Addresses[Base + I]); 426 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]; 431 Dirs.push_back(Dir); 432 } 433 // Add null terminator. 434 Dirs.push_back(make<NullChunk>(sizeof(ImportDirectoryTableEntry))); 435 } 436 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()); 443 return V; 444 } 445 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()); 450 return V; 451 } 452 453 uint64_t DelayLoadContents::getDirSize() { 454 return Dirs.size() * sizeof(delay_import_directory_table_entry); 455 } 456 457 void DelayLoadContents::create(Defined *H) { 458 Helper = H; 459 std::vector<std::vector<DefinedImportData *>> V = binImports(Imports); 460 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()); 466 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); 472 Thunks.push_back(T); 473 StringRef ExtName = S->getExternalName(); 474 if (ExtName.empty()) { 475 Names.push_back(make<OrdinalOnlyChunk>(S->getOrdinal())); 476 } else { 477 auto *C = make<HintNameChunk>(ExtName, 0); 478 Names.push_back(make<LookupChunk>(C)); 479 HintNames.push_back(C); 480 } 481 } 482 // Terminate with null values. 483 Addresses.push_back(make<NullChunk>(8)); 484 Names.push_back(make<NullChunk>(8)); 485 486 for (int I = 0, E = Syms.size(); I < E; ++I) 487 Syms[I]->setLocation(Addresses[Base + I]); 488 auto *MH = make<NullChunk>(8); 489 MH->setAlign(8); 490 ModuleHandles.push_back(MH); 491 492 // Fill the delay import table header fields. 493 Dir->ModuleHandle = MH; 494 Dir->AddressTab = Addresses[Base]; 495 Dir->NameTab = Names[Base]; 496 Dirs.push_back(Dir); 497 } 498 // Add null terminator. 499 Dirs.push_back(make<NullChunk>(sizeof(delay_import_directory_table_entry))); 500 } 501 502 Chunk *DelayLoadContents::newThunkChunk(DefinedImportData *S, Chunk *Dir) { 503 switch (Config->Machine) { 504 case AMD64: 505 return make<ThunkChunkX64>(S, Dir, Helper); 506 case I386: 507 return make<ThunkChunkX86>(S, Dir, Helper); 508 default: 509 llvm_unreachable("unsupported machine type"); 510 } 511 } 512 513 EdataContents::EdataContents() { 514 uint16_t MaxOrdinal = 0; 515 for (Export &E : Config->Exports) 516 MaxOrdinal = std::max(MaxOrdinal, E.Ordinal); 517 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) 522 if (!E.Noname) 523 Names.push_back(make<StringChunk>(E.ExportName)); 524 525 std::vector<Chunk *> Forwards; 526 for (Export &E : Config->Exports) { 527 if (E.ForwardTo.empty()) 528 continue; 529 E.ForwardChunk = make<StringChunk>(E.ForwardTo); 530 Forwards.push_back(E.ForwardChunk); 531 } 532 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()); 544 } 545 546 } // namespace coff 547 } // namespace lld 548