Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 25 additions & 11 deletions bolt/lib/Passes/PointerAuthCFIAnalyzer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,10 @@

using namespace llvm;

namespace opts {
extern llvm::cl::opt<unsigned> Verbosity;
} // namespace opts

namespace llvm {
namespace bolt {

Expand All @@ -43,9 +47,10 @@ bool PointerAuthCFIAnalyzer::runOnFunction(BinaryFunction &BF) {
// Not all functions have .cfi_negate_ra_state in them. But if one does,
// we expect psign/pauth instructions to have the hasNegateRAState
// annotation.
BC.outs() << "BOLT-INFO: inconsistent RAStates in function "
<< BF.getPrintName()
<< ": ptr sign/auth inst without .cfi_negate_ra_state\n";
if (opts::Verbosity >= 1)
BC.outs() << "BOLT-INFO: inconsistent RAStates in function "
<< BF.getPrintName()
<< ": ptr sign/auth inst without .cfi_negate_ra_state\n";
std::lock_guard<std::mutex> Lock(IgnoreMutex);
BF.setIgnored();
return false;
Expand All @@ -65,20 +70,22 @@ bool PointerAuthCFIAnalyzer::runOnFunction(BinaryFunction &BF) {
if (BC.MIB->isPSignOnLR(Inst)) {
if (RAState) {
// RA signing instructions should only follow unsigned RA state.
BC.outs() << "BOLT-INFO: inconsistent RAStates in function "
<< BF.getPrintName()
<< ": ptr signing inst encountered in Signed RA state\n";
if (opts::Verbosity >= 1)
BC.outs() << "BOLT-INFO: inconsistent RAStates in function "
<< BF.getPrintName()
<< ": ptr signing inst encountered in Signed RA state\n";
std::lock_guard<std::mutex> Lock(IgnoreMutex);
BF.setIgnored();
return false;
}
} else if (BC.MIB->isPAuthOnLR(Inst)) {
if (!RAState) {
// RA authenticating instructions should only follow signed RA state.
BC.outs() << "BOLT-INFO: inconsistent RAStates in function "
<< BF.getPrintName()
<< ": ptr authenticating inst encountered in Unsigned RA "
"state\n";
if (opts::Verbosity >= 1)
BC.outs() << "BOLT-INFO: inconsistent RAStates in function "
<< BF.getPrintName()
<< ": ptr authenticating inst encountered in Unsigned RA "
"state\n";
std::lock_guard<std::mutex> Lock(IgnoreMutex);
BF.setIgnored();
return false;
Expand Down Expand Up @@ -133,11 +140,18 @@ Error PointerAuthCFIAnalyzer::runOnFunctions(BinaryContext &BC) {
ParallelUtilities::runOnEachFunction(
BC, ParallelUtilities::SchedulingPolicy::SP_INST_LINEAR, WorkFun,
SkipPredicate, "PointerAuthCFIAnalyzer");

float IgnoredPercent = (100.0 * FunctionsIgnored) / Total;
BC.outs() << "BOLT-INFO: PointerAuthCFIAnalyzer ran on " << Total
<< " functions. Ignored " << FunctionsIgnored << " functions "
<< format("(%.2lf%%)", (100.0 * FunctionsIgnored) / Total)
<< format("(%.2lf%%)", IgnoredPercent)
<< " because of CFI inconsistencies\n";

if (IgnoredPercent >= 10.0)
BC.outs() << "BOLT-WARNING: PointerAuthCFIAnalyzer only supports "
"asynchronous unwind tables. For C compilers, see "
"-fasynchronous-unwind-tables.\n";

return Error::success();
}

Expand Down
2 changes: 1 addition & 1 deletion bolt/test/AArch64/negate-ra-state-incorrect.s
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@

# RUN: llvm-mc -filetype=obj -triple aarch64-unknown-unknown %s -o %t.o
# RUN: %clang %cflags %t.o -o %t.exe -Wl,-q
# RUN: llvm-bolt %t.exe -o %t.exe.bolt --no-threads | FileCheck %s --check-prefix=CHECK-BOLT
# RUN: llvm-bolt %t.exe -o %t.exe.bolt -v=1 --no-threads | FileCheck %s --check-prefix=CHECK-BOLT

# CHECK-BOLT: BOLT-INFO: inconsistent RAStates in function foo: ptr authenticating inst encountered in Unsigned RA state
# CHECK-BOLT: BOLT-INFO: inconsistent RAStates in function bar: ptr signing inst encountered in Signed RA state
Expand Down
33 changes: 33 additions & 0 deletions bolt/test/runtime/AArch64/pacret-synchronous-unwind.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
// Test to demonstrate that functions compiled with synchronous unwind tables
// are ignored by the PointerAuthCFIAnalyzer.
// Exception handling is needed to have _any_ unwind tables, otherwise the
// PointerAuthCFIAnalyzer does not run on these functions, so it does not ignore
// any function.
//
// REQUIRES: system-linux,bolt-runtime
//
// RUN: %clangxx --target=aarch64-unknown-linux-gnu \
// RUN: -mbranch-protection=pac-ret \
// RUN: -fno-asynchronous-unwind-tables \
// RUN: %s -o %t.exe -Wl,-q
// RUN: llvm-bolt %t.exe -o %t.bolt | FileCheck %s --check-prefix=CHECK
//
// CHECK: PointerAuthCFIAnalyzer ran on 3 functions. Ignored
// CHECK-NOT: 0 functions (0.00%) because of CFI inconsistencies
// CHECK-SAME: 1 functions (33.33%) because of CFI inconsistencies
// CHECK-NEXT: BOLT-WARNING: PointerAuthCFIAnalyzer only supports asynchronous
// CHECK-SAME: unwind tables. For C compilers, see -fasynchronous-unwind-tables.

#include <cstdio>
#include <stdexcept>

void foo() { throw std::runtime_error("Exception from foo()."); }

int main() {
try {
foo();
} catch (const std::exception &e) {
printf("Exception caught: %s\n", e.what());
}
return 0;
}
Loading