diff options
author | Rafael Auler <rafaelauler@fb.com> | 2023-05-16 12:04:03 -0700 |
---|---|---|
committer | Rafael Auler <rafaelauler@fb.com> | 2023-05-16 14:54:16 -0700 |
commit | 62a2feff5784bcee3c7b037501956552acdf736c (patch) | |
tree | 82ad9bcf29afbe900884a095ed362be7b162a819 /bolt/lib | |
parent | 32ab0978dc3f7f7036df2038ee96a4ab89196255 (diff) | |
download | llvm-62a2feff5784bcee3c7b037501956552acdf736c.tar.gz |
[BOLT] Fix state of MCSymbols in lowering pass
We have mostly harmless data races when running
BinaryContext::calculateEmittedSize() in parallel, while performing
split function pass. However, it is possible to end up in a state
where some MCSymbols are still registered and our clean up
failed. This happens rarely but it does happen, and when it happens,
it is a difficult to diagnose heisenbug. To avoid this, add a new
clean pass to perform a last check on MCSymbols, before they
undergo our final emission pass, to verify that they are in a sane
state. If we fail to do this, we might resolve some symbols to zero
and crash the output binary.
Reviewed By: #bolt, Amir
Differential Revision: https://reviews.llvm.org/D137984
Diffstat (limited to 'bolt/lib')
-rw-r--r-- | bolt/lib/Passes/BinaryPasses.cpp | 24 | ||||
-rw-r--r-- | bolt/lib/Rewrite/BinaryPassManager.cpp | 4 |
2 files changed, 28 insertions, 0 deletions
diff --git a/bolt/lib/Passes/BinaryPasses.cpp b/bolt/lib/Passes/BinaryPasses.cpp index 377176e9c533..872133842b92 100644 --- a/bolt/lib/Passes/BinaryPasses.cpp +++ b/bolt/lib/Passes/BinaryPasses.cpp @@ -626,6 +626,30 @@ void LowerAnnotations::runOnFunctions(BinaryContext &BC) { BC.MIB->setOffset(*Item.first, Item.second); } +// Check for dirty state in MCSymbol objects that might be a consequence +// of running calculateEmittedSize() in parallel, during split functions +// pass. If an inconsistent state is found (symbol already registered or +// already defined), clean it. +void CleanMCState::runOnFunctions(BinaryContext &BC) { + MCContext &Ctx = *BC.Ctx; + for (const auto &SymMapEntry : Ctx.getSymbols()) { + const MCSymbol *S = SymMapEntry.second; + if (S->isDefined()) { + LLVM_DEBUG(dbgs() << "BOLT-DEBUG: Symbol \"" << S->getName() + << "\" is already defined\n"); + const_cast<MCSymbol *>(S)->setUndefined(); + } + if (S->isRegistered()) { + LLVM_DEBUG(dbgs() << "BOLT-DEBUG: Symbol \"" << S->getName() + << "\" is already registered\n"); + const_cast<MCSymbol *>(S)->setIsRegistered(false); + } + LLVM_DEBUG(if (S->isVariable()) { + dbgs() << "BOLT-DEBUG: Symbol \"" << S->getName() << "\" is variable\n"; + }); + } +} + // This peephole fixes jump instructions that jump to another basic // block with a single jump instruction, e.g. // diff --git a/bolt/lib/Rewrite/BinaryPassManager.cpp b/bolt/lib/Rewrite/BinaryPassManager.cpp index 53a45ab58db3..dd00d62bfa71 100644 --- a/bolt/lib/Rewrite/BinaryPassManager.cpp +++ b/bolt/lib/Rewrite/BinaryPassManager.cpp @@ -488,6 +488,10 @@ void BinaryFunctionPassManager::runAllPasses(BinaryContext &BC) { Manager.registerPass(std::make_unique<LowerAnnotations>(NeverPrint)); + // Check for dirty state of MCSymbols caused by running calculateEmittedSize + // in parallel and restore them + Manager.registerPass(std::make_unique<CleanMCState>(NeverPrint)); + Manager.runPasses(); } |