mirror of
https://github.com/intel/llvm.git
synced 2026-01-13 11:02:04 +08:00
[BOLT] Rename Pointer Auth DWARF rewriter passes (#164622)
Rename passes to names that better reflect their intent, and describe their relationship to each other. InsertNegateRAStatePass renamed to PointerAuthCFIFixup, MarkRAStates renamed to PointerAuthCFIAnalyzer. Added the --print-<passname> flags for these passes.
This commit is contained in:
@@ -10,6 +10,10 @@ intended audience is BOLT developers. The document is an updated version of the
|
||||
in assembly, or `OpNegateRAState` in BOLT sources. In this document, I will use
|
||||
**negate-ra-state** as a shorthand.
|
||||
|
||||
Note: there are two resolutions for CFI:
|
||||
- Call Frame Instruction: individual DWARF instruction, e.g. negate-ra-state
|
||||
- Control Flow Integrity: a security mechanism, e.g. pointer authentication.
|
||||
|
||||
## Introduction
|
||||
|
||||
### Pointer Authentication
|
||||
@@ -104,9 +108,9 @@ negate-ra-state CFIs will become invalid during BasicBlock reordering.
|
||||
## Solution design
|
||||
|
||||
The implementation introduces two new passes:
|
||||
1. `MarkRAStatesPass`: assigns the RA state to each instruction based on the CFIs
|
||||
in the input binary
|
||||
2. `InsertNegateRAStatePass`: reads those assigned instruction RA states after
|
||||
1. `PointerAuthCFIAnalyzer`: assigns the RA state to each instruction based on
|
||||
the CFIs in the input binary
|
||||
2. `PointerAuthCFIFixup`: reads those assigned instruction RA states after
|
||||
optimizations, and emits `DW_CFA_AARCH64_negate_ra_state` CFIs at the correct
|
||||
places: wherever there is a state change between two consecutive instructions
|
||||
in the layout order.
|
||||
@@ -129,7 +133,7 @@ instruction.
|
||||
This special case is handled by adding an `initialRAState` bool to each BinaryFunction.
|
||||
If the `Offset` the CFI refers to is zero, we don't store an annotation, but set
|
||||
the `initialRAState` in `FillCFIInfoFor`. This information is then used in
|
||||
`MarkRAStates`.
|
||||
`PointerAuthCFIAnalyzer`.
|
||||
|
||||
### Binaries without DWARF info
|
||||
|
||||
@@ -146,7 +150,7 @@ In summary:
|
||||
- pointer auth is used, and we have DWARF CFIs: passes run, and rewrite the
|
||||
negate-ra-state CFI.
|
||||
|
||||
### MarkRAStates pass
|
||||
### PointerAuthCFIAnalyzer pass
|
||||
|
||||
This pass runs before optimizations reorder anything.
|
||||
|
||||
@@ -173,9 +177,9 @@ what we have before the pass, and after it.
|
||||
| autiasp | negate-ra-state | signed |
|
||||
| ret | | unsigned |
|
||||
|
||||
##### Error handling in MarkRAState Pass:
|
||||
##### Error handling in PointerAuthCFIAnalyzer pass:
|
||||
|
||||
Whenever the MarkRAStates pass finds inconsistencies in the current
|
||||
Whenever the PointerAuthCFIAnalyzer pass finds inconsistencies in the current
|
||||
BinaryFunction, it marks the function as ignored using `BF.setIgnored()`. BOLT
|
||||
will not optimize this function but will emit it unchanged in the original section
|
||||
(`.bolt.org.text`).
|
||||
@@ -188,16 +192,17 @@ The inconsistencies are as follows:
|
||||
Users will be informed about the number of ignored functions in the pass, the
|
||||
exact functions ignored, and the found inconsistency.
|
||||
|
||||
### InsertNegateRAStatePass
|
||||
### PointerAuthCFIFixup
|
||||
|
||||
This pass runs after optimizations. It performns the _inverse_ of MarkRAState pa s:
|
||||
This pass runs after optimizations. It performs the _inverse_ of PointerAuthCFIAnalyzer
|
||||
pass:
|
||||
1. it reads the RA state annotations attached to the instructions, and
|
||||
2. whenever the state changes, it adds a PseudoInstruction that holds an
|
||||
OpNegateRAState CFI.
|
||||
|
||||
##### Covering newly generated instructions:
|
||||
|
||||
Some BOLT passes can add new Instructions. In InsertNegateRAStatePass, we have
|
||||
Some BOLT passes can add new Instructions. In PointerAuthCFIFixup, we have
|
||||
to know what RA state these have.
|
||||
|
||||
> [!important]
|
||||
@@ -224,7 +229,7 @@ freely. The only special case is function splitting. When a function is split,
|
||||
the split part becomes a new function in the emitted binary. For unwinding to
|
||||
work, it needs to "replay" all CFIs that lead up to the split point. BOLT does
|
||||
this for other CFIs. As negate-ra-state is not read (only stored as an Annotation),
|
||||
we have to do this manually in InsertNegateRAStatePass. Here, if the split part
|
||||
we have to do this manually in PointerAuthCFIFixup. Here, if the split part
|
||||
starts with an instruction that has Signed RA state, we add a negate-ra-state CFI
|
||||
to indicate this.
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
//===- bolt/Passes/MarkRAStates.cpp ---------------------------------===//
|
||||
//===- bolt/Passes/PointerAuthCFIAnalyzer.h -------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
@@ -6,11 +6,11 @@
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file implements the MarkRAStates class.
|
||||
// This file implements the PointerAuthCFIAnalyzer class.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
#ifndef BOLT_PASSES_MARK_RA_STATES
|
||||
#define BOLT_PASSES_MARK_RA_STATES
|
||||
#ifndef BOLT_PASSES_POINTER_AUTH_CFI_ANALYZER
|
||||
#define BOLT_PASSES_POINTER_AUTH_CFI_ANALYZER
|
||||
|
||||
#include "bolt/Passes/BinaryPasses.h"
|
||||
#include <mutex>
|
||||
@@ -18,15 +18,16 @@
|
||||
namespace llvm {
|
||||
namespace bolt {
|
||||
|
||||
class MarkRAStates : public BinaryFunctionPass {
|
||||
class PointerAuthCFIAnalyzer : public BinaryFunctionPass {
|
||||
// setIgnored() is not thread-safe, but the pass is running on functions in
|
||||
// parallel.
|
||||
std::mutex IgnoreMutex;
|
||||
|
||||
public:
|
||||
explicit MarkRAStates() : BinaryFunctionPass(false) {}
|
||||
explicit PointerAuthCFIAnalyzer(const cl::opt<bool> &PrintPass)
|
||||
: BinaryFunctionPass(PrintPass) {}
|
||||
|
||||
const char *getName() const override { return "mark-ra-states"; }
|
||||
const char *getName() const override { return "pointer-auth-cfi-analyzer"; }
|
||||
|
||||
/// Pass entry point
|
||||
Error runOnFunctions(BinaryContext &BC) override;
|
||||
@@ -1,4 +1,4 @@
|
||||
//===- bolt/Passes/InsertNegateRAStatePass.h ------------------------------===//
|
||||
//===- bolt/Passes/PointerAuthCFIFixup.h ----------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
@@ -6,22 +6,23 @@
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file implements the InsertNegateRAStatePass class.
|
||||
// This file implements the PointerAuthCFIFixup class.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
#ifndef BOLT_PASSES_INSERT_NEGATE_RA_STATE_PASS
|
||||
#define BOLT_PASSES_INSERT_NEGATE_RA_STATE_PASS
|
||||
#ifndef BOLT_PASSES_POINTER_AUTH_CFI_FIXUP
|
||||
#define BOLT_PASSES_POINTER_AUTH_CFI_FIXUP
|
||||
|
||||
#include "bolt/Passes/BinaryPasses.h"
|
||||
|
||||
namespace llvm {
|
||||
namespace bolt {
|
||||
|
||||
class InsertNegateRAState : public BinaryFunctionPass {
|
||||
class PointerAuthCFIFixup : public BinaryFunctionPass {
|
||||
public:
|
||||
explicit InsertNegateRAState() : BinaryFunctionPass(false) {}
|
||||
explicit PointerAuthCFIFixup(const cl::opt<bool> &PrintPass)
|
||||
: BinaryFunctionPass(PrintPass) {}
|
||||
|
||||
const char *getName() const override { return "insert-negate-ra-state-pass"; }
|
||||
const char *getName() const override { return "pointer-auth-cfi-fixup"; }
|
||||
|
||||
/// Pass entry point
|
||||
Error runOnFunctions(BinaryContext &BC) override;
|
||||
@@ -572,7 +572,7 @@ bool CFIReaderWriter::fillCFIInfoFor(BinaryFunction &Function) const {
|
||||
if (Function.getBinaryContext().isAArch64()) {
|
||||
// Support for pointer authentication:
|
||||
// We need to annotate instructions that modify the RA State, to work
|
||||
// out the state of each instruction in MarkRAStates Pass.
|
||||
// out the state of each instruction in PointerAuthCFIAnalyzer Pass.
|
||||
if (Offset != 0)
|
||||
Function.setInstModifiesRAState(DW_CFA_remember_state, Offset);
|
||||
}
|
||||
@@ -583,7 +583,7 @@ bool CFIReaderWriter::fillCFIInfoFor(BinaryFunction &Function) const {
|
||||
if (Function.getBinaryContext().isAArch64()) {
|
||||
// Support for pointer authentication:
|
||||
// We need to annotate instructions that modify the RA State, to work
|
||||
// out the state of each instruction in MarkRAStates Pass.
|
||||
// out the state of each instruction in PointerAuthCFIAnalyzer Pass.
|
||||
if (Offset != 0)
|
||||
Function.setInstModifiesRAState(DW_CFA_restore_state, Offset);
|
||||
}
|
||||
@@ -652,7 +652,7 @@ bool CFIReaderWriter::fillCFIInfoFor(BinaryFunction &Function) const {
|
||||
// BasicBlocks, which changes during optimizations. Instead of adding
|
||||
// OpNegateRAState CFIs, an annotation is added to the instruction, to
|
||||
// mark that the instruction modifies the RA State. The actual state for
|
||||
// instructions are worked out in MarkRAStates based on these
|
||||
// instructions are worked out in PointerAuthCFIAnalyzer based on these
|
||||
// annotations.
|
||||
if (Offset != 0)
|
||||
Function.setInstModifiesRAState(DW_CFA_AARCH64_negate_ra_state,
|
||||
@@ -660,7 +660,7 @@ bool CFIReaderWriter::fillCFIInfoFor(BinaryFunction &Function) const {
|
||||
else
|
||||
// We cannot Annotate an instruction at Offset == 0.
|
||||
// Instead, we save the initial (Signed) state, and push it to
|
||||
// MarkRAStates' RAStateStack.
|
||||
// PointerAuthCFIAnalyzer's RAStateStack.
|
||||
Function.setInitialRAState(true);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -17,18 +17,18 @@ add_llvm_library(LLVMBOLTPasses
|
||||
IdenticalCodeFolding.cpp
|
||||
IndirectCallPromotion.cpp
|
||||
Inliner.cpp
|
||||
InsertNegateRAStatePass.cpp
|
||||
Instrumentation.cpp
|
||||
JTFootprintReduction.cpp
|
||||
LongJmp.cpp
|
||||
LoopInversionPass.cpp
|
||||
LivenessAnalysis.cpp
|
||||
MCF.cpp
|
||||
MarkRAStates.cpp
|
||||
PatchEntries.cpp
|
||||
PAuthGadgetScanner.cpp
|
||||
PettisAndHansen.cpp
|
||||
PLTCall.cpp
|
||||
PointerAuthCFIAnalyzer.cpp
|
||||
PointerAuthCFIFixup.cpp
|
||||
ProfileQualityStats.cpp
|
||||
RegAnalysis.cpp
|
||||
RegReAssign.cpp
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
//===- bolt/Passes/MarkRAStates.cpp ---------------------------------===//
|
||||
//===- bolt/Passes/PointerAuthCFIAnalyzer.cpp -----------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
@@ -6,7 +6,7 @@
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file implements the MarkRAStates class.
|
||||
// This file implements the PointerAuthCFIAnalyzer class.
|
||||
// Three CFIs have an influence on the RA State of an instruction:
|
||||
// - NegateRAState flips the RA State,
|
||||
// - RememberState pushes the RA State to a stack,
|
||||
@@ -16,10 +16,10 @@
|
||||
// the RA State of each instruction, and save it as new MCAnnotations. The new
|
||||
// annotations are Signing, Signed, Authenticating and Unsigned. After
|
||||
// optimizations, .cfi_negate_ra_state CFIs are added to the places where the
|
||||
// state changes in InsertNegateRAStatePass.
|
||||
// state changes in PointerAuthCFIFixup.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
#include "bolt/Passes/MarkRAStates.h"
|
||||
#include "bolt/Passes/PointerAuthCFIAnalyzer.h"
|
||||
#include "bolt/Core/BinaryFunction.h"
|
||||
#include "bolt/Core/ParallelUtilities.h"
|
||||
#include <cstdlib>
|
||||
@@ -31,7 +31,7 @@ using namespace llvm;
|
||||
namespace llvm {
|
||||
namespace bolt {
|
||||
|
||||
bool MarkRAStates::runOnFunction(BinaryFunction &BF) {
|
||||
bool PointerAuthCFIAnalyzer::runOnFunction(BinaryFunction &BF) {
|
||||
|
||||
BinaryContext &BC = BF.getBinaryContext();
|
||||
|
||||
@@ -110,7 +110,7 @@ bool MarkRAStates::runOnFunction(BinaryFunction &BF) {
|
||||
return true;
|
||||
}
|
||||
|
||||
Error MarkRAStates::runOnFunctions(BinaryContext &BC) {
|
||||
Error PointerAuthCFIAnalyzer::runOnFunctions(BinaryContext &BC) {
|
||||
std::atomic<uint64_t> FunctionsIgnored{0};
|
||||
ParallelUtilities::WorkFuncTy WorkFun = [&](BinaryFunction &BF) {
|
||||
if (!runOnFunction(BF)) {
|
||||
@@ -132,8 +132,8 @@ Error MarkRAStates::runOnFunctions(BinaryContext &BC) {
|
||||
|
||||
ParallelUtilities::runOnEachFunction(
|
||||
BC, ParallelUtilities::SchedulingPolicy::SP_INST_LINEAR, WorkFun,
|
||||
SkipPredicate, "MarkRAStates");
|
||||
BC.outs() << "BOLT-INFO: MarkRAStates ran on " << Total
|
||||
SkipPredicate, "PointerAuthCFIAnalyzer");
|
||||
BC.outs() << "BOLT-INFO: PointerAuthCFIAnalyzer ran on " << Total
|
||||
<< " functions. Ignored " << FunctionsIgnored << " functions "
|
||||
<< format("(%.2lf%%)", (100.0 * FunctionsIgnored) / Total)
|
||||
<< " because of CFI inconsistencies\n";
|
||||
@@ -1,4 +1,4 @@
|
||||
//===- bolt/Passes/InsertNegateRAStatePass.cpp ----------------------------===//
|
||||
//===- bolt/Passes/PointerAuthCFIFixup.cpp --------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
@@ -6,12 +6,12 @@
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file implements the InsertNegateRAStatePass class. It inserts
|
||||
// This file implements the PointerAuthCFIFixup class. It inserts
|
||||
// OpNegateRAState CFIs to places where the state of two consecutive
|
||||
// instructions are different.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
#include "bolt/Passes/InsertNegateRAStatePass.h"
|
||||
#include "bolt/Passes/PointerAuthCFIFixup.h"
|
||||
#include "bolt/Core/BinaryFunction.h"
|
||||
#include "bolt/Core/ParallelUtilities.h"
|
||||
#include <cstdlib>
|
||||
@@ -23,7 +23,7 @@ namespace bolt {
|
||||
|
||||
static bool PassFailed = false;
|
||||
|
||||
void InsertNegateRAState::runOnFunction(BinaryFunction &BF) {
|
||||
void PointerAuthCFIFixup::runOnFunction(BinaryFunction &BF) {
|
||||
if (PassFailed)
|
||||
return;
|
||||
|
||||
@@ -35,7 +35,7 @@ void InsertNegateRAState::runOnFunction(BinaryFunction &BF) {
|
||||
if (BF.getState() != BinaryFunction::State::CFG &&
|
||||
BF.getState() != BinaryFunction::State::CFG_Finalized) {
|
||||
BC.outs() << "BOLT-INFO: no CFG for " << BF.getPrintName()
|
||||
<< " in InsertNegateRAStatePass\n";
|
||||
<< " in PointerAuthCFIFixup\n";
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -74,7 +74,7 @@ void InsertNegateRAState::runOnFunction(BinaryFunction &BF) {
|
||||
}
|
||||
}
|
||||
|
||||
void InsertNegateRAState::inferUnknownStates(BinaryFunction &BF) {
|
||||
void PointerAuthCFIFixup::inferUnknownStates(BinaryFunction &BF) {
|
||||
BinaryContext &BC = BF.getBinaryContext();
|
||||
|
||||
// Fill in missing RAStates in simple cases (inside BBs).
|
||||
@@ -88,7 +88,7 @@ void InsertNegateRAState::inferUnknownStates(BinaryFunction &BF) {
|
||||
fillUnknownStubs(BF);
|
||||
}
|
||||
|
||||
void InsertNegateRAState::coverFunctionFragmentStart(BinaryFunction &BF,
|
||||
void PointerAuthCFIFixup::coverFunctionFragmentStart(BinaryFunction &BF,
|
||||
FunctionFragment &FF) {
|
||||
BinaryContext &BC = BF.getBinaryContext();
|
||||
if (FF.empty())
|
||||
@@ -119,7 +119,7 @@ void InsertNegateRAState::coverFunctionFragmentStart(BinaryFunction &BF,
|
||||
}
|
||||
|
||||
std::optional<bool>
|
||||
InsertNegateRAState::getFirstKnownRAState(BinaryContext &BC,
|
||||
PointerAuthCFIFixup::getFirstKnownRAState(BinaryContext &BC,
|
||||
BinaryBasicBlock &BB) {
|
||||
for (const MCInst &Inst : BB) {
|
||||
if (BC.MIB->isCFI(Inst))
|
||||
@@ -131,13 +131,13 @@ InsertNegateRAState::getFirstKnownRAState(BinaryContext &BC,
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
bool InsertNegateRAState::isUnknownBlock(BinaryContext &BC,
|
||||
bool PointerAuthCFIFixup::isUnknownBlock(BinaryContext &BC,
|
||||
BinaryBasicBlock &BB) {
|
||||
std::optional<bool> FirstRAState = getFirstKnownRAState(BC, BB);
|
||||
return !FirstRAState.has_value();
|
||||
}
|
||||
|
||||
void InsertNegateRAState::fillUnknownStateInBB(BinaryContext &BC,
|
||||
void PointerAuthCFIFixup::fillUnknownStateInBB(BinaryContext &BC,
|
||||
BinaryBasicBlock &BB) {
|
||||
|
||||
auto First = BB.getFirstNonPseudo();
|
||||
@@ -180,7 +180,7 @@ void InsertNegateRAState::fillUnknownStateInBB(BinaryContext &BC,
|
||||
}
|
||||
}
|
||||
|
||||
void InsertNegateRAState::markUnknownBlock(BinaryContext &BC,
|
||||
void PointerAuthCFIFixup::markUnknownBlock(BinaryContext &BC,
|
||||
BinaryBasicBlock &BB, bool State) {
|
||||
// If we call this when an Instruction has either kRASigned or kRAUnsigned
|
||||
// annotation, setRASigned or setRAUnsigned would fail.
|
||||
@@ -193,7 +193,7 @@ void InsertNegateRAState::markUnknownBlock(BinaryContext &BC,
|
||||
}
|
||||
}
|
||||
|
||||
void InsertNegateRAState::fillUnknownStubs(BinaryFunction &BF) {
|
||||
void PointerAuthCFIFixup::fillUnknownStubs(BinaryFunction &BF) {
|
||||
BinaryContext &BC = BF.getBinaryContext();
|
||||
bool FirstIter = true;
|
||||
MCInst PrevInst;
|
||||
@@ -235,7 +235,7 @@ void InsertNegateRAState::fillUnknownStubs(BinaryFunction &BF) {
|
||||
}
|
||||
}
|
||||
|
||||
Error InsertNegateRAState::runOnFunctions(BinaryContext &BC) {
|
||||
Error PointerAuthCFIFixup::runOnFunctions(BinaryContext &BC) {
|
||||
std::atomic<uint64_t> FunctionsModified{0};
|
||||
ParallelUtilities::WorkFuncTy WorkFun = [&](BinaryFunction &BF) {
|
||||
FunctionsModified++;
|
||||
@@ -252,7 +252,7 @@ Error InsertNegateRAState::runOnFunctions(BinaryContext &BC) {
|
||||
|
||||
ParallelUtilities::runOnEachFunction(
|
||||
BC, ParallelUtilities::SchedulingPolicy::SP_INST_LINEAR, WorkFun,
|
||||
SkipPredicate, "InsertNegateRAStatePass");
|
||||
SkipPredicate, "PointerAuthCFIFixup");
|
||||
|
||||
BC.outs() << "BOLT-INFO: rewritten pac-ret DWARF info in "
|
||||
<< FunctionsModified << " out of " << BC.getBinaryFunctions().size()
|
||||
@@ -19,15 +19,15 @@
|
||||
#include "bolt/Passes/IdenticalCodeFolding.h"
|
||||
#include "bolt/Passes/IndirectCallPromotion.h"
|
||||
#include "bolt/Passes/Inliner.h"
|
||||
#include "bolt/Passes/InsertNegateRAStatePass.h"
|
||||
#include "bolt/Passes/Instrumentation.h"
|
||||
#include "bolt/Passes/JTFootprintReduction.h"
|
||||
#include "bolt/Passes/LongJmp.h"
|
||||
#include "bolt/Passes/LoopInversionPass.h"
|
||||
#include "bolt/Passes/MCF.h"
|
||||
#include "bolt/Passes/MarkRAStates.h"
|
||||
#include "bolt/Passes/PLTCall.h"
|
||||
#include "bolt/Passes/PatchEntries.h"
|
||||
#include "bolt/Passes/PointerAuthCFIAnalyzer.h"
|
||||
#include "bolt/Passes/PointerAuthCFIFixup.h"
|
||||
#include "bolt/Passes/ProfileQualityStats.h"
|
||||
#include "bolt/Passes/RegReAssign.h"
|
||||
#include "bolt/Passes/ReorderData.h"
|
||||
@@ -134,6 +134,15 @@ static cl::opt<bool> PrintAArch64Relaxation(
|
||||
cl::desc("print functions after ADR/LDR Relaxation pass"), cl::Hidden,
|
||||
cl::cat(BoltOptCategory));
|
||||
|
||||
cl::opt<bool> PrintPAuthCFIAnalyzer(
|
||||
"print-pointer-auth-cfi-analyzer",
|
||||
cl::desc("print functions after PointerAuthCFIAnalyzer pass"), cl::Hidden,
|
||||
cl::cat(BoltOptCategory));
|
||||
static cl::opt<bool> PrintPAuthCFIFixup(
|
||||
"print-pointer-auth-cfi-fixup",
|
||||
cl::desc("print functions after PointerAuthCFIFixup pass"), cl::Hidden,
|
||||
cl::cat(BoltOptCategory));
|
||||
|
||||
static cl::opt<bool>
|
||||
PrintLongJmp("print-longjmp",
|
||||
cl::desc("print functions after longjmp pass"), cl::Hidden,
|
||||
@@ -362,7 +371,8 @@ Error BinaryFunctionPassManager::runAllPasses(BinaryContext &BC) {
|
||||
BinaryFunctionPassManager Manager(BC);
|
||||
|
||||
if (BC.isAArch64())
|
||||
Manager.registerPass(std::make_unique<MarkRAStates>());
|
||||
Manager.registerPass(
|
||||
std::make_unique<PointerAuthCFIAnalyzer>(PrintPAuthCFIAnalyzer));
|
||||
|
||||
Manager.registerPass(
|
||||
std::make_unique<EstimateEdgeCounts>(PrintEstimateEdgeCounts));
|
||||
@@ -524,7 +534,8 @@ Error BinaryFunctionPassManager::runAllPasses(BinaryContext &BC) {
|
||||
// relocations out of range and crash during linking.
|
||||
Manager.registerPass(std::make_unique<LongJmpPass>(PrintLongJmp));
|
||||
|
||||
Manager.registerPass(std::make_unique<InsertNegateRAState>());
|
||||
Manager.registerPass(
|
||||
std::make_unique<PointerAuthCFIFixup>(PrintPAuthCFIFixup));
|
||||
}
|
||||
|
||||
// This pass should always run last.*
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# This test checks that MarkRAStates pass ignores functions with
|
||||
# This test checks that PointerAuthCFIAnalyzer pass ignores functions with
|
||||
# malformed .cfi_negate_ra_state sequences in the input binary.
|
||||
|
||||
# The cases checked are:
|
||||
@@ -9,13 +9,13 @@
|
||||
# RUN: llvm-bolt %t.exe -o %t.exe.bolt --no-threads --print-all | FileCheck %s --check-prefix=CHECK-BOLT
|
||||
|
||||
# Check that the negate-ra-state at the start of bar is not discarded.
|
||||
# If it was discarded, MarkRAState would report bar as having inconsistent RAStates.
|
||||
# If it was discarded, PointerAuthCFIAnalyzer would report bar as having inconsistent RAStates.
|
||||
# This is testing the handling of initialRAState on the BinaryFunction.
|
||||
# CHECK-BOLT-NOT: BOLT-INFO: inconsistent RAStates in function foo
|
||||
# CHECK-BOLT-NOT: BOLT-INFO: inconsistent RAStates in function bar
|
||||
|
||||
# Check that OpNegateRAState CFIs are generated correctly.
|
||||
# CHECK-BOLT: Binary Function "foo" after insert-negate-ra-state-pass {
|
||||
# CHECK-BOLT: Binary Function "foo" after pointer-auth-cfi-fixup {
|
||||
# CHECK-BOLT: paciasp
|
||||
# CHECK-BOLT-NEXT: OpNegateRAState
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
# CHECK-BOLT-NEXT: 0: OpNegateRAState
|
||||
# CHECK-BOLT-NEXT: End of Function "foo"
|
||||
|
||||
# CHECK-BOLT: Binary Function "bar" after insert-negate-ra-state-pass {
|
||||
# CHECK-BOLT: Binary Function "bar" after pointer-auth-cfi-fixup {
|
||||
# CHECK-BOLT: OpNegateRAState
|
||||
# CHECK-BOLT-NEXT: mov x1, #0x0
|
||||
# CHECK-BOLT-NEXT: mov x1, #0x1
|
||||
@@ -37,7 +37,7 @@
|
||||
# CHECK-BOLT-NEXT: End of Function "bar"
|
||||
|
||||
# End of negate-ra-state insertion logs for foo and bar.
|
||||
# CHECK: Binary Function "_start" after insert-negate-ra-state-pass {
|
||||
# CHECK: Binary Function "_start" after pointer-auth-cfi-fixup {
|
||||
|
||||
# Check that the functions are in the new .text section
|
||||
# RUN: llvm-objdump %t.exe.bolt -d -j .text | FileCheck %s --check-prefix=CHECK-OBJDUMP
|
||||
@@ -11,7 +11,7 @@
|
||||
|
||||
# Checking that we don't see any OpNegateRAState CFIs before the insertion pass.
|
||||
# CHECK-NOT: OpNegateRAState
|
||||
# CHECK: Binary Function "foo" after insert-negate-ra-state-pass
|
||||
# CHECK: Binary Function "foo" after pointer-auth-cfi-fixup
|
||||
|
||||
# CHECK: paciasp
|
||||
# CHECK-NEXT: OpNegateRAState
|
||||
@@ -24,7 +24,7 @@
|
||||
# CHECK-NEXT: OpNegateRAState
|
||||
# CHECK-NEXT: ret
|
||||
|
||||
# End of the insert-negate-ra-state-pass logs
|
||||
# End of the pointer-auth-cfi-fixup logs
|
||||
# CHECK: Binary Function "foo" after finalize-functions
|
||||
|
||||
.text
|
||||
|
||||
@@ -6,7 +6,7 @@ set(LLVM_LINK_COMPONENTS
|
||||
)
|
||||
|
||||
add_bolt_unittest(PassTests
|
||||
InsertNegateRAState.cpp
|
||||
PointerAuthCFIFixup.cpp
|
||||
|
||||
DISABLE_LLVM_LINK_LLVM_DYLIB
|
||||
)
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
//===- bolt/unittest/Passes/InsertNegateRAState.cpp -----------------------===//
|
||||
//===- bolt/unittest/Passes/PointerAuthCFIFixup.cpp ----------------------===//
|
||||
//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
@@ -14,9 +14,10 @@
|
||||
|
||||
#include "bolt/Core/BinaryBasicBlock.h"
|
||||
#include "bolt/Core/BinaryFunction.h"
|
||||
#include "bolt/Passes/InsertNegateRAStatePass.h"
|
||||
#include "bolt/Passes/PointerAuthCFIFixup.h"
|
||||
#include "bolt/Rewrite/BinaryPassManager.h"
|
||||
#include "bolt/Rewrite/RewriteInstance.h"
|
||||
#include "bolt/Utils/CommandLineOpts.h"
|
||||
#include "llvm/BinaryFormat/ELF.h"
|
||||
#include "llvm/MC/MCDwarf.h"
|
||||
#include "llvm/MC/MCInstBuilder.h"
|
||||
@@ -28,6 +29,10 @@ using namespace llvm::object;
|
||||
using namespace llvm::ELF;
|
||||
using namespace bolt;
|
||||
|
||||
namespace opts {
|
||||
extern cl::opt<bool> PrintPAuthCFIAnalyzer;
|
||||
} // namespace opts
|
||||
|
||||
namespace {
|
||||
struct PassTester : public testing::TestWithParam<Triple::ArchType> {
|
||||
void SetUp() override {
|
||||
@@ -83,7 +88,8 @@ protected:
|
||||
BC->MRI.get(), BC->STI.get())));
|
||||
|
||||
PassManager = std::make_unique<BinaryFunctionPassManager>(*BC);
|
||||
PassManager->registerPass(std::make_unique<InsertNegateRAState>());
|
||||
PassManager->registerPass(
|
||||
std::make_unique<PointerAuthCFIFixup>(opts::PrintPAuthCFIAnalyzer));
|
||||
|
||||
TextSection = &BC->registerOrUpdateSection(
|
||||
".text", ELF::SHT_PROGBITS, ELF::SHF_ALLOC | ELF::SHF_EXECINSTR,
|
||||
@@ -30,18 +30,18 @@ static_library("Passes") {
|
||||
"IdenticalCodeFolding.cpp",
|
||||
"IndirectCallPromotion.cpp",
|
||||
"Inliner.cpp",
|
||||
"InsertNegateRAStatePass.cpp",
|
||||
"Instrumentation.cpp",
|
||||
"JTFootprintReduction.cpp",
|
||||
"LivenessAnalysis.cpp",
|
||||
"LongJmp.cpp",
|
||||
"LoopInversionPass.cpp",
|
||||
"MCF.cpp",
|
||||
"MarkRAStates.cpp",
|
||||
"PAuthGadgetScanner.cpp",
|
||||
"PLTCall.cpp",
|
||||
"PatchEntries.cpp",
|
||||
"PettisAndHansen.cpp",
|
||||
"PointerAuthCFIAnalyzer.cpp",
|
||||
"PointerAuthCFIFixup.cpp",
|
||||
"ProfileQualityStats.cpp",
|
||||
"RegAnalysis.cpp",
|
||||
"RegReAssign.cpp",
|
||||
|
||||
Reference in New Issue
Block a user