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
|
import lldb
from intelpt_testcase import *
from lldbsuite.test.lldbtest import *
from lldbsuite.test import lldbutil
from lldbsuite.test.decorators import *
@skipIfNoIntelPT
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=[r": \[\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(r" (.+): \[(.+)\ 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=[r": \[\d+.\d+ ns\] 0x0000000000400511 movl"],
)
self.expect(
"thread trace dump instructions -t -c 1 --pretty-json",
patterns=[r'''"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=[r": \[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.
|