diff --git a/lld/COFF/Chunks.h b/lld/COFF/Chunks.h --- a/lld/COFF/Chunks.h +++ b/lld/COFF/Chunks.h @@ -50,7 +50,7 @@ // doesn't even have actual data (if common or bss). class Chunk { public: - enum Kind { SectionKind, OtherKind }; + enum Kind : uint8_t { SectionKind, OtherKind }; Kind kind() const { return ChunkKind; } virtual ~Chunk() = default; @@ -114,6 +114,12 @@ Chunk(Kind K = OtherKind) : ChunkKind(K) {} const Kind ChunkKind; +public: + // Whether this section needs to be kept distinct from other sections during + // ICF. This is set by the driver using address-significance tables. + bool KeepUnique = false; + +protected: // The RVA of this chunk in the output. The writer sets a value. uint64_t RVA = 0; @@ -123,10 +129,6 @@ public: // The offset from beginning of the output section. The writer sets a value. uint64_t OutputSectionOff = 0; - - // Whether this section needs to be kept distinct from other sections during - // ICF. This is set by the driver using address-significance tables. - bool KeepUnique = false; }; // A chunk corresponding a section of an input file. @@ -217,36 +219,41 @@ bool isHotPatchable() const override { return File->HotPatchable; } - // A pointer pointing to a replacement for this chunk. - // Initially it points to "this" object. If this chunk is merged - // with other chunk by ICF, it points to another chunk, - // and this chunk is considered as dead. - SectionChunk *Repl; - - // The CRC of the contents as described in the COFF spec 4.5.5. - // Auxiliary Format 5: Section Definitions. Used for ICF. - uint32_t Checksum = 0; - - const coff_section *Header; - // The file that this chunk was created from. ObjFile *File; + // Pointer to the COFF section header in the input file. + const coff_section *Header; + // The COMDAT leader symbol if this is a COMDAT chunk. DefinedRegular *Sym = nullptr; - // The COMDAT selection if this is a COMDAT chunk. - llvm::COFF::COMDATType Selection = (llvm::COFF::COMDATType)0; - + // Relocations for this section. ArrayRef Relocs; - // Used by the garbage collector. - bool Live; - // When inserting a thunk, we need to adjust a relocation to point to // the thunk instead of the actual original target Symbol. std::vector RelocTargets; + // The CRC of the contents as described in the COFF spec 4.5.5. + // Auxiliary Format 5: Section Definitions. Used for ICF. + uint32_t Checksum = 0; + + // Indicates whether the section should be included in the output file. + // Sections may become dead if the garbage collector discards them, if ICF + // replaces them, or if they are associated with a non-prevailing comdat + // section. + bool Live; + + // The COMDAT selection if this is a COMDAT chunk. + llvm::COFF::COMDATType Selection = (llvm::COFF::COMDATType)0; + + // A pointer pointing to a replacement for this chunk. + // Initially it points to "this" object. If this chunk is merged + // with other chunk by ICF, it points to another chunk, + // and this chunk is considered as dead. + SectionChunk *Repl; + private: StringRef SectionName; std::vector AssocChildren; diff --git a/lld/COFF/Chunks.cpp b/lld/COFF/Chunks.cpp --- a/lld/COFF/Chunks.cpp +++ b/lld/COFF/Chunks.cpp @@ -30,8 +30,8 @@ namespace coff { SectionChunk::SectionChunk(ObjFile *F, const coff_section *H) - : Chunk(SectionKind), Repl(this), Header(H), File(F), - Relocs(File->getCOFFObj()->getRelocations(Header)) { + : Chunk(SectionKind), File(F), Header(H), + Relocs(File->getCOFFObj()->getRelocations(Header)), Repl(this) { // Initialize SectionName. File->getCOFFObj()->getSectionName(Header, SectionName); @@ -44,6 +44,48 @@ Live = !Config->DoGC || !isCOMDAT(); } +namespace { +// This class exists just for the purpose of calculating the expected size of +// Chunk. +struct ChunkFields { + uintptr_t VPtr; + uint32_t Alignment; + uint8_t ChunkKind; + bool KeepUnique; + uint64_t RVA; + uintptr_t Out; + uint64_t OutputSectionOff; +}; + +// Chunk is one of the most frequently allocated classes, so it is important to +// keep it as compact as possible. +static_assert(sizeof(Chunk) == sizeof(ChunkFields), + "Chunk grew unexpectedly"); + +// This class exists just for the purpose of calculating the expected size of +// SectionChunk. +struct SectionChunkFields { + ChunkFields ChunkBase; + uintptr_t File; + uintptr_t Header; + uintptr_t Sym; + uintptr_t Relocs[2]; + uintptr_t RelocTargets[3]; + uint32_t Checksum; + bool Live; + uint8_t Selection; + uintptr_t Repl; + uintptr_t SectionName[2]; + uintptr_t AssocChildren[3]; + uint32_t Class[2]; +}; + +// SectionChunk is one of the most frequently allocated classes, so it is +// important to keep it as compact as possible. +static_assert(sizeof(SectionChunk) == sizeof(SectionChunkFields), + "SectionChunk grew unexpectedly"); +} // namespace + // Initialize the RelocTargets vector, to allow redirecting certain relocations // to a thunk instead of the actual symbol the relocation's symbol table index // indicates. diff --git a/llvm/include/llvm/BinaryFormat/COFF.h b/llvm/include/llvm/BinaryFormat/COFF.h --- a/llvm/include/llvm/BinaryFormat/COFF.h +++ b/llvm/include/llvm/BinaryFormat/COFF.h @@ -402,7 +402,7 @@ IMAGE_REL_ARM64_REL32 = 0x0011, }; -enum COMDATType : unsigned { +enum COMDATType : uint8_t { IMAGE_COMDAT_SELECT_NODUPLICATES = 1, IMAGE_COMDAT_SELECT_ANY, IMAGE_COMDAT_SELECT_SAME_SIZE,