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 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185
|
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)
|