llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT--> @llvm/pr-subscribers-libunwind Author: Jack Styles (Stylie777) <details> <summary>Changes</summary> As part of FEAT_PAuthLR, a new DWARF Frame Instruction was introduced, `DW_CFA_AARCH64_negate_ra_state_with_pc`. This instructs Libunwind that the PC has been used with the signing instruction. This change includes three commits - Libunwind support for the newly introduced DWARF Instruction - CodeGen Support for the DWARF Instructions - Reversing the changes made in #<!-- -->96377. Due to `DW_CFA_AARCH64_negate_ra_state_with_pc`'s requirements to be placed immediately after the signing instruction, this would mean the CFI Instruction location was not consistent with the generated location when not using FEAT_PAuthLR. The commit reverses the changes and makes the location consistent across the different branch protection options. While this does have a code size effect, this is a negligible one. For the ABI information, see here: https://github.com/ARM-software/abi-aa/blob/853286c7ab66048e4b819682ce17f567b77a0291/aadwarf64/aadwarf64.rst#id23 --- Patch is 78.23 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/112171.diff 34 Files Affected: - (modified) libunwind/src/DwarfInstructions.hpp (+42-12) - (modified) libunwind/src/DwarfParser.hpp (+20) - (modified) libunwind/src/dwarf2.h (+2-1) - (modified) llvm/include/llvm/BinaryFormat/Dwarf.def (+1) - (modified) llvm/include/llvm/MC/MCDwarf.h (+8) - (modified) llvm/include/llvm/MC/MCStreamer.h (+1) - (modified) llvm/lib/CodeGen/AsmPrinter/AsmPrinterDwarf.cpp (+3) - (modified) llvm/lib/CodeGen/CFIInstrInserter.cpp (+1) - (modified) llvm/lib/CodeGen/MIRParser/MILexer.cpp (+2) - (modified) llvm/lib/CodeGen/MIRParser/MILexer.h (+1) - (modified) llvm/lib/CodeGen/MIRParser/MIParser.cpp (+5) - (modified) llvm/lib/CodeGen/MachineOperand.cpp (+4) - (modified) llvm/lib/DebugInfo/DWARF/DWARFDebugFrame.cpp (+24) - (modified) llvm/lib/MC/MCAsmStreamer.cpp (+7) - (modified) llvm/lib/MC/MCDwarf.cpp (+4) - (modified) llvm/lib/MC/MCStreamer.cpp (+10) - (modified) llvm/lib/Target/AArch64/AArch64FrameLowering.cpp (+4-1) - (modified) llvm/lib/Target/AArch64/AArch64PointerAuth.cpp (+41-31) - (modified) llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp (+10) - (modified) llvm/test/CodeGen/AArch64/machine-outliner-retaddr-sign-cfi.ll (+1-2) - (modified) llvm/test/CodeGen/AArch64/machine-outliner-retaddr-sign-diff-scope-same-key.ll (+2-4) - (modified) llvm/test/CodeGen/AArch64/machine-outliner-retaddr-sign-non-leaf.ll (+103-18) - (modified) llvm/test/CodeGen/AArch64/machine-outliner-retaddr-sign-regsave.mir (+1-2) - (modified) llvm/test/CodeGen/AArch64/machine-outliner-retaddr-sign-same-scope-diff-key.ll (+113-26) - (modified) llvm/test/CodeGen/AArch64/machine-outliner-retaddr-sign-subtarget.ll (+3-6) - (modified) llvm/test/CodeGen/AArch64/machine-outliner-retaddr-sign-thunk.ll (+133-36) - (modified) llvm/test/CodeGen/AArch64/pacbti-llvm-generated-funcs-2.ll (+1-2) - (modified) llvm/test/CodeGen/AArch64/sign-return-address-cfi-negate-ra-state.ll (+5-6) - (modified) llvm/test/CodeGen/AArch64/sign-return-address-pauth-lr.ll (+105-57) - (modified) llvm/test/CodeGen/AArch64/sign-return-address.ll (+9-9) - (modified) llvm/test/CodeGen/MIR/AArch64/return-address-signing.mir (+23) - (modified) llvm/test/MC/AArch64/directives-case_insensitive.s (+2) - (added) llvm/test/MC/AArch64/negate_ra_state_with_pc.s (+7) - (modified) llvm/unittests/DebugInfo/DWARF/DWARFDebugFrameTest.cpp (+1) ``````````diff diff --git a/libunwind/src/DwarfInstructions.hpp b/libunwind/src/DwarfInstructions.hpp index bd9ece60ee5881..e7c467de80adb6 100644 --- a/libunwind/src/DwarfInstructions.hpp +++ b/libunwind/src/DwarfInstructions.hpp @@ -74,8 +74,10 @@ class DwarfInstructions { __builtin_unreachable(); } #if defined(_LIBUNWIND_TARGET_AARCH64) - static bool getRA_SIGN_STATE(A &addressSpace, R registers, pint_t cfa, - PrologInfo &prolog); + static bool isReturnAddressSigned(A &addressSpace, R registers, pint_t cfa, + PrologInfo &prolog); + static bool isReturnAddressSignedWithPC(A &addressSpace, R registers, + pint_t cfa, PrologInfo &prolog); #endif }; @@ -173,8 +175,9 @@ v128 DwarfInstructions<A, R>::getSavedVectorRegister( } #if defined(_LIBUNWIND_TARGET_AARCH64) template <typename A, typename R> -bool DwarfInstructions<A, R>::getRA_SIGN_STATE(A &addressSpace, R registers, - pint_t cfa, PrologInfo &prolog) { +bool DwarfInstructions<A, R>::isReturnAddressSigned(A &addressSpace, + R registers, pint_t cfa, + PrologInfo &prolog) { pint_t raSignState; auto regloc = prolog.savedRegisters[UNW_AARCH64_RA_SIGN_STATE]; if (regloc.location == CFI_Parser<A>::kRegisterUnused) @@ -185,6 +188,22 @@ bool DwarfInstructions<A, R>::getRA_SIGN_STATE(A &addressSpace, R registers, // Only bit[0] is meaningful. return raSignState & 0x01; } + +template <typename A, typename R> +bool DwarfInstructions<A, R>::isReturnAddressSignedWithPC(A &addressSpace, + R registers, + pint_t cfa, + PrologInfo &prolog) { + pint_t raSignState; + auto regloc = prolog.savedRegisters[UNW_AARCH64_RA_SIGN_STATE]; + if (regloc.location == CFI_Parser<A>::kRegisterUnused) + raSignState = static_cast<pint_t>(regloc.value); + else + raSignState = getSavedRegister(addressSpace, registers, cfa, regloc); + + // Only bit[1] is meaningful. + return raSignState & 0x02; +} #endif template <typename A, typename R> @@ -288,7 +307,7 @@ int DwarfInstructions<A, R>::stepWithDwarf(A &addressSpace, pint_t pc, // restored. autia1716 is used instead of autia as autia1716 assembles // to a NOP on pre-v8.3a architectures. if ((R::getArch() == REGISTERS_ARM64) && - getRA_SIGN_STATE(addressSpace, registers, cfa, prolog) && + isReturnAddressSigned(addressSpace, registers, cfa, prolog) && returnAddress != 0) { #if !defined(_LIBUNWIND_IS_NATIVE_ONLY) return UNW_ECROSSRASIGNING; @@ -296,13 +315,24 @@ int DwarfInstructions<A, R>::stepWithDwarf(A &addressSpace, pint_t pc, register unsigned long long x17 __asm("x17") = returnAddress; register unsigned long long x16 __asm("x16") = cfa; - // These are the autia1716/autib1716 instructions. The hint instructions - // are used here as gcc does not assemble autia1716/autib1716 for pre - // armv8.3a targets. - if (cieInfo.addressesSignedWithBKey) - asm("hint 0xe" : "+r"(x17) : "r"(x16)); // autib1716 - else - asm("hint 0xc" : "+r"(x17) : "r"(x16)); // autia1716 + // We use the hint versions of the authentication instructions below to + // ensure they're assembled by the compiler even for targets with no + // FEAT_PAuth/FEAT_PAuth_LR support. + if(isReturnAddressSignedWithPC(addressSpace, registers, cfa, prolog)) { + register unsigned long long x15 __asm("x15") = prolog.ptrAuthDiversifier; + if(cieInfo.addressesSignedWithBKey) { + asm("hint 0x27\n\t" // pacm + "hint 0xe" : "+r"(x17) : "r"(x16), "r"(x15)); // autib1716 + } else { + asm("hint 0x27\n\t" // pacm + "hint 0xc" : "+r"(x17) : "r"(x16), "r"(x15)); // autia1716 + } + } else { + if (cieInfo.addressesSignedWithBKey) + asm("hint 0xe" : "+r"(x17) : "r"(x16)); // autib1716 + else + asm("hint 0xc" : "+r"(x17) : "r"(x16)); // autia1716 + } returnAddress = x17; #endif } diff --git a/libunwind/src/DwarfParser.hpp b/libunwind/src/DwarfParser.hpp index 0682942ce13799..b104d773ed4440 100644 --- a/libunwind/src/DwarfParser.hpp +++ b/libunwind/src/DwarfParser.hpp @@ -91,6 +91,9 @@ class CFI_Parser { int64_t cfaExpression; // CFA = expression uint32_t spExtraArgSize; RegisterLocation savedRegisters[kMaxRegisterNumber + 1]; + #if defined(_LIBUNWIND_TARGET_AARCH64) + pint_t ptrAuthDiversifier; + #endif enum class InitializeTime { kLazy, kNormal }; // When saving registers, this data structure is lazily initialized. @@ -799,6 +802,23 @@ bool CFI_Parser<A>::parseFDEInstructions(A &addressSpace, } break; +#if defined(_LIBUNWIND_TARGET_AARCH64) + case DW_CFA_AARCH64_negate_ra_state_with_pc: { + int64_t value = + results->savedRegisters[UNW_AARCH64_RA_SIGN_STATE].value ^ 0x3; + results->setRegisterValue(UNW_AARCH64_RA_SIGN_STATE, value, + initialState); + // When calucating the value of the PC, it is assumed that the CFI instruction + // is placed before the signing instruction, however it is placed after. Because + // of this, we need to take into account the CFI instruction is one instruction + // call later than expected, and reduce the PC value by 4 bytes to compensate. + results->ptrAuthDiversifier = fdeInfo.pcStart + codeOffset - 0x4; + _LIBUNWIND_TRACE_DWARF("DW_CFA_AARCH64_negate_ra_state_with_pc(pc=0x%" PRIx64 ")\n", + static_cast<uint64_t>(results->ptrAuthDiversifier)); + } + break; +#endif + #else (void)arch; #endif diff --git a/libunwind/src/dwarf2.h b/libunwind/src/dwarf2.h index 174277d5a79508..2ad3d3c464e80d 100644 --- a/libunwind/src/dwarf2.h +++ b/libunwind/src/dwarf2.h @@ -51,7 +51,8 @@ enum { DW_CFA_GNU_negative_offset_extended = 0x2F, // AARCH64 extensions - DW_CFA_AARCH64_negate_ra_state = 0x2D + DW_CFA_AARCH64_negate_ra_state_with_pc = 0x2C, + DW_CFA_AARCH64_negate_ra_state = 0x2D }; diff --git a/llvm/include/llvm/BinaryFormat/Dwarf.def b/llvm/include/llvm/BinaryFormat/Dwarf.def index d55947fc5103ac..9336f2a454ae47 100644 --- a/llvm/include/llvm/BinaryFormat/Dwarf.def +++ b/llvm/include/llvm/BinaryFormat/Dwarf.def @@ -1238,6 +1238,7 @@ HANDLE_DW_CFA(0x16, val_expression) // Vendor extensions: HANDLE_DW_CFA_PRED(0x1d, MIPS_advance_loc8, SELECT_MIPS64) HANDLE_DW_CFA_PRED(0x2d, GNU_window_save, SELECT_SPARC) +HANDLE_DW_CFA_PRED(0x2c, AARCH64_negate_ra_state_with_pc, SELECT_AARCH64) HANDLE_DW_CFA_PRED(0x2d, AARCH64_negate_ra_state, SELECT_AARCH64) HANDLE_DW_CFA_PRED(0x2e, GNU_args_size, SELECT_X86) // Heterogeneous Debugging Extension defined at diff --git a/llvm/include/llvm/MC/MCDwarf.h b/llvm/include/llvm/MC/MCDwarf.h index bea79545d1ab96..2ceea906ea57a7 100644 --- a/llvm/include/llvm/MC/MCDwarf.h +++ b/llvm/include/llvm/MC/MCDwarf.h @@ -515,6 +515,7 @@ class MCCFIInstruction { OpRegister, OpWindowSave, OpNegateRAState, + OpNegateRAStateWithPC, OpGnuArgsSize, OpLabel, }; @@ -642,6 +643,13 @@ class MCCFIInstruction { return MCCFIInstruction(OpNegateRAState, L, 0, INT64_C(0), Loc); } + /// .cfi_negate_ra_state_with_pc AArch64 negate RA state with PC. + static MCCFIInstruction createNegateRAStateWithPC(MCSymbol *L, + SMLoc Loc = {}) { + return MCCFIInstruction(OpNegateRAStateWithPC, L, 0, INT64_C(0), Loc); + } + + /// .cfi_restore says that the rule for Register is now the same as it /// was at the beginning of the function, after all initial instructions added /// by .cfi_startproc were executed. diff --git a/llvm/include/llvm/MC/MCStreamer.h b/llvm/include/llvm/MC/MCStreamer.h index 707aecc5dc578e..a376ba810ba515 100644 --- a/llvm/include/llvm/MC/MCStreamer.h +++ b/llvm/include/llvm/MC/MCStreamer.h @@ -1022,6 +1022,7 @@ class MCStreamer { SMLoc Loc = {}); virtual void emitCFIWindowSave(SMLoc Loc = {}); virtual void emitCFINegateRAState(SMLoc Loc = {}); + virtual void emitCFINegateRAStateWithPC(SMLoc Loc = {}); virtual void emitCFILabelDirective(SMLoc Loc, StringRef Name); virtual void emitWinCFIStartProc(const MCSymbol *Symbol, SMLoc Loc = SMLoc()); diff --git a/llvm/lib/CodeGen/AsmPrinter/AsmPrinterDwarf.cpp b/llvm/lib/CodeGen/AsmPrinter/AsmPrinterDwarf.cpp index 21d0d070c247f4..daad82d26da652 100644 --- a/llvm/lib/CodeGen/AsmPrinter/AsmPrinterDwarf.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/AsmPrinterDwarf.cpp @@ -236,6 +236,9 @@ void AsmPrinter::emitCFIInstruction(const MCCFIInstruction &Inst) const { case MCCFIInstruction::OpNegateRAState: OutStreamer->emitCFINegateRAState(Loc); break; + case MCCFIInstruction::OpNegateRAStateWithPC: + OutStreamer->emitCFINegateRAStateWithPC(Loc); + break; case MCCFIInstruction::OpSameValue: OutStreamer->emitCFISameValue(Inst.getRegister(), Loc); break; diff --git a/llvm/lib/CodeGen/CFIInstrInserter.cpp b/llvm/lib/CodeGen/CFIInstrInserter.cpp index f5bedc7b8ecdfc..4217ec6a1cca8a 100644 --- a/llvm/lib/CodeGen/CFIInstrInserter.cpp +++ b/llvm/lib/CodeGen/CFIInstrInserter.cpp @@ -260,6 +260,7 @@ void CFIInstrInserter::calculateOutgoingCFAInfo(MBBCFAInfo &MBBInfo) { case MCCFIInstruction::OpEscape: case MCCFIInstruction::OpWindowSave: case MCCFIInstruction::OpNegateRAState: + case MCCFIInstruction::OpNegateRAStateWithPC: case MCCFIInstruction::OpGnuArgsSize: case MCCFIInstruction::OpLabel: break; diff --git a/llvm/lib/CodeGen/MIRParser/MILexer.cpp b/llvm/lib/CodeGen/MIRParser/MILexer.cpp index 0809f88fde56b1..5a3806ce57335a 100644 --- a/llvm/lib/CodeGen/MIRParser/MILexer.cpp +++ b/llvm/lib/CodeGen/MIRParser/MILexer.cpp @@ -238,6 +238,8 @@ static MIToken::TokenKind getIdentifierKind(StringRef Identifier) { .Case("window_save", MIToken::kw_cfi_window_save) .Case("negate_ra_sign_state", MIToken::kw_cfi_aarch64_negate_ra_sign_state) + .Case("negate_ra_sign_state_with_pc", + MIToken::kw_cfi_aarch64_negate_ra_sign_state_with_pc) .Case("blockaddress", MIToken::kw_blockaddress) .Case("intrinsic", MIToken::kw_intrinsic) .Case("target-index", MIToken::kw_target_index) diff --git a/llvm/lib/CodeGen/MIRParser/MILexer.h b/llvm/lib/CodeGen/MIRParser/MILexer.h index 22547483a8a86b..3931da3eaae1d3 100644 --- a/llvm/lib/CodeGen/MIRParser/MILexer.h +++ b/llvm/lib/CodeGen/MIRParser/MILexer.h @@ -96,6 +96,7 @@ struct MIToken { kw_cfi_undefined, kw_cfi_window_save, kw_cfi_aarch64_negate_ra_sign_state, + kw_cfi_aarch64_negate_ra_sign_state_with_pc, kw_blockaddress, kw_intrinsic, kw_target_index, diff --git a/llvm/lib/CodeGen/MIRParser/MIParser.cpp b/llvm/lib/CodeGen/MIRParser/MIParser.cpp index 74f38e886a6b97..a00cf0b906d5a0 100644 --- a/llvm/lib/CodeGen/MIRParser/MIParser.cpp +++ b/llvm/lib/CodeGen/MIRParser/MIParser.cpp @@ -2565,6 +2565,10 @@ bool MIParser::parseCFIOperand(MachineOperand &Dest) { case MIToken::kw_cfi_aarch64_negate_ra_sign_state: CFIIndex = MF.addFrameInst(MCCFIInstruction::createNegateRAState(nullptr)); break; + case MIToken::kw_cfi_aarch64_negate_ra_sign_state_with_pc: + CFIIndex = + MF.addFrameInst(MCCFIInstruction::createNegateRAStateWithPC(nullptr)); + break; case MIToken::kw_cfi_escape: { std::string Values; if (parseCFIEscapeValues(Values)) @@ -2920,6 +2924,7 @@ bool MIParser::parseMachineOperand(const unsigned OpCode, const unsigned OpIdx, case MIToken::kw_cfi_undefined: case MIToken::kw_cfi_window_save: case MIToken::kw_cfi_aarch64_negate_ra_sign_state: + case MIToken::kw_cfi_aarch64_negate_ra_sign_state_with_pc: return parseCFIOperand(Dest); case MIToken::kw_blockaddress: return parseBlockAddressOperand(Dest); diff --git a/llvm/lib/CodeGen/MachineOperand.cpp b/llvm/lib/CodeGen/MachineOperand.cpp index 89d32c3f005e00..cd94213da79893 100644 --- a/llvm/lib/CodeGen/MachineOperand.cpp +++ b/llvm/lib/CodeGen/MachineOperand.cpp @@ -768,6 +768,10 @@ static void printCFI(raw_ostream &OS, const MCCFIInstruction &CFI, if (MCSymbol *Label = CFI.getLabel()) MachineOperand::printSymbol(OS, *Label); break; + case MCCFIInstruction::OpNegateRAStateWithPC: + OS << "negate_ra_sign_state_with_pc "; + if (MCSymbol *Label = CFI.getLabel()) + MachineOperand::printSymbol(OS, *Label); default: // TODO: Print the other CFI Operations. OS << "<unserializable cfi directive>"; diff --git a/llvm/lib/DebugInfo/DWARF/DWARFDebugFrame.cpp b/llvm/lib/DebugInfo/DWARF/DWARFDebugFrame.cpp index aff26824dda104..38e264f233e39b 100644 --- a/llvm/lib/DebugInfo/DWARF/DWARFDebugFrame.cpp +++ b/llvm/lib/DebugInfo/DWARF/DWARFDebugFrame.cpp @@ -288,6 +288,7 @@ Error CFIProgram::parse(DWARFDataExtractor Data, uint64_t *Offset, case DW_CFA_remember_state: case DW_CFA_restore_state: case DW_CFA_GNU_window_save: + case DW_CFA_AARCH64_negate_ra_state_with_pc: // No operands addInstruction(Opcode); break; @@ -666,6 +667,28 @@ Error UnwindTable::parseRows(const CFIProgram &CFIP, UnwindRow &Row, } break; + case dwarf::DW_CFA_AARCH64_negate_ra_state_with_pc: { + constexpr uint32_t AArch64DWARFPAuthRaState = 34; + auto LRLoc = Row.getRegisterLocations().getRegisterLocation( + AArch64DWARFPAuthRaState); + if (LRLoc) { + if (LRLoc->getLocation() == UnwindLocation::Constant) { + // Toggle the constant value of bits[1:0] from 0 to 1 or 1 to 0. + LRLoc->setConstant(LRLoc->getConstant() ^ 0x3); + } else { + return createStringError( + errc::invalid_argument, + "%s encountered when existing rule for this register is not " + "a constant", + CFIP.callFrameString(Inst.Opcode).str().c_str()); + } + } else { + Row.getRegisterLocations().setRegisterLocation( + AArch64DWARFPAuthRaState, UnwindLocation::createIsConstant(0x3)); + } + break; + } + case dwarf::DW_CFA_undefined: { llvm::Expected<uint64_t> RegNum = Inst.getOperandAsUnsigned(CFIP, 0); if (!RegNum) @@ -847,6 +870,7 @@ CFIProgram::getOperandTypes() { DECLARE_OP0(DW_CFA_remember_state); DECLARE_OP0(DW_CFA_restore_state); DECLARE_OP0(DW_CFA_GNU_window_save); + DECLARE_OP0(DW_CFA_AARCH64_negate_ra_state_with_pc); DECLARE_OP1(DW_CFA_GNU_args_size, OT_Offset); DECLARE_OP0(DW_CFA_nop); diff --git a/llvm/lib/MC/MCAsmStreamer.cpp b/llvm/lib/MC/MCAsmStreamer.cpp index 31b519a3e5c56a..b9ad0b4eac9c7b 100644 --- a/llvm/lib/MC/MCAsmStreamer.cpp +++ b/llvm/lib/MC/MCAsmStreamer.cpp @@ -373,6 +373,7 @@ class MCAsmStreamer final : public MCStreamer { SMLoc Loc) override; void emitCFIWindowSave(SMLoc Loc) override; void emitCFINegateRAState(SMLoc Loc) override; + void emitCFINegateRAStateWithPC(SMLoc Loc) override; void emitCFIReturnColumn(int64_t Register) override; void emitCFILabelDirective(SMLoc Loc, StringRef Name) override; @@ -2145,6 +2146,12 @@ void MCAsmStreamer::emitCFINegateRAState(SMLoc Loc) { EmitEOL(); } +void MCAsmStreamer::emitCFINegateRAStateWithPC(SMLoc Loc) { + MCStreamer::emitCFINegateRAStateWithPC(Loc); + OS << "\t.cfi_negate_ra_state_with_pc"; + EmitEOL(); +} + void MCAsmStreamer::emitCFIReturnColumn(int64_t Register) { MCStreamer::emitCFIReturnColumn(Register); OS << "\t.cfi_return_column "; diff --git a/llvm/lib/MC/MCDwarf.cpp b/llvm/lib/MC/MCDwarf.cpp index 8ff097f29aebd1..e058358fb8ad4b 100644 --- a/llvm/lib/MC/MCDwarf.cpp +++ b/llvm/lib/MC/MCDwarf.cpp @@ -1381,6 +1381,10 @@ void FrameEmitterImpl::emitCFIInstruction(const MCCFIInstruction &Instr) { Streamer.emitInt8(dwarf::DW_CFA_AARCH64_negate_ra_state); return; + case MCCFIInstruction::OpNegateRAStateWithPC: + Streamer.emitInt8(dwarf::DW_CFA_AARCH64_negate_ra_state_with_pc); + return; + case MCCFIInstruction::OpUndefined: { unsigned Reg = Instr.getRegister(); Streamer.emitInt8(dwarf::DW_CFA_undefined); diff --git a/llvm/lib/MC/MCStreamer.cpp b/llvm/lib/MC/MCStreamer.cpp index 13b162768578c5..5474db1315f141 100644 --- a/llvm/lib/MC/MCStreamer.cpp +++ b/llvm/lib/MC/MCStreamer.cpp @@ -688,6 +688,16 @@ void MCStreamer::emitCFINegateRAState(SMLoc Loc) { CurFrame->Instructions.push_back(Instruction); } +void MCStreamer::emitCFINegateRAStateWithPC(SMLoc Loc) { + MCSymbol *Label = emitCFILabel(); + MCCFIInstruction Instruction = + MCCFIInstruction::createNegateRAStateWithPC(Label, Loc); + MCDwarfFrameInfo *CurFrame = getCurrentDwarfFrameInfo(); + if (!CurFrame) + return; + CurFrame->Instructions.push_back(Instruction); +} + void MCStreamer::emitCFIReturnColumn(int64_t Register) { MCDwarfFrameInfo *CurFrame = getCurrentDwarfFrameInfo(); if (!CurFrame) diff --git a/llvm/lib/Target/AArch64/AArch64FrameLowering.cpp b/llvm/lib/Target/AArch64/AArch64FrameLowering.cpp index be33331be4e8ff..98293bc7ac30e2 100644 --- a/llvm/lib/Target/AArch64/AArch64FrameLowering.cpp +++ b/llvm/lib/Target/AArch64/AArch64FrameLowering.cpp @@ -702,7 +702,10 @@ void AArch64FrameLowering::resetCFIToInitialState( // Flip the RA sign state. if (MFI.shouldSignReturnAddress(MF)) { - CFIIndex = MF.addFrameInst(MCCFIInstruction::createNegateRAState(nullptr)); + auto CFIInst = MFI.branchProtectionPAuthLR() + ? MCCFIInstruction::createNegateRAStateWithPC(nullptr) + : MCCFIInstruction::createNegateRAState(nullptr); + CFIIndex = MF.addFrameInst(CFIInst); BuildMI(MBB, InsertPt, DL, CFIDesc).addCFIIndex(CFIIndex); } diff --git a/llvm/lib/Target/AArch64/AArch64PointerAuth.cpp b/llvm/lib/Target/AArch64/AArch64PointerAuth.cpp index 92ab4b5c3d251f..c3ad488fb8e4d1 100644 --- a/llvm/lib/Target/AArch64/AArch64PointerAuth.cpp +++ b/llvm/lib/Target/AArch64/AArch64PointerAuth.cpp @@ -71,6 +71,18 @@ FunctionPass *llvm::createAArch64PointerAuthPass() { char AArch64PointerAuth::ID = 0; +static void emitPACSymOffsetIntoX16(const TargetInstrInfo &TII, + MachineBasicBlock &MBB, + MachineBasicBlock::iterator I, DebugLoc DL, + MCSymbol *PACSym) { + BuildMI(MBB, I, DL, TII.get(AArch64::ADRP), AArch64::X16) + .addSym(PACSym, AArch64II::MO_PAGE); + BuildMI(MBB, I, DL, TII.get(AArch64::ADDXri), AArch64::X16) + .addReg(AArch64::X16) + .addSym(PACSym, AArch64II::MO_PAGEOFF | AArch64II::MO_NC) + .addImm(0); +} + // Where PAuthLR support is not known at compile time, it is supported using // PACM. PACM is in the hint space so has no effect when PAuthLR is not // supported by the hardware, but will alter the behaviour of PACI*SP, AUTI*SP @@ -81,12 +93,10 @@ static void BuildPACM(const AArch64Subtarget &Subtarget, MachineBasicBlock &MBB, const TargetInstrInfo *TII = Subtarget.getInstrInfo(); auto &MFnI = *MBB.getParent()->getInfo<AArch64FunctionInfo>(); - // ADR X16,<address_of_PACIASP> + // Offset to PAC*SP using ADRP + ADD. if (PACSym) { assert(Flags == MachineInstr::FrameDestroy); - BuildMI(MBB, MBBI, DL, TII->get(AArch64::ADR)) - .addReg(AArch64::X16, RegState::Define) - .addSym(PACSym); + emitPACSymOffsetIntoX16(*TII, MBB, MBBI, DL, PACSym); } // Only emit PACM if -mbranch-protection has +pc and the target does not @@ -95,12 +105,31 @@ static void BuildPACM(const AArch64Subtarget &Subtarget, MachineBasicBlock &MBB, BuildMI(MBB, MBBI, DL, TII->get(AArch64::PACM)).setMIFlag(Flags); } +static void emitPACCFI(const AArch64Subtarget &Subtarget, + MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, + ... [truncated] `````````` </details> https://github.com/llvm/llvm-project/pull/112171 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits