@@ -346,6 +346,12 @@ class SrcSafetyAnalysis {
346
346
return S;
347
347
}
348
348
349
+ // / Creates a state with all registers marked unsafe (not to be confused
350
+ // / with empty state).
351
+ SrcState createUnsafeState () const {
352
+ return SrcState (NumRegs, RegsToTrackInstsFor.getNumTrackedRegisters ());
353
+ }
354
+
349
355
BitVector getClobberedRegs (const MCInst &Point ) const {
350
356
BitVector Clobbered (NumRegs);
351
357
// Assume a call can clobber all registers, including callee-saved
@@ -585,6 +591,13 @@ class DataflowSrcSafetyAnalysis
585
591
if (BB.isEntryPoint ())
586
592
return createEntryState ();
587
593
594
+ // If a basic block without any predecessors is found in an optimized code,
595
+ // this likely means that some CFG edges were not detected. Pessimistically
596
+ // assume all registers to be unsafe before this basic block and warn about
597
+ // this fact in FunctionAnalysis::findUnsafeUses().
598
+ if (BB.pred_empty ())
599
+ return createUnsafeState ();
600
+
588
601
return SrcState ();
589
602
}
590
603
@@ -658,12 +671,6 @@ class CFGUnawareSrcSafetyAnalysis : public SrcSafetyAnalysis {
658
671
BC.MIB ->removeAnnotation (I.second , StateAnnotationIndex);
659
672
}
660
673
661
- // / Creates a state with all registers marked unsafe (not to be confused
662
- // / with empty state).
663
- SrcState createUnsafeState () const {
664
- return SrcState (NumRegs, RegsToTrackInstsFor.getNumTrackedRegisters ());
665
- }
666
-
667
674
public:
668
675
CFGUnawareSrcSafetyAnalysis (BinaryFunction &BF,
669
676
MCPlusBuilder::AllocatorIdTy AllocId,
@@ -1335,19 +1342,30 @@ void FunctionAnalysis::findUnsafeUses(
1335
1342
BF.dump ();
1336
1343
});
1337
1344
1345
+ if (BF.hasCFG ()) {
1346
+ // Warn on basic blocks being unreachable according to BOLT, as this
1347
+ // likely means CFG is imprecise.
1348
+ for (BinaryBasicBlock &BB : BF) {
1349
+ if (!BB.pred_empty () || BB.isEntryPoint ())
1350
+ continue ;
1351
+ // Arbitrarily attach the report to the first instruction of BB.
1352
+ MCInst *InstToReport = BB.getFirstNonPseudoInstr ();
1353
+ if (!InstToReport)
1354
+ continue ; // BB has no real instructions
1355
+
1356
+ Reports.push_back (
1357
+ make_generic_report (MCInstReference::get (InstToReport, BF),
1358
+ " Warning: no predecessor basic blocks detected "
1359
+ " (possibly incomplete CFG)" ));
1360
+ }
1361
+ }
1362
+
1338
1363
iterateOverInstrs (BF, [&](MCInstReference Inst) {
1339
1364
if (BC.MIB ->isCFI (Inst))
1340
1365
return ;
1341
1366
1342
1367
const SrcState &S = Analysis->getStateBefore (Inst);
1343
-
1344
- // If non-empty state was never propagated from the entry basic block
1345
- // to Inst, assume it to be unreachable and report a warning.
1346
- if (S.empty ()) {
1347
- Reports.push_back (
1348
- make_generic_report (Inst, " Warning: unreachable instruction found" ));
1349
- return ;
1350
- }
1368
+ assert (!S.empty () && " Instruction has no associated state" );
1351
1369
1352
1370
if (auto Report = shouldReportReturnGadget (BC, Inst, S))
1353
1371
Reports.push_back (*Report);
0 commit comments