@@ -52,8 +52,8 @@ void InsertNegateRAState::runOnFunction(BinaryFunction &BF) {
5252 MCInst &Inst = *It;
5353 if (BC.MIB ->isCFI (Inst))
5454 continue ;
55- auto RAState = BC.MIB ->getRAState (Inst);
56- if (!RAState) {
55+ std::optional< bool > RAState = BC.MIB ->getRAState (Inst);
56+ if (!RAState. has_value () ) {
5757 BC.errs () << " BOLT-ERROR: unknown RAState after inferUnknownStates "
5858 << " in function " << BF.getPrintName () << " \n " ;
5959 PassFailed = true ;
@@ -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+ // BasicBlocks which are made entirely of "new instructions" (instructions
85+ // without RAState annotation) are stubs, and do not have correct unwind info.
86+ // We should iterate in layout order and fill them based on previous known
87+ // RAState.
88+ fillUnknownStubs (BF);
89+ }
90+
7791void InsertNegateRAState::coverFunctionFragmentStart (BinaryFunction &BF,
7892 FunctionFragment &FF) {
7993 BinaryContext &BC = BF.getBinaryContext ();
@@ -92,8 +106,8 @@ void InsertNegateRAState::coverFunctionFragmentStart(BinaryFunction &BF,
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.
94108 auto II = (*FirstNonEmpty)->getFirstNonPseudo ();
95- auto RAState = BC.MIB ->getRAState (*II);
96- if (!RAState) {
109+ std::optional< bool > RAState = BC.MIB ->getRAState (*II);
110+ if (!RAState. has_value () ) {
97111 BC.errs () << " BOLT-ERROR: unknown RAState after inferUnknownStates "
98112 << " in function " << BF.getPrintName () << " \n " ;
99113 PassFailed = true ;
@@ -104,32 +118,119 @@ void InsertNegateRAState::coverFunctionFragmentStart(BinaryFunction &BF,
104118 MCCFIInstruction::createNegateRAState (nullptr ));
105119}
106120
107- 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+ std::optional<bool > RAState = BC.MIB ->getRAState (Inst);
128+ if (RAState.has_value ())
129+ return RAState;
130+ }
131+ return std::nullopt ;
132+ }
133+
134+ bool InsertNegateRAState::isUnknownBlock (BinaryContext &BC,
135+ BinaryBasicBlock &BB) {
136+ std::optional<bool > FirstRAState = getFirstKnownRAState (BC, BB);
137+ return !FirstRAState.has_value ();
138+ }
139+
140+ void InsertNegateRAState::fillUnknownStateInBB (BinaryContext &BC,
141+ BinaryBasicBlock &BB) {
142+
143+ auto First = BB.getFirstNonPseudo ();
144+ if (First == BB.end ())
145+ return ;
146+ // If the first instruction has unknown RAState, we should copy the first
147+ // known RAState.
148+ std::optional<bool > RAState = BC.MIB ->getRAState (*First);
149+ if (!RAState.has_value ()) {
150+ std::optional<bool > FirstRAState = getFirstKnownRAState (BC, BB);
151+ if (!FirstRAState.has_value ())
152+ // We fill unknown BBs later.
153+ return ;
154+
155+ BC.MIB ->setRAState (*First, *FirstRAState);
156+ }
157+
158+ // At this point we know the RAState of the first instruction,
159+ // so we can propagate the RAStates to all subsequent unknown instructions.
160+ MCInst Prev = *First;
161+ for (auto It = First + 1 ; It != BB.end (); ++It) {
162+ MCInst &Inst = *It;
163+ if (BC.MIB ->isCFI (Inst))
164+ continue ;
165+
166+ // No need to check for nullopt: we only entered this loop after the first
167+ // instruction had its RAState set, and RAState is always set for the
168+ // previous instruction in the previous iteration of the loop.
169+ std::optional<bool > PrevRAState = BC.MIB ->getRAState (Prev);
170+
171+ std::optional<bool > RAState = BC.MIB ->getRAState (Inst);
172+ if (!RAState.has_value ()) {
173+ if (BC.MIB ->isPSignOnLR (Prev))
174+ PrevRAState = true ;
175+ else if (BC.MIB ->isPAuthOnLR (Prev))
176+ PrevRAState = false ;
177+ BC.MIB ->setRAState (Inst, *PrevRAState);
178+ }
179+ Prev = Inst;
180+ }
181+ }
182+
183+ void InsertNegateRAState::markUnknownBlock (BinaryContext &BC,
184+ BinaryBasicBlock &BB, bool State) {
185+ // If we call this when an Instruction has either kRASigned or kRAUnsigned
186+ // annotation, setRASigned or setRAUnsigned would fail.
187+ assert (isUnknownBlock (BC, BB) &&
188+ " markUnknownBlock should only be called on unknown blocks" );
189+ for (MCInst &Inst : BB) {
190+ if (BC.MIB ->isCFI (Inst))
191+ continue ;
192+ BC.MIB ->setRAState (Inst, State);
193+ }
194+ }
195+
196+ void InsertNegateRAState::fillUnknownStubs (BinaryFunction &BF) {
108197 BinaryContext &BC = BF.getBinaryContext ();
109198 bool FirstIter = true ;
110199 MCInst PrevInst;
111- for (BinaryBasicBlock &BB : BF) {
112- for (MCInst &Inst : BB) {
113- if (BC.MIB ->isCFI (Inst))
114- continue ;
200+ for (FunctionFragment &FF : BF.getLayout ().fragments ()) {
201+ for (BinaryBasicBlock *BB : FF) {
202+ if (FirstIter) {
203+ FirstIter = false ;
204+ if (isUnknownBlock (BC, *BB))
205+ // If the first BasicBlock is unknown, the function's entry RAState
206+ // should be used.
207+ markUnknownBlock (BC, *BB, BF.getInitialRAState ());
208+ } else if (isUnknownBlock (BC, *BB)) {
209+ // As explained in issue #160989, the unwind info is incorrect for
210+ // stubs. Indicating the correct RAState without the rest of the unwind
211+ // info being correct is not useful. Instead, we copy the RAState from
212+ // the previous instruction.
213+ std::optional<bool > PrevRAState = BC.MIB ->getRAState (PrevInst);
214+ if (!PrevRAState.has_value ()) {
215+ // No non-cfi instruction encountered in the function yet.
216+ // This means the RAState is the same as at the function entry.
217+ markUnknownBlock (BC, *BB, BF.getInitialRAState ());
218+ continue ;
219+ }
115220
116- auto RAState = BC.MIB ->getRAState (Inst);
117- if (!FirstIter && !RAState) {
118221 if (BC.MIB ->isPSignOnLR (PrevInst))
119- RAState = true ;
222+ PrevRAState = true ;
120223 else if (BC.MIB ->isPAuthOnLR (PrevInst))
121- RAState = false ;
122- else {
123- auto PrevRAState = BC.MIB ->getRAState (PrevInst);
124- RAState = PrevRAState ? *PrevRAState : false ;
125- }
126- BC.MIB ->setRAState (Inst, *RAState);
127- } else {
128- FirstIter = false ;
129- if (!RAState)
130- BC.MIB ->setRAState (Inst, BF.getInitialRAState ());
224+ PrevRAState = false ;
225+ markUnknownBlock (BC, *BB, *PrevRAState);
131226 }
132- PrevInst = Inst;
227+ // This function iterates on BasicBlocks, so the PrevInst has to be
228+ // updated to the last instruction of the current BasicBlock. If the
229+ // BasicBlock is empty, or only has PseudoInstructions, PrevInst will not
230+ // be updated.
231+ auto Last = BB->getLastNonPseudo ();
232+ if (Last != BB->rend ())
233+ PrevInst = *Last;
133234 }
134235 }
135236}
0 commit comments