|
11 | 11 | #include "InputFiles.h" |
12 | 12 | #include "Symbols.h" |
13 | 13 | #include "Writer.h" |
| 14 | +#include "SymbolTable.h" |
14 | 15 | #include "lld/Common/ErrorHandler.h" |
15 | 16 | #include "llvm/ADT/Twine.h" |
16 | 17 | #include "llvm/BinaryFormat/COFF.h" |
@@ -315,6 +316,32 @@ void SectionChunk::applyRelARM64(uint8_t *Off, uint16_t Type, OutputSection *OS, |
315 | 316 | } |
316 | 317 | } |
317 | 318 |
|
| 319 | +static void maybeReportRelocationToDiscarded(const SectionChunk *FromChunk, |
| 320 | + Defined *Sym, |
| 321 | + const coff_relocation &Rel) { |
| 322 | + // Don't report these errors when the relocation comes from a debug info |
| 323 | + // section or in mingw mode. MinGW mode object files (built by GCC) can |
| 324 | + // have leftover sections with relocations against discarded comdat |
| 325 | + // sections. Such sections are left as is, with relocations untouched. |
| 326 | + if (FromChunk->isCodeView() || FromChunk->isDWARF() || Config->MinGW) |
| 327 | + return; |
| 328 | + |
| 329 | + // Get the name of the symbol. If it's null, it was discarded early, so we |
| 330 | + // have to go back to the object file. |
| 331 | + ObjFile *File = FromChunk->File; |
| 332 | + StringRef Name; |
| 333 | + if (Sym) { |
| 334 | + Name = Sym->getName(); |
| 335 | + } else { |
| 336 | + COFFSymbolRef COFFSym = |
| 337 | + check(File->getCOFFObj()->getSymbol(Rel.SymbolTableIndex)); |
| 338 | + File->getCOFFObj()->getSymbolName(COFFSym, Name); |
| 339 | + } |
| 340 | + |
| 341 | + error("relocation against symbol in discarded section: " + Name + |
| 342 | + getSymbolLocations(File, Rel.SymbolTableIndex)); |
| 343 | +} |
| 344 | + |
318 | 345 | void SectionChunk::writeTo(uint8_t *Buf) const { |
319 | 346 | if (!hasData()) |
320 | 347 | return; |
@@ -342,41 +369,23 @@ void SectionChunk::writeTo(uint8_t *Buf) const { |
342 | 369 | // Use the potentially remapped Symbol instead of the one that the |
343 | 370 | // relocation points to. |
344 | 371 | auto *Sym = dyn_cast_or_null<Defined>(RelocTargets[I]); |
345 | | - if (!Sym) { |
346 | | - if (isCodeView() || isDWARF()) |
347 | | - continue; |
348 | | - // Symbols in early discarded sections are represented using null pointers, |
349 | | - // so we need to retrieve the name from the object file. |
350 | | - COFFSymbolRef Sym = |
351 | | - check(File->getCOFFObj()->getSymbol(Rel.SymbolTableIndex)); |
352 | | - StringRef Name; |
353 | | - File->getCOFFObj()->getSymbolName(Sym, Name); |
354 | | - |
355 | | - // MinGW mode object files (built by GCC) can have leftover sections |
356 | | - // with relocations against discarded comdat sections. Such sections |
357 | | - // are left as is, with relocations untouched. |
358 | | - if (!Config->MinGW) |
359 | | - error("relocation against symbol in discarded section: " + Name); |
360 | | - continue; |
361 | | - } |
| 372 | + |
362 | 373 | // Get the output section of the symbol for this relocation. The output |
363 | 374 | // section is needed to compute SECREL and SECTION relocations used in debug |
364 | 375 | // info. |
365 | | - Chunk *C = Sym->getChunk(); |
| 376 | + Chunk *C = Sym ? Sym->getChunk() : nullptr; |
366 | 377 | OutputSection *OS = C ? C->getOutputSection() : nullptr; |
367 | 378 |
|
368 | | - // Only absolute and __ImageBase symbols lack an output section. For any |
369 | | - // other symbol, this indicates that the chunk was discarded. Normally |
370 | | - // relocations against discarded sections are an error. However, debug info |
371 | | - // sections are not GC roots and can end up with these kinds of relocations. |
372 | | - // Skip these relocations. |
373 | | - if (!OS && !isa<DefinedAbsolute>(Sym) && !isa<DefinedSynthetic>(Sym)) { |
374 | | - if (isCodeView() || isDWARF()) |
375 | | - continue; |
376 | | - error("relocation against symbol in discarded section: " + |
377 | | - Sym->getName()); |
| 379 | + // Skip the relocation if it refers to a discarded section, and diagnose it |
| 380 | + // as an error if appropriate. If a symbol was discarded early, it may be |
| 381 | + // null. If it was discarded late, the output section will be null, unless |
| 382 | + // it was an absolute or synthetic symbol. |
| 383 | + if (!Sym || |
| 384 | + (!OS && !isa<DefinedAbsolute>(Sym) && !isa<DefinedSynthetic>(Sym))) { |
| 385 | + maybeReportRelocationToDiscarded(this, Sym, Rel); |
378 | 386 | continue; |
379 | 387 | } |
| 388 | + |
380 | 389 | uint64_t S = Sym->getRVA(); |
381 | 390 |
|
382 | 391 | // Compute the RVA of the relocation for relative relocations. |
|
0 commit comments