diff options
Diffstat (limited to 'lld/COFF')
| -rw-r--r-- | lld/COFF/Chunks.cpp | 15 | ||||
| -rw-r--r-- | lld/COFF/Symbols.cpp | 2 | ||||
| -rw-r--r-- | lld/COFF/Symbols.h | 5 | ||||
| -rw-r--r-- | lld/COFF/Writer.cpp | 6 |
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(); |

