1"""
2This tests that we do not lose control of the inferior, while doing an instruction-level step
3over a thread creation instruction.
4"""
5
6
7
8import lldb
9from lldbsuite.test.decorators import *
10from lldbsuite.test.lldbtest import *
11from lldbsuite.test import lldbutil
12
13
14class CreateDuringInstructionStepTestCase(TestBase):
15
16    mydir = TestBase.compute_mydir(__file__)
17    NO_DEBUG_INFO_TESTCASE = True
18
19    @skipUnlessPlatform(['linux'])
20    @expectedFailureAndroid('llvm.org/pr24737', archs=['arm'])
21    @expectedFailureAll(
22        oslist=["linux"],
23        archs=["arm"],
24        bugnumber="llvm.org/pr24737")
25    def test_step_inst(self):
26        self.build(dictionary=self.getBuildFlags())
27        exe = self.getBuildArtifact("a.out")
28        target = self.dbg.CreateTarget(exe)
29        self.assertTrue(target and target.IsValid(), "Target is valid")
30
31        # This should create a breakpoint in the stepping thread.
32        breakpoint = target.BreakpointCreateByName("main")
33        self.assertTrue(
34            breakpoint and breakpoint.IsValid(),
35            "Breakpoint is valid")
36
37        # Run the program.
38        process = target.LaunchSimple(
39            None, None, self.get_process_working_directory())
40        self.assertTrue(process and process.IsValid(), PROCESS_IS_VALID)
41
42        # The stop reason of the thread should be breakpoint.
43        self.assertEqual(
44            process.GetState(),
45            lldb.eStateStopped,
46            PROCESS_STOPPED)
47
48        threads = lldbutil.get_threads_stopped_at_breakpoint(
49            process, breakpoint)
50        self.assertEqual(len(threads), 1, STOPPED_DUE_TO_BREAKPOINT)
51
52        thread = threads[0]
53        self.assertTrue(thread and thread.IsValid(), "Thread is valid")
54
55        # Make sure we see only one threads
56        self.assertEqual(
57            process.GetNumThreads(),
58            1,
59            'Number of expected threads and actual threads do not match.')
60
61        # Keep stepping until we see the thread creation
62        while process.GetNumThreads() < 2:
63            thread.StepInstruction(False)
64            self.assertEqual(
65                process.GetState(),
66                lldb.eStateStopped,
67                PROCESS_STOPPED)
68            self.assertEqual(
69                thread.GetStopReason(),
70                lldb.eStopReasonPlanComplete,
71                "Step operation succeeded")
72            if self.TraceOn():
73                self.runCmd("disassemble --pc")
74
75        if self.TraceOn():
76            self.runCmd("thread list")
77
78        # We have successfully caught thread creation. Now just run to
79        # completion
80        process.Continue()
81
82        # At this point, the inferior process should have exited.
83        self.assertEqual(process.GetState(), lldb.eStateExited, PROCESS_EXITED)
84