@@ -50,8 +50,10 @@ void InsertNegateRAState::runOnFunction(BinaryFunction &BF) {
5050 continue ;
5151 auto RAState = BC.MIB ->getRAState (Inst);
5252 if (!RAState) {
53- BC.errs () << " BOLT-ERROR: unknown RAState after inferUnknownStates "
54- << " in function " << BF.getPrintName () << " \n " ;
53+ BC.errs () << " BOLT-ERROR: unknown RAState after inferUnknownStates"
54+ << " in function " << BF.getPrintName ()
55+ << " . Function will not be optimized.\n " ;
56+ BF.setIgnored ();
5557 }
5658 if (!FirstIter) {
5759 // Consecutive instructions with different RAState means we need to
@@ -69,6 +71,20 @@ void InsertNegateRAState::runOnFunction(BinaryFunction &BF) {
6971 }
7072}
7173
74+ void InsertNegateRAState::inferUnknownStates (BinaryFunction &BF) {
75+ BinaryContext &BC = BF.getBinaryContext ();
76+
77+ // Fill in missing RAStates in simple cases (inside BBs).
78+ for (BinaryBasicBlock &BB : BF) {
79+ fillUnknownStateInBB (BC, BB);
80+ }
81+ // Some stubs have no predecessors. For those, we iterate once in the layout
82+ // order to fill their RAState.
83+ fillUnknownStubs (BF);
84+
85+ fillUnknownBlocksInCFG (BF);
86+ }
87+
7288void InsertNegateRAState::coverFunctionFragmentStart (BinaryFunction &BF,
7389 FunctionFragment &FF) {
7490 BinaryContext &BC = BF.getBinaryContext ();
@@ -86,43 +102,217 @@ void InsertNegateRAState::coverFunctionFragmentStart(BinaryFunction &BF,
86102 });
87103 // If a function is already split in the input, the first FF can also start
88104 // with Signed state. This covers that scenario as well.
89- auto RAState = BC.MIB ->getRAState (*(*FirstNonEmpty)->begin ());
105+ auto II = (*FirstNonEmpty)->getFirstNonPseudo ();
106+ auto RAState = BC.MIB ->getRAState (*II);
90107 if (!RAState) {
91- BC.errs () << " BOLT-ERROR: unknown RAState after inferUnknownStates "
92- << " in function " << BF.getPrintName () << " \n " ;
108+ BC.errs () << " BOLT-ERROR: unknown RAState after inferUnknownStates"
109+ << " in function " << BF.getPrintName ()
110+ << " . Function will not be optimized.\n " ;
111+ BF.setIgnored ();
93112 return ;
94113 }
95114 if (*RAState)
96- BF.addCFIInstruction (*FirstNonEmpty, (*FirstNonEmpty)-> begin () ,
115+ BF.addCFIInstruction (*FirstNonEmpty, II ,
97116 MCCFIInstruction::createNegateRAState (nullptr ));
98117}
99118
100- void InsertNegateRAState::inferUnknownStates (BinaryFunction &BF) {
119+ std::optional<bool >
120+ InsertNegateRAState::getFirstKnownRAState (BinaryContext &BC,
121+ BinaryBasicBlock &BB) {
122+ for (const MCInst &Inst : BB) {
123+ if (BC.MIB ->isCFI (Inst))
124+ continue ;
125+ auto RAStateOpt = BC.MIB ->getRAState (Inst);
126+ if (RAStateOpt)
127+ return RAStateOpt;
128+ }
129+ return std::nullopt ;
130+ }
131+
132+ void InsertNegateRAState::fillUnknownStateInBB (BinaryContext &BC,
133+ BinaryBasicBlock &BB) {
134+
135+ auto First = BB.getFirstNonPseudo ();
136+ if (First == BB.end ())
137+ return ;
138+ // If the first instruction has unknown RAState, we should copy the first
139+ // known RAState.
140+ auto RAStateOpt = BC.MIB ->getRAState (*First);
141+ if (!RAStateOpt) {
142+ auto FirstRAState = getFirstKnownRAState (BC, BB);
143+ if (!FirstRAState)
144+ // We fill unknown BBs later.
145+ return ;
146+
147+ BC.MIB ->setRAState (*First, *FirstRAState);
148+ }
149+
150+ // At this point we know the RAState of the first instruction,
151+ // so we can propagate the RAStates to all subsequent unknown instructions.
152+ MCInst Prev = *First;
153+ for (auto It = BB.begin () + 1 ; It != BB.end (); ++It) {
154+ MCInst &Inst = *It;
155+ if (BC.MIB ->isCFI (Inst))
156+ continue ;
157+
158+ auto PrevRAState = BC.MIB ->getRAState (Prev);
159+ if (!PrevRAState)
160+ llvm_unreachable (" Previous Instruction has no RAState." );
161+
162+ auto RAState = BC.MIB ->getRAState (Inst);
163+ if (!RAState) {
164+ if (BC.MIB ->isPSignOnLR (Prev))
165+ PrevRAState = true ;
166+ else if (BC.MIB ->isPAuthOnLR (Prev))
167+ PrevRAState = false ;
168+ BC.MIB ->setRAState (Inst, *PrevRAState);
169+ }
170+ Prev = Inst;
171+ }
172+ }
173+
174+ bool InsertNegateRAState::isUnknownBlock (BinaryContext &BC,
175+ BinaryBasicBlock &BB) {
176+ for (const MCInst &Inst : BB) {
177+ if (BC.MIB ->isCFI (Inst))
178+ continue ;
179+ auto RAState = BC.MIB ->getRAState (Inst);
180+ if (RAState)
181+ return false ;
182+ }
183+ return true ;
184+ }
185+
186+ void InsertNegateRAState::markUnknownBlock (BinaryContext &BC,
187+ BinaryBasicBlock &BB, bool State) {
188+ // If we call this when an Instruction has either kRASigned or kRAUnsigned
189+ // annotation, setRASigned or setRAUnsigned would fail.
190+ assert (isUnknownBlock (BC, BB) &&
191+ " markUnknownBlock should only be called on unknown blocks" );
192+ for (MCInst &Inst : BB) {
193+ if (BC.MIB ->isCFI (Inst))
194+ continue ;
195+ BC.MIB ->setRAState (Inst, State);
196+ }
197+ }
198+
199+ std::optional<bool > InsertNegateRAState::getRAStateByCFG (BinaryBasicBlock &BB,
200+ BinaryFunction &BF) {
101201 BinaryContext &BC = BF.getBinaryContext ();
102- bool FirstIter = true ;
103- MCInst PrevInst;
104- for (BinaryBasicBlock &BB : BF) {
105- for (MCInst &Inst : BB) {
106- if (BC.MIB ->isCFI (Inst))
202+
203+ auto checkRAState = [&](std::optional<bool > &NeighborRAState, MCInst &Inst) {
204+ auto RAState = BC.MIB ->getRAState (Inst);
205+ if (!RAState)
206+ return ;
207+ if (!NeighborRAState) {
208+ NeighborRAState = *RAState;
209+ return ;
210+ }
211+ if (NeighborRAState != *RAState) {
212+ BC.outs () << " BOLT-WARNING: Conflicting RAState found in function "
213+ << BF.getPrintName () << " . Function will not be optimized.\n " ;
214+ BF.setIgnored ();
215+ }
216+ };
217+
218+ // Holds the first found RAState from CFG neighbors.
219+ std::optional<bool > NeighborRAState = std::nullopt ;
220+ if (BB.pred_size () != 0 ) {
221+ for (BinaryBasicBlock *PredBB : BB.predecessors ()) {
222+ // find last inst of Predecessor with known RA State.
223+ auto LI = PredBB->getLastNonPseudo ();
224+ if (LI == PredBB->rend ())
225+ continue ;
226+ MCInst &LastInst = *LI;
227+ checkRAState (NeighborRAState, LastInst);
228+ }
229+ } else if (BB.succ_size () != 0 ) {
230+ for (BinaryBasicBlock *SuccBB : BB.successors ()) {
231+ // find first inst of Successor with known RA State.
232+ auto FI = SuccBB->getFirstNonPseudo ();
233+ if (FI == SuccBB->end ())
107234 continue ;
235+ MCInst &FirstInst = *FI;
236+ checkRAState (NeighborRAState, FirstInst);
237+ }
238+ } else {
239+ llvm_unreachable (" Called getRAStateByCFG on a BB with no preds or succs." );
240+ }
241+
242+ return NeighborRAState;
243+ }
108244
109- auto RAState = BC.MIB ->getRAState (Inst);
110- if (!FirstIter && !RAState) {
111- if (BC.MIB ->isPSignOnLR (PrevInst))
112- RAState = true ;
113- else if (BC.MIB ->isPAuthOnLR (PrevInst))
114- RAState = false ;
115- else {
245+ void InsertNegateRAState::fillUnknownStubs (BinaryFunction &BF) {
246+ BinaryContext &BC = BF.getBinaryContext ();
247+ bool FirstIter = true ;
248+ MCInst PrevInst;
249+ for (FunctionFragment &FF : BF.getLayout ().fragments ()) {
250+ for (BinaryBasicBlock *BB : FF) {
251+ if (!FirstIter && isUnknownBlock (BC, *BB)) {
252+ // If we have no predecessors or successors, current BB is a Stub called
253+ // from another BinaryFunction. As of #160989, we have to copy the
254+ // PrevInst's RAState, because CFIs are already incorrect here.
255+ if (BB->pred_size () == 0 && BB->succ_size () == 0 ) {
116256 auto PrevRAState = BC.MIB ->getRAState (PrevInst);
117- RAState = PrevRAState ? *PrevRAState : false ;
257+ if (!PrevRAState) {
258+ BF.dump ();
259+ BB->dump ();
260+ llvm_unreachable (
261+ " Previous Instruction has no RAState in fillUnknownStubs." );
262+ continue ;
263+ }
264+
265+ if (BC.MIB ->isPSignOnLR (PrevInst)) {
266+ PrevRAState = true ;
267+ } else if (BC.MIB ->isPAuthOnLR (PrevInst)) {
268+ PrevRAState = false ;
269+ }
270+ markUnknownBlock (BC, *BB, *PrevRAState);
118271 }
119- BC. MIB -> setRAState (Inst, *RAState);
120- } else {
272+ }
273+ if (FirstIter) {
121274 FirstIter = false ;
122- if (!RAState )
123- BC. MIB -> setRAState (Inst, BF. getInitialRAState () );
275+ if (isUnknownBlock (BC, *BB) )
276+ markUnknownBlock (BC, *BB, false );
124277 }
125- PrevInst = Inst;
278+ auto Last = BB->getLastNonPseudo ();
279+ if (Last != BB->rend ())
280+ PrevInst = *Last;
281+ }
282+ }
283+ }
284+ void InsertNegateRAState::fillUnknownBlocksInCFG (BinaryFunction &BF) {
285+ BinaryContext &BC = BF.getBinaryContext ();
286+
287+ auto fillUnknowns = [&](BinaryFunction &BF) -> std::pair<int , bool > {
288+ int Unknowns = 0 ;
289+ bool Updated = false ;
290+ for (BinaryBasicBlock &BB : BF) {
291+ // Only try to iterate if the BB has either predecessors or successors.
292+ if (isUnknownBlock (BC, BB) &&
293+ (BB.pred_size () != 0 || BB.succ_size () != 0 )) {
294+ auto RAStateOpt = getRAStateByCFG (BB, BF);
295+ if (RAStateOpt) {
296+ markUnknownBlock (BC, BB, *RAStateOpt);
297+ Updated = true ;
298+ } else {
299+ Unknowns++;
300+ }
301+ }
302+ }
303+ return std::pair<int , bool >{Unknowns, Updated};
304+ };
305+
306+ while (true ) {
307+ std::pair<int , bool > Iter = fillUnknowns (BF);
308+ if (Iter.first == 0 )
309+ break ;
310+ if (!Iter.second ) {
311+ BC.errs () << " BOLT-WARNING: Could not infer RAState for " << Iter.first
312+ << " BBs in function " << BF.getPrintName ()
313+ << " . Function will not be optimized.\n " ;
314+ BF.setIgnored ();
315+ break ;
126316 }
127317 }
128318}
0 commit comments