Skip to content

Commit c43bff6

Browse files
committed
[AArch64] Add support for the SEH opcode for return address signing
This was documented upstream in MicrosoftDocs/cpp-docs#4202. Differential Revision: https://reviews.llvm.org/D135276
1 parent 2a66abb commit c43bff6

File tree

7 files changed

+42
-6
lines changed

7 files changed

+42
-6
lines changed

llvm/include/llvm/Support/Win64EH.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@ enum UnwindOpcodes {
6161
UOP_TrapFrame,
6262
UOP_Context,
6363
UOP_ClearUnwoundToCall,
64+
UOP_PACSignReturnAddress,
6465
// The following set of unwind opcodes is for ARM. They are documented at
6566
// https://docs.microsoft.com/en-us/cpp/build/arm-exception-handling
6667

llvm/lib/MC/MCWin64EH.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -377,6 +377,9 @@ static uint32_t ARM64CountOfUnwindCodes(ArrayRef<WinEH::Instruction> Insns) {
377377
case Win64EH::UOP_ClearUnwoundToCall:
378378
Count += 1;
379379
break;
380+
case Win64EH::UOP_PACSignReturnAddress:
381+
Count += 1;
382+
break;
380383
}
381384
}
382385
return Count;
@@ -543,6 +546,10 @@ static void ARM64EmitUnwindCode(MCStreamer &streamer,
543546
b = 0xEC;
544547
streamer.emitInt8(b);
545548
break;
549+
case Win64EH::UOP_PACSignReturnAddress:
550+
b = 0xFC;
551+
streamer.emitInt8(b);
552+
break;
546553
}
547554
}
548555

llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -218,6 +218,7 @@ class AArch64AsmParser : public MCTargetAsmParser {
218218
bool parseDirectiveSEHMachineFrame(SMLoc L);
219219
bool parseDirectiveSEHContext(SMLoc L);
220220
bool parseDirectiveSEHClearUnwoundToCall(SMLoc L);
221+
bool parseDirectiveSEHPACSignReturnAddress(SMLoc L);
221222

222223
bool validateInstruction(MCInst &Inst, SMLoc &IDLoc,
223224
SmallVectorImpl<SMLoc> &Loc);
@@ -6099,6 +6100,8 @@ bool AArch64AsmParser::ParseDirective(AsmToken DirectiveID) {
60996100
parseDirectiveSEHContext(Loc);
61006101
else if (IDVal == ".seh_clear_unwound_to_call")
61016102
parseDirectiveSEHClearUnwoundToCall(Loc);
6103+
else if (IDVal == ".seh_pac_sign_return_address")
6104+
parseDirectiveSEHPACSignReturnAddress(Loc);
61026105
else
61036106
return true;
61046107
} else
@@ -6775,6 +6778,13 @@ bool AArch64AsmParser::parseDirectiveSEHClearUnwoundToCall(SMLoc L) {
67756778
return false;
67766779
}
67776780

6781+
/// parseDirectiveSEHPACSignReturnAddress
6782+
/// ::= .seh_pac_sign_return_address
6783+
bool AArch64AsmParser::parseDirectiveSEHPACSignReturnAddress(SMLoc L) {
6784+
getTargetStreamer().emitARM64WinCFIPACSignReturnAddress();
6785+
return false;
6786+
}
6787+
67786788
bool
67796789
AArch64AsmParser::classifySymbolRef(const MCExpr *Expr,
67806790
AArch64MCExpr::VariantKind &ELFRefKind,

llvm/lib/Target/AArch64/MCTargetDesc/AArch64ELFStreamer.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,9 @@ class AArch64TargetAsmStreamer : public AArch64TargetStreamer {
107107
void emitARM64WinCFIClearUnwoundToCall() override {
108108
OS << "\t.seh_clear_unwound_to_call\n";
109109
}
110+
void emitARM64WinCFIPACSignReturnAddress() override {
111+
OS << "\t.seh_pac_sign_return_address\n";
112+
}
110113

111114
public:
112115
AArch64TargetAsmStreamer(MCStreamer &S, formatted_raw_ostream &OS);

llvm/lib/Target/AArch64/MCTargetDesc/AArch64TargetStreamer.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@ class AArch64TargetStreamer : public MCTargetStreamer {
6767
virtual void emitARM64WinCFIMachineFrame() {}
6868
virtual void emitARM64WinCFIContext() {}
6969
virtual void emitARM64WinCFIClearUnwoundToCall() {}
70+
virtual void emitARM64WinCFIPACSignReturnAddress() {}
7071

7172
private:
7273
std::unique_ptr<AssemblerConstantPools> ConstantPools;
@@ -120,6 +121,7 @@ class AArch64TargetWinCOFFStreamer : public llvm::AArch64TargetStreamer {
120121
void emitARM64WinCFIMachineFrame() override;
121122
void emitARM64WinCFIContext() override;
122123
void emitARM64WinCFIClearUnwoundToCall() override;
124+
void emitARM64WinCFIPACSignReturnAddress() override;
123125

124126
private:
125127
void emitARM64WinUnwindCode(unsigned UnwindCode, int Reg, int Offset);

llvm/lib/Target/AArch64/MCTargetDesc/AArch64WinCOFFStreamer.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -221,6 +221,10 @@ void AArch64TargetWinCOFFStreamer::emitARM64WinCFIClearUnwoundToCall() {
221221
emitARM64WinUnwindCode(Win64EH::UOP_ClearUnwoundToCall, -1, 0);
222222
}
223223

224+
void AArch64TargetWinCOFFStreamer::emitARM64WinCFIPACSignReturnAddress() {
225+
emitARM64WinUnwindCode(Win64EH::UOP_PACSignReturnAddress, -1, 0);
226+
}
227+
224228
MCWinCOFFStreamer *llvm::createAArch64WinCOFFStreamer(
225229
MCContext &Context, std::unique_ptr<MCAsmBackend> MAB,
226230
std::unique_ptr<MCObjectWriter> OW, std::unique_ptr<MCCodeEmitter> Emitter,

llvm/test/MC/AArch64/seh.s

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
// CHECK-NEXT: }
2121
// CHECK: Section {
2222
// CHECK: Name: .xdata
23-
// CHECK: RawDataSize: 52
23+
// CHECK: RawDataSize: 56
2424
// CHECK: RelocationCount: 1
2525
// CHECK: Characteristics [
2626
// CHECK-NEXT: ALIGN_4BYTES
@@ -41,7 +41,7 @@
4141

4242
// CHECK-NEXT: Relocations [
4343
// CHECK-NEXT: Section (4) .xdata {
44-
// CHECK-NEXT: 0x28 IMAGE_REL_ARM64_ADDR32NB __C_specific_handler
44+
// CHECK-NEXT: 0x2C IMAGE_REL_ARM64_ADDR32NB __C_specific_handler
4545
// CHECK-NEXT: }
4646
// CHECK-NEXT: Section (5) .pdata {
4747
// CHECK-NEXT: 0x0 IMAGE_REL_ARM64_ADDR32NB .text
@@ -54,8 +54,9 @@
5454
// CHECK-NEXT: Function: func
5555
// CHECK-NEXT: ExceptionRecord: .xdata
5656
// CHECK-NEXT: ExceptionData {
57-
// CHECK-NEXT: FunctionLength: 100
57+
// CHECK-NEXT: FunctionLength: 104
5858
// CHECK: Prologue [
59+
// CHECK-NEXT: 0xfc ; pacibsp
5960
// CHECK-NEXT: 0xec ; clear unwound to call
6061
// CHECK-NEXT: 0xea ; context
6162
// CHECK-NEXT: 0xe9 ; machine frame
@@ -80,9 +81,15 @@
8081
// CHECK-NEXT: 0x01 ; sub sp, #16
8182
// CHECK-NEXT: 0xe4 ; end
8283
// CHECK-NEXT: ]
83-
// CHECK-NEXT: Epilogue [
84-
// CHECK-NEXT: 0x01 ; add sp, #16
85-
// CHECK-NEXT: 0xe4 ; end
84+
// CHECK-NEXT: EpilogueScopes [
85+
// CHECK-NEXT: EpilogueScope {
86+
// CHECK-NEXT: StartOffset: 24
87+
// CHECK-NEXT: EpilogueStartIndex: 32
88+
// CHECK-NEXT: Opcodes [
89+
// CHECK-NEXT: 0x01 ; add sp, #16
90+
// CHECK-NEXT: 0xe4 ; end
91+
// CHECK-NEXT: ]
92+
// CHECK-NEXT: }
8693
// CHECK-NEXT: ]
8794
// CHECK-NEXT: ExceptionHandler [
8895
// CHECK-NEXT: Routine: __C_specific_handler (0x0)
@@ -145,6 +152,8 @@ func:
145152
.seh_context
146153
nop
147154
.seh_clear_unwound_to_call
155+
pacibsp
156+
.seh_pac_sign_return_address
148157
.seh_endprologue
149158
nop
150159
.seh_startepilogue

0 commit comments

Comments
 (0)