summaryrefslogtreecommitdiffstats
path: root/lld/COFF
diff options
context:
space:
mode:
Diffstat (limited to 'lld/COFF')
-rw-r--r--lld/COFF/Chunks.cpp15
-rw-r--r--lld/COFF/Symbols.cpp2
-rw-r--r--lld/COFF/Symbols.h5
-rw-r--r--lld/COFF/Writer.cpp6
4 files changed, 25 insertions, 3 deletions
diff --git a/lld/COFF/Chunks.cpp b/lld/COFF/Chunks.cpp
index 1d5ae5571d2..56124acaf9a 100644
--- a/lld/COFF/Chunks.cpp
+++ b/lld/COFF/Chunks.cpp
@@ -52,6 +52,15 @@ 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); }
static void or16(uint8_t *P, uint16_t V) { write16le(P, read16le(P) | V); }
+static void applySecRel(const SectionChunk *Sec, uint8_t *Off, Defined *Sym) {
+ // Don't apply section relative relocations to absolute symbols in codeview
+ // debug info sections. MSVC does not treat such relocations as fatal errors,
+ // and they can be found in the standard library for linker-provided symbols
+ // like __guard_fids_table and __safe_se_handler_table.
+ if (!(isa<DefinedAbsolute>(Sym) && Sec->isCodeView()))
+ add32(Off, Sym->getSecrel());
+}
+
void SectionChunk::applyRelX64(uint8_t *Off, uint16_t Type, Defined *Sym,
uint64_t P) const {
uint64_t S = Sym->getRVA();
@@ -66,7 +75,7 @@ void SectionChunk::applyRelX64(uint8_t *Off, uint16_t Type, Defined *Sym,
case IMAGE_REL_AMD64_REL32_4: add32(Off, S - P - 8); break;
case IMAGE_REL_AMD64_REL32_5: add32(Off, S - P - 9); break;
case IMAGE_REL_AMD64_SECTION: add16(Off, Sym->getSectionIndex()); break;
- case IMAGE_REL_AMD64_SECREL: add32(Off, Sym->getSecrel()); break;
+ case IMAGE_REL_AMD64_SECREL: applySecRel(this, Off, Sym); break;
default:
fatal("unsupported relocation type 0x" + Twine::utohexstr(Type));
}
@@ -81,7 +90,7 @@ void SectionChunk::applyRelX86(uint8_t *Off, uint16_t Type, Defined *Sym,
case IMAGE_REL_I386_DIR32NB: add32(Off, S); break;
case IMAGE_REL_I386_REL32: add32(Off, S - P - 4); break;
case IMAGE_REL_I386_SECTION: add16(Off, Sym->getSectionIndex()); break;
- case IMAGE_REL_I386_SECREL: add32(Off, Sym->getSecrel()); break;
+ case IMAGE_REL_I386_SECREL: applySecRel(this, Off, Sym); break;
default:
fatal("unsupported relocation type 0x" + Twine::utohexstr(Type));
}
@@ -141,7 +150,7 @@ void SectionChunk::applyRelARM(uint8_t *Off, uint16_t Type, Defined *Sym,
case IMAGE_REL_ARM_BRANCH20T: applyBranch20T(Off, S - P - 4); break;
case IMAGE_REL_ARM_BRANCH24T: applyBranch24T(Off, S - P - 4); break;
case IMAGE_REL_ARM_BLX23T: applyBranch24T(Off, S - P - 4); break;
- case IMAGE_REL_ARM_SECREL: add32(Off, Sym->getSecrel()); break;
+ case IMAGE_REL_ARM_SECREL: applySecRel(this, Off, Sym); break;
default:
fatal("unsupported relocation type 0x" + Twine::utohexstr(Type));
}
diff --git a/lld/COFF/Symbols.cpp b/lld/COFF/Symbols.cpp
index 5c185a511dd..1cf2934a355 100644
--- a/lld/COFF/Symbols.cpp
+++ b/lld/COFF/Symbols.cpp
@@ -61,6 +61,8 @@ COFFSymbolRef DefinedCOFF::getCOFFSymbol() {
return COFFSymbolRef(reinterpret_cast<const coff_symbol32 *>(Sym));
}
+uint16_t DefinedAbsolute::OutputSectionIndex = 0;
+
static Chunk *makeImportThunk(DefinedImportData *S, uint16_t Machine) {
if (Machine == AMD64)
return make<ImportThunkChunkX64>(S);
diff --git a/lld/COFF/Symbols.h b/lld/COFF/Symbols.h
index 801fc87f91d..828744b8ff3 100644
--- a/lld/COFF/Symbols.h
+++ b/lld/COFF/Symbols.h
@@ -212,6 +212,11 @@ public:
uint64_t getRVA() { return VA - Config->ImageBase; }
void setVA(uint64_t V) { VA = V; }
+ // The sentinel absolute symbol section index. Section index relocations
+ // against absolute symbols resolve to this 16 bit number, and it is the
+ // largest valid section index plus one. This is written by the Writer.
+ static uint16_t OutputSectionIndex;
+
private:
uint64_t VA;
};
diff --git a/lld/COFF/Writer.cpp b/lld/COFF/Writer.cpp
index d31f0c3d57a..c67fac59f92 100644
--- a/lld/COFF/Writer.cpp
+++ b/lld/COFF/Writer.cpp
@@ -219,6 +219,8 @@ uint64_t Defined::getSecrel() {
uint64_t Defined::getSectionIndex() {
if (auto *D = dyn_cast<DefinedRegular>(this))
return D->getChunk()->getOutputSection()->SectionIndex;
+ if (auto *D = dyn_cast<DefinedAbsolute>(this))
+ return DefinedAbsolute::OutputSectionIndex;
fatal("SECTION relocation points to a non-regular symbol: " +
toString(*this));
}
@@ -775,6 +777,10 @@ void Writer::setSectionPermissions() {
// Write section contents to a mmap'ed file.
void Writer::writeSections() {
+ // Record the section index that should be used when resolving a section
+ // relocation against an absolute symbol.
+ DefinedAbsolute::OutputSectionIndex = OutputSections.size() + 1;
+
uint8_t *Buf = Buffer->getBufferStart();
for (OutputSection *Sec : OutputSections) {
uint8_t *SecBuf = Buf + Sec->getFileOff();
OpenPOWER on IntegriCloud