[llvm] [BOLT] Gadget scanner: analyze functions without CFG information (PR #133461)
Kristof Beyls via llvm-commits
llvm-commits at lists.llvm.org
Mon Apr 7 05:32:36 PDT 2025
================
@@ -458,14 +448,141 @@ class PacRetAnalysis
}
std::vector<MCInstReference> Result;
for (const MCInst *Inst : LastWritingInsts) {
- MCInstInBBReference Ref = MCInstInBBReference::get(Inst, BF);
- assert(Ref.BB != nullptr && "Expected Inst to be found");
+ MCInstReference Ref = MCInstReference::get(Inst, BF);
+ assert(Ref && "Expected Inst to be found");
Result.push_back(MCInstReference(Ref));
}
return Result;
}
};
+class PacRetDFAnalysis
+ : public PacRetAnalysis,
+ public DataflowAnalysis<PacRetDFAnalysis, State, /*Backward=*/false,
+ PacStatePrinter> {
+ using DFParent =
+ DataflowAnalysis<PacRetDFAnalysis, State, false, PacStatePrinter>;
+ friend DFParent;
+
+ using PacRetAnalysis::BC;
+ using PacRetAnalysis::computeNext;
+
+public:
+ PacRetDFAnalysis(BinaryFunction &BF, MCPlusBuilder::AllocatorIdTy AllocId,
+ const std::vector<MCPhysReg> &RegsToTrackInstsFor)
+ : PacRetAnalysis(BF, RegsToTrackInstsFor), DFParent(BF, AllocId) {}
+
+ ErrorOr<const State &> getStateBefore(const MCInst &Inst) const override {
+ return DFParent::getStateBefore(Inst);
+ }
+
+ void run() override { DFParent::run(); }
+
+protected:
+ void preflight() {}
+
+ State getStartingStateAtBB(const BinaryBasicBlock &BB) {
+ if (BB.isEntryPoint())
+ return createEntryState();
+
+ return State();
+ }
+
+ State getStartingStateAtPoint(const MCInst &Point) { return State(); }
+
+ void doConfluence(State &StateOut, const State &StateIn) {
+ PacStatePrinter P(BC);
+ LLVM_DEBUG({
+ dbgs() << " PacRetAnalysis::Confluence(\n";
+ dbgs() << " State 1: ";
+ P.print(dbgs(), StateOut);
+ dbgs() << "\n";
+ dbgs() << " State 2: ";
+ P.print(dbgs(), StateIn);
+ dbgs() << ")\n";
+ });
+
+ StateOut.merge(StateIn);
+
+ LLVM_DEBUG({
+ dbgs() << " merged state: ";
+ P.print(dbgs(), StateOut);
+ dbgs() << "\n";
+ });
+ }
+
+ StringRef getAnnotationName() const { return "PacRetAnalysis"; }
+};
+
+class NoCFGPacRetAnalysis : public PacRetAnalysis {
+ BinaryFunction &BF;
+ MCPlusBuilder::AllocatorIdTy AllocId;
+ unsigned StateAnnotationIndex;
+
+ void cleanStateAnnotations() {
+ for (auto &I : BF.instrs())
+ BC.MIB->removeAnnotation(I.second, StateAnnotationIndex);
+ }
+
+ /// Creates a State with all registers marked unsafe (not to be confused
+ /// with empty state).
+ State createUnsafeState() const {
+ return State(NumRegs, RegsToTrackInstsFor.getNumTrackedRegisters());
+ }
+
+public:
+ NoCFGPacRetAnalysis(BinaryFunction &BF, MCPlusBuilder::AllocatorIdTy AllocId,
+ const std::vector<MCPhysReg> &RegsToTrackInstsFor)
+ : PacRetAnalysis(BF, RegsToTrackInstsFor), BF(BF), AllocId(AllocId) {
+ StateAnnotationIndex =
+ BC.MIB->getOrCreateAnnotationIndex("NoCFGPacRetAnalysis");
+ }
+
+ void run() override {
+ State S = createEntryState();
+ for (auto &I : BF.instrs()) {
+ MCInst &Inst = I.second;
+
+ // If there is a label before this instruction, it is possible that it
+ // can be jumped-to, thus conservatively resetting S. As an exception,
+ // let's ignore any labels at the beginning of the function, as at least
+ // one label is expected there.
+ if (BF.hasLabelAt(I.first) && &Inst != &BF.instrs().begin()->second)
+ S = createUnsafeState();
+
+ // Check if we need to remove an old annotation (this is the case if
+ // this is the second, detailed, run of the analysis).
+ if (BC.MIB->hasAnnotation(Inst, StateAnnotationIndex))
+ BC.MIB->removeAnnotation(Inst, StateAnnotationIndex);
+ // Attach the state *before* this instruction.
----------------
kbeyls wrote:
Maybe "// Attach the state *before* this instruction executes."?
https://github.com/llvm/llvm-project/pull/133461
More information about the llvm-commits
mailing list