Skip to content

Commit cd8b71c

Browse files
committed
[PAuthLR] Add support for FEAT_PAuth_LR's DWARF frame instruction
This introduces compiler and dwarfdump support for emitting and parsing the new `DW_CFA_AARCH64_negate_ra_state_with_pc` DWARF instruction for FEAT_PAuth_LR. This does mean that, when using FEAT_PAuthLR, the improvements introduced in #96337 cannot be utilised. `.cfi_negate_ra_state_with_pc` must be emitted directly after the signing instruction, and when bundled with other CFI calls, leads to faults when running a program. There are no changes seen when not using FEAT_PAuthLR to how the CFI Instructions are generated. See ARM-software/abi-aa#245 for the ABI change that incororates FEAT_PAuthLR. Authored-by: pratlucas <lucas.prates@arm.com> Co-authored by: vhscampos <victor.campos@arm.com> Co-authored by: Stylie777 <jack.styles@arm.com>
1 parent a702473 commit cd8b71c

22 files changed

+283
-91
lines changed

llvm/include/llvm/BinaryFormat/Dwarf.def

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1238,6 +1238,7 @@ HANDLE_DW_CFA(0x16, val_expression)
12381238
// Vendor extensions:
12391239
HANDLE_DW_CFA_PRED(0x1d, MIPS_advance_loc8, SELECT_MIPS64)
12401240
HANDLE_DW_CFA_PRED(0x2d, GNU_window_save, SELECT_SPARC)
1241+
HANDLE_DW_CFA_PRED(0x2c, AARCH64_negate_ra_state_with_pc, SELECT_AARCH64)
12411242
HANDLE_DW_CFA_PRED(0x2d, AARCH64_negate_ra_state, SELECT_AARCH64)
12421243
HANDLE_DW_CFA_PRED(0x2e, GNU_args_size, SELECT_X86)
12431244
// Heterogeneous Debugging Extension defined at

llvm/include/llvm/MC/MCDwarf.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -515,6 +515,7 @@ class MCCFIInstruction {
515515
OpRegister,
516516
OpWindowSave,
517517
OpNegateRAState,
518+
OpNegateRAStateWithPC,
518519
OpGnuArgsSize,
519520
OpLabel,
520521
};
@@ -642,6 +643,13 @@ class MCCFIInstruction {
642643
return MCCFIInstruction(OpNegateRAState, L, 0, INT64_C(0), Loc);
643644
}
644645

646+
/// .cfi_negate_ra_state_with_pc AArch64 negate RA state with PC.
647+
static MCCFIInstruction createNegateRAStateWithPC(MCSymbol *L,
648+
SMLoc Loc = {}) {
649+
return MCCFIInstruction(OpNegateRAStateWithPC, L, 0, INT64_C(0), Loc);
650+
}
651+
652+
645653
/// .cfi_restore says that the rule for Register is now the same as it
646654
/// was at the beginning of the function, after all initial instructions added
647655
/// by .cfi_startproc were executed.

llvm/include/llvm/MC/MCStreamer.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1022,6 +1022,7 @@ class MCStreamer {
10221022
SMLoc Loc = {});
10231023
virtual void emitCFIWindowSave(SMLoc Loc = {});
10241024
virtual void emitCFINegateRAState(SMLoc Loc = {});
1025+
virtual void emitCFINegateRAStateWithPC(SMLoc Loc = {});
10251026
virtual void emitCFILabelDirective(SMLoc Loc, StringRef Name);
10261027

10271028
virtual void emitWinCFIStartProc(const MCSymbol *Symbol, SMLoc Loc = SMLoc());

llvm/lib/CodeGen/AsmPrinter/AsmPrinterDwarf.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -236,6 +236,9 @@ void AsmPrinter::emitCFIInstruction(const MCCFIInstruction &Inst) const {
236236
case MCCFIInstruction::OpNegateRAState:
237237
OutStreamer->emitCFINegateRAState(Loc);
238238
break;
239+
case MCCFIInstruction::OpNegateRAStateWithPC:
240+
OutStreamer->emitCFINegateRAStateWithPC(Loc);
241+
break;
239242
case MCCFIInstruction::OpSameValue:
240243
OutStreamer->emitCFISameValue(Inst.getRegister(), Loc);
241244
break;

llvm/lib/CodeGen/CFIInstrInserter.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -260,6 +260,7 @@ void CFIInstrInserter::calculateOutgoingCFAInfo(MBBCFAInfo &MBBInfo) {
260260
case MCCFIInstruction::OpEscape:
261261
case MCCFIInstruction::OpWindowSave:
262262
case MCCFIInstruction::OpNegateRAState:
263+
case MCCFIInstruction::OpNegateRAStateWithPC:
263264
case MCCFIInstruction::OpGnuArgsSize:
264265
case MCCFIInstruction::OpLabel:
265266
break;

llvm/lib/CodeGen/MIRParser/MILexer.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -238,6 +238,8 @@ static MIToken::TokenKind getIdentifierKind(StringRef Identifier) {
238238
.Case("window_save", MIToken::kw_cfi_window_save)
239239
.Case("negate_ra_sign_state",
240240
MIToken::kw_cfi_aarch64_negate_ra_sign_state)
241+
.Case("negate_ra_sign_state_with_pc",
242+
MIToken::kw_cfi_aarch64_negate_ra_sign_state_with_pc)
241243
.Case("blockaddress", MIToken::kw_blockaddress)
242244
.Case("intrinsic", MIToken::kw_intrinsic)
243245
.Case("target-index", MIToken::kw_target_index)

llvm/lib/CodeGen/MIRParser/MILexer.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,7 @@ struct MIToken {
9696
kw_cfi_undefined,
9797
kw_cfi_window_save,
9898
kw_cfi_aarch64_negate_ra_sign_state,
99+
kw_cfi_aarch64_negate_ra_sign_state_with_pc,
99100
kw_blockaddress,
100101
kw_intrinsic,
101102
kw_target_index,

llvm/lib/CodeGen/MIRParser/MIParser.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2576,6 +2576,10 @@ bool MIParser::parseCFIOperand(MachineOperand &Dest) {
25762576
case MIToken::kw_cfi_aarch64_negate_ra_sign_state:
25772577
CFIIndex = MF.addFrameInst(MCCFIInstruction::createNegateRAState(nullptr));
25782578
break;
2579+
case MIToken::kw_cfi_aarch64_negate_ra_sign_state_with_pc:
2580+
CFIIndex =
2581+
MF.addFrameInst(MCCFIInstruction::createNegateRAStateWithPC(nullptr));
2582+
break;
25792583
case MIToken::kw_cfi_escape: {
25802584
std::string Values;
25812585
if (parseCFIEscapeValues(Values))
@@ -2931,6 +2935,7 @@ bool MIParser::parseMachineOperand(const unsigned OpCode, const unsigned OpIdx,
29312935
case MIToken::kw_cfi_undefined:
29322936
case MIToken::kw_cfi_window_save:
29332937
case MIToken::kw_cfi_aarch64_negate_ra_sign_state:
2938+
case MIToken::kw_cfi_aarch64_negate_ra_sign_state_with_pc:
29342939
return parseCFIOperand(Dest);
29352940
case MIToken::kw_blockaddress:
29362941
return parseBlockAddressOperand(Dest);

llvm/lib/CodeGen/MachineOperand.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -768,6 +768,10 @@ static void printCFI(raw_ostream &OS, const MCCFIInstruction &CFI,
768768
if (MCSymbol *Label = CFI.getLabel())
769769
MachineOperand::printSymbol(OS, *Label);
770770
break;
771+
case MCCFIInstruction::OpNegateRAStateWithPC:
772+
OS << "negate_ra_sign_state_with_pc ";
773+
if (MCSymbol *Label = CFI.getLabel())
774+
MachineOperand::printSymbol(OS, *Label);
771775
default:
772776
// TODO: Print the other CFI Operations.
773777
OS << "<unserializable cfi directive>";

llvm/lib/DebugInfo/DWARF/DWARFDebugFrame.cpp

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -288,6 +288,7 @@ Error CFIProgram::parse(DWARFDataExtractor Data, uint64_t *Offset,
288288
case DW_CFA_remember_state:
289289
case DW_CFA_restore_state:
290290
case DW_CFA_GNU_window_save:
291+
case DW_CFA_AARCH64_negate_ra_state_with_pc:
291292
// No operands
292293
addInstruction(Opcode);
293294
break;
@@ -666,6 +667,28 @@ Error UnwindTable::parseRows(const CFIProgram &CFIP, UnwindRow &Row,
666667
}
667668
break;
668669

670+
case dwarf::DW_CFA_AARCH64_negate_ra_state_with_pc: {
671+
constexpr uint32_t AArch64DWARFPAuthRaState = 34;
672+
auto LRLoc = Row.getRegisterLocations().getRegisterLocation(
673+
AArch64DWARFPAuthRaState);
674+
if (LRLoc) {
675+
if (LRLoc->getLocation() == UnwindLocation::Constant) {
676+
// Toggle the constant value of bits[1:0] from 0 to 1 or 1 to 0.
677+
LRLoc->setConstant(LRLoc->getConstant() ^ 0x3);
678+
} else {
679+
return createStringError(
680+
errc::invalid_argument,
681+
"%s encountered when existing rule for this register is not "
682+
"a constant",
683+
CFIP.callFrameString(Inst.Opcode).str().c_str());
684+
}
685+
} else {
686+
Row.getRegisterLocations().setRegisterLocation(
687+
AArch64DWARFPAuthRaState, UnwindLocation::createIsConstant(0x3));
688+
}
689+
break;
690+
}
691+
669692
case dwarf::DW_CFA_undefined: {
670693
llvm::Expected<uint64_t> RegNum = Inst.getOperandAsUnsigned(CFIP, 0);
671694
if (!RegNum)
@@ -847,6 +870,7 @@ CFIProgram::getOperandTypes() {
847870
DECLARE_OP0(DW_CFA_remember_state);
848871
DECLARE_OP0(DW_CFA_restore_state);
849872
DECLARE_OP0(DW_CFA_GNU_window_save);
873+
DECLARE_OP0(DW_CFA_AARCH64_negate_ra_state_with_pc);
850874
DECLARE_OP1(DW_CFA_GNU_args_size, OT_Offset);
851875
DECLARE_OP0(DW_CFA_nop);
852876

0 commit comments

Comments
 (0)