forked from OSchip/llvm-project
[COFF] De-virtualize Chunk and SectionChunk
Shaves another pointer off of SectionChunk, reducing the size from 96 to 88 bytes, down from 144 before I started working on this. Combined with D62356, this reduced peak memory usage when linking chrome_child.dll from 713MB to 675MB, or 5%. Create NonSectionChunk to provide virtual dispatch to the rest of the chunk types. Reviewers: ruiu, aganea Differential Revision: https://reviews.llvm.org/D62362 llvm-svn: 361667
This commit is contained in:
parent
96f02a8db8
commit
a431dd7ae7
|
@ -43,6 +43,8 @@ SectionChunk::SectionChunk(ObjFile *F, const coff_section *H)
|
|||
|
||||
setAlignment(Header->getAlignment());
|
||||
|
||||
HasData = !(Header->Characteristics & IMAGE_SCN_CNT_UNINITIALIZED_DATA);
|
||||
|
||||
// If linker GC is disabled, every chunk starts out alive. If linker GC is
|
||||
// enabled, treat non-comdat sections as roots. Generally optimized object
|
||||
// files will be built with -ffunction-sections or /Gy, so most things worth
|
||||
|
@ -53,7 +55,7 @@ SectionChunk::SectionChunk(ObjFile *F, const coff_section *H)
|
|||
// SectionChunk is one of the most frequently allocated classes, so it is
|
||||
// important to keep it as compact as possible. As of this writing, the number
|
||||
// below is the size of this class on x64 platforms.
|
||||
static_assert(sizeof(SectionChunk) <= 96, "SectionChunk grew unexpectedly");
|
||||
static_assert(sizeof(SectionChunk) <= 88, "SectionChunk grew unexpectedly");
|
||||
|
||||
static void add16(uint8_t *P, int16_t V) { write16le(P, read16le(P) + V); }
|
||||
static void add32(uint8_t *P, int32_t V) { write32le(P, read32le(P) + V); }
|
||||
|
@ -559,14 +561,6 @@ void SectionChunk::getRuntimePseudoRelocs(
|
|||
}
|
||||
}
|
||||
|
||||
bool SectionChunk::hasData() const {
|
||||
return !(Header->Characteristics & IMAGE_SCN_CNT_UNINITIALIZED_DATA);
|
||||
}
|
||||
|
||||
uint32_t SectionChunk::getOutputCharacteristics() const {
|
||||
return Header->Characteristics & (PermMask | TypeMask);
|
||||
}
|
||||
|
||||
bool SectionChunk::isCOMDAT() const {
|
||||
return Header->Characteristics & IMAGE_SCN_LNK_COMDAT;
|
||||
}
|
||||
|
@ -578,7 +572,7 @@ void SectionChunk::printDiscardedMessage() const {
|
|||
message("Discarded " + Sym->getName());
|
||||
}
|
||||
|
||||
StringRef SectionChunk::getDebugName() {
|
||||
StringRef SectionChunk::getDebugName() const {
|
||||
if (Sym)
|
||||
return Sym->getName();
|
||||
return "";
|
||||
|
@ -642,6 +636,7 @@ CommonChunk::CommonChunk(const COFFSymbolRef S) : Sym(S) {
|
|||
// than 32 bytes naturally, i.e. round the size up to the next power of two.
|
||||
// This is what MSVC link.exe does.
|
||||
setAlignment(std::min(32U, uint32_t(PowerOf2Ceil(Sym.getValue()))));
|
||||
HasData = false;
|
||||
}
|
||||
|
||||
uint32_t CommonChunk::getOutputCharacteristics() const {
|
||||
|
@ -858,7 +853,7 @@ uint8_t Baserel::getDefaultType() {
|
|||
MergeChunk *MergeChunk::Instances[Log2MaxSectionAlignment + 1] = {};
|
||||
|
||||
MergeChunk::MergeChunk(uint32_t Alignment)
|
||||
: Chunk(OtherKind), Builder(StringTableBuilder::RAW, Alignment) {
|
||||
: Builder(StringTableBuilder::RAW, Alignment) {
|
||||
setAlignment(Alignment);
|
||||
}
|
||||
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
#include "InputFiles.h"
|
||||
#include "lld/Common/LLVM.h"
|
||||
#include "llvm/ADT/ArrayRef.h"
|
||||
#include "llvm/ADT/PointerIntPair.h"
|
||||
#include "llvm/ADT/iterator.h"
|
||||
#include "llvm/ADT/iterator_range.h"
|
||||
#include "llvm/MC/StringTableBuilder.h"
|
||||
|
@ -55,14 +56,16 @@ class Chunk {
|
|||
public:
|
||||
enum Kind : uint8_t { SectionKind, OtherKind };
|
||||
Kind kind() const { return ChunkKind; }
|
||||
virtual ~Chunk() = default;
|
||||
|
||||
// Returns the size of this chunk (even if this is a common or BSS.)
|
||||
virtual size_t getSize() const = 0;
|
||||
size_t getSize() const;
|
||||
|
||||
// Returns chunk alignment in power of two form. Value values are powers of
|
||||
// two from 1 to 8192.
|
||||
uint32_t getAlignment() const { return 1U << P2Align; }
|
||||
|
||||
// Update the chunk section alignment measured in bytes. Internally alignment
|
||||
// is stored in log2.
|
||||
void setAlignment(uint32_t Align) {
|
||||
// Treat zero byte alignment as 1 byte alignment.
|
||||
Align = Align ? Align : 1;
|
||||
|
@ -76,7 +79,7 @@ public:
|
|||
// beginning of the file. Because this function may use RVA values
|
||||
// of other chunks for relocations, you need to set them properly
|
||||
// before calling this function.
|
||||
virtual void writeTo(uint8_t *Buf) const {}
|
||||
void writeTo(uint8_t *Buf) const;
|
||||
|
||||
// The writer sets and uses the addresses. In practice, PE images cannot be
|
||||
// larger than 2GB. Chunks are always laid as part of the image, so Chunk RVAs
|
||||
|
@ -90,16 +93,14 @@ public:
|
|||
// Returns true if this has non-zero data. BSS chunks return
|
||||
// false. If false is returned, the space occupied by this chunk
|
||||
// will be filled with zeros.
|
||||
virtual bool hasData() const { return true; }
|
||||
bool hasData() const { return HasData; }
|
||||
|
||||
// Returns readable/writable/executable bits.
|
||||
virtual uint32_t getOutputCharacteristics() const { return 0; }
|
||||
uint32_t getOutputCharacteristics() const;
|
||||
|
||||
// Returns the section name if this is a section chunk.
|
||||
// It is illegal to call this function on non-section chunks.
|
||||
virtual StringRef getSectionName() const {
|
||||
llvm_unreachable("unimplemented getSectionName");
|
||||
}
|
||||
StringRef getSectionName() const;
|
||||
|
||||
// An output section has pointers to chunks in the section, and each
|
||||
// chunk has a back pointer to an output section.
|
||||
|
@ -109,22 +110,29 @@ public:
|
|||
|
||||
// Windows-specific.
|
||||
// Collect all locations that contain absolute addresses for base relocations.
|
||||
virtual void getBaserels(std::vector<Baserel> *Res) {}
|
||||
void getBaserels(std::vector<Baserel> *Res);
|
||||
|
||||
// Returns a human-readable name of this chunk. Chunks are unnamed chunks of
|
||||
// bytes, so this is used only for logging or debugging.
|
||||
virtual StringRef getDebugName() { return ""; }
|
||||
StringRef getDebugName() const;
|
||||
|
||||
virtual bool isHotPatchable() const { return false; }
|
||||
// Return true if this file has the hotpatch flag set to true in the
|
||||
// S_COMPILE3 record in codeview debug info. Also returns true for some thunks
|
||||
// synthesized by the linker.
|
||||
bool isHotPatchable() const;
|
||||
|
||||
protected:
|
||||
Chunk(Kind K = OtherKind) : ChunkKind(K) {}
|
||||
Chunk(Kind K = OtherKind) : ChunkKind(K), HasData(true), P2Align(0) {}
|
||||
|
||||
const Kind ChunkKind;
|
||||
|
||||
// True if the section has data. Corresponds to the
|
||||
// IMAGE_SCN_CNT_UNINITIALIZED_DATA section characteristic bit.
|
||||
uint8_t HasData : 1;
|
||||
|
||||
// The alignment of this chunk, stored in log2 form. The writer uses the
|
||||
// value.
|
||||
uint8_t P2Align = 0;
|
||||
uint8_t P2Align : 7;
|
||||
|
||||
// The output section index for this chunk. The first valid section number is
|
||||
// one.
|
||||
|
@ -134,6 +142,46 @@ protected:
|
|||
uint32_t RVA = 0;
|
||||
};
|
||||
|
||||
class NonSectionChunk : public Chunk {
|
||||
public:
|
||||
virtual ~NonSectionChunk() = default;
|
||||
|
||||
// Returns the size of this chunk (even if this is a common or BSS.)
|
||||
virtual size_t getSize() const = 0;
|
||||
|
||||
virtual uint32_t getOutputCharacteristics() const { return 0; }
|
||||
|
||||
// Write this chunk to a mmap'ed file, assuming Buf is pointing to
|
||||
// beginning of the file. Because this function may use RVA values
|
||||
// of other chunks for relocations, you need to set them properly
|
||||
// before calling this function.
|
||||
virtual void writeTo(uint8_t *Buf) const {}
|
||||
|
||||
// Returns the section name if this is a section chunk.
|
||||
// It is illegal to call this function on non-section chunks.
|
||||
virtual StringRef getSectionName() const {
|
||||
llvm_unreachable("unimplemented getSectionName");
|
||||
}
|
||||
|
||||
// Windows-specific.
|
||||
// Collect all locations that contain absolute addresses for base relocations.
|
||||
virtual void getBaserels(std::vector<Baserel> *Res) {}
|
||||
|
||||
// Return true if this file has the hotpatch flag set to true in the
|
||||
// S_COMPILE3 record in codeview debug info. Also returns true for some thunks
|
||||
// synthesized by the linker.
|
||||
virtual bool isHotPatchable() const { return false; }
|
||||
|
||||
// Returns a human-readable name of this chunk. Chunks are unnamed chunks of
|
||||
// bytes, so this is used only for logging or debugging.
|
||||
virtual StringRef getDebugName() const { return ""; }
|
||||
|
||||
static bool classof(const Chunk *C) { return C->kind() == OtherKind; }
|
||||
|
||||
protected:
|
||||
NonSectionChunk() : Chunk(OtherKind) {}
|
||||
};
|
||||
|
||||
// A chunk corresponding a section of an input file.
|
||||
class SectionChunk final : public Chunk {
|
||||
// Identical COMDAT Folding feature accesses section internal data.
|
||||
|
@ -158,15 +206,17 @@ public:
|
|||
|
||||
SectionChunk(ObjFile *File, const coff_section *Header);
|
||||
static bool classof(const Chunk *C) { return C->kind() == SectionKind; }
|
||||
size_t getSize() const override { return Header->SizeOfRawData; }
|
||||
size_t getSize() const { return Header->SizeOfRawData; }
|
||||
ArrayRef<uint8_t> getContents() const;
|
||||
void writeTo(uint8_t *Buf) const override;
|
||||
bool hasData() const override;
|
||||
uint32_t getOutputCharacteristics() const override;
|
||||
StringRef getSectionName() const override {
|
||||
void writeTo(uint8_t *Buf) const;
|
||||
|
||||
uint32_t getOutputCharacteristics() const {
|
||||
return Header->Characteristics & (PermMask | TypeMask);
|
||||
}
|
||||
StringRef getSectionName() const {
|
||||
return StringRef(SectionNameData, SectionNameSize);
|
||||
}
|
||||
void getBaserels(std::vector<Baserel> *Res) override;
|
||||
void getBaserels(std::vector<Baserel> *Res);
|
||||
bool isCOMDAT() const;
|
||||
void applyRelX64(uint8_t *Off, uint16_t Type, OutputSection *OS, uint64_t S,
|
||||
uint64_t P) const;
|
||||
|
@ -187,7 +237,7 @@ public:
|
|||
// and its children are treated as a group by the garbage collector.
|
||||
void addAssociative(SectionChunk *Child);
|
||||
|
||||
StringRef getDebugName() override;
|
||||
StringRef getDebugName() const;
|
||||
|
||||
// True if this is a codeview debug info chunk. These will not be laid out in
|
||||
// the image. Instead they will end up in the PDB, if one is requested.
|
||||
|
@ -200,6 +250,8 @@ public:
|
|||
return getSectionName().startswith(".debug_") || getSectionName() == ".eh_frame";
|
||||
}
|
||||
|
||||
bool isHotPatchable() const { return File->HotPatchable; }
|
||||
|
||||
// Allow iteration over the bodies of this chunk's relocated symbols.
|
||||
llvm::iterator_range<symbol_iterator> symbols() const {
|
||||
return llvm::make_range(symbol_iterator(File, RelocsData),
|
||||
|
@ -257,8 +309,6 @@ public:
|
|||
static SectionChunk *findByName(ArrayRef<SectionChunk *> Sections,
|
||||
StringRef Name);
|
||||
|
||||
bool isHotPatchable() const override { return File->HotPatchable; }
|
||||
|
||||
// The file that this chunk was created from.
|
||||
ObjFile *File;
|
||||
|
||||
|
@ -305,6 +355,58 @@ private:
|
|||
uint32_t SectionNameSize = 0;
|
||||
};
|
||||
|
||||
// Inline methods to implement faux-virtual dispatch for SectionChunk.
|
||||
|
||||
inline size_t Chunk::getSize() const {
|
||||
if (isa<SectionChunk>(this))
|
||||
return static_cast<const SectionChunk *>(this)->getSize();
|
||||
else
|
||||
return static_cast<const NonSectionChunk *>(this)->getSize();
|
||||
}
|
||||
|
||||
inline uint32_t Chunk::getOutputCharacteristics() const {
|
||||
if (isa<SectionChunk>(this))
|
||||
return static_cast<const SectionChunk *>(this)->getOutputCharacteristics();
|
||||
else
|
||||
return static_cast<const NonSectionChunk *>(this)
|
||||
->getOutputCharacteristics();
|
||||
}
|
||||
|
||||
inline void Chunk::writeTo(uint8_t *Buf) const {
|
||||
if (isa<SectionChunk>(this))
|
||||
static_cast<const SectionChunk *>(this)->writeTo(Buf);
|
||||
else
|
||||
static_cast<const NonSectionChunk *>(this)->writeTo(Buf);
|
||||
}
|
||||
|
||||
inline bool Chunk::isHotPatchable() const {
|
||||
if (isa<SectionChunk>(this))
|
||||
return static_cast<const SectionChunk *>(this)->isHotPatchable();
|
||||
else
|
||||
return static_cast<const NonSectionChunk *>(this)->isHotPatchable();
|
||||
}
|
||||
|
||||
inline StringRef Chunk::getSectionName() const {
|
||||
if (isa<SectionChunk>(this))
|
||||
return static_cast<const SectionChunk *>(this)->getSectionName();
|
||||
else
|
||||
return static_cast<const NonSectionChunk *>(this)->getSectionName();
|
||||
}
|
||||
|
||||
inline void Chunk::getBaserels(std::vector<Baserel> *Res) {
|
||||
if (isa<SectionChunk>(this))
|
||||
static_cast<SectionChunk *>(this)->getBaserels(Res);
|
||||
else
|
||||
static_cast<NonSectionChunk *>(this)->getBaserels(Res);
|
||||
}
|
||||
|
||||
inline StringRef Chunk::getDebugName() const {
|
||||
if (isa<SectionChunk>(this))
|
||||
return static_cast<const SectionChunk *>(this)->getDebugName();
|
||||
else
|
||||
return static_cast<const NonSectionChunk *>(this)->getDebugName();
|
||||
}
|
||||
|
||||
// This class is used to implement an lld-specific feature (not implemented in
|
||||
// MSVC) that minimizes the output size by finding string literals sharing tail
|
||||
// parts and merging them.
|
||||
|
@ -314,7 +416,7 @@ private:
|
|||
// The MergeChunk then tail merges the strings using the StringTableBuilder
|
||||
// class and assigns RVAs and section offsets to each of the member chunks based
|
||||
// on the offsets assigned by the StringTableBuilder.
|
||||
class MergeChunk : public Chunk {
|
||||
class MergeChunk : public NonSectionChunk {
|
||||
public:
|
||||
MergeChunk(uint32_t Alignment);
|
||||
static void addSection(SectionChunk *C);
|
||||
|
@ -335,11 +437,10 @@ private:
|
|||
};
|
||||
|
||||
// A chunk for common symbols. Common chunks don't have actual data.
|
||||
class CommonChunk : public Chunk {
|
||||
class CommonChunk : public NonSectionChunk {
|
||||
public:
|
||||
CommonChunk(const COFFSymbolRef Sym);
|
||||
size_t getSize() const override { return Sym.getValue(); }
|
||||
bool hasData() const override { return false; }
|
||||
uint32_t getOutputCharacteristics() const override;
|
||||
StringRef getSectionName() const override { return ".bss"; }
|
||||
|
||||
|
@ -348,7 +449,7 @@ private:
|
|||
};
|
||||
|
||||
// A chunk for linker-created strings.
|
||||
class StringChunk : public Chunk {
|
||||
class StringChunk : public NonSectionChunk {
|
||||
public:
|
||||
explicit StringChunk(StringRef S) : Str(S) {}
|
||||
size_t getSize() const override { return Str.size() + 1; }
|
||||
|
@ -377,7 +478,7 @@ static const uint8_t ImportThunkARM64[] = {
|
|||
// Windows-specific.
|
||||
// A chunk for DLL import jump table entry. In a final output, its
|
||||
// contents will be a JMP instruction to some __imp_ symbol.
|
||||
class ImportThunkChunkX64 : public Chunk {
|
||||
class ImportThunkChunkX64 : public NonSectionChunk {
|
||||
public:
|
||||
explicit ImportThunkChunkX64(Defined *S);
|
||||
size_t getSize() const override { return sizeof(ImportThunkX86); }
|
||||
|
@ -389,9 +490,10 @@ private:
|
|||
Defined *ImpSymbol;
|
||||
};
|
||||
|
||||
class ImportThunkChunkX86 : public Chunk {
|
||||
class ImportThunkChunkX86 : public NonSectionChunk {
|
||||
public:
|
||||
explicit ImportThunkChunkX86(Defined *S) : ImpSymbol(S) {}
|
||||
explicit ImportThunkChunkX86(Defined *S) : ImpSymbol(S) {
|
||||
}
|
||||
size_t getSize() const override { return sizeof(ImportThunkX86); }
|
||||
void getBaserels(std::vector<Baserel> *Res) override;
|
||||
void writeTo(uint8_t *Buf) const override;
|
||||
|
@ -402,9 +504,10 @@ private:
|
|||
Defined *ImpSymbol;
|
||||
};
|
||||
|
||||
class ImportThunkChunkARM : public Chunk {
|
||||
class ImportThunkChunkARM : public NonSectionChunk {
|
||||
public:
|
||||
explicit ImportThunkChunkARM(Defined *S) : ImpSymbol(S) {}
|
||||
explicit ImportThunkChunkARM(Defined *S) : ImpSymbol(S) {
|
||||
}
|
||||
size_t getSize() const override { return sizeof(ImportThunkARM); }
|
||||
void getBaserels(std::vector<Baserel> *Res) override;
|
||||
void writeTo(uint8_t *Buf) const override;
|
||||
|
@ -415,9 +518,10 @@ private:
|
|||
Defined *ImpSymbol;
|
||||
};
|
||||
|
||||
class ImportThunkChunkARM64 : public Chunk {
|
||||
class ImportThunkChunkARM64 : public NonSectionChunk {
|
||||
public:
|
||||
explicit ImportThunkChunkARM64(Defined *S) : ImpSymbol(S) {}
|
||||
explicit ImportThunkChunkARM64(Defined *S) : ImpSymbol(S) {
|
||||
}
|
||||
size_t getSize() const override { return sizeof(ImportThunkARM64); }
|
||||
void writeTo(uint8_t *Buf) const override;
|
||||
|
||||
|
@ -427,7 +531,7 @@ private:
|
|||
Defined *ImpSymbol;
|
||||
};
|
||||
|
||||
class RangeExtensionThunkARM : public Chunk {
|
||||
class RangeExtensionThunkARM : public NonSectionChunk {
|
||||
public:
|
||||
explicit RangeExtensionThunkARM(Defined *T) : Target(T) {}
|
||||
size_t getSize() const override;
|
||||
|
@ -436,7 +540,7 @@ public:
|
|||
Defined *Target;
|
||||
};
|
||||
|
||||
class RangeExtensionThunkARM64 : public Chunk {
|
||||
class RangeExtensionThunkARM64 : public NonSectionChunk {
|
||||
public:
|
||||
explicit RangeExtensionThunkARM64(Defined *T) : Target(T) {}
|
||||
size_t getSize() const override;
|
||||
|
@ -447,7 +551,7 @@ public:
|
|||
|
||||
// Windows-specific.
|
||||
// See comments for DefinedLocalImport class.
|
||||
class LocalImportChunk : public Chunk {
|
||||
class LocalImportChunk : public NonSectionChunk {
|
||||
public:
|
||||
explicit LocalImportChunk(Defined *S) : Sym(S) {
|
||||
setAlignment(Config->Wordsize);
|
||||
|
@ -487,7 +591,7 @@ struct ChunkAndOffset {
|
|||
using SymbolRVASet = llvm::DenseSet<ChunkAndOffset>;
|
||||
|
||||
// Table which contains symbol RVAs. Used for /safeseh and /guard:cf.
|
||||
class RVATableChunk : public Chunk {
|
||||
class RVATableChunk : public NonSectionChunk {
|
||||
public:
|
||||
explicit RVATableChunk(SymbolRVASet S) : Syms(std::move(S)) {}
|
||||
size_t getSize() const override { return Syms.size() * 4; }
|
||||
|
@ -500,7 +604,7 @@ private:
|
|||
// Windows-specific.
|
||||
// This class represents a block in .reloc section.
|
||||
// See the PE/COFF spec 5.6 for details.
|
||||
class BaserelChunk : public Chunk {
|
||||
class BaserelChunk : public NonSectionChunk {
|
||||
public:
|
||||
BaserelChunk(uint32_t Page, Baserel *Begin, Baserel *End);
|
||||
size_t getSize() const override { return Data.size(); }
|
||||
|
@ -524,7 +628,7 @@ public:
|
|||
// specific place in a section, without any data. This is used for the MinGW
|
||||
// specific symbol __RUNTIME_PSEUDO_RELOC_LIST_END__, even though the concept
|
||||
// of an empty chunk isn't MinGW specific.
|
||||
class EmptyChunk : public Chunk {
|
||||
class EmptyChunk : public NonSectionChunk {
|
||||
public:
|
||||
EmptyChunk() {}
|
||||
size_t getSize() const override { return 0; }
|
||||
|
@ -537,7 +641,7 @@ public:
|
|||
// the reference didn't use the dllimport attribute. The MinGW runtime will
|
||||
// process this table after loading, before handling control over to user
|
||||
// code.
|
||||
class PseudoRelocTableChunk : public Chunk {
|
||||
class PseudoRelocTableChunk : public NonSectionChunk {
|
||||
public:
|
||||
PseudoRelocTableChunk(std::vector<RuntimePseudoReloc> &Relocs)
|
||||
: Relocs(std::move(Relocs)) {
|
||||
|
@ -568,7 +672,7 @@ public:
|
|||
};
|
||||
|
||||
// MinGW specific. A Chunk that contains one pointer-sized absolute value.
|
||||
class AbsolutePointerChunk : public Chunk {
|
||||
class AbsolutePointerChunk : public NonSectionChunk {
|
||||
public:
|
||||
AbsolutePointerChunk(uint64_t Value) : Value(Value) {
|
||||
setAlignment(getSize());
|
||||
|
|
|
@ -35,7 +35,7 @@ namespace {
|
|||
// Import table
|
||||
|
||||
// A chunk for the import descriptor table.
|
||||
class HintNameChunk : public Chunk {
|
||||
class HintNameChunk : public NonSectionChunk {
|
||||
public:
|
||||
HintNameChunk(StringRef N, uint16_t H) : Name(N), Hint(H) {}
|
||||
|
||||
|
@ -57,7 +57,7 @@ private:
|
|||
};
|
||||
|
||||
// A chunk for the import descriptor table.
|
||||
class LookupChunk : public Chunk {
|
||||
class LookupChunk : public NonSectionChunk {
|
||||
public:
|
||||
explicit LookupChunk(Chunk *C) : HintName(C) {
|
||||
setAlignment(Config->Wordsize);
|
||||
|
@ -77,7 +77,7 @@ public:
|
|||
// A chunk for the import descriptor table.
|
||||
// This chunk represent import-by-ordinal symbols.
|
||||
// See Microsoft PE/COFF spec 7.1. Import Header for details.
|
||||
class OrdinalOnlyChunk : public Chunk {
|
||||
class OrdinalOnlyChunk : public NonSectionChunk {
|
||||
public:
|
||||
explicit OrdinalOnlyChunk(uint16_t V) : Ordinal(V) {
|
||||
setAlignment(Config->Wordsize);
|
||||
|
@ -98,7 +98,7 @@ public:
|
|||
};
|
||||
|
||||
// A chunk for the import descriptor table.
|
||||
class ImportDirectoryChunk : public Chunk {
|
||||
class ImportDirectoryChunk : public NonSectionChunk {
|
||||
public:
|
||||
explicit ImportDirectoryChunk(Chunk *N) : DLLName(N) {}
|
||||
size_t getSize() const override { return sizeof(ImportDirectoryTableEntry); }
|
||||
|
@ -119,10 +119,9 @@ public:
|
|||
|
||||
// A chunk representing null terminator in the import table.
|
||||
// Contents of this chunk is always null bytes.
|
||||
class NullChunk : public Chunk {
|
||||
class NullChunk : public NonSectionChunk {
|
||||
public:
|
||||
explicit NullChunk(size_t N) : Size(N) {}
|
||||
bool hasData() const override { return false; }
|
||||
explicit NullChunk(size_t N) : Size(N) { HasData = false; }
|
||||
size_t getSize() const override { return Size; }
|
||||
|
||||
void writeTo(uint8_t *Buf) const override {
|
||||
|
@ -162,7 +161,7 @@ binImports(const std::vector<DefinedImportData *> &Imports) {
|
|||
// See Microsoft PE/COFF spec 4.3 for details.
|
||||
|
||||
// A chunk for the delay import descriptor table etnry.
|
||||
class DelayDirectoryChunk : public Chunk {
|
||||
class DelayDirectoryChunk : public NonSectionChunk {
|
||||
public:
|
||||
explicit DelayDirectoryChunk(Chunk *N) : DLLName(N) {}
|
||||
|
||||
|
@ -274,7 +273,7 @@ static const uint8_t ThunkARM64[] = {
|
|||
};
|
||||
|
||||
// A chunk for the delay import thunk.
|
||||
class ThunkChunkX64 : public Chunk {
|
||||
class ThunkChunkX64 : public NonSectionChunk {
|
||||
public:
|
||||
ThunkChunkX64(Defined *I, Chunk *D, Defined *H)
|
||||
: Imp(I), Desc(D), Helper(H) {}
|
||||
|
@ -293,7 +292,7 @@ public:
|
|||
Defined *Helper = nullptr;
|
||||
};
|
||||
|
||||
class ThunkChunkX86 : public Chunk {
|
||||
class ThunkChunkX86 : public NonSectionChunk {
|
||||
public:
|
||||
ThunkChunkX86(Defined *I, Chunk *D, Defined *H)
|
||||
: Imp(I), Desc(D), Helper(H) {}
|
||||
|
@ -317,7 +316,7 @@ public:
|
|||
Defined *Helper = nullptr;
|
||||
};
|
||||
|
||||
class ThunkChunkARM : public Chunk {
|
||||
class ThunkChunkARM : public NonSectionChunk {
|
||||
public:
|
||||
ThunkChunkARM(Defined *I, Chunk *D, Defined *H)
|
||||
: Imp(I), Desc(D), Helper(H) {}
|
||||
|
@ -341,7 +340,7 @@ public:
|
|||
Defined *Helper = nullptr;
|
||||
};
|
||||
|
||||
class ThunkChunkARM64 : public Chunk {
|
||||
class ThunkChunkARM64 : public NonSectionChunk {
|
||||
public:
|
||||
ThunkChunkARM64(Defined *I, Chunk *D, Defined *H)
|
||||
: Imp(I), Desc(D), Helper(H) {}
|
||||
|
@ -363,7 +362,7 @@ public:
|
|||
};
|
||||
|
||||
// A chunk for the import descriptor table.
|
||||
class DelayAddressChunk : public Chunk {
|
||||
class DelayAddressChunk : public NonSectionChunk {
|
||||
public:
|
||||
explicit DelayAddressChunk(Chunk *C) : Thunk(C) {
|
||||
setAlignment(Config->Wordsize);
|
||||
|
@ -393,7 +392,7 @@ public:
|
|||
// Read Microsoft PE/COFF spec 5.3 for details.
|
||||
|
||||
// A chunk for the export descriptor table.
|
||||
class ExportDirectoryChunk : public Chunk {
|
||||
class ExportDirectoryChunk : public NonSectionChunk {
|
||||
public:
|
||||
ExportDirectoryChunk(int I, int J, Chunk *D, Chunk *A, Chunk *N, Chunk *O)
|
||||
: MaxOrdinal(I), NameTabSize(J), DLLName(D), AddressTab(A), NameTab(N),
|
||||
|
@ -424,7 +423,7 @@ public:
|
|||
Chunk *OrdinalTab;
|
||||
};
|
||||
|
||||
class AddressTableChunk : public Chunk {
|
||||
class AddressTableChunk : public NonSectionChunk {
|
||||
public:
|
||||
explicit AddressTableChunk(size_t MaxOrdinal) : Size(MaxOrdinal + 1) {}
|
||||
size_t getSize() const override { return Size * 4; }
|
||||
|
@ -450,7 +449,7 @@ private:
|
|||
size_t Size;
|
||||
};
|
||||
|
||||
class NamePointersChunk : public Chunk {
|
||||
class NamePointersChunk : public NonSectionChunk {
|
||||
public:
|
||||
explicit NamePointersChunk(std::vector<Chunk *> &V) : Chunks(V) {}
|
||||
size_t getSize() const override { return Chunks.size() * 4; }
|
||||
|
@ -466,7 +465,7 @@ private:
|
|||
std::vector<Chunk *> Chunks;
|
||||
};
|
||||
|
||||
class ExportOrdinalChunk : public Chunk {
|
||||
class ExportOrdinalChunk : public NonSectionChunk {
|
||||
public:
|
||||
explicit ExportOrdinalChunk(size_t I) : Size(I) {}
|
||||
size_t getSize() const override { return Size * 2; }
|
||||
|
|
|
@ -88,7 +88,7 @@ OutputSection *Chunk::getOutputSection() const {
|
|||
|
||||
namespace {
|
||||
|
||||
class DebugDirectoryChunk : public Chunk {
|
||||
class DebugDirectoryChunk : public NonSectionChunk {
|
||||
public:
|
||||
DebugDirectoryChunk(const std::vector<Chunk *> &R, bool WriteRepro)
|
||||
: Records(R), WriteRepro(WriteRepro) {}
|
||||
|
@ -143,7 +143,7 @@ private:
|
|||
bool WriteRepro;
|
||||
};
|
||||
|
||||
class CVDebugRecordChunk : public Chunk {
|
||||
class CVDebugRecordChunk : public NonSectionChunk {
|
||||
public:
|
||||
size_t getSize() const override {
|
||||
return sizeof(codeview::DebugInfo) + Config->PDBAltPath.size() + 1;
|
||||
|
|
Loading…
Reference in New Issue