1"""
2Test some lldb command abbreviations.
3"""
4from __future__ import print_function
5
6
7import lldb
8from lldbsuite.test.decorators import *
9from lldbsuite.test.lldbtest import *
10from lldbsuite.test import lldbutil
11
12
13class ExecTestCase(TestBase):
14
15    NO_DEBUG_INFO_TESTCASE = True
16
17    mydir = TestBase.compute_mydir(__file__)
18
19    @expectedFailureAll(archs=['i386'],
20                        oslist=no_match(["freebsd"]),
21                        bugnumber="rdar://28656532")
22    @expectedFailureAll(oslist=["ios", "tvos", "watchos", "bridgeos"], bugnumber="rdar://problem/34559552") # this exec test has problems on ios systems
23    @expectedFailureNetBSD
24    @skipIfAsan # rdar://problem/43756823
25    @skipIfWindows
26    def test_hitting_exec (self):
27        self.do_test(False)
28
29    @expectedFailureAll(archs=['i386'],
30                        oslist=no_match(["freebsd"]),
31                        bugnumber="rdar://28656532")
32    @expectedFailureAll(oslist=["ios", "tvos", "watchos", "bridgeos"], bugnumber="rdar://problem/34559552") # this exec test has problems on ios systems
33    @expectedFailureNetBSD
34    @skipIfAsan # rdar://problem/43756823
35    @skipIfWindows
36    def test_skipping_exec (self):
37        self.do_test(True)
38
39    def do_test(self, skip_exec):
40        self.build()
41        exe = self.getBuildArtifact("a.out")
42        secondprog = self.getBuildArtifact("secondprog")
43
44        # Create the target
45        target = self.dbg.CreateTarget(exe)
46
47        # Create any breakpoints we need
48        breakpoint1 = target.BreakpointCreateBySourceRegex(
49            'Set breakpoint 1 here', lldb.SBFileSpec("main.cpp", False))
50        self.assertTrue(breakpoint1, VALID_BREAKPOINT)
51        breakpoint2 = target.BreakpointCreateBySourceRegex(
52            'Set breakpoint 2 here', lldb.SBFileSpec("secondprog.cpp", False))
53        self.assertTrue(breakpoint2, VALID_BREAKPOINT)
54
55        # Launch the process
56        process = target.LaunchSimple(
57            None, None, self.get_process_working_directory())
58        self.assertTrue(process, PROCESS_IS_VALID)
59
60        if self.TraceOn():
61            self.runCmd("settings show target.process.stop-on-exec", check=False)
62        if skip_exec:
63            self.dbg.HandleCommand("settings set target.process.stop-on-exec false")
64            def cleanup():
65                self.runCmd("settings set target.process.stop-on-exec false",
66                            check=False)
67
68            # Execute the cleanup function during test case tear down.
69            self.addTearDownHook(cleanup)
70
71        # The stop reason of the thread should be breakpoint.
72        self.assertEqual(process.GetState(), lldb.eStateStopped,
73                        STOPPED_DUE_TO_BREAKPOINT)
74
75        threads = lldbutil.get_threads_stopped_at_breakpoint(
76        process, breakpoint1)
77        self.assertEqual(len(threads), 1)
78
79        # We had a deadlock tearing down the TypeSystemMap on exec, but only if some
80        # expression had been evaluated.  So make sure we do that here so the teardown
81        # is not trivial.
82
83        thread = threads[0]
84        value = thread.frames[0].EvaluateExpression("1 + 2")
85        self.assertTrue(
86            value.IsValid(),
87            "Expression evaluated successfully")
88        int_value = value.GetValueAsSigned()
89        self.assertEqual(int_value, 3, "Expression got the right result.")
90
91        # Run and we should stop due to exec
92        process.Continue()
93
94        if not skip_exec:
95            self.assertNotEqual(process.GetState(), lldb.eStateExited,
96                                "Process should not have exited!")
97            self.assertEqual(process.GetState(), lldb.eStateStopped,
98                             "Process should be stopped at __dyld_start")
99
100            threads = lldbutil.get_stopped_threads(
101                process, lldb.eStopReasonExec)
102            self.assertEqual(
103                len(threads), 1,
104                "We got a thread stopped for exec.")
105
106            # Run and we should stop at breakpoint in main after exec
107            process.Continue()
108
109        threads = lldbutil.get_threads_stopped_at_breakpoint(
110            process, breakpoint2)
111        if self.TraceOn():
112            for t in process.threads:
113                print(t)
114                if t.GetStopReason() != lldb.eStopReasonBreakpoint:
115                    self.runCmd("bt")
116        self.assertEqual(len(threads), 1,
117                        "Stopped at breakpoint in exec'ed process.")
118
119    @expectedFailureAll(archs=['i386'],
120                        oslist=no_match(["freebsd"]),
121                        bugnumber="rdar://28656532")
122    @expectedFailureAll(oslist=["ios", "tvos", "watchos", "bridgeos"], bugnumber="rdar://problem/34559552") # this exec test has problems on ios systems
123    @expectedFailureNetBSD
124    @skipIfAsan # rdar://problem/43756823
125    @skipIfWindows
126    def test_correct_thread_plan_state_before_exec(self):
127        '''
128        In this test we make sure that the Thread* cache in the ThreadPlans
129        is cleared correctly when performing exec
130        '''
131
132        self.build()
133        exe = self.getBuildArtifact("a.out")
134        target = self.dbg.CreateTarget(exe)
135
136        (target, process, thread, breakpoint1) = lldbutil.run_to_source_breakpoint(
137            self, 'Set breakpoint 1 here', lldb.SBFileSpec('main.cpp', False))
138
139        # The stop reason of the thread should be breakpoint.
140        self.assertEqual(process.GetState(), lldb.eStateStopped,
141                        STOPPED_DUE_TO_BREAKPOINT)
142
143        threads = lldbutil.get_threads_stopped_at_breakpoint(process, breakpoint1)
144        self.assertEqual(len(threads), 1)
145
146        # We perform an instruction step, which effectively sets the cache of the base
147        # thread plan, which should be cleared when a new thread list appears.
148        #
149        # Continuing after this instruction step will trigger a call to
150        # ThreadPlan::ShouldReportRun, which sets the ThreadPlan's Thread cache to
151        # the old Thread* value. In Process::UpdateThreadList we are clearing this
152        # cache in preparation for the new ThreadList.
153        #
154        # Not doing this stepping will cause LLDB to first execute a private single step
155        # past the current breakpoint, which eventually avoids the call to ShouldReportRun,
156        # thus not setting the cache to its invalid value.
157        thread.StepInstruction(False)
158
159        # Run and we should stop due to exec
160        breakpoint2 = target.BreakpointCreateBySourceRegex(
161            'Set breakpoint 2 here', lldb.SBFileSpec("secondprog.cpp", False))
162
163        process.Continue()
164
165        self.assertNotEqual(process.GetState(), lldb.eStateExited,
166                            "Process should not have exited!")
167        self.assertEqual(process.GetState(), lldb.eStateStopped,
168                         "Process should be stopped at __dyld_start")
169
170        threads = lldbutil.get_stopped_threads(
171            process, lldb.eStopReasonExec)
172        self.assertEqual(
173            len(threads), 1,
174            "We got a thread stopped for exec.")
175
176        # Run and we should stop at breakpoint in main after exec
177        process.Continue()
178
179        threads = lldbutil.get_threads_stopped_at_breakpoint(
180            process, breakpoint2)
181        self.assertEqual(len(threads), 1,
182                        "Stopped at breakpoint in exec'ed process.")
183