https://github.com/charles-zablit updated https://github.com/llvm/llvm-project/pull/210076
>From 59f6e466cd01831e9ce2bafb5db427eba8a1c9b8 Mon Sep 17 00:00:00 2001 From: Charles Zablit <[email protected]> Date: Thu, 16 Jul 2026 15:43:10 +0100 Subject: [PATCH 1/2] [lldb][Windows] Fix x86_64 default unwind plan; enable trampoline_stepping --- .../Plugins/ABI/X86/ABIWindows_x86_64.cpp | 10 +- .../API/lang/c/trampoline_stepping/Makefile | 3 + .../TestTrampolineStepping.py | 100 ++++++++++++++++++ .../API/lang/c/trampoline_stepping/main.c | 52 +++++++++ 4 files changed, 157 insertions(+), 8 deletions(-) create mode 100644 lldb/test/API/lang/c/trampoline_stepping/Makefile create mode 100644 lldb/test/API/lang/c/trampoline_stepping/TestTrampolineStepping.py create mode 100644 lldb/test/API/lang/c/trampoline_stepping/main.c diff --git a/lldb/source/Plugins/ABI/X86/ABIWindows_x86_64.cpp b/lldb/source/Plugins/ABI/X86/ABIWindows_x86_64.cpp index 079b22a307602..be3c83880bd60 100644 --- a/lldb/source/Plugins/ABI/X86/ABIWindows_x86_64.cpp +++ b/lldb/source/Plugins/ABI/X86/ABIWindows_x86_64.cpp @@ -751,21 +751,15 @@ UnwindPlanSP ABIWindows_x86_64::CreateFunctionEntryUnwindPlan() { // Windows-x86_64 doesn't use %rbp // No available Unwind information for Windows-x86_64 (section .pdata) -// Let's use SysV-x86_64 one for now UnwindPlanSP ABIWindows_x86_64::CreateDefaultUnwindPlan() { - uint32_t fp_reg_num = dwarf_rbp; uint32_t sp_reg_num = dwarf_rsp; uint32_t pc_reg_num = dwarf_rip; UnwindPlan::Row row; - - const int32_t ptr_size = 8; - row.GetCFAValue().SetIsRegisterPlusOffset(dwarf_rbp, 2 * ptr_size); row.SetOffset(0); row.SetUnspecifiedRegistersAreUndefined(true); - - row.SetRegisterLocationToAtCFAPlusOffset(fp_reg_num, ptr_size * -2, true); - row.SetRegisterLocationToAtCFAPlusOffset(pc_reg_num, ptr_size * -1, true); + row.GetCFAValue().SetIsRegisterPlusOffset(sp_reg_num, 8); + row.SetRegisterLocationToAtCFAPlusOffset(pc_reg_num, -8, false); row.SetRegisterLocationToIsCFAPlusOffset(sp_reg_num, 0, true); auto plan_sp = std::make_shared<UnwindPlan>(eRegisterKindDWARF); diff --git a/lldb/test/API/lang/c/trampoline_stepping/Makefile b/lldb/test/API/lang/c/trampoline_stepping/Makefile new file mode 100644 index 0000000000000..10495940055b6 --- /dev/null +++ b/lldb/test/API/lang/c/trampoline_stepping/Makefile @@ -0,0 +1,3 @@ +C_SOURCES := main.c + +include Makefile.rules diff --git a/lldb/test/API/lang/c/trampoline_stepping/TestTrampolineStepping.py b/lldb/test/API/lang/c/trampoline_stepping/TestTrampolineStepping.py new file mode 100644 index 0000000000000..bbf1dc8cb7fea --- /dev/null +++ b/lldb/test/API/lang/c/trampoline_stepping/TestTrampolineStepping.py @@ -0,0 +1,100 @@ +"""Test that stepping in/out of trampolines works as expected.""" + +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + + +class TestTrampoline(TestBase): + def setup(self, bkpt_str): + self.build() + + _, _, thread, _ = lldbutil.run_to_source_breakpoint( + self, bkpt_str, lldb.SBFileSpec("main.c") + ) + return thread + + def test_direct_call(self): + thread = self.setup("Break here for direct") + + # Sanity check that we start out in the correct function. + name = thread.frames[0].GetFunctionName() + self.assertIn("direct_trampoline_call", name) + + # Check that stepping in will take us directly to the trampoline target. + thread.StepInto() + name = thread.frames[0].GetFunctionName() + self.assertIn("foo", name) + + # Check that stepping out takes us back to the trampoline caller. + thread.StepOut() + name = thread.frames[0].GetFunctionName() + self.assertIn("direct_trampoline_call", name) + + # Check that stepping over the end of the trampoline target + # takes us back to the trampoline caller. + thread.StepInto() + thread.StepOver() + name = thread.frames[0].GetFunctionName() + self.assertIn("direct_trampoline_call", name) + + def test_chained_call(self): + thread = self.setup("Break here for chained") + + # Sanity check that we start out in the correct function. + name = thread.frames[0].GetFunctionName() + self.assertIn("chained_trampoline_call", name) + + # Check that stepping in will take us directly to the trampoline target. + thread.StepInto() + name = thread.frames[0].GetFunctionName() + self.assertIn("foo", name) + + # Check that stepping out takes us back to the trampoline caller. + thread.StepOut() + name = thread.frames[0].GetFunctionName() + self.assertIn("chained_trampoline_call", name) + + # Check that stepping over the end of the trampoline target + # takes us back to the trampoline caller. + thread.StepInto() + thread.StepOver() + name = thread.frames[0].GetFunctionName() + self.assertIn("chained_trampoline_call", name) + + def test_trampoline_after_nodebug(self): + thread = self.setup("Break here for nodebug then trampoline") + + # Sanity check that we start out in the correct function. + name = thread.frames[0].GetFunctionName() + self.assertIn("trampoline_after_nodebug", name) + + # Check that stepping in will take us directly to the trampoline target. + thread.StepInto() + name = thread.frames[0].GetFunctionName() + self.assertIn("foo", name) + + # Check that stepping out takes us back to the trampoline caller. + thread.StepOut() + name = thread.frames[0].GetFunctionName() + self.assertIn("trampoline_after_nodebug", name) + + # Check that stepping over the end of the trampoline target + # takes us back to the trampoline caller. + thread.StepInto() + thread.StepOver() + name = thread.frames[0].GetFunctionName() + self.assertIn("trampoline_after_nodebug", name) + + def test_unused_target(self): + thread = self.setup("Break here for unused") + + # Sanity check that we start out in the correct function. + name = thread.frames[0].GetFunctionName() + self.assertIn("unused_target", name) + + # Check that stepping into a trampoline that doesn't call its target + # jumps back to its caller. + thread.StepInto() + name = thread.frames[0].GetFunctionName() + self.assertIn("unused_target", name) diff --git a/lldb/test/API/lang/c/trampoline_stepping/main.c b/lldb/test/API/lang/c/trampoline_stepping/main.c new file mode 100644 index 0000000000000..cb98be00ca1f6 --- /dev/null +++ b/lldb/test/API/lang/c/trampoline_stepping/main.c @@ -0,0 +1,52 @@ +void foo(void) {} + +__attribute__((transparent_stepping)) +void bar(void) { + foo(); +} + +__attribute__((transparent_stepping)) +void baz(void) { + bar(); +} + +__attribute__((nodebug)) +void nodebug(void) {} + +__attribute__((transparent_stepping)) +void nodebug_then_trampoline(void) { + nodebug(); + baz(); +} + +__attribute__((transparent_stepping)) +void doesnt_call_trampoline(void) {} + +void direct_trampoline_call(void) { + bar(); // Break here for direct + bar(); +} + +void chained_trampoline_call(void) { + baz(); // Break here for chained + baz(); +} + +void trampoline_after_nodebug(void) { + nodebug_then_trampoline(); // Break here for nodebug then trampoline + nodebug_then_trampoline(); +} + +void unused_target(void) { + doesnt_call_trampoline(); // Break here for unused +} + + +int main(void) { + direct_trampoline_call(); + chained_trampoline_call(); + trampoline_after_nodebug(); + unused_target(); + return 0; +} + >From a1d435a5f9accefbb2a5f969e153b07cf50ef3b0 Mon Sep 17 00:00:00 2001 From: Charles Zablit <[email protected]> Date: Thu, 16 Jul 2026 15:53:58 +0100 Subject: [PATCH 2/2] fixup! [lldb][Windows] Fix x86_64 default unwind plan; enable trampoline_stepping --- .../API/lang/c/trampoline_stepping/main.c | 23 +++++-------------- 1 file changed, 6 insertions(+), 17 deletions(-) diff --git a/lldb/test/API/lang/c/trampoline_stepping/main.c b/lldb/test/API/lang/c/trampoline_stepping/main.c index cb98be00ca1f6..25f41e2bad0ad 100644 --- a/lldb/test/API/lang/c/trampoline_stepping/main.c +++ b/lldb/test/API/lang/c/trampoline_stepping/main.c @@ -1,29 +1,20 @@ void foo(void) {} -__attribute__((transparent_stepping)) -void bar(void) { - foo(); -} +__attribute__((transparent_stepping)) void bar(void) { foo(); } -__attribute__((transparent_stepping)) -void baz(void) { - bar(); -} +__attribute__((transparent_stepping)) void baz(void) { bar(); } -__attribute__((nodebug)) -void nodebug(void) {} +__attribute__((nodebug)) void nodebug(void) {} -__attribute__((transparent_stepping)) -void nodebug_then_trampoline(void) { +__attribute__((transparent_stepping)) void nodebug_then_trampoline(void) { nodebug(); baz(); } -__attribute__((transparent_stepping)) -void doesnt_call_trampoline(void) {} +__attribute__((transparent_stepping)) void doesnt_call_trampoline(void) {} void direct_trampoline_call(void) { - bar(); // Break here for direct + bar(); // Break here for direct bar(); } @@ -41,7 +32,6 @@ void unused_target(void) { doesnt_call_trampoline(); // Break here for unused } - int main(void) { direct_trampoline_call(); chained_trampoline_call(); @@ -49,4 +39,3 @@ int main(void) { unused_target(); return 0; } - _______________________________________________ lldb-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
