| """ | |
| Test the use of setjmp/longjmp for non-local goto operations in a single-threaded inferior. | |
| """ | |
| import lldb | |
| from lldbsuite.test.decorators import * | |
| from lldbsuite.test.lldbtest import * | |
| from lldbsuite.test import lldbutil | |
| @requireNotWasm("setjmp/longjmp on wasm requires exception-handling support") | |
| class LongjmpTestCase(TestBase): | |
| @skipIfDarwin # llvm.org/pr16769: LLDB on Mac OS X dies in function ReadRegisterBytes in GDBRemoteRegisterContext.cpp | |
| @skipIfWindows # Test is flaky on Windows | |
| @expectedFlakeyNetBSD | |
| def test_step_out(self): | |
| """Test stepping when the inferior calls setjmp/longjmp, in particular, thread step-out.""" | |
| self.build() | |
| self.step_out() | |
| @skipIfDarwin # llvm.org/pr16769: LLDB on Mac OS X dies in function ReadRegisterBytes in GDBRemoteRegisterContext.cpp | |
| @skipIfWindows # Test is flaky on Windows | |
| @skipIfNetBSD | |
| def test_step_over(self): | |
| """Test stepping when the inferior calls setjmp/longjmp, in particular, thread step-over a longjmp.""" | |
| self.build() | |
| self.step_over() | |
| @skipIfDarwin # llvm.org/pr16769: LLDB on Mac OS X dies in function ReadRegisterBytes in GDBRemoteRegisterContext.cpp | |
| @skipIfWindows # Test is flaky on Windows | |
| @expectedFlakeyNetBSD | |
| def test_step_back_out(self): | |
| """Test stepping when the inferior calls setjmp/longjmp, in particular, thread step-out after thread step-in.""" | |
| self.build() | |
| self.step_back_out() | |
| def start_test(self, symbol): | |
| exe = self.getBuildArtifact("a.out") | |
| self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET) | |
| # Break in main(). | |
| lldbutil.run_break_set_by_symbol(self, symbol, num_expected_locations=-1) | |
| self.runCmd("run", RUN_SUCCEEDED) | |
| # The stop reason of the thread should be breakpoint. | |
| self.expect( | |
| "thread list", | |
| STOPPED_DUE_TO_BREAKPOINT, | |
| substrs=["stopped", "stop reason = breakpoint"], | |
| ) | |
| def check_status(self): | |
| # Note: Depending on the generated mapping of DWARF to assembly, | |
| # the process may have stopped or exited. | |
| self.expect( | |
| "process status", | |
| PROCESS_STOPPED, | |
| patterns=["Process .* exited with status = 0"], | |
| ) | |
| def step_out(self): | |
| self.start_test("do_jump") | |
| self.runCmd("thread step-out", RUN_SUCCEEDED) | |
| self.check_status() | |
| def step_over(self): | |
| self.start_test("do_jump") | |
| self.runCmd("thread step-over", RUN_SUCCEEDED) | |
| self.runCmd("thread step-over", RUN_SUCCEEDED) | |
| self.check_status() | |
| def step_back_out(self): | |
| self.start_test("main") | |
| self.runCmd("thread step-over", RUN_SUCCEEDED) | |
| self.runCmd("thread step-in", RUN_SUCCEEDED) | |
| self.runCmd("thread step-out", RUN_SUCCEEDED) | |
| self.check_status() |