Skip to content

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

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Apr 10, 2025

Conversation

atrosinenko
Copy link
Contributor

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.

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.
@atrosinenko atrosinenko marked this pull request as ready for review April 9, 2025 19:51
@llvmbot llvmbot added the BOLT label Apr 9, 2025
@llvmbot
Copy link
Member

llvmbot commented Apr 9, 2025

@llvm/pr-subscribers-bolt

Author: Anatoly Trosinenko (atrosinenko)

Changes

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.


Patch is 24.27 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/135073.diff

3 Files Affected:

  • (modified) bolt/include/bolt/Passes/PAuthGadgetScanner.h (+2-2)
  • (modified) bolt/lib/Passes/PAuthGadgetScanner.cpp (+53-50)
  • (modified) bolt/test/binary-analysis/AArch64/gs-pauth-debug-output.s (+61-57)
diff --git a/bolt/include/bolt/Passes/PAuthGadgetScanner.h b/bolt/include/bolt/Passes/PAuthGadgetScanner.h
index 622e6721dea55..ee69337637da3 100644
--- a/bolt/include/bolt/Passes/PAuthGadgetScanner.h
+++ b/bolt/include/bolt/Passes/PAuthGadgetScanner.h
@@ -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.
diff --git a/bolt/lib/Passes/PAuthGadgetScanner.cpp b/bolt/lib/Passes/PAuthGadgetScanner.cpp
index a7c22b23e4364..2a20bcd09c786 100644
--- a/bolt/lib/Passes/PAuthGadgetScanner.cpp
+++ b/bolt/lib/Passes/PAuthGadgetScanner.cpp
@@ -172,7 +172,7 @@ class TrackedRegisters {
 /// * 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 @@ class PacRetAnalysis
   /// 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 @@ class PacRetAnalysis
 
   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 @@ class PacRetAnalysis
     StateOut.merge(StateIn);
 
     LLVM_DEBUG({
-      dbgs() << "   merged state: ";
+      dbgs() << "    merged state: ";
       P.print(dbgs(), StateOut);
       dbgs() << "\n";
     });
@@ -354,7 +354,7 @@ class PacRetAnalysis
   // 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 @@ class PacRetAnalysis
     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 @@ class PacRetAnalysis
     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 @@ class PacRetAnalysis
         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 @@ class PacRetAnalysis
     }
 
     LLVM_DEBUG({
-      dbgs() << "  .. result: (";
+      dbgs() << "    .. result: (";
       P.print(dbgs(), Next);
       dbgs() << ")\n";
     });
@@ -438,7 +438,7 @@ class PacRetAnalysis
     return Next;
   }
 
-  StringRef getAnnotationName() const { return StringRef("PacRetAnalysis"); }
+  StringRef getAnnotationName() const { return StringRef("SrcSafetyAnalysis"); }
 
 public:
   std::vector<MCInstReference>
@@ -448,8 +448,8 @@ class PacRetAnalysis
       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 @@ class PacRetAnalysis
 
 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();
   });
 
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 b271cda9da62f..cca1efe695168 100644
--- a/bolt/test/binary-analysis/AArch64/gs-pauth-debug-output.s
+++ b/bolt/test/binary-analysis/AArch64/gs-pauth-debug-output.s
@@ -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<SafeToDe...
[truncated]

Copy link
Collaborator

@kbeyls kbeyls left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, thanks!

@atrosinenko atrosinenko merged commit 2927050 into main Apr 10, 2025
13 checks passed
@atrosinenko atrosinenko deleted the users/atrosinenko/bolt-gs-rename-classes-nfc branch April 10, 2025 17:54
var-const pushed a commit to ldionne/llvm-project that referenced this pull request Apr 17, 2025
…m#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.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants