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