1 //===- DLL.cpp ------------------------------------------------------------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 // 9 // This file defines various types of chunks for the DLL import or export 10 // descriptor tables. They are inherently Windows-specific. 11 // You need to read Microsoft PE/COFF spec to understand details 12 // about the data structures. 13 // 14 // If you are not particularly interested in linking against Windows 15 // DLL, you can skip this file, and you should still be able to 16 // understand the rest of the linker. 17 // 18 //===----------------------------------------------------------------------===// 19 20 #include "DLL.h" 21 #include "Chunks.h" 22 #include "llvm/Object/COFF.h" 23 #include "llvm/Support/Endian.h" 24 #include "llvm/Support/Path.h" 25 26 using namespace llvm; 27 using namespace llvm::object; 28 using namespace llvm::support::endian; 29 using namespace llvm::COFF; 30 31 namespace lld { 32 namespace coff { 33 namespace { 34 35 // Import table 36 37 // A chunk for the import descriptor table. 38 class HintNameChunk : public Chunk { 39 public: 40 HintNameChunk(StringRef N, uint16_t H) : Name(N), Hint(H) {} 41 42 size_t getSize() const override { 43 // Starts with 2 byte Hint field, followed by a null-terminated string, 44 // ends with 0 or 1 byte padding. 45 return alignTo(Name.size() + 3, 2); 46 } 47 48 void writeTo(uint8_t *Buf) const override { 49 memset(Buf, 0, getSize()); 50 write16le(Buf, Hint); 51 memcpy(Buf + 2, Name.data(), Name.size()); 52 } 53 54 private: 55 StringRef Name; 56 uint16_t Hint; 57 }; 58 59 // A chunk for the import descriptor table. 60 class LookupChunk : public Chunk { 61 public: 62 explicit LookupChunk(Chunk *C) : HintName(C) { 63 setAlignment(Config->Wordsize); 64 } 65 size_t getSize() const override { return Config->Wordsize; } 66 67 void writeTo(uint8_t *Buf) const override { 68 if (Config->is64()) 69 write64le(Buf, HintName->getRVA()); 70 else 71 write32le(Buf, HintName->getRVA()); 72 } 73 74 Chunk *HintName; 75 }; 76 77 // A chunk for the import descriptor table. 78 // This chunk represent import-by-ordinal symbols. 79 // See Microsoft PE/COFF spec 7.1. Import Header for details. 80 class OrdinalOnlyChunk : public Chunk { 81 public: 82 explicit OrdinalOnlyChunk(uint16_t V) : Ordinal(V) { 83 setAlignment(Config->Wordsize); 84 } 85 size_t getSize() const override { return Config->Wordsize; } 86 87 void writeTo(uint8_t *Buf) const override { 88 // An import-by-ordinal slot has MSB 1 to indicate that 89 // this is import-by-ordinal (and not import-by-name). 90 if (Config->is64()) { 91 write64le(Buf, (1ULL << 63) | Ordinal); 92 } else { 93 write32le(Buf, (1ULL << 31) | Ordinal); 94 } 95 } 96 97 uint16_t Ordinal; 98 }; 99 100 // A chunk for the import descriptor table. 101 class ImportDirectoryChunk : public Chunk { 102 public: 103 explicit ImportDirectoryChunk(Chunk *N) : DLLName(N) {} 104 size_t getSize() const override { return sizeof(ImportDirectoryTableEntry); } 105 106 void writeTo(uint8_t *Buf) const override { 107 memset(Buf, 0, getSize()); 108 109 auto *E = (coff_import_directory_table_entry *)(Buf); 110 E->ImportLookupTableRVA = LookupTab->getRVA(); 111 E->NameRVA = DLLName->getRVA(); 112 E->ImportAddressTableRVA = AddressTab->getRVA(); 113 } 114 115 Chunk *DLLName; 116 Chunk *LookupTab; 117 Chunk *AddressTab; 118 }; 119 120 // A chunk representing null terminator in the import table. 121 // Contents of this chunk is always null bytes. 122 class NullChunk : public Chunk { 123 public: 124 explicit NullChunk(size_t N) : Size(N) {} 125 bool hasData() const override { return false; } 126 size_t getSize() const override { return Size; } 127 128 void writeTo(uint8_t *Buf) const override { 129 memset(Buf, 0, Size); 130 } 131 132 private: 133 size_t Size; 134 }; 135 136 static std::vector<std::vector<DefinedImportData *>> 137 binImports(const std::vector<DefinedImportData *> &Imports) { 138 // Group DLL-imported symbols by DLL name because that's how 139 // symbols are layed out in the import descriptor table. 140 auto Less = [](const std::string &A, const std::string &B) { 141 return Config->DLLOrder[A] < Config->DLLOrder[B]; 142 }; 143 std::map<std::string, std::vector<DefinedImportData *>, 144 bool(*)(const std::string &, const std::string &)> M(Less); 145 for (DefinedImportData *Sym : Imports) 146 M[Sym->getDLLName().lower()].push_back(Sym); 147 148 std::vector<std::vector<DefinedImportData *>> V; 149 for (auto &KV : M) { 150 // Sort symbols by name for each group. 151 std::vector<DefinedImportData *> &Syms = KV.second; 152 std::sort(Syms.begin(), Syms.end(), 153 [](DefinedImportData *A, DefinedImportData *B) { 154 return A->getName() < B->getName(); 155 }); 156 V.push_back(std::move(Syms)); 157 } 158 return V; 159 } 160 161 // Export table 162 // See Microsoft PE/COFF spec 4.3 for details. 163 164 // A chunk for the delay import descriptor table etnry. 165 class DelayDirectoryChunk : public Chunk { 166 public: 167 explicit DelayDirectoryChunk(Chunk *N) : DLLName(N) {} 168 169 size_t getSize() const override { 170 return sizeof(delay_import_directory_table_entry); 171 } 172 173 void writeTo(uint8_t *Buf) const override { 174 memset(Buf, 0, getSize()); 175 176 auto *E = (delay_import_directory_table_entry *)(Buf); 177 E->Attributes = 1; 178 E->Name = DLLName->getRVA(); 179 E->ModuleHandle = ModuleHandle->getRVA(); 180 E->DelayImportAddressTable = AddressTab->getRVA(); 181 E->DelayImportNameTable = NameTab->getRVA(); 182 } 183 184 Chunk *DLLName; 185 Chunk *ModuleHandle; 186 Chunk *AddressTab; 187 Chunk *NameTab; 188 }; 189 190 // Initial contents for delay-loaded functions. 191 // This code calls __delayLoadHelper2 function to resolve a symbol 192 // and then overwrites its jump table slot with the result 193 // for subsequent function calls. 194 static const uint8_t ThunkX64[] = { 195 0x51, // push rcx 196 0x52, // push rdx 197 0x41, 0x50, // push r8 198 0x41, 0x51, // push r9 199 0x48, 0x83, 0xEC, 0x48, // sub rsp, 48h 200 0x66, 0x0F, 0x7F, 0x04, 0x24, // movdqa xmmword ptr [rsp], xmm0 201 0x66, 0x0F, 0x7F, 0x4C, 0x24, 0x10, // movdqa xmmword ptr [rsp+10h], xmm1 202 0x66, 0x0F, 0x7F, 0x54, 0x24, 0x20, // movdqa xmmword ptr [rsp+20h], xmm2 203 0x66, 0x0F, 0x7F, 0x5C, 0x24, 0x30, // movdqa xmmword ptr [rsp+30h], xmm3 204 0x48, 0x8D, 0x15, 0, 0, 0, 0, // lea rdx, [__imp_<FUNCNAME>] 205 0x48, 0x8D, 0x0D, 0, 0, 0, 0, // lea rcx, [___DELAY_IMPORT_...] 206 0xE8, 0, 0, 0, 0, // call __delayLoadHelper2 207 0x66, 0x0F, 0x6F, 0x04, 0x24, // movdqa xmm0, xmmword ptr [rsp] 208 0x66, 0x0F, 0x6F, 0x4C, 0x24, 0x10, // movdqa xmm1, xmmword ptr [rsp+10h] 209 0x66, 0x0F, 0x6F, 0x54, 0x24, 0x20, // movdqa xmm2, xmmword ptr [rsp+20h] 210 0x66, 0x0F, 0x6F, 0x5C, 0x24, 0x30, // movdqa xmm3, xmmword ptr [rsp+30h] 211 0x48, 0x83, 0xC4, 0x48, // add rsp, 48h 212 0x41, 0x59, // pop r9 213 0x41, 0x58, // pop r8 214 0x5A, // pop rdx 215 0x59, // pop rcx 216 0xFF, 0xE0, // jmp rax 217 }; 218 219 static const uint8_t ThunkX86[] = { 220 0x51, // push ecx 221 0x52, // push edx 222 0x68, 0, 0, 0, 0, // push offset ___imp__<FUNCNAME> 223 0x68, 0, 0, 0, 0, // push offset ___DELAY_IMPORT_DESCRIPTOR_<DLLNAME>_dll 224 0xE8, 0, 0, 0, 0, // call ___delayLoadHelper2@8 225 0x5A, // pop edx 226 0x59, // pop ecx 227 0xFF, 0xE0, // jmp eax 228 }; 229 230 static const uint8_t ThunkARM[] = { 231 0x40, 0xf2, 0x00, 0x0c, // mov.w ip, #0 __imp_<FUNCNAME> 232 0xc0, 0xf2, 0x00, 0x0c, // mov.t ip, #0 __imp_<FUNCNAME> 233 0x2d, 0xe9, 0x0f, 0x48, // push.w {r0, r1, r2, r3, r11, lr} 234 0x0d, 0xf2, 0x10, 0x0b, // addw r11, sp, #16 235 0x2d, 0xed, 0x10, 0x0b, // vpush {d0, d1, d2, d3, d4, d5, d6, d7} 236 0x61, 0x46, // mov r1, ip 237 0x40, 0xf2, 0x00, 0x00, // mov.w r0, #0 DELAY_IMPORT_DESCRIPTOR 238 0xc0, 0xf2, 0x00, 0x00, // mov.t r0, #0 DELAY_IMPORT_DESCRIPTOR 239 0x00, 0xf0, 0x00, 0xd0, // bl #0 __delayLoadHelper2 240 0x84, 0x46, // mov ip, r0 241 0xbd, 0xec, 0x10, 0x0b, // vpop {d0, d1, d2, d3, d4, d5, d6, d7} 242 0xbd, 0xe8, 0x0f, 0x48, // pop.w {r0, r1, r2, r3, r11, lr} 243 0x60, 0x47, // bx ip 244 }; 245 246 static const uint8_t ThunkARM64[] = { 247 0x11, 0x00, 0x00, 0x90, // adrp x17, #0 __imp_<FUNCNAME> 248 0x31, 0x02, 0x00, 0x91, // add x17, x17, #0 :lo12:__imp_<FUNCNAME> 249 0xfd, 0x7b, 0xb3, 0xa9, // stp x29, x30, [sp, #-208]! 250 0xfd, 0x03, 0x00, 0x91, // mov x29, sp 251 0xe0, 0x07, 0x01, 0xa9, // stp x0, x1, [sp, #16] 252 0xe2, 0x0f, 0x02, 0xa9, // stp x2, x3, [sp, #32] 253 0xe4, 0x17, 0x03, 0xa9, // stp x4, x5, [sp, #48] 254 0xe6, 0x1f, 0x04, 0xa9, // stp x6, x7, [sp, #64] 255 0xe0, 0x87, 0x02, 0xad, // stp q0, q1, [sp, #80] 256 0xe2, 0x8f, 0x03, 0xad, // stp q2, q3, [sp, #112] 257 0xe4, 0x97, 0x04, 0xad, // stp q4, q5, [sp, #144] 258 0xe6, 0x9f, 0x05, 0xad, // stp q6, q7, [sp, #176] 259 0xe1, 0x03, 0x11, 0xaa, // mov x1, x17 260 0x00, 0x00, 0x00, 0x90, // adrp x0, #0 DELAY_IMPORT_DESCRIPTOR 261 0x00, 0x00, 0x00, 0x91, // add x0, x0, #0 :lo12:DELAY_IMPORT_DESCRIPTOR 262 0x00, 0x00, 0x00, 0x94, // bl #0 __delayLoadHelper2 263 0xf0, 0x03, 0x00, 0xaa, // mov x16, x0 264 0xe6, 0x9f, 0x45, 0xad, // ldp q6, q7, [sp, #176] 265 0xe4, 0x97, 0x44, 0xad, // ldp q4, q5, [sp, #144] 266 0xe2, 0x8f, 0x43, 0xad, // ldp q2, q3, [sp, #112] 267 0xe0, 0x87, 0x42, 0xad, // ldp q0, q1, [sp, #80] 268 0xe6, 0x1f, 0x44, 0xa9, // ldp x6, x7, [sp, #64] 269 0xe4, 0x17, 0x43, 0xa9, // ldp x4, x5, [sp, #48] 270 0xe2, 0x0f, 0x42, 0xa9, // ldp x2, x3, [sp, #32] 271 0xe0, 0x07, 0x41, 0xa9, // ldp x0, x1, [sp, #16] 272 0xfd, 0x7b, 0xcd, 0xa8, // ldp x29, x30, [sp], #208 273 0x00, 0x02, 0x1f, 0xd6, // br x16 274 }; 275 276 // A chunk for the delay import thunk. 277 class ThunkChunkX64 : public Chunk { 278 public: 279 ThunkChunkX64(Defined *I, Chunk *D, Defined *H) 280 : Imp(I), Desc(D), Helper(H) {} 281 282 size_t getSize() const override { return sizeof(ThunkX64); } 283 284 void writeTo(uint8_t *Buf) const override { 285 memcpy(Buf, ThunkX64, sizeof(ThunkX64)); 286 write32le(Buf + 36, Imp->getRVA() - RVA - 40); 287 write32le(Buf + 43, Desc->getRVA() - RVA - 47); 288 write32le(Buf + 48, Helper->getRVA() - RVA - 52); 289 } 290 291 Defined *Imp = nullptr; 292 Chunk *Desc = nullptr; 293 Defined *Helper = nullptr; 294 }; 295 296 class ThunkChunkX86 : public Chunk { 297 public: 298 ThunkChunkX86(Defined *I, Chunk *D, Defined *H) 299 : Imp(I), Desc(D), Helper(H) {} 300 301 size_t getSize() const override { return sizeof(ThunkX86); } 302 303 void writeTo(uint8_t *Buf) const override { 304 memcpy(Buf, ThunkX86, sizeof(ThunkX86)); 305 write32le(Buf + 3, Imp->getRVA() + Config->ImageBase); 306 write32le(Buf + 8, Desc->getRVA() + Config->ImageBase); 307 write32le(Buf + 13, Helper->getRVA() - RVA - 17); 308 } 309 310 void getBaserels(std::vector<Baserel> *Res) override { 311 Res->emplace_back(RVA + 3); 312 Res->emplace_back(RVA + 8); 313 } 314 315 Defined *Imp = nullptr; 316 Chunk *Desc = nullptr; 317 Defined *Helper = nullptr; 318 }; 319 320 class ThunkChunkARM : public Chunk { 321 public: 322 ThunkChunkARM(Defined *I, Chunk *D, Defined *H) 323 : Imp(I), Desc(D), Helper(H) {} 324 325 size_t getSize() const override { return sizeof(ThunkARM); } 326 327 void writeTo(uint8_t *Buf) const override { 328 memcpy(Buf, ThunkARM, sizeof(ThunkARM)); 329 applyMOV32T(Buf + 0, Imp->getRVA() + Config->ImageBase); 330 applyMOV32T(Buf + 22, Desc->getRVA() + Config->ImageBase); 331 applyBranch24T(Buf + 30, Helper->getRVA() - RVA - 34); 332 } 333 334 void getBaserels(std::vector<Baserel> *Res) override { 335 Res->emplace_back(RVA + 0, IMAGE_REL_BASED_ARM_MOV32T); 336 Res->emplace_back(RVA + 22, IMAGE_REL_BASED_ARM_MOV32T); 337 } 338 339 Defined *Imp = nullptr; 340 Chunk *Desc = nullptr; 341 Defined *Helper = nullptr; 342 }; 343 344 class ThunkChunkARM64 : public Chunk { 345 public: 346 ThunkChunkARM64(Defined *I, Chunk *D, Defined *H) 347 : Imp(I), Desc(D), Helper(H) {} 348 349 size_t getSize() const override { return sizeof(ThunkARM64); } 350 351 void writeTo(uint8_t *Buf) const override { 352 memcpy(Buf, ThunkARM64, sizeof(ThunkARM64)); 353 applyArm64Addr(Buf + 0, Imp->getRVA(), RVA + 0, 12); 354 applyArm64Imm(Buf + 4, Imp->getRVA() & 0xfff, 0); 355 applyArm64Addr(Buf + 52, Desc->getRVA(), RVA + 52, 12); 356 applyArm64Imm(Buf + 56, Desc->getRVA() & 0xfff, 0); 357 applyArm64Branch26(Buf + 60, Helper->getRVA() - RVA - 60); 358 } 359 360 Defined *Imp = nullptr; 361 Chunk *Desc = nullptr; 362 Defined *Helper = nullptr; 363 }; 364 365 // A chunk for the import descriptor table. 366 class DelayAddressChunk : public Chunk { 367 public: 368 explicit DelayAddressChunk(Chunk *C) : Thunk(C) { 369 setAlignment(Config->Wordsize); 370 } 371 size_t getSize() const override { return Config->Wordsize; } 372 373 void writeTo(uint8_t *Buf) const override { 374 if (Config->is64()) { 375 write64le(Buf, Thunk->getRVA() + Config->ImageBase); 376 } else { 377 uint32_t Bit = 0; 378 // Pointer to thumb code must have the LSB set, so adjust it. 379 if (Config->Machine == ARMNT) 380 Bit = 1; 381 write32le(Buf, (Thunk->getRVA() + Config->ImageBase) | Bit); 382 } 383 } 384 385 void getBaserels(std::vector<Baserel> *Res) override { 386 Res->emplace_back(RVA); 387 } 388 389 Chunk *Thunk; 390 }; 391 392 // Export table 393 // Read Microsoft PE/COFF spec 5.3 for details. 394 395 // A chunk for the export descriptor table. 396 class ExportDirectoryChunk : public Chunk { 397 public: 398 ExportDirectoryChunk(int I, int J, Chunk *D, Chunk *A, Chunk *N, Chunk *O) 399 : MaxOrdinal(I), NameTabSize(J), DLLName(D), AddressTab(A), NameTab(N), 400 OrdinalTab(O) {} 401 402 size_t getSize() const override { 403 return sizeof(export_directory_table_entry); 404 } 405 406 void writeTo(uint8_t *Buf) const override { 407 memset(Buf, 0, getSize()); 408 409 auto *E = (export_directory_table_entry *)(Buf); 410 E->NameRVA = DLLName->getRVA(); 411 E->OrdinalBase = 0; 412 E->AddressTableEntries = MaxOrdinal + 1; 413 E->NumberOfNamePointers = NameTabSize; 414 E->ExportAddressTableRVA = AddressTab->getRVA(); 415 E->NamePointerRVA = NameTab->getRVA(); 416 E->OrdinalTableRVA = OrdinalTab->getRVA(); 417 } 418 419 uint16_t MaxOrdinal; 420 uint16_t NameTabSize; 421 Chunk *DLLName; 422 Chunk *AddressTab; 423 Chunk *NameTab; 424 Chunk *OrdinalTab; 425 }; 426 427 class AddressTableChunk : public Chunk { 428 public: 429 explicit AddressTableChunk(size_t MaxOrdinal) : Size(MaxOrdinal + 1) {} 430 size_t getSize() const override { return Size * 4; } 431 432 void writeTo(uint8_t *Buf) const override { 433 memset(Buf, 0, getSize()); 434 435 for (const Export &E : Config->Exports) { 436 uint8_t *P = Buf + E.Ordinal * 4; 437 uint32_t Bit = 0; 438 // Pointer to thumb code must have the LSB set, so adjust it. 439 if (Config->Machine == ARMNT && !E.Data) 440 Bit = 1; 441 if (E.ForwardChunk) { 442 write32le(P, E.ForwardChunk->getRVA() | Bit); 443 } else { 444 write32le(P, cast<Defined>(E.Sym)->getRVA() | Bit); 445 } 446 } 447 } 448 449 private: 450 size_t Size; 451 }; 452 453 class NamePointersChunk : public Chunk { 454 public: 455 explicit NamePointersChunk(std::vector<Chunk *> &V) : Chunks(V) {} 456 size_t getSize() const override { return Chunks.size() * 4; } 457 458 void writeTo(uint8_t *Buf) const override { 459 for (Chunk *C : Chunks) { 460 write32le(Buf, C->getRVA()); 461 Buf += 4; 462 } 463 } 464 465 private: 466 std::vector<Chunk *> Chunks; 467 }; 468 469 class ExportOrdinalChunk : public Chunk { 470 public: 471 explicit ExportOrdinalChunk(size_t I) : Size(I) {} 472 size_t getSize() const override { return Size * 2; } 473 474 void writeTo(uint8_t *Buf) const override { 475 for (Export &E : Config->Exports) { 476 if (E.Noname) 477 continue; 478 write16le(Buf, E.Ordinal); 479 Buf += 2; 480 } 481 } 482 483 private: 484 size_t Size; 485 }; 486 487 } // anonymous namespace 488 489 void IdataContents::create() { 490 std::vector<std::vector<DefinedImportData *>> V = binImports(Imports); 491 492 // Create .idata contents for each DLL. 493 for (std::vector<DefinedImportData *> &Syms : V) { 494 // Create lookup and address tables. If they have external names, 495 // we need to create HintName chunks to store the names. 496 // If they don't (if they are import-by-ordinals), we store only 497 // ordinal values to the table. 498 size_t Base = Lookups.size(); 499 for (DefinedImportData *S : Syms) { 500 uint16_t Ord = S->getOrdinal(); 501 if (S->getExternalName().empty()) { 502 Lookups.push_back(make<OrdinalOnlyChunk>(Ord)); 503 Addresses.push_back(make<OrdinalOnlyChunk>(Ord)); 504 continue; 505 } 506 auto *C = make<HintNameChunk>(S->getExternalName(), Ord); 507 Lookups.push_back(make<LookupChunk>(C)); 508 Addresses.push_back(make<LookupChunk>(C)); 509 Hints.push_back(C); 510 } 511 // Terminate with null values. 512 Lookups.push_back(make<NullChunk>(Config->Wordsize)); 513 Addresses.push_back(make<NullChunk>(Config->Wordsize)); 514 515 for (int I = 0, E = Syms.size(); I < E; ++I) 516 Syms[I]->setLocation(Addresses[Base + I]); 517 518 // Create the import table header. 519 DLLNames.push_back(make<StringChunk>(Syms[0]->getDLLName())); 520 auto *Dir = make<ImportDirectoryChunk>(DLLNames.back()); 521 Dir->LookupTab = Lookups[Base]; 522 Dir->AddressTab = Addresses[Base]; 523 Dirs.push_back(Dir); 524 } 525 // Add null terminator. 526 Dirs.push_back(make<NullChunk>(sizeof(ImportDirectoryTableEntry))); 527 } 528 529 std::vector<Chunk *> DelayLoadContents::getChunks() { 530 std::vector<Chunk *> V; 531 V.insert(V.end(), Dirs.begin(), Dirs.end()); 532 V.insert(V.end(), Names.begin(), Names.end()); 533 V.insert(V.end(), HintNames.begin(), HintNames.end()); 534 V.insert(V.end(), DLLNames.begin(), DLLNames.end()); 535 return V; 536 } 537 538 std::vector<Chunk *> DelayLoadContents::getDataChunks() { 539 std::vector<Chunk *> V; 540 V.insert(V.end(), ModuleHandles.begin(), ModuleHandles.end()); 541 V.insert(V.end(), Addresses.begin(), Addresses.end()); 542 return V; 543 } 544 545 uint64_t DelayLoadContents::getDirSize() { 546 return Dirs.size() * sizeof(delay_import_directory_table_entry); 547 } 548 549 void DelayLoadContents::create(Defined *H) { 550 Helper = H; 551 std::vector<std::vector<DefinedImportData *>> V = binImports(Imports); 552 553 // Create .didat contents for each DLL. 554 for (std::vector<DefinedImportData *> &Syms : V) { 555 // Create the delay import table header. 556 DLLNames.push_back(make<StringChunk>(Syms[0]->getDLLName())); 557 auto *Dir = make<DelayDirectoryChunk>(DLLNames.back()); 558 559 size_t Base = Addresses.size(); 560 for (DefinedImportData *S : Syms) { 561 Chunk *T = newThunkChunk(S, Dir); 562 auto *A = make<DelayAddressChunk>(T); 563 Addresses.push_back(A); 564 Thunks.push_back(T); 565 StringRef ExtName = S->getExternalName(); 566 if (ExtName.empty()) { 567 Names.push_back(make<OrdinalOnlyChunk>(S->getOrdinal())); 568 } else { 569 auto *C = make<HintNameChunk>(ExtName, 0); 570 Names.push_back(make<LookupChunk>(C)); 571 HintNames.push_back(C); 572 } 573 } 574 // Terminate with null values. 575 Addresses.push_back(make<NullChunk>(8)); 576 Names.push_back(make<NullChunk>(8)); 577 578 for (int I = 0, E = Syms.size(); I < E; ++I) 579 Syms[I]->setLocation(Addresses[Base + I]); 580 auto *MH = make<NullChunk>(8); 581 MH->setAlignment(8); 582 ModuleHandles.push_back(MH); 583 584 // Fill the delay import table header fields. 585 Dir->ModuleHandle = MH; 586 Dir->AddressTab = Addresses[Base]; 587 Dir->NameTab = Names[Base]; 588 Dirs.push_back(Dir); 589 } 590 // Add null terminator. 591 Dirs.push_back(make<NullChunk>(sizeof(delay_import_directory_table_entry))); 592 } 593 594 Chunk *DelayLoadContents::newThunkChunk(DefinedImportData *S, Chunk *Dir) { 595 switch (Config->Machine) { 596 case AMD64: 597 return make<ThunkChunkX64>(S, Dir, Helper); 598 case I386: 599 return make<ThunkChunkX86>(S, Dir, Helper); 600 case ARMNT: 601 return make<ThunkChunkARM>(S, Dir, Helper); 602 case ARM64: 603 return make<ThunkChunkARM64>(S, Dir, Helper); 604 default: 605 llvm_unreachable("unsupported machine type"); 606 } 607 } 608 609 EdataContents::EdataContents() { 610 uint16_t MaxOrdinal = 0; 611 for (Export &E : Config->Exports) 612 MaxOrdinal = std::max(MaxOrdinal, E.Ordinal); 613 614 auto *DLLName = make<StringChunk>(sys::path::filename(Config->OutputFile)); 615 auto *AddressTab = make<AddressTableChunk>(MaxOrdinal); 616 std::vector<Chunk *> Names; 617 for (Export &E : Config->Exports) 618 if (!E.Noname) 619 Names.push_back(make<StringChunk>(E.ExportName)); 620 621 std::vector<Chunk *> Forwards; 622 for (Export &E : Config->Exports) { 623 if (E.ForwardTo.empty()) 624 continue; 625 E.ForwardChunk = make<StringChunk>(E.ForwardTo); 626 Forwards.push_back(E.ForwardChunk); 627 } 628 629 auto *NameTab = make<NamePointersChunk>(Names); 630 auto *OrdinalTab = make<ExportOrdinalChunk>(Names.size()); 631 auto *Dir = make<ExportDirectoryChunk>(MaxOrdinal, Names.size(), DLLName, 632 AddressTab, NameTab, OrdinalTab); 633 Chunks.push_back(Dir); 634 Chunks.push_back(DLLName); 635 Chunks.push_back(AddressTab); 636 Chunks.push_back(NameTab); 637 Chunks.push_back(OrdinalTab); 638 Chunks.insert(Chunks.end(), Names.begin(), Names.end()); 639 Chunks.insert(Chunks.end(), Forwards.begin(), Forwards.end()); 640 } 641 642 } // namespace coff 643 } // namespace lld 644