[BOLT][AArch64] Handle PAuth call instructions in isIndirectCall (#133227)

Handle `BLRA*` opcodes in AArch64MCPlusBuilder::isIndirectCall, update
getRegUsedAsCallDest accordingly.
This commit is contained in:
Anatoly Trosinenko
2025-04-08 13:23:10 +03:00
committed by GitHub
parent ff5b649a84
commit 8521bd2424
4 changed files with 30 additions and 17 deletions

View File

@@ -577,12 +577,12 @@ public:
return getNoRegister();
}
/// Returns the register used as call destination, or no-register, if not
/// an indirect call. Sets IsAuthenticatedInternally if the instruction
/// accepts a signed pointer as its operand and authenticates it internally.
/// Returns the register used as the destination of an indirect branch or call
/// instruction. Sets IsAuthenticatedInternally if the instruction accepts
/// a signed pointer as its operand and authenticates it internally.
virtual MCPhysReg
getRegUsedAsCallDest(const MCInst &Inst,
bool &IsAuthenticatedInternally) const {
getRegUsedAsIndirectBranchDest(const MCInst &Inst,
bool &IsAuthenticatedInternally) const {
llvm_unreachable("not implemented");
return getNoRegister();
}

View File

@@ -498,14 +498,16 @@ static std::shared_ptr<Report>
shouldReportCallGadget(const BinaryContext &BC, const MCInstReference &Inst,
const State &S) {
static const GadgetKind CallKind("non-protected call found");
if (!BC.MIB->isCall(Inst) && !BC.MIB->isBranch(Inst))
if (!BC.MIB->isIndirectCall(Inst) && !BC.MIB->isIndirectBranch(Inst))
return nullptr;
bool IsAuthenticated = false;
MCPhysReg DestReg = BC.MIB->getRegUsedAsCallDest(Inst, IsAuthenticated);
if (IsAuthenticated || DestReg == BC.MIB->getNoRegister())
MCPhysReg DestReg =
BC.MIB->getRegUsedAsIndirectBranchDest(Inst, IsAuthenticated);
if (IsAuthenticated)
return nullptr;
assert(DestReg != BC.MIB->getNoRegister());
LLVM_DEBUG({
traceInst(BC, "Found call inst", Inst);
traceReg(BC, "Call destination reg", DestReg);

View File

@@ -10,6 +10,7 @@
//
//===----------------------------------------------------------------------===//
#include "AArch64InstrInfo.h"
#include "AArch64MCSymbolizer.h"
#include "MCTargetDesc/AArch64AddressingModes.h"
#include "MCTargetDesc/AArch64FixupKinds.h"
@@ -277,15 +278,14 @@ public:
}
}
MCPhysReg
getRegUsedAsCallDest(const MCInst &Inst,
bool &IsAuthenticatedInternally) const override {
assert(isCall(Inst) || isBranch(Inst));
IsAuthenticatedInternally = false;
MCPhysReg getRegUsedAsIndirectBranchDest(
const MCInst &Inst, bool &IsAuthenticatedInternally) const override {
assert(isIndirectCall(Inst) || isIndirectBranch(Inst));
switch (Inst.getOpcode()) {
case AArch64::BR:
case AArch64::BLR:
IsAuthenticatedInternally = false;
return Inst.getOperand(0).getReg();
case AArch64::BRAA:
case AArch64::BRAB:
@@ -298,9 +298,7 @@ public:
IsAuthenticatedInternally = true;
return Inst.getOperand(0).getReg();
default:
if (isIndirectCall(Inst) || isIndirectBranch(Inst))
llvm_unreachable("Unhandled indirect branch");
return getNoRegister();
llvm_unreachable("Unhandled indirect branch or call");
}
}
@@ -699,7 +697,7 @@ public:
}
bool isIndirectCall(const MCInst &Inst) const override {
return Inst.getOpcode() == AArch64::BLR;
return isIndirectCallOpcode(Inst.getOpcode());
}
MCPhysReg getSpRegister(int Size) const {

View File

@@ -726,6 +726,19 @@ static inline bool isIndirectBranchOpcode(int Opc) {
return false;
}
static inline bool isIndirectCallOpcode(unsigned Opc) {
switch (Opc) {
case AArch64::BLR:
case AArch64::BLRAA:
case AArch64::BLRAB:
case AArch64::BLRAAZ:
case AArch64::BLRABZ:
return true;
default:
return false;
}
}
static inline bool isPTrueOpcode(unsigned Opc) {
switch (Opc) {
case AArch64::PTRUE_B: