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