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 80b697561SWalter Erquinigo 92238dcc3SJonas Devlieghereclass TestTraceStartStopMultipleThreads(TraceIntelPTTestCaseBase): 102238dcc3SJonas Devlieghere @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") 262238dcc3SJonas Devlieghere 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") 302238dcc3SJonas Devlieghere self.expect("thread trace dump instructions", substrs=["main.cpp:4"]) 310b697561SWalter Erquinigo 321f49714dSWalter Erquinigo self.traceStopProcess() 331f49714dSWalter Erquinigo 342238dcc3SJonas Devlieghere @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 self.dbg.CreateTarget(exe) 400b697561SWalter Erquinigo 410b697561SWalter Erquinigo self.expect("b main") 420b697561SWalter Erquinigo self.expect("b 6") 430b697561SWalter Erquinigo self.expect("b 11") 440b697561SWalter Erquinigo 450b697561SWalter Erquinigo self.expect("r") 46bf9f21a2SWalter Erquinigo 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 532238dcc3SJonas Devlieghere self.expect("thread trace dump instructions", substrs=["main.cpp:9"]) 542238dcc3SJonas Devlieghere self.expect("thread trace dump instructions 2", substrs=["main.cpp:9"]) 550b697561SWalter Erquinigo 560b697561SWalter Erquinigo # We stop tracing all 570b697561SWalter Erquinigo self.expect("thread trace stop all") 580b697561SWalter Erquinigo 590b697561SWalter Erquinigo # The trace is still in memory 602238dcc3SJonas Devlieghere self.expect("thread trace dump instructions 2", substrs=["main.cpp:9"]) 610b697561SWalter Erquinigo 620b697561SWalter Erquinigo # We'll stop at the next breakpoint in thread 3, thread 2 and 3 will be alive, but only 3 traced. 630b697561SWalter Erquinigo self.expect("continue") 642238dcc3SJonas Devlieghere self.expect("thread trace dump instructions", substrs=["main.cpp:4"]) 652238dcc3SJonas Devlieghere self.expect("thread trace dump instructions 3", substrs=["main.cpp:4"]) 662238dcc3SJonas Devlieghere self.expect( 672238dcc3SJonas Devlieghere "thread trace dump instructions 1", substrs=["not traced"], error=True 682238dcc3SJonas Devlieghere ) 692238dcc3SJonas Devlieghere self.expect( 702238dcc3SJonas Devlieghere "thread trace dump instructions 2", substrs=["not traced"], error=True 712238dcc3SJonas Devlieghere ) 720b697561SWalter Erquinigo 731f49714dSWalter Erquinigo self.traceStopProcess() 741f49714dSWalter Erquinigo 752238dcc3SJonas Devlieghere @skipIf(oslist=no_match(["linux"]), archs=no_match(["i386", "x86_64"])) 760b697561SWalter Erquinigo def testStartMultipleLiveThreadsWithThreadStartAll(self): 770b697561SWalter Erquinigo self.build() 780b697561SWalter Erquinigo exe = self.getBuildArtifact("a.out") 790b697561SWalter Erquinigo target = self.dbg.CreateTarget(exe) 800b697561SWalter Erquinigo 810b697561SWalter Erquinigo self.expect("b main") 820b697561SWalter Erquinigo self.expect("b 6") 830b697561SWalter Erquinigo self.expect("b 11") 840b697561SWalter Erquinigo 850b697561SWalter Erquinigo self.expect("r") 860b697561SWalter Erquinigo 870b697561SWalter Erquinigo self.expect("continue") 880b697561SWalter Erquinigo # We are in thread 2 890b697561SWalter Erquinigo self.expect("thread trace start all") 900b697561SWalter Erquinigo # Now we have instructions in thread's 2 trace 910b697561SWalter Erquinigo self.expect("n") 920b697561SWalter Erquinigo 932238dcc3SJonas Devlieghere self.expect("thread trace dump instructions 2", substrs=["main.cpp:11"]) 940b697561SWalter Erquinigo 950b697561SWalter Erquinigo # We stop tracing all 960b697561SWalter Erquinigo self.runCmd("thread trace stop all") 970b697561SWalter Erquinigo 980b697561SWalter Erquinigo # The trace is still in memory 992238dcc3SJonas Devlieghere self.expect("thread trace dump instructions 2", substrs=["main.cpp:11"]) 1000b697561SWalter Erquinigo 1010b697561SWalter Erquinigo # We'll stop at the next breakpoint in thread 3, and nothing should be traced 1020b697561SWalter Erquinigo self.expect("continue") 1032238dcc3SJonas Devlieghere self.expect( 1042238dcc3SJonas Devlieghere "thread trace dump instructions 3", substrs=["not traced"], error=True 1052238dcc3SJonas Devlieghere ) 1062238dcc3SJonas Devlieghere self.expect( 1072238dcc3SJonas Devlieghere "thread trace dump instructions 1", substrs=["not traced"], error=True 1082238dcc3SJonas Devlieghere ) 1092238dcc3SJonas Devlieghere self.expect( 1102238dcc3SJonas Devlieghere "thread trace dump instructions 2", substrs=["not traced"], error=True 1112238dcc3SJonas Devlieghere ) 1120b697561SWalter Erquinigo 1132238dcc3SJonas Devlieghere @skipIf(oslist=no_match(["linux"]), archs=no_match(["i386", "x86_64"])) 114bf9f21a2SWalter Erquinigo @testSBAPIAndCommands 1150b697561SWalter Erquinigo def testStartMultipleLiveThreadsWithSmallTotalLimit(self): 1160b697561SWalter Erquinigo self.build() 1170b697561SWalter Erquinigo exe = self.getBuildArtifact("a.out") 118bf9f21a2SWalter Erquinigo 119bf9f21a2SWalter Erquinigo self.dbg.CreateTarget(exe) 1200b697561SWalter Erquinigo 1210b697561SWalter Erquinigo self.expect("b main") 1220b697561SWalter Erquinigo self.expect("r") 123bf9f21a2SWalter Erquinigo 1240b697561SWalter Erquinigo # trace the entire process with enough total size for 1 thread trace 125bf9f21a2SWalter Erquinigo self.traceStartProcess(processBufferSizeLimit=5000) 126bf9f21a2SWalter Erquinigo 1270b697561SWalter Erquinigo # we get the stop event when trace 2 appears and can't be traced 1282238dcc3SJonas Devlieghere self.expect("c", substrs=["Thread", "can't be traced"]) 1290b697561SWalter Erquinigo # we get the stop event when trace 3 appears and can't be traced 1302238dcc3SJonas Devlieghere self.expect("c", substrs=["Thread", "can't be traced"]) 131bf9f21a2SWalter Erquinigo 132bf9f21a2SWalter Erquinigo self.traceStopProcess() 133b8d1776fSWalter Erquinigo 1342238dcc3SJonas Devlieghere @skipIf(oslist=no_match(["linux"]), archs=no_match(["i386", "x86_64"])) 135b8d1776fSWalter Erquinigo @testSBAPIAndCommands 1366a5355e8SWalter Erquinigo def testStartPerCpuSession(self): 1376a5355e8SWalter Erquinigo self.skipIfPerCpuTracingIsNotSupported() 1381f49714dSWalter Erquinigo 139b8d1776fSWalter Erquinigo self.build() 140b8d1776fSWalter Erquinigo exe = self.getBuildArtifact("a.out") 141b8d1776fSWalter Erquinigo self.dbg.CreateTarget(exe) 142b8d1776fSWalter Erquinigo 143b8d1776fSWalter Erquinigo self.expect("b main") 144b8d1776fSWalter Erquinigo self.expect("r") 145b8d1776fSWalter Erquinigo 1461f49714dSWalter Erquinigo # We should fail if we hit the total buffer limit. Useful if the number 1476a5355e8SWalter Erquinigo # of cpus is huge. 1482238dcc3SJonas Devlieghere self.traceStartProcess( 1492238dcc3SJonas Devlieghere error="True", 1502238dcc3SJonas Devlieghere processBufferSizeLimit=100, 1516a5355e8SWalter Erquinigo perCpuTracing=True, 1522238dcc3SJonas Devlieghere substrs=[ 1532238dcc3SJonas Devlieghere "The process can't be traced because the process trace size " 1542238dcc3SJonas Devlieghere "limit has been reached. Consider retracing with a higher limit." 1552238dcc3SJonas Devlieghere ], 1562238dcc3SJonas Devlieghere ) 1571f49714dSWalter Erquinigo 1586a5355e8SWalter Erquinigo self.traceStartProcess(perCpuTracing=True) 1591f49714dSWalter Erquinigo self.traceStopProcess() 1601f49714dSWalter Erquinigo 1616a5355e8SWalter Erquinigo self.traceStartProcess(perCpuTracing=True) 1626a5355e8SWalter Erquinigo # We can't support multiple per-cpu tracing sessions. 1632238dcc3SJonas Devlieghere self.traceStartProcess( 1642238dcc3SJonas Devlieghere error=True, 1652238dcc3SJonas Devlieghere perCpuTracing=True, 1662238dcc3SJonas Devlieghere substrs=["Process currently traced. Stop process tracing first"], 1672238dcc3SJonas Devlieghere ) 1681f49714dSWalter Erquinigo 1696a5355e8SWalter Erquinigo # We can't support tracing per thread is per cpu is enabled. 1701f49714dSWalter Erquinigo self.traceStartThread( 1712238dcc3SJonas Devlieghere error="True", substrs=["Thread with tid ", "is currently traced"] 1722238dcc3SJonas Devlieghere ) 1731f49714dSWalter Erquinigo 1746a5355e8SWalter Erquinigo # We can't stop individual thread when per cpu is enabled. 1752238dcc3SJonas Devlieghere self.traceStopThread( 1762238dcc3SJonas Devlieghere error="True", 1772238dcc3SJonas Devlieghere substrs=[ 1782238dcc3SJonas Devlieghere "Can't stop tracing an individual thread when per-cpu process tracing is enabled" 1792238dcc3SJonas Devlieghere ], 1802238dcc3SJonas Devlieghere ) 1811f49714dSWalter Erquinigo 182a7582059SWalter Erquinigo # We move forward a little bit to collect some data 183a7582059SWalter Erquinigo self.expect("b 19") 184a7582059SWalter Erquinigo self.expect("c") 185a7582059SWalter Erquinigo 1866a5355e8SWalter Erquinigo # We will assert that the trace state will contain valid context switch and intel pt trace buffer entries. 1871f2d49a8SWalter Erquinigo # Besides that, we need to get tsc-to-nanos conversion information. 188a7582059SWalter Erquinigo 189a7582059SWalter Erquinigo # We first parse the json response from the custom packet 1902238dcc3SJonas Devlieghere self.runCmd( 1912238dcc3SJonas Devlieghere """process plugin packet send 'jLLDBTraceGetState:{"type":"intel-pt"}]'""" 1922238dcc3SJonas Devlieghere ) 1932238dcc3SJonas Devlieghere response_header = "response: " 194a7582059SWalter Erquinigo output = None 195a7582059SWalter Erquinigo for line in self.res.GetOutput().splitlines(): 196a7582059SWalter Erquinigo if line.find(response_header) != -1: 1972238dcc3SJonas Devlieghere response = line[ 1982238dcc3SJonas Devlieghere line.find(response_header) + len(response_header) : 1992238dcc3SJonas Devlieghere ].strip() 200a7582059SWalter Erquinigo output = json.loads(response) 201a7582059SWalter Erquinigo 202*9c246882SJordan Rupprecht self.assertIsNotNone(output) 2036a5355e8SWalter Erquinigo self.assertIn("cpus", output) 2041f2d49a8SWalter Erquinigo self.assertIn("tscPerfZeroConversion", output) 205a7582059SWalter Erquinigo found_non_empty_context_switch = False 206a7582059SWalter Erquinigo 2076a5355e8SWalter Erquinigo for cpu in output["cpus"]: 208a7582059SWalter Erquinigo context_switch_size = None 2096a5355e8SWalter Erquinigo ipt_trace_size = None 2106a5355e8SWalter Erquinigo for binary_data in cpu["binaryData"]: 2116a5355e8SWalter Erquinigo if binary_data["kind"] == "iptTrace": 2126a5355e8SWalter Erquinigo ipt_trace_size = binary_data["size"] 213a7582059SWalter Erquinigo elif binary_data["kind"] == "perfContextSwitchTrace": 214a7582059SWalter Erquinigo context_switch_size = binary_data["size"] 215*9c246882SJordan Rupprecht self.assertIsNotNone(context_switch_size) 216*9c246882SJordan Rupprecht self.assertIsNotNone(ipt_trace_size) 217a7582059SWalter Erquinigo if context_switch_size > 0: 218a7582059SWalter Erquinigo found_non_empty_context_switch = True 219a7582059SWalter Erquinigo 220a7582059SWalter Erquinigo # We must have captured the context switch of when the target resumed 221a7582059SWalter Erquinigo self.assertTrue(found_non_empty_context_switch) 222a7582059SWalter Erquinigo 223a19fcc2bSWalter Erquinigo self.expect("thread trace dump instructions") 2241f49714dSWalter Erquinigo 2251f49714dSWalter Erquinigo self.traceStopProcess() 226