10b697561SWalter Erquinigoimport lldb
2a7582059SWalter Erquinigoimport json
3bf9f21a2SWalter Erquinigofrom intelpt_testcase import *
40b697561SWalter Erquinigofrom lldbsuite.test.lldbtest import *
50b697561SWalter Erquinigofrom lldbsuite.test import lldbutil
60b697561SWalter Erquinigofrom lldbsuite.test.decorators import *
70b697561SWalter Erquinigo
8bf9f21a2SWalter Erquinigoclass TestTraceStartStopMultipleThreads(TraceIntelPTTestCaseBase):
90b697561SWalter Erquinigo
100b697561SWalter Erquinigo    @skipIf(oslist=no_match(['linux']), archs=no_match(['i386', 'x86_64']))
11bf9f21a2SWalter Erquinigo    @testSBAPIAndCommands
120b697561SWalter Erquinigo    def testStartMultipleLiveThreads(self):
130b697561SWalter Erquinigo        self.build()
14bf9f21a2SWalter Erquinigo        exe = self.getBuildArtifact("a.out")
15bf9f21a2SWalter Erquinigo
16bf9f21a2SWalter Erquinigo        self.dbg.CreateTarget(exe)
170b697561SWalter Erquinigo
180b697561SWalter Erquinigo        self.expect("b main")
190b697561SWalter Erquinigo        self.expect("b 6")
200b697561SWalter Erquinigo        self.expect("b 11")
210b697561SWalter Erquinigo
220b697561SWalter Erquinigo        self.expect("r")
23bf9f21a2SWalter Erquinigo        self.traceStartProcess()
240b697561SWalter Erquinigo
250b697561SWalter Erquinigo        self.expect("continue")
260b697561SWalter Erquinigo        self.expect("thread trace dump instructions", substrs=['main.cpp:9'])
270b697561SWalter Erquinigo
280b697561SWalter Erquinigo        # We'll see here the second thread
290b697561SWalter Erquinigo        self.expect("continue")
300b697561SWalter Erquinigo        self.expect("thread trace dump instructions", substrs=['main.cpp:4'])
310b697561SWalter Erquinigo
321f49714dSWalter Erquinigo        self.traceStopProcess()
331f49714dSWalter Erquinigo
340b697561SWalter Erquinigo    @skipIf(oslist=no_match(['linux']), archs=no_match(['i386', 'x86_64']))
35bf9f21a2SWalter Erquinigo    @testSBAPIAndCommands
360b697561SWalter Erquinigo    def testStartMultipleLiveThreadsWithStops(self):
370b697561SWalter Erquinigo        self.build()
38bf9f21a2SWalter Erquinigo        exe = self.getBuildArtifact("a.out")
39bf9f21a2SWalter Erquinigo
40bf9f21a2SWalter Erquinigo        self.dbg.CreateTarget(exe)
410b697561SWalter Erquinigo
420b697561SWalter Erquinigo        self.expect("b main")
430b697561SWalter Erquinigo        self.expect("b 6")
440b697561SWalter Erquinigo        self.expect("b 11")
450b697561SWalter Erquinigo
460b697561SWalter Erquinigo        self.expect("r")
47bf9f21a2SWalter Erquinigo        self.traceStartProcess()
480b697561SWalter Erquinigo
490b697561SWalter Erquinigo        # We'll see here the first thread
500b697561SWalter Erquinigo        self.expect("continue")
510b697561SWalter Erquinigo
520b697561SWalter Erquinigo        # We are in thread 2
530b697561SWalter Erquinigo        self.expect("thread trace dump instructions", substrs=['main.cpp:9'])
540b697561SWalter Erquinigo        self.expect("thread trace dump instructions 2", substrs=['main.cpp:9'])
550b697561SWalter Erquinigo
560b697561SWalter Erquinigo        # We stop tracing it
570b697561SWalter Erquinigo        self.expect("thread trace stop 2")
580b697561SWalter Erquinigo
590b697561SWalter Erquinigo        # The trace is still in memory
600b697561SWalter Erquinigo        self.expect("thread trace dump instructions 2", substrs=['main.cpp:9'])
610b697561SWalter Erquinigo
620b697561SWalter Erquinigo        # We'll stop at the next breakpoint, thread 2 will be still alive, but not traced. Thread 3 will be traced
630b697561SWalter Erquinigo        self.expect("continue")
640b697561SWalter Erquinigo        self.expect("thread trace dump instructions", substrs=['main.cpp:4'])
650b697561SWalter Erquinigo        self.expect("thread trace dump instructions 3", substrs=['main.cpp:4'])
660b697561SWalter Erquinigo
670b697561SWalter Erquinigo        self.expect("thread trace dump instructions 2", substrs=['not traced'])
680b697561SWalter Erquinigo
691f49714dSWalter Erquinigo        self.traceStopProcess()
701f49714dSWalter Erquinigo
710b697561SWalter Erquinigo    @skipIf(oslist=no_match(['linux']), archs=no_match(['i386', 'x86_64']))
72bf9f21a2SWalter Erquinigo    @testSBAPIAndCommands
730b697561SWalter Erquinigo    def testStartMultipleLiveThreadsWithStops(self):
740b697561SWalter Erquinigo        self.build()
750b697561SWalter Erquinigo        exe = self.getBuildArtifact("a.out")
76bf9f21a2SWalter Erquinigo        self.dbg.CreateTarget(exe)
770b697561SWalter Erquinigo
780b697561SWalter Erquinigo        self.expect("b main")
790b697561SWalter Erquinigo        self.expect("b 6")
800b697561SWalter Erquinigo        self.expect("b 11")
810b697561SWalter Erquinigo
820b697561SWalter Erquinigo        self.expect("r")
83bf9f21a2SWalter Erquinigo
84bf9f21a2SWalter Erquinigo        self.traceStartProcess()
850b697561SWalter Erquinigo
860b697561SWalter Erquinigo        # We'll see here the first thread
870b697561SWalter Erquinigo        self.expect("continue")
880b697561SWalter Erquinigo
890b697561SWalter Erquinigo        # We are in thread 2
900b697561SWalter Erquinigo        self.expect("thread trace dump instructions", substrs=['main.cpp:9'])
910b697561SWalter Erquinigo        self.expect("thread trace dump instructions 2", substrs=['main.cpp:9'])
920b697561SWalter Erquinigo
930b697561SWalter Erquinigo        # We stop tracing all
940b697561SWalter Erquinigo        self.expect("thread trace stop all")
950b697561SWalter Erquinigo
960b697561SWalter Erquinigo        # The trace is still in memory
970b697561SWalter Erquinigo        self.expect("thread trace dump instructions 2", substrs=['main.cpp:9'])
980b697561SWalter Erquinigo
990b697561SWalter Erquinigo        # We'll stop at the next breakpoint in thread 3, thread 2 and 3 will be alive, but only 3 traced.
1000b697561SWalter Erquinigo        self.expect("continue")
1010b697561SWalter Erquinigo        self.expect("thread trace dump instructions", substrs=['main.cpp:4'])
1020b697561SWalter Erquinigo        self.expect("thread trace dump instructions 3", substrs=['main.cpp:4'])
103*a7d6c3efSWalter Erquinigo        self.expect("thread trace dump instructions 1", substrs=['not traced'], error=True)
104*a7d6c3efSWalter Erquinigo        self.expect("thread trace dump instructions 2", substrs=['not traced'], error=True)
1050b697561SWalter Erquinigo
1061f49714dSWalter Erquinigo        self.traceStopProcess()
1071f49714dSWalter Erquinigo
1080b697561SWalter Erquinigo    @skipIf(oslist=no_match(['linux']), archs=no_match(['i386', 'x86_64']))
1090b697561SWalter Erquinigo    def testStartMultipleLiveThreadsWithThreadStartAll(self):
1100b697561SWalter Erquinigo        self.build()
1110b697561SWalter Erquinigo        exe = self.getBuildArtifact("a.out")
1120b697561SWalter Erquinigo        target = self.dbg.CreateTarget(exe)
1130b697561SWalter Erquinigo
1140b697561SWalter Erquinigo        self.expect("b main")
1150b697561SWalter Erquinigo        self.expect("b 6")
1160b697561SWalter Erquinigo        self.expect("b 11")
1170b697561SWalter Erquinigo
1180b697561SWalter Erquinigo        self.expect("r")
1190b697561SWalter Erquinigo
1200b697561SWalter Erquinigo        self.expect("continue")
1210b697561SWalter Erquinigo        # We are in thread 2
1220b697561SWalter Erquinigo        self.expect("thread trace start all")
1230b697561SWalter Erquinigo        # Now we have instructions in thread's 2 trace
1240b697561SWalter Erquinigo        self.expect("n")
1250b697561SWalter Erquinigo
1260b697561SWalter Erquinigo        self.expect("thread trace dump instructions 2", substrs=['main.cpp:11'])
1270b697561SWalter Erquinigo
1280b697561SWalter Erquinigo        # We stop tracing all
1290b697561SWalter Erquinigo        self.runCmd("thread trace stop all")
1300b697561SWalter Erquinigo
1310b697561SWalter Erquinigo        # The trace is still in memory
1320b697561SWalter Erquinigo        self.expect("thread trace dump instructions 2", substrs=['main.cpp:11'])
1330b697561SWalter Erquinigo
1340b697561SWalter Erquinigo        # We'll stop at the next breakpoint in thread 3, and nothing should be traced
1350b697561SWalter Erquinigo        self.expect("continue")
136*a7d6c3efSWalter Erquinigo        self.expect("thread trace dump instructions 3", substrs=['not traced'], error=True)
137*a7d6c3efSWalter Erquinigo        self.expect("thread trace dump instructions 1", substrs=['not traced'], error=True)
138*a7d6c3efSWalter Erquinigo        self.expect("thread trace dump instructions 2", substrs=['not traced'], error=True)
1390b697561SWalter Erquinigo
1400b697561SWalter Erquinigo    @skipIf(oslist=no_match(['linux']), archs=no_match(['i386', 'x86_64']))
141bf9f21a2SWalter Erquinigo    @testSBAPIAndCommands
1420b697561SWalter Erquinigo    def testStartMultipleLiveThreadsWithSmallTotalLimit(self):
1430b697561SWalter Erquinigo        self.build()
1440b697561SWalter Erquinigo        exe = self.getBuildArtifact("a.out")
145bf9f21a2SWalter Erquinigo
146bf9f21a2SWalter Erquinigo        self.dbg.CreateTarget(exe)
1470b697561SWalter Erquinigo
1480b697561SWalter Erquinigo        self.expect("b main")
1490b697561SWalter Erquinigo        self.expect("r")
150bf9f21a2SWalter Erquinigo
1510b697561SWalter Erquinigo        # trace the entire process with enough total size for 1 thread trace
152bf9f21a2SWalter Erquinigo        self.traceStartProcess(processBufferSizeLimit=5000)
153bf9f21a2SWalter Erquinigo
1540b697561SWalter Erquinigo        # we get the stop event when trace 2 appears and can't be traced
1550b697561SWalter Erquinigo        self.expect("c", substrs=['Thread', "can't be traced"])
1560b697561SWalter Erquinigo        # we get the stop event when trace 3 appears and can't be traced
1570b697561SWalter Erquinigo        self.expect("c", substrs=['Thread', "can't be traced"])
158bf9f21a2SWalter Erquinigo
159bf9f21a2SWalter Erquinigo        self.traceStopProcess()
160b8d1776fSWalter Erquinigo
161b8d1776fSWalter Erquinigo    @skipIf(oslist=no_match(['linux']), archs=no_match(['i386', 'x86_64']))
162b8d1776fSWalter Erquinigo    @testSBAPIAndCommands
1636a5355e8SWalter Erquinigo    def testStartPerCpuSession(self):
1646a5355e8SWalter Erquinigo        self.skipIfPerCpuTracingIsNotSupported()
1651f49714dSWalter Erquinigo
166b8d1776fSWalter Erquinigo        self.build()
167b8d1776fSWalter Erquinigo        exe = self.getBuildArtifact("a.out")
168b8d1776fSWalter Erquinigo        self.dbg.CreateTarget(exe)
169b8d1776fSWalter Erquinigo
170b8d1776fSWalter Erquinigo        self.expect("b main")
171b8d1776fSWalter Erquinigo        self.expect("r")
172b8d1776fSWalter Erquinigo
1731f49714dSWalter Erquinigo        # We should fail if we hit the total buffer limit. Useful if the number
1746a5355e8SWalter Erquinigo        # of cpus is huge.
1751f49714dSWalter Erquinigo        self.traceStartProcess(error="True", processBufferSizeLimit=100,
1766a5355e8SWalter Erquinigo            perCpuTracing=True,
1771f49714dSWalter Erquinigo            substrs=["The process can't be traced because the process trace size "
1781f49714dSWalter Erquinigo            "limit has been reached. Consider retracing with a higher limit."])
1791f49714dSWalter Erquinigo
1806a5355e8SWalter Erquinigo        self.traceStartProcess(perCpuTracing=True)
1811f49714dSWalter Erquinigo        self.traceStopProcess()
1821f49714dSWalter Erquinigo
1836a5355e8SWalter Erquinigo        self.traceStartProcess(perCpuTracing=True)
1846a5355e8SWalter Erquinigo        # We can't support multiple per-cpu tracing sessions.
1856a5355e8SWalter Erquinigo        self.traceStartProcess(error=True, perCpuTracing=True,
1861f49714dSWalter Erquinigo            substrs=["Process currently traced. Stop process tracing first"])
1871f49714dSWalter Erquinigo
1886a5355e8SWalter Erquinigo        # We can't support tracing per thread is per cpu is enabled.
1891f49714dSWalter Erquinigo        self.traceStartThread(
1901f49714dSWalter Erquinigo            error="True",
1911f56f7fcSWalter Erquinigo            substrs=["Thread with tid ", "is currently traced"])
1921f49714dSWalter Erquinigo
1936a5355e8SWalter Erquinigo        # We can't stop individual thread when per cpu is enabled.
1941f49714dSWalter Erquinigo        self.traceStopThread(error="True",
1956a5355e8SWalter Erquinigo            substrs=["Can't stop tracing an individual thread when per-cpu process tracing is enabled"])
1961f49714dSWalter Erquinigo
197a7582059SWalter Erquinigo        # We move forward a little bit to collect some data
198a7582059SWalter Erquinigo        self.expect("b 19")
199a7582059SWalter Erquinigo        self.expect("c")
200a7582059SWalter Erquinigo
2016a5355e8SWalter Erquinigo        # We will assert that the trace state will contain valid context switch and intel pt trace buffer entries.
2021f2d49a8SWalter Erquinigo        # Besides that, we need to get tsc-to-nanos conversion information.
203a7582059SWalter Erquinigo
204a7582059SWalter Erquinigo        # We first parse the json response from the custom packet
205a7582059SWalter Erquinigo        self.runCmd("""process plugin packet send 'jLLDBTraceGetState:{"type":"intel-pt"}]'""")
206a7582059SWalter Erquinigo        response_header = 'response: '
207a7582059SWalter Erquinigo        output = None
208a7582059SWalter Erquinigo        for line in self.res.GetOutput().splitlines():
209a7582059SWalter Erquinigo            if line.find(response_header) != -1:
210a7582059SWalter Erquinigo                response = line[line.find(response_header) + len(response_header):].strip()
211a7582059SWalter Erquinigo                output = json.loads(response)
212a7582059SWalter Erquinigo
213a7582059SWalter Erquinigo        self.assertTrue(output is not None)
2146a5355e8SWalter Erquinigo        self.assertIn("cpus", output)
2151f2d49a8SWalter Erquinigo        self.assertIn("tscPerfZeroConversion", output)
216a7582059SWalter Erquinigo        found_non_empty_context_switch = False
217a7582059SWalter Erquinigo
2186a5355e8SWalter Erquinigo        for cpu in output["cpus"]:
219a7582059SWalter Erquinigo            context_switch_size = None
2206a5355e8SWalter Erquinigo            ipt_trace_size = None
2216a5355e8SWalter Erquinigo            for binary_data in cpu["binaryData"]:
2226a5355e8SWalter Erquinigo                if binary_data["kind"] == "iptTrace":
2236a5355e8SWalter Erquinigo                    ipt_trace_size = binary_data["size"]
224a7582059SWalter Erquinigo                elif binary_data["kind"] == "perfContextSwitchTrace":
225a7582059SWalter Erquinigo                    context_switch_size = binary_data["size"]
226a7582059SWalter Erquinigo            self.assertTrue(context_switch_size is not None)
2276a5355e8SWalter Erquinigo            self.assertTrue(ipt_trace_size is not None)
228a7582059SWalter Erquinigo            if context_switch_size > 0:
229a7582059SWalter Erquinigo                found_non_empty_context_switch = True
230a7582059SWalter Erquinigo
231a7582059SWalter Erquinigo        # We must have captured the context switch of when the target resumed
232a7582059SWalter Erquinigo        self.assertTrue(found_non_empty_context_switch)
233a7582059SWalter Erquinigo
234a19fcc2bSWalter Erquinigo        self.expect("thread trace dump instructions")
2351f49714dSWalter Erquinigo
2361f49714dSWalter Erquinigo        self.traceStopProcess()
237