[llvm] [BOLT] Gadget scanner: refactor analysis of RET instructions (PR #131897)
Anatoly Trosinenko via llvm-commits
llvm-commits at lists.llvm.org
Fri Mar 21 04:09:34 PDT 2025
================
@@ -376,57 +376,88 @@ class PacRetAnalysis
}
};
+static std::shared_ptr<Report> tryCheckReturn(const BinaryContext &BC,
+ const MCInstReference &Inst,
+ const State &S) {
+ static const GadgetKind RetKind("non-protected ret found");
+ if (!BC.MIB->isReturn(Inst))
+ return nullptr;
+
+ ErrorOr<MCPhysReg> MaybeRetReg = BC.MIB->getRegUsedAsRetDest(Inst);
+ if (MaybeRetReg.getError()) {
+ return std::make_shared<GenericReport>(
+ Inst, "Warning: pac-ret analysis could not analyze this return "
+ "instruction");
+ }
+ MCPhysReg RetReg = *MaybeRetReg;
+ LLVM_DEBUG({
+ traceInst(BC, "Found RET inst", Inst);
+ traceReg(BC, "RetReg", RetReg);
+ traceReg(BC, "Authenticated reg", BC.MIB->getAuthenticatedReg(Inst));
+ });
+ if (BC.MIB->isAuthenticationOfReg(Inst, RetReg))
+ return nullptr;
+ BitVector UsedDirtyRegs = S.NonAutClobRegs;
+ LLVM_DEBUG({ traceRegMask(BC, "NonAutClobRegs at Ret", UsedDirtyRegs); });
+ UsedDirtyRegs &= BC.MIB->getAliases(RetReg, /*OnlySmaller=*/true);
+ LLVM_DEBUG({ traceRegMask(BC, "Intersection with RetReg", UsedDirtyRegs); });
+ if (!UsedDirtyRegs.any())
+ return nullptr;
+
+ return std::make_shared<GadgetReport>(RetKind, Inst, UsedDirtyRegs);
+}
+
FunctionAnalysisResult
-Analysis::computeDfState(PacRetAnalysis &PRA, BinaryFunction &BF,
+Analysis::computeDfState(BinaryFunction &BF,
MCPlusBuilder::AllocatorIdTy AllocatorId) {
+ FunctionAnalysisResult Result;
+
+ PacRetAnalysis PRA(BF, AllocatorId, {});
PRA.run();
LLVM_DEBUG({
dbgs() << " After PacRetAnalysis:\n";
BF.dump();
});
- FunctionAnalysisResult Result;
- // Now scan the CFG for non-authenticating return instructions that use an
- // overwritten, non-authenticated register as return address.
BinaryContext &BC = BF.getBinaryContext();
for (BinaryBasicBlock &BB : BF) {
- for (int64_t I = BB.size() - 1; I >= 0; --I) {
- MCInst &Inst = BB.getInstructionAtIndex(I);
- if (BC.MIB->isReturn(Inst)) {
- ErrorOr<MCPhysReg> MaybeRetReg = BC.MIB->getRegUsedAsRetDest(Inst);
- if (MaybeRetReg.getError()) {
- Result.Diagnostics.push_back(std::make_shared<GenericReport>(
- MCInstInBBReference(&BB, I),
- "Warning: pac-ret analysis could not analyze this return "
- "instruction"));
- continue;
- }
- MCPhysReg RetReg = *MaybeRetReg;
- LLVM_DEBUG({
- traceInst(BC, "Found RET inst", Inst);
- traceReg(BC, "RetReg", RetReg);
- traceReg(BC, "Authenticated reg", BC.MIB->getAuthenticatedReg(Inst));
- });
- if (BC.MIB->isAuthenticationOfReg(Inst, RetReg))
- break;
- BitVector UsedDirtyRegs = PRA.getStateAt(Inst)->NonAutClobRegs;
- LLVM_DEBUG(
- { traceRegMask(BC, "NonAutClobRegs at Ret", UsedDirtyRegs); });
- UsedDirtyRegs &= BC.MIB->getAliases(RetReg, /*OnlySmaller=*/true);
- LLVM_DEBUG(
- { traceRegMask(BC, "Intersection with RetReg", UsedDirtyRegs); });
- if (UsedDirtyRegs.any()) {
- static const GadgetKind RetKind("non-protected ret found");
- // This return instruction needs to be reported
- Result.Diagnostics.push_back(std::make_shared<GadgetReport>(
- RetKind, MCInstInBBReference(&BB, I),
- PRA.getLastClobberingInsts(Inst, BF, UsedDirtyRegs)));
- for (MCPhysReg RetRegWithGadget : UsedDirtyRegs.set_bits())
- Result.RegistersAffected.insert(RetRegWithGadget);
- }
- }
+ for (int64_t I = 0, E = BB.size(); I < E; ++I) {
+ MCInstReference Inst(&BB, I);
+ const State &S = *PRA.getStateAt(Inst);
+
+ if (auto Report = tryCheckReturn(BC, Inst, S))
----------------
atrosinenko wrote:
`shouldReportReturnGadget` name is much better, thanks!
https://github.com/llvm/llvm-project/pull/131897
More information about the llvm-commits
mailing list