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/ADT/STLExtras.h" 24 #include "llvm/Object/COFF.h" 25 #include "llvm/Support/Endian.h" 26 #include "llvm/Support/Path.h" 27 28 using namespace llvm; 29 using namespace llvm::object; 30 using namespace llvm::support::endian; 31 using namespace llvm::COFF; 32 using llvm::RoundUpToAlignment; 33 34 namespace lld { 35 namespace coff { 36 37 // Import table 38 39 static int ptrSize() { return Config->is64() ? 8 : 4; } 40 41 // A chunk for the import descriptor table. 42 class HintNameChunk : public Chunk { 43 public: 44 HintNameChunk(StringRef N, uint16_t H) : Name(N), Hint(H) {} 45 46 size_t getSize() const override { 47 // Starts with 2 byte Hint field, followed by a null-terminated string, 48 // ends with 0 or 1 byte padding. 49 return RoundUpToAlignment(Name.size() + 3, 2); 50 } 51 52 void writeTo(uint8_t *Buf) override { 53 write16le(Buf + FileOff, Hint); 54 memcpy(Buf + FileOff + 2, Name.data(), Name.size()); 55 } 56 57 private: 58 StringRef Name; 59 uint16_t Hint; 60 }; 61 62 // A chunk for the import descriptor table. 63 class LookupChunk : public Chunk { 64 public: 65 explicit LookupChunk(Chunk *C) : HintName(C) {} 66 size_t getSize() const override { return ptrSize(); } 67 68 void writeTo(uint8_t *Buf) override { 69 write32le(Buf + FileOff, HintName->getRVA()); 70 } 71 72 Chunk *HintName; 73 }; 74 75 // A chunk for the import descriptor table. 76 // This chunk represent import-by-ordinal symbols. 77 // See Microsoft PE/COFF spec 7.1. Import Header for details. 78 class OrdinalOnlyChunk : public Chunk { 79 public: 80 explicit OrdinalOnlyChunk(uint16_t V) : Ordinal(V) {} 81 size_t getSize() const override { return ptrSize(); } 82 83 void writeTo(uint8_t *Buf) override { 84 // An import-by-ordinal slot has MSB 1 to indicate that 85 // this is import-by-ordinal (and not import-by-name). 86 if (Config->is64()) { 87 write64le(Buf + FileOff, (1ULL << 63) | Ordinal); 88 } else { 89 write32le(Buf + FileOff, (1ULL << 31) | Ordinal); 90 } 91 } 92 93 uint16_t Ordinal; 94 }; 95 96 // A chunk for the import descriptor table. 97 class ImportDirectoryChunk : public Chunk { 98 public: 99 explicit ImportDirectoryChunk(Chunk *N) : DLLName(N) {} 100 size_t getSize() const override { return sizeof(ImportDirectoryTableEntry); } 101 102 void writeTo(uint8_t *Buf) override { 103 auto *E = (coff_import_directory_table_entry *)(Buf + FileOff); 104 E->ImportLookupTableRVA = LookupTab->getRVA(); 105 E->NameRVA = DLLName->getRVA(); 106 E->ImportAddressTableRVA = AddressTab->getRVA(); 107 } 108 109 Chunk *DLLName; 110 Chunk *LookupTab; 111 Chunk *AddressTab; 112 }; 113 114 // A chunk representing null terminator in the import table. 115 // Contents of this chunk is always null bytes. 116 class NullChunk : public Chunk { 117 public: 118 explicit NullChunk(size_t N) : Size(N) {} 119 bool hasData() const override { return false; } 120 size_t getSize() const override { return Size; } 121 void setAlign(size_t N) { Align = N; } 122 123 private: 124 size_t Size; 125 }; 126 127 uint64_t IdataContents::getDirSize() { 128 return Dirs.size() * sizeof(ImportDirectoryTableEntry); 129 } 130 131 uint64_t IdataContents::getIATSize() { 132 return Addresses.size() * ptrSize(); 133 } 134 135 // Returns a list of .idata contents. 136 // See Microsoft PE/COFF spec 5.4 for details. 137 std::vector<Chunk *> IdataContents::getChunks() { 138 create(); 139 std::vector<Chunk *> V; 140 // The loader assumes a specific order of data. 141 // Add each type in the correct order. 142 for (std::unique_ptr<Chunk> &C : Dirs) 143 V.push_back(C.get()); 144 for (std::unique_ptr<Chunk> &C : Lookups) 145 V.push_back(C.get()); 146 for (std::unique_ptr<Chunk> &C : Addresses) 147 V.push_back(C.get()); 148 for (std::unique_ptr<Chunk> &C : Hints) 149 V.push_back(C.get()); 150 for (auto &P : DLLNames) { 151 std::unique_ptr<Chunk> &C = P.second; 152 V.push_back(C.get()); 153 } 154 return V; 155 } 156 157 static std::map<StringRef, std::vector<DefinedImportData *>> 158 binImports(const std::vector<DefinedImportData *> &Imports) { 159 // Group DLL-imported symbols by DLL name because that's how 160 // symbols are layed out in the import descriptor table. 161 std::map<StringRef, std::vector<DefinedImportData *>> M; 162 for (DefinedImportData *Sym : Imports) 163 M[Sym->getDLLName()].push_back(Sym); 164 165 for (auto &P : M) { 166 // Sort symbols by name for each group. 167 std::vector<DefinedImportData *> &Syms = P.second; 168 std::sort(Syms.begin(), Syms.end(), 169 [](DefinedImportData *A, DefinedImportData *B) { 170 return A->getName() < B->getName(); 171 }); 172 } 173 return M; 174 } 175 176 void IdataContents::create() { 177 std::map<StringRef, std::vector<DefinedImportData *>> Map = 178 binImports(Imports); 179 180 // Create .idata contents for each DLL. 181 for (auto &P : Map) { 182 StringRef Name = P.first; 183 std::vector<DefinedImportData *> &Syms = P.second; 184 185 // Create lookup and address tables. If they have external names, 186 // we need to create HintName chunks to store the names. 187 // If they don't (if they are import-by-ordinals), we store only 188 // ordinal values to the table. 189 size_t Base = Lookups.size(); 190 for (DefinedImportData *S : Syms) { 191 uint16_t Ord = S->getOrdinal(); 192 if (S->getExternalName().empty()) { 193 Lookups.push_back(make_unique<OrdinalOnlyChunk>(Ord)); 194 Addresses.push_back(make_unique<OrdinalOnlyChunk>(Ord)); 195 continue; 196 } 197 auto C = make_unique<HintNameChunk>(S->getExternalName(), Ord); 198 Lookups.push_back(make_unique<LookupChunk>(C.get())); 199 Addresses.push_back(make_unique<LookupChunk>(C.get())); 200 Hints.push_back(std::move(C)); 201 } 202 // Terminate with null values. 203 Lookups.push_back(make_unique<NullChunk>(ptrSize())); 204 Addresses.push_back(make_unique<NullChunk>(ptrSize())); 205 206 for (int I = 0, E = Syms.size(); I < E; ++I) 207 Syms[I]->setLocation(Addresses[Base + I].get()); 208 209 // Create the import table header. 210 if (!DLLNames.count(Name)) 211 DLLNames[Name] = make_unique<StringChunk>(Name); 212 auto Dir = make_unique<ImportDirectoryChunk>(DLLNames[Name].get()); 213 Dir->LookupTab = Lookups[Base].get(); 214 Dir->AddressTab = Addresses[Base].get(); 215 Dirs.push_back(std::move(Dir)); 216 } 217 // Add null terminator. 218 Dirs.push_back(make_unique<NullChunk>(sizeof(ImportDirectoryTableEntry))); 219 } 220 221 // Export table 222 // See Microsoft PE/COFF spec 4.3 for details. 223 224 // A chunk for the delay import descriptor table etnry. 225 class DelayDirectoryChunk : public Chunk { 226 public: 227 explicit DelayDirectoryChunk(Chunk *N) : DLLName(N) {} 228 229 size_t getSize() const override { 230 return sizeof(delay_import_directory_table_entry); 231 } 232 233 void writeTo(uint8_t *Buf) override { 234 auto *E = (delay_import_directory_table_entry *)(Buf + FileOff); 235 E->Attributes = 1; 236 E->Name = DLLName->getRVA(); 237 E->ModuleHandle = ModuleHandle->getRVA(); 238 E->DelayImportAddressTable = AddressTab->getRVA(); 239 E->DelayImportNameTable = NameTab->getRVA(); 240 } 241 242 Chunk *DLLName; 243 Chunk *ModuleHandle; 244 Chunk *AddressTab; 245 Chunk *NameTab; 246 }; 247 248 // Initial contents for delay-loaded functions. 249 // This code calls __delayLoadHelper2 function to resolve a symbol 250 // and then overwrites its jump table slot with the result 251 // for subsequent function calls. 252 static const uint8_t Thunk[] = { 253 0x51, // push rcx 254 0x52, // push rdx 255 0x41, 0x50, // push r8 256 0x41, 0x51, // push r9 257 0x48, 0x83, 0xEC, 0x48, // sub rsp, 48h 258 0x66, 0x0F, 0x7F, 0x04, 0x24, // movdqa xmmword ptr [rsp], xmm0 259 0x66, 0x0F, 0x7F, 0x4C, 0x24, 0x10, // movdqa xmmword ptr [rsp+10h], xmm1 260 0x66, 0x0F, 0x7F, 0x54, 0x24, 0x20, // movdqa xmmword ptr [rsp+20h], xmm2 261 0x66, 0x0F, 0x7F, 0x5C, 0x24, 0x30, // movdqa xmmword ptr [rsp+30h], xmm3 262 0x48, 0x8D, 0x15, 0, 0, 0, 0, // lea rdx, [__imp_<FUNCNAME>] 263 0x48, 0x8D, 0x0D, 0, 0, 0, 0, // lea rcx, [___DELAY_IMPORT_...] 264 0xE8, 0, 0, 0, 0, // call __delayLoadHelper2 265 0x66, 0x0F, 0x6F, 0x04, 0x24, // movdqa xmm0, xmmword ptr [rsp] 266 0x66, 0x0F, 0x6F, 0x4C, 0x24, 0x10, // movdqa xmm1, xmmword ptr [rsp+10h] 267 0x66, 0x0F, 0x6F, 0x54, 0x24, 0x20, // movdqa xmm2, xmmword ptr [rsp+20h] 268 0x66, 0x0F, 0x6F, 0x5C, 0x24, 0x30, // movdqa xmm3, xmmword ptr [rsp+30h] 269 0x48, 0x83, 0xC4, 0x48, // add rsp, 48h 270 0x41, 0x59, // pop r9 271 0x41, 0x58, // pop r8 272 0x5A, // pop rdx 273 0x59, // pop rcx 274 0xFF, 0xE0, // jmp rax 275 }; 276 277 // A chunk for the delay import thunk. 278 class ThunkChunk : public Chunk { 279 public: 280 ThunkChunk(Defined *I, Chunk *D, Defined *H) : Imp(I), Desc(D), Helper(H) {} 281 size_t getSize() const override { return sizeof(Thunk); } 282 283 void writeTo(uint8_t *Buf) override { 284 memcpy(Buf + FileOff, Thunk, sizeof(Thunk)); 285 write32le(Buf + FileOff + 36, Imp->getRVA() - RVA - 40); 286 write32le(Buf + FileOff + 43, Desc->getRVA() - RVA - 47); 287 write32le(Buf + FileOff + 48, Helper->getRVA() - RVA - 52); 288 } 289 290 Defined *Imp = nullptr; 291 Chunk *Desc = nullptr; 292 Defined *Helper = nullptr; 293 }; 294 295 std::vector<Chunk *> DelayLoadContents::getChunks() { 296 std::vector<Chunk *> V; 297 for (std::unique_ptr<Chunk> &C : Dirs) 298 V.push_back(C.get()); 299 for (std::unique_ptr<Chunk> &C : Names) 300 V.push_back(C.get()); 301 for (std::unique_ptr<Chunk> &C : HintNames) 302 V.push_back(C.get()); 303 for (auto &P : DLLNames) { 304 std::unique_ptr<Chunk> &C = P.second; 305 V.push_back(C.get()); 306 } 307 return V; 308 } 309 310 std::vector<Chunk *> DelayLoadContents::getDataChunks() { 311 std::vector<Chunk *> V; 312 for (std::unique_ptr<Chunk> &C : ModuleHandles) 313 V.push_back(C.get()); 314 for (std::unique_ptr<Chunk> &C : Addresses) 315 V.push_back(C.get()); 316 return V; 317 } 318 319 uint64_t DelayLoadContents::getDirSize() { 320 return Dirs.size() * sizeof(delay_import_directory_table_entry); 321 } 322 323 // A chunk for the import descriptor table. 324 class DelayAddressChunk : public Chunk { 325 public: 326 explicit DelayAddressChunk(Chunk *C) : Thunk(C) {} 327 size_t getSize() const override { return 8; } 328 329 void writeTo(uint8_t *Buf) override { 330 write64le(Buf + FileOff, Thunk->getRVA() + Config->ImageBase); 331 } 332 333 void getBaserels(std::vector<uint32_t> *Res, Defined *ImageBase) override { 334 Res->push_back(RVA); 335 } 336 337 Chunk *Thunk; 338 }; 339 340 void DelayLoadContents::create(Defined *H) { 341 Helper = H; 342 std::map<StringRef, std::vector<DefinedImportData *>> Map = 343 binImports(Imports); 344 345 // Create .didat contents for each DLL. 346 for (auto &P : Map) { 347 StringRef Name = P.first; 348 std::vector<DefinedImportData *> &Syms = P.second; 349 350 // Create the delay import table header. 351 if (!DLLNames.count(Name)) 352 DLLNames[Name] = make_unique<StringChunk>(Name); 353 auto Dir = make_unique<DelayDirectoryChunk>(DLLNames[Name].get()); 354 355 size_t Base = Addresses.size(); 356 for (DefinedImportData *S : Syms) { 357 auto T = make_unique<ThunkChunk>(S, Dir.get(), Helper); 358 auto A = make_unique<DelayAddressChunk>(T.get()); 359 Addresses.push_back(std::move(A)); 360 Thunks.push_back(std::move(T)); 361 StringRef ExtName = S->getExternalName(); 362 if (ExtName.empty()) { 363 Names.push_back(make_unique<OrdinalOnlyChunk>(S->getOrdinal())); 364 } else { 365 auto C = make_unique<HintNameChunk>(ExtName, 0); 366 Names.push_back(make_unique<LookupChunk>(C.get())); 367 HintNames.push_back(std::move(C)); 368 } 369 } 370 // Terminate with null values. 371 Addresses.push_back(make_unique<NullChunk>(8)); 372 Names.push_back(make_unique<NullChunk>(8)); 373 374 for (int I = 0, E = Syms.size(); I < E; ++I) 375 Syms[I]->setLocation(Addresses[Base + I].get()); 376 auto *MH = new NullChunk(8); 377 MH->setAlign(8); 378 ModuleHandles.push_back(std::unique_ptr<Chunk>(MH)); 379 380 // Fill the delay import table header fields. 381 Dir->ModuleHandle = MH; 382 Dir->AddressTab = Addresses[Base].get(); 383 Dir->NameTab = Names[Base].get(); 384 Dirs.push_back(std::move(Dir)); 385 } 386 // Add null terminator. 387 Dirs.push_back( 388 make_unique<NullChunk>(sizeof(delay_import_directory_table_entry))); 389 } 390 391 // Export table 392 // Read Microsoft PE/COFF spec 5.3 for details. 393 394 // A chunk for the export descriptor table. 395 class ExportDirectoryChunk : public Chunk { 396 public: 397 ExportDirectoryChunk(int I, int J, Chunk *D, Chunk *A, Chunk *N, Chunk *O) 398 : MaxOrdinal(I), NameTabSize(J), DLLName(D), AddressTab(A), NameTab(N), 399 OrdinalTab(O) {} 400 401 size_t getSize() const override { 402 return sizeof(export_directory_table_entry); 403 } 404 405 void writeTo(uint8_t *Buf) override { 406 auto *E = (export_directory_table_entry *)(Buf + FileOff); 407 E->NameRVA = DLLName->getRVA(); 408 E->OrdinalBase = 0; 409 E->AddressTableEntries = MaxOrdinal + 1; 410 E->NumberOfNamePointers = NameTabSize; 411 E->ExportAddressTableRVA = AddressTab->getRVA(); 412 E->NamePointerRVA = NameTab->getRVA(); 413 E->OrdinalTableRVA = OrdinalTab->getRVA(); 414 } 415 416 uint16_t MaxOrdinal; 417 uint16_t NameTabSize; 418 Chunk *DLLName; 419 Chunk *AddressTab; 420 Chunk *NameTab; 421 Chunk *OrdinalTab; 422 }; 423 424 class AddressTableChunk : public Chunk { 425 public: 426 explicit AddressTableChunk(size_t MaxOrdinal) : Size(MaxOrdinal + 1) {} 427 size_t getSize() const override { return Size * 4; } 428 429 void writeTo(uint8_t *Buf) override { 430 for (Export &E : Config->Exports) { 431 auto *D = cast<Defined>(E.Sym->repl()); 432 write32le(Buf + FileOff + E.Ordinal * 4, D->getRVA()); 433 } 434 } 435 436 private: 437 size_t Size; 438 }; 439 440 class NamePointersChunk : public Chunk { 441 public: 442 explicit NamePointersChunk(std::vector<Chunk *> &V) : Chunks(V) {} 443 size_t getSize() const override { return Chunks.size() * 4; } 444 445 void writeTo(uint8_t *Buf) override { 446 uint8_t *P = Buf + FileOff; 447 for (Chunk *C : Chunks) { 448 write32le(P, C->getRVA()); 449 P += 4; 450 } 451 } 452 453 private: 454 std::vector<Chunk *> Chunks; 455 }; 456 457 class ExportOrdinalChunk : public Chunk { 458 public: 459 explicit ExportOrdinalChunk(size_t I) : Size(I) {} 460 size_t getSize() const override { return Size * 2; } 461 462 void writeTo(uint8_t *Buf) override { 463 uint8_t *P = Buf + FileOff; 464 for (Export &E : Config->Exports) { 465 if (E.Noname) 466 continue; 467 write16le(P, E.Ordinal); 468 P += 2; 469 } 470 } 471 472 private: 473 size_t Size; 474 }; 475 476 EdataContents::EdataContents() { 477 uint16_t MaxOrdinal = 0; 478 for (Export &E : Config->Exports) 479 MaxOrdinal = std::max(MaxOrdinal, E.Ordinal); 480 481 auto *DLLName = new StringChunk(sys::path::filename(Config->OutputFile)); 482 auto *AddressTab = new AddressTableChunk(MaxOrdinal); 483 std::vector<Chunk *> Names; 484 for (Export &E : Config->Exports) 485 if (!E.Noname) 486 Names.push_back(new StringChunk(E.ExtName)); 487 auto *NameTab = new NamePointersChunk(Names); 488 auto *OrdinalTab = new ExportOrdinalChunk(Names.size()); 489 auto *Dir = new ExportDirectoryChunk(MaxOrdinal, Names.size(), DLLName, 490 AddressTab, NameTab, OrdinalTab); 491 Chunks.push_back(std::unique_ptr<Chunk>(Dir)); 492 Chunks.push_back(std::unique_ptr<Chunk>(DLLName)); 493 Chunks.push_back(std::unique_ptr<Chunk>(AddressTab)); 494 Chunks.push_back(std::unique_ptr<Chunk>(NameTab)); 495 Chunks.push_back(std::unique_ptr<Chunk>(OrdinalTab)); 496 for (Chunk *C : Names) 497 Chunks.push_back(std::unique_ptr<Chunk>(C)); 498 } 499 500 } // namespace coff 501 } // namespace lld 502