[BOLT] Gadget scanner: refine class names and debug output (NFC) (#135073)

Scanning functions without CFG information as well as the detection of
authentication oracles requires introducing more classes related to
register state analysis. To make the future code easier to understand,
rename several classes beforehand.

To detect authentication oracles, one has to query the properties of
*output* operands of authentication instructions *after* the instruction
is executed - this requires adding another analysis that iterates over
the instructions in reverse order, and a corresponding state class.

As the main difference of the existing `State` class is that it stores
the properties of source register operands of the instructions before
the instruction's execution, rename it to `SrcState` and
`PacRetAnalysis` to `SrcSafetyAnalysis`.

Apply minor adjustments to the debug output along the way.
This commit is contained in:
Anatoly Trosinenko 2025-04-10 20:54:05 +03:00 committed by GitHub
parent cd56666d7b
commit 2927050dd4
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 116 additions and 109 deletions

View File

@ -175,8 +175,8 @@ raw_ostream &operator<<(raw_ostream &OS, const MCInstReference &);
namespace PAuthGadgetScanner {
class PacRetAnalysis;
struct State;
class SrcSafetyAnalysis;
struct SrcState;
/// Description of a gadget kind that can be detected. Intended to be
/// statically allocated to be attached to reports by reference.

View File

@ -172,7 +172,7 @@ public:
/// * RET (which is implicitly RET X30) is a protected return if and only if
/// X30 is safe-to-dereference - the state computed for sub- and
/// super-registers is not inspected.
struct State {
struct SrcState {
/// A BitVector containing the registers that are either safe at function
/// entry and were not clobbered yet, or those not clobbered since being
/// authenticated.
@ -186,12 +186,12 @@ struct State {
std::vector<SmallPtrSet<const MCInst *, 4>> LastInstWritingReg;
/// Construct an empty state.
State() {}
SrcState() {}
State(unsigned NumRegs, unsigned NumRegsToTrack)
SrcState(unsigned NumRegs, unsigned NumRegsToTrack)
: SafeToDerefRegs(NumRegs), LastInstWritingReg(NumRegsToTrack) {}
State &merge(const State &StateIn) {
SrcState &merge(const SrcState &StateIn) {
if (StateIn.empty())
return *this;
if (empty())
@ -208,11 +208,11 @@ struct State {
/// neither safe, nor unsafe ones.
bool empty() const { return SafeToDerefRegs.empty(); }
bool operator==(const State &RHS) const {
bool operator==(const SrcState &RHS) const {
return SafeToDerefRegs == RHS.SafeToDerefRegs &&
LastInstWritingReg == RHS.LastInstWritingReg;
}
bool operator!=(const State &RHS) const { return !((*this) == RHS); }
bool operator!=(const SrcState &RHS) const { return !((*this) == RHS); }
};
static void printLastInsts(
@ -228,8 +228,8 @@ static void printLastInsts(
}
}
raw_ostream &operator<<(raw_ostream &OS, const State &S) {
OS << "pacret-state<";
raw_ostream &operator<<(raw_ostream &OS, const SrcState &S) {
OS << "src-state<";
if (S.empty()) {
OS << "empty";
} else {
@ -240,18 +240,18 @@ raw_ostream &operator<<(raw_ostream &OS, const State &S) {
return OS;
}
class PacStatePrinter {
class SrcStatePrinter {
public:
void print(raw_ostream &OS, const State &State) const;
explicit PacStatePrinter(const BinaryContext &BC) : BC(BC) {}
void print(raw_ostream &OS, const SrcState &State) const;
explicit SrcStatePrinter(const BinaryContext &BC) : BC(BC) {}
private:
const BinaryContext &BC;
};
void PacStatePrinter::print(raw_ostream &OS, const State &S) const {
void SrcStatePrinter::print(raw_ostream &OS, const SrcState &S) const {
RegStatePrinter RegStatePrinter(BC);
OS << "pacret-state<";
OS << "src-state<";
if (S.empty()) {
assert(S.SafeToDerefRegs.empty());
assert(S.LastInstWritingReg.empty());
@ -265,19 +265,19 @@ void PacStatePrinter::print(raw_ostream &OS, const State &S) const {
OS << ">";
}
class PacRetAnalysis
: public DataflowAnalysis<PacRetAnalysis, State, /*Backward=*/false,
PacStatePrinter> {
class SrcSafetyAnalysis
: public DataflowAnalysis<SrcSafetyAnalysis, SrcState, /*Backward=*/false,
SrcStatePrinter> {
using Parent =
DataflowAnalysis<PacRetAnalysis, State, false, PacStatePrinter>;
DataflowAnalysis<SrcSafetyAnalysis, SrcState, false, SrcStatePrinter>;
friend Parent;
public:
PacRetAnalysis(BinaryFunction &BF, MCPlusBuilder::AllocatorIdTy AllocId,
const std::vector<MCPhysReg> &RegsToTrackInstsFor)
SrcSafetyAnalysis(BinaryFunction &BF, MCPlusBuilder::AllocatorIdTy AllocId,
const std::vector<MCPhysReg> &RegsToTrackInstsFor)
: Parent(BF, AllocId), NumRegs(BF.getBinaryContext().MRI->getNumRegs()),
RegsToTrackInstsFor(RegsToTrackInstsFor) {}
virtual ~PacRetAnalysis() {}
virtual ~SrcSafetyAnalysis() {}
protected:
const unsigned NumRegs;
@ -285,12 +285,12 @@ protected:
/// must compute which the last set of instructions writing to it are.
const TrackedRegisters RegsToTrackInstsFor;
SmallPtrSet<const MCInst *, 4> &lastWritingInsts(State &S,
SmallPtrSet<const MCInst *, 4> &lastWritingInsts(SrcState &S,
MCPhysReg Reg) const {
unsigned Index = RegsToTrackInstsFor.getIndex(Reg);
return S.LastInstWritingReg[Index];
}
const SmallPtrSet<const MCInst *, 4> &lastWritingInsts(const State &S,
const SmallPtrSet<const MCInst *, 4> &lastWritingInsts(const SrcState &S,
MCPhysReg Reg) const {
unsigned Index = RegsToTrackInstsFor.getIndex(Reg);
return S.LastInstWritingReg[Index];
@ -298,30 +298,30 @@ protected:
void preflight() {}
State createEntryState() {
State S(NumRegs, RegsToTrackInstsFor.getNumTrackedRegisters());
SrcState createEntryState() {
SrcState S(NumRegs, RegsToTrackInstsFor.getNumTrackedRegisters());
for (MCPhysReg Reg : BC.MIB->getTrustedLiveInRegs())
S.SafeToDerefRegs |= BC.MIB->getAliases(Reg, /*OnlySmaller=*/true);
return S;
}
State getStartingStateAtBB(const BinaryBasicBlock &BB) {
SrcState getStartingStateAtBB(const BinaryBasicBlock &BB) {
if (BB.isEntryPoint())
return createEntryState();
return State();
return SrcState();
}
State getStartingStateAtPoint(const MCInst &Point) { return State(); }
SrcState getStartingStateAtPoint(const MCInst &Point) { return SrcState(); }
void doConfluence(State &StateOut, const State &StateIn) {
PacStatePrinter P(BC);
void doConfluence(SrcState &StateOut, const SrcState &StateIn) {
SrcStatePrinter P(BC);
LLVM_DEBUG({
dbgs() << " PacRetAnalysis::Confluence(\n";
dbgs() << " State 1: ";
dbgs() << " SrcSafetyAnalysis::Confluence(\n";
dbgs() << " State 1: ";
P.print(dbgs(), StateOut);
dbgs() << "\n";
dbgs() << " State 2: ";
dbgs() << " State 2: ";
P.print(dbgs(), StateIn);
dbgs() << ")\n";
});
@ -329,7 +329,7 @@ protected:
StateOut.merge(StateIn);
LLVM_DEBUG({
dbgs() << " merged state: ";
dbgs() << " merged state: ";
P.print(dbgs(), StateOut);
dbgs() << "\n";
});
@ -354,7 +354,7 @@ protected:
// Returns all registers that can be treated as if they are written by an
// authentication instruction.
SmallVector<MCPhysReg> getRegsMadeSafeToDeref(const MCInst &Point,
const State &Cur) const {
const SrcState &Cur) const {
SmallVector<MCPhysReg> Regs;
const MCPhysReg NoReg = BC.MIB->getNoRegister();
@ -378,10 +378,10 @@ protected:
return Regs;
}
State computeNext(const MCInst &Point, const State &Cur) {
PacStatePrinter P(BC);
SrcState computeNext(const MCInst &Point, const SrcState &Cur) {
SrcStatePrinter P(BC);
LLVM_DEBUG({
dbgs() << " PacRetAnalysis::ComputeNext(";
dbgs() << " SrcSafetyAnalysis::ComputeNext(";
BC.InstPrinter->printInst(&const_cast<MCInst &>(Point), 0, "", *BC.STI,
dbgs());
dbgs() << ", ";
@ -395,7 +395,7 @@ protected:
if (Cur.empty()) {
LLVM_DEBUG(
{ dbgs() << "Skipping computeNext(Point, Cur) as Cur is empty.\n"; });
return State();
return SrcState();
}
// First, compute various properties of the instruction, taking the state
@ -406,7 +406,7 @@ protected:
getRegsMadeSafeToDeref(Point, Cur);
// Then, compute the state after this instruction is executed.
State Next = Cur;
SrcState Next = Cur;
Next.SafeToDerefRegs.reset(Clobbered);
// Keep track of this instruction if it writes to any of the registers we
@ -430,7 +430,7 @@ protected:
}
LLVM_DEBUG({
dbgs() << " .. result: (";
dbgs() << " .. result: (";
P.print(dbgs(), Next);
dbgs() << ")\n";
});
@ -438,7 +438,7 @@ protected:
return Next;
}
StringRef getAnnotationName() const { return StringRef("PacRetAnalysis"); }
StringRef getAnnotationName() const { return StringRef("SrcSafetyAnalysis"); }
public:
std::vector<MCInstReference>
@ -448,8 +448,8 @@ public:
return {};
auto MaybeState = getStateBefore(Inst);
if (!MaybeState)
llvm_unreachable("Expected State to be present");
const State &S = *MaybeState;
llvm_unreachable("Expected state to be present");
const SrcState &S = *MaybeState;
// Due to aliasing registers, multiple registers may have been tracked.
std::set<const MCInst *> LastWritingInsts;
for (MCPhysReg TrackedReg : UsedDirtyRegs) {
@ -468,7 +468,7 @@ public:
static std::shared_ptr<Report>
shouldReportReturnGadget(const BinaryContext &BC, const MCInstReference &Inst,
const State &S) {
const SrcState &S) {
static const GadgetKind RetKind("non-protected ret found");
if (!BC.MIB->isReturn(Inst))
return nullptr;
@ -496,7 +496,7 @@ shouldReportReturnGadget(const BinaryContext &BC, const MCInstReference &Inst,
static std::shared_ptr<Report>
shouldReportCallGadget(const BinaryContext &BC, const MCInstReference &Inst,
const State &S) {
const SrcState &S) {
static const GadgetKind CallKind("non-protected call found");
if (!BC.MIB->isIndirectCall(Inst) && !BC.MIB->isIndirectBranch(Inst))
return nullptr;
@ -524,10 +524,11 @@ Analysis::findGadgets(BinaryFunction &BF,
MCPlusBuilder::AllocatorIdTy AllocatorId) {
FunctionAnalysisResult Result;
PacRetAnalysis PRA(BF, AllocatorId, {});
SrcSafetyAnalysis PRA(BF, AllocatorId, {});
LLVM_DEBUG({ dbgs() << "Running src register safety analysis...\n"; });
PRA.run();
LLVM_DEBUG({
dbgs() << " After PacRetAnalysis:\n";
dbgs() << "After src register safety analysis:\n";
BF.dump();
});
@ -535,7 +536,7 @@ Analysis::findGadgets(BinaryFunction &BF,
for (BinaryBasicBlock &BB : BF) {
for (int64_t I = 0, E = BB.size(); I < E; ++I) {
MCInstReference Inst(&BB, I);
const State &S = *PRA.getStateBefore(Inst);
const SrcState &S = *PRA.getStateBefore(Inst);
// If non-empty state was never propagated from the entry basic block
// to Inst, assume it to be unreachable and report a warning.
@ -570,10 +571,12 @@ void Analysis::computeDetailedInfo(BinaryFunction &BF,
std::vector<MCPhysReg> RegsToTrackVec(RegsToTrack.begin(), RegsToTrack.end());
// Re-compute the analysis with register tracking.
PacRetAnalysis PRWIA(BF, AllocatorId, RegsToTrackVec);
SrcSafetyAnalysis PRWIA(BF, AllocatorId, RegsToTrackVec);
LLVM_DEBUG(
{ dbgs() << "\nRunning detailed src register safety analysis...\n"; });
PRWIA.run();
LLVM_DEBUG({
dbgs() << " After detailed PacRetAnalysis:\n";
dbgs() << "After detailed src register safety analysis:\n";
BF.dump();
});

View File

@ -50,41 +50,42 @@ simple:
// CHECK-NEXT: <empty>
// CHECK-NEXT: End of Function "simple"
// CHECK-EMPTY:
// CHECK-NEXT: PacRetAnalysis::ComputeNext( hint #25, pacret-state<SafeToDerefRegs: LR W30 W30_HI , Insts: >)
// CHECK-NEXT: .. result: (pacret-state<SafeToDerefRegs: , Insts: >)
// CHECK-NEXT: PacRetAnalysis::ComputeNext( stp x29, x30, [sp, #-0x10]!, pacret-state<SafeToDerefRegs: , Insts: >)
// CHECK-NEXT: .. result: (pacret-state<SafeToDerefRegs: , Insts: >)
// CHECK-NEXT: PacRetAnalysis::ComputeNext( b [[BB1]], pacret-state<SafeToDerefRegs: , Insts: >)
// CHECK-NEXT: .. result: (pacret-state<SafeToDerefRegs: , Insts: >)
// CHECK-NEXT: PacRetAnalysis::Confluence(
// CHECK-NEXT: State 1: pacret-state<empty>
// CHECK-NEXT: State 2: pacret-state<SafeToDerefRegs: , Insts: >)
// CHECK-NEXT: merged state: pacret-state<SafeToDerefRegs: , Insts: >
// CHECK-NEXT: PacRetAnalysis::ComputeNext( autiza x0, pacret-state<SafeToDerefRegs: , Insts: >)
// CHECK-NEXT: .. result: (pacret-state<SafeToDerefRegs: W0 X0 W0_HI , Insts: >)
// CHECK-NEXT: PacRetAnalysis::ComputeNext( blr x0, pacret-state<SafeToDerefRegs: W0 X0 W0_HI , Insts: >)
// CHECK-NEXT: .. result: (pacret-state<SafeToDerefRegs: , Insts: >)
// CHECK-NEXT: PacRetAnalysis::ComputeNext( ldp x29, x30, [sp], #0x10, pacret-state<SafeToDerefRegs: , Insts: >)
// CHECK-NEXT: .. result: (pacret-state<SafeToDerefRegs: , Insts: >)
// CHECK-NEXT: PacRetAnalysis::ComputeNext( hint #29, pacret-state<SafeToDerefRegs: , Insts: >)
// CHECK-NEXT: .. result: (pacret-state<SafeToDerefRegs: LR W30 W30_HI , Insts: >)
// CHECK-NEXT: PacRetAnalysis::ComputeNext( ret x30, pacret-state<SafeToDerefRegs: LR W30 W30_HI , Insts: >)
// CHECK-NEXT: .. result: (pacret-state<SafeToDerefRegs: LR W30 W30_HI , Insts: >)
// CHECK-NEXT: PacRetAnalysis::Confluence(
// CHECK-NEXT: State 1: pacret-state<SafeToDerefRegs: , Insts: >
// CHECK-NEXT: State 2: pacret-state<SafeToDerefRegs: , Insts: >)
// CHECK-NEXT: merged state: pacret-state<SafeToDerefRegs: , Insts: >
// CHECK-NEXT: PacRetAnalysis::ComputeNext( autiza x0, pacret-state<SafeToDerefRegs: , Insts: >)
// CHECK-NEXT: .. result: (pacret-state<SafeToDerefRegs: W0 X0 W0_HI , Insts: >)
// CHECK-NEXT: PacRetAnalysis::ComputeNext( blr x0, pacret-state<SafeToDerefRegs: W0 X0 W0_HI , Insts: >)
// CHECK-NEXT: .. result: (pacret-state<SafeToDerefRegs: , Insts: >)
// CHECK-NEXT: PacRetAnalysis::ComputeNext( ldp x29, x30, [sp], #0x10, pacret-state<SafeToDerefRegs: , Insts: >)
// CHECK-NEXT: .. result: (pacret-state<SafeToDerefRegs: , Insts: >)
// CHECK-NEXT: PacRetAnalysis::ComputeNext( hint #29, pacret-state<SafeToDerefRegs: , Insts: >)
// CHECK-NEXT: .. result: (pacret-state<SafeToDerefRegs: LR W30 W30_HI , Insts: >)
// CHECK-NEXT: PacRetAnalysis::ComputeNext( ret x30, pacret-state<SafeToDerefRegs: LR W30 W30_HI , Insts: >)
// CHECK-NEXT: .. result: (pacret-state<SafeToDerefRegs: LR W30 W30_HI , Insts: >)
// CHECK-NEXT: After PacRetAnalysis:
// CHECK-NEXT: Running src register safety analysis...
// CHECK-NEXT: SrcSafetyAnalysis::ComputeNext( hint #25, src-state<SafeToDerefRegs: LR W30 W30_HI , Insts: >)
// CHECK-NEXT: .. result: (src-state<SafeToDerefRegs: , Insts: >)
// CHECK-NEXT: SrcSafetyAnalysis::ComputeNext( stp x29, x30, [sp, #-0x10]!, src-state<SafeToDerefRegs: , Insts: >)
// CHECK-NEXT: .. result: (src-state<SafeToDerefRegs: , Insts: >)
// CHECK-NEXT: SrcSafetyAnalysis::ComputeNext( b [[BB1]], src-state<SafeToDerefRegs: , Insts: >)
// CHECK-NEXT: .. result: (src-state<SafeToDerefRegs: , Insts: >)
// CHECK-NEXT: SrcSafetyAnalysis::Confluence(
// CHECK-NEXT: State 1: src-state<empty>
// CHECK-NEXT: State 2: src-state<SafeToDerefRegs: , Insts: >)
// CHECK-NEXT: merged state: src-state<SafeToDerefRegs: , Insts: >
// CHECK-NEXT: SrcSafetyAnalysis::ComputeNext( autiza x0, src-state<SafeToDerefRegs: , Insts: >)
// CHECK-NEXT: .. result: (src-state<SafeToDerefRegs: W0 X0 W0_HI , Insts: >)
// CHECK-NEXT: SrcSafetyAnalysis::ComputeNext( blr x0, src-state<SafeToDerefRegs: W0 X0 W0_HI , Insts: >)
// CHECK-NEXT: .. result: (src-state<SafeToDerefRegs: , Insts: >)
// CHECK-NEXT: SrcSafetyAnalysis::ComputeNext( ldp x29, x30, [sp], #0x10, src-state<SafeToDerefRegs: , Insts: >)
// CHECK-NEXT: .. result: (src-state<SafeToDerefRegs: , Insts: >)
// CHECK-NEXT: SrcSafetyAnalysis::ComputeNext( hint #29, src-state<SafeToDerefRegs: , Insts: >)
// CHECK-NEXT: .. result: (src-state<SafeToDerefRegs: LR W30 W30_HI , Insts: >)
// CHECK-NEXT: SrcSafetyAnalysis::ComputeNext( ret x30, src-state<SafeToDerefRegs: LR W30 W30_HI , Insts: >)
// CHECK-NEXT: .. result: (src-state<SafeToDerefRegs: LR W30 W30_HI , Insts: >)
// CHECK-NEXT: SrcSafetyAnalysis::Confluence(
// CHECK-NEXT: State 1: src-state<SafeToDerefRegs: , Insts: >
// CHECK-NEXT: State 2: src-state<SafeToDerefRegs: , Insts: >)
// CHECK-NEXT: merged state: src-state<SafeToDerefRegs: , Insts: >
// CHECK-NEXT: SrcSafetyAnalysis::ComputeNext( autiza x0, src-state<SafeToDerefRegs: , Insts: >)
// CHECK-NEXT: .. result: (src-state<SafeToDerefRegs: W0 X0 W0_HI , Insts: >)
// CHECK-NEXT: SrcSafetyAnalysis::ComputeNext( blr x0, src-state<SafeToDerefRegs: W0 X0 W0_HI , Insts: >)
// CHECK-NEXT: .. result: (src-state<SafeToDerefRegs: , Insts: >)
// CHECK-NEXT: SrcSafetyAnalysis::ComputeNext( ldp x29, x30, [sp], #0x10, src-state<SafeToDerefRegs: , Insts: >)
// CHECK-NEXT: .. result: (src-state<SafeToDerefRegs: , Insts: >)
// CHECK-NEXT: SrcSafetyAnalysis::ComputeNext( hint #29, src-state<SafeToDerefRegs: , Insts: >)
// CHECK-NEXT: .. result: (src-state<SafeToDerefRegs: LR W30 W30_HI , Insts: >)
// CHECK-NEXT: SrcSafetyAnalysis::ComputeNext( ret x30, src-state<SafeToDerefRegs: LR W30 W30_HI , Insts: >)
// CHECK-NEXT: .. result: (src-state<SafeToDerefRegs: LR W30 W30_HI , Insts: >)
// CHECK-NEXT: After src register safety analysis:
// CHECK-NEXT: Binary Function "simple" {
// CHECK-NEXT: Number : 1
// CHECK-NEXT: State : CFG constructed
@ -93,27 +94,27 @@ simple:
// CHECK-NEXT: }
// CHECK-NEXT: [[BB0]] (3 instructions, align : 1)
// CHECK-NEXT: Entry Point
// CHECK-NEXT: 00000000: paciasp # PacRetAnalysis: pacret-state<SafeToDerefRegs: BitVector, Insts: >
// CHECK-NEXT: 00000004: stp x29, x30, [sp, #-0x10]! # PacRetAnalysis: pacret-state<SafeToDerefRegs: BitVector, Insts: >
// CHECK-NEXT: 00000008: b [[BB1]] # PacRetAnalysis: pacret-state<SafeToDerefRegs: BitVector, Insts: >
// CHECK-NEXT: 00000000: paciasp # SrcSafetyAnalysis: src-state<SafeToDerefRegs: BitVector, Insts: >
// CHECK-NEXT: 00000004: stp x29, x30, [sp, #-0x10]! # SrcSafetyAnalysis: src-state<SafeToDerefRegs: BitVector, Insts: >
// CHECK-NEXT: 00000008: b [[BB1]] # SrcSafetyAnalysis: src-state<SafeToDerefRegs: BitVector, Insts: >
// CHECK-NEXT: Successors: [[BB1]]
// CHECK-EMPTY:
// CHECK-NEXT: [[BB1]] (5 instructions, align : 1)
// CHECK-NEXT: Predecessors: [[BB0]]
// CHECK-NEXT: 0000000c: autiza x0 # PacRetAnalysis: pacret-state<SafeToDerefRegs: BitVector, Insts: >
// CHECK-NEXT: 00000010: blr x0 # PacRetAnalysis: pacret-state<SafeToDerefRegs: BitVector, Insts: >
// CHECK-NEXT: 00000014: ldp x29, x30, [sp], #0x10 # PacRetAnalysis: pacret-state<SafeToDerefRegs: BitVector, Insts: >
// CHECK-NEXT: 00000018: autiasp # PacRetAnalysis: pacret-state<SafeToDerefRegs: BitVector, Insts: >
// CHECK-NEXT: 0000001c: ret # PacRetAnalysis: pacret-state<SafeToDerefRegs: BitVector, Insts: >
// CHECK-NEXT: 0000000c: autiza x0 # SrcSafetyAnalysis: src-state<SafeToDerefRegs: BitVector, Insts: >
// CHECK-NEXT: 00000010: blr x0 # SrcSafetyAnalysis: src-state<SafeToDerefRegs: BitVector, Insts: >
// CHECK-NEXT: 00000014: ldp x29, x30, [sp], #0x10 # SrcSafetyAnalysis: src-state<SafeToDerefRegs: BitVector, Insts: >
// CHECK-NEXT: 00000018: autiasp # SrcSafetyAnalysis: src-state<SafeToDerefRegs: BitVector, Insts: >
// CHECK-NEXT: 0000001c: ret # SrcSafetyAnalysis: src-state<SafeToDerefRegs: BitVector, Insts: >
// CHECK-EMPTY:
// CHECK-NEXT: DWARF CFI Instructions:
// CHECK-NEXT: <empty>
// CHECK-NEXT: End of Function "simple"
// CHECK-EMPTY:
// PAUTH-NEXT: Found call inst: 00000000: blr x0 # PacRetAnalysis: pacret-state<SafeToDerefRegs: BitVector, Insts: >
// PAUTH-NEXT: Found call inst: 00000000: blr x0 # SrcSafetyAnalysis: src-state<SafeToDerefRegs: BitVector, Insts: >
// PAUTH-NEXT: Call destination reg: X0
// PAUTH-NEXT: SafeToDerefRegs: W0 X0 W0_HI{{[ \t]*$}}
// CHECK-NEXT: Found RET inst: 00000000: ret # PacRetAnalysis: pacret-state<SafeToDerefRegs: BitVector, Insts: >
// CHECK-NEXT: Found RET inst: 00000000: ret # SrcSafetyAnalysis: src-state<SafeToDerefRegs: BitVector, Insts: >
// CHECK-NEXT: RetReg: LR
// CHECK-NEXT: Authenticated reg: (none)
// CHECK-NEXT: SafeToDerefRegs: LR W30 W30_HI{{[ \t]*$}}
@ -127,11 +128,12 @@ clobber:
// CHECK-LABEL:Analyzing in function clobber, AllocatorId 1
// ...
// CHECK: PacRetAnalysis::ComputeNext( mov w30, #0x0, pacret-state<SafeToDerefRegs: LR W30 W30_HI , Insts: >)
// CHECK-NEXT: .. result: (pacret-state<SafeToDerefRegs: W30_HI , Insts: >)
// CHECK-NEXT: PacRetAnalysis::ComputeNext( ret x30, pacret-state<SafeToDerefRegs: W30_HI , Insts: >)
// CHECK-NEXT: .. result: (pacret-state<SafeToDerefRegs: W30_HI , Insts: >)
// CHECK-NEXT: After PacRetAnalysis:
// CHECK: Running src register safety analysis...
// CHECK-NEXT: SrcSafetyAnalysis::ComputeNext( mov w30, #0x0, src-state<SafeToDerefRegs: LR W30 W30_HI , Insts: >)
// CHECK-NEXT: .. result: (src-state<SafeToDerefRegs: W30_HI , Insts: >)
// CHECK-NEXT: SrcSafetyAnalysis::ComputeNext( ret x30, src-state<SafeToDerefRegs: W30_HI , Insts: >)
// CHECK-NEXT: .. result: (src-state<SafeToDerefRegs: W30_HI , Insts: >)
// CHECK-NEXT: After src register safety analysis:
// CHECK-NEXT: Binary Function "clobber" {
// ...
// CHECK: End of Function "clobber"
@ -139,15 +141,17 @@ clobber:
// The above output was printed after first run of analysis
// CHECK-EMPTY:
// CHECK-NEXT: Found RET inst: 00000000: ret # PacRetAnalysis: pacret-state<SafeToDerefRegs: BitVector, Insts: >
// CHECK-NEXT: Found RET inst: 00000000: ret # SrcSafetyAnalysis: src-state<SafeToDerefRegs: BitVector, Insts: >
// CHECK-NEXT: RetReg: LR
// CHECK-NEXT: Authenticated reg: (none)
// CHECK-NEXT: SafeToDerefRegs: W30_HI{{[ \t]*$}}
// CHECK-NEXT: PacRetAnalysis::ComputeNext( mov w30, #0x0, pacret-state<SafeToDerefRegs: LR W30 W30_HI , Insts: [0]()>)
// CHECK-NEXT: .. result: (pacret-state<SafeToDerefRegs: W30_HI , Insts: [0](0x{{[0-9a-f]+}} )>)
// CHECK-NEXT: PacRetAnalysis::ComputeNext( ret x30, pacret-state<SafeToDerefRegs: W30_HI , Insts: [0](0x{{[0-9a-f]+}} )>)
// CHECK-NEXT: .. result: (pacret-state<SafeToDerefRegs: W30_HI , Insts: [0](0x{{[0-9a-f]+}} )>)
// CHECK-NEXT: After detailed PacRetAnalysis:
// CHECK-EMPTY:
// CHECK-NEXT: Running detailed src register safety analysis...
// CHECK-NEXT: SrcSafetyAnalysis::ComputeNext( mov w30, #0x0, src-state<SafeToDerefRegs: LR W30 W30_HI , Insts: [0]()>)
// CHECK-NEXT: .. result: (src-state<SafeToDerefRegs: W30_HI , Insts: [0](0x{{[0-9a-f]+}} )>)
// CHECK-NEXT: SrcSafetyAnalysis::ComputeNext( ret x30, src-state<SafeToDerefRegs: W30_HI , Insts: [0](0x{{[0-9a-f]+}} )>)
// CHECK-NEXT: .. result: (src-state<SafeToDerefRegs: W30_HI , Insts: [0](0x{{[0-9a-f]+}} )>)
// CHECK-NEXT: After detailed src register safety analysis:
// CHECK-NEXT: Binary Function "clobber" {
// ...
// CHECK: End of Function "clobber"
@ -156,7 +160,7 @@ clobber:
// Iterating over the reports and attaching clobbering info:
// CHECK-EMPTY:
// CHECK-NEXT: Attaching clobbering info to: 00000000: ret # PacRetAnalysis: pacret-state<SafeToDerefRegs: BitVector, Insts: [0](0x{{[0-9a-f]+}} )>
// CHECK-NEXT: Attaching clobbering info to: 00000000: ret # SrcSafetyAnalysis: src-state<SafeToDerefRegs: BitVector, Insts: [0](0x{{[0-9a-f]+}} )>
// CHECK-LABEL:Analyzing in function main, AllocatorId 1