• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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