xref: /llvm-project/lldb/packages/Python/lldbsuite/test/tools/intelpt/intelpt_testcase.py (revision 586114510c5fa71d1377c7f53e68a3b12c472aa2)
1bf9f21a2SWalter Erquinigofrom lldbsuite.test.lldbtest import *
2bf9f21a2SWalter Erquinigoimport os
3bf9f21a2SWalter Erquinigoimport time
4bf9f21a2SWalter Erquinigoimport json
5bf9f21a2SWalter Erquinigo
62238dcc3SJonas DevlieghereADDRESS_REGEX = "0x[0-9a-fA-F]*"
72238dcc3SJonas Devlieghere
8bf9f21a2SWalter Erquinigo
9bf9f21a2SWalter Erquinigo# Decorator that runs a test with both modes of USE_SB_API.
10bf9f21a2SWalter Erquinigo# It assumes that no tests can be executed in parallel.
11bf9f21a2SWalter Erquinigodef testSBAPIAndCommands(func):
12bf9f21a2SWalter Erquinigo    def wrapper(*args, **kwargs):
13bf9f21a2SWalter Erquinigo        TraceIntelPTTestCaseBase.USE_SB_API = True
14bf9f21a2SWalter Erquinigo        func(*args, **kwargs)
15bf9f21a2SWalter Erquinigo        TraceIntelPTTestCaseBase.USE_SB_API = False
16bf9f21a2SWalter Erquinigo        func(*args, **kwargs)
172238dcc3SJonas Devlieghere
18bf9f21a2SWalter Erquinigo    return wrapper
19bf9f21a2SWalter Erquinigo
202238dcc3SJonas Devlieghere
21bf9f21a2SWalter Erquinigo# Class that should be used by all python Intel PT tests.
22bf9f21a2SWalter Erquinigo#
23bf9f21a2SWalter Erquinigo# It has a handy check that skips the test if the intel-pt plugin is not enabled.
24bf9f21a2SWalter Erquinigo#
25bf9f21a2SWalter Erquinigo# It also contains many functions that can test both the SB API or the command line version
26bf9f21a2SWalter Erquinigo# of the most important tracing actions.
27bf9f21a2SWalter Erquinigoclass TraceIntelPTTestCaseBase(TestBase):
28bf9f21a2SWalter Erquinigo    NO_DEBUG_INFO_TESTCASE = True
29bf9f21a2SWalter Erquinigo
30bf9f21a2SWalter Erquinigo    # If True, the trace test methods will use the SB API, otherwise they'll use raw commands.
31bf9f21a2SWalter Erquinigo    USE_SB_API = False
32bf9f21a2SWalter Erquinigo
33bf9f21a2SWalter Erquinigo    def setUp(self):
34bf9f21a2SWalter Erquinigo        TestBase.setUp(self)
352238dcc3SJonas Devlieghere        if "intel-pt" not in configuration.enabled_plugins:
36bf9f21a2SWalter Erquinigo            self.skipTest("The intel-pt test plugin is not enabled")
37bf9f21a2SWalter Erquinigo
386a5355e8SWalter Erquinigo    def skipIfPerCpuTracingIsNotSupported(self):
391f49714dSWalter Erquinigo        def is_supported():
401f49714dSWalter Erquinigo            try:
411f49714dSWalter Erquinigo                with open("/proc/sys/kernel/perf_event_paranoid", "r") as permissions:
421f49714dSWalter Erquinigo                    value = int(permissions.readlines()[0])
431f49714dSWalter Erquinigo                    if value <= 0:
441f49714dSWalter Erquinigo                        return True
451f49714dSWalter Erquinigo            except:
461f49714dSWalter Erquinigo                return False
472238dcc3SJonas Devlieghere
481f49714dSWalter Erquinigo        if not is_supported():
492238dcc3SJonas Devlieghere            self.skipTest(
502238dcc3SJonas Devlieghere                "Per cpu tracing is not supported. You need "
5137161079SWalter Erquinigo                "/proc/sys/kernel/perf_event_paranoid to be 0 or -1. "
522238dcc3SJonas Devlieghere                "You can use `sudo sysctl -w kernel.perf_event_paranoid=-1` for that."
532238dcc3SJonas Devlieghere            )
541f49714dSWalter Erquinigo
55bf9f21a2SWalter Erquinigo    def getTraceOrCreate(self):
56bf9f21a2SWalter Erquinigo        if not self.target().GetTrace().IsValid():
57bf9f21a2SWalter Erquinigo            error = lldb.SBError()
58bf9f21a2SWalter Erquinigo            self.target().CreateTrace(error)
59bf9f21a2SWalter Erquinigo        return self.target().GetTrace()
60bf9f21a2SWalter Erquinigo
61bf9f21a2SWalter Erquinigo    def assertSBError(self, sberror, error=False):
62bf9f21a2SWalter Erquinigo        if error:
63bf9f21a2SWalter Erquinigo            self.assertTrue(sberror.Fail())
64bf9f21a2SWalter Erquinigo        else:
65bf9f21a2SWalter Erquinigo            self.assertSuccess(sberror)
66bf9f21a2SWalter Erquinigo
672238dcc3SJonas Devlieghere    def createConfiguration(
682238dcc3SJonas Devlieghere        self,
692238dcc3SJonas Devlieghere        iptTraceSize=None,
702238dcc3SJonas Devlieghere        processBufferSizeLimit=None,
712238dcc3SJonas Devlieghere        enableTsc=False,
722238dcc3SJonas Devlieghere        psbPeriod=None,
732238dcc3SJonas Devlieghere        perCpuTracing=False,
742238dcc3SJonas Devlieghere    ):
75bf9f21a2SWalter Erquinigo        obj = {}
76bf9f21a2SWalter Erquinigo        if processBufferSizeLimit is not None:
77bf9f21a2SWalter Erquinigo            obj["processBufferSizeLimit"] = processBufferSizeLimit
786a5355e8SWalter Erquinigo        if iptTraceSize is not None:
796a5355e8SWalter Erquinigo            obj["iptTraceSize"] = iptTraceSize
8004195843SWalter Erquinigo        if psbPeriod is not None:
8104195843SWalter Erquinigo            obj["psbPeriod"] = psbPeriod
8204195843SWalter Erquinigo        obj["enableTsc"] = enableTsc
836a5355e8SWalter Erquinigo        obj["perCpuTracing"] = perCpuTracing
84bf9f21a2SWalter Erquinigo
85bf9f21a2SWalter Erquinigo        configuration = lldb.SBStructuredData()
86bf9f21a2SWalter Erquinigo        configuration.SetFromJSON(json.dumps(obj))
87bf9f21a2SWalter Erquinigo        return configuration
88bf9f21a2SWalter Erquinigo
892238dcc3SJonas Devlieghere    def traceStartThread(
902238dcc3SJonas Devlieghere        self,
912238dcc3SJonas Devlieghere        thread=None,
922238dcc3SJonas Devlieghere        error=False,
932238dcc3SJonas Devlieghere        substrs=None,
942238dcc3SJonas Devlieghere        iptTraceSize=None,
952238dcc3SJonas Devlieghere        enableTsc=False,
962238dcc3SJonas Devlieghere        psbPeriod=None,
972238dcc3SJonas Devlieghere    ):
98bf9f21a2SWalter Erquinigo        if self.USE_SB_API:
99bf9f21a2SWalter Erquinigo            trace = self.getTraceOrCreate()
100bf9f21a2SWalter Erquinigo            thread = thread if thread is not None else self.thread()
10104195843SWalter Erquinigo            configuration = self.createConfiguration(
1022238dcc3SJonas Devlieghere                iptTraceSize=iptTraceSize, enableTsc=enableTsc, psbPeriod=psbPeriod
1032238dcc3SJonas Devlieghere            )
104bf9f21a2SWalter Erquinigo            self.assertSBError(trace.Start(thread, configuration), error)
105bf9f21a2SWalter Erquinigo        else:
106bf9f21a2SWalter Erquinigo            command = "thread trace start"
107bf9f21a2SWalter Erquinigo            if thread is not None:
108bf9f21a2SWalter Erquinigo                command += " " + str(thread.GetIndexID())
1096a5355e8SWalter Erquinigo            if iptTraceSize is not None:
1106a5355e8SWalter Erquinigo                command += " -s " + str(iptTraceSize)
11104195843SWalter Erquinigo            if enableTsc:
11204195843SWalter Erquinigo                command += " --tsc"
11304195843SWalter Erquinigo            if psbPeriod is not None:
11404195843SWalter Erquinigo                command += " --psb-period " + str(psbPeriod)
115bf9f21a2SWalter Erquinigo            self.expect(command, error=error, substrs=substrs)
116bf9f21a2SWalter Erquinigo
1172238dcc3SJonas Devlieghere    def traceStartProcess(
1182238dcc3SJonas Devlieghere        self,
1192238dcc3SJonas Devlieghere        processBufferSizeLimit=None,
1202238dcc3SJonas Devlieghere        error=False,
1212238dcc3SJonas Devlieghere        substrs=None,
1222238dcc3SJonas Devlieghere        enableTsc=False,
1232238dcc3SJonas Devlieghere        psbPeriod=None,
1242238dcc3SJonas Devlieghere        perCpuTracing=False,
1252238dcc3SJonas Devlieghere    ):
126bf9f21a2SWalter Erquinigo        if self.USE_SB_API:
127bf9f21a2SWalter Erquinigo            trace = self.getTraceOrCreate()
12804195843SWalter Erquinigo            configuration = self.createConfiguration(
1292238dcc3SJonas Devlieghere                processBufferSizeLimit=processBufferSizeLimit,
1302238dcc3SJonas Devlieghere                enableTsc=enableTsc,
1312238dcc3SJonas Devlieghere                psbPeriod=psbPeriod,
1322238dcc3SJonas Devlieghere                perCpuTracing=perCpuTracing,
1332238dcc3SJonas Devlieghere            )
134bf9f21a2SWalter Erquinigo            self.assertSBError(trace.Start(configuration), error=error)
135bf9f21a2SWalter Erquinigo        else:
136bf9f21a2SWalter Erquinigo            command = "process trace start"
137*58611451SEisuke Kawashima            if processBufferSizeLimit is not None:
138bf9f21a2SWalter Erquinigo                command += " -l " + str(processBufferSizeLimit)
13904195843SWalter Erquinigo            if enableTsc:
14004195843SWalter Erquinigo                command += " --tsc"
14104195843SWalter Erquinigo            if psbPeriod is not None:
14204195843SWalter Erquinigo                command += " --psb-period " + str(psbPeriod)
1436a5355e8SWalter Erquinigo            if perCpuTracing:
1446a5355e8SWalter Erquinigo                command += " --per-cpu-tracing"
145bf9f21a2SWalter Erquinigo            self.expect(command, error=error, substrs=substrs)
146bf9f21a2SWalter Erquinigo
147bf9f21a2SWalter Erquinigo    def traceStopProcess(self):
148bf9f21a2SWalter Erquinigo        if self.USE_SB_API:
149bf9f21a2SWalter Erquinigo            self.assertSuccess(self.target().GetTrace().Stop())
150bf9f21a2SWalter Erquinigo        else:
151bf9f21a2SWalter Erquinigo            self.expect("process trace stop")
152bf9f21a2SWalter Erquinigo
1531f49714dSWalter Erquinigo    def traceStopThread(self, thread=None, error=False, substrs=None):
154bf9f21a2SWalter Erquinigo        if self.USE_SB_API:
155bf9f21a2SWalter Erquinigo            thread = thread if thread is not None else self.thread()
156bf9f21a2SWalter Erquinigo            self.assertSBError(self.target().GetTrace().Stop(thread), error)
157bf9f21a2SWalter Erquinigo
158bf9f21a2SWalter Erquinigo        else:
159bf9f21a2SWalter Erquinigo            command = "thread trace stop"
160bf9f21a2SWalter Erquinigo            if thread is not None:
161bf9f21a2SWalter Erquinigo                command += " " + str(thread.GetIndexID())
1621f49714dSWalter Erquinigo            self.expect(command, error=error, substrs=substrs)
16350f93679SJakob Johnson
164b532dd54SWalter Erquinigo    def traceLoad(self, traceDescriptionFilePath, error=False, substrs=None):
16550f93679SJakob Johnson        if self.USE_SB_API:
16650f93679SJakob Johnson            traceDescriptionFile = lldb.SBFileSpec(traceDescriptionFilePath, True)
16750f93679SJakob Johnson            loadTraceError = lldb.SBError()
168b532dd54SWalter Erquinigo            self.dbg.LoadTraceFromFile(loadTraceError, traceDescriptionFile)
16950f93679SJakob Johnson            self.assertSBError(loadTraceError, error)
17050f93679SJakob Johnson        else:
17150f93679SJakob Johnson            command = f"trace load -v {traceDescriptionFilePath}"
17250f93679SJakob Johnson            self.expect(command, error=error, substrs=substrs)
173b532dd54SWalter Erquinigo
174b532dd54SWalter Erquinigo    def traceSave(self, traceBundleDir, compact=False, error=False, substrs=None):
175b532dd54SWalter Erquinigo        if self.USE_SB_API:
176b532dd54SWalter Erquinigo            save_error = lldb.SBError()
177b532dd54SWalter Erquinigo            self.target().GetTrace().SaveToDisk(
1782238dcc3SJonas Devlieghere                save_error, lldb.SBFileSpec(traceBundleDir), compact
1792238dcc3SJonas Devlieghere            )
180b532dd54SWalter Erquinigo            self.assertSBError(save_error, error)
181b532dd54SWalter Erquinigo        else:
182b532dd54SWalter Erquinigo            command = f"trace save {traceBundleDir}"
183b532dd54SWalter Erquinigo            if compact:
184b532dd54SWalter Erquinigo                command += " -c"
185b532dd54SWalter Erquinigo            self.expect(command, error=error, substrs=substrs)
186