1"""
2Test that we can backtrace correctly with 'sigtramp' functions on the stack
3"""
4
5from __future__ import print_function
6
7
8import lldb
9from lldbsuite.test.decorators import *
10from lldbsuite.test.lldbtest import *
11from lldbsuite.test import lldbutil
12
13
14class SigtrampUnwind(TestBase):
15
16    # On different platforms the "_sigtramp" and "__kill" frames are likely to be different.
17    # This test could probably be adapted to run on linux/*bsd easily enough.
18    @skipUnlessDarwin
19    @expectedFailureAll(archs=["arm64"], bugnumber="<rdar://problem/34006863>")  # lldb skips 1 frame on arm64 above _sigtramp
20    def test(self):
21        """Test that we can backtrace correctly with _sigtramp on the stack"""
22        self.build()
23        self.setTearDownCleanup()
24
25        exe = self.getBuildArtifact("a.out")
26        target = self.dbg.CreateTarget(exe)
27        self.assertTrue(target, VALID_TARGET)
28
29        lldbutil.run_break_set_by_file_and_line(self, "main.c", line_number(
30            'main.c', '// Set breakpoint here'), num_expected_locations=1)
31
32        process = target.LaunchSimple(
33            None, None, self.get_process_working_directory())
34
35        if not process:
36            self.fail("SBTarget.Launch() failed")
37
38        if process.GetState() != lldb.eStateStopped:
39            self.fail("Process should be in the 'stopped' state, "
40                      "instead the actual state is: '%s'" %
41                      lldbutil.state_type_to_str(process.GetState()))
42
43        self.expect(
44            "pro handle  -n false -p true -s false SIGUSR1",
45            "Have lldb pass SIGUSR1 signals",
46            substrs=[
47                "SIGUSR1",
48                "true",
49                "false",
50                "false"])
51
52        lldbutil.run_break_set_by_symbol(
53            self,
54            "handler",
55            num_expected_locations=1,
56            module_name="a.out")
57
58        self.runCmd("continue")
59
60        thread = process.GetThreadAtIndex(0)
61
62        found_handler = False
63        found_sigtramp = False
64        found_kill = False
65        found_main = False
66
67        for f in thread.frames:
68            if f.GetFunctionName() == "handler":
69                found_handler = True
70            if f.GetFunctionName() == "_sigtramp":
71                found_sigtramp = True
72            if f.GetFunctionName() == "__kill":
73                found_kill = True
74            if f.GetFunctionName() == "main":
75                found_main = True
76
77        if self.TraceOn():
78            print("Backtrace once we're stopped:")
79            for f in thread.frames:
80                print("  %d %s" % (f.GetFrameID(), f.GetFunctionName()))
81
82        if not found_handler:
83            self.fail("Unable to find handler() in backtrace.")
84
85        if not found_sigtramp:
86            self.fail("Unable to find _sigtramp() in backtrace.")
87
88        if not found_kill:
89            self.fail("Unable to find kill() in backtrace.")
90
91        if not found_main:
92            self.fail("Unable to find main() in backtrace.")
93