mstorsjo created this revision. mstorsjo added reviewers: labath, jasonmolenda. Herald added a subscriber: jsji. Herald added a project: All. mstorsjo requested review of this revision. Herald added a project: LLDB.
This fixes https://github.com/llvm/llvm-project/issues/56095. @labath, FWIW while making the testcase, I realized why most tests on Windows need the %build script instead of plain %clang_host. For this testcase, I do need to have at least symbols available (full debug info isn't needed). On unix-like systems, a command like "clang source.c -o exec" will produce an executable with symbols. With MSVC and clang in MSVC mode, the default linking command won't produce any debug info at all, no symbols, nothing. We can fix it by passing "-fuse-ld=lld -Wl,-debug:symtab", but that breaks mingw builds (where symbols are kept by default). The %build script handles all the options that are needed for creating PDB debug info with clang-cl/lld-link, and produces symbols when building in mingw mode too. Repository: rG LLVM Github Monorepo https://reviews.llvm.org/D129455 Files: lldb/source/Plugins/ABI/X86/ABIWindows_x86_64.h lldb/test/Shell/Unwind/Inputs/windows-unaligned-x86_64-asm.s lldb/test/Shell/Unwind/Inputs/windows-unaligned-x86_64.cpp lldb/test/Shell/Unwind/windows-unaligned-x86_64.test Index: lldb/test/Shell/Unwind/windows-unaligned-x86_64.test =================================================================== --- /dev/null +++ lldb/test/Shell/Unwind/windows-unaligned-x86_64.test @@ -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 Index: lldb/test/Shell/Unwind/Inputs/windows-unaligned-x86_64.cpp =================================================================== --- /dev/null +++ lldb/test/Shell/Unwind/Inputs/windows-unaligned-x86_64.cpp @@ -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; +} Index: lldb/test/Shell/Unwind/Inputs/windows-unaligned-x86_64-asm.s =================================================================== --- /dev/null +++ lldb/test/Shell/Unwind/Inputs/windows-unaligned-x86_64-asm.s @@ -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 Index: lldb/source/Plugins/ABI/X86/ABIWindows_x86_64.h =================================================================== --- lldb/source/Plugins/ABI/X86/ABIWindows_x86_64.h +++ lldb/source/Plugins/ABI/X86/ABIWindows_x86_64.h @@ -40,10 +40,15 @@ 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;
Index: lldb/test/Shell/Unwind/windows-unaligned-x86_64.test =================================================================== --- /dev/null +++ lldb/test/Shell/Unwind/windows-unaligned-x86_64.test @@ -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 Index: lldb/test/Shell/Unwind/Inputs/windows-unaligned-x86_64.cpp =================================================================== --- /dev/null +++ lldb/test/Shell/Unwind/Inputs/windows-unaligned-x86_64.cpp @@ -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; +} Index: lldb/test/Shell/Unwind/Inputs/windows-unaligned-x86_64-asm.s =================================================================== --- /dev/null +++ lldb/test/Shell/Unwind/Inputs/windows-unaligned-x86_64-asm.s @@ -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 Index: lldb/source/Plugins/ABI/X86/ABIWindows_x86_64.h =================================================================== --- lldb/source/Plugins/ABI/X86/ABIWindows_x86_64.h +++ lldb/source/Plugins/ABI/X86/ABIWindows_x86_64.h @@ -40,10 +40,15 @@ 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;
_______________________________________________ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits