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