1 //===- Chunks.h -------------------------------------------------*- C++ -*-===// 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 #ifndef LLD_COFF_CHUNKS_H 10 #define LLD_COFF_CHUNKS_H 11 12 #include "Config.h" 13 #include "InputFiles.h" 14 #include "lld/Common/LLVM.h" 15 #include "llvm/ADT/ArrayRef.h" 16 #include "llvm/ADT/PointerIntPair.h" 17 #include "llvm/ADT/iterator.h" 18 #include "llvm/ADT/iterator_range.h" 19 #include "llvm/MC/StringTableBuilder.h" 20 #include "llvm/Object/COFF.h" 21 #include "llvm/Object/WindowsMachineFlag.h" 22 #include <utility> 23 #include <vector> 24 25 namespace lld::coff { 26 27 using llvm::COFF::ImportDirectoryTableEntry; 28 using llvm::object::chpe_range_type; 29 using llvm::object::coff_relocation; 30 using llvm::object::coff_section; 31 using llvm::object::COFFSymbolRef; 32 using llvm::object::SectionRef; 33 34 class Baserel; 35 class Defined; 36 class DefinedImportData; 37 class DefinedRegular; 38 class ObjFile; 39 class OutputSection; 40 class RuntimePseudoReloc; 41 class Symbol; 42 43 // Mask for permissions (discardable, writable, readable, executable, etc). 44 const uint32_t permMask = 0xFE000000; 45 46 // Mask for section types (code, data, bss). 47 const uint32_t typeMask = 0x000000E0; 48 49 // The log base 2 of the largest section alignment, which is log2(8192), or 13. 50 enum : unsigned { Log2MaxSectionAlignment = 13 }; 51 52 // A Chunk represents a chunk of data that will occupy space in the 53 // output (if the resolver chose that). It may or may not be backed by 54 // a section of an input file. It could be linker-created data, or 55 // doesn't even have actual data (if common or bss). 56 class Chunk { 57 public: 58 enum Kind : uint8_t { 59 SectionKind, 60 SectionECKind, 61 OtherKind, 62 ImportThunkKind 63 }; 64 Kind kind() const { return chunkKind; } 65 66 // Returns the size of this chunk (even if this is a common or BSS.) 67 size_t getSize() const; 68 69 // Returns chunk alignment in power of two form. Value values are powers of 70 // two from 1 to 8192. 71 uint32_t getAlignment() const { return 1U << p2Align; } 72 73 // Update the chunk section alignment measured in bytes. Internally alignment 74 // is stored in log2. 75 void setAlignment(uint32_t align) { 76 // Treat zero byte alignment as 1 byte alignment. 77 align = align ? align : 1; 78 assert(llvm::isPowerOf2_32(align) && "alignment is not a power of 2"); 79 p2Align = llvm::Log2_32(align); 80 assert(p2Align <= Log2MaxSectionAlignment && 81 "impossible requested alignment"); 82 } 83 84 // Write this chunk to a mmap'ed file, assuming Buf is pointing to 85 // beginning of the file. Because this function may use RVA values 86 // of other chunks for relocations, you need to set them properly 87 // before calling this function. 88 void writeTo(uint8_t *buf) const; 89 90 // The writer sets and uses the addresses. In practice, PE images cannot be 91 // larger than 2GB. Chunks are always laid as part of the image, so Chunk RVAs 92 // can be stored with 32 bits. 93 uint32_t getRVA() const { return rva; } 94 void setRVA(uint64_t v) { 95 // This may truncate. The writer checks for overflow later. 96 rva = (uint32_t)v; 97 } 98 99 // Returns readable/writable/executable bits. 100 uint32_t getOutputCharacteristics() const; 101 102 // Returns the section name if this is a section chunk. 103 // It is illegal to call this function on non-section chunks. 104 StringRef getSectionName() const; 105 106 // An output section has pointers to chunks in the section, and each 107 // chunk has a back pointer to an output section. 108 void setOutputSectionIdx(uint16_t o) { osidx = o; } 109 uint16_t getOutputSectionIdx() const { return osidx; } 110 111 // Windows-specific. 112 // Collect all locations that contain absolute addresses for base relocations. 113 void getBaserels(std::vector<Baserel> *res); 114 115 // Returns a human-readable name of this chunk. Chunks are unnamed chunks of 116 // bytes, so this is used only for logging or debugging. 117 StringRef getDebugName() const; 118 119 // Return true if this file has the hotpatch flag set to true in the 120 // S_COMPILE3 record in codeview debug info. Also returns true for some thunks 121 // synthesized by the linker. 122 bool isHotPatchable() const; 123 124 MachineTypes getMachine() const; 125 llvm::Triple::ArchType getArch() const; 126 std::optional<chpe_range_type> getArm64ECRangeType() const; 127 128 // ARM64EC entry thunk associated with the chunk. 129 Defined *getEntryThunk() const; 130 void setEntryThunk(Defined *entryThunk); 131 132 protected: 133 Chunk(Kind k = OtherKind) : chunkKind(k), hasData(true), p2Align(0) {} 134 135 const Kind chunkKind; 136 137 public: 138 // Returns true if this has non-zero data. BSS chunks return 139 // false. If false is returned, the space occupied by this chunk 140 // will be filled with zeros. Corresponds to the 141 // IMAGE_SCN_CNT_UNINITIALIZED_DATA section characteristic bit. 142 uint8_t hasData : 1; 143 144 public: 145 // The alignment of this chunk, stored in log2 form. The writer uses the 146 // value. 147 uint8_t p2Align : 7; 148 149 // The output section index for this chunk. The first valid section number is 150 // one. 151 uint16_t osidx = 0; 152 153 // The RVA of this chunk in the output. The writer sets a value. 154 uint32_t rva = 0; 155 }; 156 157 class NonSectionChunk : public Chunk { 158 public: 159 virtual ~NonSectionChunk() = default; 160 161 // Returns the size of this chunk (even if this is a common or BSS.) 162 virtual size_t getSize() const = 0; 163 164 virtual uint32_t getOutputCharacteristics() const { return 0; } 165 166 // Write this chunk to a mmap'ed file, assuming Buf is pointing to 167 // beginning of the file. Because this function may use RVA values 168 // of other chunks for relocations, you need to set them properly 169 // before calling this function. 170 virtual void writeTo(uint8_t *buf) const {} 171 172 // Returns the section name if this is a section chunk. 173 // It is illegal to call this function on non-section chunks. 174 virtual StringRef getSectionName() const { 175 llvm_unreachable("unimplemented getSectionName"); 176 } 177 178 // Windows-specific. 179 // Collect all locations that contain absolute addresses for base relocations. 180 virtual void getBaserels(std::vector<Baserel> *res) {} 181 182 virtual MachineTypes getMachine() const { return IMAGE_FILE_MACHINE_UNKNOWN; } 183 184 // Returns a human-readable name of this chunk. Chunks are unnamed chunks of 185 // bytes, so this is used only for logging or debugging. 186 virtual StringRef getDebugName() const { return ""; } 187 188 static bool classof(const Chunk *c) { return c->kind() >= OtherKind; } 189 190 protected: 191 NonSectionChunk(Kind k = OtherKind) : Chunk(k) {} 192 }; 193 194 class NonSectionCodeChunk : public NonSectionChunk { 195 public: 196 virtual uint32_t getOutputCharacteristics() const override { 197 return llvm::COFF::IMAGE_SCN_MEM_READ | llvm::COFF::IMAGE_SCN_MEM_EXECUTE; 198 } 199 200 protected: 201 NonSectionCodeChunk(Kind k = OtherKind) : NonSectionChunk(k) {} 202 }; 203 204 // MinGW specific; information about one individual location in the image 205 // that needs to be fixed up at runtime after loading. This represents 206 // one individual element in the PseudoRelocTableChunk table. 207 class RuntimePseudoReloc { 208 public: 209 RuntimePseudoReloc(Defined *sym, SectionChunk *target, uint32_t targetOffset, 210 int flags) 211 : sym(sym), target(target), targetOffset(targetOffset), flags(flags) {} 212 213 Defined *sym; 214 SectionChunk *target; 215 uint32_t targetOffset; 216 // The Flags field contains the size of the relocation, in bits. No other 217 // flags are currently defined. 218 int flags; 219 }; 220 221 // A chunk corresponding a section of an input file. 222 class SectionChunk : public Chunk { 223 // Identical COMDAT Folding feature accesses section internal data. 224 friend class ICF; 225 226 public: 227 class symbol_iterator : public llvm::iterator_adaptor_base< 228 symbol_iterator, const coff_relocation *, 229 std::random_access_iterator_tag, Symbol *> { 230 friend SectionChunk; 231 232 ObjFile *file; 233 234 symbol_iterator(ObjFile *file, const coff_relocation *i) 235 : symbol_iterator::iterator_adaptor_base(i), file(file) {} 236 237 public: 238 symbol_iterator() = default; 239 240 Symbol *operator*() const { return file->getSymbol(I->SymbolTableIndex); } 241 }; 242 243 SectionChunk(ObjFile *file, const coff_section *header, Kind k = SectionKind); 244 static bool classof(const Chunk *c) { return c->kind() <= SectionECKind; } 245 size_t getSize() const { return header->SizeOfRawData; } 246 ArrayRef<uint8_t> getContents() const; 247 void writeTo(uint8_t *buf) const; 248 249 MachineTypes getMachine() const { return file->getMachineType(); } 250 251 // Defend against unsorted relocations. This may be overly conservative. 252 void sortRelocations(); 253 254 // Write and relocate a portion of the section. This is intended to be called 255 // in a loop. Relocations must be sorted first. 256 void writeAndRelocateSubsection(ArrayRef<uint8_t> sec, 257 ArrayRef<uint8_t> subsec, 258 uint32_t &nextRelocIndex, uint8_t *buf) const; 259 260 uint32_t getOutputCharacteristics() const { 261 return header->Characteristics & (permMask | typeMask); 262 } 263 StringRef getSectionName() const { 264 return StringRef(sectionNameData, sectionNameSize); 265 } 266 void getBaserels(std::vector<Baserel> *res); 267 bool isCOMDAT() const; 268 void applyRelocation(uint8_t *off, const coff_relocation &rel) const; 269 void applyRelX64(uint8_t *off, uint16_t type, OutputSection *os, uint64_t s, 270 uint64_t p, uint64_t imageBase) const; 271 void applyRelX86(uint8_t *off, uint16_t type, OutputSection *os, uint64_t s, 272 uint64_t p, uint64_t imageBase) const; 273 void applyRelARM(uint8_t *off, uint16_t type, OutputSection *os, uint64_t s, 274 uint64_t p, uint64_t imageBase) const; 275 void applyRelARM64(uint8_t *off, uint16_t type, OutputSection *os, uint64_t s, 276 uint64_t p, uint64_t imageBase) const; 277 278 void getRuntimePseudoRelocs(std::vector<RuntimePseudoReloc> &res); 279 280 // Called if the garbage collector decides to not include this chunk 281 // in a final output. It's supposed to print out a log message to stdout. 282 void printDiscardedMessage() const; 283 284 // Adds COMDAT associative sections to this COMDAT section. A chunk 285 // and its children are treated as a group by the garbage collector. 286 void addAssociative(SectionChunk *child); 287 288 StringRef getDebugName() const; 289 290 // True if this is a codeview debug info chunk. These will not be laid out in 291 // the image. Instead they will end up in the PDB, if one is requested. 292 bool isCodeView() const { 293 return getSectionName() == ".debug" || getSectionName().starts_with(".debug$"); 294 } 295 296 // True if this is a DWARF debug info or exception handling chunk. 297 bool isDWARF() const { 298 return getSectionName().starts_with(".debug_") || getSectionName() == ".eh_frame"; 299 } 300 301 // Allow iteration over the bodies of this chunk's relocated symbols. 302 llvm::iterator_range<symbol_iterator> symbols() const { 303 return llvm::make_range(symbol_iterator(file, relocsData), 304 symbol_iterator(file, relocsData + relocsSize)); 305 } 306 307 ArrayRef<coff_relocation> getRelocs() const { 308 return llvm::ArrayRef(relocsData, relocsSize); 309 } 310 311 // Reloc setter used by ARM range extension thunk insertion. 312 void setRelocs(ArrayRef<coff_relocation> newRelocs) { 313 relocsData = newRelocs.data(); 314 relocsSize = newRelocs.size(); 315 assert(relocsSize == newRelocs.size() && "reloc size truncation"); 316 } 317 318 // Single linked list iterator for associated comdat children. 319 class AssociatedIterator 320 : public llvm::iterator_facade_base< 321 AssociatedIterator, std::forward_iterator_tag, SectionChunk> { 322 public: 323 AssociatedIterator() = default; 324 AssociatedIterator(SectionChunk *head) : cur(head) {} 325 bool operator==(const AssociatedIterator &r) const { return cur == r.cur; } 326 // FIXME: Wrong const-ness, but it makes filter ranges work. 327 SectionChunk &operator*() const { return *cur; } 328 SectionChunk &operator*() { return *cur; } 329 AssociatedIterator &operator++() { 330 cur = cur->assocChildren; 331 return *this; 332 } 333 334 private: 335 SectionChunk *cur = nullptr; 336 }; 337 338 // Allow iteration over the associated child chunks for this section. 339 llvm::iterator_range<AssociatedIterator> children() const { 340 // Associated sections do not have children. The assocChildren field is 341 // part of the parent's list of children. 342 bool isAssoc = selection == llvm::COFF::IMAGE_COMDAT_SELECT_ASSOCIATIVE; 343 return llvm::make_range( 344 AssociatedIterator(isAssoc ? nullptr : assocChildren), 345 AssociatedIterator(nullptr)); 346 } 347 348 // The section ID this chunk belongs to in its Obj. 349 uint32_t getSectionNumber() const; 350 351 ArrayRef<uint8_t> consumeDebugMagic(); 352 353 static ArrayRef<uint8_t> consumeDebugMagic(ArrayRef<uint8_t> data, 354 StringRef sectionName); 355 356 static SectionChunk *findByName(ArrayRef<SectionChunk *> sections, 357 StringRef name); 358 359 // The file that this chunk was created from. 360 ObjFile *file; 361 362 // Pointer to the COFF section header in the input file. 363 const coff_section *header; 364 365 // The COMDAT leader symbol if this is a COMDAT chunk. 366 DefinedRegular *sym = nullptr; 367 368 // The CRC of the contents as described in the COFF spec 4.5.5. 369 // Auxiliary Format 5: Section Definitions. Used for ICF. 370 uint32_t checksum = 0; 371 372 // Used by the garbage collector. 373 bool live; 374 375 // Whether this section needs to be kept distinct from other sections during 376 // ICF. This is set by the driver using address-significance tables. 377 bool keepUnique = false; 378 379 // The COMDAT selection if this is a COMDAT chunk. 380 llvm::COFF::COMDATType selection = (llvm::COFF::COMDATType)0; 381 382 // A pointer pointing to a replacement for this chunk. 383 // Initially it points to "this" object. If this chunk is merged 384 // with other chunk by ICF, it points to another chunk, 385 // and this chunk is considered as dead. 386 SectionChunk *repl; 387 388 private: 389 SectionChunk *assocChildren = nullptr; 390 391 // Used for ICF (Identical COMDAT Folding) 392 void replace(SectionChunk *other); 393 uint32_t eqClass[2] = {0, 0}; 394 395 // Relocations for this section. Size is stored below. 396 const coff_relocation *relocsData; 397 398 // Section name string. Size is stored below. 399 const char *sectionNameData; 400 401 uint32_t relocsSize = 0; 402 uint32_t sectionNameSize = 0; 403 }; 404 405 // A section chunk corresponding a section of an EC input file. 406 class SectionChunkEC final : public SectionChunk { 407 public: 408 static bool classof(const Chunk *c) { return c->kind() == SectionECKind; } 409 410 SectionChunkEC(ObjFile *file, const coff_section *header) 411 : SectionChunk(file, header, SectionECKind) {} 412 Defined *entryThunk = nullptr; 413 }; 414 415 // Inline methods to implement faux-virtual dispatch for SectionChunk. 416 417 inline size_t Chunk::getSize() const { 418 if (isa<SectionChunk>(this)) 419 return static_cast<const SectionChunk *>(this)->getSize(); 420 return static_cast<const NonSectionChunk *>(this)->getSize(); 421 } 422 423 inline uint32_t Chunk::getOutputCharacteristics() const { 424 if (isa<SectionChunk>(this)) 425 return static_cast<const SectionChunk *>(this)->getOutputCharacteristics(); 426 return static_cast<const NonSectionChunk *>(this)->getOutputCharacteristics(); 427 } 428 429 inline void Chunk::writeTo(uint8_t *buf) const { 430 if (isa<SectionChunk>(this)) 431 static_cast<const SectionChunk *>(this)->writeTo(buf); 432 else 433 static_cast<const NonSectionChunk *>(this)->writeTo(buf); 434 } 435 436 inline StringRef Chunk::getSectionName() const { 437 if (isa<SectionChunk>(this)) 438 return static_cast<const SectionChunk *>(this)->getSectionName(); 439 return static_cast<const NonSectionChunk *>(this)->getSectionName(); 440 } 441 442 inline void Chunk::getBaserels(std::vector<Baserel> *res) { 443 if (isa<SectionChunk>(this)) 444 static_cast<SectionChunk *>(this)->getBaserels(res); 445 else 446 static_cast<NonSectionChunk *>(this)->getBaserels(res); 447 } 448 449 inline StringRef Chunk::getDebugName() const { 450 if (isa<SectionChunk>(this)) 451 return static_cast<const SectionChunk *>(this)->getDebugName(); 452 return static_cast<const NonSectionChunk *>(this)->getDebugName(); 453 } 454 455 inline MachineTypes Chunk::getMachine() const { 456 if (isa<SectionChunk>(this)) 457 return static_cast<const SectionChunk *>(this)->getMachine(); 458 return static_cast<const NonSectionChunk *>(this)->getMachine(); 459 } 460 461 inline llvm::Triple::ArchType Chunk::getArch() const { 462 return llvm::getMachineArchType(getMachine()); 463 } 464 465 inline std::optional<chpe_range_type> Chunk::getArm64ECRangeType() const { 466 // Data sections don't need codemap entries. 467 if (!(getOutputCharacteristics() & llvm::COFF::IMAGE_SCN_MEM_EXECUTE)) 468 return std::nullopt; 469 470 switch (getMachine()) { 471 case AMD64: 472 return chpe_range_type::Amd64; 473 case ARM64EC: 474 return chpe_range_type::Arm64EC; 475 default: 476 return chpe_range_type::Arm64; 477 } 478 } 479 480 // This class is used to implement an lld-specific feature (not implemented in 481 // MSVC) that minimizes the output size by finding string literals sharing tail 482 // parts and merging them. 483 // 484 // If string tail merging is enabled and a section is identified as containing a 485 // string literal, it is added to a MergeChunk with an appropriate alignment. 486 // The MergeChunk then tail merges the strings using the StringTableBuilder 487 // class and assigns RVAs and section offsets to each of the member chunks based 488 // on the offsets assigned by the StringTableBuilder. 489 class MergeChunk : public NonSectionChunk { 490 public: 491 MergeChunk(uint32_t alignment); 492 static void addSection(COFFLinkerContext &ctx, SectionChunk *c); 493 void finalizeContents(); 494 void assignSubsectionRVAs(); 495 496 uint32_t getOutputCharacteristics() const override; 497 StringRef getSectionName() const override { return ".rdata"; } 498 size_t getSize() const override; 499 void writeTo(uint8_t *buf) const override; 500 501 std::vector<SectionChunk *> sections; 502 503 private: 504 llvm::StringTableBuilder builder; 505 bool finalized = false; 506 }; 507 508 // A chunk for common symbols. Common chunks don't have actual data. 509 class CommonChunk : public NonSectionChunk { 510 public: 511 CommonChunk(const COFFSymbolRef sym); 512 size_t getSize() const override { return sym.getValue(); } 513 uint32_t getOutputCharacteristics() const override; 514 StringRef getSectionName() const override { return ".bss"; } 515 516 private: 517 const COFFSymbolRef sym; 518 }; 519 520 // A chunk for linker-created strings. 521 class StringChunk : public NonSectionChunk { 522 public: 523 explicit StringChunk(StringRef s) : str(s) {} 524 size_t getSize() const override { return str.size() + 1; } 525 void writeTo(uint8_t *buf) const override; 526 527 private: 528 StringRef str; 529 }; 530 531 static const uint8_t importThunkX86[] = { 532 0xff, 0x25, 0x00, 0x00, 0x00, 0x00, // JMP *0x0 533 }; 534 535 static const uint8_t importThunkARM[] = { 536 0x40, 0xf2, 0x00, 0x0c, // mov.w ip, #0 537 0xc0, 0xf2, 0x00, 0x0c, // mov.t ip, #0 538 0xdc, 0xf8, 0x00, 0xf0, // ldr.w pc, [ip] 539 }; 540 541 static const uint8_t importThunkARM64[] = { 542 0x10, 0x00, 0x00, 0x90, // adrp x16, #0 543 0x10, 0x02, 0x40, 0xf9, // ldr x16, [x16] 544 0x00, 0x02, 0x1f, 0xd6, // br x16 545 }; 546 547 // Windows-specific. 548 // A chunk for DLL import jump table entry. In a final output, its 549 // contents will be a JMP instruction to some __imp_ symbol. 550 class ImportThunkChunk : public NonSectionCodeChunk { 551 public: 552 ImportThunkChunk(COFFLinkerContext &ctx, Defined *s) 553 : NonSectionCodeChunk(ImportThunkKind), impSymbol(s), ctx(ctx) {} 554 static bool classof(const Chunk *c) { return c->kind() == ImportThunkKind; } 555 556 protected: 557 Defined *impSymbol; 558 COFFLinkerContext &ctx; 559 }; 560 561 class ImportThunkChunkX64 : public ImportThunkChunk { 562 public: 563 explicit ImportThunkChunkX64(COFFLinkerContext &ctx, Defined *s); 564 size_t getSize() const override { return sizeof(importThunkX86); } 565 void writeTo(uint8_t *buf) const override; 566 MachineTypes getMachine() const override { return AMD64; } 567 }; 568 569 class ImportThunkChunkX86 : public ImportThunkChunk { 570 public: 571 explicit ImportThunkChunkX86(COFFLinkerContext &ctx, Defined *s) 572 : ImportThunkChunk(ctx, s) {} 573 size_t getSize() const override { return sizeof(importThunkX86); } 574 void getBaserels(std::vector<Baserel> *res) override; 575 void writeTo(uint8_t *buf) const override; 576 MachineTypes getMachine() const override { return I386; } 577 }; 578 579 class ImportThunkChunkARM : public ImportThunkChunk { 580 public: 581 explicit ImportThunkChunkARM(COFFLinkerContext &ctx, Defined *s) 582 : ImportThunkChunk(ctx, s) { 583 setAlignment(2); 584 } 585 size_t getSize() const override { return sizeof(importThunkARM); } 586 void getBaserels(std::vector<Baserel> *res) override; 587 void writeTo(uint8_t *buf) const override; 588 MachineTypes getMachine() const override { return ARMNT; } 589 }; 590 591 class ImportThunkChunkARM64 : public ImportThunkChunk { 592 public: 593 explicit ImportThunkChunkARM64(COFFLinkerContext &ctx, Defined *s) 594 : ImportThunkChunk(ctx, s) { 595 setAlignment(4); 596 } 597 size_t getSize() const override { return sizeof(importThunkARM64); } 598 void writeTo(uint8_t *buf) const override; 599 MachineTypes getMachine() const override { return ARM64; } 600 }; 601 602 class RangeExtensionThunkARM : public NonSectionCodeChunk { 603 public: 604 explicit RangeExtensionThunkARM(COFFLinkerContext &ctx, Defined *t) 605 : target(t), ctx(ctx) { 606 setAlignment(2); 607 } 608 size_t getSize() const override; 609 void writeTo(uint8_t *buf) const override; 610 MachineTypes getMachine() const override { return ARMNT; } 611 612 Defined *target; 613 614 private: 615 COFFLinkerContext &ctx; 616 }; 617 618 class RangeExtensionThunkARM64 : public NonSectionCodeChunk { 619 public: 620 explicit RangeExtensionThunkARM64(COFFLinkerContext &ctx, Defined *t) 621 : target(t), ctx(ctx) { 622 setAlignment(4); 623 } 624 size_t getSize() const override; 625 void writeTo(uint8_t *buf) const override; 626 MachineTypes getMachine() const override { return ARM64; } 627 628 Defined *target; 629 630 private: 631 COFFLinkerContext &ctx; 632 }; 633 634 // Windows-specific. 635 // See comments for DefinedLocalImport class. 636 class LocalImportChunk : public NonSectionChunk { 637 public: 638 explicit LocalImportChunk(COFFLinkerContext &ctx, Defined *s); 639 size_t getSize() const override; 640 void getBaserels(std::vector<Baserel> *res) override; 641 void writeTo(uint8_t *buf) const override; 642 643 private: 644 Defined *sym; 645 COFFLinkerContext &ctx; 646 }; 647 648 // Duplicate RVAs are not allowed in RVA tables, so unique symbols by chunk and 649 // offset into the chunk. Order does not matter as the RVA table will be sorted 650 // later. 651 struct ChunkAndOffset { 652 Chunk *inputChunk; 653 uint32_t offset; 654 655 struct DenseMapInfo { 656 static ChunkAndOffset getEmptyKey() { 657 return {llvm::DenseMapInfo<Chunk *>::getEmptyKey(), 0}; 658 } 659 static ChunkAndOffset getTombstoneKey() { 660 return {llvm::DenseMapInfo<Chunk *>::getTombstoneKey(), 0}; 661 } 662 static unsigned getHashValue(const ChunkAndOffset &co) { 663 return llvm::DenseMapInfo<std::pair<Chunk *, uint32_t>>::getHashValue( 664 {co.inputChunk, co.offset}); 665 } 666 static bool isEqual(const ChunkAndOffset &lhs, const ChunkAndOffset &rhs) { 667 return lhs.inputChunk == rhs.inputChunk && lhs.offset == rhs.offset; 668 } 669 }; 670 }; 671 672 using SymbolRVASet = llvm::DenseSet<ChunkAndOffset>; 673 674 // Table which contains symbol RVAs. Used for /safeseh and /guard:cf. 675 class RVATableChunk : public NonSectionChunk { 676 public: 677 explicit RVATableChunk(SymbolRVASet s) : syms(std::move(s)) {} 678 size_t getSize() const override { return syms.size() * 4; } 679 void writeTo(uint8_t *buf) const override; 680 681 private: 682 SymbolRVASet syms; 683 }; 684 685 // Table which contains symbol RVAs with flags. Used for /guard:ehcont. 686 class RVAFlagTableChunk : public NonSectionChunk { 687 public: 688 explicit RVAFlagTableChunk(SymbolRVASet s) : syms(std::move(s)) {} 689 size_t getSize() const override { return syms.size() * 5; } 690 void writeTo(uint8_t *buf) const override; 691 692 private: 693 SymbolRVASet syms; 694 }; 695 696 // Windows-specific. 697 // This class represents a block in .reloc section. 698 // See the PE/COFF spec 5.6 for details. 699 class BaserelChunk : public NonSectionChunk { 700 public: 701 BaserelChunk(uint32_t page, Baserel *begin, Baserel *end); 702 size_t getSize() const override { return data.size(); } 703 void writeTo(uint8_t *buf) const override; 704 705 private: 706 std::vector<uint8_t> data; 707 }; 708 709 class Baserel { 710 public: 711 Baserel(uint32_t v, uint8_t ty) : rva(v), type(ty) {} 712 explicit Baserel(uint32_t v, llvm::COFF::MachineTypes machine) 713 : Baserel(v, getDefaultType(machine)) {} 714 uint8_t getDefaultType(llvm::COFF::MachineTypes machine); 715 716 uint32_t rva; 717 uint8_t type; 718 }; 719 720 // This is a placeholder Chunk, to allow attaching a DefinedSynthetic to a 721 // specific place in a section, without any data. This is used for the MinGW 722 // specific symbol __RUNTIME_PSEUDO_RELOC_LIST_END__, even though the concept 723 // of an empty chunk isn't MinGW specific. 724 class EmptyChunk : public NonSectionChunk { 725 public: 726 EmptyChunk() {} 727 size_t getSize() const override { return 0; } 728 void writeTo(uint8_t *buf) const override {} 729 }; 730 731 class ECCodeMapEntry { 732 public: 733 ECCodeMapEntry(Chunk *first, Chunk *last, chpe_range_type type) 734 : first(first), last(last), type(type) {} 735 Chunk *first; 736 Chunk *last; 737 chpe_range_type type; 738 }; 739 740 // This is a chunk containing CHPE code map on EC targets. It's a table 741 // of address ranges and their types. 742 class ECCodeMapChunk : public NonSectionChunk { 743 public: 744 ECCodeMapChunk(std::vector<ECCodeMapEntry> &map) : map(map) {} 745 size_t getSize() const override; 746 void writeTo(uint8_t *buf) const override; 747 748 private: 749 std::vector<ECCodeMapEntry> ↦ 750 }; 751 752 // MinGW specific, for the "automatic import of variables from DLLs" feature. 753 // This provides the table of runtime pseudo relocations, for variable 754 // references that turned out to need to be imported from a DLL even though 755 // the reference didn't use the dllimport attribute. The MinGW runtime will 756 // process this table after loading, before handling control over to user 757 // code. 758 class PseudoRelocTableChunk : public NonSectionChunk { 759 public: 760 PseudoRelocTableChunk(std::vector<RuntimePseudoReloc> &relocs) 761 : relocs(std::move(relocs)) { 762 setAlignment(4); 763 } 764 size_t getSize() const override; 765 void writeTo(uint8_t *buf) const override; 766 767 private: 768 std::vector<RuntimePseudoReloc> relocs; 769 }; 770 771 // MinGW specific. A Chunk that contains one pointer-sized absolute value. 772 class AbsolutePointerChunk : public NonSectionChunk { 773 public: 774 AbsolutePointerChunk(COFFLinkerContext &ctx, uint64_t value) 775 : value(value), ctx(ctx) { 776 setAlignment(getSize()); 777 } 778 size_t getSize() const override; 779 void writeTo(uint8_t *buf) const override; 780 781 private: 782 uint64_t value; 783 COFFLinkerContext &ctx; 784 }; 785 786 // Return true if this file has the hotpatch flag set to true in the S_COMPILE3 787 // record in codeview debug info. Also returns true for some thunks synthesized 788 // by the linker. 789 inline bool Chunk::isHotPatchable() const { 790 if (auto *sc = dyn_cast<SectionChunk>(this)) 791 return sc->file->hotPatchable; 792 else if (isa<ImportThunkChunk>(this)) 793 return true; 794 return false; 795 } 796 797 inline Defined *Chunk::getEntryThunk() const { 798 if (auto *c = dyn_cast<const SectionChunkEC>(this)) 799 return c->entryThunk; 800 return nullptr; 801 } 802 803 inline void Chunk::setEntryThunk(Defined *entryThunk) { 804 if (auto c = dyn_cast<SectionChunkEC>(this)) 805 c->entryThunk = entryThunk; 806 } 807 808 void applyMOV32T(uint8_t *off, uint32_t v); 809 void applyBranch24T(uint8_t *off, int32_t v); 810 811 void applyArm64Addr(uint8_t *off, uint64_t s, uint64_t p, int shift); 812 void applyArm64Imm(uint8_t *off, uint64_t imm, uint32_t rangeLimit); 813 void applyArm64Branch26(uint8_t *off, int64_t v); 814 815 // Convenience class for initializing a coff_section with specific flags. 816 class FakeSection { 817 public: 818 FakeSection(int c) { section.Characteristics = c; } 819 820 coff_section section; 821 }; 822 823 // Convenience class for initializing a SectionChunk with specific flags. 824 class FakeSectionChunk { 825 public: 826 FakeSectionChunk(const coff_section *section) : chunk(nullptr, section) { 827 // Comdats from LTO files can't be fully treated as regular comdats 828 // at this point; we don't know what size or contents they are going to 829 // have, so we can't do proper checking of such aspects of them. 830 chunk.selection = llvm::COFF::IMAGE_COMDAT_SELECT_ANY; 831 } 832 833 SectionChunk chunk; 834 }; 835 836 } // namespace lld::coff 837 838 namespace llvm { 839 template <> 840 struct DenseMapInfo<lld::coff::ChunkAndOffset> 841 : lld::coff::ChunkAndOffset::DenseMapInfo {}; 842 } 843 844 #endif 845