summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--lld/COFF/Chunks.cpp65
1 files changed, 36 insertions, 29 deletions
diff --git a/lld/COFF/Chunks.cpp b/lld/COFF/Chunks.cpp
index 321bfeb0406..ae37a963248 100644
--- a/lld/COFF/Chunks.cpp
+++ b/lld/COFF/Chunks.cpp
@@ -316,6 +316,32 @@ void SectionChunk::applyRelARM64(uint8_t *Off, uint16_t Type, OutputSection *OS,
}
}
+static void maybeReportRelocationToDiscarded(const SectionChunk *FromChunk,
+ Defined *Sym,
+ const coff_relocation &Rel) {
+ // Don't report these errors when the relocation comes from a debug info
+ // section or in mingw mode. MinGW mode object files (built by GCC) can
+ // have leftover sections with relocations against discarded comdat
+ // sections. Such sections are left as is, with relocations untouched.
+ if (FromChunk->isCodeView() || FromChunk->isDWARF() || Config->MinGW)
+ return;
+
+ // Get the name of the symbol. If it's null, it was discarded early, so we
+ // have to go back to the object file.
+ ObjFile *File = FromChunk->File;
+ StringRef Name;
+ if (Sym) {
+ Name = Sym->getName();
+ } else {
+ COFFSymbolRef COFFSym =
+ check(File->getCOFFObj()->getSymbol(Rel.SymbolTableIndex));
+ File->getCOFFObj()->getSymbolName(COFFSym, Name);
+ }
+
+ error("relocation against symbol in discarded section: " + Name +
+ getSymbolLocations(File, Rel.SymbolTableIndex));
+}
+
void SectionChunk::writeTo(uint8_t *Buf) const {
if (!hasData())
return;
@@ -343,42 +369,23 @@ void SectionChunk::writeTo(uint8_t *Buf) const {
// Use the potentially remapped Symbol instead of the one that the
// relocation points to.
auto *Sym = dyn_cast_or_null<Defined>(RelocTargets[I]);
- if (!Sym) {
- if (isCodeView() || isDWARF())
- continue;
- // Symbols in early discarded sections are represented using null pointers,
- // so we need to retrieve the name from the object file.
- COFFSymbolRef Sym =
- check(File->getCOFFObj()->getSymbol(Rel.SymbolTableIndex));
- StringRef Name;
- File->getCOFFObj()->getSymbolName(Sym, Name);
-
- // MinGW mode object files (built by GCC) can have leftover sections
- // with relocations against discarded comdat sections. Such sections
- // are left as is, with relocations untouched.
- if (!Config->MinGW)
- error("relocation against symbol in discarded section: " + Name +
- getSymbolLocations(File, Rel.SymbolTableIndex));
- continue;
- }
+
// Get the output section of the symbol for this relocation. The output
// section is needed to compute SECREL and SECTION relocations used in debug
// info.
- Chunk *C = Sym->getChunk();
+ Chunk *C = Sym ? Sym->getChunk() : nullptr;
OutputSection *OS = C ? C->getOutputSection() : nullptr;
- // Only absolute and __ImageBase symbols lack an output section. For any
- // other symbol, this indicates that the chunk was discarded. Normally
- // relocations against discarded sections are an error. However, debug info
- // sections are not GC roots and can end up with these kinds of relocations.
- // Skip these relocations.
- if (!OS && !isa<DefinedAbsolute>(Sym) && !isa<DefinedSynthetic>(Sym)) {
- if (isCodeView() || isDWARF())
- continue;
- error("relocation against symbol in discarded section: " +
- Sym->getName() + getSymbolLocations(File, Rel.SymbolTableIndex));
+ // Skip the relocation if it refers to a discarded section, and diagnose it
+ // as an error if appropriate. If a symbol was discarded early, it may be
+ // null. If it was discarded late, the output section will be null, unless
+ // it was an absolute or synthetic symbol.
+ if (!Sym ||
+ (!OS && !isa<DefinedAbsolute>(Sym) && !isa<DefinedSynthetic>(Sym))) {
+ maybeReportRelocationToDiscarded(this, Sym, Rel);
continue;
}
+
uint64_t S = Sym->getRVA();
// Compute the RVA of the relocation for relative relocations.
OpenPOWER on IntegriCloud