1 // Copyright 2015 The Chromium OS Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "sample_info_reader.h"
6
7 #include <byteswap.h>
8
9 #include "compat/test.h"
10 #include "kernel/perf_event.h"
11 #include "kernel/perf_internals.h"
12 #include "test_perf_data.h"
13 #include "test_utils.h"
14
15 namespace quipper {
16
17 using testing::PunU32U64;
18
TEST(SampleInfoReaderTest,ReadSampleEvent)19 TEST(SampleInfoReaderTest, ReadSampleEvent) {
20 // clang-format off
21 uint64_t sample_type = // * == in sample_id_all
22 PERF_SAMPLE_IP |
23 PERF_SAMPLE_TID | // *
24 PERF_SAMPLE_TIME | // *
25 PERF_SAMPLE_ADDR |
26 PERF_SAMPLE_ID | // *
27 PERF_SAMPLE_STREAM_ID | // *
28 PERF_SAMPLE_CPU | // *
29 PERF_SAMPLE_PERIOD |
30 PERF_SAMPLE_WEIGHT |
31 PERF_SAMPLE_DATA_SRC |
32 PERF_SAMPLE_TRANSACTION;
33 // clang-format on
34 struct perf_event_attr attr = {0};
35 attr.sample_type = sample_type;
36
37 SampleInfoReader reader(attr, false /* read_cross_endian */);
38
39 const u64 sample_event_array[] = {
40 0xffffffff01234567, // IP
41 PunU32U64{.v32 = {0x68d, 0x68e}}.v64, // TID (u32 pid, tid)
42 1415837014 * 1000000000ULL, // TIME
43 0x00007f999c38d15a, // ADDR
44 2, // ID
45 1, // STREAM_ID
46 8, // CPU
47 10001, // PERIOD
48 12345, // WEIGHT
49 0x68100142, // DATA_SRC
50 67890, // TRANSACTIONS
51 };
52 const sample_event sample_event_struct = {
53 .header = {
54 .type = PERF_RECORD_SAMPLE,
55 .misc = 0,
56 .size = sizeof(sample_event) + sizeof(sample_event_array),
57 }};
58
59 std::stringstream input;
60 input.write(reinterpret_cast<const char*>(&sample_event_struct),
61 sizeof(sample_event_struct));
62 input.write(reinterpret_cast<const char*>(sample_event_array),
63 sizeof(sample_event_array));
64 string input_string = input.str();
65 const event_t& event = *reinterpret_cast<const event_t*>(input_string.data());
66
67 perf_sample sample;
68 ASSERT_TRUE(reader.ReadPerfSampleInfo(event, &sample));
69
70 EXPECT_EQ(0xffffffff01234567, sample.ip);
71 EXPECT_EQ(0x68d, sample.pid);
72 EXPECT_EQ(0x68e, sample.tid);
73 EXPECT_EQ(1415837014 * 1000000000ULL, sample.time);
74 EXPECT_EQ(0x00007f999c38d15a, sample.addr);
75 EXPECT_EQ(2, sample.id);
76 EXPECT_EQ(1, sample.stream_id);
77 EXPECT_EQ(8, sample.cpu);
78 EXPECT_EQ(10001, sample.period);
79 EXPECT_EQ(12345, sample.weight);
80 EXPECT_EQ(0x68100142, sample.data_src);
81 EXPECT_EQ(67890, sample.transaction);
82 }
83
TEST(SampleInfoReaderTest,ReadSampleEventCrossEndian)84 TEST(SampleInfoReaderTest, ReadSampleEventCrossEndian) {
85 // clang-format off
86 uint64_t sample_type = // * == in sample_id_all
87 PERF_SAMPLE_IP |
88 PERF_SAMPLE_TID | // *
89 PERF_SAMPLE_TIME | // *
90 PERF_SAMPLE_ADDR |
91 PERF_SAMPLE_ID | // *
92 PERF_SAMPLE_STREAM_ID | // *
93 PERF_SAMPLE_CPU | // *
94 PERF_SAMPLE_PERIOD;
95 // clang-format on
96 struct perf_event_attr attr = {0};
97 attr.sample_type = sample_type;
98
99 SampleInfoReader reader(attr, true /* read_cross_endian */);
100
101 const u64 sample_event_array[] = {
102 0xffffffff01234567, // IP
103 PunU32U64{.v32 = {0x68d, 0x68e}}.v64, // TID (u32 pid, tid)
104 1415837014 * 1000000000ULL, // TIME
105 0x00007f999c38d15a, // ADDR
106 2, // ID
107 1, // STREAM_ID
108 8, // CPU
109 10001, // PERIOD
110 };
111
112 const sample_event sample_event_struct = {
113 .header = {
114 .type = PERF_RECORD_SAMPLE,
115 .misc = 0,
116 .size = sizeof(sample_event) + sizeof(sample_event_array),
117 }};
118
119 std::stringstream input;
120 input.write(reinterpret_cast<const char*>(&sample_event_struct),
121 sizeof(sample_event_struct));
122 input.write(reinterpret_cast<const char*>(sample_event_array),
123 sizeof(sample_event_array));
124 string input_string = input.str();
125 const event_t& event = *reinterpret_cast<const event_t*>(input_string.data());
126
127 perf_sample sample;
128 ASSERT_TRUE(reader.ReadPerfSampleInfo(event, &sample));
129
130 EXPECT_EQ(bswap_64(0xffffffff01234567), sample.ip);
131 EXPECT_EQ(bswap_32(0x68d), sample.pid); // 32-bit
132 EXPECT_EQ(bswap_32(0x68e), sample.tid); // 32-bit
133 EXPECT_EQ(bswap_64(1415837014 * 1000000000ULL), sample.time);
134 EXPECT_EQ(bswap_64(0x00007f999c38d15a), sample.addr);
135 EXPECT_EQ(bswap_64(2), sample.id);
136 EXPECT_EQ(bswap_64(1), sample.stream_id);
137 EXPECT_EQ(bswap_32(8), sample.cpu); // 32-bit
138 EXPECT_EQ(bswap_64(10001), sample.period);
139 }
140
TEST(SampleInfoReaderTest,ReadMmapEvent)141 TEST(SampleInfoReaderTest, ReadMmapEvent) {
142 // clang-format off
143 uint64_t sample_type = // * == in sample_id_all
144 PERF_SAMPLE_IP |
145 PERF_SAMPLE_TID | // *
146 PERF_SAMPLE_TIME | // *
147 PERF_SAMPLE_ADDR |
148 PERF_SAMPLE_ID | // *
149 PERF_SAMPLE_STREAM_ID | // *
150 PERF_SAMPLE_CPU | // *
151 PERF_SAMPLE_PERIOD;
152 // clang-format on
153 struct perf_event_attr attr = {0};
154 attr.sample_type = sample_type;
155 attr.sample_id_all = true;
156
157 SampleInfoReader reader(attr, false /* read_cross_endian */);
158
159 // PERF_RECORD_MMAP
160 ASSERT_EQ(40, offsetof(struct mmap_event, filename));
161 const u64 mmap_sample_id[] = {
162 PunU32U64{.v32 = {0x68d, 0x68e}}.v64, // TID (u32 pid, tid)
163 1415911367 * 1000000000ULL, // TIME
164 3, // ID
165 2, // STREAM_ID
166 9, // CPU
167 };
168 // clang-format off
169 const size_t mmap_event_size =
170 offsetof(struct mmap_event, filename) +
171 10+6 /* ==16, nearest 64-bit boundary for filename */ +
172 sizeof(mmap_sample_id);
173 // clang-format on
174
175 const char mmap_filename[10 + 6] = "/dev/zero";
176 struct mmap_event written_mmap_event = {
177 .header =
178 {
179 .type = PERF_RECORD_MMAP,
180 .misc = 0,
181 .size = mmap_event_size,
182 },
183 .pid = 0x68d,
184 .tid = 0x68d,
185 .start = 0x1d000,
186 .len = 0x1000,
187 .pgoff = 0,
188 // .filename = ..., // written separately
189 };
190
191 std::stringstream input;
192 input.write(reinterpret_cast<const char*>(&written_mmap_event),
193 offsetof(struct mmap_event, filename));
194 input.write(mmap_filename, 10 + 6);
195 input.write(reinterpret_cast<const char*>(mmap_sample_id),
196 sizeof(mmap_sample_id));
197
198 string input_string = input.str();
199 const event_t& event = *reinterpret_cast<const event_t*>(input_string.data());
200
201 perf_sample sample;
202 ASSERT_TRUE(reader.ReadPerfSampleInfo(event, &sample));
203
204 EXPECT_EQ(0x68d, sample.pid);
205 EXPECT_EQ(0x68e, sample.tid);
206 EXPECT_EQ(1415911367 * 1000000000ULL, sample.time);
207 EXPECT_EQ(3, sample.id);
208 EXPECT_EQ(2, sample.stream_id);
209 EXPECT_EQ(9, sample.cpu);
210 }
211
TEST(SampleInfoReaderTest,ReadReadInfoAllFields)212 TEST(SampleInfoReaderTest, ReadReadInfoAllFields) {
213 struct perf_event_attr attr = {0};
214 attr.sample_type = PERF_SAMPLE_IP | PERF_SAMPLE_TID | PERF_SAMPLE_READ;
215 attr.read_format = PERF_FORMAT_TOTAL_TIME_ENABLED |
216 PERF_FORMAT_TOTAL_TIME_RUNNING | PERF_FORMAT_ID;
217
218 SampleInfoReader reader(attr, false /* read_cross_endian */);
219
220 // PERF_RECORD_SAMPLE
221 const u64 sample_event_array[] = {
222 0xffffffff01234567, // IP
223 PunU32U64{.v32 = {0x68d, 0x68e}}.v64, // TID (u32 pid, tid)
224 // From kernel/perf_event.h:
225 // struct read_format {
226 // { u64 value;
227 // { u64 time_enabled; } && PERF_FORMAT_TOTAL_TIME_ENABLED
228 // { u64 time_running; } && PERF_FORMAT_TOTAL_TIME_RUNNING
229 // { u64 id; } && PERF_FORMAT_ID
230 // } && !PERF_FORMAT_GROUP
231 // };
232 1000000, // READ: value
233 1415837014 * 1000000000ULL, // READ: time_enabled
234 1234567890 * 1000000000ULL, // READ: time_running
235 0xabcdef, // READ: id
236 };
237 sample_event sample_event_struct = {
238 .header = {
239 .type = PERF_RECORD_SAMPLE,
240 .misc = 0,
241 .size = sizeof(sample_event) + sizeof(sample_event_array),
242 }};
243
244 std::stringstream input;
245 input.write(reinterpret_cast<const char*>(&sample_event_struct),
246 sizeof(sample_event_struct));
247 input.write(reinterpret_cast<const char*>(sample_event_array),
248 sizeof(sample_event_array));
249 string input_string = input.str();
250 const event_t& event = *reinterpret_cast<const event_t*>(input_string.data());
251
252 perf_sample sample;
253 ASSERT_TRUE(reader.ReadPerfSampleInfo(event, &sample));
254
255 EXPECT_EQ(0xffffffff01234567, sample.ip);
256 EXPECT_EQ(0x68d, sample.pid);
257 EXPECT_EQ(0x68e, sample.tid);
258 EXPECT_EQ(1415837014 * 1000000000ULL, sample.read.time_enabled);
259 EXPECT_EQ(1234567890 * 1000000000ULL, sample.read.time_running);
260 EXPECT_EQ(0xabcdef, sample.read.one.id);
261 EXPECT_EQ(1000000, sample.read.one.value);
262 }
263
TEST(SampleInfoReaderTest,ReadReadInfoOmitTotalTimeFields)264 TEST(SampleInfoReaderTest, ReadReadInfoOmitTotalTimeFields) {
265 struct perf_event_attr attr = {0};
266 attr.sample_type = PERF_SAMPLE_IP | PERF_SAMPLE_TID | PERF_SAMPLE_READ;
267 // Omit the PERF_FORMAT_TOTAL_TIME_* fields.
268 attr.read_format = PERF_FORMAT_ID;
269
270 SampleInfoReader reader(attr, false /* read_cross_endian */);
271
272 // PERF_RECORD_SAMPLE
273 const u64 sample_event_array[] = {
274 0xffffffff01234567, // IP
275 PunU32U64{.v32 = {0x68d, 0x68e}}.v64, // TID (u32 pid, tid)
276 1000000, // READ: value
277 0xabcdef, // READ: id
278 };
279 sample_event sample_event_struct = {
280 .header = {
281 .type = PERF_RECORD_SAMPLE,
282 .misc = 0,
283 .size = sizeof(sample_event) + sizeof(sample_event_array),
284 }};
285
286 std::stringstream input;
287 input.write(reinterpret_cast<const char*>(&sample_event_struct),
288 sizeof(sample_event_struct));
289 input.write(reinterpret_cast<const char*>(sample_event_array),
290 sizeof(sample_event_array));
291 string input_string = input.str();
292 const event_t& event = *reinterpret_cast<const event_t*>(input_string.data());
293
294 perf_sample sample;
295 ASSERT_TRUE(reader.ReadPerfSampleInfo(event, &sample));
296
297 EXPECT_EQ(0xffffffff01234567, sample.ip);
298 EXPECT_EQ(0x68d, sample.pid);
299 EXPECT_EQ(0x68e, sample.tid);
300 EXPECT_EQ(0xabcdef, sample.read.one.id);
301 EXPECT_EQ(1000000, sample.read.one.value);
302 }
303
TEST(SampleInfoReaderTest,ReadReadInfoValueFieldOnly)304 TEST(SampleInfoReaderTest, ReadReadInfoValueFieldOnly) {
305 struct perf_event_attr attr = {0};
306 attr.sample_type = PERF_SAMPLE_IP | PERF_SAMPLE_TID | PERF_SAMPLE_READ;
307 // Omit all optional fields. The |value| field still remains.
308 attr.read_format = 0;
309
310 SampleInfoReader reader(attr, false /* read_cross_endian */);
311
312 // PERF_RECORD_SAMPLE
313 const u64 sample_event_array[] = {
314 0xffffffff01234567, // IP
315 PunU32U64{.v32 = {0x68d, 0x68e}}.v64, // TID (u32 pid, tid)
316 1000000, // READ: value
317 };
318 sample_event sample_event_struct = {
319 .header = {
320 .type = PERF_RECORD_SAMPLE,
321 .misc = 0,
322 .size = sizeof(sample_event) + sizeof(sample_event_array),
323 }};
324
325 std::stringstream input;
326 input.write(reinterpret_cast<const char*>(&sample_event_struct),
327 sizeof(sample_event_struct));
328 input.write(reinterpret_cast<const char*>(sample_event_array),
329 sizeof(sample_event_array));
330 string input_string = input.str();
331 const event_t& event = *reinterpret_cast<const event_t*>(input_string.data());
332
333 perf_sample sample;
334 ASSERT_TRUE(reader.ReadPerfSampleInfo(event, &sample));
335
336 EXPECT_EQ(0xffffffff01234567, sample.ip);
337 EXPECT_EQ(0x68d, sample.pid);
338 EXPECT_EQ(0x68e, sample.tid);
339 EXPECT_EQ(1000000, sample.read.one.value);
340 }
341
TEST(SampleInfoReaderTest,ReadReadInfoWithGroups)342 TEST(SampleInfoReaderTest, ReadReadInfoWithGroups) {
343 struct perf_event_attr attr = {0};
344 attr.sample_type = PERF_SAMPLE_IP | PERF_SAMPLE_TID | PERF_SAMPLE_READ;
345 // Omit the PERF_FORMAT_TOTAL_TIME_* fields.
346 attr.read_format = PERF_FORMAT_ID | PERF_FORMAT_GROUP;
347
348 SampleInfoReader reader(attr, false /* read_cross_endian */);
349
350 // PERF_RECORD_SAMPLE
351 const u64 sample_event_array[] = {
352 0xffffffff01234567, // IP
353 PunU32U64{.v32 = {0x68d, 0x68e}}.v64, // TID (u32 pid, tid)
354 3, // READ: nr
355 1000000, // READ: values[0].value
356 0xabcdef, // READ: values[0].id
357 2000000, // READ: values[1].value
358 0xdecaf0, // READ: values[1].id
359 3000000, // READ: values[2].value
360 0xbeef00, // READ: values[2].id
361 };
362 sample_event sample_event_struct = {
363 .header = {
364 .type = PERF_RECORD_SAMPLE,
365 .misc = 0,
366 .size = sizeof(sample_event) + sizeof(sample_event_array),
367 }};
368
369 std::stringstream input;
370 input.write(reinterpret_cast<const char*>(&sample_event_struct),
371 sizeof(sample_event_struct));
372 input.write(reinterpret_cast<const char*>(sample_event_array),
373 sizeof(sample_event_array));
374 string input_string = input.str();
375 const event_t& event = *reinterpret_cast<const event_t*>(input_string.data());
376
377 perf_sample sample;
378 ASSERT_TRUE(reader.ReadPerfSampleInfo(event, &sample));
379
380 EXPECT_EQ(0xffffffff01234567, sample.ip);
381 EXPECT_EQ(0x68d, sample.pid);
382 EXPECT_EQ(0x68e, sample.tid);
383 EXPECT_EQ(3, sample.read.group.nr);
384 ASSERT_NE(static_cast<void*>(NULL), sample.read.group.values);
385 EXPECT_EQ(0xabcdef, sample.read.group.values[0].id);
386 EXPECT_EQ(1000000, sample.read.group.values[0].value);
387 EXPECT_EQ(0xdecaf0, sample.read.group.values[1].id);
388 EXPECT_EQ(2000000, sample.read.group.values[1].value);
389 EXPECT_EQ(0xbeef00, sample.read.group.values[2].id);
390 EXPECT_EQ(3000000, sample.read.group.values[2].value);
391 }
392
393 } // namespace quipper
394