OSDN Git Service

am 5e191823: am 96f2bc51: am e7da7e9b: Simpleperf: remove abort in child process.
[android-x86/system-extras.git] / simpleperf / cmd_dumprecord.cpp
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 <inttypes.h>
18
19 #include <map>
20 #include <string>
21 #include <vector>
22
23 #include <base/logging.h>
24 #include <base/stringprintf.h>
25 #include <base/strings.h>
26
27 #include "command.h"
28 #include "event_attr.h"
29 #include "record.h"
30 #include "record_file.h"
31 #include "utils.h"
32
33 using namespace PerfFileFormat;
34
35 class DumpRecordCommand : public Command {
36  public:
37   DumpRecordCommand()
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") {
42   }
43
44   bool Run(const std::vector<std::string>& args);
45
46  private:
47   bool ParseOptions(const std::vector<std::string>& args);
48   void DumpFileHeader();
49   void DumpAttrSection();
50   void DumpDataSection();
51   void DumpFeatureSection();
52
53   std::string record_filename_;
54   std::unique_ptr<RecordFileReader> record_file_reader_;
55 };
56
57 bool DumpRecordCommand::Run(const std::vector<std::string>& args) {
58   if (!ParseOptions(args)) {
59     return false;
60   }
61   record_file_reader_ = RecordFileReader::CreateInstance(record_filename_);
62   if (record_file_reader_ == nullptr) {
63     return false;
64   }
65   DumpFileHeader();
66   DumpAttrSection();
67   DumpDataSection();
68   DumpFeatureSection();
69
70   return true;
71 }
72
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);
78     return false;
79   }
80   return true;
81 }
82
83 static const std::string GetFeatureName(int feature);
84
85 void DumpRecordCommand::DumpFileHeader() {
86   const FileHeader* header = record_file_reader_->FileHeader();
87   printf("magic: ");
88   for (size_t i = 0; i < 8; ++i) {
89     printf("%c", header->magic[i]);
90   }
91   printf("\n");
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 "
95                   << sizeof(*header);
96   }
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);
100   }
101   printf("attrs[file section]: offset %" PRId64 ", size %" PRId64 "\n", header->attrs.offset,
102          header->attrs.size);
103   printf("data[file section]: offset %" PRId64 ", size %" PRId64 "\n", header->data.offset,
104          header->data.size);
105   printf("event_types[file section]: offset %" PRId64 ", size %" PRId64 "\n",
106          header->event_types.offset, header->event_types.size);
107
108   std::vector<int> features;
109   for (size_t i = 0; i < FEAT_MAX_NUM; ++i) {
110     size_t j = i / 8;
111     size_t k = i % 8;
112     if ((header->features[j] & (1 << k)) != 0) {
113       features.push_back(i);
114     }
115   }
116   for (auto& feature : features) {
117     printf("feature: %s\n", GetFeatureName(feature).c_str());
118   }
119 }
120
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"},
128       {FEAT_ARCH, "arch"},
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"},
140   };
141   auto it = feature_name_map.find(feature);
142   if (it != feature_name_map.end()) {
143     return it->second;
144   }
145   return android::base::StringPrintf("unknown_feature(%d)", feature);
146 }
147
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,
155            attr->ids.size);
156     std::vector<uint64_t> ids = record_file_reader_->IdsForAttr(attr);
157     if (ids.size() > 0) {
158       printf("  ids:");
159       for (auto& id : ids) {
160         printf(" %" PRId64, id);
161       }
162       printf("\n");
163     }
164   }
165 }
166
167 void DumpRecordCommand::DumpDataSection() {
168   std::vector<std::unique_ptr<const Record>> records = record_file_reader_->DataSection();
169   for (auto& record : records) {
170     record->Dump();
171   }
172 }
173
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) {
184         r.Dump(1);
185       }
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());
189     }
190   }
191 }
192
193 __attribute__((constructor)) static void RegisterDumpRecordCommand() {
194   RegisterCommand("dump", [] { return std::unique_ptr<Command>(new DumpRecordCommand); });
195 }