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