[BOLT] Ignore AArch64 markers outside their sections. (#74106)

AArch64 uses $d and $x symbols to delimit data embedded in code.
However, sometimes we see $d symbols, typically in .eh_frame, with
addresses that belong to different sections. These occasionally fall
inside .text functions and cause BOLT to stop disassembling, which in
turn causes DWARF CFA processing to fail.

As a workaround, we just ignore symbols with addresses outside the
section they belong to. This behaviour is consistent with objdump and
similar tools.
This commit is contained in:
Jacob Bramley
2024-11-07 12:16:14 +00:00
committed by GitHub
parent 3d0b283dcd
commit 16cd5cdf4d
4 changed files with 155 additions and 3 deletions

View File

@@ -789,9 +789,44 @@ void RewriteInstance::discoverFileObjects() {
BinarySection Section(*BC, *cantFail(Sym.getSection()));
return Section.isAllocatable();
};
auto checkSymbolInSection = [this](const SymbolInfo &S) {
// Sometimes, we encounter symbols with addresses outside their section. If
// such symbols happen to fall into another section, they can interfere with
// disassembly. Notably, this occurs with AArch64 marker symbols ($d and $t)
// that belong to .eh_frame, but end up pointing into .text.
// As a workaround, we ignore all symbols that lie outside their sections.
auto Section = cantFail(S.Symbol.getSection());
// Accept all absolute symbols.
if (Section == InputFile->section_end())
return true;
uint64_t SecStart = Section->getAddress();
uint64_t SecEnd = SecStart + Section->getSize();
uint64_t SymEnd = S.Address + ELFSymbolRef(S.Symbol).getSize();
if (S.Address >= SecStart && SymEnd <= SecEnd)
return true;
auto SymType = cantFail(S.Symbol.getType());
// Skip warnings for common benign cases.
if (opts::Verbosity < 1 && SymType == SymbolRef::ST_Other)
return false; // E.g. ELF::STT_TLS.
auto SymName = S.Symbol.getName();
auto SecName = cantFail(S.Symbol.getSection())->getName();
BC->errs() << "BOLT-WARNING: ignoring symbol "
<< (SymName ? *SymName : "[unnamed]") << " at 0x"
<< Twine::utohexstr(S.Address) << ", which lies outside "
<< (SecName ? *SecName : "[unnamed]") << "\n";
return false;
};
for (const SymbolRef &Symbol : InputFile->symbols())
if (isSymbolInMemory(Symbol))
SortedSymbols.push_back({cantFail(Symbol.getAddress()), Symbol});
if (isSymbolInMemory(Symbol)) {
SymbolInfo SymInfo{cantFail(Symbol.getAddress()), Symbol};
if (checkSymbolInSection(SymInfo))
SortedSymbols.push_back(SymInfo);
}
auto CompareSymbols = [this](const SymbolInfo &A, const SymbolInfo &B) {
if (A.Address != B.Address)