• 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_reader.h"
6 
7 #include <stdio.h>
8 #include <stdlib.h>
9 #include <string.h>
10 #include <sys/time.h>
11 
12 #include <algorithm>
13 #include <vector>
14 
15 #include "base/logging.h"
16 #include "base/macros.h"
17 
18 #include "binary_data_utils.h"
19 #include "buffer_reader.h"
20 #include "buffer_writer.h"
21 #include "compat/string.h"
22 #include "file_reader.h"
23 #include "file_utils.h"
24 #include "perf_data_structures.h"
25 #include "perf_data_utils.h"
26 #include "sample_info_reader.h"
27 
28 namespace quipper {
29 
30 using PerfEvent = PerfDataProto_PerfEvent;
31 using SampleInfo = PerfDataProto_SampleInfo;
32 using StringAndMd5sumPrefix =
33     PerfDataProto_StringMetadata_StringAndMd5sumPrefix;
34 
35 namespace {
36 
37 // The type of the storage size of a string, prefixed before each string field
38 // in raw data.
39 typedef u32 string_size_type;
40 
41 // The type of the number of string data, found in the command line metadata in
42 // the perf data file.
43 typedef u32 num_string_data_type;
44 
45 // Types of the event desc fields that are not found in other structs.
46 typedef u32 event_desc_num_events;
47 typedef u32 event_desc_attr_size;
48 typedef u32 event_desc_num_unique_ids;
49 
50 // The type of the number of nodes field in NUMA topology.
51 typedef u32 numa_topology_num_nodes_type;
52 
53 // The type of the number of mappings in pmu mappings.
54 typedef u32 pmu_mappings_num_mappings_type;
55 
56 // The type of the number of groups in group desc.
57 typedef u32 group_desc_num_groups_type;
58 
59 // A mask that is applied to |metadata_mask()| in order to get a mask for
60 // only the metadata supported by quipper.
61 const uint32_t kSupportedMetadataMask =
62     1 << HEADER_TRACING_DATA | 1 << HEADER_BUILD_ID | 1 << HEADER_HOSTNAME |
63     1 << HEADER_OSRELEASE | 1 << HEADER_VERSION | 1 << HEADER_ARCH |
64     1 << HEADER_NRCPUS | 1 << HEADER_CPUDESC | 1 << HEADER_CPUID |
65     1 << HEADER_TOTAL_MEM | 1 << HEADER_CMDLINE | 1 << HEADER_EVENT_DESC |
66     1 << HEADER_CPU_TOPOLOGY | 1 << HEADER_NUMA_TOPOLOGY |
67     1 << HEADER_BRANCH_STACK | 1 << HEADER_PMU_MAPPINGS |
68     1 << HEADER_GROUP_DESC;
69 
70 // By default, the build ID event has PID = -1.
71 const uint32_t kDefaultBuildIDEventPid = static_cast<uint32_t>(-1);
72 
73 // Eight bits in a byte.
BytesToBits(size_t num_bytes)74 size_t BytesToBits(size_t num_bytes) { return num_bytes * 8; }
75 
ReverseByte(u8 x)76 u8 ReverseByte(u8 x) {
77   x = (x & 0xf0) >> 4 | (x & 0x0f) << 4;  // exchange nibbles
78   x = (x & 0xcc) >> 2 | (x & 0x33) << 2;  // exchange pairs
79   x = (x & 0xaa) >> 1 | (x & 0x55) << 1;  // exchange neighbors
80   return x;
81 }
82 
83 // If field points to the start of a bitfield padded to len bytes, this
84 // performs an endian swap of the bitfield, assuming the compiler that produced
85 // it conforms to the same ABI (bitfield layout is not completely specified by
86 // the language).
SwapBitfieldOfBits(u8 * field,size_t len)87 void SwapBitfieldOfBits(u8* field, size_t len) {
88   for (size_t i = 0; i < len; i++) {
89     field[i] = ReverseByte(field[i]);
90   }
91 }
92 
93 // The code currently assumes that the compiler will not add any padding to the
94 // various structs.  These CHECKs make sure that this is true.
CheckNoEventHeaderPadding()95 void CheckNoEventHeaderPadding() {
96   perf_event_header header;
97   CHECK_EQ(sizeof(header),
98            sizeof(header.type) + sizeof(header.misc) + sizeof(header.size));
99 }
100 
CheckNoPerfEventAttrPadding()101 void CheckNoPerfEventAttrPadding() {
102   perf_event_attr attr;
103   CHECK_EQ(sizeof(attr), (reinterpret_cast<u64>(&attr.__reserved_2) -
104                           reinterpret_cast<u64>(&attr)) +
105                              sizeof(attr.__reserved_2));
106 }
107 
CheckNoEventTypePadding()108 void CheckNoEventTypePadding() {
109   perf_trace_event_type event_type;
110   CHECK_EQ(sizeof(event_type),
111            sizeof(event_type.event_id) + sizeof(event_type.name));
112 }
113 
CheckNoBuildIDEventPadding()114 void CheckNoBuildIDEventPadding() {
115   build_id_event event;
116   CHECK_EQ(sizeof(event), sizeof(event.header.type) +
117                               sizeof(event.header.misc) +
118                               sizeof(event.header.size) + sizeof(event.pid) +
119                               sizeof(event.build_id));
120 }
121 
122 // Creates a new build ID event with the given build ID string, filename, and
123 // misc value.
CreateBuildIDEvent(const string & build_id,const string & filename,uint16_t misc)124 malloced_unique_ptr<build_id_event> CreateBuildIDEvent(const string& build_id,
125                                                        const string& filename,
126                                                        uint16_t misc) {
127   size_t filename_len = GetUint64AlignedStringLength(filename);
128   size_t size = sizeof(struct build_id_event) + filename_len;
129   malloced_unique_ptr<build_id_event> event(CallocMemoryForBuildID(size));
130   event->header.type = HEADER_BUILD_ID;
131   event->header.misc = misc;
132   event->header.size = size;
133 
134   event->pid = kDefaultBuildIDEventPid;
135   snprintf(event->filename, filename_len, "%s", filename.c_str());
136   memset(event->filename + filename.size(), 0, filename_len - filename.size());
137 
138   HexStringToRawData(build_id, event->build_id, sizeof(event->build_id));
139   return event;
140 }
141 
142 // Given a string, returns the total size required to store the string in perf
143 // data, including a preceding length field and extra padding to align the
144 // string + null terminator to a multiple of uint64s.
ExpectedStorageSizeOf(const string & str)145 size_t ExpectedStorageSizeOf(const string& str) {
146   return sizeof(string_size_type) + GetUint64AlignedStringLength(str);
147 }
148 
149 // Reads a perf_event_header from |data| and performs byte swapping if
150 // necessary. Returns true on success, or false if there was an error.
ReadPerfEventHeader(DataReader * data,struct perf_event_header * header)151 bool ReadPerfEventHeader(DataReader* data, struct perf_event_header* header) {
152   if (!data->ReadData(sizeof(struct perf_event_header), header)) {
153     LOG(ERROR) << "Error reading perf event header.";
154     return false;
155   }
156   if (data->is_cross_endian()) {
157     ByteSwap(&header->type);
158     ByteSwap(&header->size);
159     ByteSwap(&header->misc);
160   }
161   return true;
162 }
163 
164 // Reads a perf_file_section from |data| and performs byte swapping if
165 // necessary. Returns true on success, or false if there was an error.
ReadPerfFileSection(DataReader * data,struct perf_file_section * section)166 bool ReadPerfFileSection(DataReader* data, struct perf_file_section* section) {
167   if (!data->ReadData(sizeof(*section), section)) {
168     LOG(ERROR) << "Error reading perf file section info.";
169     return false;
170   }
171   if (data->is_cross_endian()) {
172     ByteSwap(&section->offset);
173     ByteSwap(&section->size);
174   }
175   return true;
176 }
177 
178 // Returns true if |e1| has an earlier timestamp than |e2|. Used to sort an
179 // array of events.
CompareEventTimes(const PerfEvent * e1,const PerfEvent * e2)180 static bool CompareEventTimes(const PerfEvent* e1, const PerfEvent* e2) {
181   return e1->timestamp() < e2->timestamp();
182 }
183 
184 }  // namespace
185 
PerfReader()186 PerfReader::PerfReader()
187     : proto_(Arena::CreateMessage<PerfDataProto>(&arena_)),
188       is_cross_endian_(false) {
189   // The metadata mask is stored in |proto_|. It should be initialized to 0
190   // since it is used heavily.
191   proto_->add_metadata_mask(0);
192 }
193 
~PerfReader()194 PerfReader::~PerfReader() {}
195 
Serialize(PerfDataProto * perf_data_proto) const196 bool PerfReader::Serialize(PerfDataProto* perf_data_proto) const {
197   perf_data_proto->CopyFrom(*proto_);
198 
199   // Add a timestamp_sec to the protobuf.
200   struct timeval timestamp_sec;
201   if (!gettimeofday(&timestamp_sec, NULL))
202     perf_data_proto->set_timestamp_sec(timestamp_sec.tv_sec);
203   return true;
204 }
205 
Deserialize(const PerfDataProto & perf_data_proto)206 bool PerfReader::Deserialize(const PerfDataProto& perf_data_proto) {
207   proto_->CopyFrom(perf_data_proto);
208 
209   // Iterate through all attrs and create a SampleInfoReader for each of them.
210   // This is necessary for writing the proto representation of perf data to raw
211   // data.
212   for (const auto& stored_attr : proto_->file_attrs()) {
213     PerfFileAttr attr;
214     serializer_.DeserializePerfFileAttr(stored_attr, &attr);
215     serializer_.CreateSampleInfoReader(attr, false /* read_cross_endian */);
216   }
217   return true;
218 }
219 
ReadFile(const string & filename)220 bool PerfReader::ReadFile(const string& filename) {
221   FileReader reader(filename);
222   if (!reader.IsOpen()) {
223     LOG(ERROR) << "Unable to open file " << filename;
224     return false;
225   }
226   return ReadFromData(&reader);
227 }
228 
ReadFromVector(const std::vector<char> & data)229 bool PerfReader::ReadFromVector(const std::vector<char>& data) {
230   return ReadFromPointer(data.data(), data.size());
231 }
232 
ReadFromString(const string & str)233 bool PerfReader::ReadFromString(const string& str) {
234   return ReadFromPointer(str.data(), str.size());
235 }
236 
ReadFromPointer(const char * data,size_t size)237 bool PerfReader::ReadFromPointer(const char* data, size_t size) {
238   BufferReader buffer(data, size);
239   return ReadFromData(&buffer);
240 }
241 
ReadFromData(DataReader * data)242 bool PerfReader::ReadFromData(DataReader* data) {
243   if (data->size() == 0) {
244     LOG(ERROR) << "Input data is empty";
245     return false;
246   }
247   if (!ReadHeader(data)) return false;
248 
249   // Check if it is normal perf data.
250   if (header_.size == sizeof(header_)) {
251     DVLOG(1) << "Perf data is in normal format.";
252     return ReadFileData(data);
253   }
254 
255   // Otherwise it is piped data.
256   if (piped_header_.size != sizeof(piped_header_)) {
257     LOG(ERROR) << "Expecting piped data format, but header size "
258                << piped_header_.size << " does not match expected size "
259                << sizeof(piped_header_);
260     return false;
261   }
262 
263   return ReadPipedData(data);
264 }
265 
WriteFile(const string & filename)266 bool PerfReader::WriteFile(const string& filename) {
267   std::vector<char> data;
268   return WriteToVector(&data) && BufferToFile(filename, data);
269 }
270 
WriteToVector(std::vector<char> * data)271 bool PerfReader::WriteToVector(std::vector<char>* data) {
272   data->resize(GetSize());
273   return WriteToPointerWithoutCheckingSize(&data->at(0), data->size());
274 }
275 
WriteToString(string * str)276 bool PerfReader::WriteToString(string* str) {
277   str->resize(GetSize());
278   return WriteToPointerWithoutCheckingSize(&str->at(0), str->size());
279 }
280 
WriteToPointer(char * buffer,size_t size)281 bool PerfReader::WriteToPointer(char* buffer, size_t size) {
282   size_t required_size = GetSize();
283   if (size < required_size) {
284     LOG(ERROR) << "Buffer is too small - buffer size is " << size
285                << " and required size is " << required_size;
286     return false;
287   }
288   return WriteToPointerWithoutCheckingSize(buffer, size);
289 }
290 
WriteToPointerWithoutCheckingSize(char * buffer,size_t size)291 bool PerfReader::WriteToPointerWithoutCheckingSize(char* buffer, size_t size) {
292   BufferWriter data(buffer, size);
293   struct perf_file_header header;
294   GenerateHeader(&header);
295 
296   return WriteHeader(header, &data) && WriteAttrs(header, &data) &&
297          WriteData(header, &data) && WriteMetadata(header, &data);
298 }
299 
GetSize() const300 size_t PerfReader::GetSize() const {
301   struct perf_file_header header;
302   GenerateHeader(&header);
303 
304   size_t total_size = 0;
305   total_size += header.size;
306   total_size += header.attrs.size;
307   total_size += header.event_types.size;
308   total_size += header.data.size;
309   // Add the ID info, whose size is not explicitly included in the header.
310   for (const auto& attr : proto_->file_attrs()) {
311     total_size +=
312         attr.ids_size() * sizeof(decltype(PerfFileAttr::ids)::value_type);
313   }
314 
315   // Additional info about metadata.  See WriteMetadata for explanation.
316   total_size += GetNumSupportedMetadata() * sizeof(struct perf_file_section);
317 
318   // Add the sizes of the various metadata.
319   total_size += tracing_data().size();
320   total_size += GetBuildIDMetadataSize();
321   total_size += GetStringMetadataSize();
322   total_size += GetUint32MetadataSize();
323   total_size += GetUint64MetadataSize();
324   total_size += GetEventDescMetadataSize();
325   total_size += GetCPUTopologyMetadataSize();
326   total_size += GetNUMATopologyMetadataSize();
327   total_size += GetPMUMappingsMetadataSize();
328   total_size += GetGroupDescMetadataSize();
329   return total_size;
330 }
331 
GenerateHeader(struct perf_file_header * header) const332 void PerfReader::GenerateHeader(struct perf_file_header* header) const {
333   // This is the order of the input perf file contents in normal mode:
334   // 1. Header
335   // 2. Attribute IDs (pointed to by attr.ids.offset)
336   // 3. Attributes
337   // 4. Event types
338   // 5. Data
339   // 6. Metadata
340 
341   // Compute offsets in the above order.
342   CheckNoEventHeaderPadding();
343   memset(header, 0, sizeof(*header));
344   header->magic = kPerfMagic;
345   header->size = sizeof(*header);
346   header->attr_size = sizeof(perf_file_attr);
347   header->attrs.size = header->attr_size * attrs().size();
348   for (const PerfEvent& event : proto_->events()) {
349     header->data.size += event.header().size();
350     // Auxtrace event contain trace data at the end of the event. Add the size
351     // of this trace data to the header.data size.
352     if (event.header().type() == PERF_RECORD_AUXTRACE) {
353       header->data.size += event.auxtrace_event().size();
354     }
355   }
356   // Do not use the event_types section. Use EVENT_DESC metadata instead.
357   header->event_types.size = 0;
358 
359   u64 current_offset = 0;
360   current_offset += header->size;
361   for (const auto& attr : proto_->file_attrs()) {
362     current_offset +=
363         sizeof(decltype(PerfFileAttr::ids)::value_type) * attr.ids_size();
364   }
365   header->attrs.offset = current_offset;
366   current_offset += header->attrs.size;
367   header->event_types.offset = current_offset;
368   current_offset += header->event_types.size;
369 
370   header->data.offset = current_offset;
371 
372   // Construct the header feature bits.
373   memset(&header->adds_features, 0, sizeof(header->adds_features));
374   // The following code makes the assumption that all feature bits are in the
375   // first word of |adds_features|.  If the perf data format changes and the
376   // assumption is no longer valid, this CHECK will fail, at which point the
377   // below code needs to be updated.  For now, sticking to that assumption keeps
378   // the code simple.
379   // This assumption is also used when reading metadata, so that code
380   // will also have to be updated if this CHECK starts to fail.
381   CHECK_LE(static_cast<size_t>(HEADER_LAST_FEATURE),
382            BytesToBits(sizeof(header->adds_features[0])));
383   header->adds_features[0] |= metadata_mask() & kSupportedMetadataMask;
384 }
385 
InjectBuildIDs(const std::map<string,string> & filenames_to_build_ids)386 bool PerfReader::InjectBuildIDs(
387     const std::map<string, string>& filenames_to_build_ids) {
388   set_metadata_mask_bit(HEADER_BUILD_ID);
389   std::set<string> updated_filenames;
390   // Inject new build ID's for existing build ID events.
391   for (auto& build_id : *proto_->mutable_build_ids()) {
392     auto find_result = filenames_to_build_ids.find(build_id.filename());
393     if (find_result == filenames_to_build_ids.end()) continue;
394     const string& build_id_string = find_result->second;
395     const int kHexCharsPerByte = 2;
396     std::vector<uint8_t> build_id_data(build_id_string.size() /
397                                        kHexCharsPerByte);
398     if (!HexStringToRawData(build_id_string, build_id_data.data(),
399                             build_id_data.size())) {
400       LOG(ERROR) << "Could not convert hex string to raw data: "
401                  << build_id_string;
402       return false;
403     }
404     build_id.set_build_id_hash(build_id_data.data(), build_id_data.size());
405 
406     updated_filenames.insert(build_id.filename());
407   }
408 
409   // For files with no existing build ID events, create new build ID events.
410   // This requires a lookup of all MMAP's to determine the |misc| field of each
411   // build ID event.
412   std::map<string, uint16_t> filename_to_misc;
413   for (const PerfEvent& event : proto_->events()) {
414     if (event.header().type() == PERF_RECORD_MMAP ||
415         event.header().type() == PERF_RECORD_MMAP2) {
416       filename_to_misc[event.mmap_event().filename()] = event.header().misc();
417     }
418   }
419 
420   std::map<string, string>::const_iterator it;
421   for (it = filenames_to_build_ids.begin(); it != filenames_to_build_ids.end();
422        ++it) {
423     const string& filename = it->first;
424     if (updated_filenames.find(filename) != updated_filenames.end()) continue;
425 
426     // Determine the misc field.
427     uint16_t new_misc = PERF_RECORD_MISC_KERNEL;
428     std::map<string, uint16_t>::const_iterator misc_iter =
429         filename_to_misc.find(filename);
430     if (misc_iter != filename_to_misc.end()) new_misc = misc_iter->second;
431 
432     string build_id = it->second;
433     malloced_unique_ptr<build_id_event> event =
434         CreateBuildIDEvent(build_id, filename, new_misc);
435     if (!serializer_.SerializeBuildIDEvent(event, proto_->add_build_ids())) {
436       LOG(ERROR) << "Could not serialize build ID event with ID " << build_id;
437       return false;
438     }
439   }
440   return true;
441 }
442 
Localize(const std::map<string,string> & build_ids_to_filenames)443 bool PerfReader::Localize(
444     const std::map<string, string>& build_ids_to_filenames) {
445   std::map<string, string> filename_map;
446   for (auto& build_id : *proto_->mutable_build_ids()) {
447     string build_id_string = RawDataToHexString(build_id.build_id_hash());
448     auto find_result = build_ids_to_filenames.find(build_id_string);
449     if (find_result == build_ids_to_filenames.end()) continue;
450     const string& new_filename = find_result->second;
451     filename_map[build_id.filename()] = new_filename;
452   }
453 
454   return LocalizeUsingFilenames(filename_map);
455 }
456 
LocalizeUsingFilenames(const std::map<string,string> & filename_map)457 bool PerfReader::LocalizeUsingFilenames(
458     const std::map<string, string>& filename_map) {
459   LocalizeMMapFilenames(filename_map);
460   for (auto& build_id : *proto_->mutable_build_ids()) {
461     auto find_result = filename_map.find(build_id.filename());
462     if (find_result != filename_map.end())
463       build_id.set_filename(find_result->second);
464   }
465   return true;
466 }
467 
GetFilenames(std::vector<string> * filenames) const468 void PerfReader::GetFilenames(std::vector<string>* filenames) const {
469   std::set<string> filename_set;
470   GetFilenamesAsSet(&filename_set);
471   filenames->clear();
472   filenames->insert(filenames->begin(), filename_set.begin(),
473                     filename_set.end());
474 }
475 
GetFilenamesAsSet(std::set<string> * filenames) const476 void PerfReader::GetFilenamesAsSet(std::set<string>* filenames) const {
477   filenames->clear();
478   for (const PerfEvent& event : proto_->events()) {
479     if (event.header().type() == PERF_RECORD_MMAP ||
480         event.header().type() == PERF_RECORD_MMAP2) {
481       filenames->insert(event.mmap_event().filename());
482     }
483   }
484 }
485 
GetFilenamesToBuildIDs(std::map<string,string> * filenames_to_build_ids) const486 void PerfReader::GetFilenamesToBuildIDs(
487     std::map<string, string>* filenames_to_build_ids) const {
488   filenames_to_build_ids->clear();
489   for (const auto& build_id : proto_->build_ids()) {
490     string build_id_string = RawDataToHexString(build_id.build_id_hash());
491     PerfizeBuildIDString(&build_id_string);
492     (*filenames_to_build_ids)[build_id.filename()] = build_id_string;
493   }
494 }
495 
MaybeSortEventsByTime()496 void PerfReader::MaybeSortEventsByTime() {
497   // Events can not be sorted by time if PERF_SAMPLE_TIME is not set in
498   // attr.sample_type for all attrs.
499   for (const auto& attr : attrs()) {
500     if (!(attr.attr().sample_type() & PERF_SAMPLE_TIME)) {
501       return;
502     }
503   }
504 
505   // Sort the events based on timestamp.
506 
507   // This sorts the pointers in the proto-internal vector, which
508   // requires no copying and less external space.
509   std::stable_sort(proto_->mutable_events()->pointer_begin(),
510                    proto_->mutable_events()->pointer_end(), CompareEventTimes);
511 }
512 
ReadHeader(DataReader * data)513 bool PerfReader::ReadHeader(DataReader* data) {
514   CheckNoEventHeaderPadding();
515   // The header is the first thing to be read. Don't use SeekSet(0) because it
516   // doesn't make sense for piped files. Instead, verify that the reader points
517   // to the start of the data.
518   CHECK_EQ(0U, data->Tell());
519   if (!data->ReadUint64(&piped_header_.magic)) {
520     LOG(ERROR) << "Error reading header magic number.";
521     return false;
522   }
523 
524   if (piped_header_.magic != kPerfMagic &&
525       piped_header_.magic != bswap_64(kPerfMagic)) {
526     // clang-format off
527     LOG(ERROR) << "Read wrong magic. Expected: 0x" << std::hex << kPerfMagic
528                << " or 0x" << std::hex << bswap_64(kPerfMagic)
529                << " Got: 0x" << std::hex << piped_header_.magic;
530     // clang-format on
531     return false;
532   }
533   is_cross_endian_ = (piped_header_.magic != kPerfMagic);
534   data->set_is_cross_endian(is_cross_endian_);
535 
536   if (!data->ReadUint64(&piped_header_.size)) {
537     LOG(ERROR) << "Error reading header size.";
538     return false;
539   }
540 
541   CHECK_EQ(data->Tell(), sizeof(piped_header_));
542 
543   // Header can be a piped header.
544   if (piped_header_.size == sizeof(piped_header_)) return true;
545 
546   // Read as a non-piped header.
547   if (!data->ReadUint64(&header_.attr_size)) {
548     LOG(ERROR) << "Error reading header::attr_size.";
549     return false;
550   }
551   if (!ReadPerfFileSection(data, &header_.attrs) ||
552       !ReadPerfFileSection(data, &header_.data) ||
553       !ReadPerfFileSection(data, &header_.event_types)) {
554     LOG(ERROR) << "Error reading header file section info.";
555     return false;
556   }
557 
558   const size_t features_size = sizeof(header_.adds_features);
559   CHECK_EQ(data->Tell(), sizeof(header_) - features_size);
560 
561   if (!data->ReadData(features_size, header_.adds_features)) {
562     LOG(ERROR) << "Error reading header::adds_features.";
563     return false;
564   }
565   proto_->set_metadata_mask(0, header_.adds_features[0]);
566 
567   // Byte-swapping |adds_features| is tricky. It is defined as an array of
568   // unsigned longs, which can vary between architectures. However, the overall
569   // size of the array in bytes is fixed.
570   //
571   // According to perf's perf_file_header__read() function, the hostname feature
572   // should always be set. Try byte-swapping as uint64s first and check the
573   // hostname bit. If it's not set, then try swapping as uint32s. This is
574   // similar to the algorithm used in perf.
575   if (data->is_cross_endian()) {
576     static_assert(sizeof(header_.adds_features[0]) == sizeof(uint32_t) ||
577                       sizeof(header_.adds_features[0]) == sizeof(uint64_t),
578                   "|header_.adds_features| must be defined as an array of "
579                   "either 32-bit or 64-bit words.");
580 
581     uint64_t features64 = 0;
582     // Some compilers will complain if we directly cast |header_.adds_features|
583     // to a uint64_t*. Instead, determine the first uint64_t without using
584     // pointer aliasing.
585     if (sizeof(header_.adds_features[0]) == sizeof(uint64_t)) {
586       features64 = bswap_64(header_.adds_features[0]);
587     } else {
588       // If the native |adds_features| is composed of 32-bit words, swap the
589       // byte order of each word and then swap their positions to create a
590       // 64-bit word.
591       features64 = static_cast<uint64_t>(bswap_32(header_.adds_features[0]))
592                    << 32;
593       features64 |= bswap_32(header_.adds_features[1]);
594     }
595     if (features64 & (1 << HEADER_HOSTNAME)) {
596       for (size_t i = 0; i < features_size / sizeof(uint64_t); ++i)
597         ByteSwap(reinterpret_cast<uint64_t*>(header_.adds_features) + i);
598     } else {
599       for (size_t i = 0; i < features_size / sizeof(uint32_t); ++i)
600         ByteSwap(reinterpret_cast<uint32_t*>(header_.adds_features) + i);
601     }
602   }
603 
604   return true;
605 }
606 
ReadAttrsSection(DataReader * data)607 bool PerfReader::ReadAttrsSection(DataReader* data) {
608   size_t num_attrs = header_.attrs.size / header_.attr_size;
609   if (header_.attrs.size % header_.attr_size != 0) {
610     LOG(ERROR) << "Total size of attrs " << header_.attrs.size
611                << " is not a multiple of attr size " << header_.attr_size;
612   }
613   data->SeekSet(header_.attrs.offset);
614   for (size_t i = 0; i < num_attrs; i++) {
615     if (!ReadAttr(data)) return false;
616   }
617   return true;
618 }
619 
ReadAttr(DataReader * data)620 bool PerfReader::ReadAttr(DataReader* data) {
621   PerfFileAttr attr;
622   if (!ReadEventAttr(data, &attr.attr)) return false;
623 
624   perf_file_section ids;
625   if (!ReadPerfFileSection(data, &ids)) return false;
626 
627   // The ID may be stored at a different location in the file than where we're
628   // currently reading.
629   size_t saved_offset = data->Tell();
630   data->SeekSet(ids.offset);
631 
632   size_t num_ids = ids.size / sizeof(decltype(attr.ids)::value_type);
633   if (!ReadUniqueIDs(data, num_ids, &attr.ids)) return false;
634   data->SeekSet(saved_offset);
635   AddPerfFileAttr(attr);
636 
637   return true;
638 }
639 
ReadEventAttr(DataReader * data,perf_event_attr * attr)640 bool PerfReader::ReadEventAttr(DataReader* data, perf_event_attr* attr) {
641   CheckNoPerfEventAttrPadding();
642   *attr = {0};
643 
644   static_assert(
645       offsetof(struct perf_event_attr, size) == sizeof(perf_event_attr::type),
646       "type and size should be the first to fields of perf_event_attr");
647 
648   if (!data->ReadUint32(&attr->type) || !data->ReadUint32(&attr->size)) {
649     LOG(ERROR) << "Error reading event attr type and size.";
650     return false;
651   }
652 
653   // Now read the rest of the attr struct.
654   const size_t attr_offset = sizeof(attr->type) + sizeof(attr->size);
655   const size_t attr_readable_size =
656       std::min(static_cast<size_t>(attr->size), sizeof(*attr));
657   if (!data->ReadDataValue(attr_readable_size - attr_offset, "attribute",
658                            reinterpret_cast<char*>(attr) + attr_offset)) {
659     return false;
660   }
661   data->SeekSet(data->Tell() + attr->size - attr_readable_size);
662 
663   if (data->is_cross_endian()) {
664     // Depending on attr->size, some of these might not have actually been
665     // read. This is okay: they are zero.
666     ByteSwap(&attr->type);
667     ByteSwap(&attr->size);
668     ByteSwap(&attr->config);
669     ByteSwap(&attr->sample_period);
670     ByteSwap(&attr->sample_type);
671     ByteSwap(&attr->read_format);
672 
673     // NB: This will also reverse precise_ip : 2 as if it was two fields:
674     auto* const bitfield_start = &attr->read_format + 1;
675     SwapBitfieldOfBits(reinterpret_cast<u8*>(bitfield_start), sizeof(u64));
676     // ... So swap it back:
677     const auto tmp = attr->precise_ip;
678     attr->precise_ip = (tmp & 0x2) >> 1 | (tmp & 0x1) << 1;
679 
680     ByteSwap(&attr->wakeup_events);  // union with wakeup_watermark
681     ByteSwap(&attr->bp_type);
682     ByteSwap(&attr->bp_addr);  // union with config1
683     ByteSwap(&attr->bp_len);   // union with config2
684     ByteSwap(&attr->branch_sample_type);
685     ByteSwap(&attr->sample_regs_user);
686     ByteSwap(&attr->sample_stack_user);
687   }
688 
689   // The actual perf_event_attr data size might be different from the size of
690   // the struct definition.  Check against perf_event_attr's |size| field.
691   attr->size = sizeof(*attr);
692 
693   return true;
694 }
695 
ReadUniqueIDs(DataReader * data,size_t num_ids,std::vector<u64> * ids)696 bool PerfReader::ReadUniqueIDs(DataReader* data, size_t num_ids,
697                                std::vector<u64>* ids) {
698   ids->resize(num_ids);
699   for (u64& id : *ids) {
700     if (!data->ReadUint64(&id)) {
701       LOG(ERROR) << "Error reading unique ID.";
702       return false;
703     }
704   }
705   return true;
706 }
707 
ReadEventTypesSection(DataReader * data)708 bool PerfReader::ReadEventTypesSection(DataReader* data) {
709   int num_event_types =
710       header_.event_types.size / sizeof(struct perf_trace_event_type);
711   if (num_event_types == 0) {
712     // Not available.
713     return true;
714   }
715   CHECK_EQ(proto_->file_attrs().size(), num_event_types);
716   CHECK_EQ(sizeof(perf_trace_event_type) * num_event_types,
717            header_.event_types.size);
718   data->SeekSet(header_.event_types.offset);
719   for (int i = 0; i < num_event_types; ++i) {
720     if (!ReadEventType(data, i, 0)) return false;
721   }
722   return true;
723 }
724 
ReadEventType(DataReader * data,int attr_idx,size_t event_size)725 bool PerfReader::ReadEventType(DataReader* data, int attr_idx,
726                                size_t event_size) {
727   CheckNoEventTypePadding();
728   decltype(perf_trace_event_type::event_id) event_id;
729 
730   if (!data->ReadUint64(&event_id)) {
731     LOG(ERROR) << "Error reading event ID.";
732     return false;
733   }
734 
735   size_t event_name_len;
736   if (event_size == 0) {  // Not in an event.
737     event_name_len = sizeof(perf_trace_event_type::name);
738   } else {
739     event_name_len = event_size - sizeof(perf_event_header) - sizeof(event_id);
740   }
741 
742   PerfFileAttr attr;
743   if (!data->ReadString(event_name_len, &attr.name)) {
744     LOG(ERROR) << "Not enough data left in data to read event name.";
745     return false;
746   }
747 
748   if (attr_idx >= proto_->file_attrs().size()) {
749     LOG(ERROR) << "Too many event types, or attrs not read yet!";
750     return false;
751   }
752   if (event_id != proto_->file_attrs(attr_idx).attr().config()) {
753     LOG(ERROR) << "event_id for perf_trace_event_type (" << event_id << ") "
754                << "does not match attr.config ("
755                << proto_->file_attrs(attr_idx).attr().config() << ")";
756     return false;
757   }
758   attr.attr.config = proto_->file_attrs(attr_idx).attr().config();
759 
760   serializer_.SerializePerfEventType(attr, proto_->add_event_types());
761   return true;
762 }
763 
ReadDataSection(DataReader * data)764 bool PerfReader::ReadDataSection(DataReader* data) {
765   u64 data_remaining_bytes = header_.data.size;
766   data->SeekSet(header_.data.offset);
767   while (data_remaining_bytes != 0) {
768     // Read the header to determine the size of the event.
769     perf_event_header header;
770     if (!ReadPerfEventHeader(data, &header)) {
771       LOG(ERROR) << "Error reading event header from data section.";
772       return false;
773     }
774 
775     // Read the rest of the event data.
776     malloced_unique_ptr<event_t> event(CallocMemoryForEvent(header.size));
777     event->header = header;
778     if (!data->ReadDataValue(event->header.size - sizeof(event->header),
779                              "rest of event", &event->header + 1)) {
780       return false;
781     }
782     MaybeSwapEventFields(event.get(), data->is_cross_endian());
783 
784     // We must have a valid way to read sample info before reading perf events.
785     CHECK(serializer_.SampleInfoReaderAvailable());
786 
787     // Serialize the event to protobuf form.
788     PerfEvent* proto_event = proto_->add_events();
789     if (!serializer_.SerializeEvent(event, proto_event)) return false;
790 
791     if (proto_event->header().type() == PERF_RECORD_AUXTRACE) {
792       if (!ReadAuxtraceTraceData(data, proto_event)) return false;
793       data_remaining_bytes -= proto_event->auxtrace_event().size();
794     }
795     data_remaining_bytes -= event->header.size;
796   }
797 
798   DLOG(INFO) << "Number of events stored: " << proto_->events_size();
799   return true;
800 }
801 
ReadMetadata(DataReader * data)802 bool PerfReader::ReadMetadata(DataReader* data) {
803   // Metadata comes after the event data.
804   data->SeekSet(header_.data.offset + header_.data.size);
805 
806   // Read the (offset, size) pairs of all the metadata elements. Note that this
807   // takes into account all present metadata types, not just the ones included
808   // in |kSupportedMetadataMask|. If a metadata type is not supported, it is
809   // skipped over.
810   std::vector<struct perf_file_section> sections(GetNumBits(metadata_mask()));
811   for (struct perf_file_section& section : sections) {
812     if (!ReadPerfFileSection(data, &section)) {
813       LOG(ERROR) << "Error reading metadata entry info.";
814       return false;
815     }
816   }
817 
818   auto section_iter = sections.begin();
819   for (u32 type = HEADER_FIRST_FEATURE; type != HEADER_LAST_FEATURE; ++type) {
820     if (!get_metadata_mask_bit(type)) continue;
821     data->SeekSet(section_iter->offset);
822     u64 size = section_iter->size;
823 
824     switch (type) {
825       case HEADER_TRACING_DATA:
826         if (!ReadTracingMetadata(data, size)) return false;
827         break;
828       case HEADER_BUILD_ID:
829         if (!ReadBuildIDMetadata(data, size)) return false;
830         break;
831       case HEADER_HOSTNAME:
832         if (!ReadSingleStringMetadata(
833                 data, size,
834                 proto_->mutable_string_metadata()->mutable_hostname())) {
835           return false;
836         }
837         break;
838       case HEADER_OSRELEASE:
839         if (!ReadSingleStringMetadata(
840                 data, size,
841                 proto_->mutable_string_metadata()->mutable_kernel_version())) {
842           return false;
843         }
844         break;
845       case HEADER_VERSION:
846         if (!ReadSingleStringMetadata(
847                 data, size,
848                 proto_->mutable_string_metadata()->mutable_perf_version())) {
849           return false;
850         }
851         break;
852       case HEADER_ARCH:
853         if (!ReadSingleStringMetadata(
854                 data, size,
855                 proto_->mutable_string_metadata()->mutable_architecture())) {
856           return false;
857         }
858         break;
859       case HEADER_CPUDESC:
860         if (!ReadSingleStringMetadata(
861                 data, size,
862                 proto_->mutable_string_metadata()->mutable_cpu_description())) {
863           return false;
864         }
865         break;
866       case HEADER_CPUID:
867         if (!ReadSingleStringMetadata(
868                 data, size,
869                 proto_->mutable_string_metadata()->mutable_cpu_id())) {
870           return false;
871         }
872         break;
873       case HEADER_CMDLINE: {
874         auto* string_metadata = proto_->mutable_string_metadata();
875         if (!ReadRepeatedStringMetadata(
876                 data, size, string_metadata->mutable_perf_command_line_token(),
877                 string_metadata->mutable_perf_command_line_whole())) {
878           return false;
879         }
880         break;
881       }
882       case HEADER_NRCPUS:
883         if (!ReadUint32Metadata(data, type, size)) return false;
884         break;
885       case HEADER_TOTAL_MEM:
886         if (!ReadUint64Metadata(data, type, size)) return false;
887         break;
888       case HEADER_EVENT_DESC:
889         if (!ReadEventDescMetadata(data)) return false;
890         break;
891       case HEADER_CPU_TOPOLOGY:
892         if (!ReadCPUTopologyMetadata(data)) return false;
893         break;
894       case HEADER_NUMA_TOPOLOGY:
895         if (!ReadNUMATopologyMetadata(data)) return false;
896         break;
897       case HEADER_BRANCH_STACK:
898         break;
899       case HEADER_PMU_MAPPINGS:
900         if (!ReadPMUMappingsMetadata(data, size)) return false;
901         break;
902       case HEADER_GROUP_DESC:
903         if (!ReadGroupDescMetadata(data)) return false;
904         break;
905       default:
906         LOG(INFO) << "Unsupported metadata type, skipping: " << type;
907         break;
908     }
909     ++section_iter;
910   }
911 
912   return true;
913 }
914 
ReadBuildIDMetadata(DataReader * data,size_t size)915 bool PerfReader::ReadBuildIDMetadata(DataReader* data, size_t size) {
916   CheckNoBuildIDEventPadding();
917   while (size > 0) {
918     // Make sure there is enough data for everything but the filename.
919     perf_event_header build_id_header;
920     if (!ReadPerfEventHeader(data, &build_id_header)) {
921       LOG(ERROR) << "Error reading build ID header.";
922       return false;
923     }
924 
925     if (!ReadBuildIDMetadataWithoutHeader(data, build_id_header)) return false;
926     size -= build_id_header.size;
927   }
928 
929   return true;
930 }
931 
ReadBuildIDMetadataWithoutHeader(DataReader * data,const perf_event_header & header)932 bool PerfReader::ReadBuildIDMetadataWithoutHeader(
933     DataReader* data, const perf_event_header& header) {
934   // Allocate memory for the event.
935   malloced_unique_ptr<build_id_event> event(
936       CallocMemoryForBuildID(header.size));
937   event->header = header;
938 
939   // Make sure there is enough data for the rest of the event.
940   if (!data->ReadDataValue(header.size - sizeof(header),
941                            "rest of build ID event", &event->header + 1)) {
942     LOG(ERROR) << "Not enough bytes to read build id event";
943     return false;
944   }
945   if (data->is_cross_endian()) ByteSwap(&event->pid);
946 
947   // Perf tends to use more space than necessary, so fix the size.
948   event->header.size =
949       sizeof(*event) + GetUint64AlignedStringLength(event->filename);
950 
951   if (!serializer_.SerializeBuildIDEvent(event, proto_->add_build_ids())) {
952     LOG(ERROR) << "Could not serialize build ID event with ID "
953                << RawDataToHexString(event->build_id, sizeof(event->build_id));
954     return false;
955   }
956   return true;
957 }
958 
ReadSingleStringMetadata(DataReader * data,size_t max_readable_size,StringAndMd5sumPrefix * dest) const959 bool PerfReader::ReadSingleStringMetadata(DataReader* data,
960                                           size_t max_readable_size,
961                                           StringAndMd5sumPrefix* dest) const {
962   // If a string metadata field is present but empty, it can have a size of 0,
963   // in which case there is nothing to be read.
964   string single_string;
965   if (max_readable_size && !data->ReadStringWithSizeFromData(&single_string))
966     return false;
967   dest->set_value(single_string);
968   dest->set_value_md5_prefix(Md5Prefix(single_string));
969   return true;
970 }
971 
ReadRepeatedStringMetadata(DataReader * data,size_t max_readable_size,RepeatedPtrField<StringAndMd5sumPrefix> * dest_array,StringAndMd5sumPrefix * dest_single) const972 bool PerfReader::ReadRepeatedStringMetadata(
973     DataReader* data, size_t max_readable_size,
974     RepeatedPtrField<StringAndMd5sumPrefix>* dest_array,
975     StringAndMd5sumPrefix* dest_single) const {
976   num_string_data_type count = 1;
977   if (!data->ReadUint32(&count)) {
978     LOG(ERROR) << "Error reading string count.";
979     return false;
980   }
981   size_t size_read = sizeof(count);
982 
983   string full_string;
984   while (count-- > 0 && size_read < max_readable_size) {
985     StringAndMd5sumPrefix* new_entry = dest_array->Add();
986     size_t offset = data->Tell();
987     if (!ReadSingleStringMetadata(data, max_readable_size - size_read,
988                                   new_entry)) {
989       return false;
990     }
991 
992     if (!full_string.empty()) full_string += " ";
993     full_string += new_entry->value();
994 
995     size_read += data->Tell() - offset;
996   }
997 
998   dest_single->set_value(full_string);
999   dest_single->set_value_md5_prefix(Md5Prefix(full_string));
1000   return true;
1001 }
1002 
ReadUint32Metadata(DataReader * data,u32 type,size_t size)1003 bool PerfReader::ReadUint32Metadata(DataReader* data, u32 type, size_t size) {
1004   PerfUint32Metadata uint32_data;
1005   uint32_data.type = type;
1006 
1007   while (size > 0) {
1008     uint32_t item;
1009     if (!data->ReadUint32(&item)) {
1010       LOG(ERROR) << "Error reading uint32 metadata";
1011       return false;
1012     }
1013 
1014     uint32_data.data.push_back(item);
1015     size -= sizeof(item);
1016   }
1017 
1018   serializer_.SerializeSingleUint32Metadata(uint32_data,
1019                                             proto_->add_uint32_metadata());
1020   return true;
1021 }
1022 
ReadUint64Metadata(DataReader * data,u32 type,size_t size)1023 bool PerfReader::ReadUint64Metadata(DataReader* data, u32 type, size_t size) {
1024   PerfUint64Metadata uint64_data;
1025   uint64_data.type = type;
1026 
1027   while (size > 0) {
1028     uint64_t item;
1029     if (!data->ReadUint64(&item)) {
1030       LOG(ERROR) << "Error reading uint64 metadata";
1031       return false;
1032     }
1033 
1034     uint64_data.data.push_back(item);
1035     size -= sizeof(item);
1036   }
1037 
1038   serializer_.SerializeSingleUint64Metadata(uint64_data,
1039                                             proto_->add_uint64_metadata());
1040   return true;
1041 }
ReadEventDescMetadata(DataReader * data)1042 bool PerfReader::ReadEventDescMetadata(DataReader* data) {
1043   // Structure:
1044   // u32 nr_events
1045   // u32 sizeof(perf_event_attr)
1046   // foreach event (nr_events):
1047   //   struct perf_event_attr
1048   //   u32 nr_ids
1049   //   event name (len & string, 64-bit padded)
1050   //   u64 ids[nr_ids]
1051 
1052   u32 nr_events;
1053   if (!data->ReadUint32(&nr_events)) {
1054     LOG(ERROR) << "Error reading event_desc nr_events.";
1055     return false;
1056   }
1057 
1058   u32 attr_size;
1059   if (!data->ReadUint32(&attr_size)) {
1060     LOG(ERROR) << "Error reading event_desc attr_size.";
1061     return false;
1062   }
1063 
1064   file_attrs_seen_.clear();
1065   proto_->clear_file_attrs();
1066   proto_->mutable_file_attrs()->Reserve(nr_events);
1067 
1068   for (u32 i = 0; i < nr_events; i++) {
1069     PerfFileAttr attr;
1070     if (!ReadEventAttr(data, &attr.attr)) return false;
1071 
1072     u32 nr_ids;
1073     if (!data->ReadUint32(&nr_ids)) {
1074       LOG(ERROR) << "Error reading event_desc nr_ids.";
1075       return false;
1076     }
1077 
1078     if (!data->ReadStringWithSizeFromData(&attr.name)) return false;
1079     std::vector<u64>& ids = attr.ids;
1080     ids.resize(nr_ids);
1081     for (u64& id : ids) {
1082       if (!data->ReadUint64(&id)) {
1083         LOG(ERROR) << "Error reading ID value for attr #" << i;
1084         return false;
1085       }
1086     }
1087     AddPerfFileAttr(attr);
1088     // The EVENT_DESC metadata is the newer replacement for the older event type
1089     // fields. In the protobuf, both types of data are stored in the
1090     // |event_types| field.
1091     serializer_.SerializePerfEventType(attr, proto_->add_event_types());
1092   }
1093   return true;
1094 }
1095 
ReadCPUTopologyMetadata(DataReader * data)1096 bool PerfReader::ReadCPUTopologyMetadata(DataReader* data) {
1097   num_siblings_type num_core_siblings;
1098   if (!data->ReadUint32(&num_core_siblings)) {
1099     LOG(ERROR) << "Error reading num core siblings.";
1100     return false;
1101   }
1102 
1103   PerfCPUTopologyMetadata cpu_topology;
1104   cpu_topology.core_siblings.resize(num_core_siblings);
1105   for (size_t i = 0; i < num_core_siblings; ++i) {
1106     if (!data->ReadStringWithSizeFromData(&cpu_topology.core_siblings[i]))
1107       return false;
1108   }
1109 
1110   num_siblings_type num_thread_siblings;
1111   if (!data->ReadUint32(&num_thread_siblings)) {
1112     LOG(ERROR) << "Error reading num core siblings.";
1113     return false;
1114   }
1115 
1116   cpu_topology.thread_siblings.resize(num_thread_siblings);
1117   for (size_t i = 0; i < num_thread_siblings; ++i) {
1118     if (!data->ReadStringWithSizeFromData(&cpu_topology.thread_siblings[i]))
1119       return false;
1120   }
1121 
1122   serializer_.SerializeCPUTopologyMetadata(cpu_topology,
1123                                            proto_->mutable_cpu_topology());
1124   return true;
1125 }
1126 
ReadNUMATopologyMetadata(DataReader * data)1127 bool PerfReader::ReadNUMATopologyMetadata(DataReader* data) {
1128   numa_topology_num_nodes_type num_nodes;
1129   if (!data->ReadUint32(&num_nodes)) {
1130     LOG(ERROR) << "Error reading NUMA topology num nodes.";
1131     return false;
1132   }
1133 
1134   for (size_t i = 0; i < num_nodes; ++i) {
1135     PerfNodeTopologyMetadata node;
1136     if (!data->ReadUint32(&node.id) || !data->ReadUint64(&node.total_memory) ||
1137         !data->ReadUint64(&node.free_memory) ||
1138         !data->ReadStringWithSizeFromData(&node.cpu_list)) {
1139       LOG(ERROR) << "Error reading NUMA topology info for node #" << i;
1140       return false;
1141     }
1142     serializer_.SerializeNodeTopologyMetadata(node,
1143                                               proto_->add_numa_topology());
1144   }
1145   return true;
1146 }
1147 
ReadPMUMappingsMetadata(DataReader * data,size_t size)1148 bool PerfReader::ReadPMUMappingsMetadata(DataReader* data, size_t size) {
1149   pmu_mappings_num_mappings_type num_mappings;
1150   auto begin_offset = data->Tell();
1151   if (!data->ReadUint32(&num_mappings)) {
1152     LOG(ERROR) << "Error reading the number of PMU mappings.";
1153     return false;
1154   }
1155 
1156   // Check size of the data read in addition to the iteration based on the
1157   // number of PMU mappings because the number of pmu mappings is always zero
1158   // in piped perf.data file.
1159   //
1160   // The number of PMU mappings is initialized to zero and after all the
1161   // mappings are wirtten to the perf.data files, this value is set to the
1162   // number of PMU mappings written. This logic doesn't work in pipe mode. So,
1163   // the number of PMU mappings is always zero.
1164   // Fix to write the number of PMU mappings before writing the actual PMU
1165   // mappings landed upstream in 4.14. But the check for size is required as
1166   // long as there are machines with older version of perf.
1167   for (u32 i = 0; i < num_mappings || data->Tell() - begin_offset < size; ++i) {
1168     PerfPMUMappingsMetadata mapping;
1169     if (!data->ReadUint32(&mapping.type) ||
1170         !data->ReadStringWithSizeFromData(&mapping.name)) {
1171       LOG(ERROR) << "Error reading PMU mapping info for mapping #" << i;
1172       return false;
1173     }
1174     serializer_.SerializePMUMappingsMetadata(mapping,
1175                                              proto_->add_pmu_mappings());
1176   }
1177   if (data->Tell() - begin_offset != size) {
1178     LOG(ERROR) << "Size from the header doesn't match the read size";
1179     return false;
1180   }
1181   return true;
1182 }
1183 
ReadGroupDescMetadata(DataReader * data)1184 bool PerfReader::ReadGroupDescMetadata(DataReader* data) {
1185   group_desc_num_groups_type num_groups;
1186   if (!data->ReadUint32(&num_groups)) {
1187     LOG(ERROR) << "Error reading group desc num groups.";
1188     return false;
1189   }
1190 
1191   for (u32 i = 0; i < num_groups; ++i) {
1192     PerfGroupDescMetadata group;
1193     if (!data->ReadStringWithSizeFromData(&group.name) ||
1194         !data->ReadUint32(&group.leader_idx) ||
1195         !data->ReadUint32(&group.num_members)) {
1196       LOG(ERROR) << "Error reading group desc info for group #" << i;
1197       return false;
1198     }
1199     serializer_.SerializeGroupDescMetadata(group, proto_->add_group_desc());
1200   }
1201   return true;
1202 }
ReadTracingMetadata(DataReader * data,size_t size)1203 bool PerfReader::ReadTracingMetadata(DataReader* data, size_t size) {
1204   std::vector<char> tracing_data(size);
1205   if (!data->ReadDataValue(tracing_data.size(), "tracing_data",
1206                            tracing_data.data())) {
1207     return false;
1208   }
1209   serializer_.SerializeTracingMetadata(tracing_data, proto_);
1210   return true;
1211 }
1212 
ReadFileData(DataReader * data)1213 bool PerfReader::ReadFileData(DataReader* data) {
1214   // Make sure sections are within the size of the file. This check prevents
1215   // more obscure messages later when attempting to read from one of these
1216   // sections.
1217   if (header_.attrs.offset + header_.attrs.size > data->size()) {
1218     LOG(ERROR) << "Header says attrs section ends at "
1219                << header_.attrs.offset + header_.attrs.size
1220                << " bytes, which is larger than perf data size of "
1221                << data->size() << " bytes.";
1222     return false;
1223   }
1224   if (header_.data.offset + header_.data.size > data->size()) {
1225     LOG(ERROR) << "Header says data section ends at "
1226                << header_.data.offset + header_.data.size
1227                << " bytes, which is larger than perf data size of "
1228                << data->size() << " bytes.";
1229     return false;
1230   }
1231   if (header_.event_types.offset + header_.event_types.size > data->size()) {
1232     LOG(ERROR) << "Header says event_types section ends at "
1233                << header_.event_types.offset + header_.event_types.size
1234                << " bytes, which is larger than perf data size of "
1235                << data->size() << " bytes.";
1236     return false;
1237   }
1238 
1239   if (!get_metadata_mask_bit(HEADER_EVENT_DESC)) {
1240     // Prefer to read attrs and event names from HEADER_EVENT_DESC metadata if
1241     // available. event_types section of perf.data is obsolete, but use it as
1242     // a fallback:
1243     if (!(ReadAttrsSection(data) && ReadEventTypesSection(data))) return false;
1244   }
1245 
1246   if (!(ReadMetadata(data) && ReadDataSection(data))) return false;
1247 
1248   // We can construct HEADER_EVENT_DESC from attrs and event types.
1249   // NB: Can't set this before ReadMetadata(), or it may misread the metadata.
1250   if (!event_types().empty()) set_metadata_mask_bit(HEADER_EVENT_DESC);
1251 
1252   return true;
1253 }
1254 
ReadPipedData(DataReader * data)1255 bool PerfReader::ReadPipedData(DataReader* data) {
1256   // The piped data comes right after the file header.
1257   CHECK_EQ(piped_header_.size, data->Tell());
1258   bool result = true;
1259   int num_event_types = 0;
1260 
1261   CheckNoEventHeaderPadding();
1262 
1263   while (result && data->Tell() < data->size()) {
1264     perf_event_header header;
1265     if (!ReadPerfEventHeader(data, &header)) {
1266       LOG(ERROR) << "Error reading event header.";
1267       break;
1268     }
1269 
1270     if (header.size == 0) {
1271       // Avoid an infinite loop.
1272       LOG(ERROR) << "Event size is zero. Type: " << header.type;
1273       return false;
1274     }
1275 
1276     // Compute the size of the post-header part of the event data.
1277     size_t size_without_header = header.size - sizeof(header);
1278 
1279     bool isHeaderEventType = [&] {
1280       switch (header.type) {
1281         case PERF_RECORD_HEADER_ATTR:
1282         case PERF_RECORD_HEADER_EVENT_TYPE:
1283         case PERF_RECORD_HEADER_TRACING_DATA:
1284         case PERF_RECORD_HEADER_BUILD_ID:
1285           return true;
1286         default:
1287           return false;
1288       }
1289     }();
1290 
1291     if (!isHeaderEventType) {
1292       // Allocate space for an event struct based on the size in the header.
1293       // Don't blindly allocate the entire event_t because it is a
1294       // variable-sized type that may include data beyond what's nominally
1295       // declared in its definition.
1296       malloced_unique_ptr<event_t> event(CallocMemoryForEvent(header.size));
1297       event->header = header;
1298 
1299       // Read the rest of the event data.
1300       if (!data->ReadDataValue(size_without_header, "rest of piped event",
1301                                &event->header + 1)) {
1302         break;
1303       }
1304       MaybeSwapEventFields(event.get(), data->is_cross_endian());
1305 
1306       // Serialize the event to protobuf form.
1307       PerfEvent* proto_event = proto_->add_events();
1308       if (!serializer_.SerializeEvent(event, proto_event)) return false;
1309 
1310       if (proto_event->header().type() == PERF_RECORD_AUXTRACE) {
1311         if (!ReadAuxtraceTraceData(data, proto_event)) return false;
1312       }
1313       continue;
1314     }
1315 
1316     result = [&] {
1317       switch (header.type) {
1318         case PERF_RECORD_HEADER_ATTR:
1319           return ReadAttrEventBlock(data, size_without_header);
1320         case PERF_RECORD_HEADER_EVENT_TYPE:
1321           return ReadEventType(data, num_event_types++, header.size);
1322         case PERF_RECORD_HEADER_TRACING_DATA:
1323           set_metadata_mask_bit(HEADER_TRACING_DATA);
1324           {
1325             // TRACING_DATA's header.size is a lie. It is the size of only the
1326             // event struct. The size of the data is in the event struct, and
1327             // followed immediately by the tracing header data.
1328             decltype(tracing_data_event::size) size = 0;
1329             if (!data->ReadUint32(&size)) {
1330               LOG(ERROR) << "Error reading tracing data size.";
1331               return false;
1332             }
1333             return ReadTracingMetadata(data, size);
1334           }
1335         case PERF_RECORD_HEADER_BUILD_ID:
1336           set_metadata_mask_bit(HEADER_BUILD_ID);
1337           return ReadBuildIDMetadataWithoutHeader(data, header);
1338         default:
1339           // For unsupported event types, log a warning only if the type is an
1340           // unknown type.
1341           if (header.type < PERF_RECORD_USER_TYPE_START ||
1342               header.type >= PERF_RECORD_HEADER_MAX) {
1343             LOG(WARNING) << "Unknown event type: " << header.type;
1344           }
1345           // Skip over the data in this event.
1346           data->SeekSet(data->Tell() + size_without_header);
1347           return true;
1348       }
1349     }();
1350   }
1351 
1352   if (!result) return false;
1353 
1354   // The PERF_RECORD_HEADER_EVENT_TYPE events are obsolete, but if present
1355   // and PERF_RECORD_HEADER_EVENT_DESC metadata events are not, we should use
1356   // them. Otherwise, we should use prefer the _EVENT_DESC data.
1357   if (!get_metadata_mask_bit(HEADER_EVENT_DESC) &&
1358       num_event_types == proto_->file_attrs().size()) {
1359     // We can construct HEADER_EVENT_DESC:
1360     set_metadata_mask_bit(HEADER_EVENT_DESC);
1361   }
1362 
1363   return result;
1364 }
1365 
ReadAuxtraceTraceData(DataReader * data,PerfEvent * proto_event)1366 bool PerfReader::ReadAuxtraceTraceData(DataReader* data,
1367                                        PerfEvent* proto_event) {
1368   std::vector<char> trace_data(proto_event->auxtrace_event().size());
1369   if (!data->ReadDataValue(trace_data.size(),
1370                            "trace date from PERF_RECORD_AUXTRACE event",
1371                            trace_data.data())) {
1372     return false;
1373   }
1374   if (data->is_cross_endian()) {
1375     LOG(ERROR) << "Cannot byteswap trace data from PERF_RECORD_AUXTRACE";
1376   }
1377   if (!serializer_.SerializeAuxtraceEventTraceData(
1378           trace_data, proto_event->mutable_auxtrace_event())) {
1379     return false;
1380   }
1381   return true;
1382 }
1383 
WriteHeader(const struct perf_file_header & header,DataWriter * data) const1384 bool PerfReader::WriteHeader(const struct perf_file_header& header,
1385                              DataWriter* data) const {
1386   CheckNoEventHeaderPadding();
1387   size_t size = sizeof(header);
1388   return data->WriteDataValue(&header, size, "file header");
1389 }
1390 
WriteAttrs(const struct perf_file_header & header,DataWriter * data) const1391 bool PerfReader::WriteAttrs(const struct perf_file_header& header,
1392                             DataWriter* data) const {
1393   CheckNoPerfEventAttrPadding();
1394   const size_t id_offset = header.size;
1395   CHECK_EQ(id_offset, data->Tell());
1396 
1397   std::vector<struct perf_file_section> id_sections;
1398   id_sections.reserve(attrs().size());
1399   for (const auto& attr : proto_->file_attrs()) {
1400     size_t section_size =
1401         attr.ids_size() * sizeof(decltype(PerfFileAttr::ids)::value_type);
1402     id_sections.push_back(perf_file_section{data->Tell(), section_size});
1403     for (const uint64_t& id : attr.ids()) {
1404       if (!data->WriteDataValue(&id, sizeof(id), "ID info")) return false;
1405     }
1406   }
1407 
1408   CHECK_EQ(header.attrs.offset, data->Tell());
1409   for (int i = 0; i < attrs().size(); i++) {
1410     const struct perf_file_section& id_section = id_sections[i];
1411     PerfFileAttr attr;
1412     serializer_.DeserializePerfFileAttr(proto_->file_attrs(i), &attr);
1413     if (!data->WriteDataValue(&attr.attr, sizeof(attr.attr), "attribute") ||
1414         !data->WriteDataValue(&id_section, sizeof(id_section), "ID section")) {
1415       return false;
1416     }
1417   }
1418   return true;
1419 }
1420 
WriteData(const struct perf_file_header & header,DataWriter * data) const1421 bool PerfReader::WriteData(const struct perf_file_header& header,
1422                            DataWriter* data) const {
1423   // No need to CHECK anything if no event data is being written.
1424   if (proto_->events().empty()) return true;
1425 
1426   CHECK(serializer_.SampleInfoReaderAvailable());
1427   CHECK_EQ(header.data.offset, data->Tell());
1428   for (const PerfEvent& proto_event : proto_->events()) {
1429     malloced_unique_ptr<event_t> event;
1430     // The nominal size given by |proto_event| may not be correct, as the
1431     // contents may have changed since the PerfEvent was created. Use the size
1432     // in the event_t returned by PerfSerializer::DeserializeEvent().
1433     if (!serializer_.DeserializeEvent(proto_event, &event) ||
1434         !data->WriteDataValue(event.get(), event->header.size, "event data")) {
1435       return false;
1436     }
1437     // PERF_RECORD_AUXTRACE contains trace data that is written after writing
1438     // the actual event data.
1439     if (proto_event.header().type() == PERF_RECORD_AUXTRACE &&
1440         proto_event.auxtrace_event().size() > 0) {
1441       std::vector<char> trace_data;
1442       if (!serializer_.DeserializeAuxtraceEventTraceData(
1443               proto_event.auxtrace_event(), &trace_data) ||
1444           !data->WriteDataValue(reinterpret_cast<void*>(trace_data.data()),
1445                                 trace_data.size(),
1446                                 "trace data from PERF_RECORD_AUXTRACE event")) {
1447         return false;
1448       }
1449     }
1450   }
1451   return true;
1452 }
1453 
WriteMetadata(const struct perf_file_header & header,DataWriter * data) const1454 bool PerfReader::WriteMetadata(const struct perf_file_header& header,
1455                                DataWriter* data) const {
1456   const size_t header_offset = header.data.offset + header.data.size;
1457   CHECK_EQ(header_offset, data->Tell());
1458 
1459   // There is one header for each feature pointing to the metadata for that
1460   // feature. If a feature has no metadata, the size field is zero.
1461   const size_t headers_size =
1462       GetNumSupportedMetadata() * sizeof(perf_file_section);
1463   const size_t metadata_offset = header_offset + headers_size;
1464   data->SeekSet(metadata_offset);
1465 
1466   // Record the new metadata offsets and sizes in this vector of info entries.
1467   std::vector<struct perf_file_section> metadata_sections;
1468   metadata_sections.reserve(GetNumSupportedMetadata());
1469 
1470   // For less verbose access to string metadata fields.
1471   const auto& string_metadata = proto_->string_metadata();
1472 
1473   for (u32 type = HEADER_FIRST_FEATURE; type != HEADER_LAST_FEATURE; ++type) {
1474     if ((header.adds_features[0] & (1 << type)) == 0) continue;
1475 
1476     struct perf_file_section header_entry;
1477     header_entry.offset = data->Tell();
1478     // Write actual metadata to address metadata_offset
1479     switch (type) {
1480       case HEADER_TRACING_DATA:
1481         if (!data->WriteDataValue(tracing_data().data(), tracing_data().size(),
1482                                   "tracing data")) {
1483           return false;
1484         }
1485         break;
1486       case HEADER_BUILD_ID:
1487         if (!WriteBuildIDMetadata(type, data)) return false;
1488         break;
1489       case HEADER_HOSTNAME:
1490         if (!WriteSingleStringMetadata(string_metadata.hostname(), data))
1491           return false;
1492         break;
1493       case HEADER_OSRELEASE:
1494         if (!WriteSingleStringMetadata(string_metadata.kernel_version(), data))
1495           return false;
1496         break;
1497       case HEADER_VERSION:
1498         if (!WriteSingleStringMetadata(string_metadata.perf_version(), data))
1499           return false;
1500         break;
1501       case HEADER_ARCH:
1502         if (!WriteSingleStringMetadata(string_metadata.architecture(), data))
1503           return false;
1504         break;
1505       case HEADER_CPUDESC:
1506         if (!WriteSingleStringMetadata(string_metadata.cpu_description(), data))
1507           return false;
1508         break;
1509       case HEADER_CPUID:
1510         if (!WriteSingleStringMetadata(string_metadata.cpu_id(), data))
1511           return false;
1512         break;
1513       case HEADER_CMDLINE:
1514         if (!WriteRepeatedStringMetadata(
1515                 string_metadata.perf_command_line_token(), data)) {
1516           return false;
1517         }
1518         break;
1519       case HEADER_NRCPUS:
1520         if (!WriteUint32Metadata(type, data)) return false;
1521         break;
1522       case HEADER_TOTAL_MEM:
1523         if (!WriteUint64Metadata(type, data)) return false;
1524         break;
1525       case HEADER_EVENT_DESC:
1526         if (!WriteEventDescMetadata(data)) return false;
1527         break;
1528       case HEADER_CPU_TOPOLOGY:
1529         if (!WriteCPUTopologyMetadata(data)) return false;
1530         break;
1531       case HEADER_NUMA_TOPOLOGY:
1532         if (!WriteNUMATopologyMetadata(data)) return false;
1533         break;
1534       case HEADER_BRANCH_STACK:
1535         break;
1536       case HEADER_PMU_MAPPINGS:
1537         if (!WritePMUMappingsMetadata(data)) return false;
1538         break;
1539       case HEADER_GROUP_DESC:
1540         if (!WriteGroupDescMetadata(data)) return false;
1541         break;
1542       default:
1543         LOG(ERROR) << "Unsupported metadata type: " << type;
1544         return false;
1545     }
1546 
1547     // Compute the size of the metadata that was just written. This is reflected
1548     // in how much the data write pointer has moved.
1549     header_entry.size = data->Tell() - header_entry.offset;
1550     metadata_sections.push_back(header_entry);
1551   }
1552   // Make sure we have recorded the right number of entries.
1553   CHECK_EQ(GetNumSupportedMetadata(), metadata_sections.size());
1554 
1555   // Now write the metadata offset and size info back to the metadata headers.
1556   size_t old_offset = data->Tell();
1557   data->SeekSet(header_offset);
1558   if (!data->WriteDataValue(metadata_sections.data(), headers_size,
1559                             "metadata section info")) {
1560     return false;
1561   }
1562   // Make sure the write pointer now points to the end of the metadata headers
1563   // and hence the beginning of the actual metadata.
1564   CHECK_EQ(metadata_offset, data->Tell());
1565   data->SeekSet(old_offset);
1566 
1567   return true;
1568 }
1569 
WriteBuildIDMetadata(u32 type,DataWriter * data) const1570 bool PerfReader::WriteBuildIDMetadata(u32 type, DataWriter* data) const {
1571   CheckNoBuildIDEventPadding();
1572   for (const auto& build_id : proto_->build_ids()) {
1573     malloced_unique_ptr<build_id_event> event;
1574     if (!serializer_.DeserializeBuildIDEvent(build_id, &event)) {
1575       LOG(ERROR) << "Could not deserialize build ID event with build ID "
1576                  << RawDataToHexString(build_id.build_id_hash());
1577       return false;
1578     }
1579     if (!data->WriteDataValue(event.get(), event->header.size,
1580                               "Build ID metadata")) {
1581       return false;
1582     }
1583   }
1584   return true;
1585 }
1586 
WriteSingleStringMetadata(const StringAndMd5sumPrefix & src,DataWriter * data) const1587 bool PerfReader::WriteSingleStringMetadata(const StringAndMd5sumPrefix& src,
1588                                            DataWriter* data) const {
1589   return data->WriteStringWithSizeToData(src.value());
1590 }
1591 
WriteRepeatedStringMetadata(const RepeatedPtrField<StringAndMd5sumPrefix> & src_array,DataWriter * data) const1592 bool PerfReader::WriteRepeatedStringMetadata(
1593     const RepeatedPtrField<StringAndMd5sumPrefix>& src_array,
1594     DataWriter* data) const {
1595   num_string_data_type num_strings = src_array.size();
1596   if (!data->WriteDataValue(&num_strings, sizeof(num_strings),
1597                             "number of string metadata")) {
1598     return false;
1599   }
1600   for (const auto& src_entry : src_array) {
1601     if (!data->WriteStringWithSizeToData(src_entry.value())) return false;
1602   }
1603   return true;
1604 }
1605 
WriteUint32Metadata(u32 type,DataWriter * data) const1606 bool PerfReader::WriteUint32Metadata(u32 type, DataWriter* data) const {
1607   for (const auto& metadata : proto_->uint32_metadata()) {
1608     if (metadata.type() != type) continue;
1609     PerfUint32Metadata local_metadata;
1610     serializer_.DeserializeSingleUint32Metadata(metadata, &local_metadata);
1611     const std::vector<uint32_t>& raw_data = local_metadata.data;
1612     return data->WriteDataValue(raw_data.data(),
1613                                 raw_data.size() * sizeof(uint32_t),
1614                                 "uint32_t metadata");
1615   }
1616   LOG(ERROR) << "Uint32 metadata of type " << type << " not present";
1617   return false;
1618 }
1619 
WriteUint64Metadata(u32 type,DataWriter * data) const1620 bool PerfReader::WriteUint64Metadata(u32 type, DataWriter* data) const {
1621   for (const auto& metadata : proto_->uint64_metadata()) {
1622     if (metadata.type() != type) continue;
1623     PerfUint64Metadata local_metadata;
1624     serializer_.DeserializeSingleUint64Metadata(metadata, &local_metadata);
1625     const std::vector<uint64_t>& raw_data = local_metadata.data;
1626     return data->WriteDataValue(raw_data.data(),
1627                                 raw_data.size() * sizeof(uint64_t),
1628                                 "uint32_t metadata");
1629   }
1630   LOG(ERROR) << "Uint64 metadata of type " << type << " not present";
1631   return false;
1632 }
1633 
WriteEventDescMetadata(DataWriter * data) const1634 bool PerfReader::WriteEventDescMetadata(DataWriter* data) const {
1635   CheckNoPerfEventAttrPadding();
1636 
1637   if (attrs().size() > event_types().size()) {
1638     LOG(ERROR) << "Number of attrs (" << attrs().size() << ") cannot exceed "
1639                << "number of event types (" << event_types().size() << ")";
1640     return false;
1641   }
1642 
1643   event_desc_num_events num_events = proto_->file_attrs().size();
1644   if (!data->WriteDataValue(&num_events, sizeof(num_events),
1645                             "event_desc num_events")) {
1646     return false;
1647   }
1648   event_desc_attr_size attr_size = sizeof(perf_event_attr);
1649   if (!data->WriteDataValue(&attr_size, sizeof(attr_size),
1650                             "event_desc attr_size")) {
1651     return false;
1652   }
1653 
1654   for (int i = 0; i < attrs().size(); ++i) {
1655     const auto& stored_attr = attrs().Get(i);
1656     PerfFileAttr attr;
1657     serializer_.DeserializePerfFileAttr(stored_attr, &attr);
1658     if (!serializer_.DeserializePerfEventType(proto_->event_types(i), &attr))
1659       return false;
1660 
1661     if (!data->WriteDataValue(&attr.attr, sizeof(attr.attr),
1662                               "event_desc attribute")) {
1663       return false;
1664     }
1665 
1666     event_desc_num_unique_ids num_ids = attr.ids.size();
1667     if (!data->WriteDataValue(&num_ids, sizeof(num_ids),
1668                               "event_desc num_unique_ids")) {
1669       return false;
1670     }
1671 
1672     if (!data->WriteStringWithSizeToData(attr.name)) return false;
1673 
1674     if (!data->WriteDataValue(attr.ids.data(), num_ids * sizeof(attr.ids[0]),
1675                               "event_desc unique_ids")) {
1676       return false;
1677     }
1678   }
1679   return true;
1680 }
1681 
WriteCPUTopologyMetadata(DataWriter * data) const1682 bool PerfReader::WriteCPUTopologyMetadata(DataWriter* data) const {
1683   PerfCPUTopologyMetadata cpu_topology;
1684   serializer_.DeserializeCPUTopologyMetadata(proto_->cpu_topology(),
1685                                              &cpu_topology);
1686 
1687   std::vector<string>& cores = cpu_topology.core_siblings;
1688   num_siblings_type num_cores = cores.size();
1689   if (!data->WriteDataValue(&num_cores, sizeof(num_cores), "num cores"))
1690     return false;
1691   for (string& core_name : cores) {
1692     if (!data->WriteStringWithSizeToData(core_name)) return false;
1693   }
1694 
1695   std::vector<string>& threads = cpu_topology.thread_siblings;
1696   num_siblings_type num_threads = threads.size();
1697   if (!data->WriteDataValue(&num_threads, sizeof(num_threads), "num threads"))
1698     return false;
1699   for (string& thread_name : threads) {
1700     if (!data->WriteStringWithSizeToData(thread_name)) return false;
1701   }
1702 
1703   return true;
1704 }
1705 
WriteNUMATopologyMetadata(DataWriter * data) const1706 bool PerfReader::WriteNUMATopologyMetadata(DataWriter* data) const {
1707   numa_topology_num_nodes_type num_nodes = proto_->numa_topology().size();
1708   if (!data->WriteDataValue(&num_nodes, sizeof(num_nodes), "num nodes"))
1709     return false;
1710 
1711   for (const auto& node_proto : proto_->numa_topology()) {
1712     PerfNodeTopologyMetadata node;
1713     serializer_.DeserializeNodeTopologyMetadata(node_proto, &node);
1714 
1715     if (!data->WriteDataValue(&node.id, sizeof(node.id), "node id") ||
1716         !data->WriteDataValue(&node.total_memory, sizeof(node.total_memory),
1717                               "node total memory") ||
1718         !data->WriteDataValue(&node.free_memory, sizeof(node.free_memory),
1719                               "node free memory") ||
1720         !data->WriteStringWithSizeToData(node.cpu_list)) {
1721       return false;
1722     }
1723   }
1724   return true;
1725 }
1726 
WritePMUMappingsMetadata(DataWriter * data) const1727 bool PerfReader::WritePMUMappingsMetadata(DataWriter* data) const {
1728   pmu_mappings_num_mappings_type num_mappings = proto_->pmu_mappings().size();
1729   if (!data->WriteDataValue(&num_mappings, sizeof(num_mappings),
1730                             "num mappings"))
1731     return false;
1732 
1733   for (const auto& mapping_proto : proto_->pmu_mappings()) {
1734     PerfPMUMappingsMetadata mapping;
1735     serializer_.DeserializePMUMappingsMetadata(mapping_proto, &mapping);
1736 
1737     if (!data->WriteDataValue(&mapping.type, sizeof(mapping.type),
1738                               "mapping type") ||
1739         !data->WriteStringWithSizeToData(mapping.name)) {
1740       return false;
1741     }
1742   }
1743   return true;
1744 }
1745 
WriteGroupDescMetadata(DataWriter * data) const1746 bool PerfReader::WriteGroupDescMetadata(DataWriter* data) const {
1747   group_desc_num_groups_type num_groups = proto_->group_desc().size();
1748   if (!data->WriteDataValue(&num_groups, sizeof(num_groups), "num groups"))
1749     return false;
1750 
1751   for (const auto& group_proto : proto_->group_desc()) {
1752     PerfGroupDescMetadata group;
1753     serializer_.DeserializeGroupDescMetadata(group_proto, &group);
1754 
1755     if (!data->WriteStringWithSizeToData(group.name) ||
1756         !data->WriteDataValue(&group.leader_idx, sizeof(group.leader_idx),
1757                               "group leader index") ||
1758         !data->WriteDataValue(&group.num_members, sizeof(group.num_members),
1759                               "group num members")) {
1760       return false;
1761     }
1762   }
1763   return true;
1764 }
1765 
ReadAttrEventBlock(DataReader * data,size_t size)1766 bool PerfReader::ReadAttrEventBlock(DataReader* data, size_t size) {
1767   const size_t initial_offset = data->Tell();
1768   PerfFileAttr attr;
1769   if (!ReadEventAttr(data, &attr.attr)) return false;
1770 
1771   // attr.attr.size has been upgraded to the current size of perf_event_attr.
1772   const size_t actual_attr_size = data->Tell() - initial_offset;
1773 
1774   const size_t num_ids =
1775       (size - actual_attr_size) / sizeof(decltype(attr.ids)::value_type);
1776   if (!ReadUniqueIDs(data, num_ids, &attr.ids)) return false;
1777 
1778   // Event types are found many times in the perf data file.
1779   // Only add this event type if it is not already present.
1780   if (!attr.ids.empty() &&
1781       file_attrs_seen_.find(attr.ids[0]) != file_attrs_seen_.end()) {
1782     return true;
1783   }
1784 
1785   AddPerfFileAttr(attr);
1786   return true;
1787 }
1788 
MaybeSwapEventFields(event_t * event,bool is_cross_endian)1789 void PerfReader::MaybeSwapEventFields(event_t* event, bool is_cross_endian) {
1790   if (!is_cross_endian) return;
1791   uint32_t type = event->header.type;
1792   switch (type) {
1793     case PERF_RECORD_SAMPLE:
1794       break;
1795     case PERF_RECORD_MMAP:
1796       ByteSwap(&event->mmap.pid);
1797       ByteSwap(&event->mmap.tid);
1798       ByteSwap(&event->mmap.start);
1799       ByteSwap(&event->mmap.len);
1800       ByteSwap(&event->mmap.pgoff);
1801       break;
1802     case PERF_RECORD_MMAP2:
1803       ByteSwap(&event->mmap2.pid);
1804       ByteSwap(&event->mmap2.tid);
1805       ByteSwap(&event->mmap2.start);
1806       ByteSwap(&event->mmap2.len);
1807       ByteSwap(&event->mmap2.pgoff);
1808       ByteSwap(&event->mmap2.maj);
1809       ByteSwap(&event->mmap2.min);
1810       ByteSwap(&event->mmap2.ino);
1811       ByteSwap(&event->mmap2.ino_generation);
1812       ByteSwap(&event->mmap2.prot);
1813       ByteSwap(&event->mmap2.flags);
1814       break;
1815     case PERF_RECORD_FORK:
1816     case PERF_RECORD_EXIT:
1817       ByteSwap(&event->fork.pid);
1818       ByteSwap(&event->fork.tid);
1819       ByteSwap(&event->fork.ppid);
1820       ByteSwap(&event->fork.ptid);
1821       ByteSwap(&event->fork.time);
1822       break;
1823     case PERF_RECORD_COMM:
1824       ByteSwap(&event->comm.pid);
1825       ByteSwap(&event->comm.tid);
1826       break;
1827     case PERF_RECORD_LOST:
1828       ByteSwap(&event->lost.id);
1829       ByteSwap(&event->lost.lost);
1830       break;
1831     case PERF_RECORD_THROTTLE:
1832     case PERF_RECORD_UNTHROTTLE:
1833       ByteSwap(&event->throttle.time);
1834       ByteSwap(&event->throttle.id);
1835       ByteSwap(&event->throttle.stream_id);
1836       break;
1837     case PERF_RECORD_READ:
1838       ByteSwap(&event->read.pid);
1839       ByteSwap(&event->read.tid);
1840       ByteSwap(&event->read.value);
1841       ByteSwap(&event->read.time_enabled);
1842       ByteSwap(&event->read.time_running);
1843       ByteSwap(&event->read.id);
1844       break;
1845     case PERF_RECORD_AUX:
1846       ByteSwap(&event->aux.aux_offset);
1847       ByteSwap(&event->aux.aux_size);
1848       ByteSwap(&event->aux.flags);
1849       break;
1850     case PERF_RECORD_AUXTRACE:
1851       ByteSwap(&event->auxtrace.size);
1852       ByteSwap(&event->auxtrace.offset);
1853       ByteSwap(&event->auxtrace.reference);
1854       ByteSwap(&event->auxtrace.idx);
1855       ByteSwap(&event->auxtrace.tid);
1856       ByteSwap(&event->auxtrace.cpu);
1857       break;
1858     default:
1859       LOG(FATAL) << "Unknown event type: " << type;
1860   }
1861 
1862   // Do not swap the sample info fields that are not explicitly listed in the
1863   // struct definition of each event type. Leave that up to SampleInfoReader
1864   // within |serializer_|.
1865 }
1866 
GetNumSupportedMetadata() const1867 size_t PerfReader::GetNumSupportedMetadata() const {
1868   return GetNumBits(metadata_mask() & kSupportedMetadataMask);
1869 }
1870 
GetEventDescMetadataSize() const1871 size_t PerfReader::GetEventDescMetadataSize() const {
1872   if (attrs().size() > event_types().size()) {
1873     LOG(ERROR) << "Number of attrs (" << attrs().size() << ") cannot exceed "
1874                << "number of event types (" << event_types().size() << ")";
1875     return 0;
1876   }
1877 
1878   size_t size = 0;
1879   if (get_metadata_mask_bit(HEADER_EVENT_DESC)) {
1880     size += sizeof(event_desc_num_events) + sizeof(event_desc_attr_size);
1881     for (int i = 0; i < attrs().size(); ++i) {
1882       size += sizeof(perf_event_attr);
1883       size += sizeof(event_desc_num_unique_ids);
1884       size += ExpectedStorageSizeOf(event_types().Get(i).name());
1885       size += attrs().Get(i).ids_size() *
1886               sizeof(decltype(PerfFileAttr::ids)::value_type);
1887     }
1888   }
1889   return size;
1890 }
1891 
GetBuildIDMetadataSize() const1892 size_t PerfReader::GetBuildIDMetadataSize() const {
1893   size_t size = 0;
1894   for (const auto& build_id : proto_->build_ids()) {
1895     size += sizeof(build_id_event) +
1896             GetUint64AlignedStringLength(build_id.filename());
1897   }
1898   return size;
1899 }
1900 
GetStringMetadataSize() const1901 size_t PerfReader::GetStringMetadataSize() const {
1902   size_t size = 0;
1903   if (string_metadata().has_hostname())
1904     size += ExpectedStorageSizeOf(string_metadata().hostname().value());
1905   if (string_metadata().has_kernel_version())
1906     size += ExpectedStorageSizeOf(string_metadata().kernel_version().value());
1907   if (string_metadata().has_perf_version())
1908     size += ExpectedStorageSizeOf(string_metadata().perf_version().value());
1909   if (string_metadata().has_architecture())
1910     size += ExpectedStorageSizeOf(string_metadata().architecture().value());
1911   if (string_metadata().has_cpu_description())
1912     size += ExpectedStorageSizeOf(string_metadata().cpu_description().value());
1913   if (string_metadata().has_cpu_id())
1914     size += ExpectedStorageSizeOf(string_metadata().cpu_id().value());
1915 
1916   if (!string_metadata().perf_command_line_token().empty()) {
1917     size += sizeof(num_string_data_type);
1918     for (const auto& token : string_metadata().perf_command_line_token())
1919       size += ExpectedStorageSizeOf(token.value());
1920   }
1921   return size;
1922 }
1923 
GetUint32MetadataSize() const1924 size_t PerfReader::GetUint32MetadataSize() const {
1925   size_t size = 0;
1926   for (const auto& metadata : proto_->uint32_metadata())
1927     size += metadata.data().size() * sizeof(uint32_t);
1928   return size;
1929 }
1930 
GetUint64MetadataSize() const1931 size_t PerfReader::GetUint64MetadataSize() const {
1932   size_t size = 0;
1933   for (const auto& metadata : proto_->uint64_metadata())
1934     size += metadata.data().size() * sizeof(uint64_t);
1935   return size;
1936 }
1937 
GetCPUTopologyMetadataSize() const1938 size_t PerfReader::GetCPUTopologyMetadataSize() const {
1939   // Core siblings.
1940   size_t size = sizeof(num_siblings_type);
1941   for (const string& core_sibling : proto_->cpu_topology().core_siblings())
1942     size += ExpectedStorageSizeOf(core_sibling);
1943 
1944   // Thread siblings.
1945   size += sizeof(num_siblings_type);
1946   for (const string& thread_sibling : proto_->cpu_topology().thread_siblings())
1947     size += ExpectedStorageSizeOf(thread_sibling);
1948 
1949   return size;
1950 }
1951 
GetNUMATopologyMetadataSize() const1952 size_t PerfReader::GetNUMATopologyMetadataSize() const {
1953   size_t size = sizeof(numa_topology_num_nodes_type);
1954   for (const auto& node : proto_->numa_topology()) {
1955     size += sizeof(node.id());
1956     size += sizeof(node.total_memory()) + sizeof(node.free_memory());
1957     size += ExpectedStorageSizeOf(node.cpu_list());
1958   }
1959   return size;
1960 }
1961 
GetPMUMappingsMetadataSize() const1962 size_t PerfReader::GetPMUMappingsMetadataSize() const {
1963   size_t size = sizeof(pmu_mappings_num_mappings_type);
1964   for (const auto& node : proto_->pmu_mappings()) {
1965     size += sizeof(node.type());
1966     size += ExpectedStorageSizeOf(node.name());
1967   }
1968   return size;
1969 }
1970 
GetGroupDescMetadataSize() const1971 size_t PerfReader::GetGroupDescMetadataSize() const {
1972   size_t size = sizeof(group_desc_num_groups_type);
1973   for (const auto& group : proto_->group_desc()) {
1974     size += ExpectedStorageSizeOf(group.name());
1975     size += sizeof(group.leader_idx());
1976     size += sizeof(group.num_members());
1977   }
1978   return size;
1979 }
1980 
NeedsNumberOfStringData(u32 type) const1981 bool PerfReader::NeedsNumberOfStringData(u32 type) const {
1982   return type == HEADER_CMDLINE;
1983 }
1984 
LocalizeMMapFilenames(const std::map<string,string> & filename_map)1985 bool PerfReader::LocalizeMMapFilenames(
1986     const std::map<string, string>& filename_map) {
1987   CHECK(serializer_.SampleInfoReaderAvailable());
1988 
1989   // Search for mmap/mmap2 events for which the filename needs to be updated.
1990   for (PerfEvent& event : *proto_->mutable_events()) {
1991     if (event.header().type() != PERF_RECORD_MMAP &&
1992         event.header().type() != PERF_RECORD_MMAP2) {
1993       continue;
1994     }
1995     const string& filename = event.mmap_event().filename();
1996     const auto it = filename_map.find(filename);
1997     if (it == filename_map.end())  // not found
1998       continue;
1999 
2000     const string& new_filename = it->second;
2001     size_t old_len = GetUint64AlignedStringLength(filename);
2002     size_t new_len = GetUint64AlignedStringLength(new_filename);
2003     size_t new_size = event.header().size() - old_len + new_len;
2004 
2005     event.mutable_mmap_event()->set_filename(new_filename);
2006     event.mutable_header()->set_size(new_size);
2007   }
2008 
2009   return true;
2010 }
2011 
AddPerfFileAttr(const PerfFileAttr & attr)2012 void PerfReader::AddPerfFileAttr(const PerfFileAttr& attr) {
2013   serializer_.SerializePerfFileAttr(attr, proto_->add_file_attrs());
2014 
2015   // Generate a new SampleInfoReader with the new attr.
2016   serializer_.CreateSampleInfoReader(attr, is_cross_endian_);
2017   if (!attr.ids.empty()) {
2018     file_attrs_seen_.insert(attr.ids[0]);
2019   }
2020 }
2021 
2022 }  // namespace quipper
2023