@@ -376,9 +376,9 @@ class PacRetAnalysis
376
376
}
377
377
};
378
378
379
- static std::shared_ptr<Report> tryCheckReturn ( const BinaryContext &BC,
380
- const MCInstReference &Inst,
381
- const State &S) {
379
+ static std::shared_ptr<Report>
380
+ shouldReportReturnGadget ( const BinaryContext &BC, const MCInstReference &Inst,
381
+ const State &S) {
382
382
static const GadgetKind RetKind (" non-protected ret found" );
383
383
if (!BC.MIB ->isReturn (Inst))
384
384
return nullptr ;
@@ -408,8 +408,8 @@ static std::shared_ptr<Report> tryCheckReturn(const BinaryContext &BC,
408
408
}
409
409
410
410
FunctionAnalysisResult
411
- Analysis::computeDfState (BinaryFunction &BF,
412
- MCPlusBuilder::AllocatorIdTy AllocatorId) {
411
+ Analysis::findGadgets (BinaryFunction &BF,
412
+ MCPlusBuilder::AllocatorIdTy AllocatorId) {
413
413
FunctionAnalysisResult Result;
414
414
415
415
PacRetAnalysis PRA (BF, AllocatorId, {});
@@ -425,40 +425,39 @@ Analysis::computeDfState(BinaryFunction &BF,
425
425
MCInstReference Inst (&BB, I);
426
426
const State &S = *PRA.getStateAt (Inst);
427
427
428
- if (auto Report = tryCheckReturn (BC, Inst, S))
428
+ if (auto Report = shouldReportReturnGadget (BC, Inst, S))
429
429
Result.Diagnostics .push_back (Report);
430
430
}
431
431
}
432
+ return Result;
433
+ }
432
434
433
- if (Result.Diagnostics .empty ())
434
- return Result;
435
-
436
- // Redo the analysis, but now also track which instructions last wrote
437
- // to any of the registers in RetRegsWithGadgets, so that better
438
- // diagnostics can be produced.
435
+ void Analysis::computeDetailedInfo (BinaryFunction &BF,
436
+ MCPlusBuilder::AllocatorIdTy AllocatorId,
437
+ FunctionAnalysisResult &Result) {
438
+ BinaryContext &BC = BF.getBinaryContext ();
439
439
440
+ // Collect the affected registers across all gadgets found in this function.
440
441
SmallSet<MCPhysReg, 4 > RegsToTrack;
441
442
for (auto Report : Result.Diagnostics )
442
- for (MCPhysReg Reg : Report->getAffectedRegisters ())
443
- RegsToTrack.insert (Reg);
444
-
443
+ RegsToTrack.insert_range (Report->getAffectedRegisters ());
445
444
std::vector<MCPhysReg> RegsToTrackVec (RegsToTrack.begin (), RegsToTrack.end ());
446
445
446
+ // Re-compute the analysis with register tracking.
447
447
PacRetAnalysis PRWIA (BF, AllocatorId, RegsToTrackVec);
448
448
PRWIA.run ();
449
449
LLVM_DEBUG ({
450
450
dbgs () << " After detailed PacRetAnalysis:\n " ;
451
451
BF.dump ();
452
452
});
453
453
454
+ // Augment gadget reports.
454
455
for (auto Report : Result.Diagnostics ) {
455
456
LLVM_DEBUG (
456
457
{ traceInst (BC, " Attaching clobbering info to" , Report->Location ); });
457
458
Report->setOverwritingInstrs (PRWIA.getLastClobberingInsts (
458
459
Report->Location , BF, Report->getAffectedRegisters ()));
459
460
}
460
-
461
- return Result;
462
461
}
463
462
464
463
void Analysis::runOnFunction (BinaryFunction &BF,
@@ -472,10 +471,16 @@ void Analysis::runOnFunction(BinaryFunction &BF,
472
471
if (!BF.hasCFG ())
473
472
return ;
474
473
475
- FunctionAnalysisResult FAR = computeDfState (BF, AllocatorId);
474
+ FunctionAnalysisResult FAR = findGadgets (BF, AllocatorId);
476
475
if (FAR.Diagnostics .empty ())
477
476
return ;
478
477
478
+ // Redo the analysis, but now also track which instructions last wrote
479
+ // to any of the registers in RetRegsWithGadgets, so that better
480
+ // diagnostics can be produced.
481
+
482
+ computeDetailedInfo (BF, AllocatorId, FAR);
483
+
479
484
// `runOnFunction` is typically getting called from multiple threads in
480
485
// parallel. Therefore, use a lock to avoid data races when storing the
481
486
// result of the analysis in the `AnalysisResults` map.
@@ -540,7 +545,7 @@ void GadgetReport::generateReport(raw_ostream &OS,
540
545
<< " instructions that write to the affected registers after any "
541
546
" authentication are:\n " ;
542
547
// Sort by address to ensure output is deterministic.
543
- std::vector <MCInstReference> OI = OverwritingInstrs;
548
+ SmallVector <MCInstReference> OI = OverwritingInstrs;
544
549
llvm::sort (OI, [](const MCInstReference &A, const MCInstReference &B) {
545
550
return A.getAddress () < B.getAddress ();
546
551
});
0 commit comments