Skip to content

Commit f543673

Browse files
committed
[BOLT][AArch64] Fix which PSign and PAuth variants are used (llvm#120064)
- only the ones operating on LR should be marked with .cfi_cfi_negate_ra_state - added support for fused PtrAuth and Ret instructions, e.g. RETAA.
1 parent d3f8e37 commit f543673

File tree

5 files changed

+65
-39
lines changed

5 files changed

+65
-39
lines changed

bolt/include/bolt/Core/MCPlusBuilder.h

Lines changed: 21 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -599,6 +599,27 @@ class MCPlusBuilder {
599599
return std::nullopt;
600600
}
601601

602+
virtual bool isPSignOnLR(const MCInst &Inst) const {
603+
llvm_unreachable("not implemented");
604+
return false;
605+
}
606+
607+
virtual bool isPAuthOnLR(const MCInst &Inst) const {
608+
llvm_unreachable("not implemented");
609+
return false;
610+
}
611+
612+
virtual bool isPAuthAndRet(const MCInst &Inst) const {
613+
llvm_unreachable("not implemented");
614+
return false;
615+
}
616+
617+
virtual bool isAuthenticationOfReg(const MCInst &Inst,
618+
MCPhysReg AuthenticatedReg) const {
619+
llvm_unreachable("not implemented");
620+
return false;
621+
}
622+
602623
/// Returns the register used as a return address. Returns std::nullopt if
603624
/// not applicable, such as reading the return address from a system register
604625
/// or from the stack.
@@ -818,13 +839,6 @@ class MCPlusBuilder {
818839
llvm_unreachable("not implemented");
819840
return false;
820841
}
821-
virtual bool isPAuth(MCInst &Inst) const {
822-
llvm_unreachable("not implemented");
823-
}
824-
825-
virtual bool isPSign(MCInst &Inst) const {
826-
llvm_unreachable("not implemented");
827-
}
828842

829843
virtual bool isCleanRegXOR(const MCInst &Inst) const {
830844
llvm_unreachable("not implemented");

bolt/include/bolt/Passes/InsertNegateRAStatePass.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,9 @@ class InsertNegateRAState : public BinaryFunctionPass {
3030

3131
private:
3232
/// Loops over all instructions and adds OpNegateRAState CFI
33-
/// after any pointer signing or authenticating instructions.
33+
/// after any pointer signing or authenticating instructions,
34+
/// which operate on the LR, except fused ptrauth + ret instructions
35+
/// (such as RETAA).
3436
/// Returns true, if any OpNegateRAState CFIs were added.
3537
bool addNegateRAStateAfterPacOrAuth(BinaryFunction &BF);
3638
/// Because states are tracked as MCAnnotations on individual instructions,

bolt/lib/Passes/InsertNegateRAStatePass.cpp

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -46,14 +46,16 @@ void InsertNegateRAState::runOnFunction(BinaryFunction &BF) {
4646
bool FirstIter = true;
4747
MCInst PrevInst;
4848
BinaryBasicBlock *PrevBB = nullptr;
49+
// We need to iterate on BBs in the Layout order
50+
// not in the order they are stored in the BF class.
4951
auto *Begin = BF.getLayout().block_begin();
5052
auto *End = BF.getLayout().block_end();
5153
for (auto *BB = Begin; BB != End; BB++) {
5254

5355
// Support for function splitting:
54-
// if two consecutive BBs are going to end up in different functions,
55-
// we have to negate the RA State, so the new function starts with a Signed
56-
// state.
56+
// if two consecutive BBs with Signed state are going to end up in different
57+
// functions, we have to add a OpNegateRAState to the beginning of the newly
58+
// split function, so it starts with a Signed state.
5759
if (PrevBB != nullptr &&
5860
PrevBB->getFragmentNum() != (*BB)->getFragmentNum() &&
5961
BC.MIB->isRASigned(*((*BB)->begin()))) {
@@ -68,6 +70,8 @@ void InsertNegateRAState::runOnFunction(BinaryFunction &BF) {
6870
continue;
6971

7072
if (!FirstIter) {
73+
// Consecutive instructions with different RAState means we need to add
74+
// a OpNegateRAState.
7175
if ((BC.MIB->isRASigned(PrevInst) && BC.MIB->isRAUnsigned(Inst)) ||
7276
(BC.MIB->isRAUnsigned(PrevInst) && BC.MIB->isRASigned(Inst))) {
7377

@@ -90,7 +94,8 @@ bool InsertNegateRAState::addNegateRAStateAfterPacOrAuth(BinaryFunction &BF) {
9094
for (BinaryBasicBlock &BB : BF) {
9195
for (auto Iter = BB.begin(); Iter != BB.end(); ++Iter) {
9296
MCInst &Inst = *Iter;
93-
if (BC.MIB->isPSign(Inst) || BC.MIB->isPAuth(Inst)) {
97+
if (BC.MIB->isPSignOnLR(Inst) ||
98+
(BC.MIB->isPAuthOnLR(Inst) && !BC.MIB->isPAuthAndRet(Inst))) {
9499
Iter = BF.addCFIInstruction(
95100
&BB, Iter + 1, MCCFIInstruction::createNegateRAState(nullptr));
96101
FoundAny = true;

bolt/lib/Passes/MarkRAStates.cpp

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,8 @@ void MarkRAStates::runOnFunction(BinaryFunction &BF) {
4646
for (BinaryBasicBlock &BB : BF) {
4747
for (auto It = BB.begin(); It != BB.end(); ++It) {
4848
MCInst &Inst = *It;
49-
if ((BC.MIB->isPSign(Inst) || BC.MIB->isPAuth(Inst)) &&
49+
if ((BC.MIB->isPSignOnLR(Inst) ||
50+
(BC.MIB->isPAuthOnLR(Inst) && !BC.MIB->isPAuthAndRet(Inst))) &&
5051
!BC.MIB->hasNegateRAState(Inst)) {
5152
// no .cfi_negate_ra_state attached to signing or authenticating instr
5253
// means, that this is a function with handwritten assembly, which might
@@ -71,7 +72,7 @@ void MarkRAStates::runOnFunction(BinaryFunction &BF) {
7172
if (BC.MIB->isCFI(Inst))
7273
continue;
7374

74-
if (BC.MIB->isPSign(Inst)) {
75+
if (BC.MIB->isPSignOnLR(Inst)) {
7576
if (RAState) {
7677
// RA signing instructions should only follow unsigned RA state.
7778
BC.outs() << "BOLT-INFO: inconsistent RAStates in function "
@@ -80,7 +81,7 @@ void MarkRAStates::runOnFunction(BinaryFunction &BF) {
8081
return;
8182
}
8283
BC.MIB->setRASigning(Inst);
83-
} else if (BC.MIB->isPAuth(Inst)) {
84+
} else if (BC.MIB->isPAuthOnLR(Inst)) {
8485
if (!RAState) {
8586
// RA authenticating instructions should only follow signed RA state.
8687
BC.outs() << "BOLT-INFO: inconsistent RAStates in function "

bolt/lib/Target/AArch64/AArch64MCPlusBuilder.cpp

Lines changed: 28 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -232,6 +232,34 @@ class AArch64MCPlusBuilder : public MCPlusBuilder {
232232
}
233233
}
234234

235+
bool isPSignOnLR(const MCInst &Inst) const override {
236+
MCPhysReg SignReg = getSignedReg(Inst);
237+
return SignReg != getNoRegister() && SignReg == AArch64::LR;
238+
}
239+
240+
bool isPAuthOnLR(const MCInst &Inst) const override {
241+
ErrorOr<MCPhysReg> AutReg = getAuthenticatedReg(Inst);
242+
if (AutReg && *AutReg != getNoRegister() && *AutReg == AArch64::LR)
243+
return true;
244+
return false;
245+
}
246+
247+
bool isPAuthAndRet(const MCInst &Inst) const override {
248+
return Inst.getOpcode() == AArch64::RETAA ||
249+
Inst.getOpcode() == AArch64::RETAB ||
250+
Inst.getOpcode() == AArch64::RETAASPPCi ||
251+
Inst.getOpcode() == AArch64::RETABSPPCi ||
252+
Inst.getOpcode() == AArch64::RETAASPPCr ||
253+
Inst.getOpcode() == AArch64::RETABSPPCr;
254+
}
255+
256+
bool isAuthenticationOfReg(const MCInst &Inst, MCPhysReg Reg) const override {
257+
if (Reg == getNoRegister())
258+
return false;
259+
ErrorOr<MCPhysReg> AuthenticatedReg = getAuthenticatedReg(Inst);
260+
return AuthenticatedReg.getError() ? false : *AuthenticatedReg == Reg;
261+
}
262+
235263
std::optional<MCPhysReg> getSignedReg(const MCInst &Inst) const override {
236264
switch (Inst.getOpcode()) {
237265
case AArch64::PACIA:
@@ -895,30 +923,6 @@ class AArch64MCPlusBuilder : public MCPlusBuilder {
895923
}
896924
return false;
897925
}
898-
bool isPAuth(MCInst &Inst) const override {
899-
return Inst.getOpcode() == AArch64::AUTIA ||
900-
Inst.getOpcode() == AArch64::AUTIB ||
901-
Inst.getOpcode() == AArch64::AUTIA1716 ||
902-
Inst.getOpcode() == AArch64::AUTIB1716 ||
903-
Inst.getOpcode() == AArch64::AUTIASP ||
904-
Inst.getOpcode() == AArch64::AUTIBSP ||
905-
Inst.getOpcode() == AArch64::AUTIAZ ||
906-
Inst.getOpcode() == AArch64::AUTIBZ ||
907-
Inst.getOpcode() == AArch64::AUTIZA ||
908-
Inst.getOpcode() == AArch64::AUTIZB;
909-
}
910-
bool isPSign(MCInst &Inst) const override {
911-
return Inst.getOpcode() == AArch64::PACIA ||
912-
Inst.getOpcode() == AArch64::PACIB ||
913-
Inst.getOpcode() == AArch64::PACIA1716 ||
914-
Inst.getOpcode() == AArch64::PACIB1716 ||
915-
Inst.getOpcode() == AArch64::PACIASP ||
916-
Inst.getOpcode() == AArch64::PACIBSP ||
917-
Inst.getOpcode() == AArch64::PACIAZ ||
918-
Inst.getOpcode() == AArch64::PACIBZ ||
919-
Inst.getOpcode() == AArch64::PACIZA ||
920-
Inst.getOpcode() == AArch64::PACIZB;
921-
}
922926

923927
bool isRegToRegMove(const MCInst &Inst, MCPhysReg &From,
924928
MCPhysReg &To) const override {

0 commit comments

Comments
 (0)