xref: /llvm-project/lldb/packages/Python/lldbsuite/test/tools/intelpt/intelpt_testcase.py (revision 1f49714d3e19502753fcea7ad8378a194222328f)
1from lldbsuite.test.lldbtest import *
2import os
3import time
4import json
5
6ADDRESS_REGEX = '0x[0-9a-fA-F]*'
7
8# Decorator that runs a test with both modes of USE_SB_API.
9# It assumes that no tests can be executed in parallel.
10def testSBAPIAndCommands(func):
11    def wrapper(*args, **kwargs):
12        TraceIntelPTTestCaseBase.USE_SB_API = True
13        func(*args, **kwargs)
14        TraceIntelPTTestCaseBase.USE_SB_API = False
15        func(*args, **kwargs)
16    return wrapper
17
18# Class that should be used by all python Intel PT tests.
19#
20# It has a handy check that skips the test if the intel-pt plugin is not enabled.
21#
22# It also contains many functions that can test both the SB API or the command line version
23# of the most important tracing actions.
24class TraceIntelPTTestCaseBase(TestBase):
25
26    NO_DEBUG_INFO_TESTCASE = True
27
28    # If True, the trace test methods will use the SB API, otherwise they'll use raw commands.
29    USE_SB_API = False
30
31    def setUp(self):
32        TestBase.setUp(self)
33        if 'intel-pt' not in configuration.enabled_plugins:
34            self.skipTest("The intel-pt test plugin is not enabled")
35
36    def skipIfPerCoreTracingIsNotSupported(self):
37        def is_supported():
38            try:
39                with open("/proc/sys/kernel/perf_event_paranoid", "r") as permissions:
40                    value = int(permissions.readlines()[0])
41                    if value <= 0:
42                        return True
43            except:
44                return False
45        if not is_supported():
46            self.skipTest("Per core tracing is not supported. You need "
47                "/proc/sys/kernel/perf_event_paranoid to be 0 or -1.")
48
49    def getTraceOrCreate(self):
50        if not self.target().GetTrace().IsValid():
51            error = lldb.SBError()
52            self.target().CreateTrace(error)
53        return self.target().GetTrace()
54
55    def assertSBError(self, sberror, error=False):
56        if error:
57            self.assertTrue(sberror.Fail())
58        else:
59            self.assertSuccess(sberror)
60
61    def createConfiguration(self, traceBufferSize=None,
62                            processBufferSizeLimit=None, enableTsc=False,
63                            psbPeriod=None, perCoreTracing=False):
64        obj = {}
65        if processBufferSizeLimit is not None:
66            obj["processBufferSizeLimit"] = processBufferSizeLimit
67        if traceBufferSize is not None:
68            obj["traceBufferSize"] = traceBufferSize
69        if psbPeriod is not None:
70            obj["psbPeriod"] = psbPeriod
71        obj["enableTsc"] = enableTsc
72        obj["perCoreTracing"] = perCoreTracing
73
74        configuration = lldb.SBStructuredData()
75        configuration.SetFromJSON(json.dumps(obj))
76        return configuration
77
78    def traceStartThread(self, thread=None, error=False, substrs=None,
79                         traceBufferSize=None, enableTsc=False, psbPeriod=None):
80        if self.USE_SB_API:
81            trace = self.getTraceOrCreate()
82            thread = thread if thread is not None else self.thread()
83            configuration = self.createConfiguration(
84                traceBufferSize=traceBufferSize, enableTsc=enableTsc,
85                psbPeriod=psbPeriod)
86            self.assertSBError(trace.Start(thread, configuration), error)
87        else:
88            command = "thread trace start"
89            if thread is not None:
90                command += " " + str(thread.GetIndexID())
91            if traceBufferSize is not None:
92                command += " -s " + str(traceBufferSize)
93            if enableTsc:
94                command += " --tsc"
95            if psbPeriod is not None:
96                command += " --psb-period " + str(psbPeriod)
97            self.expect(command, error=error, substrs=substrs)
98
99    def traceStartProcess(self, processBufferSizeLimit=None, error=False,
100                          substrs=None, enableTsc=False, psbPeriod=None,
101                          perCoreTracing=False):
102        if self.USE_SB_API:
103            trace = self.getTraceOrCreate()
104            configuration = self.createConfiguration(
105                processBufferSizeLimit=processBufferSizeLimit, enableTsc=enableTsc,
106                psbPeriod=psbPeriod, perCoreTracing=perCoreTracing)
107            self.assertSBError(trace.Start(configuration), error=error)
108        else:
109            command = "process trace start"
110            if processBufferSizeLimit != None:
111                command += " -l " + str(processBufferSizeLimit)
112            if enableTsc:
113                command += " --tsc"
114            if psbPeriod is not None:
115                command += " --psb-period " + str(psbPeriod)
116            if perCoreTracing:
117                command += " --per-core-tracing"
118            self.expect(command, error=error, substrs=substrs)
119
120    def traceStopProcess(self):
121        if self.USE_SB_API:
122            self.assertSuccess(self.target().GetTrace().Stop())
123        else:
124            self.expect("process trace stop")
125
126    def traceStopThread(self, thread=None, error=False, substrs=None):
127        if self.USE_SB_API:
128            thread = thread if thread is not None else self.thread()
129            self.assertSBError(self.target().GetTrace().Stop(thread), error)
130
131        else:
132            command = "thread trace stop"
133            if thread is not None:
134                command += " " + str(thread.GetIndexID())
135            self.expect(command, error=error, substrs=substrs)
136