1import lldb
2from lldbsuite.test.lldbtest import *
3from lldbsuite.test import lldbutil
4from lldbsuite.test.decorators import *
5
6ADDRESS_REGEX = '0x[0-9a-fA-F]*'
7
8class TestTraceStartStopMultipleThreads(TestBase):
9
10    mydir = TestBase.compute_mydir(__file__)
11    NO_DEBUG_INFO_TESTCASE = True
12
13    def setUp(self):
14        TestBase.setUp(self)
15        if 'intel-pt' not in configuration.enabled_plugins:
16            self.skipTest("The intel-pt test plugin is not enabled")
17
18    @skipIf(oslist=no_match(['linux']), archs=no_match(['i386', 'x86_64']))
19    def testStartMultipleLiveThreads(self):
20        self.build()
21        target = self.createTestTarget()
22
23        self.expect("b main")
24        self.expect("b 6")
25        self.expect("b 11")
26
27        self.expect("r")
28        self.expect("proce trace start")
29
30
31        # We'll see here the first thread
32        self.expect("continue")
33        self.expect("thread trace dump instructions", substrs=['main.cpp:9'])
34
35        # We'll see here the second thread
36        self.expect("continue")
37        self.expect("thread trace dump instructions", substrs=['main.cpp:4'])
38
39    @skipIf(oslist=no_match(['linux']), archs=no_match(['i386', 'x86_64']))
40    def testStartMultipleLiveThreadsWithStops(self):
41        self.build()
42        target = self.createTestTarget()
43
44        self.expect("b main")
45        self.expect("b 6")
46        self.expect("b 11")
47
48        self.expect("r")
49        self.expect("process trace start")
50
51
52        # We'll see here the first thread
53        self.expect("continue")
54
55        # We are in thread 2
56        self.expect("thread trace dump instructions", substrs=['main.cpp:9'])
57        self.expect("thread trace dump instructions 2", substrs=['main.cpp:9'])
58
59        # We stop tracing it
60        self.expect("thread trace stop 2")
61
62        # The trace is still in memory
63        self.expect("thread trace dump instructions 2", substrs=['main.cpp:9'])
64
65        # We'll stop at the next breakpoint, thread 2 will be still alive, but not traced. Thread 3 will be traced
66        self.expect("continue")
67        self.expect("thread trace dump instructions", substrs=['main.cpp:4'])
68        self.expect("thread trace dump instructions 3", substrs=['main.cpp:4'])
69
70        self.expect("thread trace dump instructions 2", substrs=['not traced'])
71
72    @skipIf(oslist=no_match(['linux']), archs=no_match(['i386', 'x86_64']))
73    def testStartMultipleLiveThreadsWithStops(self):
74        self.build()
75        exe = self.getBuildArtifact("a.out")
76        target = self.dbg.CreateTarget(exe)
77
78        self.expect("b main")
79        self.expect("b 6")
80        self.expect("b 11")
81
82        self.expect("r")
83        self.expect("process trace start")
84
85        # We'll see here the first thread
86        self.expect("continue")
87
88        # We are in thread 2
89        self.expect("thread trace dump instructions", substrs=['main.cpp:9'])
90        self.expect("thread trace dump instructions 2", substrs=['main.cpp:9'])
91
92        # We stop tracing all
93        self.expect("thread trace stop all")
94
95        # The trace is still in memory
96        self.expect("thread trace dump instructions 2", substrs=['main.cpp:9'])
97
98        # We'll stop at the next breakpoint in thread 3, thread 2 and 3 will be alive, but only 3 traced.
99        self.expect("continue")
100        self.expect("thread trace dump instructions", substrs=['main.cpp:4'])
101        self.expect("thread trace dump instructions 3", substrs=['main.cpp:4'])
102        self.expect("thread trace dump instructions 1", substrs=['not traced'])
103        self.expect("thread trace dump instructions 2", substrs=['not traced'])
104
105    @skipIf(oslist=no_match(['linux']), archs=no_match(['i386', 'x86_64']))
106    def testStartMultipleLiveThreadsWithThreadStartAll(self):
107        self.build()
108        exe = self.getBuildArtifact("a.out")
109        target = self.dbg.CreateTarget(exe)
110
111        self.expect("b main")
112        self.expect("b 6")
113        self.expect("b 11")
114
115        self.expect("r")
116
117        self.expect("continue")
118        # We are in thread 2
119        self.expect("thread trace start all")
120        # Now we have instructions in thread's 2 trace
121        self.expect("n")
122
123        self.expect("thread trace dump instructions 2", substrs=['main.cpp:11'])
124
125        # We stop tracing all
126        self.runCmd("thread trace stop all")
127
128        # The trace is still in memory
129        self.expect("thread trace dump instructions 2", substrs=['main.cpp:11'])
130
131        # We'll stop at the next breakpoint in thread 3, and nothing should be traced
132        self.expect("continue")
133        self.expect("thread trace dump instructions 3", substrs=['not traced'])
134        self.expect("thread trace dump instructions 1", substrs=['not traced'])
135        self.expect("thread trace dump instructions 2", substrs=['not traced'])
136
137    @skipIf(oslist=no_match(['linux']), archs=no_match(['i386', 'x86_64']))
138    def testStartMultipleLiveThreadsWithSmallTotalLimit(self):
139        self.build()
140        exe = self.getBuildArtifact("a.out")
141        target = self.dbg.CreateTarget(exe)
142
143        self.expect("b main")
144        self.expect("r")
145        # trace the entire process with enough total size for 1 thread trace
146        self.expect("process trace start -l 5000")
147        # we get the stop event when trace 2 appears and can't be traced
148        self.expect("c", substrs=['Thread', "can't be traced"])
149        # we get the stop event when trace 3 appears and can't be traced
150        self.expect("c", substrs=['Thread', "can't be traced"])
151