-
Notifications
You must be signed in to change notification settings - Fork 15.2k
[BOLT][WIP] Support restartable sequences in tcmalloc #157774
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
@llvm/pr-subscribers-bolt Author: Maksim Panchenko (maksfb) ChangesFull diff: https://github.com/llvm/llvm-project/pull/157774.diff 5 Files Affected:
diff --git a/bolt/include/bolt/Rewrite/MetadataRewriters.h b/bolt/include/bolt/Rewrite/MetadataRewriters.h
index b71bd6cad2505..429c2d7712979 100644
--- a/bolt/include/bolt/Rewrite/MetadataRewriters.h
+++ b/bolt/include/bolt/Rewrite/MetadataRewriters.h
@@ -19,12 +19,14 @@ class BinaryContext;
// The list of rewriter build functions.
-std::unique_ptr<MetadataRewriter> createLinuxKernelRewriter(BinaryContext &);
-
std::unique_ptr<MetadataRewriter> createBuildIDRewriter(BinaryContext &);
+std::unique_ptr<MetadataRewriter> createLinuxKernelRewriter(BinaryContext &);
+
std::unique_ptr<MetadataRewriter> createPseudoProbeRewriter(BinaryContext &);
+std::unique_ptr<MetadataRewriter> createRSeqRewriter(BinaryContext &);
+
std::unique_ptr<MetadataRewriter> createSDTRewriter(BinaryContext &);
} // namespace bolt
diff --git a/bolt/lib/Rewrite/CMakeLists.txt b/bolt/lib/Rewrite/CMakeLists.txt
index 775036063dd5a..12914bfe64301 100644
--- a/bolt/lib/Rewrite/CMakeLists.txt
+++ b/bolt/lib/Rewrite/CMakeLists.txt
@@ -24,6 +24,7 @@ add_llvm_library(LLVMBOLTRewrite
BuildIDRewriter.cpp
PseudoProbeRewriter.cpp
RewriteInstance.cpp
+ RSeqRewriter.cpp
SDTRewriter.cpp
NO_EXPORT
diff --git a/bolt/lib/Rewrite/RSeqRewriter.cpp b/bolt/lib/Rewrite/RSeqRewriter.cpp
new file mode 100644
index 0000000000000..7cbe9ac17da52
--- /dev/null
+++ b/bolt/lib/Rewrite/RSeqRewriter.cpp
@@ -0,0 +1,71 @@
+//===- bolt/Rewrite/RSeqRewriter.cpp --------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// Basic support for restartable sequences used by tcmalloc. Prevent critical
+// section overrides by ignoring optimizations in containing functions.
+//
+// References:
+// * https://google.github.io/tcmalloc/rseq.html
+// * tcmalloc/internal/percpu_rseq_x86_64.S
+//
+//===----------------------------------------------------------------------===//
+
+#include "bolt/Core/BinaryFunction.h"
+#include "bolt/Rewrite/MetadataRewriter.h"
+#include "bolt/Rewrite/MetadataRewriters.h"
+#include "llvm/Support/Errc.h"
+
+using namespace llvm;
+using namespace bolt;
+
+namespace {
+
+class RSeqRewriter final : public MetadataRewriter {
+public:
+ RSeqRewriter(StringRef Name, BinaryContext &BC)
+ : MetadataRewriter(Name, BC) {}
+
+ Error postCFGInitializer() override {
+ for (const BinarySection &Section : BC.allocatableSections()) {
+ if (Section.getName() != "__rseq_cs")
+ continue;
+
+ auto handleRelocation = [&](const Relocation &Rel) {
+ BinaryFunction *BF = nullptr;
+ if (Rel.Symbol)
+ BF = BC.getFunctionForSymbol(Rel.Symbol);
+ else if (Relocation::isRelative(Rel.Type))
+ BF = BC.getBinaryFunctionContainingAddress(Rel.Addend);
+
+ if (BF) {
+ BC.outs() << "BOLT-INFO: restartable sequence detected in " << *BF
+ << ". Function will not be optimized\n";
+ BF->setSimple(false);
+ } else {
+ BC.errs() << "BOLT-WARNING: no function found matching dynamic "
+ "relocation in __rseq_cs\n";
+ }
+ };
+
+ for (const Relocation &Rel : Section.dynamicRelocations())
+ handleRelocation(Rel);
+
+ for (const Relocation &Rel : Section.relocations())
+ handleRelocation(Rel);
+ }
+
+ return Error::success();
+ }
+};
+
+} // namespace
+
+std::unique_ptr<MetadataRewriter>
+llvm::bolt::createRSeqRewriter(BinaryContext &BC) {
+ return std::make_unique<RSeqRewriter>("rseq-cs-rewriter", BC);
+}
diff --git a/bolt/lib/Rewrite/RewriteInstance.cpp b/bolt/lib/Rewrite/RewriteInstance.cpp
index a6e4dbc9c192f..6e07d2ea8d975 100644
--- a/bolt/lib/Rewrite/RewriteInstance.cpp
+++ b/bolt/lib/Rewrite/RewriteInstance.cpp
@@ -3338,6 +3338,8 @@ void RewriteInstance::initializeMetadataManager() {
MetadataManager.registerRewriter(createPseudoProbeRewriter(*BC));
+ MetadataManager.registerRewriter(createRSeqRewriter(*BC));
+
MetadataManager.registerRewriter(createSDTRewriter(*BC));
}
diff --git a/bolt/test/X86/rseq.s b/bolt/test/X86/rseq.s
new file mode 100644
index 0000000000000..7ebc57e1128f4
--- /dev/null
+++ b/bolt/test/X86/rseq.s
@@ -0,0 +1,32 @@
+## Check that llvm-bolt avoids optimization of functions referenced from
+## __rseq_cs section, i.e. containing critical sections used by restartable
+## sequences in tcmalloc.
+
+# RUN: %clang %cflags %s -o %t -nostdlib -no-pie -Wl,-q
+# RUN: llvm-bolt %t -o %t.bolt --print-cfg 2>&1 \
+# RUN: | FileCheck %s --check-prefix=CHECK-NO-PIE
+# RUN: %clang %cflags %s -o %t.pie -nostdlib -pie -Wl,-q
+# RUN: llvm-bolt %t.pie -o %t.pie.bolt 2>&1 \
+# RUN: | FileCheck %s --check-prefix=CHECK-PIE
+
+# CHECK-NO-PIE: Binary Function "_start"
+# CHECK-NO-PIE: IsSimple
+# CHECK-NO-PIE-SAME: 0
+
+# CHECK-PIE: restartable sequence detected in _start
+
+.global _start
+ .type _start, %function
+_start:
+ pushq %rbp
+ mov %rsp, %rbp
+.L1:
+ pop %rbp
+ retq
+.size _start, .-_start
+
+.reloc 0, R_X86_64_NONE
+
+.section __rseq_cs, "aw"
+.balign 32
+ .quad .L1
|
Tried out the patch, it seems to successfully print out all the functions in info but the final binary still crashes. Test:
back to just being TcmallocSlab_Internal_PopBatch/PushBatch and used this new version of bolt. Prints out:
Moved the skip func from TcmallocSlab_Internal_PopBatch/PushBatch back to
and it started working again. |
Thanks for trying the patch out. I'm going to look more into it and specifically at the warnings. Meanwhile, I've updated the patch to ignore the |
Thanks that seems to work! It also turns out almost all the functions on our skip list seem to have been there due to rseq related reasons. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Overall, the patch looks good, and it was verified that ignoring the function does the trick.
One thing it's not clear to me: is fixed code (non-pie) safe, given the heuristic won't detect which functions to ignore?
For the logs, would it be better to condense the BOLT-INFO messages into a warning summary like:
~ N functionsN functions were found in restartable sequences section and were ignored ..
possibly, including a hint to view full details at higher verbosity? Not a strong opinion.
I believe you will also suppress these messages?
BOLT-WARNING: no function found matching dynamic relocation in __rseq_cs
Hi Paschalis, what do you mean by static binaries? Note that we check both types of relocations. |
Hey Maksim, sorry I meant fixed code, ie the non-pie case listed in the test. |
For non-pie, we rely on linker's Let me take another look at the warnings. |
No description provided.