1 // Copyright (c) 2012 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 "perf_serializer.h"
6
7 #include <stdint.h>
8 #include <stdio.h>
9 #include <sys/time.h>
10
11 #include <algorithm> // for std::copy
12
13 #include "base/logging.h"
14
15 #include "binary_data_utils.h"
16 #include "compat/proto.h"
17 #include "compat/string.h"
18 #include "kernel/perf_event.h"
19 #include "perf_data_structures.h"
20 #include "perf_data_utils.h"
21 #include "perf_parser.h"
22 #include "perf_reader.h"
23
24 namespace quipper {
25
PerfSerializer()26 PerfSerializer::PerfSerializer() {}
27
~PerfSerializer()28 PerfSerializer::~PerfSerializer() {}
29
SerializePerfFileAttr(const PerfFileAttr & perf_file_attr,PerfDataProto_PerfFileAttr * perf_file_attr_proto) const30 bool PerfSerializer::SerializePerfFileAttr(
31 const PerfFileAttr& perf_file_attr,
32 PerfDataProto_PerfFileAttr* perf_file_attr_proto) const {
33 if (!SerializePerfEventAttr(perf_file_attr.attr,
34 perf_file_attr_proto->mutable_attr())) {
35 return false;
36 }
37
38 for (size_t i = 0; i < perf_file_attr.ids.size(); i++)
39 perf_file_attr_proto->add_ids(perf_file_attr.ids[i]);
40 return true;
41 }
42
DeserializePerfFileAttr(const PerfDataProto_PerfFileAttr & perf_file_attr_proto,PerfFileAttr * perf_file_attr) const43 bool PerfSerializer::DeserializePerfFileAttr(
44 const PerfDataProto_PerfFileAttr& perf_file_attr_proto,
45 PerfFileAttr* perf_file_attr) const {
46 if (!DeserializePerfEventAttr(perf_file_attr_proto.attr(),
47 &perf_file_attr->attr)) {
48 return false;
49 }
50
51 for (int i = 0; i < perf_file_attr_proto.ids_size(); i++)
52 perf_file_attr->ids.push_back(perf_file_attr_proto.ids(i));
53 return true;
54 }
55
SerializePerfEventAttr(const perf_event_attr & perf_event_attr,PerfDataProto_PerfEventAttr * perf_event_attr_proto) const56 bool PerfSerializer::SerializePerfEventAttr(
57 const perf_event_attr& perf_event_attr,
58 PerfDataProto_PerfEventAttr* perf_event_attr_proto) const {
59 #define S(x) perf_event_attr_proto->set_##x(perf_event_attr.x)
60 S(type);
61 S(size);
62 S(config);
63 if (perf_event_attr_proto->freq())
64 S(sample_freq);
65 else
66 S(sample_period);
67 S(sample_type);
68 S(read_format);
69 S(disabled);
70 S(inherit);
71 S(pinned);
72 S(exclusive);
73 S(exclude_user);
74 S(exclude_kernel);
75 S(exclude_hv);
76 S(exclude_idle);
77 S(mmap);
78 S(comm);
79 S(freq);
80 S(inherit_stat);
81 S(enable_on_exec);
82 S(task);
83 S(watermark);
84 S(precise_ip);
85 S(mmap_data);
86 S(sample_id_all);
87 S(exclude_host);
88 S(exclude_guest);
89 S(exclude_callchain_kernel);
90 S(exclude_callchain_user);
91 S(mmap2);
92 S(comm_exec);
93 if (perf_event_attr_proto->watermark())
94 S(wakeup_watermark);
95 else
96 S(wakeup_events);
97 S(bp_type);
98 S(bp_addr);
99 S(bp_len);
100 S(branch_sample_type);
101 S(sample_regs_user);
102 S(sample_stack_user);
103 #undef S
104 return true;
105 }
106
DeserializePerfEventAttr(const PerfDataProto_PerfEventAttr & perf_event_attr_proto,perf_event_attr * perf_event_attr) const107 bool PerfSerializer::DeserializePerfEventAttr(
108 const PerfDataProto_PerfEventAttr& perf_event_attr_proto,
109 perf_event_attr* perf_event_attr) const {
110 memset(perf_event_attr, 0, sizeof(*perf_event_attr));
111 #define S(x) perf_event_attr->x = perf_event_attr_proto.x()
112 S(type);
113 S(size);
114 S(config);
115 if (perf_event_attr->freq)
116 S(sample_freq);
117 else
118 S(sample_period);
119 S(sample_type);
120 S(read_format);
121 S(disabled);
122 S(inherit);
123 S(pinned);
124 S(exclusive);
125 S(exclude_user);
126 S(exclude_kernel);
127 S(exclude_hv);
128 S(exclude_idle);
129 S(mmap);
130 S(comm);
131 S(freq);
132 S(inherit_stat);
133 S(enable_on_exec);
134 S(task);
135 S(watermark);
136 S(precise_ip);
137 S(mmap_data);
138 S(sample_id_all);
139 S(exclude_host);
140 S(exclude_guest);
141 S(exclude_callchain_kernel);
142 S(exclude_callchain_user);
143 S(mmap2);
144 S(comm_exec);
145 if (perf_event_attr->watermark)
146 S(wakeup_watermark);
147 else
148 S(wakeup_events);
149 S(bp_type);
150 S(bp_addr);
151 S(bp_len);
152 S(branch_sample_type);
153 S(sample_regs_user);
154 S(sample_stack_user);
155 #undef S
156 return true;
157 }
158
SerializePerfEventType(const PerfFileAttr & event_attr,quipper::PerfDataProto_PerfEventType * event_type_proto) const159 bool PerfSerializer::SerializePerfEventType(
160 const PerfFileAttr& event_attr,
161 quipper::PerfDataProto_PerfEventType* event_type_proto) const {
162 event_type_proto->set_id(event_attr.attr.config);
163 event_type_proto->set_name(event_attr.name);
164 event_type_proto->set_name_md5_prefix(Md5Prefix(event_attr.name));
165 return true;
166 }
167
DeserializePerfEventType(const quipper::PerfDataProto_PerfEventType & event_type_proto,PerfFileAttr * event_attr) const168 bool PerfSerializer::DeserializePerfEventType(
169 const quipper::PerfDataProto_PerfEventType& event_type_proto,
170 PerfFileAttr* event_attr) const {
171 // Attr should have already been deserialized.
172 if (event_attr->attr.config != event_type_proto.id()) {
173 LOG(ERROR) << "Event type ID " << event_type_proto.id()
174 << " does not match attr.config " << event_attr->attr.config
175 << ". Not deserializing the event name!";
176 return false;
177 }
178 event_attr->name = event_type_proto.name();
179 return true;
180 }
181
SerializeEvent(const malloced_unique_ptr<event_t> & event_ptr,PerfDataProto_PerfEvent * event_proto) const182 bool PerfSerializer::SerializeEvent(
183 const malloced_unique_ptr<event_t>& event_ptr,
184 PerfDataProto_PerfEvent* event_proto) const {
185 const event_t& event = *event_ptr;
186
187 if (!SerializeEventHeader(event.header, event_proto->mutable_header()))
188 return false;
189
190 if (event.header.type >= PERF_RECORD_USER_TYPE_START) {
191 if (!SerializeUserEvent(event, event_proto)) {
192 return false;
193 }
194 } else if (!SerializeKernelEvent(event, event_proto)) {
195 return false;
196 }
197
198 event_proto->set_timestamp(GetTimeFromPerfEvent(*event_proto));
199 return true;
200 }
201
SerializeKernelEvent(const event_t & event,PerfDataProto_PerfEvent * event_proto) const202 bool PerfSerializer::SerializeKernelEvent(
203 const event_t& event, PerfDataProto_PerfEvent* event_proto) const {
204 switch (event.header.type) {
205 case PERF_RECORD_SAMPLE:
206 return SerializeSampleEvent(event, event_proto->mutable_sample_event());
207 case PERF_RECORD_MMAP:
208 return SerializeMMapEvent(event, event_proto->mutable_mmap_event());
209 case PERF_RECORD_MMAP2:
210 return SerializeMMap2Event(event, event_proto->mutable_mmap_event());
211 case PERF_RECORD_COMM:
212 return SerializeCommEvent(event, event_proto->mutable_comm_event());
213 case PERF_RECORD_EXIT:
214 return SerializeForkExitEvent(event, event_proto->mutable_exit_event());
215 case PERF_RECORD_FORK:
216 return SerializeForkExitEvent(event, event_proto->mutable_fork_event());
217 case PERF_RECORD_LOST:
218 return SerializeLostEvent(event, event_proto->mutable_lost_event());
219 case PERF_RECORD_THROTTLE:
220 case PERF_RECORD_UNTHROTTLE:
221 return SerializeThrottleEvent(event,
222 event_proto->mutable_throttle_event());
223 case PERF_RECORD_READ:
224 return SerializeReadEvent(event, event_proto->mutable_read_event());
225 case PERF_RECORD_AUX:
226 return SerializeAuxEvent(event, event_proto->mutable_aux_event());
227 default:
228 LOG(ERROR) << "Unknown event type: " << event.header.type;
229 }
230 return true;
231 }
232
SerializeUserEvent(const event_t & event,PerfDataProto_PerfEvent * event_proto) const233 bool PerfSerializer::SerializeUserEvent(
234 const event_t& event, PerfDataProto_PerfEvent* event_proto) const {
235 switch (event.header.type) {
236 case PERF_RECORD_AUXTRACE:
237 return SerializeAuxtraceEvent(event,
238 event_proto->mutable_auxtrace_event());
239 default:
240 if (event.header.type >= PERF_RECORD_HEADER_MAX) {
241 LOG(ERROR) << "Unknown event type: " << event.header.type;
242 }
243 }
244 return true;
245 }
246
DeserializeEvent(const PerfDataProto_PerfEvent & event_proto,malloced_unique_ptr<event_t> * event_ptr) const247 bool PerfSerializer::DeserializeEvent(
248 const PerfDataProto_PerfEvent& event_proto,
249 malloced_unique_ptr<event_t>* event_ptr) const {
250 event_ptr->reset(CallocMemoryForEvent(event_proto.header().size()));
251 event_t* event = event_ptr->get();
252
253 if (!DeserializeEventHeader(event_proto.header(), &event->header))
254 return false;
255
256 bool event_deserialized = false;
257 if (event_proto.header().type() >= PERF_RECORD_USER_TYPE_START) {
258 event_deserialized = DeserializeUserEvent(event_proto, event);
259 } else {
260 event_deserialized = DeserializeKernelEvent(event_proto, event);
261 }
262
263 if (!event_deserialized) {
264 LOG(ERROR) << "Could not deserialize event of type "
265 << event_proto.header().type();
266 return false;
267 }
268
269 return true;
270 }
271
DeserializeKernelEvent(const PerfDataProto_PerfEvent & event_proto,event_t * event) const272 bool PerfSerializer::DeserializeKernelEvent(
273 const PerfDataProto_PerfEvent& event_proto, event_t* event) const {
274 switch (event_proto.header().type()) {
275 case PERF_RECORD_SAMPLE:
276 return DeserializeSampleEvent(event_proto.sample_event(), event);
277 case PERF_RECORD_MMAP:
278 return DeserializeMMapEvent(event_proto.mmap_event(), event);
279 case PERF_RECORD_MMAP2:
280 return DeserializeMMap2Event(event_proto.mmap_event(), event);
281 case PERF_RECORD_COMM:
282 return DeserializeCommEvent(event_proto.comm_event(), event);
283 case PERF_RECORD_EXIT:
284 return (event_proto.has_exit_event() &&
285 DeserializeForkExitEvent(event_proto.exit_event(), event)) ||
286 (event_proto.has_fork_event() &&
287 DeserializeForkExitEvent(event_proto.fork_event(), event));
288 // Some older protobufs use the |fork_event| field to store exit
289 // events.
290 case PERF_RECORD_FORK:
291 return DeserializeForkExitEvent(event_proto.fork_event(), event);
292 case PERF_RECORD_LOST:
293 return DeserializeLostEvent(event_proto.lost_event(), event);
294 case PERF_RECORD_THROTTLE:
295 case PERF_RECORD_UNTHROTTLE:
296 return DeserializeThrottleEvent(event_proto.throttle_event(), event);
297 case PERF_RECORD_READ:
298 return DeserializeReadEvent(event_proto.read_event(), event);
299 case PERF_RECORD_AUX:
300 return DeserializeAuxEvent(event_proto.aux_event(), event);
301 case PERF_RECORD_ITRACE_START:
302 case PERF_RECORD_LOST_SAMPLES:
303 case PERF_RECORD_SWITCH:
304 case PERF_RECORD_SWITCH_CPU_WIDE:
305 case PERF_RECORD_NAMESPACES:
306 LOG(ERROR) << "Event type: " << event_proto.header().type()
307 << ". Not yet supported.";
308 return true;
309 break;
310 }
311 return false;
312 }
313
DeserializeUserEvent(const PerfDataProto_PerfEvent & event_proto,event_t * event) const314 bool PerfSerializer::DeserializeUserEvent(
315 const PerfDataProto_PerfEvent& event_proto, event_t* event) const {
316 switch (event_proto.header().type()) {
317 case PERF_RECORD_AUXTRACE:
318 return DeserializeAuxtraceEvent(event_proto.auxtrace_event(), event);
319 default:
320 // User type events are marked as deserialized because they don't
321 // have non-header data in perf.data proto.
322 if (event_proto.header().type() >= PERF_RECORD_HEADER_MAX) {
323 return false;
324 }
325 }
326 return true;
327 }
328
SerializeEventHeader(const perf_event_header & header,PerfDataProto_EventHeader * header_proto) const329 bool PerfSerializer::SerializeEventHeader(
330 const perf_event_header& header,
331 PerfDataProto_EventHeader* header_proto) const {
332 header_proto->set_type(header.type);
333 header_proto->set_misc(header.misc);
334 header_proto->set_size(header.size);
335 return true;
336 }
337
DeserializeEventHeader(const PerfDataProto_EventHeader & header_proto,perf_event_header * header) const338 bool PerfSerializer::DeserializeEventHeader(
339 const PerfDataProto_EventHeader& header_proto,
340 perf_event_header* header) const {
341 header->type = header_proto.type();
342 header->misc = header_proto.misc();
343 header->size = header_proto.size();
344 return true;
345 }
346
SerializeSampleEvent(const event_t & event,PerfDataProto_SampleEvent * sample) const347 bool PerfSerializer::SerializeSampleEvent(
348 const event_t& event, PerfDataProto_SampleEvent* sample) const {
349 perf_sample sample_info;
350 uint64_t sample_type = 0;
351 if (!ReadPerfSampleInfoAndType(event, &sample_info, &sample_type))
352 return false;
353
354 if (sample_type & PERF_SAMPLE_IP) sample->set_ip(sample_info.ip);
355 if (sample_type & PERF_SAMPLE_TID) {
356 sample->set_pid(sample_info.pid);
357 sample->set_tid(sample_info.tid);
358 }
359 if (sample_type & PERF_SAMPLE_TIME)
360 sample->set_sample_time_ns(sample_info.time);
361 if (sample_type & PERF_SAMPLE_ADDR) sample->set_addr(sample_info.addr);
362 if ((sample_type & PERF_SAMPLE_ID) || (sample_type & PERF_SAMPLE_IDENTIFIER))
363 sample->set_id(sample_info.id);
364 if (sample_type & PERF_SAMPLE_STREAM_ID)
365 sample->set_stream_id(sample_info.stream_id);
366 if (sample_type & PERF_SAMPLE_CPU) sample->set_cpu(sample_info.cpu);
367 if (sample_type & PERF_SAMPLE_PERIOD) sample->set_period(sample_info.period);
368 if (sample_type & PERF_SAMPLE_RAW) sample->set_raw_size(sample_info.raw_size);
369 if (sample_type & PERF_SAMPLE_READ) {
370 const SampleInfoReader* reader = GetSampleInfoReaderForEvent(event);
371 if (reader) {
372 PerfDataProto_ReadInfo* read_info = sample->mutable_read_info();
373 if (reader->event_attr().read_format & PERF_FORMAT_TOTAL_TIME_ENABLED)
374 read_info->set_time_enabled(sample_info.read.time_enabled);
375 if (reader->event_attr().read_format & PERF_FORMAT_TOTAL_TIME_RUNNING)
376 read_info->set_time_running(sample_info.read.time_running);
377 if (reader->event_attr().read_format & PERF_FORMAT_GROUP) {
378 for (size_t i = 0; i < sample_info.read.group.nr; i++) {
379 auto read_value = read_info->add_read_value();
380 read_value->set_value(sample_info.read.group.values[i].value);
381 read_value->set_id(sample_info.read.group.values[i].id);
382 }
383 } else {
384 auto read_value = read_info->add_read_value();
385 read_value->set_value(sample_info.read.one.value);
386 read_value->set_id(sample_info.read.one.id);
387 }
388 }
389 }
390 if (sample_type & PERF_SAMPLE_CALLCHAIN) {
391 sample->mutable_callchain()->Reserve(sample_info.callchain->nr);
392 for (size_t i = 0; i < sample_info.callchain->nr; ++i)
393 sample->add_callchain(sample_info.callchain->ips[i]);
394 }
395 if (sample_type & PERF_SAMPLE_BRANCH_STACK) {
396 for (size_t i = 0; i < sample_info.branch_stack->nr; ++i) {
397 sample->add_branch_stack();
398 const struct branch_entry& entry = sample_info.branch_stack->entries[i];
399 sample->mutable_branch_stack(i)->set_from_ip(entry.from);
400 sample->mutable_branch_stack(i)->set_to_ip(entry.to);
401 sample->mutable_branch_stack(i)->set_mispredicted(entry.flags.mispred);
402 }
403 }
404
405 if (sample_type & PERF_SAMPLE_WEIGHT) sample->set_weight(sample_info.weight);
406 if (sample_type & PERF_SAMPLE_DATA_SRC)
407 sample->set_data_src(sample_info.data_src);
408 if (sample_type & PERF_SAMPLE_TRANSACTION)
409 sample->set_transaction(sample_info.transaction);
410
411 return true;
412 }
413
DeserializeSampleEvent(const PerfDataProto_SampleEvent & sample,event_t * event) const414 bool PerfSerializer::DeserializeSampleEvent(
415 const PerfDataProto_SampleEvent& sample, event_t* event) const {
416 perf_sample sample_info;
417 if (sample.has_ip()) sample_info.ip = sample.ip();
418 if (sample.has_pid()) {
419 CHECK(sample.has_tid()) << "Cannot have PID without TID.";
420 sample_info.pid = sample.pid();
421 sample_info.tid = sample.tid();
422 }
423 if (sample.has_sample_time_ns()) sample_info.time = sample.sample_time_ns();
424 if (sample.has_addr()) sample_info.addr = sample.addr();
425 if (sample.has_id()) sample_info.id = sample.id();
426 if (sample.has_stream_id()) sample_info.stream_id = sample.stream_id();
427 if (sample.has_cpu()) sample_info.cpu = sample.cpu();
428 if (sample.has_period()) sample_info.period = sample.period();
429 if (sample.has_read_info()) {
430 const SampleInfoReader* reader = GetSampleInfoReaderForEvent(*event);
431 if (reader) {
432 const PerfDataProto_ReadInfo& read_info = sample.read_info();
433 if (reader->event_attr().read_format & PERF_FORMAT_TOTAL_TIME_ENABLED)
434 sample_info.read.time_enabled = read_info.time_enabled();
435 if (reader->event_attr().read_format & PERF_FORMAT_TOTAL_TIME_RUNNING)
436 sample_info.read.time_running = read_info.time_running();
437 if (reader->event_attr().read_format & PERF_FORMAT_GROUP) {
438 sample_info.read.group.nr = read_info.read_value_size();
439 sample_info.read.group.values =
440 new sample_read_value[read_info.read_value_size()];
441 for (size_t i = 0; i < sample_info.read.group.nr; i++) {
442 sample_info.read.group.values[i].value =
443 read_info.read_value(i).value();
444 sample_info.read.group.values[i].id = read_info.read_value(i).id();
445 }
446 } else if (read_info.read_value_size() == 1) {
447 sample_info.read.one.value = read_info.read_value(0).value();
448 sample_info.read.one.id = read_info.read_value(0).id();
449 } else {
450 LOG(ERROR) << "Expected read_value array size of 1 but got "
451 << read_info.read_value_size();
452 }
453 }
454 }
455 if (sample.callchain_size() > 0) {
456 uint64_t callchain_size = sample.callchain_size();
457 sample_info.callchain = reinterpret_cast<struct ip_callchain*>(
458 new uint64_t[callchain_size + 1]);
459 sample_info.callchain->nr = callchain_size;
460 for (size_t i = 0; i < callchain_size; ++i)
461 sample_info.callchain->ips[i] = sample.callchain(i);
462 }
463 if (sample.raw_size() > 0) {
464 sample_info.raw_size = sample.raw_size();
465 sample_info.raw_data = new uint8_t[sample.raw_size()];
466 memset(sample_info.raw_data, 0, sample.raw_size());
467 }
468 if (sample.branch_stack_size() > 0) {
469 uint64_t branch_stack_size = sample.branch_stack_size();
470 sample_info.branch_stack = reinterpret_cast<struct branch_stack*>(
471 new uint8_t[sizeof(uint64_t) +
472 branch_stack_size * sizeof(struct branch_entry)]);
473 sample_info.branch_stack->nr = branch_stack_size;
474 for (size_t i = 0; i < branch_stack_size; ++i) {
475 struct branch_entry& entry = sample_info.branch_stack->entries[i];
476 memset(&entry, 0, sizeof(entry));
477 entry.from = sample.branch_stack(i).from_ip();
478 entry.to = sample.branch_stack(i).to_ip();
479 entry.flags.mispred = sample.branch_stack(i).mispredicted();
480 entry.flags.predicted = !entry.flags.mispred;
481 }
482 }
483
484 if (sample.has_weight()) sample_info.weight = sample.weight();
485 if (sample.has_data_src()) sample_info.data_src = sample.data_src();
486 if (sample.has_transaction()) sample_info.transaction = sample.transaction();
487
488 const SampleInfoReader* writer = GetSampleInfoReaderForId(sample.id());
489 CHECK(writer);
490 return writer->WritePerfSampleInfo(sample_info, event);
491 }
492
SerializeMMapEvent(const event_t & event,PerfDataProto_MMapEvent * sample) const493 bool PerfSerializer::SerializeMMapEvent(const event_t& event,
494 PerfDataProto_MMapEvent* sample) const {
495 const struct mmap_event& mmap = event.mmap;
496 sample->set_pid(mmap.pid);
497 sample->set_tid(mmap.tid);
498 sample->set_start(mmap.start);
499 sample->set_len(mmap.len);
500 sample->set_pgoff(mmap.pgoff);
501 sample->set_filename(mmap.filename);
502 sample->set_filename_md5_prefix(Md5Prefix(mmap.filename));
503
504 return SerializeSampleInfo(event, sample->mutable_sample_info());
505 }
506
DeserializeMMapEvent(const PerfDataProto_MMapEvent & sample,event_t * event) const507 bool PerfSerializer::DeserializeMMapEvent(const PerfDataProto_MMapEvent& sample,
508 event_t* event) const {
509 struct mmap_event& mmap = event->mmap;
510 mmap.pid = sample.pid();
511 mmap.tid = sample.tid();
512 mmap.start = sample.start();
513 mmap.len = sample.len();
514 mmap.pgoff = sample.pgoff();
515 snprintf(mmap.filename, PATH_MAX, "%s", sample.filename().c_str());
516
517 return DeserializeSampleInfo(sample.sample_info(), event);
518 }
519
SerializeMMap2Event(const event_t & event,PerfDataProto_MMapEvent * sample) const520 bool PerfSerializer::SerializeMMap2Event(
521 const event_t& event, PerfDataProto_MMapEvent* sample) const {
522 const struct mmap2_event& mmap = event.mmap2;
523 sample->set_pid(mmap.pid);
524 sample->set_tid(mmap.tid);
525 sample->set_start(mmap.start);
526 sample->set_len(mmap.len);
527 sample->set_pgoff(mmap.pgoff);
528 sample->set_maj(mmap.maj);
529 sample->set_min(mmap.min);
530 sample->set_ino(mmap.ino);
531 sample->set_ino_generation(mmap.ino_generation);
532 sample->set_prot(mmap.prot);
533 sample->set_flags(mmap.flags);
534 sample->set_filename(mmap.filename);
535 sample->set_filename_md5_prefix(Md5Prefix(mmap.filename));
536
537 return SerializeSampleInfo(event, sample->mutable_sample_info());
538 }
539
DeserializeMMap2Event(const PerfDataProto_MMapEvent & sample,event_t * event) const540 bool PerfSerializer::DeserializeMMap2Event(
541 const PerfDataProto_MMapEvent& sample, event_t* event) const {
542 struct mmap2_event& mmap = event->mmap2;
543 mmap.pid = sample.pid();
544 mmap.tid = sample.tid();
545 mmap.start = sample.start();
546 mmap.len = sample.len();
547 mmap.pgoff = sample.pgoff();
548 mmap.maj = sample.maj();
549 mmap.min = sample.min();
550 mmap.ino = sample.ino();
551 mmap.ino_generation = sample.ino_generation();
552 mmap.prot = sample.prot();
553 mmap.flags = sample.flags();
554 snprintf(mmap.filename, PATH_MAX, "%s", sample.filename().c_str());
555
556 return DeserializeSampleInfo(sample.sample_info(), event);
557 }
558
SerializeCommEvent(const event_t & event,PerfDataProto_CommEvent * sample) const559 bool PerfSerializer::SerializeCommEvent(const event_t& event,
560 PerfDataProto_CommEvent* sample) const {
561 const struct comm_event& comm = event.comm;
562 sample->set_pid(comm.pid);
563 sample->set_tid(comm.tid);
564 sample->set_comm(comm.comm);
565 sample->set_comm_md5_prefix(Md5Prefix(comm.comm));
566
567 return SerializeSampleInfo(event, sample->mutable_sample_info());
568 }
569
DeserializeCommEvent(const PerfDataProto_CommEvent & sample,event_t * event) const570 bool PerfSerializer::DeserializeCommEvent(const PerfDataProto_CommEvent& sample,
571 event_t* event) const {
572 struct comm_event& comm = event->comm;
573 comm.pid = sample.pid();
574 comm.tid = sample.tid();
575 snprintf(comm.comm, sizeof(comm.comm), "%s", sample.comm().c_str());
576
577 // Sometimes the command string will be modified. e.g. if the original comm
578 // string is not recoverable from the Md5sum prefix, then use the latter as a
579 // replacement comm string. However, if the original was < 8 bytes (fit into
580 // |sizeof(uint64_t)|), then the size is no longer correct. This section
581 // checks for the size difference and updates the size in the header.
582 const SampleInfoReader* reader =
583 GetSampleInfoReaderForId(sample.sample_info().id());
584 CHECK(reader);
585 uint64_t sample_fields = SampleInfoReader::GetSampleFieldsForEventType(
586 comm.header.type, reader->event_attr().sample_type);
587 comm.header.size = SampleInfoReader::GetPerfSampleDataOffset(*event) +
588 GetNumBits(sample_fields) * sizeof(uint64_t);
589
590 return DeserializeSampleInfo(sample.sample_info(), event);
591 }
592
SerializeForkExitEvent(const event_t & event,PerfDataProto_ForkEvent * sample) const593 bool PerfSerializer::SerializeForkExitEvent(
594 const event_t& event, PerfDataProto_ForkEvent* sample) const {
595 const struct fork_event& fork = event.fork;
596 sample->set_pid(fork.pid);
597 sample->set_ppid(fork.ppid);
598 sample->set_tid(fork.tid);
599 sample->set_ptid(fork.ptid);
600 sample->set_fork_time_ns(fork.time);
601
602 return SerializeSampleInfo(event, sample->mutable_sample_info());
603 }
604
DeserializeForkExitEvent(const PerfDataProto_ForkEvent & sample,event_t * event) const605 bool PerfSerializer::DeserializeForkExitEvent(
606 const PerfDataProto_ForkEvent& sample, event_t* event) const {
607 struct fork_event& fork = event->fork;
608 fork.pid = sample.pid();
609 fork.ppid = sample.ppid();
610 fork.tid = sample.tid();
611 fork.ptid = sample.ptid();
612 fork.time = sample.fork_time_ns();
613
614 return DeserializeSampleInfo(sample.sample_info(), event);
615 }
616
SerializeLostEvent(const event_t & event,PerfDataProto_LostEvent * sample) const617 bool PerfSerializer::SerializeLostEvent(const event_t& event,
618 PerfDataProto_LostEvent* sample) const {
619 const struct lost_event& lost = event.lost;
620 sample->set_id(lost.id);
621 sample->set_lost(lost.lost);
622
623 return SerializeSampleInfo(event, sample->mutable_sample_info());
624 }
625
DeserializeLostEvent(const PerfDataProto_LostEvent & sample,event_t * event) const626 bool PerfSerializer::DeserializeLostEvent(const PerfDataProto_LostEvent& sample,
627 event_t* event) const {
628 struct lost_event& lost = event->lost;
629 lost.id = sample.id();
630 lost.lost = sample.lost();
631
632 return DeserializeSampleInfo(sample.sample_info(), event);
633 }
634
SerializeThrottleEvent(const event_t & event,PerfDataProto_ThrottleEvent * sample) const635 bool PerfSerializer::SerializeThrottleEvent(
636 const event_t& event, PerfDataProto_ThrottleEvent* sample) const {
637 const struct throttle_event& throttle = event.throttle;
638 sample->set_time_ns(throttle.time);
639 sample->set_id(throttle.id);
640 sample->set_stream_id(throttle.stream_id);
641
642 return SerializeSampleInfo(event, sample->mutable_sample_info());
643 }
644
DeserializeThrottleEvent(const PerfDataProto_ThrottleEvent & sample,event_t * event) const645 bool PerfSerializer::DeserializeThrottleEvent(
646 const PerfDataProto_ThrottleEvent& sample, event_t* event) const {
647 struct throttle_event& throttle = event->throttle;
648 throttle.time = sample.time_ns();
649 throttle.id = sample.id();
650 throttle.stream_id = sample.stream_id();
651
652 return DeserializeSampleInfo(sample.sample_info(), event);
653 }
654
SerializeReadEvent(const event_t & event,PerfDataProto_ReadEvent * sample) const655 bool PerfSerializer::SerializeReadEvent(const event_t& event,
656 PerfDataProto_ReadEvent* sample) const {
657 const struct read_event& read = event.read;
658 sample->set_pid(read.pid);
659 sample->set_tid(read.tid);
660 sample->set_value(read.value);
661 sample->set_time_enabled(read.time_enabled);
662 sample->set_time_running(read.time_running);
663 sample->set_id(read.id);
664
665 return true;
666 }
667
DeserializeReadEvent(const PerfDataProto_ReadEvent & sample,event_t * event) const668 bool PerfSerializer::DeserializeReadEvent(const PerfDataProto_ReadEvent& sample,
669 event_t* event) const {
670 struct read_event& read = event->read;
671 read.pid = sample.pid();
672 read.tid = sample.tid();
673 read.value = sample.value();
674 read.time_enabled = sample.time_enabled();
675 read.time_running = sample.time_running();
676 read.id = sample.id();
677
678 return true;
679 }
680
SerializeAuxEvent(const event_t & event,PerfDataProto_AuxEvent * sample) const681 bool PerfSerializer::SerializeAuxEvent(const event_t& event,
682 PerfDataProto_AuxEvent* sample) const {
683 const struct aux_event& aux = event.aux;
684 sample->set_aux_offset(aux.aux_offset);
685 sample->set_aux_size(aux.aux_size);
686 sample->set_is_truncated(aux.flags & PERF_AUX_FLAG_TRUNCATED ? true : false);
687 sample->set_is_overwrite(aux.flags & PERF_AUX_FLAG_OVERWRITE ? true : false);
688 sample->set_is_partial(aux.flags & PERF_AUX_FLAG_PARTIAL ? true : false);
689 if (aux.flags & ~(PERF_AUX_FLAG_TRUNCATED | PERF_AUX_FLAG_OVERWRITE |
690 PERF_AUX_FLAG_PARTIAL)) {
691 LOG(WARNING) << "Ignoring unknown PERF_RECORD_AUX flag: " << aux.flags;
692 }
693
694 return SerializeSampleInfo(event, sample->mutable_sample_info());
695 }
696
DeserializeAuxEvent(const PerfDataProto_AuxEvent & sample,event_t * event) const697 bool PerfSerializer::DeserializeAuxEvent(const PerfDataProto_AuxEvent& sample,
698 event_t* event) const {
699 struct aux_event& aux = event->aux;
700 aux.aux_offset = sample.aux_offset();
701 aux.aux_size = sample.aux_size();
702 aux.flags |= sample.is_truncated() ? PERF_AUX_FLAG_TRUNCATED : 0;
703 aux.flags |= sample.is_overwrite() ? PERF_AUX_FLAG_OVERWRITE : 0;
704 aux.flags |= sample.is_partial() ? PERF_AUX_FLAG_PARTIAL : 0;
705
706 return DeserializeSampleInfo(sample.sample_info(), event);
707 }
708
SerializeSampleInfo(const event_t & event,PerfDataProto_SampleInfo * sample) const709 bool PerfSerializer::SerializeSampleInfo(
710 const event_t& event, PerfDataProto_SampleInfo* sample) const {
711 if (!SampleIdAll()) return true;
712
713 perf_sample sample_info;
714 uint64_t sample_type = 0;
715 if (!ReadPerfSampleInfoAndType(event, &sample_info, &sample_type))
716 return false;
717
718 if (sample_type & PERF_SAMPLE_TID) {
719 sample->set_pid(sample_info.pid);
720 sample->set_tid(sample_info.tid);
721 }
722 if (sample_type & PERF_SAMPLE_TIME)
723 sample->set_sample_time_ns(sample_info.time);
724 if ((sample_type & PERF_SAMPLE_ID) || (sample_type & PERF_SAMPLE_IDENTIFIER))
725 sample->set_id(sample_info.id);
726 if (sample_type & PERF_SAMPLE_CPU) sample->set_cpu(sample_info.cpu);
727 if (sample_type & PERF_SAMPLE_STREAM_ID)
728 sample->set_stream_id(sample_info.stream_id);
729 return true;
730 }
731
DeserializeSampleInfo(const PerfDataProto_SampleInfo & sample,event_t * event) const732 bool PerfSerializer::DeserializeSampleInfo(
733 const PerfDataProto_SampleInfo& sample, event_t* event) const {
734 if (!SampleIdAll()) return true;
735
736 perf_sample sample_info;
737 if (sample.has_tid()) {
738 sample_info.pid = sample.pid();
739 sample_info.tid = sample.tid();
740 }
741 if (sample.has_sample_time_ns()) sample_info.time = sample.sample_time_ns();
742 if (sample.has_id()) sample_info.id = sample.id();
743 if (sample.has_cpu()) sample_info.cpu = sample.cpu();
744 if (sample.has_stream_id()) sample_info.stream_id = sample.stream_id();
745
746 const SampleInfoReader* writer = GetSampleInfoReaderForId(sample.id());
747 CHECK(writer);
748 return writer->WritePerfSampleInfo(sample_info, event);
749 }
750
SerializeTracingMetadata(const std::vector<char> & from,PerfDataProto * to) const751 bool PerfSerializer::SerializeTracingMetadata(const std::vector<char>& from,
752 PerfDataProto* to) const {
753 if (from.empty()) {
754 return true;
755 }
756 PerfDataProto_PerfTracingMetadata* data = to->mutable_tracing_data();
757 data->set_tracing_data(from.data(), from.size());
758 data->set_tracing_data_md5_prefix(Md5Prefix(from));
759
760 return true;
761 }
762
DeserializeTracingMetadata(const PerfDataProto & from,std::vector<char> * to) const763 bool PerfSerializer::DeserializeTracingMetadata(const PerfDataProto& from,
764 std::vector<char>* to) const {
765 if (!from.has_tracing_data()) {
766 to->clear();
767 return true;
768 }
769
770 const PerfDataProto_PerfTracingMetadata& data = from.tracing_data();
771 to->assign(data.tracing_data().begin(), data.tracing_data().end());
772 return true;
773 }
774
SerializeBuildIDEvent(const malloced_unique_ptr<build_id_event> & from,PerfDataProto_PerfBuildID * to) const775 bool PerfSerializer::SerializeBuildIDEvent(
776 const malloced_unique_ptr<build_id_event>& from,
777 PerfDataProto_PerfBuildID* to) const {
778 to->set_misc(from->header.misc);
779 to->set_pid(from->pid);
780 to->set_filename(from->filename);
781 to->set_filename_md5_prefix(Md5Prefix(from->filename));
782
783 // Trim out trailing zeroes from the build ID.
784 string build_id = RawDataToHexString(from->build_id, kBuildIDArraySize);
785 TrimZeroesFromBuildIDString(&build_id);
786
787 uint8_t build_id_bytes[kBuildIDArraySize];
788 if (!HexStringToRawData(build_id, build_id_bytes, sizeof(build_id_bytes)))
789 return false;
790
791 // Used to convert build IDs (and possibly other hashes) between raw data
792 // format and as string of hex digits.
793 const int kHexCharsPerByte = 2;
794 to->set_build_id_hash(build_id_bytes, build_id.size() / kHexCharsPerByte);
795
796 return true;
797 }
798
DeserializeBuildIDEvent(const PerfDataProto_PerfBuildID & from,malloced_unique_ptr<build_id_event> * to) const799 bool PerfSerializer::DeserializeBuildIDEvent(
800 const PerfDataProto_PerfBuildID& from,
801 malloced_unique_ptr<build_id_event>* to) const {
802 const string& filename = from.filename();
803 size_t size = sizeof(build_id_event) + GetUint64AlignedStringLength(filename);
804
805 malloced_unique_ptr<build_id_event>& event = *to;
806 event.reset(CallocMemoryForBuildID(size));
807 event->header.type = PERF_RECORD_HEADER_BUILD_ID;
808 event->header.size = size;
809 event->header.misc = from.misc();
810 event->pid = from.pid();
811 memcpy(event->build_id, from.build_id_hash().c_str(),
812 from.build_id_hash().size());
813
814 if (from.has_filename() && !filename.empty()) {
815 CHECK_GT(
816 snprintf(event->filename, filename.size() + 1, "%s", filename.c_str()),
817 0);
818 }
819 return true;
820 }
821
SerializeAuxtraceEvent(const event_t & event,PerfDataProto_AuxtraceEvent * sample) const822 bool PerfSerializer::SerializeAuxtraceEvent(
823 const event_t& event, PerfDataProto_AuxtraceEvent* sample) const {
824 const struct auxtrace_event& auxtrace = event.auxtrace;
825 sample->set_size(auxtrace.size);
826 sample->set_offset(auxtrace.offset);
827 sample->set_reference(auxtrace.reference);
828 sample->set_idx(auxtrace.idx);
829 sample->set_tid(auxtrace.tid);
830 sample->set_cpu(auxtrace.cpu);
831
832 return true;
833 }
834
SerializeAuxtraceEventTraceData(const std::vector<char> & from,PerfDataProto_AuxtraceEvent * to) const835 bool PerfSerializer::SerializeAuxtraceEventTraceData(
836 const std::vector<char>& from, PerfDataProto_AuxtraceEvent* to) const {
837 if (from.empty()) {
838 return true;
839 }
840 to->set_trace_data(from.data(), from.size());
841
842 return true;
843 }
844
DeserializeAuxtraceEvent(const PerfDataProto_AuxtraceEvent & sample,event_t * event) const845 bool PerfSerializer::DeserializeAuxtraceEvent(
846 const PerfDataProto_AuxtraceEvent& sample, event_t* event) const {
847 struct auxtrace_event& auxtrace = event->auxtrace;
848 auxtrace.size = sample.size();
849 auxtrace.offset = sample.offset();
850 auxtrace.reference = sample.reference();
851 auxtrace.idx = sample.idx();
852 auxtrace.tid = sample.tid();
853 auxtrace.cpu = sample.cpu();
854
855 return true;
856 }
857
DeserializeAuxtraceEventTraceData(const PerfDataProto_AuxtraceEvent & from,std::vector<char> * to) const858 bool PerfSerializer::DeserializeAuxtraceEventTraceData(
859 const PerfDataProto_AuxtraceEvent& from, std::vector<char>* to) const {
860 to->assign(from.trace_data().begin(), from.trace_data().end());
861 return true;
862 }
863
SerializeSingleUint32Metadata(const PerfUint32Metadata & metadata,PerfDataProto_PerfUint32Metadata * proto_metadata) const864 bool PerfSerializer::SerializeSingleUint32Metadata(
865 const PerfUint32Metadata& metadata,
866 PerfDataProto_PerfUint32Metadata* proto_metadata) const {
867 proto_metadata->set_type(metadata.type);
868 for (size_t i = 0; i < metadata.data.size(); ++i)
869 proto_metadata->add_data(metadata.data[i]);
870 return true;
871 }
872
DeserializeSingleUint32Metadata(const PerfDataProto_PerfUint32Metadata & proto_metadata,PerfUint32Metadata * metadata) const873 bool PerfSerializer::DeserializeSingleUint32Metadata(
874 const PerfDataProto_PerfUint32Metadata& proto_metadata,
875 PerfUint32Metadata* metadata) const {
876 metadata->type = proto_metadata.type();
877 for (int i = 0; i < proto_metadata.data_size(); ++i)
878 metadata->data.push_back(proto_metadata.data(i));
879 return true;
880 }
881
SerializeSingleUint64Metadata(const PerfUint64Metadata & metadata,PerfDataProto_PerfUint64Metadata * proto_metadata) const882 bool PerfSerializer::SerializeSingleUint64Metadata(
883 const PerfUint64Metadata& metadata,
884 PerfDataProto_PerfUint64Metadata* proto_metadata) const {
885 proto_metadata->set_type(metadata.type);
886 for (size_t i = 0; i < metadata.data.size(); ++i)
887 proto_metadata->add_data(metadata.data[i]);
888 return true;
889 }
890
DeserializeSingleUint64Metadata(const PerfDataProto_PerfUint64Metadata & proto_metadata,PerfUint64Metadata * metadata) const891 bool PerfSerializer::DeserializeSingleUint64Metadata(
892 const PerfDataProto_PerfUint64Metadata& proto_metadata,
893 PerfUint64Metadata* metadata) const {
894 metadata->type = proto_metadata.type();
895 for (int i = 0; i < proto_metadata.data_size(); ++i)
896 metadata->data.push_back(proto_metadata.data(i));
897 return true;
898 }
899
SerializeCPUTopologyMetadata(const PerfCPUTopologyMetadata & metadata,PerfDataProto_PerfCPUTopologyMetadata * proto_metadata) const900 bool PerfSerializer::SerializeCPUTopologyMetadata(
901 const PerfCPUTopologyMetadata& metadata,
902 PerfDataProto_PerfCPUTopologyMetadata* proto_metadata) const {
903 for (const string& core_name : metadata.core_siblings) {
904 proto_metadata->add_core_siblings(core_name);
905 proto_metadata->add_core_siblings_md5_prefix(Md5Prefix(core_name));
906 }
907 for (const string& thread_name : metadata.thread_siblings) {
908 proto_metadata->add_thread_siblings(thread_name);
909 proto_metadata->add_thread_siblings_md5_prefix(Md5Prefix(thread_name));
910 }
911 return true;
912 }
913
DeserializeCPUTopologyMetadata(const PerfDataProto_PerfCPUTopologyMetadata & proto_metadata,PerfCPUTopologyMetadata * metadata) const914 bool PerfSerializer::DeserializeCPUTopologyMetadata(
915 const PerfDataProto_PerfCPUTopologyMetadata& proto_metadata,
916 PerfCPUTopologyMetadata* metadata) const {
917 metadata->core_siblings.clear();
918 metadata->core_siblings.reserve(proto_metadata.core_siblings().size());
919 std::copy(proto_metadata.core_siblings().begin(),
920 proto_metadata.core_siblings().end(),
921 std::back_inserter(metadata->core_siblings));
922
923 metadata->thread_siblings.clear();
924 metadata->thread_siblings.reserve(proto_metadata.thread_siblings().size());
925 std::copy(proto_metadata.thread_siblings().begin(),
926 proto_metadata.thread_siblings().end(),
927 std::back_inserter(metadata->thread_siblings));
928 return true;
929 }
930
SerializeNodeTopologyMetadata(const PerfNodeTopologyMetadata & metadata,PerfDataProto_PerfNodeTopologyMetadata * proto_metadata) const931 bool PerfSerializer::SerializeNodeTopologyMetadata(
932 const PerfNodeTopologyMetadata& metadata,
933 PerfDataProto_PerfNodeTopologyMetadata* proto_metadata) const {
934 proto_metadata->set_id(metadata.id);
935 proto_metadata->set_total_memory(metadata.total_memory);
936 proto_metadata->set_free_memory(metadata.free_memory);
937 proto_metadata->set_cpu_list(metadata.cpu_list);
938 proto_metadata->set_cpu_list_md5_prefix(Md5Prefix(metadata.cpu_list));
939 return true;
940 }
941
DeserializeNodeTopologyMetadata(const PerfDataProto_PerfNodeTopologyMetadata & proto_metadata,PerfNodeTopologyMetadata * metadata) const942 bool PerfSerializer::DeserializeNodeTopologyMetadata(
943 const PerfDataProto_PerfNodeTopologyMetadata& proto_metadata,
944 PerfNodeTopologyMetadata* metadata) const {
945 metadata->id = proto_metadata.id();
946 metadata->total_memory = proto_metadata.total_memory();
947 metadata->free_memory = proto_metadata.free_memory();
948 metadata->cpu_list = proto_metadata.cpu_list();
949 return true;
950 }
951
SerializePMUMappingsMetadata(const PerfPMUMappingsMetadata & metadata,PerfDataProto_PerfPMUMappingsMetadata * proto_metadata) const952 bool PerfSerializer::SerializePMUMappingsMetadata(
953 const PerfPMUMappingsMetadata& metadata,
954 PerfDataProto_PerfPMUMappingsMetadata* proto_metadata) const {
955 proto_metadata->set_type(metadata.type);
956 proto_metadata->set_name(metadata.name);
957 proto_metadata->set_name_md5_prefix(Md5Prefix(metadata.name));
958 return true;
959 }
960
DeserializePMUMappingsMetadata(const PerfDataProto_PerfPMUMappingsMetadata & proto_metadata,PerfPMUMappingsMetadata * metadata) const961 bool PerfSerializer::DeserializePMUMappingsMetadata(
962 const PerfDataProto_PerfPMUMappingsMetadata& proto_metadata,
963 PerfPMUMappingsMetadata* metadata) const {
964 metadata->type = proto_metadata.type();
965 metadata->name = proto_metadata.name();
966 return true;
967 }
968
SerializeGroupDescMetadata(const PerfGroupDescMetadata & metadata,PerfDataProto_PerfGroupDescMetadata * proto_metadata) const969 bool PerfSerializer::SerializeGroupDescMetadata(
970 const PerfGroupDescMetadata& metadata,
971 PerfDataProto_PerfGroupDescMetadata* proto_metadata) const {
972 proto_metadata->set_name(metadata.name);
973 proto_metadata->set_name_md5_prefix(Md5Prefix(metadata.name));
974 proto_metadata->set_leader_idx(metadata.leader_idx);
975 proto_metadata->set_num_members(metadata.num_members);
976 return true;
977 }
978
DeserializeGroupDescMetadata(const PerfDataProto_PerfGroupDescMetadata & proto_metadata,PerfGroupDescMetadata * metadata) const979 bool PerfSerializer::DeserializeGroupDescMetadata(
980 const PerfDataProto_PerfGroupDescMetadata& proto_metadata,
981 PerfGroupDescMetadata* metadata) const {
982 metadata->name = proto_metadata.name();
983 metadata->leader_idx = proto_metadata.leader_idx();
984 metadata->num_members = proto_metadata.num_members();
985 return true;
986 }
987
988 // static
SerializeParserStats(const PerfEventStats & stats,PerfDataProto * perf_data_proto)989 void PerfSerializer::SerializeParserStats(const PerfEventStats& stats,
990 PerfDataProto* perf_data_proto) {
991 PerfDataProto_PerfEventStats* stats_pb = perf_data_proto->mutable_stats();
992 stats_pb->set_num_sample_events(stats.num_sample_events);
993 stats_pb->set_num_mmap_events(stats.num_mmap_events);
994 stats_pb->set_num_fork_events(stats.num_fork_events);
995 stats_pb->set_num_exit_events(stats.num_exit_events);
996 stats_pb->set_did_remap(stats.did_remap);
997 stats_pb->set_num_sample_events_mapped(stats.num_sample_events_mapped);
998 }
999
1000 // static
DeserializeParserStats(const PerfDataProto & perf_data_proto,PerfEventStats * stats)1001 void PerfSerializer::DeserializeParserStats(
1002 const PerfDataProto& perf_data_proto, PerfEventStats* stats) {
1003 const PerfDataProto_PerfEventStats& stats_pb = perf_data_proto.stats();
1004 stats->num_sample_events = stats_pb.num_sample_events();
1005 stats->num_mmap_events = stats_pb.num_mmap_events();
1006 stats->num_fork_events = stats_pb.num_fork_events();
1007 stats->num_exit_events = stats_pb.num_exit_events();
1008 stats->did_remap = stats_pb.did_remap();
1009 stats->num_sample_events_mapped = stats_pb.num_sample_events_mapped();
1010 }
1011
CreateSampleInfoReader(const PerfFileAttr & attr,bool read_cross_endian)1012 void PerfSerializer::CreateSampleInfoReader(const PerfFileAttr& attr,
1013 bool read_cross_endian) {
1014 for (const auto& id :
1015 (attr.ids.empty() ? std::initializer_list<u64>({0}) : attr.ids)) {
1016 sample_info_reader_map_[id].reset(
1017 new SampleInfoReader(attr.attr, read_cross_endian));
1018 }
1019 UpdateEventIdPositions(attr.attr);
1020 }
1021
UpdateEventIdPositions(const struct perf_event_attr & attr)1022 void PerfSerializer::UpdateEventIdPositions(
1023 const struct perf_event_attr& attr) {
1024 const u64 sample_type = attr.sample_type;
1025 ssize_t new_sample_event_id_pos = EventIdPosition::NotPresent;
1026 ssize_t new_other_event_id_pos = EventIdPosition::NotPresent;
1027 if (sample_type & PERF_SAMPLE_IDENTIFIER) {
1028 new_sample_event_id_pos = 0;
1029 new_other_event_id_pos = 1;
1030 } else if (sample_type & PERF_SAMPLE_ID) {
1031 // Increment for IP, TID, TIME, ADDR
1032 new_sample_event_id_pos = 0;
1033 if (sample_type & PERF_SAMPLE_IP) new_sample_event_id_pos++;
1034 if (sample_type & PERF_SAMPLE_TID) new_sample_event_id_pos++;
1035 if (sample_type & PERF_SAMPLE_TIME) new_sample_event_id_pos++;
1036 if (sample_type & PERF_SAMPLE_ADDR) new_sample_event_id_pos++;
1037
1038 // Increment for CPU, STREAM_ID
1039 new_other_event_id_pos = 1;
1040 if (sample_type & PERF_SAMPLE_CPU) new_other_event_id_pos++;
1041 if (sample_type & PERF_SAMPLE_STREAM_ID) new_other_event_id_pos++;
1042 }
1043
1044 if (sample_event_id_pos_ == EventIdPosition::Uninitialized) {
1045 sample_event_id_pos_ = new_sample_event_id_pos;
1046 } else {
1047 CHECK_EQ(new_sample_event_id_pos, sample_event_id_pos_)
1048 << "Event ids must be in a consistent positition";
1049 }
1050 if (other_event_id_pos_ == EventIdPosition::Uninitialized) {
1051 other_event_id_pos_ = new_other_event_id_pos;
1052 } else {
1053 CHECK_EQ(new_other_event_id_pos, other_event_id_pos_)
1054 << "Event ids must be in a consistent positition";
1055 }
1056 }
1057
SampleIdAll() const1058 bool PerfSerializer::SampleIdAll() const {
1059 if (sample_info_reader_map_.empty()) {
1060 return false;
1061 }
1062 return sample_info_reader_map_.begin()->second->event_attr().sample_id_all;
1063 }
1064
GetSampleInfoReaderForEvent(const event_t & event) const1065 const SampleInfoReader* PerfSerializer::GetSampleInfoReaderForEvent(
1066 const event_t& event) const {
1067 // Where is the event id?
1068 ssize_t event_id_pos = EventIdPosition::Uninitialized;
1069 if (event.header.type == PERF_RECORD_SAMPLE) {
1070 event_id_pos = sample_event_id_pos_;
1071 } else if (SampleIdAll()) {
1072 event_id_pos = other_event_id_pos_;
1073 } else {
1074 event_id_pos = EventIdPosition::NotPresent;
1075 }
1076
1077 // What is the event id?
1078 u64 event_id;
1079 switch (event_id_pos) {
1080 case EventIdPosition::Uninitialized:
1081 LOG(FATAL) << "Position of the event id was not initialized!";
1082 return nullptr;
1083 case EventIdPosition::NotPresent:
1084 event_id = 0;
1085 break;
1086 default:
1087 if (event.header.type == PERF_RECORD_SAMPLE) {
1088 event_id = event.sample.array[event_id_pos];
1089 } else {
1090 // Pretend this is a sample event--ie, an array of u64. Find the length
1091 // of the array. The sample id is at the end of the array, and
1092 // event_id_pos (aka other_event_id_pos_) counts from the end.
1093 size_t event_end_pos =
1094 (event.header.size - sizeof(event.header)) / sizeof(u64);
1095 event_id = event.sample.array[event_end_pos - event_id_pos];
1096 }
1097 break;
1098 }
1099 return GetSampleInfoReaderForId(event_id);
1100 }
1101
GetSampleInfoReaderForId(uint64_t id) const1102 const SampleInfoReader* PerfSerializer::GetSampleInfoReaderForId(
1103 uint64_t id) const {
1104 if (id) {
1105 auto iter = sample_info_reader_map_.find(id);
1106 if (iter == sample_info_reader_map_.end()) return nullptr;
1107 return iter->second.get();
1108 }
1109
1110 if (sample_info_reader_map_.empty()) return nullptr;
1111 return sample_info_reader_map_.begin()->second.get();
1112 }
1113
ReadPerfSampleInfoAndType(const event_t & event,perf_sample * sample_info,uint64_t * sample_type) const1114 bool PerfSerializer::ReadPerfSampleInfoAndType(const event_t& event,
1115 perf_sample* sample_info,
1116 uint64_t* sample_type) const {
1117 const SampleInfoReader* reader = GetSampleInfoReaderForEvent(event);
1118 if (!reader) {
1119 LOG(ERROR) << "No SampleInfoReader available";
1120 return false;
1121 }
1122
1123 if (!reader->ReadPerfSampleInfo(event, sample_info)) return false;
1124 *sample_type = reader->event_attr().sample_type;
1125 return true;
1126 }
1127
1128 } // namespace quipper
1129