summaryrefslogtreecommitdiff
path: root/bolt
diff options
context:
space:
mode:
authorRafael Auler <rafaelauler@fb.com>2023-05-16 12:04:03 -0700
committerRafael Auler <rafaelauler@fb.com>2023-05-16 14:54:16 -0700
commit62a2feff5784bcee3c7b037501956552acdf736c (patch)
tree82ad9bcf29afbe900884a095ed362be7b162a819 /bolt
parent32ab0978dc3f7f7036df2038ee96a4ab89196255 (diff)
downloadllvm-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')
-rw-r--r--bolt/include/bolt/Passes/BinaryPasses.h10
-rw-r--r--bolt/lib/Passes/BinaryPasses.cpp24
-rw-r--r--bolt/lib/Rewrite/BinaryPassManager.cpp4
3 files changed, 38 insertions, 0 deletions
diff --git a/bolt/include/bolt/Passes/BinaryPasses.h b/bolt/include/bolt/Passes/BinaryPasses.h
index 63cef59cfd4e..dace07e903e7 100644
--- a/bolt/include/bolt/Passes/BinaryPasses.h
+++ b/bolt/include/bolt/Passes/BinaryPasses.h
@@ -213,6 +213,16 @@ public:
void runOnFunctions(BinaryContext &BC) override;
};
+/// Clean the state of the MC representation before sending it to emission
+class CleanMCState : public BinaryFunctionPass {
+public:
+ explicit CleanMCState(const cl::opt<bool> &PrintPass)
+ : BinaryFunctionPass(PrintPass) {}
+
+ const char *getName() const override { return "clean-mc-state"; }
+ void runOnFunctions(BinaryContext &BC) override;
+};
+
/// An optimization to simplify conditional tail calls by removing
/// unnecessary branches.
///
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();
}