OSDN Git Service

5e31aa422b7ad114fc13f9e5d6eee60a731c7290
[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 "perf_regs.h"
30 #include "record.h"
31 #include "record_file.h"
32 #include "utils.h"
33
34 using namespace PerfFileFormat;
35
36 class DumpRecordCommand : public Command {
37  public:
38   DumpRecordCommand()
39       : Command("dump", "dump perf record file",
40                 "Usage: simpleperf dumprecord [options] [perf_record_file]\n"
41                 "    Dump different parts of a perf record file. Default file is perf.data.\n"),
42         record_filename_("perf.data") {
43   }
44
45   bool Run(const std::vector<std::string>& args);
46
47  private:
48   bool ParseOptions(const std::vector<std::string>& args);
49   void DumpFileHeader();
50   void DumpAttrSection();
51   void DumpDataSection();
52   void DumpFeatureSection();
53
54   std::string record_filename_;
55   std::unique_ptr<RecordFileReader> record_file_reader_;
56 };
57
58 bool DumpRecordCommand::Run(const std::vector<std::string>& args) {
59   if (!ParseOptions(args)) {
60     return false;
61   }
62   record_file_reader_ = RecordFileReader::CreateInstance(record_filename_);
63   if (record_file_reader_ == nullptr) {
64     return false;
65   }
66   std::string arch = record_file_reader_->ReadFeatureString(FEAT_ARCH);
67   if (!arch.empty()) {
68     if (!SetCurrentArch(arch)) {
69       return false;
70     }
71   }
72   DumpFileHeader();
73   DumpAttrSection();
74   DumpDataSection();
75   DumpFeatureSection();
76
77   return true;
78 }
79
80 bool DumpRecordCommand::ParseOptions(const std::vector<std::string>& args) {
81   if (args.size() == 1) {
82     record_filename_ = args[0];
83   } else if (args.size() > 1) {
84     ReportUnknownOption(args, 1);
85     return false;
86   }
87   return true;
88 }
89
90 static const std::string GetFeatureName(int feature);
91
92 void DumpRecordCommand::DumpFileHeader() {
93   const FileHeader& header = record_file_reader_->FileHeader();
94   printf("magic: ");
95   for (size_t i = 0; i < 8; ++i) {
96     printf("%c", header.magic[i]);
97   }
98   printf("\n");
99   printf("header_size: %" PRId64 "\n", header.header_size);
100   if (header.header_size != sizeof(header)) {
101     PLOG(WARNING) << "record file header size " << header.header_size
102                   << "doesn't match expected header size " << sizeof(header);
103   }
104   printf("attr_size: %" PRId64 "\n", header.attr_size);
105   if (header.attr_size != sizeof(FileAttr)) {
106     PLOG(WARNING) << "record file attr size " << header.attr_size
107                   << " doesn't match expected attr size " << sizeof(FileAttr);
108   }
109   printf("attrs[file section]: offset %" PRId64 ", size %" PRId64 "\n", header.attrs.offset,
110          header.attrs.size);
111   printf("data[file section]: offset %" PRId64 ", size %" PRId64 "\n", header.data.offset,
112          header.data.size);
113   printf("event_types[file section]: offset %" PRId64 ", size %" PRId64 "\n",
114          header.event_types.offset, header.event_types.size);
115
116   std::vector<int> features;
117   for (size_t i = 0; i < FEAT_MAX_NUM; ++i) {
118     size_t j = i / 8;
119     size_t k = i % 8;
120     if ((header.features[j] & (1 << k)) != 0) {
121       features.push_back(i);
122     }
123   }
124   for (auto& feature : features) {
125     printf("feature: %s\n", GetFeatureName(feature).c_str());
126   }
127 }
128
129 static const std::string GetFeatureName(int feature) {
130   static std::map<int, std::string> feature_name_map = {
131       {FEAT_TRACING_DATA, "tracing_data"},
132       {FEAT_BUILD_ID, "build_id"},
133       {FEAT_HOSTNAME, "hostname"},
134       {FEAT_OSRELEASE, "osrelease"},
135       {FEAT_VERSION, "version"},
136       {FEAT_ARCH, "arch"},
137       {FEAT_NRCPUS, "nrcpus"},
138       {FEAT_CPUDESC, "cpudesc"},
139       {FEAT_CPUID, "cpuid"},
140       {FEAT_TOTAL_MEM, "total_mem"},
141       {FEAT_CMDLINE, "cmdline"},
142       {FEAT_EVENT_DESC, "event_desc"},
143       {FEAT_CPU_TOPOLOGY, "cpu_topology"},
144       {FEAT_NUMA_TOPOLOGY, "numa_topology"},
145       {FEAT_BRANCH_STACK, "branch_stack"},
146       {FEAT_PMU_MAPPINGS, "pmu_mappings"},
147       {FEAT_GROUP_DESC, "group_desc"},
148   };
149   auto it = feature_name_map.find(feature);
150   if (it != feature_name_map.end()) {
151     return it->second;
152   }
153   return android::base::StringPrintf("unknown_feature(%d)", feature);
154 }
155
156 void DumpRecordCommand::DumpAttrSection() {
157   const std::vector<FileAttr>& attrs = record_file_reader_->AttrSection();
158   for (size_t i = 0; i < attrs.size(); ++i) {
159     const auto& attr = attrs[i];
160     printf("file_attr %zu:\n", i + 1);
161     DumpPerfEventAttr(attr.attr, 1);
162     printf("  ids[file_section]: offset %" PRId64 ", size %" PRId64 "\n", attr.ids.offset,
163            attr.ids.size);
164     std::vector<uint64_t> ids;
165     if (!record_file_reader_->ReadIdsForAttr(attr, &ids)) {
166       return;
167     }
168     if (!ids.empty()) {
169       printf("  ids:");
170       for (const auto& id : ids) {
171         printf(" %" PRId64, id);
172       }
173       printf("\n");
174     }
175   }
176 }
177
178 void DumpRecordCommand::DumpDataSection() {
179   record_file_reader_->ReadDataSection([](std::unique_ptr<Record> record) {
180     record->Dump();
181     return true;
182   });
183 }
184
185 void DumpRecordCommand::DumpFeatureSection() {
186   std::map<int, SectionDesc> section_map = record_file_reader_->FeatureSectionDescriptors();
187   for (const auto& pair : section_map) {
188     int feature = pair.first;
189     const auto& section = pair.second;
190     printf("feature section for %s: offset %" PRId64 ", size %" PRId64 "\n",
191            GetFeatureName(feature).c_str(), section.offset, section.size);
192     if (feature == FEAT_BUILD_ID) {
193       std::vector<BuildIdRecord> records = record_file_reader_->ReadBuildIdFeature();
194       for (auto& r : records) {
195         r.Dump(1);
196       }
197     } else if (feature == FEAT_OSRELEASE) {
198       std::string s = record_file_reader_->ReadFeatureString(feature);
199       PrintIndented(1, "osrelease: %s\n", s.c_str());
200     } else if (feature == FEAT_ARCH) {
201       std::string s = record_file_reader_->ReadFeatureString(feature);
202       PrintIndented(1, "arch: %s\n", s.c_str());
203     } else if (feature == FEAT_CMDLINE) {
204       std::vector<std::string> cmdline = record_file_reader_->ReadCmdlineFeature();
205       PrintIndented(1, "cmdline: %s\n", android::base::Join(cmdline, ' ').c_str());
206     }
207   }
208 }
209
210 __attribute__((constructor)) static void RegisterDumpRecordCommand() {
211   RegisterCommand("dump", [] { return std::unique_ptr<Command>(new DumpRecordCommand); });
212 }