[llvm] [BOLT] Gadget scanner: implement finer-grained --scanners option (PR #176135)
Anatoly Trosinenko via llvm-commits
llvm-commits at lists.llvm.org
Thu Mar 12 05:06:26 PDT 2026
https://github.com/atrosinenko updated https://github.com/llvm/llvm-project/pull/176135
>From b1c4456dd921c0831222d4b58c400297620ae509 Mon Sep 17 00:00:00 2001
From: Anatoly Trosinenko <atrosinenko at accesssoftek.com>
Date: Wed, 14 Jan 2026 16:54:35 +0300
Subject: [PATCH 1/3] [BOLT] Gadget scanner: implement finer-grained --scanners
option
Add separate options to enable each of the available gadget detectors.
Furthermore, add two meta-options enabling all PtrAuth scanners and all
available scanners of any type (which is only PtrAuth for now, though).
This commit renames `pacret` option to `ptrauth-pac-ret` and `pauth` to
`ptrauth-all`.
---
bolt/include/bolt/Passes/PAuthGadgetScanner.h | 19 ++-
bolt/include/bolt/Utils/CommandLineOpts.h | 23 +++-
bolt/lib/Passes/PAuthGadgetScanner.cpp | 46 ++++---
bolt/lib/Rewrite/RewriteInstance.cpp | 37 +++---
.../binary-analysis/AArch64/cmdline-args.test | 13 +-
.../AArch64/gs-pacret-autiasp.s | 2 +-
.../AArch64/gs-pacret-multi-bb.s | 2 +-
.../AArch64/gs-pauth-address-checks.s | 2 +-
.../gs-pauth-address-materialization.s | 2 +-
.../AArch64/gs-pauth-authentication-oracles.s | 6 +-
.../binary-analysis/AArch64/gs-pauth-calls.s | 7 +-
.../AArch64/gs-pauth-debug-output.s | 8 +-
.../AArch64/gs-pauth-scanners.s | 124 ++++++++++++++++++
.../AArch64/gs-pauth-signing-oracles.s | 7 +-
.../AArch64/gs-pauth-tail-calls.s | 7 +-
.../AArch64/trap-instructions.s | 2 +-
16 files changed, 235 insertions(+), 72 deletions(-)
create mode 100644 bolt/test/binary-analysis/AArch64/gs-pauth-scanners.s
diff --git a/bolt/include/bolt/Passes/PAuthGadgetScanner.h b/bolt/include/bolt/Passes/PAuthGadgetScanner.h
index cb865a725d72a..8482793339be6 100644
--- a/bolt/include/bolt/Passes/PAuthGadgetScanner.h
+++ b/bolt/include/bolt/Passes/PAuthGadgetScanner.h
@@ -161,7 +161,8 @@ class FunctionAnalysisContext {
MCPlusBuilder::AllocatorIdTy AllocatorId;
FunctionAnalysisResult Result;
- bool PacRetGadgetsOnly;
+ /// Bitmask of detectors to run (see opts::GadgetScannerKind).
+ uint64_t EnabledDetectorsMask;
void findUnsafeUses(SmallVector<PartialReport<MCPhysReg>> &Reports);
void augmentUnsafeUseReports(ArrayRef<PartialReport<MCPhysReg>> Reports);
@@ -176,9 +177,9 @@ class FunctionAnalysisContext {
public:
FunctionAnalysisContext(BinaryFunction &BF,
MCPlusBuilder::AllocatorIdTy AllocatorId,
- bool PacRetGadgetsOnly)
+ uint64_t EnabledDetectorsMask)
: BC(BF.getBinaryContext()), BF(BF), AllocatorId(AllocatorId),
- PacRetGadgetsOnly(PacRetGadgetsOnly) {}
+ EnabledDetectorsMask(EnabledDetectorsMask) {}
void run();
@@ -186,8 +187,8 @@ class FunctionAnalysisContext {
};
class Analysis : public BinaryFunctionPass {
- /// Only search for pac-ret violations.
- bool PacRetGadgetsOnly;
+ /// Bitmask of detectors to run (see opts::GadgetScannerKind).
+ uint64_t EnabledDetectorsMask;
void runOnFunction(BinaryFunction &Function,
MCPlusBuilder::AllocatorIdTy AllocatorId);
@@ -196,8 +197,12 @@ class Analysis : public BinaryFunctionPass {
std::mutex AnalysisResultsMutex;
public:
- explicit Analysis(bool PacRetGadgetsOnly)
- : BinaryFunctionPass(false), PacRetGadgetsOnly(PacRetGadgetsOnly) {}
+ /// Constructs the analysis pass.
+ ///
+ /// EnabledDetectorsMask selects the checks to perform, see
+ /// opts::GadgetScannerKind for the available GS_PTRAUTH_* options.
+ explicit Analysis(uint64_t EnabledDetectorsMask)
+ : BinaryFunctionPass(false), EnabledDetectorsMask(EnabledDetectorsMask) {}
const char *getName() const override { return "pauth-gadget-scanner"; }
diff --git a/bolt/include/bolt/Utils/CommandLineOpts.h b/bolt/include/bolt/Utils/CommandLineOpts.h
index 5c7f1b94315f0..5bd83c17aa900 100644
--- a/bolt/include/bolt/Utils/CommandLineOpts.h
+++ b/bolt/include/bolt/Utils/CommandLineOpts.h
@@ -130,9 +130,26 @@ bool processAllFunctions();
/// Return true if we should dump dot graphs for the given function.
bool shouldDumpDot(const llvm::bolt::BinaryFunction &Function);
-enum GadgetScannerKind { GS_PACRET, GS_PAUTH, GS_ALL };
-
-extern llvm::cl::bits<GadgetScannerKind> GadgetScannersToRun;
+enum GadgetScannerKind : uint64_t {
+ /// Scan for unprotected backward control-flow (return instructions).
+ GS_PTRAUTH_RETURN_TARGETS = (1 << 0),
+ /// Scan for tail calls performed with untrusted link register.
+ GS_PTRAUTH_TAIL_CALLS = (1 << 1),
+ /// Scan for unprotected forward control-flow (branch and call instructions).
+ GS_PTRAUTH_BRANCH_AND_CALL_TARGETS = (1 << 2),
+ /// Scan for signing oracles.
+ GS_PTRAUTH_SIGN_ORACLES = (1 << 3),
+ /// Scan for authentication oracles.
+ GS_PTRAUTH_AUTH_ORACLES = (1 << 4),
+
+ /// Scan for all Pointer Authentication issues.
+ GS_PTRAUTH_ALL_MASK = GS_PTRAUTH_RETURN_TARGETS | GS_PTRAUTH_TAIL_CALLS |
+ GS_PTRAUTH_BRANCH_AND_CALL_TARGETS |
+ GS_PTRAUTH_SIGN_ORACLES | GS_PTRAUTH_AUTH_ORACLES,
+
+ /// Run all implemented scanners.
+ GS_ALL_MASK = GS_PTRAUTH_ALL_MASK,
+};
} // namespace opts
diff --git a/bolt/lib/Passes/PAuthGadgetScanner.cpp b/bolt/lib/Passes/PAuthGadgetScanner.cpp
index 22ceeabe36c67..64a197ea9c5a1 100644
--- a/bolt/lib/Passes/PAuthGadgetScanner.cpp
+++ b/bolt/lib/Passes/PAuthGadgetScanner.cpp
@@ -1553,6 +1553,12 @@ collectRegsToTrack(ArrayRef<PartialReport<MCPhysReg>> Reports) {
void FunctionAnalysisContext::findUnsafeUses(
SmallVector<PartialReport<MCPhysReg>> &Reports) {
+ using GSK = opts::GadgetScannerKind;
+ const uint64_t HandledDetectorsMask =
+ GSK::GS_PTRAUTH_ALL_MASK & ~GSK::GS_PTRAUTH_AUTH_ORACLES;
+ if (0 == (EnabledDetectorsMask & HandledDetectorsMask))
+ return;
+
auto Analysis = SrcSafetyAnalysis::create(BF, AllocatorId, {});
LLVM_DEBUG(dbgs() << "Running src register safety analysis...\n");
Analysis->run();
@@ -1617,19 +1623,22 @@ void FunctionAnalysisContext::findUnsafeUses(
return;
}
- if (auto Report = shouldReportReturnGadget(BC, Inst, S))
- Reports.push_back(*Report);
-
- if (PacRetGadgetsOnly)
- return;
-
- if (auto Report = shouldReportUnsafeTailCall(BC, BF, Inst, S))
- Reports.push_back(*Report);
-
- if (auto Report = shouldReportCallGadget(BC, Inst, S))
- Reports.push_back(*Report);
- if (auto Report = shouldReportSigningOracle(BC, Inst, S))
- Reports.push_back(*Report);
+ if (EnabledDetectorsMask & GSK::GS_PTRAUTH_RETURN_TARGETS) {
+ if (auto Report = shouldReportReturnGadget(BC, Inst, S))
+ Reports.push_back(*Report);
+ }
+ if (EnabledDetectorsMask & GSK::GS_PTRAUTH_TAIL_CALLS) {
+ if (auto Report = shouldReportUnsafeTailCall(BC, BF, Inst, S))
+ Reports.push_back(*Report);
+ }
+ if (EnabledDetectorsMask & GSK::GS_PTRAUTH_BRANCH_AND_CALL_TARGETS) {
+ if (auto Report = shouldReportCallGadget(BC, Inst, S))
+ Reports.push_back(*Report);
+ }
+ if (EnabledDetectorsMask & GSK::GS_PTRAUTH_SIGN_ORACLES) {
+ if (auto Report = shouldReportSigningOracle(BC, Inst, S))
+ Reports.push_back(*Report);
+ }
});
}
@@ -1660,8 +1669,11 @@ void FunctionAnalysisContext::augmentUnsafeUseReports(
void FunctionAnalysisContext::findUnsafeDefs(
SmallVector<PartialReport<MCPhysReg>> &Reports) {
- if (PacRetGadgetsOnly)
+ using GSK = opts::GadgetScannerKind;
+ const uint64_t HandledDetectorsMask = GSK::GS_PTRAUTH_AUTH_ORACLES;
+ if (0 == (EnabledDetectorsMask & HandledDetectorsMask))
return;
+
if (AuthTrapsOnFailure)
return;
@@ -1741,7 +1753,7 @@ void FunctionAnalysisContext::run() {
void Analysis::runOnFunction(BinaryFunction &BF,
MCPlusBuilder::AllocatorIdTy AllocatorId) {
- FunctionAnalysisContext FA(BF, AllocatorId, PacRetGadgetsOnly);
+ FunctionAnalysisContext FA(BF, AllocatorId, EnabledDetectorsMask);
FA.run();
const FunctionAnalysisResult &FAR = FA.getResult();
@@ -1850,6 +1862,10 @@ void GenericDiagnostic::generateReport(raw_ostream &OS,
}
Error Analysis::runOnFunctions(BinaryContext &BC) {
+ using GSK = opts::GadgetScannerKind;
+ assert(0 == (EnabledDetectorsMask & ~GSK::GS_PTRAUTH_ALL_MASK) &&
+ "Unrelated detectors requested");
+
ParallelUtilities::WorkFuncWithAllocTy WorkFun =
[&](BinaryFunction &BF, MCPlusBuilder::AllocatorIdTy AllocatorId) {
runOnFunction(BF, AllocatorId);
diff --git a/bolt/lib/Rewrite/RewriteInstance.cpp b/bolt/lib/Rewrite/RewriteInstance.cpp
index cd99b04057a18..c84aabfe2e4ca 100644
--- a/bolt/lib/Rewrite/RewriteInstance.cpp
+++ b/bolt/lib/Rewrite/RewriteInstance.cpp
@@ -286,13 +286,23 @@ static cl::opt<bool> WriteBoltInfoSection(
"bolt-info", cl::desc("write bolt info section in the output binary"),
cl::init(true), cl::Hidden, cl::cat(BoltOutputCategory));
-cl::bits<GadgetScannerKind> GadgetScannersToRun(
- "scanners", cl::desc("which gadget scanners to run"),
+static cl::list<GadgetScannerKind> GadgetScannersToRun(
+ "scanners", cl::desc("Which gadget scanners to run"),
cl::values(
- clEnumValN(GS_PACRET, "pacret",
- "pac-ret: return address protection (subset of \"pauth\")"),
- clEnumValN(GS_PAUTH, "pauth", "All Pointer Authentication scanners"),
- clEnumValN(GS_ALL, "all", "All implemented scanners")),
+ clEnumValN(GS_PTRAUTH_RETURN_TARGETS, "ptrauth-pac-ret",
+ "Unprotected returns (pac-ret)"),
+ clEnumValN(GS_PTRAUTH_TAIL_CALLS, "ptrauth-tail-calls",
+ "Tail calls performed with unprotected link register"),
+ clEnumValN(GS_PTRAUTH_BRANCH_AND_CALL_TARGETS, "ptrauth-forward-cf",
+ "Unprotected calls and branches (forward control-flow)"),
+ clEnumValN(GS_PTRAUTH_SIGN_ORACLES, "ptrauth-sign-oracles",
+ "Signing of untrusted pointers (signing oracles)"),
+ clEnumValN(GS_PTRAUTH_AUTH_ORACLES, "ptrauth-auth-oracles",
+ "Authentication oracles"),
+
+ clEnumValN(GS_PTRAUTH_ALL_MASK, "ptrauth-all",
+ "All Pointer Authentication scanners"),
+ clEnumValN(GS_ALL_MASK, "all", "All implemented scanners")),
cl::ZeroOrMore, cl::CommaSeparated, cl::cat(BinaryAnalysisCategory));
// Primary targets for hooking runtime library initialization hooking
@@ -3872,16 +3882,13 @@ void RewriteInstance::runBinaryAnalyses() {
using PAuthScanner = PAuthGadgetScanner::Analysis;
// If no command line option was given, act as if "all" was specified.
- bool RunAll = !opts::GadgetScannersToRun.getBits() ||
- opts::GadgetScannersToRun.isSet(GSK::GS_ALL);
+ uint64_t AnalysesMask = 0;
+ for (uint64_t Submask : opts::GadgetScannersToRun)
+ AnalysesMask |= Submask;
- if (RunAll || opts::GadgetScannersToRun.isSet(GSK::GS_PAUTH)) {
- Manager.registerPass(
- std::make_unique<PAuthScanner>(/*OnlyPacRetChecks=*/false));
- } else if (RunAll || opts::GadgetScannersToRun.isSet(GSK::GS_PACRET)) {
- Manager.registerPass(
- std::make_unique<PAuthScanner>(/*OnlyPacRetChecks=*/true));
- }
+ uint64_t PAuthAnalysesMask = AnalysesMask & GSK::GS_PTRAUTH_ALL_MASK;
+ if (PAuthAnalysesMask)
+ Manager.registerPass(std::make_unique<PAuthScanner>(PAuthAnalysesMask));
BC->logBOLTErrorsAndQuitOnFatal(Manager.runPasses());
}
diff --git a/bolt/test/binary-analysis/AArch64/cmdline-args.test b/bolt/test/binary-analysis/AArch64/cmdline-args.test
index 9660ad3bf80f7..3221078951ab3 100644
--- a/bolt/test/binary-analysis/AArch64/cmdline-args.test
+++ b/bolt/test/binary-analysis/AArch64/cmdline-args.test
@@ -34,9 +34,14 @@ HELP-EMPTY:
HELP-NEXT: BinaryAnalysis options:
HELP-EMPTY:
HELP-NEXT: --auth-traps-on-failure - Assume authentication instructions always trap on failure
-HELP-NEXT: --scanners=<value> - which gadget scanners to run
-HELP-NEXT: =pacret - pac-ret: return address protection (subset of "pauth")
-HELP-NEXT: =pauth - All Pointer Authentication scanners
-HELP-NEXT: =all - All implemented scanners
+HELP-NEXT: --scanners=<value> - Which gadget scanners to run
+HELP-NEXT: =ptrauth-pac-ret - Unprotected returns (pac-ret)
+HELP-NEXT: =ptrauth-tail-calls - Tail calls performed with unprotected link register
+HELP-NEXT: =ptrauth-forward-cf - Unprotected calls and branches (forward control-flow)
+HELP-NEXT: =ptrauth-sign-oracles - Signing of untrusted pointers (signing oracles)
+HELP-NEXT: =ptrauth-auth-oracles - Authentication oracles
+HELP-NEXT: =ptrauth-all - All Pointer Authentication scanners
+HELP-NEXT: =all - All implemented scanners
+
HELP-EMPTY:
HELP-NEXT: Generic Options:
diff --git a/bolt/test/binary-analysis/AArch64/gs-pacret-autiasp.s b/bolt/test/binary-analysis/AArch64/gs-pacret-autiasp.s
index 8e991fade2c86..c0aa91ce21935 100644
--- a/bolt/test/binary-analysis/AArch64/gs-pacret-autiasp.s
+++ b/bolt/test/binary-analysis/AArch64/gs-pacret-autiasp.s
@@ -1,5 +1,5 @@
// RUN: %clang %cflags -march=armv9.5-a+pauth-lr -mbranch-protection=pac-ret %s %p/../../Inputs/asm_main.c -o %t.exe
-// RUN: llvm-bolt-binary-analysis --scanners=pacret %t.exe 2>&1 | FileCheck %s
+// RUN: llvm-bolt-binary-analysis --scanners=ptrauth-pac-ret %t.exe 2>&1 | FileCheck %s
.text
diff --git a/bolt/test/binary-analysis/AArch64/gs-pacret-multi-bb.s b/bolt/test/binary-analysis/AArch64/gs-pacret-multi-bb.s
index bd8edbc676c34..89fdf9f20a74d 100644
--- a/bolt/test/binary-analysis/AArch64/gs-pacret-multi-bb.s
+++ b/bolt/test/binary-analysis/AArch64/gs-pacret-multi-bb.s
@@ -1,5 +1,5 @@
// RUN: %clang %cflags -march=armv8.3-a -mbranch-protection=pac-ret %s %p/../../Inputs/asm_main.c -o %t.exe
-// RUN: llvm-bolt-binary-analysis --scanners=pacret %t.exe 2>&1 | FileCheck %s
+// RUN: llvm-bolt-binary-analysis --scanners=ptrauth-pac-ret %t.exe 2>&1 | FileCheck %s
// Verify that we can also detect gadgets across basic blocks
diff --git a/bolt/test/binary-analysis/AArch64/gs-pauth-address-checks.s b/bolt/test/binary-analysis/AArch64/gs-pauth-address-checks.s
index 74f276197923f..84063960a31f0 100644
--- a/bolt/test/binary-analysis/AArch64/gs-pauth-address-checks.s
+++ b/bolt/test/binary-analysis/AArch64/gs-pauth-address-checks.s
@@ -1,5 +1,5 @@
// RUN: %clang %cflags -march=armv8.3-a %s -o %t.exe -Wl,--emit-relocs
-// RUN: llvm-bolt-binary-analysis --scanners=pauth %t.exe 2>&1 | FileCheck %s
+// RUN: llvm-bolt-binary-analysis --scanners=ptrauth-all %t.exe 2>&1 | FileCheck %s
.text
diff --git a/bolt/test/binary-analysis/AArch64/gs-pauth-address-materialization.s b/bolt/test/binary-analysis/AArch64/gs-pauth-address-materialization.s
index 6648f96ad7d08..1c160f47468d7 100644
--- a/bolt/test/binary-analysis/AArch64/gs-pauth-address-materialization.s
+++ b/bolt/test/binary-analysis/AArch64/gs-pauth-address-materialization.s
@@ -1,6 +1,6 @@
// -Wl,--no-relax prevents converting ADRP+ADD pairs into NOP+ADR.
// RUN: %clang %cflags -march=armv8.3-a -Wl,--no-relax %s -o %t.exe
-// RUN: llvm-bolt-binary-analysis --scanners=pauth %t.exe 2>&1 | FileCheck %s
+// RUN: llvm-bolt-binary-analysis --scanners=ptrauth-all %t.exe 2>&1 | FileCheck %s
// Test various patterns that should or should not be considered safe
// materialization of PC-relative addresses.
diff --git a/bolt/test/binary-analysis/AArch64/gs-pauth-authentication-oracles.s b/bolt/test/binary-analysis/AArch64/gs-pauth-authentication-oracles.s
index 9f580b66f47c7..69ae9a086b990 100644
--- a/bolt/test/binary-analysis/AArch64/gs-pauth-authentication-oracles.s
+++ b/bolt/test/binary-analysis/AArch64/gs-pauth-authentication-oracles.s
@@ -1,14 +1,12 @@
// RUN: %clang %cflags -march=armv8.3-a %s -o %t.exe
-// RUN: llvm-bolt-binary-analysis --scanners=pacret %t.exe 2>&1 | FileCheck -check-prefix=PACRET %s
-// RUN: llvm-bolt-binary-analysis --scanners=pauth --auth-traps-on-failure %t.exe 2>&1 | FileCheck -check-prefix=FPAC %s
-// RUN: llvm-bolt-binary-analysis --scanners=pauth %t.exe 2>&1 | FileCheck %s
+// RUN: llvm-bolt-binary-analysis --scanners=ptrauth-auth-oracles --auth-traps-on-failure %t.exe 2>&1 | FileCheck -check-prefix=FPAC %s
+// RUN: llvm-bolt-binary-analysis --scanners=ptrauth-auth-oracles %t.exe 2>&1 | FileCheck %s
// The detection of compiler-generated explicit pointer checks is tested in
// gs-pauth-address-checks.s, for that reason only test here "dummy-load" and
// "high-bits-notbi" checkers, as the shortest examples of checkers that are
// detected per-instruction and per-BB.
-// PACRET-NOT: authentication oracle found in function
// FPAC-NOT: authentication oracle found in function
.text
diff --git a/bolt/test/binary-analysis/AArch64/gs-pauth-calls.s b/bolt/test/binary-analysis/AArch64/gs-pauth-calls.s
index 5e88e105a33f0..c270fcaa26aa5 100644
--- a/bolt/test/binary-analysis/AArch64/gs-pauth-calls.s
+++ b/bolt/test/binary-analysis/AArch64/gs-pauth-calls.s
@@ -1,9 +1,6 @@
// RUN: %clang %cflags -march=armv8.3-a %s -o %t.exe
-// RUN: llvm-bolt-binary-analysis --scanners=pacret %t.exe 2>&1 | FileCheck -check-prefix=PACRET %s
-// RUN: llvm-bolt-binary-analysis --scanners=pauth --auth-traps-on-failure %t.exe 2>&1 | FileCheck %s
-// RUN: llvm-bolt-binary-analysis --scanners=pauth %t.exe 2>&1 | FileCheck %s
-
-// PACRET-NOT: non-protected call found in function
+// RUN: llvm-bolt-binary-analysis --scanners=ptrauth-forward-cf --auth-traps-on-failure %t.exe 2>&1 | FileCheck %s
+// RUN: llvm-bolt-binary-analysis --scanners=ptrauth-forward-cf %t.exe 2>&1 | FileCheck %s
.text
diff --git a/bolt/test/binary-analysis/AArch64/gs-pauth-debug-output.s b/bolt/test/binary-analysis/AArch64/gs-pauth-debug-output.s
index a3ad7effe4b0d..77ccec73f5fca 100644
--- a/bolt/test/binary-analysis/AArch64/gs-pauth-debug-output.s
+++ b/bolt/test/binary-analysis/AArch64/gs-pauth-debug-output.s
@@ -1,13 +1,13 @@
// REQUIRES: asserts
//
// RUN: %clang %cflags -march=armv8.3-a %s -o %t.exe
-// RUN: llvm-bolt-binary-analysis --scanners=pacret --no-threads \
+// RUN: llvm-bolt-binary-analysis --scanners=ptrauth-pac-ret --no-threads \
// RUN: -debug-only bolt-pauth-scanner %t.exe 2>&1 | FileCheck -check-prefixes=CHECK,NOFPAC %s
-// RUN: llvm-bolt-binary-analysis --scanners=pacret --no-threads --auth-traps-on-failure \
+// RUN: llvm-bolt-binary-analysis --scanners=ptrauth-pac-ret --no-threads --auth-traps-on-failure \
// RUN: -debug-only bolt-pauth-scanner %t.exe 2>&1 | FileCheck -check-prefixes=CHECK,FPAC %s
-// RUN: llvm-bolt-binary-analysis --scanners=pauth --no-threads \
+// RUN: llvm-bolt-binary-analysis --scanners=ptrauth-all --no-threads \
// RUN: -debug-only bolt-pauth-scanner %t.exe 2>&1 | FileCheck -check-prefixes=CHECK,NOFPAC,AUTH-ORACLES,PAUTH %s
-// RUN: llvm-bolt-binary-analysis --scanners=pauth --no-threads --auth-traps-on-failure \
+// RUN: llvm-bolt-binary-analysis --scanners=ptrauth-all --no-threads --auth-traps-on-failure \
// RUN: -debug-only bolt-pauth-scanner %t.exe 2>&1 | FileCheck -check-prefixes=CHECK,FPAC,PAUTH %s
// Check the debug output generated by PAuth gadget scanner to make sure the
diff --git a/bolt/test/binary-analysis/AArch64/gs-pauth-scanners.s b/bolt/test/binary-analysis/AArch64/gs-pauth-scanners.s
new file mode 100644
index 0000000000000..2fb7b2e3d9d99
--- /dev/null
+++ b/bolt/test/binary-analysis/AArch64/gs-pauth-scanners.s
@@ -0,0 +1,124 @@
+// RUN: %clang %cflags -march=armv8.3-a %s -o %t.exe
+
+// Select single detector:
+//
+// RUN: llvm-bolt-binary-analysis --scanners=ptrauth-pac-ret %t.exe 2>&1 | \
+// RUN: FileCheck %s --implicit-check-not="found in function" \
+// RUN: --check-prefixes=PACRET
+// RUN: llvm-bolt-binary-analysis --scanners=ptrauth-tail-calls %t.exe 2>&1 | \
+// RUN: FileCheck %s --implicit-check-not="found in function" \
+// RUN: --check-prefixes=TAIL-CALLS-COMMON,TAIL-CALLS-NOFPAC
+// RUN: llvm-bolt-binary-analysis --scanners=ptrauth-forward-cf %t.exe 2>&1 | \
+// RUN: FileCheck %s --implicit-check-not="found in function" \
+// RUN: --check-prefixes=FORWARD-CF
+// RUN: llvm-bolt-binary-analysis --scanners=ptrauth-sign-oracles %t.exe 2>&1 | \
+// RUN: FileCheck %s --implicit-check-not="found in function" \
+// RUN: --check-prefixes=SIGN-ORACLES-COMMON,SIGN-ORACLES-NOFPAC
+// RUN: llvm-bolt-binary-analysis --scanners=ptrauth-auth-oracles %t.exe 2>&1 | \
+// RUN: FileCheck %s --implicit-check-not="found in function" \
+// RUN: --check-prefixes=AUTH-ORACLES-NOFPAC
+
+// Select multiple options (either disjoint or not):
+//
+// RUN: llvm-bolt-binary-analysis --scanners=ptrauth-pac-ret,ptrauth-forward-cf %t.exe 2>&1 | \
+// RUN: FileCheck %s --implicit-check-not="found in function" \
+// RUN: --check-prefixes=PACRET,FORWARD-CF
+// RUN: llvm-bolt-binary-analysis --scanners=ptrauth-pac-ret,ptrauth-all %t.exe 2>&1 | \
+// RUN: FileCheck %s --implicit-check-not="found in function" \
+// RUN: --check-prefixes=PACRET,TAIL-CALLS-COMMON,TAIL-CALLS-NOFPAC,FORWARD-CF,SIGN-ORACLES-COMMON,SIGN-ORACLES-NOFPAC,AUTH-ORACLES-NOFPAC
+
+// Select one of "all" options:
+//
+// RUN: llvm-bolt-binary-analysis --scanners=ptrauth-all %t.exe 2>&1 | \
+// RUN: FileCheck %s --implicit-check-not="found in function" \
+// RUN: --check-prefixes=PACRET,TAIL-CALLS-COMMON,TAIL-CALLS-NOFPAC,FORWARD-CF,SIGN-ORACLES-COMMON,SIGN-ORACLES-NOFPAC,AUTH-ORACLES-NOFPAC
+// RUN: llvm-bolt-binary-analysis --scanners=all %t.exe 2>&1 | \
+// RUN: FileCheck %s --implicit-check-not="found in function" \
+// RUN: --check-prefixes=PACRET,TAIL-CALLS-COMMON,TAIL-CALLS-NOFPAC,FORWARD-CF,SIGN-ORACLES-COMMON,SIGN-ORACLES-NOFPAC,AUTH-ORACLES-NOFPAC
+
+// Test FPAC handling:
+//
+// RUN: llvm-bolt-binary-analysis --auth-traps-on-failure --scanners=ptrauth-all %t.exe 2>&1 | \
+// RUN: FileCheck %s --implicit-check-not="found in function" \
+// RUN: --check-prefixes=PACRET,TAIL-CALLS-COMMON,FORWARD-CF,SIGN-ORACLES-COMMON
+// RUN: llvm-bolt-binary-analysis --auth-traps-on-failure --scanners=ptrauth-auth-oracles %t.exe 2>&1 | \
+// RUN: FileCheck %s --check-prefixes=NO-REPORTS
+
+// NO-REPORTS-NOT: found in function
+
+ .text
+
+ .globl callee
+ .type callee, at function
+callee:
+ ret
+ .size callee, .-callee
+
+ .globl bad_pacret
+ .type bad_pacret, at function
+bad_pacret:
+// PACRET: GS-PAUTH: non-protected ret found in function bad_pacret
+ stp x29, x30, [sp, #-16]!
+ mov x29, sp
+
+ ldp x29, x30, [sp], #16
+ ret
+ .size bad_pacret, .-bad_pacret
+
+ .globl bad_tail_call_common
+ .type bad_tail_call_common, at function
+bad_tail_call_common:
+// TAIL-CALLS-COMMON: GS-PAUTH: untrusted link register found before tail call in function bad_tail_call_common
+ stp x29, x30, [sp, #-16]!
+ mov x29, sp
+
+ ldp x29, x30, [sp], #16
+ b callee
+ .size bad_tail_call_common, .-bad_tail_call_common
+
+ .globl bad_tail_call_nofpac
+ .type bad_tail_call_nofpac, at function
+bad_tail_call_nofpac:
+// TAIL-CALLS-NOFPAC: GS-PAUTH: untrusted link register found before tail call in function bad_tail_call_nofpac
+// AUTH-ORACLES-NOFPAC: GS-PAUTH: authentication oracle found in function bad_tail_call_nofpac
+ paciasp
+ stp x29, x30, [sp, #-16]!
+ mov x29, sp
+
+ ldp x29, x30, [sp], #16
+ autiasp
+ b callee
+ .size bad_tail_call_nofpac, .-bad_tail_call_nofpac
+
+ .globl bad_call
+ .type bad_call, at function
+bad_call:
+// FORWARD-CF: GS-PAUTH: non-protected call found in function bad_call
+ br x0
+ .size bad_call, .-bad_call
+
+ .globl bad_signing_oracle_common
+ .type bad_signing_oracle_common, at function
+bad_signing_oracle_common:
+// SIGN-ORACLES-COMMON: GS-PAUTH: signing oracle found in function bad_signing_oracle_common
+ pacda x0, x1
+ ret
+ .size bad_signing_oracle_common, .-bad_signing_oracle_common
+
+ .globl bad_signing_oracle_nofpac
+ .type bad_signing_oracle_nofpac, at function
+bad_signing_oracle_nofpac:
+// SIGN-ORACLES-NOFPAC: GS-PAUTH: signing oracle found in function bad_signing_oracle_nofpac
+// AUTH-ORACLES-NOFPAC: GS-PAUTH: authentication oracle found in function bad_signing_oracle_nofpac
+ autda x0, x1
+ pacdb x0, x1
+ ret
+ .size bad_signing_oracle_nofpac, .-bad_signing_oracle_nofpac
+
+ .globl bad_auth_oracle
+ .type bad_auth_oracle, at function
+bad_auth_oracle:
+// AUTH-ORACLES-NOFPAC: GS-PAUTH: authentication oracle found in function bad_auth_oracle
+ autda x0, x1
+ ret
+ .size bad_auth_oracle, .-bad_auth_oracle
diff --git a/bolt/test/binary-analysis/AArch64/gs-pauth-signing-oracles.s b/bolt/test/binary-analysis/AArch64/gs-pauth-signing-oracles.s
index 7d908f234d852..920782bbacab1 100644
--- a/bolt/test/binary-analysis/AArch64/gs-pauth-signing-oracles.s
+++ b/bolt/test/binary-analysis/AArch64/gs-pauth-signing-oracles.s
@@ -1,15 +1,12 @@
// RUN: %clang %cflags -march=armv8.3-a+pauth-lr -Wl,--no-relax %s -o %t.exe
-// RUN: llvm-bolt-binary-analysis --scanners=pacret %t.exe 2>&1 | FileCheck -check-prefix=PACRET %s
-// RUN: llvm-bolt-binary-analysis --scanners=pauth %t.exe 2>&1 | FileCheck -check-prefixes=CHECK,NOFPAC %s
-// RUN: llvm-bolt-binary-analysis --scanners=pauth --auth-traps-on-failure %t.exe 2>&1 | FileCheck -check-prefixes=CHECK,FPAC %s
+// RUN: llvm-bolt-binary-analysis --scanners=ptrauth-sign-oracles %t.exe 2>&1 | FileCheck -check-prefixes=CHECK,NOFPAC %s
+// RUN: llvm-bolt-binary-analysis --scanners=ptrauth-sign-oracles --auth-traps-on-failure %t.exe 2>&1 | FileCheck -check-prefixes=CHECK,FPAC %s
// The detection of compiler-generated explicit pointer checks is tested in
// gs-pauth-address-checks.s, for that reason only test here "dummy-load" and
// "high-bits-notbi" checkers, as the shortest examples of checkers that are
// detected per-instruction and per-BB.
-// PACRET-NOT: signing oracle found in function
-
.text
.type sym, at function
diff --git a/bolt/test/binary-analysis/AArch64/gs-pauth-tail-calls.s b/bolt/test/binary-analysis/AArch64/gs-pauth-tail-calls.s
index 59b7d929275a9..daef83c69cec0 100644
--- a/bolt/test/binary-analysis/AArch64/gs-pauth-tail-calls.s
+++ b/bolt/test/binary-analysis/AArch64/gs-pauth-tail-calls.s
@@ -1,9 +1,6 @@
// RUN: %clang %cflags -Wl,--entry=_custom_start -march=armv8.3-a %s -o %t.exe
-// RUN: llvm-bolt-binary-analysis --scanners=pacret %t.exe 2>&1 | FileCheck -check-prefix=PACRET %s
-// RUN: llvm-bolt-binary-analysis --scanners=pauth --auth-traps-on-failure %t.exe 2>&1 | FileCheck -check-prefixes=CHECK,FPAC %s
-// RUN: llvm-bolt-binary-analysis --scanners=pauth %t.exe 2>&1 | FileCheck -check-prefixes=CHECK,NOFPAC %s
-
-// PACRET-NOT: untrusted link register found before tail call
+// RUN: llvm-bolt-binary-analysis --scanners=ptrauth-all --auth-traps-on-failure %t.exe 2>&1 | FileCheck -check-prefixes=CHECK,FPAC %s
+// RUN: llvm-bolt-binary-analysis --scanners=ptrauth-all %t.exe 2>&1 | FileCheck -check-prefixes=CHECK,NOFPAC %s
.text
diff --git a/bolt/test/binary-analysis/AArch64/trap-instructions.s b/bolt/test/binary-analysis/AArch64/trap-instructions.s
index 7810b2d3c3626..0d61440a5ed5a 100644
--- a/bolt/test/binary-analysis/AArch64/trap-instructions.s
+++ b/bolt/test/binary-analysis/AArch64/trap-instructions.s
@@ -1,5 +1,5 @@
// RUN: %clang %cflags -march=armv8.3-a %s -o %t.exe -Wl,--emit-relocs
-// RUN: llvm-bolt-binary-analysis --scanners=pauth %t.exe 2>&1 | FileCheck %s
+// RUN: llvm-bolt-binary-analysis --scanners=ptrauth-all %t.exe 2>&1 | FileCheck %s
// Test what instructions can be used to terminate the program abnormally
// on security violation.
>From 86f93d95f38aa81bd1580c2617ad13c2b1ea4498 Mon Sep 17 00:00:00 2001
From: Anatoly Trosinenko <atrosinenko at accesssoftek.com>
Date: Wed, 11 Mar 2026 21:50:29 +0300
Subject: [PATCH 2/3] Do not hardcode underlying type of bitmask
---
bolt/include/bolt/Passes/PAuthGadgetScanner.h | 19 ++++-----
bolt/include/bolt/Utils/CommandLineOpts.h | 3 +-
bolt/lib/Passes/PAuthGadgetScanner.cpp | 39 ++++++++++++-------
bolt/lib/Rewrite/RewriteInstance.cpp | 20 +++++-----
4 files changed, 43 insertions(+), 38 deletions(-)
diff --git a/bolt/include/bolt/Passes/PAuthGadgetScanner.h b/bolt/include/bolt/Passes/PAuthGadgetScanner.h
index 8482793339be6..4f8195c6920b0 100644
--- a/bolt/include/bolt/Passes/PAuthGadgetScanner.h
+++ b/bolt/include/bolt/Passes/PAuthGadgetScanner.h
@@ -13,6 +13,7 @@
#include "bolt/Core/BinaryFunction.h"
#include "bolt/Core/MCInstUtils.h"
#include "bolt/Passes/BinaryPasses.h"
+#include "bolt/Utils/CommandLineOpts.h"
#include "llvm/Support/raw_ostream.h"
#include <memory>
@@ -161,8 +162,8 @@ class FunctionAnalysisContext {
MCPlusBuilder::AllocatorIdTy AllocatorId;
FunctionAnalysisResult Result;
- /// Bitmask of detectors to run (see opts::GadgetScannerKind).
- uint64_t EnabledDetectorsMask;
+ /// Bitmask of detectors to run (only GS_PTRAUTH_* are allowed).
+ opts::GadgetKindBitmask EnabledDetectors;
void findUnsafeUses(SmallVector<PartialReport<MCPhysReg>> &Reports);
void augmentUnsafeUseReports(ArrayRef<PartialReport<MCPhysReg>> Reports);
@@ -177,9 +178,7 @@ class FunctionAnalysisContext {
public:
FunctionAnalysisContext(BinaryFunction &BF,
MCPlusBuilder::AllocatorIdTy AllocatorId,
- uint64_t EnabledDetectorsMask)
- : BC(BF.getBinaryContext()), BF(BF), AllocatorId(AllocatorId),
- EnabledDetectorsMask(EnabledDetectorsMask) {}
+ opts::GadgetKindBitmask EnabledDetectors);
void run();
@@ -187,8 +186,8 @@ class FunctionAnalysisContext {
};
class Analysis : public BinaryFunctionPass {
- /// Bitmask of detectors to run (see opts::GadgetScannerKind).
- uint64_t EnabledDetectorsMask;
+ /// Bitmask of detectors to run.
+ opts::GadgetKindBitmask EnabledDetectors;
void runOnFunction(BinaryFunction &Function,
MCPlusBuilder::AllocatorIdTy AllocatorId);
@@ -198,11 +197,7 @@ class Analysis : public BinaryFunctionPass {
public:
/// Constructs the analysis pass.
- ///
- /// EnabledDetectorsMask selects the checks to perform, see
- /// opts::GadgetScannerKind for the available GS_PTRAUTH_* options.
- explicit Analysis(uint64_t EnabledDetectorsMask)
- : BinaryFunctionPass(false), EnabledDetectorsMask(EnabledDetectorsMask) {}
+ explicit Analysis(opts::GadgetKindBitmask EnabledDetectors);
const char *getName() const override { return "pauth-gadget-scanner"; }
diff --git a/bolt/include/bolt/Utils/CommandLineOpts.h b/bolt/include/bolt/Utils/CommandLineOpts.h
index 5bd83c17aa900..cb4b3c73bd3fc 100644
--- a/bolt/include/bolt/Utils/CommandLineOpts.h
+++ b/bolt/include/bolt/Utils/CommandLineOpts.h
@@ -130,7 +130,8 @@ bool processAllFunctions();
/// Return true if we should dump dot graphs for the given function.
bool shouldDumpDot(const llvm::bolt::BinaryFunction &Function);
-enum GadgetScannerKind : uint64_t {
+/// Bitmask representing a subset of possible gadget scanner kinds.
+enum GadgetKindBitmask : unsigned {
/// Scan for unprotected backward control-flow (return instructions).
GS_PTRAUTH_RETURN_TARGETS = (1 << 0),
/// Scan for tail calls performed with untrusted link register.
diff --git a/bolt/lib/Passes/PAuthGadgetScanner.cpp b/bolt/lib/Passes/PAuthGadgetScanner.cpp
index 64a197ea9c5a1..542af49e26205 100644
--- a/bolt/lib/Passes/PAuthGadgetScanner.cpp
+++ b/bolt/lib/Passes/PAuthGadgetScanner.cpp
@@ -1553,10 +1553,9 @@ collectRegsToTrack(ArrayRef<PartialReport<MCPhysReg>> Reports) {
void FunctionAnalysisContext::findUnsafeUses(
SmallVector<PartialReport<MCPhysReg>> &Reports) {
- using GSK = opts::GadgetScannerKind;
- const uint64_t HandledDetectorsMask =
- GSK::GS_PTRAUTH_ALL_MASK & ~GSK::GS_PTRAUTH_AUTH_ORACLES;
- if (0 == (EnabledDetectorsMask & HandledDetectorsMask))
+ const auto HandledDetectors =
+ opts::GS_PTRAUTH_ALL_MASK & ~opts::GS_PTRAUTH_AUTH_ORACLES;
+ if (!(EnabledDetectors & HandledDetectors))
return;
auto Analysis = SrcSafetyAnalysis::create(BF, AllocatorId, {});
@@ -1623,19 +1622,19 @@ void FunctionAnalysisContext::findUnsafeUses(
return;
}
- if (EnabledDetectorsMask & GSK::GS_PTRAUTH_RETURN_TARGETS) {
+ if (EnabledDetectors & opts::GS_PTRAUTH_RETURN_TARGETS) {
if (auto Report = shouldReportReturnGadget(BC, Inst, S))
Reports.push_back(*Report);
}
- if (EnabledDetectorsMask & GSK::GS_PTRAUTH_TAIL_CALLS) {
+ if (EnabledDetectors & opts::GS_PTRAUTH_TAIL_CALLS) {
if (auto Report = shouldReportUnsafeTailCall(BC, BF, Inst, S))
Reports.push_back(*Report);
}
- if (EnabledDetectorsMask & GSK::GS_PTRAUTH_BRANCH_AND_CALL_TARGETS) {
+ if (EnabledDetectors & opts::GS_PTRAUTH_BRANCH_AND_CALL_TARGETS) {
if (auto Report = shouldReportCallGadget(BC, Inst, S))
Reports.push_back(*Report);
}
- if (EnabledDetectorsMask & GSK::GS_PTRAUTH_SIGN_ORACLES) {
+ if (EnabledDetectors & opts::GS_PTRAUTH_SIGN_ORACLES) {
if (auto Report = shouldReportSigningOracle(BC, Inst, S))
Reports.push_back(*Report);
}
@@ -1669,9 +1668,8 @@ void FunctionAnalysisContext::augmentUnsafeUseReports(
void FunctionAnalysisContext::findUnsafeDefs(
SmallVector<PartialReport<MCPhysReg>> &Reports) {
- using GSK = opts::GadgetScannerKind;
- const uint64_t HandledDetectorsMask = GSK::GS_PTRAUTH_AUTH_ORACLES;
- if (0 == (EnabledDetectorsMask & HandledDetectorsMask))
+ const auto HandledDetectors = opts::GS_PTRAUTH_AUTH_ORACLES;
+ if (!(EnabledDetectors & HandledDetectors))
return;
if (AuthTrapsOnFailure)
@@ -1731,6 +1729,15 @@ void FunctionAnalysisContext::handleSimpleReports(
llvm::erase_if(Reports, [](const auto &R) { return !R.RequestedDetails; });
}
+FunctionAnalysisContext::FunctionAnalysisContext(
+ BinaryFunction &BF, MCPlusBuilder::AllocatorIdTy AllocatorId,
+ opts::GadgetKindBitmask EnabledDetectors)
+ : BC(BF.getBinaryContext()), BF(BF), AllocatorId(AllocatorId),
+ EnabledDetectors(EnabledDetectors) {
+ assert(!(EnabledDetectors & ~opts::GS_PTRAUTH_ALL_MASK) &&
+ "Unrelated detectors requested");
+}
+
void FunctionAnalysisContext::run() {
LLVM_DEBUG({
dbgs() << "Analyzing function " << BF.getPrintName()
@@ -1753,7 +1760,7 @@ void FunctionAnalysisContext::run() {
void Analysis::runOnFunction(BinaryFunction &BF,
MCPlusBuilder::AllocatorIdTy AllocatorId) {
- FunctionAnalysisContext FA(BF, AllocatorId, EnabledDetectorsMask);
+ FunctionAnalysisContext FA(BF, AllocatorId, EnabledDetectors);
FA.run();
const FunctionAnalysisResult &FAR = FA.getResult();
@@ -1861,11 +1868,13 @@ void GenericDiagnostic::generateReport(raw_ostream &OS,
printBasicInfo(OS, BC, Text);
}
-Error Analysis::runOnFunctions(BinaryContext &BC) {
- using GSK = opts::GadgetScannerKind;
- assert(0 == (EnabledDetectorsMask & ~GSK::GS_PTRAUTH_ALL_MASK) &&
+Analysis::Analysis(opts::GadgetKindBitmask EnabledDetectors)
+ : BinaryFunctionPass(false), EnabledDetectors(EnabledDetectors) {
+ assert(!(EnabledDetectors & ~opts::GS_PTRAUTH_ALL_MASK) &&
"Unrelated detectors requested");
+}
+Error Analysis::runOnFunctions(BinaryContext &BC) {
ParallelUtilities::WorkFuncWithAllocTy WorkFun =
[&](BinaryFunction &BF, MCPlusBuilder::AllocatorIdTy AllocatorId) {
runOnFunction(BF, AllocatorId);
diff --git a/bolt/lib/Rewrite/RewriteInstance.cpp b/bolt/lib/Rewrite/RewriteInstance.cpp
index c84aabfe2e4ca..82bdbc9affd04 100644
--- a/bolt/lib/Rewrite/RewriteInstance.cpp
+++ b/bolt/lib/Rewrite/RewriteInstance.cpp
@@ -286,7 +286,7 @@ static cl::opt<bool> WriteBoltInfoSection(
"bolt-info", cl::desc("write bolt info section in the output binary"),
cl::init(true), cl::Hidden, cl::cat(BoltOutputCategory));
-static cl::list<GadgetScannerKind> GadgetScannersToRun(
+static cl::list<GadgetKindBitmask> GadgetScannersToRun(
"scanners", cl::desc("Which gadget scanners to run"),
cl::values(
clEnumValN(GS_PTRAUTH_RETURN_TARGETS, "ptrauth-pac-ret",
@@ -3878,17 +3878,17 @@ void RewriteInstance::runBinaryAnalyses() {
BinaryFunctionPassManager Manager(*BC);
// FIXME: add a pass that warns about which functions do not have CFG,
// and therefore, analysis is most likely to be less accurate.
- using GSK = opts::GadgetScannerKind;
- using PAuthScanner = PAuthGadgetScanner::Analysis;
+ using PtrAuthScanner = PAuthGadgetScanner::Analysis;
// If no command line option was given, act as if "all" was specified.
- uint64_t AnalysesMask = 0;
- for (uint64_t Submask : opts::GadgetScannersToRun)
- AnalysesMask |= Submask;
-
- uint64_t PAuthAnalysesMask = AnalysesMask & GSK::GS_PTRAUTH_ALL_MASK;
- if (PAuthAnalysesMask)
- Manager.registerPass(std::make_unique<PAuthScanner>(PAuthAnalysesMask));
+ decltype(~opts::GS_ALL_MASK) EnabledAnalyses = 0;
+ for (auto NamedOptionSubmask : opts::GadgetScannersToRun)
+ EnabledAnalyses |= NamedOptionSubmask;
+
+ const auto PtrAuthAnalyses = static_cast<opts::GadgetKindBitmask>(
+ EnabledAnalyses & opts::GS_PTRAUTH_ALL_MASK);
+ if (PtrAuthAnalyses)
+ Manager.registerPass(std::make_unique<PtrAuthScanner>(PtrAuthAnalyses));
BC->logBOLTErrorsAndQuitOnFatal(Manager.runPasses());
}
>From 89e313b839cf2e7c510f7be2b20134cac9914cfc Mon Sep 17 00:00:00 2001
From: Anatoly Trosinenko <atrosinenko at accesssoftek.com>
Date: Wed, 11 Mar 2026 22:20:47 +0300
Subject: [PATCH 3/3] Restore 'everything is enabled by default' behavior
---
bolt/lib/Rewrite/RewriteInstance.cpp | 6 +++++-
bolt/test/binary-analysis/AArch64/gs-pauth-scanners.s | 6 ++++++
2 files changed, 11 insertions(+), 1 deletion(-)
diff --git a/bolt/lib/Rewrite/RewriteInstance.cpp b/bolt/lib/Rewrite/RewriteInstance.cpp
index 82bdbc9affd04..b3208ac024ae6 100644
--- a/bolt/lib/Rewrite/RewriteInstance.cpp
+++ b/bolt/lib/Rewrite/RewriteInstance.cpp
@@ -3880,11 +3880,15 @@ void RewriteInstance::runBinaryAnalyses() {
// and therefore, analysis is most likely to be less accurate.
using PtrAuthScanner = PAuthGadgetScanner::Analysis;
- // If no command line option was given, act as if "all" was specified.
+ // Accumulate all enabled analyses.
decltype(~opts::GS_ALL_MASK) EnabledAnalyses = 0;
for (auto NamedOptionSubmask : opts::GadgetScannersToRun)
EnabledAnalyses |= NamedOptionSubmask;
+ // If no command line option was given, act as if "all" was specified.
+ if (opts::GadgetScannersToRun.empty())
+ EnabledAnalyses = opts::GS_ALL_MASK;
+
const auto PtrAuthAnalyses = static_cast<opts::GadgetKindBitmask>(
EnabledAnalyses & opts::GS_PTRAUTH_ALL_MASK);
if (PtrAuthAnalyses)
diff --git a/bolt/test/binary-analysis/AArch64/gs-pauth-scanners.s b/bolt/test/binary-analysis/AArch64/gs-pauth-scanners.s
index 2fb7b2e3d9d99..d6c96a671f9d2 100644
--- a/bolt/test/binary-analysis/AArch64/gs-pauth-scanners.s
+++ b/bolt/test/binary-analysis/AArch64/gs-pauth-scanners.s
@@ -36,6 +36,12 @@
// RUN: FileCheck %s --implicit-check-not="found in function" \
// RUN: --check-prefixes=PACRET,TAIL-CALLS-COMMON,TAIL-CALLS-NOFPAC,FORWARD-CF,SIGN-ORACLES-COMMON,SIGN-ORACLES-NOFPAC,AUTH-ORACLES-NOFPAC
+// Implicitly select all scanners by omitting --scanners=... argument.
+//
+// RUN: llvm-bolt-binary-analysis %t.exe 2>&1 | \
+// RUN: FileCheck %s --implicit-check-not="found in function" \
+// RUN: --check-prefixes=PACRET,TAIL-CALLS-COMMON,TAIL-CALLS-NOFPAC,FORWARD-CF,SIGN-ORACLES-COMMON,SIGN-ORACLES-NOFPAC,AUTH-ORACLES-NOFPAC
+
// Test FPAC handling:
//
// RUN: llvm-bolt-binary-analysis --auth-traps-on-failure --scanners=ptrauth-all %t.exe 2>&1 | \
More information about the llvm-commits
mailing list