From 924defada9bc0e3c89b0c0e288d7cb4dd654e7d4 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Martin=20Storsj=C3=B6?= Date: Wed, 18 May 2022 12:36:59 +0300 Subject: [PATCH] [MC] [Win64EH] Don't produce packed ARM64 unwind info with homed parameters There's an inconsistency regarding the epilogs of packed ARM64 unwind info with homed parameters; according to the documentation (and according to common sense), the epilog wouldn't have a series of nop instructions matching the stp x0-x7 in the prolog - however in practice, RtlVirtualUnwind still seems to behave as if the epilog does have the mirrored nops from the prolog. In practice, MSVC doesn't seem to produce packed unwind info with homed parameters, which might be why this inconsistency hasn't been noticed. Thus, to play it safe, avoid creating such packed unwind info with homed parameters. (LLVM's current behaviour matches the current runtime behaviour of RtlVirtualUnwind, but if it later is bug fixed to match the documentation, such unwind information would be incorrect.) See https://github.com/llvm/llvm-project/issues/54879 for further discussion on the matter. Differential Revision: https://reviews.llvm.org/D125876 --- llvm/lib/MC/MCWin64EH.cpp | 10 ++++++++++ llvm/test/MC/AArch64/seh-packed-unwind.s | 27 ++++++--------------------- 2 files changed, 16 insertions(+), 21 deletions(-) diff --git a/llvm/lib/MC/MCWin64EH.cpp b/llvm/lib/MC/MCWin64EH.cpp index bb33b31..bc73685 100644 --- a/llvm/lib/MC/MCWin64EH.cpp +++ b/llvm/lib/MC/MCWin64EH.cpp @@ -860,6 +860,16 @@ static bool tryPackedUnwind(WinEH::FrameInfo *info, uint32_t FuncLength, if (Nops != 0 && Nops != 4) return false; int H = Nops == 4; + // There's an inconsistency regarding packed unwind info with homed + // parameters; according to the documentation, the epilog shouldn't have + // the same corresponding nops (and thus, to set the H bit, we should + // require an epilog which isn't exactly symmetrical - we shouldn't accept + // an exact mirrored epilog for those cases), but in practice, + // RtlVirtualUnwind behaves as if it does expect the epilogue to contain + // the same nops. See https://github.com/llvm/llvm-project/issues/54879. + // To play it safe, don't produce packed unwind info with homed parameters. + if (H) + return false; int IntSZ = 8 * RegI; if (StandaloneLR) IntSZ += 8; diff --git a/llvm/test/MC/AArch64/seh-packed-unwind.s b/llvm/test/MC/AArch64/seh-packed-unwind.s index 4a56fb5..a27792c 100644 --- a/llvm/test/MC/AArch64/seh-packed-unwind.s +++ b/llvm/test/MC/AArch64/seh-packed-unwind.s @@ -81,25 +81,10 @@ // CHECK-NEXT: ] // CHECK-NEXT: } // CHECK-NEXT: RuntimeFunction { -// CHECK-NEXT: Function: func5 -// CHECK-NEXT: Fragment: No -// CHECK-NEXT: FunctionLength: 56 -// CHECK-NEXT: RegF: 0 -// CHECK-NEXT: RegI: 1 -// CHECK-NEXT: HomedParameters: Yes -// CHECK-NEXT: CR: 0 -// CHECK-NEXT: FrameSize: 112 -// CHECK-NEXT: Prologue [ -// CHECK-NEXT: sub sp, sp, #32 -// CHECK-NEXT: stp x6, x7, [sp, #64] -// CHECK-NEXT: stp x4, x5, [sp, #48] -// CHECK-NEXT: stp x2, x3, [sp, #32] -// CHECK-NEXT: stp x0, x1, [sp, #16] -// CHECK-NEXT: str x19, [sp, #-80]! -// CHECK-NEXT: end -// CHECK-NEXT: ] -// CHECK-NEXT: } -// CHECK-NEXT: RuntimeFunction { +// CHECK-NEXT: Function: notpacked_func5 +// CHECK-NEXT: ExceptionRecord: +// CHECK-NEXT: ExceptionData { +// CHECK: RuntimeFunction { // CHECK-NEXT: Function: func6 // CHECK-NEXT: Fragment: No // CHECK-NEXT: FunctionLength: 24 @@ -441,8 +426,8 @@ func4: ret .seh_endproc -func5: - .seh_proc func5 +notpacked_func5: + .seh_proc notpacked_func5 str x19, [sp, #-80]! .seh_save_reg_x x19, 80 stp x0, x1, [sp, #16] -- 2.7.4