diff --git a/llvm/include/llvm/Support/Win64EH.h b/llvm/include/llvm/Support/Win64EH.h --- a/llvm/include/llvm/Support/Win64EH.h +++ b/llvm/include/llvm/Support/Win64EH.h @@ -61,6 +61,7 @@ UOP_TrapFrame, UOP_Context, UOP_ClearUnwoundToCall, + UOP_PACSignReturnAddress, // The following set of unwind opcodes is for ARM. They are documented at // https://docs.microsoft.com/en-us/cpp/build/arm-exception-handling diff --git a/llvm/lib/MC/MCWin64EH.cpp b/llvm/lib/MC/MCWin64EH.cpp --- a/llvm/lib/MC/MCWin64EH.cpp +++ b/llvm/lib/MC/MCWin64EH.cpp @@ -377,6 +377,9 @@ case Win64EH::UOP_ClearUnwoundToCall: Count += 1; break; + case Win64EH::UOP_PACSignReturnAddress: + Count += 1; + break; } } return Count; @@ -543,6 +546,10 @@ b = 0xEC; streamer.emitInt8(b); break; + case Win64EH::UOP_PACSignReturnAddress: + b = 0xFC; + streamer.emitInt8(b); + break; } } diff --git a/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp b/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp --- a/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp +++ b/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp @@ -218,6 +218,7 @@ bool parseDirectiveSEHMachineFrame(SMLoc L); bool parseDirectiveSEHContext(SMLoc L); bool parseDirectiveSEHClearUnwoundToCall(SMLoc L); + bool parseDirectiveSEHPACSignReturnAddress(SMLoc L); bool validateInstruction(MCInst &Inst, SMLoc &IDLoc, SmallVectorImpl &Loc); @@ -6099,6 +6100,8 @@ parseDirectiveSEHContext(Loc); else if (IDVal == ".seh_clear_unwound_to_call") parseDirectiveSEHClearUnwoundToCall(Loc); + else if (IDVal == ".seh_pac_sign_return_address") + parseDirectiveSEHPACSignReturnAddress(Loc); else return true; } else @@ -6775,6 +6778,13 @@ return false; } +/// parseDirectiveSEHPACSignReturnAddress +/// ::= .seh_pac_sign_return_address +bool AArch64AsmParser::parseDirectiveSEHPACSignReturnAddress(SMLoc L) { + getTargetStreamer().emitARM64WinCFIPACSignReturnAddress(); + return false; +} + bool AArch64AsmParser::classifySymbolRef(const MCExpr *Expr, AArch64MCExpr::VariantKind &ELFRefKind, diff --git a/llvm/lib/Target/AArch64/MCTargetDesc/AArch64ELFStreamer.cpp b/llvm/lib/Target/AArch64/MCTargetDesc/AArch64ELFStreamer.cpp --- a/llvm/lib/Target/AArch64/MCTargetDesc/AArch64ELFStreamer.cpp +++ b/llvm/lib/Target/AArch64/MCTargetDesc/AArch64ELFStreamer.cpp @@ -107,6 +107,9 @@ void emitARM64WinCFIClearUnwoundToCall() override { OS << "\t.seh_clear_unwound_to_call\n"; } + void emitARM64WinCFIPACSignReturnAddress() override { + OS << "\t.seh_pac_sign_return_address\n"; + } public: AArch64TargetAsmStreamer(MCStreamer &S, formatted_raw_ostream &OS); diff --git a/llvm/lib/Target/AArch64/MCTargetDesc/AArch64TargetStreamer.h b/llvm/lib/Target/AArch64/MCTargetDesc/AArch64TargetStreamer.h --- a/llvm/lib/Target/AArch64/MCTargetDesc/AArch64TargetStreamer.h +++ b/llvm/lib/Target/AArch64/MCTargetDesc/AArch64TargetStreamer.h @@ -67,6 +67,7 @@ virtual void emitARM64WinCFIMachineFrame() {} virtual void emitARM64WinCFIContext() {} virtual void emitARM64WinCFIClearUnwoundToCall() {} + virtual void emitARM64WinCFIPACSignReturnAddress() {} private: std::unique_ptr ConstantPools; @@ -120,6 +121,7 @@ void emitARM64WinCFIMachineFrame() override; void emitARM64WinCFIContext() override; void emitARM64WinCFIClearUnwoundToCall() override; + void emitARM64WinCFIPACSignReturnAddress() override; private: void emitARM64WinUnwindCode(unsigned UnwindCode, int Reg, int Offset); diff --git a/llvm/lib/Target/AArch64/MCTargetDesc/AArch64WinCOFFStreamer.cpp b/llvm/lib/Target/AArch64/MCTargetDesc/AArch64WinCOFFStreamer.cpp --- a/llvm/lib/Target/AArch64/MCTargetDesc/AArch64WinCOFFStreamer.cpp +++ b/llvm/lib/Target/AArch64/MCTargetDesc/AArch64WinCOFFStreamer.cpp @@ -221,6 +221,10 @@ emitARM64WinUnwindCode(Win64EH::UOP_ClearUnwoundToCall, -1, 0); } +void AArch64TargetWinCOFFStreamer::emitARM64WinCFIPACSignReturnAddress() { + emitARM64WinUnwindCode(Win64EH::UOP_PACSignReturnAddress, -1, 0); +} + MCWinCOFFStreamer *llvm::createAArch64WinCOFFStreamer( MCContext &Context, std::unique_ptr MAB, std::unique_ptr OW, std::unique_ptr Emitter, diff --git a/llvm/test/MC/AArch64/seh.s b/llvm/test/MC/AArch64/seh.s --- a/llvm/test/MC/AArch64/seh.s +++ b/llvm/test/MC/AArch64/seh.s @@ -20,7 +20,7 @@ // CHECK-NEXT: } // CHECK: Section { // CHECK: Name: .xdata -// CHECK: RawDataSize: 52 +// CHECK: RawDataSize: 56 // CHECK: RelocationCount: 1 // CHECK: Characteristics [ // CHECK-NEXT: ALIGN_4BYTES @@ -41,7 +41,7 @@ // CHECK-NEXT: Relocations [ // CHECK-NEXT: Section (4) .xdata { -// CHECK-NEXT: 0x28 IMAGE_REL_ARM64_ADDR32NB __C_specific_handler +// CHECK-NEXT: 0x2C IMAGE_REL_ARM64_ADDR32NB __C_specific_handler // CHECK-NEXT: } // CHECK-NEXT: Section (5) .pdata { // CHECK-NEXT: 0x0 IMAGE_REL_ARM64_ADDR32NB .text @@ -54,8 +54,9 @@ // CHECK-NEXT: Function: func // CHECK-NEXT: ExceptionRecord: .xdata // CHECK-NEXT: ExceptionData { -// CHECK-NEXT: FunctionLength: 100 +// CHECK-NEXT: FunctionLength: 104 // CHECK: Prologue [ +// CHECK-NEXT: 0xfc ; pacibsp // CHECK-NEXT: 0xec ; clear unwound to call // CHECK-NEXT: 0xea ; context // CHECK-NEXT: 0xe9 ; machine frame @@ -80,9 +81,15 @@ // CHECK-NEXT: 0x01 ; sub sp, #16 // CHECK-NEXT: 0xe4 ; end // CHECK-NEXT: ] -// CHECK-NEXT: Epilogue [ -// CHECK-NEXT: 0x01 ; add sp, #16 -// CHECK-NEXT: 0xe4 ; end +// CHECK-NEXT: EpilogueScopes [ +// CHECK-NEXT: EpilogueScope { +// CHECK-NEXT: StartOffset: 24 +// CHECK-NEXT: EpilogueStartIndex: 32 +// CHECK-NEXT: Opcodes [ +// CHECK-NEXT: 0x01 ; add sp, #16 +// CHECK-NEXT: 0xe4 ; end +// CHECK-NEXT: ] +// CHECK-NEXT: } // CHECK-NEXT: ] // CHECK-NEXT: ExceptionHandler [ // CHECK-NEXT: Routine: __C_specific_handler (0x0) @@ -145,8 +152,10 @@ .seh_context nop .seh_clear_unwound_to_call - .seh_endprologue nop + .seh_pac_sign_return_address + .seh_endprologue + pacibsp .seh_startepilogue add sp, sp, #24 .seh_stackalloc 24