xref: /llvm-project/lldb/test/API/commands/trace/multiple-threads/TestTraceStartStopMultipleThreads.py (revision a4c18137d84bc48df49ee0101bef465a955e62ac)
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