2 * Copyright (C) 2015 The Android Open Source Project
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
23 #include <base/logging.h>
24 #include <base/stringprintf.h>
25 #include <base/strings.h>
28 #include "event_attr.h"
30 #include "record_file.h"
33 using namespace PerfFileFormat;
35 class DumpRecordCommand : public Command {
38 : Command("dump", "dump perf record file",
39 "Usage: simpleperf dumprecord [options] [perf_record_file]\n"
40 " Dump different parts of a perf record file. Default file is perf.data.\n"),
41 record_filename_("perf.data") {
44 bool Run(const std::vector<std::string>& args);
47 bool ParseOptions(const std::vector<std::string>& args);
48 void DumpFileHeader();
49 void DumpAttrSection();
50 void DumpDataSection();
51 void DumpFeatureSection();
53 std::string record_filename_;
54 std::unique_ptr<RecordFileReader> record_file_reader_;
57 bool DumpRecordCommand::Run(const std::vector<std::string>& args) {
58 if (!ParseOptions(args)) {
61 record_file_reader_ = RecordFileReader::CreateInstance(record_filename_);
62 if (record_file_reader_ == nullptr) {
73 bool DumpRecordCommand::ParseOptions(const std::vector<std::string>& args) {
74 if (args.size() == 1) {
75 record_filename_ = args[0];
76 } else if (args.size() > 1) {
77 ReportUnknownOption(args, 1);
83 static const std::string GetFeatureName(int feature);
85 void DumpRecordCommand::DumpFileHeader() {
86 const FileHeader* header = record_file_reader_->FileHeader();
88 for (size_t i = 0; i < 8; ++i) {
89 printf("%c", header->magic[i]);
92 printf("header_size: %" PRId64 "\n", header->header_size);
93 if (header->header_size != sizeof(*header)) {
94 PLOG(WARNING) << "record file header size doesn't match expected header size "
97 printf("attr_size: %" PRId64 "\n", header->attr_size);
98 if (header->attr_size != sizeof(FileAttr)) {
99 PLOG(WARNING) << "record file attr size doesn't match expected attr size " << sizeof(FileAttr);
101 printf("attrs[file section]: offset %" PRId64 ", size %" PRId64 "\n", header->attrs.offset,
103 printf("data[file section]: offset %" PRId64 ", size %" PRId64 "\n", header->data.offset,
105 printf("event_types[file section]: offset %" PRId64 ", size %" PRId64 "\n",
106 header->event_types.offset, header->event_types.size);
108 std::vector<int> features;
109 for (size_t i = 0; i < FEAT_MAX_NUM; ++i) {
112 if ((header->features[j] & (1 << k)) != 0) {
113 features.push_back(i);
116 for (auto& feature : features) {
117 printf("feature: %s\n", GetFeatureName(feature).c_str());
121 static const std::string GetFeatureName(int feature) {
122 static std::map<int, std::string> feature_name_map = {
123 {FEAT_TRACING_DATA, "tracing_data"},
124 {FEAT_BUILD_ID, "build_id"},
125 {FEAT_HOSTNAME, "hostname"},
126 {FEAT_OSRELEASE, "osrelease"},
127 {FEAT_VERSION, "version"},
129 {FEAT_NRCPUS, "nrcpus"},
130 {FEAT_CPUDESC, "cpudesc"},
131 {FEAT_CPUID, "cpuid"},
132 {FEAT_TOTAL_MEM, "total_mem"},
133 {FEAT_CMDLINE, "cmdline"},
134 {FEAT_EVENT_DESC, "event_desc"},
135 {FEAT_CPU_TOPOLOGY, "cpu_topology"},
136 {FEAT_NUMA_TOPOLOGY, "numa_topology"},
137 {FEAT_BRANCH_STACK, "branch_stack"},
138 {FEAT_PMU_MAPPINGS, "pmu_mappings"},
139 {FEAT_GROUP_DESC, "group_desc"},
141 auto it = feature_name_map.find(feature);
142 if (it != feature_name_map.end()) {
145 return android::base::StringPrintf("unknown_feature(%d)", feature);
148 void DumpRecordCommand::DumpAttrSection() {
149 std::vector<const FileAttr*> attrs = record_file_reader_->AttrSection();
150 for (size_t i = 0; i < attrs.size(); ++i) {
151 auto& attr = attrs[i];
152 printf("file_attr %zu:\n", i + 1);
153 DumpPerfEventAttr(attr->attr, 1);
154 printf(" ids[file_section]: offset %" PRId64 ", size %" PRId64 "\n", attr->ids.offset,
156 std::vector<uint64_t> ids = record_file_reader_->IdsForAttr(attr);
157 if (ids.size() > 0) {
159 for (auto& id : ids) {
160 printf(" %" PRId64, id);
167 void DumpRecordCommand::DumpDataSection() {
168 std::vector<std::unique_ptr<const Record>> records = record_file_reader_->DataSection();
169 for (auto& record : records) {
174 void DumpRecordCommand::DumpFeatureSection() {
175 std::map<int, SectionDesc> section_map = record_file_reader_->FeatureSectionDescriptors();
176 for (auto& pair : section_map) {
177 int feature = pair.first;
178 SectionDesc& section = pair.second;
179 printf("feature section for %s: offset %" PRId64 ", size %" PRId64 "\n",
180 GetFeatureName(feature).c_str(), section.offset, section.size);
181 if (feature == FEAT_BUILD_ID) {
182 std::vector<BuildIdRecord> records = record_file_reader_->ReadBuildIdFeature();
183 for (auto& r : records) {
186 } else if (feature == FEAT_CMDLINE) {
187 std::vector<std::string> cmdline = record_file_reader_->ReadCmdlineFeature();
188 PrintIndented(1, "cmdline: %s\n", android::base::Join(cmdline, ' ').c_str());
193 __attribute__((constructor)) static void RegisterDumpRecordCommand() {
194 RegisterCommand("dump", [] { return std::unique_ptr<Command>(new DumpRecordCommand); });