[lldb] Reduce the stack alignment requirements for the Windows x86_64 ABI

This fixes https://github.com/llvm/llvm-project/issues/56095.

Differential Revision: https://reviews.llvm.org/D129455
This commit is contained in:
Martin Storsjö 2022-07-09 00:36:16 +03:00
parent 2bd8e74b94
commit 66cdd6548a
4 changed files with 67 additions and 3 deletions

View File

@ -40,10 +40,15 @@ public:
bool RegisterIsVolatile(const lldb_private::RegisterInfo *reg_info) override;
// In Windows_x86_64 ABI, stack will always be maintained 16-byte aligned
// In Windows_x86_64 ABI requires that the stack will be maintained 16-byte
// aligned.
// When ntdll invokes callbacks such as KiUserExceptionDispatcher or
// KiUserCallbackDispatcher, those functions won't have a properly 16-byte
// aligned stack - but tolerate unwinding through them by relaxing the
// requirement to 8 bytes.
bool CallFrameAddressIsValid(lldb::addr_t cfa) override {
if (cfa & (16ull - 1ull))
return false; // Not 16 byte aligned
if (cfa & (8ull - 1ull))
return false; // Not 8 byte aligned
if (cfa == 0)
return false; // Zero is not a valid stack address
return true;

View File

@ -0,0 +1,25 @@
.globl call_func
.def call_func; .scl 2; .type 32; .endef
.seh_proc call_func
call_func:
subq $32, %rsp
.seh_stackalloc 32
.seh_endprologue
call realign_stack
addq $32, %rsp
ret
.seh_endproc
.globl realign_stack
.def realign_stack; .scl 2; .type 32; .endef
.seh_proc realign_stack
realign_stack:
subq $32, %rsp
.seh_stackalloc 32
.seh_endprologue
movq %rcx, %rax
movl %edx, %ecx
call *%rax
addq $32, %rsp
ret
.seh_endproc

View File

@ -0,0 +1,8 @@
extern "C" void call_func(void (*ptr)(int a), int a);
extern "C" void func(int arg) { }
int main(int argc, char **argv) {
call_func(func, 42);
return 0;
}

View File

@ -0,0 +1,26 @@
# Test unwinding through stack frames that aren't aligned to 16 bytes.
# (In real world code, this happens when unwinding through
# KiUserExceptionDispatcher and KiUserCallbackDispatcher in ntdll.dll.)
# REQUIRES: target-x86_64, native, system-windows
# RUN: %build %p/Inputs/windows-unaligned-x86_64.cpp %p/Inputs/windows-unaligned-x86_64-asm.s -o %t
# RUN: %lldb %t -s %s -o exit | FileCheck %s
# Future TODO: If %build could compile the source file in C mode, the symbol
# name handling would be easier across msvc and mingw build configurations.
# (In mingw mode, the extern C symbol "func" is printed as "::func" while
# it's plain "func" in msvc mode. Without the extern C, it's "func(..." in
# mingw mode, but "void __cdecl func(..." in msvc mode.)
breakpoint set -n func
# CHECK: Breakpoint 1: where = {{.*}}`{{(::)?}}func
process launch
# CHECK: stop reason = breakpoint 1.1
thread backtrace
# CHECK: frame #0: {{.*}}`{{(::)?}}func
# CHECK: frame #1: {{.*}}`realign_stack
# CHECK: frame #2: {{.*}}`call_func
# CHECK: frame #3: {{.*}}`main