1"""
2Test the use of setjmp/longjmp for non-local goto operations in a single-threaded inferior.
3"""
4
5
6
7import lldb
8from lldbsuite.test.decorators import *
9from lldbsuite.test.lldbtest import *
10from lldbsuite.test import lldbutil
11
12
13class LongjmpTestCase(TestBase):
14
15    @skipIfDarwin  # llvm.org/pr16769: LLDB on Mac OS X dies in function ReadRegisterBytes in GDBRemoteRegisterContext.cpp
16    @expectedFailureAll(oslist=["freebsd", "linux"], bugnumber="llvm.org/pr20231")
17    @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr24778")
18    @expectedFlakeyNetBSD
19    def test_step_out(self):
20        """Test stepping when the inferior calls setjmp/longjmp, in particular, thread step-out."""
21        self.build()
22        self.step_out()
23
24    @skipIfDarwin  # llvm.org/pr16769: LLDB on Mac OS X dies in function ReadRegisterBytes in GDBRemoteRegisterContext.cpp
25    @expectedFailureAll(oslist=["freebsd", "linux"], bugnumber="llvm.org/pr20231")
26    @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr24778")
27    @skipIfNetBSD
28    def test_step_over(self):
29        """Test stepping when the inferior calls setjmp/longjmp, in particular, thread step-over a longjmp."""
30        self.build()
31        self.step_over()
32
33    @skipIfDarwin  # llvm.org/pr16769: LLDB on Mac OS X dies in function ReadRegisterBytes in GDBRemoteRegisterContext.cpp
34    @expectedFailureAll(oslist=["freebsd", "linux"], bugnumber="llvm.org/pr20231")
35    @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr24778")
36    @expectedFlakeyNetBSD
37    def test_step_back_out(self):
38        """Test stepping when the inferior calls setjmp/longjmp, in particular, thread step-out after thread step-in."""
39        self.build()
40        self.step_back_out()
41
42    def start_test(self, symbol):
43        exe = self.getBuildArtifact("a.out")
44
45        self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET)
46
47        # Break in main().
48        lldbutil.run_break_set_by_symbol(
49            self, symbol, num_expected_locations=-1)
50
51        self.runCmd("run", RUN_SUCCEEDED)
52
53        # The stop reason of the thread should be breakpoint.
54        self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT,
55                    substrs=['stopped', 'stop reason = breakpoint'])
56
57    def check_status(self):
58        # Note: Depending on the generated mapping of DWARF to assembly,
59        # the process may have stopped or exited.
60        self.expect("process status", PROCESS_STOPPED,
61                    patterns=['Process .* exited with status = 0'])
62
63    def step_out(self):
64        self.start_test("do_jump")
65        self.runCmd("thread step-out", RUN_SUCCEEDED)
66        self.check_status()
67
68    def step_over(self):
69        self.start_test("do_jump")
70        self.runCmd("thread step-over", RUN_SUCCEEDED)
71        self.runCmd("thread step-over", RUN_SUCCEEDED)
72        self.check_status()
73
74    def step_back_out(self):
75        self.start_test("main")
76
77        self.runCmd("thread step-over", RUN_SUCCEEDED)
78        self.runCmd("thread step-in", RUN_SUCCEEDED)
79        self.runCmd("thread step-out", RUN_SUCCEEDED)
80        self.check_status()
81