COFF: Fix __ImageBase symbol relocation.
__ImageBase is a special symbol whose value is the image base address.
Previously, we handled __ImageBase symbol as an absolute symbol.
Absolute symbols point to specific locations in memory and the locations
never change even if an image is base-relocated. That means that we
don't have base relocation entries for absolute symbols.
This is not a case for __ImageBase. If an image is base-relocated, its
base address changes, and __ImageBase needs to be shifted as well.
So we have to have base relocations for __ImageBase. That means that
__ImageBase is not really an absolute symbol but a different kind of
symbol.
In this patch, I introduced a new type of symbol -- DefinedRelative.
DefinedRelative is similar to DefinedAbsolute, but it has not a VA but RVA
and is a subject of base relocation. Currently only __ImageBase is of
the new symbol type.
llvm-svn: 243176
diff --git a/lld/COFF/Symbols.h b/lld/COFF/Symbols.h
index f569a42..2730f9b 100644
--- a/lld/COFF/Symbols.h
+++ b/lld/COFF/Symbols.h
@@ -59,6 +59,7 @@
DefinedImportThunkKind,
DefinedImportDataKind,
DefinedAbsoluteKind,
+ DefinedRelativeKind,
DefinedBitcodeKind,
UndefinedKind,
@@ -222,6 +223,26 @@
uint64_t VA;
};
+// This is a kind of absolute symbol but relative to the image base.
+// Unlike absolute symbols, relocations referring this kind of symbols
+// are subject of the base relocation. This type is used rarely --
+// mainly for __ImageBase.
+class DefinedRelative : public Defined {
+public:
+ explicit DefinedRelative(StringRef Name, uint64_t V = 0)
+ : Defined(DefinedRelativeKind, Name), RVA(V) {}
+
+ static bool classof(const SymbolBody *S) {
+ return S->kind() == DefinedRelativeKind;
+ }
+
+ uint64_t getRVA() { return RVA; }
+ void setRVA(uint64_t V) { RVA = V; }
+
+private:
+ uint64_t RVA;
+};
+
// This class represents a symbol defined in an archive file. It is
// created from an archive file header, and it knows how to load an
// object file from an archive to replace itself with a defined
@@ -364,6 +385,8 @@
switch (kind()) {
case DefinedAbsoluteKind:
return cast<DefinedAbsolute>(this)->getRVA();
+ case DefinedRelativeKind:
+ return cast<DefinedRelative>(this)->getRVA();
case DefinedImportDataKind:
return cast<DefinedImportData>(this)->getRVA();
case DefinedImportThunkKind: