1import lldb 2from intelpt_testcase import * 3from lldbsuite.test.lldbtest import * 4from lldbsuite.test import lldbutil 5from lldbsuite.test.decorators import * 6 7class TestTraceTimestampCounters(TraceIntelPTTestCaseBase): 8 9 @testSBAPIAndCommands 10 @skipIf(oslist=no_match(['linux']), archs=no_match(['i386', 'x86_64'])) 11 def testTscPerThread(self): 12 self.expect("file " + os.path.join(self.getSourceDir(), "intelpt-trace", "a.out")) 13 self.expect("b main") 14 self.expect("r") 15 16 self.traceStartThread(enableTsc=True) 17 18 self.expect("n") 19 self.expect("thread trace dump instructions -t -c 1", 20 patterns=[": \[\d+.\d+ ns\] 0x0000000000400511 movl"]) 21 22 @testSBAPIAndCommands 23 @skipIf(oslist=no_match(['linux']), archs=no_match(['i386', 'x86_64'])) 24 def testMultipleTscsPerThread(self): 25 self.expect("file " + os.path.join(self.getSourceDir(), "intelpt-trace", "a.out")) 26 self.expect("b main") 27 self.expect("r") 28 29 self.traceStartThread(enableTsc=True) 30 31 # After each stop there'll be a new TSC 32 self.expect("si") 33 self.expect("si") 34 self.expect("si") 35 36 # We'll get the most recent instructions, with at least 3 different TSCs 37 self.runCmd("thread trace dump instructions -t --raw --forward") 38 id_to_timestamp = {} 39 for line in self.res.GetOutput().splitlines(): 40 m = re.search(" (.+): \[(.+)\ ns].*", line) 41 if m: 42 id_to_timestamp[int(m.group(1))] = m.group(2) 43 self.assertEqual(len(id_to_timestamp), 3) 44 45 # We check that the values are right when dumping a specific id 46 for id, timestamp in id_to_timestamp.items(): 47 self.expect(f"thread trace dump instructions -t --id {id} -c 1", 48 substrs=[f"{id}: [{timestamp} ns]"]) 49 50 @testSBAPIAndCommands 51 @skipIf(oslist=no_match(['linux']), archs=no_match(['i386', 'x86_64'])) 52 def testTscPerProcess(self): 53 self.expect("file " + os.path.join(self.getSourceDir(), "intelpt-trace", "a.out")) 54 self.expect("b main") 55 self.expect("r") 56 57 self.traceStartProcess(enableTsc=True) 58 59 self.expect("n") 60 self.expect("thread trace dump instructions -t -c 1", 61 patterns=[": \[\d+.\d+ ns\] 0x0000000000400511 movl"]) 62 63 self.expect("thread trace dump instructions -t -c 1 --pretty-json", 64 patterns=['''"timestamp_ns": "\d+.\d+"''']) 65 66 @testSBAPIAndCommands 67 @skipIf(oslist=no_match(['linux']), archs=no_match(['i386', 'x86_64'])) 68 def testDumpingAfterTracingWithoutTsc(self): 69 self.expect("file " + os.path.join(self.getSourceDir(), "intelpt-trace", "a.out")) 70 self.expect("b main") 71 self.expect("r") 72 73 self.traceStartThread(enableTsc=False) 74 75 self.expect("n") 76 self.expect("thread trace dump instructions -t -c 1", 77 patterns=[": \[unavailable\] 0x0000000000400511 movl"]) 78 79 self.expect("thread trace dump instructions -t -c 1 --json", 80 substrs=['''"timestamp_ns":null''']) 81 82 @testSBAPIAndCommands 83 @skipIf(oslist=no_match(['linux']), archs=no_match(['i386', 'x86_64'])) 84 def testPSBPeriod(self): 85 def isPSBSupported(): 86 caps_file = "/sys/bus/event_source/devices/intel_pt/caps/psb_cyc" 87 if not os.path.exists(caps_file): 88 return False 89 with open(caps_file, "r") as f: 90 val = int(f.readline()) 91 if val != 1: 92 return False 93 return True 94 95 def getValidPSBValues(): 96 values_file = "/sys/bus/event_source/devices/intel_pt/caps/psb_periods" 97 values = [] 98 with open(values_file, "r") as f: 99 mask = int(f.readline(), 16) 100 for i in range(0, 32): 101 if (1 << i) & mask: 102 values.append(i) 103 return values 104 105 106 if not isPSBSupported(): 107 self.skipTest("PSB period unsupported") 108 109 valid_psb_values = getValidPSBValues() 110 # 0 should always be valid, and it's assumed by lldb-server 111 self.assertEqual(valid_psb_values[0], 0) 112 113 self.expect("file " + (os.path.join(self.getSourceDir(), "intelpt-trace", "a.out"))) 114 self.expect("b main") 115 self.expect("r") 116 117 # it's enough to test with two valid values 118 for psb_period in (valid_psb_values[0], valid_psb_values[-1]): 119 # we first test at thread level 120 self.traceStartThread(psbPeriod=psb_period) 121 self.traceStopThread() 122 123 # we now test at process level 124 self.traceStartProcess(psbPeriod=psb_period) 125 self.traceStopProcess() 126 127 # we now test invalid values 128 self.traceStartThread(psbPeriod=valid_psb_values[-1] + 1, error=True, 129 substrs=["Invalid psb_period. Valid values are: 0"]) 130 131 # TODO: dump the perf_event_attr.config as part of the upcoming "trace dump info" 132 # command and check that the psb period is included there. 133