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);
Live = !Config->DoGC || !isCOMDAT();
}
+// 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) <= 128, "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); }
static void add64(uint8_t *P, int64_t V) { write64le(P, read64le(P) + V); }
}
void SectionChunk::addAssociative(SectionChunk *Child) {
- AssocChildren.push_back(Child);
+ // Insert this child at the head of the list.
+ assert(Child->AssocChildren == nullptr &&
+ "associated sections cannot have their own associated children");
+ Child->AssocChildren = AssocChildren;
+ AssocChildren = Child;
}
static uint8_t getBaserelType(const coff_relocation &Rel) {
// 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;
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;
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.
symbol_iterator(File, Relocs.end()));
}
+ // Single linked list iterator for associated comdat children.
+ class AssociatedIterator
+ : public llvm::iterator_facade_base<
+ AssociatedIterator, std::forward_iterator_tag, SectionChunk> {
+ public:
+ AssociatedIterator() = default;
+ AssociatedIterator(SectionChunk *Head) : Cur(Head) {}
+ AssociatedIterator &operator=(const AssociatedIterator &R) {
+ Cur = R.Cur;
+ return *this;
+ }
+ bool operator==(const AssociatedIterator &R) const { return Cur == R.Cur; }
+ const SectionChunk &operator*() const { return *Cur; }
+ SectionChunk &operator*() { return *Cur; }
+ AssociatedIterator &operator++() {
+ Cur = Cur->AssocChildren;
+ return *this;
+ }
+
+ private:
+ SectionChunk *Cur = nullptr;
+ };
+
// Allow iteration over the associated child chunks for this section.
- ArrayRef<SectionChunk *> children() const { return AssocChildren; }
+ llvm::iterator_range<AssociatedIterator> children() const {
+ return llvm::make_range(AssociatedIterator(AssocChildren),
+ AssociatedIterator(nullptr));
+ }
// The section ID this chunk belongs to in its Obj.
uint32_t getSectionNumber() const;
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<coff_relocation> Relocs;
+ // 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;
+
// Used by the garbage collector.
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<SectionChunk *> AssocChildren;
+ SectionChunk *AssocChildren = nullptr;
// Used for ICF (Identical COMDAT Folding)
void replace(SectionChunk *Other);