import lldb from intelpt_testcase import * from lldbsuite.test.lldbtest import * from lldbsuite.test import lldbutil from lldbsuite.test.decorators import * class TestTraceTimestampCounters(TraceIntelPTTestCaseBase): @testSBAPIAndCommands @skipIf(oslist=no_match(["linux"]), archs=no_match(["i386", "x86_64"])) def testTscPerThread(self): self.expect( "file " + os.path.join(self.getSourceDir(), "intelpt-trace", "a.out") ) self.expect("b main") self.expect("r") self.traceStartThread(enableTsc=True) self.expect("n") self.expect( "thread trace dump instructions -t -c 1", patterns=[": \[\d+.\d+ ns\] 0x0000000000400511 movl"], ) @testSBAPIAndCommands @skipIf(oslist=no_match(["linux"]), archs=no_match(["i386", "x86_64"])) def testMultipleTscsPerThread(self): self.expect( "file " + os.path.join(self.getSourceDir(), "intelpt-trace", "a.out") ) self.expect("b main") self.expect("r") self.traceStartThread(enableTsc=True) # After each stop there'll be a new TSC self.expect("si") self.expect("si") self.expect("si") # We'll get the most recent instructions, with at least 3 different TSCs self.runCmd("thread trace dump instructions -t --raw --forward") id_to_timestamp = {} for line in self.res.GetOutput().splitlines(): m = re.search(" (.+): \[(.+)\ ns].*", line) if m: id_to_timestamp[int(m.group(1))] = m.group(2) self.assertEqual(len(id_to_timestamp), 3) # We check that the values are right when dumping a specific id for id, timestamp in id_to_timestamp.items(): self.expect( f"thread trace dump instructions -t --id {id} -c 1", substrs=[f"{id}: [{timestamp} ns]"], ) @testSBAPIAndCommands @skipIf(oslist=no_match(["linux"]), archs=no_match(["i386", "x86_64"])) def testTscPerProcess(self): self.expect( "file " + os.path.join(self.getSourceDir(), "intelpt-trace", "a.out") ) self.expect("b main") self.expect("r") self.traceStartProcess(enableTsc=True) self.expect("n") self.expect( "thread trace dump instructions -t -c 1", patterns=[": \[\d+.\d+ ns\] 0x0000000000400511 movl"], ) self.expect( "thread trace dump instructions -t -c 1 --pretty-json", patterns=['''"timestamp_ns": "\d+.\d+"'''], ) @testSBAPIAndCommands @skipIf(oslist=no_match(["linux"]), archs=no_match(["i386", "x86_64"])) def testDumpingAfterTracingWithoutTsc(self): self.expect( "file " + os.path.join(self.getSourceDir(), "intelpt-trace", "a.out") ) self.expect("b main") self.expect("r") self.traceStartThread(enableTsc=False) self.expect("n") self.expect( "thread trace dump instructions -t -c 1", patterns=[": \[unavailable\] 0x0000000000400511 movl"], ) self.expect( "thread trace dump instructions -t -c 1 --json", substrs=[""""timestamp_ns":null"""], ) @testSBAPIAndCommands @skipIf(oslist=no_match(["linux"]), archs=no_match(["i386", "x86_64"])) def testPSBPeriod(self): def isPSBSupported(): caps_file = "/sys/bus/event_source/devices/intel_pt/caps/psb_cyc" if not os.path.exists(caps_file): return False with open(caps_file, "r") as f: val = int(f.readline()) if val != 1: return False return True def getValidPSBValues(): values_file = "/sys/bus/event_source/devices/intel_pt/caps/psb_periods" values = [] with open(values_file, "r") as f: mask = int(f.readline(), 16) for i in range(0, 32): if (1 << i) & mask: values.append(i) return values if not isPSBSupported(): self.skipTest("PSB period unsupported") valid_psb_values = getValidPSBValues() # 0 should always be valid, and it's assumed by lldb-server self.assertEqual(valid_psb_values[0], 0) self.expect( "file " + (os.path.join(self.getSourceDir(), "intelpt-trace", "a.out")) ) self.expect("b main") self.expect("r") # it's enough to test with two valid values for psb_period in (valid_psb_values[0], valid_psb_values[-1]): # we first test at thread level self.traceStartThread(psbPeriod=psb_period) self.traceStopThread() # we now test at process level self.traceStartProcess(psbPeriod=psb_period) self.traceStopProcess() # we now test invalid values self.traceStartThread( psbPeriod=valid_psb_values[-1] + 1, error=True, substrs=["Invalid psb_period. Valid values are: 0"], ) # TODO: dump the perf_event_attr.config as part of the upcoming "trace dump info" # command and check that the psb period is included there.