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(§ion->offset);
173 ByteSwap(§ion->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(×tamp_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, §ion)) {
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