1- // ===- bolt/Passes/NonPacProtectedRetAnalysis .cpp -------------------------===//
1+ // ===- bolt/Passes/PAuthGadgetScanner .cpp -------- -------------------------===//
22//
33// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
44// See https://llvm.org/LICENSE.txt for license information.
1111//
1212// ===----------------------------------------------------------------------===//
1313
14- #include " bolt/Passes/NonPacProtectedRetAnalysis .h"
14+ #include " bolt/Passes/PAuthGadgetScanner .h"
1515#include " bolt/Core/ParallelUtilities.h"
1616#include " bolt/Passes/DataflowAnalysis.h"
1717#include " llvm/ADT/STLExtras.h"
2020#include " llvm/Support/Format.h"
2121#include < memory>
2222
23- #define DEBUG_TYPE " bolt-nonpacprotectedret "
23+ #define DEBUG_TYPE " bolt-pauth-scanner "
2424
2525namespace llvm {
2626namespace bolt {
@@ -57,7 +57,7 @@ raw_ostream &operator<<(raw_ostream &OS, const MCInstReference &Ref) {
5757 llvm_unreachable (" " );
5858}
5959
60- namespace NonPacProtectedRetAnalysis {
60+ namespace PAuthGadgetScanner {
6161
6262[[maybe_unused]] static void traceInst (const BinaryContext &BC, StringRef Label,
6363 const MCInst &MI) {
@@ -395,7 +395,7 @@ Analysis::computeDfState(PacRetAnalysis &PRA, BinaryFunction &BF,
395395 if (BC.MIB ->isReturn (Inst)) {
396396 ErrorOr<MCPhysReg> MaybeRetReg = BC.MIB ->getRegUsedAsRetDest (Inst);
397397 if (MaybeRetReg.getError ()) {
398- Result.Diagnostics .push_back (std::make_shared<GenDiag >(
398+ Result.Diagnostics .push_back (std::make_shared<GenericReport >(
399399 MCInstInBBReference (&BB, I),
400400 " Warning: pac-ret analysis could not analyze this return "
401401 " instruction" ));
@@ -416,9 +416,10 @@ Analysis::computeDfState(PacRetAnalysis &PRA, BinaryFunction &BF,
416416 LLVM_DEBUG (
417417 { traceRegMask (BC, " Intersection with RetReg" , UsedDirtyRegs); });
418418 if (UsedDirtyRegs.any ()) {
419+ static const GadgetKind RetKind (" non-protected ret found" );
419420 // This return instruction needs to be reported
420- Result.Diagnostics .push_back (std::make_shared<Gadget >(
421- MCInstInBBReference (&BB, I),
421+ Result.Diagnostics .push_back (std::make_shared<GadgetReport >(
422+ RetKind, MCInstInBBReference (&BB, I),
422423 PRA.getLastClobberingInsts (Inst, BF, UsedDirtyRegs)));
423424 for (MCPhysReg RetRegWithGadget : UsedDirtyRegs.set_bits ())
424425 Result.RegistersAffected .insert (RetRegWithGadget);
@@ -480,54 +481,61 @@ static void printBB(const BinaryContext &BC, const BinaryBasicBlock *BB,
480481
481482static void reportFoundGadgetInSingleBBSingleOverwInst (
482483 raw_ostream &OS, const BinaryContext &BC, const MCInstReference OverwInst,
483- const MCInstReference RetInst ) {
484- BinaryBasicBlock *BB = RetInst .getBasicBlock ();
484+ const MCInstReference Location ) {
485+ BinaryBasicBlock *BB = Location .getBasicBlock ();
485486 assert (OverwInst.ParentKind == MCInstReference::BasicBlockParent);
486- assert (RetInst .ParentKind == MCInstReference::BasicBlockParent);
487+ assert (Location .ParentKind == MCInstReference::BasicBlockParent);
487488 MCInstInBBReference OverwInstBB = OverwInst.U .BBRef ;
488489 if (BB == OverwInstBB.BB ) {
489490 // overwriting inst and ret instruction are in the same basic block.
490- assert (OverwInstBB.BBIndex < RetInst .U .BBRef .BBIndex );
491+ assert (OverwInstBB.BBIndex < Location .U .BBRef .BBIndex );
491492 OS << " This happens in the following basic block:\n " ;
492493 printBB (BC, BB);
493494 }
494495}
495496
496- void Gadget::generateReport (raw_ostream &OS, const BinaryContext &BC) const {
497- GenDiag (RetInst, " non-protected ret found" ).generateReport (OS, BC);
497+ void Report::printBasicInfo (raw_ostream &OS, const BinaryContext &BC,
498+ StringRef IssueKind) const {
499+ BinaryFunction *BF = Location.getFunction ();
500+ BinaryBasicBlock *BB = Location.getBasicBlock ();
501+
502+ OS << " \n GS-PAUTH: " << IssueKind;
503+ OS << " in function " << BF->getPrintName ();
504+ if (BB)
505+ OS << " , basic block " << BB->getName ();
506+ OS << " , at address " << llvm::format (" %x" , Location.getAddress ()) << " \n " ;
507+ OS << " The instruction is " ;
508+ BC.printInstruction (OS, Location, Location.getAddress (), BF);
509+ }
498510
499- BinaryFunction *BF = RetInst.getFunction ();
500- OS << " The " << OverwritingRetRegInst.size ()
501- << " instructions that write to the return register after any "
511+ void GadgetReport::generateReport (raw_ostream &OS,
512+ const BinaryContext &BC) const {
513+ printBasicInfo (OS, BC, Kind.getDescription ());
514+
515+ BinaryFunction *BF = Location.getFunction ();
516+ OS << " The " << OverwritingInstrs.size ()
517+ << " instructions that write to the affected registers after any "
502518 " authentication are:\n " ;
503519 // Sort by address to ensure output is deterministic.
504- std::vector<MCInstReference> ORRI = OverwritingRetRegInst ;
505- llvm::sort (ORRI , [](const MCInstReference &A, const MCInstReference &B) {
520+ std::vector<MCInstReference> OI = OverwritingInstrs ;
521+ llvm::sort (OI , [](const MCInstReference &A, const MCInstReference &B) {
506522 return A.getAddress () < B.getAddress ();
507523 });
508- for (unsigned I = 0 ; I < ORRI .size (); ++I) {
509- MCInstReference InstRef = ORRI [I];
524+ for (unsigned I = 0 ; I < OI .size (); ++I) {
525+ MCInstReference InstRef = OI [I];
510526 OS << " " << (I + 1 ) << " . " ;
511527 BC.printInstruction (OS, InstRef, InstRef.getAddress (), BF);
512528 };
513- if (OverwritingRetRegInst .size () == 1 ) {
514- const MCInstReference OverwInst = OverwritingRetRegInst [0 ];
529+ if (OverwritingInstrs .size () == 1 ) {
530+ const MCInstReference OverwInst = OverwritingInstrs [0 ];
515531 assert (OverwInst.ParentKind == MCInstReference::BasicBlockParent);
516- reportFoundGadgetInSingleBBSingleOverwInst (OS, BC, OverwInst, RetInst );
532+ reportFoundGadgetInSingleBBSingleOverwInst (OS, BC, OverwInst, Location );
517533 }
518534}
519535
520- void GenDiag::generateReport (raw_ostream &OS, const BinaryContext &BC) const {
521- BinaryFunction *BF = RetInst.getFunction ();
522- BinaryBasicBlock *BB = RetInst.getBasicBlock ();
523-
524- OS << " \n GS-PACRET: " << Diag.Text ;
525- OS << " in function " << BF->getPrintName ();
526- if (BB)
527- OS << " , basic block " << BB->getName ();
528- OS << " , at address " << llvm::format (" %x" , RetInst.getAddress ()) << " \n " ;
529- OS << " The return instruction is " ;
530- BC.printInstruction (OS, RetInst, RetInst.getAddress (), BF);
536+ void GenericReport::generateReport (raw_ostream &OS,
537+ const BinaryContext &BC) const {
538+ printBasicInfo (OS, BC, Text);
531539}
532540
533541Error Analysis::runOnFunctions (BinaryContext &BC) {
@@ -542,17 +550,16 @@ Error Analysis::runOnFunctions(BinaryContext &BC) {
542550
543551 ParallelUtilities::runOnEachFunctionWithUniqueAllocId (
544552 BC, ParallelUtilities::SchedulingPolicy::SP_INST_LINEAR, WorkFun,
545- SkipFunc, " NonPacProtectedRetAnalysis " );
553+ SkipFunc, " PAuthGadgetScanner " );
546554
547555 for (BinaryFunction *BF : BC.getAllBinaryFunctions ())
548556 if (AnalysisResults.count (BF) > 0 ) {
549- for (const std::shared_ptr<Annotation> &A :
550- AnalysisResults[BF].Diagnostics )
551- A->generateReport (outs (), BC);
557+ for (const std::shared_ptr<Report> &R : AnalysisResults[BF].Diagnostics )
558+ R->generateReport (outs (), BC);
552559 }
553560 return Error::success ();
554561}
555562
556- } // namespace NonPacProtectedRetAnalysis
563+ } // namespace PAuthGadgetScanner
557564} // namespace bolt
558565} // namespace llvm
0 commit comments