diff --git a/llvm/test/tools/llvm-readobj/COFF/arm64-packed-unwind-pac.s b/llvm/test/tools/llvm-readobj/COFF/arm64-packed-unwind-pac.s new file mode 100644 --- /dev/null +++ b/llvm/test/tools/llvm-readobj/COFF/arm64-packed-unwind-pac.s @@ -0,0 +1,31 @@ +// REQUIRES: aarch64-registered-target +// RUN: llvm-mc -filetype=obj -triple aarch64-windows %s -o %t.o +// RUN: llvm-readobj --unwind %t.o | FileCheck %s + +// CHECK: UnwindInformation [ +// CHECK-NEXT: RuntimeFunction { +// CHECK-NEXT: Function: func +// CHECK-NEXT: Fragment: No +// CHECK-NEXT: FunctionLength: 44 +// CHECK-NEXT: RegF: 0 +// CHECK-NEXT: RegI: 0 +// CHECK-NEXT: HomedParameters: No +// CHECK-NEXT: CR: 2 +// CHECK-NEXT: FrameSize: 32 +// CHECK-NEXT: Prologue [ +// CHECK-NEXT: mov x29, sp +// CHECK-NEXT: stp x29, lr, [sp, #-32]! +// CHECK-NEXT: pacibsp +// CHECK-NEXT: end +// CHECK-NEXT: ] +// CHECK-NEXT: } +// CHECK-NEXT: ] + + .text + .globl func +func: + ret + + .section .pdata,"dr" + .long func@IMGREL + .long 0x0140002d // FunctionLength=11 RegF=0 RegI=0 H=0 CR=2 FrameSize=2 diff --git a/llvm/test/tools/llvm-readobj/COFF/arm64-unwind-pac.s b/llvm/test/tools/llvm-readobj/COFF/arm64-unwind-pac.s new file mode 100644 --- /dev/null +++ b/llvm/test/tools/llvm-readobj/COFF/arm64-unwind-pac.s @@ -0,0 +1,39 @@ +// REQUIRES: aarch64-registered-target +// RUN: llvm-mc -filetype=obj -triple aarch64-windows %s -o %t.o +// RUN: llvm-readobj --unwind %t.o | FileCheck --strict-whitespace %s + +// CHECK: Prologue [ +// CHECK-NEXT: 0xd600 ; stp x19, lr, [sp, #0] +// CHECK-NEXT: 0x01 ; sub sp, #16 +// CHECK-NEXT: 0xfc ; pacibsp +// CHECK-NEXT: 0xe4 ; end +// CHECK-NEXT: ] +// CHECK-NEXT: Epilogue [ +// CHECK-NEXT: 0x01 ; add sp, #16 +// CHECK-NEXT: 0xfc ; autibsp +// CHECK-NEXT: 0xe4 ; end +// CHECK-NEXT: ] + +.section .pdata,"dr" + .long func@IMGREL + .long "$unwind$func"@IMGREL + + .text + .globl func +func: + pacibsp + sub sp, sp, #16 + stp x19, x30, [sp] + mov w19, w1 + blr x0 + mov w0, w19 + ldp x19, x30, [sp] + add sp, sp, #16 + autibsp + ret + +.section .xdata,"dr" +"$unwind$func": +.byte 0x0a, 0x00, 0xa0, 0x10 +.byte 0xd6, 0x00, 0x01, 0xfc +.byte 0xe4, 0xe3, 0xe3, 0xe3 diff --git a/llvm/tools/llvm-readobj/ARMWinEHPrinter.h b/llvm/tools/llvm-readobj/ARMWinEHPrinter.h --- a/llvm/tools/llvm-readobj/ARMWinEHPrinter.h +++ b/llvm/tools/llvm-readobj/ARMWinEHPrinter.h @@ -131,6 +131,8 @@ bool Prologue); bool opcode_clear_unwound_to_call(const uint8_t *Opcodes, unsigned &Offset, unsigned Length, bool Prologue); + bool opcode_pac_sign_return_address(const uint8_t *Opcodes, unsigned &Offset, + unsigned Length, bool Prologue); void decodeOpcodes(ArrayRef Opcodes, unsigned Offset, bool Prologue); diff --git a/llvm/tools/llvm-readobj/ARMWinEHPrinter.cpp b/llvm/tools/llvm-readobj/ARMWinEHPrinter.cpp --- a/llvm/tools/llvm-readobj/ARMWinEHPrinter.cpp +++ b/llvm/tools/llvm-readobj/ARMWinEHPrinter.cpp @@ -172,6 +172,7 @@ {0xff, 0xe9, 1, &Decoder::opcode_machine_frame}, {0xff, 0xea, 1, &Decoder::opcode_context}, {0xff, 0xec, 1, &Decoder::opcode_clear_unwound_to_call}, + {0xff, 0xfc, 1, &Decoder::opcode_pac_sign_return_address}, }; static void printRange(raw_ostream &OS, ListSeparator &LS, unsigned First, @@ -976,6 +977,17 @@ return false; } +bool Decoder::opcode_pac_sign_return_address(const uint8_t *OC, + unsigned &Offset, unsigned Length, + bool Prologue) { + if (Prologue) + SW.startLine() << format("0x%02x ; pacibsp\n", OC[Offset]); + else + SW.startLine() << format("0x%02x ; autibsp\n", OC[Offset]); + ++Offset; + return false; +} + void Decoder::decodeOpcodes(ArrayRef Opcodes, unsigned Offset, bool Prologue) { assert((!Prologue || Offset == 0) && "prologue should always use offset 0"); @@ -1333,7 +1345,7 @@ int SavSZ = (IntSZ + FpSZ + 8 * 8 * RF.H() + 0xf) & ~0xf; int LocSZ = (RF.FrameSize() << 4) - SavSZ; - if (RF.CR() == 3) { + if (RF.CR() == 2 || RF.CR() == 3) { SW.startLine() << "mov x29, sp\n"; if (LocSZ <= 512) { SW.startLine() << format("stp x29, lr, [sp, #-%d]!\n", LocSZ); @@ -1344,7 +1356,7 @@ if (LocSZ > 4080) { SW.startLine() << format("sub sp, sp, #%d\n", LocSZ - 4080); SW.startLine() << "sub sp, sp, #4080\n"; - } else if ((RF.CR() != 3 && LocSZ > 0) || LocSZ > 512) { + } else if ((RF.CR() != 3 && RF.CR() != 2 && LocSZ > 0) || LocSZ > 512) { SW.startLine() << format("sub sp, sp, #%d\n", LocSZ); } if (RF.H()) { @@ -1406,6 +1418,11 @@ 19 + 2 * I + 1, 16 * I); } } + // CR=2 is yet undocumented, see + // https://github.com/MicrosoftDocs/cpp-docs/pull/4202 for upstream + // progress on getting it documented. + if (RF.CR() == 2) + SW.startLine() << "pacibsp\n"; SW.startLine() << "end\n"; return true;