aboutsummaryrefslogtreecommitdiff
path: root/COFF/Chunks.h
diff options
context:
space:
mode:
Diffstat (limited to 'COFF/Chunks.h')
-rw-r--r--COFF/Chunks.h121
1 files changed, 105 insertions, 16 deletions
diff --git a/COFF/Chunks.h b/COFF/Chunks.h
index 9e896531bd9a..f8a0ddd8ef3b 100644
--- a/COFF/Chunks.h
+++ b/COFF/Chunks.h
@@ -36,6 +36,7 @@ class DefinedImportData;
class DefinedRegular;
class ObjFile;
class OutputSection;
+class RuntimePseudoReloc;
class Symbol;
// Mask for permissions (discardable, writable, readable, executable, etc).
@@ -63,6 +64,13 @@ public:
// before calling this function.
virtual void writeTo(uint8_t *Buf) const {}
+ // Called by the writer once before assigning addresses and writing
+ // the output.
+ virtual void readRelocTargets() {}
+
+ // Called if restarting thunk addition.
+ virtual void resetRelocTargets() {}
+
// Called by the writer after an RVA is assigned, but before calling
// getSize().
virtual void finalizeContents() {}
@@ -114,6 +122,10 @@ protected:
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.
@@ -140,6 +152,8 @@ public:
SectionChunk(ObjFile *File, const coff_section *Header);
static bool classof(const Chunk *C) { return C->kind() == SectionKind; }
+ void readRelocTargets() override;
+ void resetRelocTargets() override;
size_t getSize() const override { return Header->SizeOfRawData; }
ArrayRef<uint8_t> getContents() const;
void writeTo(uint8_t *Buf) const override;
@@ -157,6 +171,8 @@ public:
void applyRelARM64(uint8_t *Off, uint16_t Type, OutputSection *OS, uint64_t S,
uint64_t P) const;
+ void getRuntimePseudoRelocs(std::vector<RuntimePseudoReloc> &Res);
+
// Called if the garbage collector decides to not include this chunk
// in a final output. It's supposed to print out a log message to stdout.
void printDiscardedMessage() const;
@@ -167,16 +183,6 @@ public:
StringRef getDebugName() override;
- // Returns true if the chunk was not dropped by GC.
- bool isLive() { return Live; }
-
- // Used by the garbage collector.
- void markLive() {
- assert(Config->DoGC && "should only mark things live from GC");
- assert(!isLive() && "Cannot mark an already live section!");
- Live = true;
- }
-
// 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.
bool isCodeView() const {
@@ -197,10 +203,13 @@ public:
// Allow iteration over the associated child chunks for this section.
ArrayRef<SectionChunk *> children() const { return AssocChildren; }
+ // The section ID this chunk belongs to in its Obj.
+ uint32_t getSectionNumber() const;
+
// 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 considrered as dead.
+ // and this chunk is considered as dead.
SectionChunk *Repl;
// The CRC of the contents as described in the COFF spec 4.5.5.
@@ -217,13 +226,17 @@ public:
ArrayRef<coff_relocation> 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<Symbol *> RelocTargets;
+
private:
StringRef SectionName;
std::vector<SectionChunk *> AssocChildren;
- // Used by the garbage collector.
- bool Live;
-
// Used for ICF (Identical COMDAT Folding)
void replace(SectionChunk *Other);
uint32_t Class[2] = {0, 0};
@@ -254,6 +267,7 @@ public:
private:
llvm::StringTableBuilder Builder;
+ bool Finalized = false;
};
// A chunk for common symbols. Common chunks don't have actual data.
@@ -297,7 +311,7 @@ static const uint8_t ImportThunkARM64[] = {
};
// Windows-specific.
-// A chunk for DLL import jump table entry. In a final output, it's
+// 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 {
public:
@@ -341,11 +355,22 @@ private:
Defined *ImpSymbol;
};
+class RangeExtensionThunk : public Chunk {
+public:
+ explicit RangeExtensionThunk(Defined *T) : Target(T) {}
+ size_t getSize() const override;
+ void writeTo(uint8_t *Buf) const override;
+
+ Defined *Target;
+};
+
// Windows-specific.
// See comments for DefinedLocalImport class.
class LocalImportChunk : public Chunk {
public:
- explicit LocalImportChunk(Defined *S) : Sym(S) {}
+ explicit LocalImportChunk(Defined *S) : Sym(S) {
+ Alignment = Config->Wordsize;
+ }
size_t getSize() const override;
void getBaserels(std::vector<Baserel> *Res) override;
void writeTo(uint8_t *Buf) const override;
@@ -414,9 +439,73 @@ public:
uint8_t Type;
};
+// This is a placeholder Chunk, to allow attaching a DefinedSynthetic to a
+// 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 {
+public:
+ EmptyChunk() {}
+ size_t getSize() const override { return 0; }
+ void writeTo(uint8_t *Buf) const override {}
+};
+
+// MinGW specific, for the "automatic import of variables from DLLs" feature.
+// This provides the table of runtime pseudo relocations, for variable
+// references that turned out to need to be imported from a DLL even though
+// 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 {
+public:
+ PseudoRelocTableChunk(std::vector<RuntimePseudoReloc> &Relocs)
+ : Relocs(std::move(Relocs)) {
+ Alignment = 4;
+ }
+ size_t getSize() const override;
+ void writeTo(uint8_t *Buf) const override;
+
+private:
+ std::vector<RuntimePseudoReloc> Relocs;
+};
+
+// MinGW specific; information about one individual location in the image
+// that needs to be fixed up at runtime after loading. This represents
+// one individual element in the PseudoRelocTableChunk table.
+class RuntimePseudoReloc {
+public:
+ RuntimePseudoReloc(Defined *Sym, SectionChunk *Target, uint32_t TargetOffset,
+ int Flags)
+ : Sym(Sym), Target(Target), TargetOffset(TargetOffset), Flags(Flags) {}
+
+ Defined *Sym;
+ SectionChunk *Target;
+ uint32_t TargetOffset;
+ // The Flags field contains the size of the relocation, in bits. No other
+ // flags are currently defined.
+ int Flags;
+};
+
+// MinGW specific. A Chunk that contains one pointer-sized absolute value.
+class AbsolutePointerChunk : public Chunk {
+public:
+ AbsolutePointerChunk(uint64_t Value) : Value(Value) {
+ Alignment = getSize();
+ }
+ size_t getSize() const override;
+ void writeTo(uint8_t *Buf) const override;
+
+private:
+ uint64_t Value;
+};
+
void applyMOV32T(uint8_t *Off, uint32_t V);
void applyBranch24T(uint8_t *Off, int32_t V);
+void applyArm64Addr(uint8_t *Off, uint64_t S, uint64_t P, int Shift);
+void applyArm64Imm(uint8_t *Off, uint64_t Imm, uint32_t RangeLimit);
+void applyArm64Branch26(uint8_t *Off, int64_t V);
+
} // namespace coff
} // namespace lld