1 /*
2 * Copyright (C) 2015 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include "record_file.h"
18
19 #include <fcntl.h>
20 #include <string.h>
21 #include <set>
22 #include <vector>
23
24 #include <android-base/logging.h>
25
26 #include "event_attr.h"
27 #include "record.h"
28 #include "system/extras/simpleperf/record_file.pb.h"
29 #include "utils.h"
30
31 namespace simpleperf {
32
33 using namespace PerfFileFormat;
34
35 namespace PerfFileFormat {
36
37 static const std::map<int, std::string> feature_name_map = {
38 {FEAT_TRACING_DATA, "tracing_data"},
39 {FEAT_BUILD_ID, "build_id"},
40 {FEAT_HOSTNAME, "hostname"},
41 {FEAT_OSRELEASE, "osrelease"},
42 {FEAT_VERSION, "version"},
43 {FEAT_ARCH, "arch"},
44 {FEAT_NRCPUS, "nrcpus"},
45 {FEAT_CPUDESC, "cpudesc"},
46 {FEAT_CPUID, "cpuid"},
47 {FEAT_TOTAL_MEM, "total_mem"},
48 {FEAT_CMDLINE, "cmdline"},
49 {FEAT_EVENT_DESC, "event_desc"},
50 {FEAT_CPU_TOPOLOGY, "cpu_topology"},
51 {FEAT_NUMA_TOPOLOGY, "numa_topology"},
52 {FEAT_BRANCH_STACK, "branch_stack"},
53 {FEAT_PMU_MAPPINGS, "pmu_mappings"},
54 {FEAT_GROUP_DESC, "group_desc"},
55 {FEAT_AUXTRACE, "auxtrace"},
56 {FEAT_FILE, "file"},
57 {FEAT_META_INFO, "meta_info"},
58 {FEAT_DEBUG_UNWIND, "debug_unwind"},
59 {FEAT_DEBUG_UNWIND_FILE, "debug_unwind_file"},
60 };
61
GetFeatureName(int feature_id)62 std::string GetFeatureName(int feature_id) {
63 auto it = feature_name_map.find(feature_id);
64 return it == feature_name_map.end() ? "" : it->second;
65 }
66
GetFeatureId(const std::string & feature_name)67 int GetFeatureId(const std::string& feature_name) {
68 for (auto& pair : feature_name_map) {
69 if (pair.second == feature_name) {
70 return pair.first;
71 }
72 }
73 return -1;
74 }
75
76 } // namespace PerfFileFormat
77
CreateInstance(const std::string & filename)78 std::unique_ptr<RecordFileReader> RecordFileReader::CreateInstance(const std::string& filename) {
79 std::string mode = std::string("rb") + CLOSE_ON_EXEC_MODE;
80 FILE* fp = fopen(filename.c_str(), mode.c_str());
81 if (fp == nullptr) {
82 PLOG(ERROR) << "failed to open record file '" << filename << "'";
83 return nullptr;
84 }
85 auto reader = std::unique_ptr<RecordFileReader>(new RecordFileReader(filename, fp));
86 if (!reader->ReadHeader() || !reader->ReadAttrSection() ||
87 !reader->ReadFeatureSectionDescriptors() || !reader->ReadMetaInfoFeature()) {
88 return nullptr;
89 }
90 reader->UseRecordingEnvironment();
91 return reader;
92 }
93
RecordFileReader(const std::string & filename,FILE * fp)94 RecordFileReader::RecordFileReader(const std::string& filename, FILE* fp)
95 : filename_(filename),
96 record_fp_(fp),
97 event_id_pos_in_sample_records_(0),
98 event_id_reverse_pos_in_non_sample_records_(0),
99 read_record_size_(0) {}
100
~RecordFileReader()101 RecordFileReader::~RecordFileReader() {
102 if (record_fp_ != nullptr) {
103 Close();
104 }
105 }
106
Close()107 bool RecordFileReader::Close() {
108 bool result = true;
109 if (fclose(record_fp_) != 0) {
110 PLOG(ERROR) << "failed to close record file '" << filename_ << "'";
111 result = false;
112 }
113 record_fp_ = nullptr;
114 return result;
115 }
116
ReadHeader()117 bool RecordFileReader::ReadHeader() {
118 if (!Read(&header_, sizeof(header_))) {
119 return false;
120 }
121 if (memcmp(header_.magic, PERF_MAGIC, sizeof(header_.magic)) != 0) {
122 LOG(ERROR) << filename_ << " is not a valid profiling record file.";
123 return false;
124 }
125 return true;
126 }
127
ReadAttrSection()128 bool RecordFileReader::ReadAttrSection() {
129 size_t attr_count = header_.attrs.size / header_.attr_size;
130 if (header_.attr_size != sizeof(FileAttr)) {
131 LOG(DEBUG) << "attr size (" << header_.attr_size << ") in " << filename_
132 << " doesn't match expected size (" << sizeof(FileAttr) << ")";
133 }
134 if (attr_count == 0) {
135 LOG(ERROR) << "no attr in file " << filename_;
136 return false;
137 }
138 if (fseek(record_fp_, header_.attrs.offset, SEEK_SET) != 0) {
139 PLOG(ERROR) << "fseek() failed";
140 return false;
141 }
142 for (size_t i = 0; i < attr_count; ++i) {
143 std::vector<char> buf(header_.attr_size);
144 if (!Read(buf.data(), buf.size())) {
145 return false;
146 }
147 // The size of perf_event_attr is changing between different linux kernel versions.
148 // Make sure we copy correct data to memory.
149 FileAttr attr;
150 memset(&attr, 0, sizeof(attr));
151 size_t section_desc_size = sizeof(attr.ids);
152 size_t perf_event_attr_size = header_.attr_size - section_desc_size;
153 memcpy(&attr.attr, &buf[0], std::min(sizeof(attr.attr), perf_event_attr_size));
154 memcpy(&attr.ids, &buf[perf_event_attr_size], section_desc_size);
155 file_attrs_.push_back(attr);
156 }
157 if (file_attrs_.size() > 1) {
158 std::vector<perf_event_attr> attrs;
159 for (const auto& file_attr : file_attrs_) {
160 attrs.push_back(file_attr.attr);
161 }
162 if (!GetCommonEventIdPositionsForAttrs(attrs, &event_id_pos_in_sample_records_,
163 &event_id_reverse_pos_in_non_sample_records_)) {
164 return false;
165 }
166 }
167 for (size_t i = 0; i < file_attrs_.size(); ++i) {
168 std::vector<uint64_t> ids;
169 if (!ReadIdsForAttr(file_attrs_[i], &ids)) {
170 return false;
171 }
172 event_ids_for_file_attrs_.push_back(ids);
173 for (auto id : ids) {
174 event_id_to_attr_map_[id] = i;
175 }
176 }
177 return true;
178 }
179
ReadFeatureSectionDescriptors()180 bool RecordFileReader::ReadFeatureSectionDescriptors() {
181 std::vector<int> features;
182 for (size_t i = 0; i < sizeof(header_.features); ++i) {
183 for (size_t j = 0; j < 8; ++j) {
184 if (header_.features[i] & (1 << j)) {
185 features.push_back(i * 8 + j);
186 }
187 }
188 }
189 uint64_t feature_section_offset = header_.data.offset + header_.data.size;
190 if (fseek(record_fp_, feature_section_offset, SEEK_SET) != 0) {
191 PLOG(ERROR) << "fseek() failed";
192 return false;
193 }
194 for (const auto& id : features) {
195 SectionDesc desc;
196 if (!Read(&desc, sizeof(desc))) {
197 return false;
198 }
199 feature_section_descriptors_.emplace(id, desc);
200 }
201 return true;
202 }
203
ReadIdsForAttr(const FileAttr & attr,std::vector<uint64_t> * ids)204 bool RecordFileReader::ReadIdsForAttr(const FileAttr& attr, std::vector<uint64_t>* ids) {
205 size_t id_count = attr.ids.size / sizeof(uint64_t);
206 if (fseek(record_fp_, attr.ids.offset, SEEK_SET) != 0) {
207 PLOG(ERROR) << "fseek() failed";
208 return false;
209 }
210 ids->resize(id_count);
211 if (!Read(ids->data(), attr.ids.size)) {
212 return false;
213 }
214 return true;
215 }
216
UseRecordingEnvironment()217 void RecordFileReader::UseRecordingEnvironment() {
218 std::string arch = ReadFeatureString(FEAT_ARCH);
219 if (!arch.empty()) {
220 scoped_arch_.reset(new ScopedCurrentArch(GetArchType(arch)));
221 }
222 auto& meta_info = GetMetaInfoFeature();
223 if (auto it = meta_info.find("event_type_info"); it != meta_info.end()) {
224 if (EventTypeManager::Instance().GetScopedFinder() == nullptr) {
225 scoped_event_types_.reset(new ScopedEventTypes(it->second));
226 }
227 }
228 }
229
ReadDataSection(const std::function<bool (std::unique_ptr<Record>)> & callback)230 bool RecordFileReader::ReadDataSection(
231 const std::function<bool(std::unique_ptr<Record>)>& callback) {
232 std::unique_ptr<Record> record;
233 while (ReadRecord(record)) {
234 if (record == nullptr) {
235 return true;
236 }
237 if (!callback(std::move(record))) {
238 return false;
239 }
240 }
241 return false;
242 }
243
ReadRecord(std::unique_ptr<Record> & record)244 bool RecordFileReader::ReadRecord(std::unique_ptr<Record>& record) {
245 if (read_record_size_ == 0) {
246 if (fseek(record_fp_, header_.data.offset, SEEK_SET) != 0) {
247 PLOG(ERROR) << "fseek() failed";
248 return false;
249 }
250 }
251 record = nullptr;
252 if (read_record_size_ < header_.data.size) {
253 record = ReadRecord();
254 if (record == nullptr) {
255 return false;
256 }
257 if (record->type() == SIMPLE_PERF_RECORD_EVENT_ID) {
258 ProcessEventIdRecord(*static_cast<EventIdRecord*>(record.get()));
259 }
260 }
261 return true;
262 }
263
ReadRecord()264 std::unique_ptr<Record> RecordFileReader::ReadRecord() {
265 char header_buf[Record::header_size()];
266 if (!Read(header_buf, Record::header_size())) {
267 return nullptr;
268 }
269 RecordHeader header(header_buf);
270 std::unique_ptr<char[]> p;
271 if (header.type == SIMPLE_PERF_RECORD_SPLIT) {
272 // Read until meeting a RECORD_SPLIT_END record.
273 std::vector<char> buf;
274 size_t cur_size = 0;
275 char header_buf[Record::header_size()];
276 while (header.type == SIMPLE_PERF_RECORD_SPLIT) {
277 size_t bytes_to_read = header.size - Record::header_size();
278 buf.resize(cur_size + bytes_to_read);
279 if (!Read(&buf[cur_size], bytes_to_read)) {
280 return nullptr;
281 }
282 cur_size += bytes_to_read;
283 read_record_size_ += header.size;
284 if (!Read(header_buf, Record::header_size())) {
285 return nullptr;
286 }
287 header = RecordHeader(header_buf);
288 }
289 if (header.type != SIMPLE_PERF_RECORD_SPLIT_END) {
290 LOG(ERROR) << "SPLIT records are not followed by a SPLIT_END record.";
291 return nullptr;
292 }
293 read_record_size_ += header.size;
294 header = RecordHeader(buf.data());
295 p.reset(new char[header.size]);
296 memcpy(p.get(), buf.data(), buf.size());
297 } else {
298 p.reset(new char[header.size]);
299 memcpy(p.get(), header_buf, Record::header_size());
300 if (header.size > Record::header_size()) {
301 if (!Read(p.get() + Record::header_size(), header.size - Record::header_size())) {
302 return nullptr;
303 }
304 }
305 read_record_size_ += header.size;
306 }
307
308 const perf_event_attr* attr = &file_attrs_[0].attr;
309 if (file_attrs_.size() > 1 && header.type < PERF_RECORD_USER_DEFINED_TYPE_START) {
310 bool has_event_id = false;
311 uint64_t event_id;
312 if (header.type == PERF_RECORD_SAMPLE) {
313 if (header.size > event_id_pos_in_sample_records_ + sizeof(uint64_t)) {
314 has_event_id = true;
315 event_id = *reinterpret_cast<uint64_t*>(p.get() + event_id_pos_in_sample_records_);
316 }
317 } else {
318 if (header.size > event_id_reverse_pos_in_non_sample_records_) {
319 has_event_id = true;
320 event_id = *reinterpret_cast<uint64_t*>(p.get() + header.size -
321 event_id_reverse_pos_in_non_sample_records_);
322 }
323 }
324 if (has_event_id) {
325 auto it = event_id_to_attr_map_.find(event_id);
326 if (it != event_id_to_attr_map_.end()) {
327 attr = &file_attrs_[it->second].attr;
328 }
329 }
330 }
331 auto r = ReadRecordFromOwnedBuffer(*attr, header.type, p.release());
332 if (r->type() == PERF_RECORD_AUXTRACE) {
333 auto auxtrace = static_cast<AuxTraceRecord*>(r.get());
334 auxtrace->location.file_offset = header_.data.offset + read_record_size_;
335 read_record_size_ += auxtrace->data->aux_size;
336 if (fseek(record_fp_, auxtrace->data->aux_size, SEEK_CUR) != 0) {
337 PLOG(ERROR) << "fseek() failed";
338 return nullptr;
339 }
340 }
341 return r;
342 }
343
Read(void * buf,size_t len)344 bool RecordFileReader::Read(void* buf, size_t len) {
345 if (len != 0 && fread(buf, len, 1, record_fp_) != 1) {
346 PLOG(FATAL) << "failed to read file " << filename_;
347 return false;
348 }
349 return true;
350 }
351
ReadAtOffset(uint64_t offset,void * buf,size_t len)352 bool RecordFileReader::ReadAtOffset(uint64_t offset, void* buf, size_t len) {
353 if (fseek(record_fp_, offset, SEEK_SET) != 0) {
354 PLOG(ERROR) << "failed to seek to " << offset;
355 return false;
356 }
357 return Read(buf, len);
358 }
359
ProcessEventIdRecord(const EventIdRecord & r)360 void RecordFileReader::ProcessEventIdRecord(const EventIdRecord& r) {
361 for (size_t i = 0; i < r.count; ++i) {
362 event_ids_for_file_attrs_[r.data[i].attr_id].push_back(r.data[i].event_id);
363 event_id_to_attr_map_[r.data[i].event_id] = r.data[i].attr_id;
364 }
365 }
366
GetAttrIndexOfRecord(const Record * record)367 size_t RecordFileReader::GetAttrIndexOfRecord(const Record* record) {
368 auto it = event_id_to_attr_map_.find(record->Id());
369 if (it != event_id_to_attr_map_.end()) {
370 return it->second;
371 }
372 return 0;
373 }
374
ReadFeatureSection(int feature,std::vector<char> * data)375 bool RecordFileReader::ReadFeatureSection(int feature, std::vector<char>* data) {
376 const std::map<int, SectionDesc>& section_map = FeatureSectionDescriptors();
377 auto it = section_map.find(feature);
378 if (it == section_map.end()) {
379 return false;
380 }
381 SectionDesc section = it->second;
382 data->resize(section.size);
383 if (section.size == 0) {
384 return true;
385 }
386 if (!ReadAtOffset(section.offset, data->data(), data->size())) {
387 return false;
388 }
389 return true;
390 }
391
ReadFeatureSection(int feature,std::string * data)392 bool RecordFileReader::ReadFeatureSection(int feature, std::string* data) {
393 const std::map<int, SectionDesc>& section_map = FeatureSectionDescriptors();
394 auto it = section_map.find(feature);
395 if (it == section_map.end()) {
396 return false;
397 }
398 SectionDesc section = it->second;
399 data->resize(section.size);
400 if (section.size == 0) {
401 return true;
402 }
403 if (!ReadAtOffset(section.offset, data->data(), data->size())) {
404 return false;
405 }
406 return true;
407 }
408
ReadCmdlineFeature()409 std::vector<std::string> RecordFileReader::ReadCmdlineFeature() {
410 std::vector<char> buf;
411 if (!ReadFeatureSection(FEAT_CMDLINE, &buf)) {
412 return std::vector<std::string>();
413 }
414 const char* p = buf.data();
415 const char* end = buf.data() + buf.size();
416 std::vector<std::string> cmdline;
417 uint32_t arg_count;
418 MoveFromBinaryFormat(arg_count, p);
419 CHECK_LE(p, end);
420 for (size_t i = 0; i < arg_count; ++i) {
421 uint32_t len;
422 MoveFromBinaryFormat(len, p);
423 CHECK_LE(p + len, end);
424 cmdline.push_back(p);
425 p += len;
426 }
427 return cmdline;
428 }
429
ReadBuildIdFeature()430 std::vector<BuildIdRecord> RecordFileReader::ReadBuildIdFeature() {
431 std::vector<char> buf;
432 if (!ReadFeatureSection(FEAT_BUILD_ID, &buf)) {
433 return std::vector<BuildIdRecord>();
434 }
435 const char* p = buf.data();
436 const char* end = buf.data() + buf.size();
437 std::vector<BuildIdRecord> result;
438 while (p < end) {
439 auto header = reinterpret_cast<const perf_event_header*>(p);
440 CHECK_LE(p + header->size, end);
441 char* binary = new char[header->size];
442 memcpy(binary, p, header->size);
443 p += header->size;
444 BuildIdRecord record(binary);
445 record.OwnBinary();
446 // Set type explicitly as the perf.data produced by perf doesn't set it.
447 record.SetTypeAndMisc(PERF_RECORD_BUILD_ID, record.misc());
448 result.push_back(std::move(record));
449 }
450 return result;
451 }
452
ReadFeatureString(int feature)453 std::string RecordFileReader::ReadFeatureString(int feature) {
454 std::vector<char> buf;
455 if (!ReadFeatureSection(feature, &buf)) {
456 return std::string();
457 }
458 const char* p = buf.data();
459 const char* end = buf.data() + buf.size();
460 uint32_t len;
461 MoveFromBinaryFormat(len, p);
462 CHECK_LE(p + len, end);
463 return p;
464 }
465
ReadAuxTraceFeature()466 std::vector<uint64_t> RecordFileReader::ReadAuxTraceFeature() {
467 std::vector<char> buf;
468 if (!ReadFeatureSection(FEAT_AUXTRACE, &buf)) {
469 return {};
470 }
471 std::vector<uint64_t> auxtrace_offset;
472 const char* p = buf.data();
473 const char* end = buf.data() + buf.size();
474 if (buf.size() / sizeof(uint64_t) % 2 == 1) {
475 // Recording files generated by linux perf contain an extra uint64 field. Skip it here.
476 p += sizeof(uint64_t);
477 }
478 while (p < end) {
479 uint64_t offset;
480 uint64_t size;
481 MoveFromBinaryFormat(offset, p);
482 auxtrace_offset.push_back(offset);
483 MoveFromBinaryFormat(size, p);
484 CHECK_EQ(size, AuxTraceRecord::Size());
485 }
486 return auxtrace_offset;
487 }
488
ReadFileFeature(size_t & read_pos,FileFeature * file)489 bool RecordFileReader::ReadFileFeature(size_t& read_pos, FileFeature* file) {
490 auto it = feature_section_descriptors_.find(FEAT_FILE);
491 if (it == feature_section_descriptors_.end()) {
492 return false;
493 }
494 if (read_pos >= it->second.size) {
495 return false;
496 }
497 if (read_pos == 0) {
498 if (fseek(record_fp_, it->second.offset, SEEK_SET) != 0) {
499 PLOG(ERROR) << "fseek() failed";
500 return false;
501 }
502 }
503 uint32_t size;
504 if (!Read(&size, 4)) {
505 return false;
506 }
507 std::vector<char> buf(size);
508 if (!Read(buf.data(), size)) {
509 return false;
510 }
511 read_pos += 4 + size;
512 const char* p = buf.data();
513 file->path = p;
514 p += file->path.size() + 1;
515 uint32_t file_type;
516 MoveFromBinaryFormat(file_type, p);
517 if (file_type > DSO_UNKNOWN_FILE) {
518 LOG(ERROR) << "unknown file type for " << file->path
519 << " in file feature section: " << file_type;
520 return false;
521 }
522 file->type = static_cast<DsoType>(file_type);
523 MoveFromBinaryFormat(file->min_vaddr, p);
524 uint32_t symbol_count;
525 MoveFromBinaryFormat(symbol_count, p);
526 file->symbols.clear();
527 file->symbols.reserve(symbol_count);
528 for (uint32_t i = 0; i < symbol_count; ++i) {
529 uint64_t start_vaddr;
530 uint32_t len;
531 MoveFromBinaryFormat(start_vaddr, p);
532 MoveFromBinaryFormat(len, p);
533 std::string name = p;
534 p += name.size() + 1;
535 file->symbols.emplace_back(name, start_vaddr, len);
536 }
537 file->dex_file_offsets.clear();
538 if (file->type == DSO_DEX_FILE) {
539 uint32_t offset_count;
540 MoveFromBinaryFormat(offset_count, p);
541 file->dex_file_offsets.resize(offset_count);
542 MoveFromBinaryFormat(file->dex_file_offsets.data(), offset_count, p);
543 }
544 file->file_offset_of_min_vaddr = std::numeric_limits<uint64_t>::max();
545 if ((file->type == DSO_ELF_FILE || file->type == DSO_KERNEL_MODULE) &&
546 static_cast<size_t>(p - buf.data()) < size) {
547 MoveFromBinaryFormat(file->file_offset_of_min_vaddr, p);
548 }
549 CHECK_EQ(size, static_cast<size_t>(p - buf.data()))
550 << "file " << file->path << ", type " << file->type;
551 return true;
552 }
553
ReadMetaInfoFeature()554 bool RecordFileReader::ReadMetaInfoFeature() {
555 if (feature_section_descriptors_.count(FEAT_META_INFO)) {
556 std::vector<char> buf;
557 if (!ReadFeatureSection(FEAT_META_INFO, &buf)) {
558 return false;
559 }
560 const char* p = buf.data();
561 const char* end = buf.data() + buf.size();
562 while (p < end) {
563 const char* key = p;
564 const char* value = key + strlen(key) + 1;
565 CHECK(value < end);
566 meta_info_[p] = value;
567 p = value + strlen(value) + 1;
568 }
569 }
570 return true;
571 }
572
ReadDebugUnwindFeature()573 std::optional<DebugUnwindFeature> RecordFileReader::ReadDebugUnwindFeature() {
574 if (feature_section_descriptors_.count(FEAT_DEBUG_UNWIND)) {
575 std::string s;
576 if (!ReadFeatureSection(FEAT_DEBUG_UNWIND, &s)) {
577 return std::nullopt;
578 }
579 proto::DebugUnwindFeature proto_debug_unwind;
580 proto_debug_unwind.ParseFromString(s);
581 DebugUnwindFeature debug_unwind(proto_debug_unwind.file_size());
582 for (size_t i = 0; i < proto_debug_unwind.file_size(); i++) {
583 debug_unwind[i].path = proto_debug_unwind.file(i).path();
584 debug_unwind[i].size = proto_debug_unwind.file(i).size();
585 }
586 return debug_unwind;
587 }
588 return std::nullopt;
589 }
590
LoadBuildIdAndFileFeatures(ThreadTree & thread_tree)591 void RecordFileReader::LoadBuildIdAndFileFeatures(ThreadTree& thread_tree) {
592 std::vector<BuildIdRecord> records = ReadBuildIdFeature();
593 std::vector<std::pair<std::string, BuildId>> build_ids;
594 for (auto& r : records) {
595 build_ids.push_back(std::make_pair(r.filename, r.build_id));
596 }
597 Dso::SetBuildIds(build_ids);
598
599 if (HasFeature(PerfFileFormat::FEAT_FILE)) {
600 FileFeature file_feature;
601 size_t read_pos = 0;
602 while (ReadFileFeature(read_pos, &file_feature)) {
603 thread_tree.AddDsoInfo(file_feature);
604 }
605 }
606 }
607
ReadAuxData(uint32_t cpu,uint64_t aux_offset,void * buf,size_t size)608 bool RecordFileReader::ReadAuxData(uint32_t cpu, uint64_t aux_offset, void* buf, size_t size) {
609 long saved_pos = ftell(record_fp_);
610 if (saved_pos == -1) {
611 PLOG(ERROR) << "ftell() failed";
612 return false;
613 }
614 if (aux_data_location_.empty() && !BuildAuxDataLocation()) {
615 return false;
616 }
617 AuxDataLocation* location = nullptr;
618 auto it = aux_data_location_.find(cpu);
619 if (it != aux_data_location_.end()) {
620 auto comp = [](uint64_t aux_offset, const AuxDataLocation& location) {
621 return aux_offset < location.aux_offset;
622 };
623 auto location_it = std::upper_bound(it->second.begin(), it->second.end(), aux_offset, comp);
624 if (location_it != it->second.begin()) {
625 --location_it;
626 if (location_it->aux_offset + location_it->aux_size >= aux_offset + size) {
627 location = &*location_it;
628 }
629 }
630 }
631 if (location == nullptr) {
632 LOG(ERROR) << "failed to find file offset of aux data: cpu " << cpu << ", aux_offset "
633 << aux_offset << ", size " << size;
634 return false;
635 }
636 if (!ReadAtOffset(aux_offset - location->aux_offset + location->file_offset, buf, size)) {
637 return false;
638 }
639 if (fseek(record_fp_, saved_pos, SEEK_SET) != 0) {
640 PLOG(ERROR) << "fseek() failed";
641 return false;
642 }
643 return true;
644 }
645
BuildAuxDataLocation()646 bool RecordFileReader::BuildAuxDataLocation() {
647 std::vector<uint64_t> auxtrace_offset = ReadAuxTraceFeature();
648 if (auxtrace_offset.empty()) {
649 LOG(ERROR) << "failed to read auxtrace feature section";
650 return false;
651 }
652 std::unique_ptr<char[]> buf(new char[AuxTraceRecord::Size()]);
653 for (auto offset : auxtrace_offset) {
654 if (!ReadAtOffset(offset, buf.get(), AuxTraceRecord::Size())) {
655 return false;
656 }
657 AuxTraceRecord auxtrace(buf.get());
658 aux_data_location_[auxtrace.data->cpu].emplace_back(
659 auxtrace.data->offset, auxtrace.data->aux_size, offset + auxtrace.size());
660 }
661 return true;
662 }
663
DataSection()664 std::vector<std::unique_ptr<Record>> RecordFileReader::DataSection() {
665 std::vector<std::unique_ptr<Record>> records;
666 ReadDataSection([&](std::unique_ptr<Record> record) {
667 records.push_back(std::move(record));
668 return true;
669 });
670 return records;
671 }
672
IsPerfDataFile(const std::string & filename)673 bool IsPerfDataFile(const std::string& filename) {
674 auto fd = FileHelper::OpenReadOnly(filename);
675 if (fd.ok()) {
676 PerfFileFormat::FileHeader header;
677 return android::base::ReadFully(fd, &header, sizeof(header)) &&
678 memcmp(header.magic, PERF_MAGIC, sizeof(header.magic)) == 0;
679 }
680 return false;
681 }
682
683 } // namespace simpleperf
684