193 lines · python
1from lldbsuite.test.lldbtest import *2import os3import time4import json5 6ADDRESS_REGEX = "0x[0-9a-fA-F]*"7 8 9# Decorator that runs a test with both modes of USE_SB_API.10# It assumes that no tests can be executed in parallel.11def testSBAPIAndCommands(func):12 def wrapper(*args, **kwargs):13 TraceIntelPTTestCaseBase.USE_SB_API = True14 func(*args, **kwargs)15 TraceIntelPTTestCaseBase.USE_SB_API = False16 func(*args, **kwargs)17 18 return wrapper19 20 21def skipIfNoIntelPT(func):22 """Skip tests if the system does not support tracing."""23 24 supported = os.path.exists("/sys/bus/event_source/devices/intel_pt/type")25 return unittest.skipIf(not supported, "intel-pt tracing is unsupported")(func)26 27 28# Class that should be used by all python Intel PT tests.29#30# It has a handy check that skips the test if the intel-pt plugin is not enabled.31#32# It also contains many functions that can test both the SB API or the command line version33# of the most important tracing actions.34class TraceIntelPTTestCaseBase(TestBase):35 NO_DEBUG_INFO_TESTCASE = True36 37 # If True, the trace test methods will use the SB API, otherwise they'll use raw commands.38 USE_SB_API = False39 40 def setUp(self):41 TestBase.setUp(self)42 if "intel-pt" not in configuration.enabled_plugins:43 self.skipTest("The intel-pt test plugin is not enabled")44 45 def skipIfPerCpuTracingIsNotSupported(self):46 def is_supported():47 try:48 with open("/proc/sys/kernel/perf_event_paranoid", "r") as permissions:49 value = int(permissions.readlines()[0])50 if value <= 0:51 return True52 except:53 return False54 55 if not is_supported():56 self.skipTest(57 "Per cpu tracing is not supported. You need "58 "/proc/sys/kernel/perf_event_paranoid to be 0 or -1. "59 "You can use `sudo sysctl -w kernel.perf_event_paranoid=-1` for that."60 )61 62 def getTraceOrCreate(self):63 if not self.target().GetTrace().IsValid():64 error = lldb.SBError()65 self.target().CreateTrace(error)66 return self.target().GetTrace()67 68 def assertSBError(self, sberror, error=False):69 if error:70 self.assertTrue(sberror.Fail())71 else:72 self.assertSuccess(sberror)73 74 def createConfiguration(75 self,76 iptTraceSize=None,77 processBufferSizeLimit=None,78 enableTsc=False,79 psbPeriod=None,80 perCpuTracing=False,81 ):82 obj = {}83 if processBufferSizeLimit is not None:84 obj["processBufferSizeLimit"] = processBufferSizeLimit85 if iptTraceSize is not None:86 obj["iptTraceSize"] = iptTraceSize87 if psbPeriod is not None:88 obj["psbPeriod"] = psbPeriod89 obj["enableTsc"] = enableTsc90 obj["perCpuTracing"] = perCpuTracing91 92 configuration = lldb.SBStructuredData()93 configuration.SetFromJSON(json.dumps(obj))94 return configuration95 96 def traceStartThread(97 self,98 thread=None,99 error=False,100 substrs=None,101 iptTraceSize=None,102 enableTsc=False,103 psbPeriod=None,104 ):105 if self.USE_SB_API:106 trace = self.getTraceOrCreate()107 thread = thread if thread is not None else self.thread()108 configuration = self.createConfiguration(109 iptTraceSize=iptTraceSize, enableTsc=enableTsc, psbPeriod=psbPeriod110 )111 self.assertSBError(trace.Start(thread, configuration), error)112 else:113 command = "thread trace start"114 if thread is not None:115 command += " " + str(thread.GetIndexID())116 if iptTraceSize is not None:117 command += " -s " + str(iptTraceSize)118 if enableTsc:119 command += " --tsc"120 if psbPeriod is not None:121 command += " --psb-period " + str(psbPeriod)122 self.expect(command, error=error, substrs=substrs)123 124 def traceStartProcess(125 self,126 processBufferSizeLimit=None,127 error=False,128 substrs=None,129 enableTsc=False,130 psbPeriod=None,131 perCpuTracing=False,132 ):133 if self.USE_SB_API:134 trace = self.getTraceOrCreate()135 configuration = self.createConfiguration(136 processBufferSizeLimit=processBufferSizeLimit,137 enableTsc=enableTsc,138 psbPeriod=psbPeriod,139 perCpuTracing=perCpuTracing,140 )141 self.assertSBError(trace.Start(configuration), error=error)142 else:143 command = "process trace start"144 if processBufferSizeLimit is not None:145 command += " -l " + str(processBufferSizeLimit)146 if enableTsc:147 command += " --tsc"148 if psbPeriod is not None:149 command += " --psb-period " + str(psbPeriod)150 if perCpuTracing:151 command += " --per-cpu-tracing"152 self.expect(command, error=error, substrs=substrs)153 154 def traceStopProcess(self):155 if self.USE_SB_API:156 self.assertSuccess(self.target().GetTrace().Stop())157 else:158 self.expect("process trace stop")159 160 def traceStopThread(self, thread=None, error=False, substrs=None):161 if self.USE_SB_API:162 thread = thread if thread is not None else self.thread()163 self.assertSBError(self.target().GetTrace().Stop(thread), error)164 165 else:166 command = "thread trace stop"167 if thread is not None:168 command += " " + str(thread.GetIndexID())169 self.expect(command, error=error, substrs=substrs)170 171 def traceLoad(self, traceDescriptionFilePath, error=False, substrs=None):172 if self.USE_SB_API:173 traceDescriptionFile = lldb.SBFileSpec(traceDescriptionFilePath, True)174 loadTraceError = lldb.SBError()175 self.dbg.LoadTraceFromFile(loadTraceError, traceDescriptionFile)176 self.assertSBError(loadTraceError, error)177 else:178 command = f"trace load -v {traceDescriptionFilePath}"179 self.expect(command, error=error, substrs=substrs)180 181 def traceSave(self, traceBundleDir, compact=False, error=False, substrs=None):182 if self.USE_SB_API:183 save_error = lldb.SBError()184 self.target().GetTrace().SaveToDisk(185 save_error, lldb.SBFileSpec(traceBundleDir), compact186 )187 self.assertSBError(save_error, error)188 else:189 command = f"trace save {traceBundleDir}"190 if compact:191 command += " -c"192 self.expect(command, error=error, substrs=substrs)193