[Lldb-commits] [lldb] 66cdd65 - [lldb] Reduce the stack alignment requirements for the Windows x86_64 ABI
Martin Storsjö via lldb-commits
lldb-commits at lists.llvm.org
Mon Jul 11 13:42:32 PDT 2022
Author: Martin Storsjö
Date: 2022-07-11T23:41:35+03:00
New Revision: 66cdd6548ac51f2039b9f0bc10ec03f387b210c4
URL: https://github.com/llvm/llvm-project/commit/66cdd6548ac51f2039b9f0bc10ec03f387b210c4
DIFF: https://github.com/llvm/llvm-project/commit/66cdd6548ac51f2039b9f0bc10ec03f387b210c4.diff
LOG: [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
Added:
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
Modified:
lldb/source/Plugins/ABI/X86/ABIWindows_x86_64.h
Removed:
################################################################################
diff --git a/lldb/source/Plugins/ABI/X86/ABIWindows_x86_64.h b/lldb/source/Plugins/ABI/X86/ABIWindows_x86_64.h
index e74b9126404e1..a9c2ed9c2f141 100644
--- a/lldb/source/Plugins/ABI/X86/ABIWindows_x86_64.h
+++ b/lldb/source/Plugins/ABI/X86/ABIWindows_x86_64.h
@@ -40,10 +40,15 @@ class ABIWindows_x86_64 : public ABIX86_64 {
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;
diff --git a/lldb/test/Shell/Unwind/Inputs/windows-unaligned-x86_64-asm.s b/lldb/test/Shell/Unwind/Inputs/windows-unaligned-x86_64-asm.s
new file mode 100644
index 0000000000000..c042901683648
--- /dev/null
+++ b/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
diff --git a/lldb/test/Shell/Unwind/Inputs/windows-unaligned-x86_64.cpp b/lldb/test/Shell/Unwind/Inputs/windows-unaligned-x86_64.cpp
new file mode 100644
index 0000000000000..d310ef7d7ed2f
--- /dev/null
+++ b/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;
+}
diff --git a/lldb/test/Shell/Unwind/windows-unaligned-x86_64.test b/lldb/test/Shell/Unwind/windows-unaligned-x86_64.test
new file mode 100644
index 0000000000000..94f1c011ebd2a
--- /dev/null
+++ b/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
More information about the lldb-commits
mailing list