OSDN Git Service

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