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