@@ -34,57 +34,35 @@ void InsertNegateRAState::runOnFunction(BinaryFunction &BF) {
3434 return ;
3535 }
3636
37- // If none is inserted, the function doesn't need more work.
38- if (!addNegateRAStateAfterPSignOrPAuth (BF))
39- return ;
37+ // Attach .cfi_negate_ra_state to the "trivial" cases first.
38+ addNegateRAStateAfterPSignOrPAuth (BF);
4039
4140 inferUnknownStates (BF);
4241
43- // Support for function splitting:
44- // if two consecutive BBs with Signed state are going to end up in different
45- // functions (so are held by different FunctionFragments), we have to add a
46- // OpNegateRAState to the beginning of the newly split function, so it starts
47- // with a Signed state.
4842 for (FunctionFragment &FF : BF.getLayout ().fragments ()) {
49- // Find the first BB in the FF which has Instructions.
50- // BOLT can generate empty BBs at function splitting which are only used as
51- // target labels. We should add the negate-ra-state CFI to the first
52- // non-empty BB.
53- auto *FirstNonEmpty =
54- std::find_if (FF.begin (), FF.end (), [](BinaryBasicBlock *BB) {
55- // getFirstNonPseudo returns BB.end() if it does not find any
56- // Instructions.
57- return BB->getFirstNonPseudo () != BB->end ();
58- });
59- if (BC.MIB ->isRASigned (*((*FirstNonEmpty)->begin ()))) {
60- BF.addCFIInstruction (*FirstNonEmpty, (*FirstNonEmpty)->begin (),
61- MCCFIInstruction::createNegateRAState (nullptr ));
62- }
63- }
64-
65- bool FirstIter = true ;
66- MCInst PrevInst;
67- for (BinaryBasicBlock &BB : BF) {
68- for (auto It = BB.begin (); It != BB.end (); ++It) {
69-
70- MCInst &Inst = *It;
71- if (BC.MIB ->isCFI (Inst))
72- continue ;
73-
74- if (!FirstIter) {
75- // Consecutive instructions with different RAState means we need to add
76- // a OpNegateRAState.
77- if ((BC.MIB ->isRASigned (PrevInst) && BC.MIB ->isRAUnsigned (Inst)) ||
78- (BC.MIB ->isRAUnsigned (PrevInst) && BC.MIB ->isRASigned (Inst))) {
79-
80- It = BF.addCFIInstruction (
81- &BB, It, MCCFIInstruction::createNegateRAState (nullptr ));
43+ coverFunctionFragmentStart (BF, FF);
44+ bool FirstIter = true ;
45+ MCInst PrevInst;
46+ // As this pass runs after function splitting, we should only check
47+ // consecutive instructions inside FunctionFragments.
48+ for (BinaryBasicBlock *BB : FF) {
49+ for (auto It = BB->begin (); It != BB->end (); ++It) {
50+ MCInst &Inst = *It;
51+ if (BC.MIB ->isCFI (Inst))
52+ continue ;
53+ if (!FirstIter) {
54+ // Consecutive instructions with different RAState means we need to
55+ // add a OpNegateRAState.
56+ if ((BC.MIB ->isRASigned (PrevInst) && BC.MIB ->isRAUnsigned (Inst)) ||
57+ (BC.MIB ->isRAUnsigned (PrevInst) && BC.MIB ->isRASigned (Inst))) {
58+ It = BF.addCFIInstruction (
59+ BB, It, MCCFIInstruction::createNegateRAState (nullptr ));
60+ }
61+ } else {
62+ FirstIter = false ;
8263 }
83-
84- } else {
85- FirstIter = false ;
64+ PrevInst = *It;
8665 }
87- PrevInst = *It;
8866 }
8967 }
9068}
@@ -107,6 +85,29 @@ bool InsertNegateRAState::addNegateRAStateAfterPSignOrPAuth(
10785 return FoundAny;
10886}
10987
88+ void InsertNegateRAState::coverFunctionFragmentStart (BinaryFunction &BF,
89+ FunctionFragment &FF) {
90+ BinaryContext &BC = BF.getBinaryContext ();
91+ if (FF.empty ())
92+ return ;
93+ // Find the first BB in the FF which has Instructions.
94+ // BOLT can generate empty BBs at function splitting which are only used as
95+ // target labels. We should add the negate-ra-state CFI to the first
96+ // non-empty BB.
97+ auto *FirstNonEmpty =
98+ std::find_if (FF.begin (), FF.end (), [](BinaryBasicBlock *BB) {
99+ // getFirstNonPseudo returns BB.end() if it does not find any
100+ // Instructions.
101+ return BB->getFirstNonPseudo () != BB->end ();
102+ });
103+ // If a function is already split in the input, the first FF can also start
104+ // with Signed state. This covers that scenario as well.
105+ if (BC.MIB ->isRASigned (*((*FirstNonEmpty)->begin ()))) {
106+ BF.addCFIInstruction (*FirstNonEmpty, (*FirstNonEmpty)->begin (),
107+ MCCFIInstruction::createNegateRAState (nullptr ));
108+ }
109+ }
110+
110111void InsertNegateRAState::inferUnknownStates (BinaryFunction &BF) {
111112 BinaryContext &BC = BF.getBinaryContext ();
112113 bool FirstIter = true ;
0 commit comments