@@ -346,6 +346,12 @@ class SrcSafetyAnalysis {
346346 return S;
347347 }
348348
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+
349355 BitVector getClobberedRegs (const MCInst &Point) const {
350356 BitVector Clobbered (NumRegs);
351357 // Assume a call can clobber all registers, including callee-saved
@@ -585,6 +591,13 @@ class DataflowSrcSafetyAnalysis
585591 if (BB.isEntryPoint ())
586592 return createEntryState ();
587593
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+
588601 return SrcState ();
589602 }
590603
@@ -658,12 +671,6 @@ class CFGUnawareSrcSafetyAnalysis : public SrcSafetyAnalysis {
658671 BC.MIB ->removeAnnotation (I.second , StateAnnotationIndex);
659672 }
660673
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-
667674public:
668675 CFGUnawareSrcSafetyAnalysis (BinaryFunction &BF,
669676 MCPlusBuilder::AllocatorIdTy AllocId,
@@ -1335,19 +1342,30 @@ void FunctionAnalysis::findUnsafeUses(
13351342 BF.dump ();
13361343 });
13371344
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+
13381363 iterateOverInstrs (BF, [&](MCInstReference Inst) {
13391364 if (BC.MIB ->isCFI (Inst))
13401365 return ;
13411366
13421367 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" );
13511369
13521370 if (auto Report = shouldReportReturnGadget (BC, Inst, S))
13531371 Reports.push_back (*Report);
0 commit comments