1
- // ===- bolt/Passes/NonPacProtectedRetAnalysis .cpp -------------------------===//
1
+ // ===- bolt/Passes/PAuthGadgetScanner .cpp -------- -------------------------===//
2
2
//
3
3
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4
4
// See https://llvm.org/LICENSE.txt for license information.
11
11
//
12
12
// ===----------------------------------------------------------------------===//
13
13
14
- #include " bolt/Passes/NonPacProtectedRetAnalysis .h"
14
+ #include " bolt/Passes/PAuthGadgetScanner .h"
15
15
#include " bolt/Core/ParallelUtilities.h"
16
16
#include " bolt/Passes/DataflowAnalysis.h"
17
17
#include " llvm/ADT/STLExtras.h"
20
20
#include " llvm/Support/Format.h"
21
21
#include < memory>
22
22
23
- #define DEBUG_TYPE " bolt-nonpacprotectedret "
23
+ #define DEBUG_TYPE " bolt-pauth-scanner "
24
24
25
25
namespace llvm {
26
26
namespace bolt {
@@ -57,7 +57,7 @@ raw_ostream &operator<<(raw_ostream &OS, const MCInstReference &Ref) {
57
57
llvm_unreachable (" " );
58
58
}
59
59
60
- namespace NonPacProtectedRetAnalysis {
60
+ namespace PAuthGadgetScanner {
61
61
62
62
[[maybe_unused]] static void traceInst (const BinaryContext &BC, StringRef Label,
63
63
const MCInst &MI) {
@@ -395,7 +395,7 @@ Analysis::computeDfState(PacRetAnalysis &PRA, BinaryFunction &BF,
395
395
if (BC.MIB ->isReturn (Inst)) {
396
396
ErrorOr<MCPhysReg> MaybeRetReg = BC.MIB ->getRegUsedAsRetDest (Inst);
397
397
if (MaybeRetReg.getError ()) {
398
- Result.Diagnostics .push_back (std::make_shared<GenDiag >(
398
+ Result.Diagnostics .push_back (std::make_shared<GenericReport >(
399
399
MCInstInBBReference (&BB, I),
400
400
" Warning: pac-ret analysis could not analyze this return "
401
401
" instruction" ));
@@ -416,9 +416,10 @@ Analysis::computeDfState(PacRetAnalysis &PRA, BinaryFunction &BF,
416
416
LLVM_DEBUG (
417
417
{ traceRegMask (BC, " Intersection with RetReg" , UsedDirtyRegs); });
418
418
if (UsedDirtyRegs.any ()) {
419
+ static const GadgetKind RetKind (" non-protected ret found" );
419
420
// 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),
422
423
PRA.getLastClobberingInsts (Inst, BF, UsedDirtyRegs)));
423
424
for (MCPhysReg RetRegWithGadget : UsedDirtyRegs.set_bits ())
424
425
Result.RegistersAffected .insert (RetRegWithGadget);
@@ -480,54 +481,61 @@ static void printBB(const BinaryContext &BC, const BinaryBasicBlock *BB,
480
481
481
482
static void reportFoundGadgetInSingleBBSingleOverwInst (
482
483
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 ();
485
486
assert (OverwInst.ParentKind == MCInstReference::BasicBlockParent);
486
- assert (RetInst .ParentKind == MCInstReference::BasicBlockParent);
487
+ assert (Location .ParentKind == MCInstReference::BasicBlockParent);
487
488
MCInstInBBReference OverwInstBB = OverwInst.U .BBRef ;
488
489
if (BB == OverwInstBB.BB ) {
489
490
// 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 );
491
492
OS << " This happens in the following basic block:\n " ;
492
493
printBB (BC, BB);
493
494
}
494
495
}
495
496
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
+ }
498
510
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 "
502
518
" authentication are:\n " ;
503
519
// 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) {
506
522
return A.getAddress () < B.getAddress ();
507
523
});
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];
510
526
OS << " " << (I + 1 ) << " . " ;
511
527
BC.printInstruction (OS, InstRef, InstRef.getAddress (), BF);
512
528
};
513
- if (OverwritingRetRegInst .size () == 1 ) {
514
- const MCInstReference OverwInst = OverwritingRetRegInst [0 ];
529
+ if (OverwritingInstrs .size () == 1 ) {
530
+ const MCInstReference OverwInst = OverwritingInstrs [0 ];
515
531
assert (OverwInst.ParentKind == MCInstReference::BasicBlockParent);
516
- reportFoundGadgetInSingleBBSingleOverwInst (OS, BC, OverwInst, RetInst );
532
+ reportFoundGadgetInSingleBBSingleOverwInst (OS, BC, OverwInst, Location );
517
533
}
518
534
}
519
535
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);
531
539
}
532
540
533
541
Error Analysis::runOnFunctions (BinaryContext &BC) {
@@ -542,17 +550,16 @@ Error Analysis::runOnFunctions(BinaryContext &BC) {
542
550
543
551
ParallelUtilities::runOnEachFunctionWithUniqueAllocId (
544
552
BC, ParallelUtilities::SchedulingPolicy::SP_INST_LINEAR, WorkFun,
545
- SkipFunc, " NonPacProtectedRetAnalysis " );
553
+ SkipFunc, " PAuthGadgetScanner " );
546
554
547
555
for (BinaryFunction *BF : BC.getAllBinaryFunctions ())
548
556
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);
552
559
}
553
560
return Error::success ();
554
561
}
555
562
556
- } // namespace NonPacProtectedRetAnalysis
563
+ } // namespace PAuthGadgetScanner
557
564
} // namespace bolt
558
565
} // namespace llvm
0 commit comments