1*288bf522SAndroid Build Coastguard Worker /*
2*288bf522SAndroid Build Coastguard Worker * Copyright (C) 2016 The Android Open Source Project
3*288bf522SAndroid Build Coastguard Worker *
4*288bf522SAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License");
5*288bf522SAndroid Build Coastguard Worker * you may not use this file except in compliance with the License.
6*288bf522SAndroid Build Coastguard Worker * You may obtain a copy of the License at
7*288bf522SAndroid Build Coastguard Worker *
8*288bf522SAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0
9*288bf522SAndroid Build Coastguard Worker *
10*288bf522SAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software
11*288bf522SAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS,
12*288bf522SAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*288bf522SAndroid Build Coastguard Worker * See the License for the specific language governing permissions and
14*288bf522SAndroid Build Coastguard Worker * limitations under the License.
15*288bf522SAndroid Build Coastguard Worker */
16*288bf522SAndroid Build Coastguard Worker
17*288bf522SAndroid Build Coastguard Worker #include <memory>
18*288bf522SAndroid Build Coastguard Worker #include <optional>
19*288bf522SAndroid Build Coastguard Worker #include <queue>
20*288bf522SAndroid Build Coastguard Worker #include <utility>
21*288bf522SAndroid Build Coastguard Worker
22*288bf522SAndroid Build Coastguard Worker #include <android-base/file.h>
23*288bf522SAndroid Build Coastguard Worker #include <android-base/logging.h>
24*288bf522SAndroid Build Coastguard Worker #include <android-base/strings.h>
25*288bf522SAndroid Build Coastguard Worker
26*288bf522SAndroid Build Coastguard Worker #include "JITDebugReader.h"
27*288bf522SAndroid Build Coastguard Worker #include "RecordFilter.h"
28*288bf522SAndroid Build Coastguard Worker #include "dso.h"
29*288bf522SAndroid Build Coastguard Worker #include "event_attr.h"
30*288bf522SAndroid Build Coastguard Worker #include "event_type.h"
31*288bf522SAndroid Build Coastguard Worker #include "record_file.h"
32*288bf522SAndroid Build Coastguard Worker #include "report_utils.h"
33*288bf522SAndroid Build Coastguard Worker #include "thread_tree.h"
34*288bf522SAndroid Build Coastguard Worker #include "tracing.h"
35*288bf522SAndroid Build Coastguard Worker #include "utils.h"
36*288bf522SAndroid Build Coastguard Worker
37*288bf522SAndroid Build Coastguard Worker extern "C" {
38*288bf522SAndroid Build Coastguard Worker
39*288bf522SAndroid Build Coastguard Worker struct Sample {
40*288bf522SAndroid Build Coastguard Worker uint64_t ip;
41*288bf522SAndroid Build Coastguard Worker uint32_t pid;
42*288bf522SAndroid Build Coastguard Worker uint32_t tid;
43*288bf522SAndroid Build Coastguard Worker const char* thread_comm;
44*288bf522SAndroid Build Coastguard Worker uint64_t time;
45*288bf522SAndroid Build Coastguard Worker uint32_t in_kernel;
46*288bf522SAndroid Build Coastguard Worker uint32_t cpu;
47*288bf522SAndroid Build Coastguard Worker uint64_t period;
48*288bf522SAndroid Build Coastguard Worker };
49*288bf522SAndroid Build Coastguard Worker
50*288bf522SAndroid Build Coastguard Worker struct TracingFieldFormat {
51*288bf522SAndroid Build Coastguard Worker const char* name;
52*288bf522SAndroid Build Coastguard Worker uint32_t offset;
53*288bf522SAndroid Build Coastguard Worker uint32_t elem_size;
54*288bf522SAndroid Build Coastguard Worker uint32_t elem_count;
55*288bf522SAndroid Build Coastguard Worker uint32_t is_signed;
56*288bf522SAndroid Build Coastguard Worker uint32_t is_dynamic;
57*288bf522SAndroid Build Coastguard Worker };
58*288bf522SAndroid Build Coastguard Worker
59*288bf522SAndroid Build Coastguard Worker struct TracingDataFormat {
60*288bf522SAndroid Build Coastguard Worker uint32_t size;
61*288bf522SAndroid Build Coastguard Worker uint32_t field_count;
62*288bf522SAndroid Build Coastguard Worker TracingFieldFormat* fields;
63*288bf522SAndroid Build Coastguard Worker };
64*288bf522SAndroid Build Coastguard Worker
65*288bf522SAndroid Build Coastguard Worker struct Event {
66*288bf522SAndroid Build Coastguard Worker const char* name;
67*288bf522SAndroid Build Coastguard Worker TracingDataFormat tracing_data_format;
68*288bf522SAndroid Build Coastguard Worker };
69*288bf522SAndroid Build Coastguard Worker
70*288bf522SAndroid Build Coastguard Worker struct Mapping {
71*288bf522SAndroid Build Coastguard Worker uint64_t start;
72*288bf522SAndroid Build Coastguard Worker uint64_t end;
73*288bf522SAndroid Build Coastguard Worker uint64_t pgoff;
74*288bf522SAndroid Build Coastguard Worker };
75*288bf522SAndroid Build Coastguard Worker
76*288bf522SAndroid Build Coastguard Worker struct SymbolEntry {
77*288bf522SAndroid Build Coastguard Worker const char* dso_name;
78*288bf522SAndroid Build Coastguard Worker uint64_t vaddr_in_file;
79*288bf522SAndroid Build Coastguard Worker const char* symbol_name;
80*288bf522SAndroid Build Coastguard Worker uint64_t symbol_addr;
81*288bf522SAndroid Build Coastguard Worker uint64_t symbol_len;
82*288bf522SAndroid Build Coastguard Worker Mapping* mapping;
83*288bf522SAndroid Build Coastguard Worker };
84*288bf522SAndroid Build Coastguard Worker
85*288bf522SAndroid Build Coastguard Worker struct CallChainEntry {
86*288bf522SAndroid Build Coastguard Worker uint64_t ip;
87*288bf522SAndroid Build Coastguard Worker SymbolEntry symbol;
88*288bf522SAndroid Build Coastguard Worker };
89*288bf522SAndroid Build Coastguard Worker
90*288bf522SAndroid Build Coastguard Worker struct CallChain {
91*288bf522SAndroid Build Coastguard Worker uint32_t nr;
92*288bf522SAndroid Build Coastguard Worker CallChainEntry* entries;
93*288bf522SAndroid Build Coastguard Worker };
94*288bf522SAndroid Build Coastguard Worker
95*288bf522SAndroid Build Coastguard Worker struct EventCounter {
96*288bf522SAndroid Build Coastguard Worker const char* name;
97*288bf522SAndroid Build Coastguard Worker uint64_t id;
98*288bf522SAndroid Build Coastguard Worker uint64_t count;
99*288bf522SAndroid Build Coastguard Worker };
100*288bf522SAndroid Build Coastguard Worker
101*288bf522SAndroid Build Coastguard Worker struct EventCountersView {
102*288bf522SAndroid Build Coastguard Worker size_t nr;
103*288bf522SAndroid Build Coastguard Worker EventCounter* event_counter;
104*288bf522SAndroid Build Coastguard Worker };
105*288bf522SAndroid Build Coastguard Worker
106*288bf522SAndroid Build Coastguard Worker struct FeatureSection {
107*288bf522SAndroid Build Coastguard Worker const char* data;
108*288bf522SAndroid Build Coastguard Worker uint32_t data_size;
109*288bf522SAndroid Build Coastguard Worker };
110*288bf522SAndroid Build Coastguard Worker
111*288bf522SAndroid Build Coastguard Worker } // extern "C"
112*288bf522SAndroid Build Coastguard Worker
113*288bf522SAndroid Build Coastguard Worker namespace simpleperf {
114*288bf522SAndroid Build Coastguard Worker namespace {
115*288bf522SAndroid Build Coastguard Worker
116*288bf522SAndroid Build Coastguard Worker struct EventInfo {
117*288bf522SAndroid Build Coastguard Worker perf_event_attr attr;
118*288bf522SAndroid Build Coastguard Worker std::string name;
119*288bf522SAndroid Build Coastguard Worker
120*288bf522SAndroid Build Coastguard Worker struct TracingInfo {
121*288bf522SAndroid Build Coastguard Worker TracingDataFormat data_format;
122*288bf522SAndroid Build Coastguard Worker std::vector<std::string> field_names;
123*288bf522SAndroid Build Coastguard Worker std::vector<TracingFieldFormat> fields;
124*288bf522SAndroid Build Coastguard Worker } tracing_info;
125*288bf522SAndroid Build Coastguard Worker };
126*288bf522SAndroid Build Coastguard Worker
127*288bf522SAndroid Build Coastguard Worker // If a recording file is generated with --trace-offcpu, we can select TraceOffCpuMode to report.
128*288bf522SAndroid Build Coastguard Worker // It affects which samples are reported, and how period in each sample is calculated.
129*288bf522SAndroid Build Coastguard Worker enum class TraceOffCpuMode {
130*288bf522SAndroid Build Coastguard Worker // Only report on-cpu samples, with period representing time spent on cpu.
131*288bf522SAndroid Build Coastguard Worker ON_CPU,
132*288bf522SAndroid Build Coastguard Worker // Only report off-cpu samples, with period representing time spent off cpu.
133*288bf522SAndroid Build Coastguard Worker OFF_CPU,
134*288bf522SAndroid Build Coastguard Worker // Report both on-cpu and off-cpu samples.
135*288bf522SAndroid Build Coastguard Worker ON_OFF_CPU,
136*288bf522SAndroid Build Coastguard Worker // Report on-cpu and off-cpu samples under the same event type.
137*288bf522SAndroid Build Coastguard Worker MIXED_ON_OFF_CPU,
138*288bf522SAndroid Build Coastguard Worker };
139*288bf522SAndroid Build Coastguard Worker
TraceOffCpuModeToString(TraceOffCpuMode mode)140*288bf522SAndroid Build Coastguard Worker static std::string TraceOffCpuModeToString(TraceOffCpuMode mode) {
141*288bf522SAndroid Build Coastguard Worker switch (mode) {
142*288bf522SAndroid Build Coastguard Worker case TraceOffCpuMode::ON_CPU:
143*288bf522SAndroid Build Coastguard Worker return "on-cpu";
144*288bf522SAndroid Build Coastguard Worker case TraceOffCpuMode::OFF_CPU:
145*288bf522SAndroid Build Coastguard Worker return "off-cpu";
146*288bf522SAndroid Build Coastguard Worker case TraceOffCpuMode::ON_OFF_CPU:
147*288bf522SAndroid Build Coastguard Worker return "on-off-cpu";
148*288bf522SAndroid Build Coastguard Worker case TraceOffCpuMode::MIXED_ON_OFF_CPU:
149*288bf522SAndroid Build Coastguard Worker return "mixed-on-off-cpu";
150*288bf522SAndroid Build Coastguard Worker }
151*288bf522SAndroid Build Coastguard Worker }
152*288bf522SAndroid Build Coastguard Worker
StringToTraceOffCpuMode(const std::string & s)153*288bf522SAndroid Build Coastguard Worker static std::optional<TraceOffCpuMode> StringToTraceOffCpuMode(const std::string& s) {
154*288bf522SAndroid Build Coastguard Worker if (s == "on-cpu") {
155*288bf522SAndroid Build Coastguard Worker return TraceOffCpuMode::ON_CPU;
156*288bf522SAndroid Build Coastguard Worker }
157*288bf522SAndroid Build Coastguard Worker if (s == "off-cpu") {
158*288bf522SAndroid Build Coastguard Worker return TraceOffCpuMode::OFF_CPU;
159*288bf522SAndroid Build Coastguard Worker }
160*288bf522SAndroid Build Coastguard Worker if (s == "on-off-cpu") {
161*288bf522SAndroid Build Coastguard Worker return TraceOffCpuMode::ON_OFF_CPU;
162*288bf522SAndroid Build Coastguard Worker }
163*288bf522SAndroid Build Coastguard Worker if (s == "mixed-on-off-cpu") {
164*288bf522SAndroid Build Coastguard Worker return TraceOffCpuMode::MIXED_ON_OFF_CPU;
165*288bf522SAndroid Build Coastguard Worker }
166*288bf522SAndroid Build Coastguard Worker return std::nullopt;
167*288bf522SAndroid Build Coastguard Worker }
168*288bf522SAndroid Build Coastguard Worker
169*288bf522SAndroid Build Coastguard Worker struct TraceOffCpuData {
170*288bf522SAndroid Build Coastguard Worker std::vector<TraceOffCpuMode> supported_modes;
171*288bf522SAndroid Build Coastguard Worker std::string supported_modes_string;
172*288bf522SAndroid Build Coastguard Worker std::optional<TraceOffCpuMode> mode;
173*288bf522SAndroid Build Coastguard Worker std::unordered_map<pid_t, std::unique_ptr<SampleRecord>> thread_map;
174*288bf522SAndroid Build Coastguard Worker };
175*288bf522SAndroid Build Coastguard Worker
176*288bf522SAndroid Build Coastguard Worker } // namespace
177*288bf522SAndroid Build Coastguard Worker
178*288bf522SAndroid Build Coastguard Worker class ReportLib {
179*288bf522SAndroid Build Coastguard Worker public:
ReportLib()180*288bf522SAndroid Build Coastguard Worker ReportLib()
181*288bf522SAndroid Build Coastguard Worker : log_severity_(new android::base::ScopedLogSeverity(android::base::INFO)),
182*288bf522SAndroid Build Coastguard Worker record_filename_("perf.data"),
183*288bf522SAndroid Build Coastguard Worker current_thread_(nullptr),
184*288bf522SAndroid Build Coastguard Worker callchain_report_builder_(thread_tree_),
185*288bf522SAndroid Build Coastguard Worker record_filter_(thread_tree_) {}
186*288bf522SAndroid Build Coastguard Worker
187*288bf522SAndroid Build Coastguard Worker bool SetLogSeverity(const char* log_level);
188*288bf522SAndroid Build Coastguard Worker
SetSymfs(const char * symfs_dir)189*288bf522SAndroid Build Coastguard Worker bool SetSymfs(const char* symfs_dir) { return Dso::SetSymFsDir(symfs_dir); }
190*288bf522SAndroid Build Coastguard Worker
SetRecordFile(const char * record_file)191*288bf522SAndroid Build Coastguard Worker bool SetRecordFile(const char* record_file) {
192*288bf522SAndroid Build Coastguard Worker if (record_file_reader_) {
193*288bf522SAndroid Build Coastguard Worker LOG(ERROR) << "recording file " << record_filename_ << " has been opened";
194*288bf522SAndroid Build Coastguard Worker return false;
195*288bf522SAndroid Build Coastguard Worker }
196*288bf522SAndroid Build Coastguard Worker record_filename_ = record_file;
197*288bf522SAndroid Build Coastguard Worker return OpenRecordFileIfNecessary();
198*288bf522SAndroid Build Coastguard Worker }
199*288bf522SAndroid Build Coastguard Worker
200*288bf522SAndroid Build Coastguard Worker bool SetKallsymsFile(const char* kallsyms_file);
201*288bf522SAndroid Build Coastguard Worker
ShowIpForUnknownSymbol()202*288bf522SAndroid Build Coastguard Worker void ShowIpForUnknownSymbol() { thread_tree_.ShowIpForUnknownSymbol(); }
ShowArtFrames(bool show)203*288bf522SAndroid Build Coastguard Worker void ShowArtFrames(bool show) {
204*288bf522SAndroid Build Coastguard Worker bool remove_art_frame = !show;
205*288bf522SAndroid Build Coastguard Worker callchain_report_builder_.SetRemoveArtFrame(remove_art_frame);
206*288bf522SAndroid Build Coastguard Worker }
RemoveMethod(const char * method_name_regex)207*288bf522SAndroid Build Coastguard Worker bool RemoveMethod(const char* method_name_regex) {
208*288bf522SAndroid Build Coastguard Worker return callchain_report_builder_.RemoveMethod(method_name_regex);
209*288bf522SAndroid Build Coastguard Worker }
MergeJavaMethods(bool merge)210*288bf522SAndroid Build Coastguard Worker void MergeJavaMethods(bool merge) { callchain_report_builder_.SetConvertJITFrame(merge); }
AddProguardMappingFile(const char * mapping_file)211*288bf522SAndroid Build Coastguard Worker bool AddProguardMappingFile(const char* mapping_file) {
212*288bf522SAndroid Build Coastguard Worker return callchain_report_builder_.AddProguardMappingFile(mapping_file);
213*288bf522SAndroid Build Coastguard Worker }
214*288bf522SAndroid Build Coastguard Worker const char* GetSupportedTraceOffCpuModes();
215*288bf522SAndroid Build Coastguard Worker bool SetTraceOffCpuMode(const char* mode);
216*288bf522SAndroid Build Coastguard Worker bool SetSampleFilter(const char** filters, int filters_len);
217*288bf522SAndroid Build Coastguard Worker bool AggregateThreads(const char** thread_name_regex, int thread_name_regex_len);
218*288bf522SAndroid Build Coastguard Worker
219*288bf522SAndroid Build Coastguard Worker Sample* GetNextSample();
GetEventOfCurrentSample()220*288bf522SAndroid Build Coastguard Worker Event* GetEventOfCurrentSample() { return ¤t_event_; }
GetSymbolOfCurrentSample()221*288bf522SAndroid Build Coastguard Worker SymbolEntry* GetSymbolOfCurrentSample() { return current_symbol_; }
GetCallChainOfCurrentSample()222*288bf522SAndroid Build Coastguard Worker CallChain* GetCallChainOfCurrentSample() { return ¤t_callchain_; }
GetEventCountersOfCurrentSample()223*288bf522SAndroid Build Coastguard Worker EventCountersView* GetEventCountersOfCurrentSample() {
224*288bf522SAndroid Build Coastguard Worker event_counters_view_.nr = event_counters_.size();
225*288bf522SAndroid Build Coastguard Worker event_counters_view_.event_counter = event_counters_.data();
226*288bf522SAndroid Build Coastguard Worker return &event_counters_view_;
227*288bf522SAndroid Build Coastguard Worker }
GetTracingDataOfCurrentSample()228*288bf522SAndroid Build Coastguard Worker const char* GetTracingDataOfCurrentSample() { return current_tracing_data_; }
GetProcessNameOfCurrentSample()229*288bf522SAndroid Build Coastguard Worker const char* GetProcessNameOfCurrentSample() {
230*288bf522SAndroid Build Coastguard Worker const ThreadEntry* thread = thread_tree_.FindThread(current_sample_.pid);
231*288bf522SAndroid Build Coastguard Worker return (thread != nullptr) ? thread->comm : "unknown";
232*288bf522SAndroid Build Coastguard Worker }
233*288bf522SAndroid Build Coastguard Worker
234*288bf522SAndroid Build Coastguard Worker const char* GetBuildIdForPath(const char* path);
235*288bf522SAndroid Build Coastguard Worker FeatureSection* GetFeatureSection(const char* feature_name);
236*288bf522SAndroid Build Coastguard Worker
237*288bf522SAndroid Build Coastguard Worker private:
238*288bf522SAndroid Build Coastguard Worker std::unique_ptr<SampleRecord> GetNextSampleRecord();
239*288bf522SAndroid Build Coastguard Worker void ProcessSampleRecord(std::unique_ptr<Record> r);
240*288bf522SAndroid Build Coastguard Worker void ProcessSwitchRecord(std::unique_ptr<Record> r);
241*288bf522SAndroid Build Coastguard Worker void AddSampleRecordToQueue(SampleRecord* r);
242*288bf522SAndroid Build Coastguard Worker bool SetCurrentSample(std::unique_ptr<SampleRecord> sample_record);
243*288bf522SAndroid Build Coastguard Worker void SetEventCounters(const SampleRecord& r);
244*288bf522SAndroid Build Coastguard Worker const EventInfo& FindEvent(const SampleRecord& r);
245*288bf522SAndroid Build Coastguard Worker void CreateEvents();
246*288bf522SAndroid Build Coastguard Worker
247*288bf522SAndroid Build Coastguard Worker bool OpenRecordFileIfNecessary();
248*288bf522SAndroid Build Coastguard Worker Mapping* AddMapping(const MapEntry& map);
249*288bf522SAndroid Build Coastguard Worker
250*288bf522SAndroid Build Coastguard Worker std::unique_ptr<android::base::ScopedLogSeverity> log_severity_;
251*288bf522SAndroid Build Coastguard Worker std::string record_filename_;
252*288bf522SAndroid Build Coastguard Worker std::unique_ptr<RecordFileReader> record_file_reader_;
253*288bf522SAndroid Build Coastguard Worker ThreadTree thread_tree_;
254*288bf522SAndroid Build Coastguard Worker std::queue<std::unique_ptr<SampleRecord>> sample_record_queue_;
255*288bf522SAndroid Build Coastguard Worker const ThreadEntry* current_thread_;
256*288bf522SAndroid Build Coastguard Worker Sample current_sample_;
257*288bf522SAndroid Build Coastguard Worker Event current_event_;
258*288bf522SAndroid Build Coastguard Worker SymbolEntry* current_symbol_;
259*288bf522SAndroid Build Coastguard Worker CallChain current_callchain_;
260*288bf522SAndroid Build Coastguard Worker std::vector<EventCounter> event_counters_;
261*288bf522SAndroid Build Coastguard Worker EventCountersView event_counters_view_;
262*288bf522SAndroid Build Coastguard Worker const char* current_tracing_data_;
263*288bf522SAndroid Build Coastguard Worker std::vector<std::unique_ptr<Mapping>> current_mappings_;
264*288bf522SAndroid Build Coastguard Worker std::vector<CallChainEntry> callchain_entries_;
265*288bf522SAndroid Build Coastguard Worker std::string build_id_string_;
266*288bf522SAndroid Build Coastguard Worker std::vector<EventInfo> events_;
267*288bf522SAndroid Build Coastguard Worker TraceOffCpuData trace_offcpu_;
268*288bf522SAndroid Build Coastguard Worker FeatureSection feature_section_;
269*288bf522SAndroid Build Coastguard Worker std::vector<char> feature_section_data_;
270*288bf522SAndroid Build Coastguard Worker CallChainReportBuilder callchain_report_builder_;
271*288bf522SAndroid Build Coastguard Worker ThreadReportBuilder thread_report_builder_;
272*288bf522SAndroid Build Coastguard Worker std::unique_ptr<Tracing> tracing_;
273*288bf522SAndroid Build Coastguard Worker RecordFilter record_filter_;
274*288bf522SAndroid Build Coastguard Worker };
275*288bf522SAndroid Build Coastguard Worker
SetLogSeverity(const char * log_level)276*288bf522SAndroid Build Coastguard Worker bool ReportLib::SetLogSeverity(const char* log_level) {
277*288bf522SAndroid Build Coastguard Worker android::base::LogSeverity severity;
278*288bf522SAndroid Build Coastguard Worker if (!GetLogSeverity(log_level, &severity)) {
279*288bf522SAndroid Build Coastguard Worker LOG(ERROR) << "Unknown log severity: " << log_level;
280*288bf522SAndroid Build Coastguard Worker return false;
281*288bf522SAndroid Build Coastguard Worker }
282*288bf522SAndroid Build Coastguard Worker log_severity_ = nullptr;
283*288bf522SAndroid Build Coastguard Worker log_severity_.reset(new android::base::ScopedLogSeverity(severity));
284*288bf522SAndroid Build Coastguard Worker return true;
285*288bf522SAndroid Build Coastguard Worker }
286*288bf522SAndroid Build Coastguard Worker
SetKallsymsFile(const char * kallsyms_file)287*288bf522SAndroid Build Coastguard Worker bool ReportLib::SetKallsymsFile(const char* kallsyms_file) {
288*288bf522SAndroid Build Coastguard Worker std::string kallsyms;
289*288bf522SAndroid Build Coastguard Worker if (!android::base::ReadFileToString(kallsyms_file, &kallsyms)) {
290*288bf522SAndroid Build Coastguard Worker LOG(WARNING) << "Failed to read in kallsyms file from " << kallsyms_file;
291*288bf522SAndroid Build Coastguard Worker return false;
292*288bf522SAndroid Build Coastguard Worker }
293*288bf522SAndroid Build Coastguard Worker Dso::SetKallsyms(std::move(kallsyms));
294*288bf522SAndroid Build Coastguard Worker return true;
295*288bf522SAndroid Build Coastguard Worker }
296*288bf522SAndroid Build Coastguard Worker
GetSupportedTraceOffCpuModes()297*288bf522SAndroid Build Coastguard Worker const char* ReportLib::GetSupportedTraceOffCpuModes() {
298*288bf522SAndroid Build Coastguard Worker if (!OpenRecordFileIfNecessary()) {
299*288bf522SAndroid Build Coastguard Worker return nullptr;
300*288bf522SAndroid Build Coastguard Worker }
301*288bf522SAndroid Build Coastguard Worker std::string& s = trace_offcpu_.supported_modes_string;
302*288bf522SAndroid Build Coastguard Worker s.clear();
303*288bf522SAndroid Build Coastguard Worker for (auto mode : trace_offcpu_.supported_modes) {
304*288bf522SAndroid Build Coastguard Worker if (!s.empty()) {
305*288bf522SAndroid Build Coastguard Worker s += ",";
306*288bf522SAndroid Build Coastguard Worker }
307*288bf522SAndroid Build Coastguard Worker s += TraceOffCpuModeToString(mode);
308*288bf522SAndroid Build Coastguard Worker }
309*288bf522SAndroid Build Coastguard Worker return s.data();
310*288bf522SAndroid Build Coastguard Worker }
311*288bf522SAndroid Build Coastguard Worker
SetTraceOffCpuMode(const char * mode)312*288bf522SAndroid Build Coastguard Worker bool ReportLib::SetTraceOffCpuMode(const char* mode) {
313*288bf522SAndroid Build Coastguard Worker auto mode_value = StringToTraceOffCpuMode(mode);
314*288bf522SAndroid Build Coastguard Worker if (!mode_value) {
315*288bf522SAndroid Build Coastguard Worker return false;
316*288bf522SAndroid Build Coastguard Worker }
317*288bf522SAndroid Build Coastguard Worker if (!OpenRecordFileIfNecessary()) {
318*288bf522SAndroid Build Coastguard Worker return false;
319*288bf522SAndroid Build Coastguard Worker }
320*288bf522SAndroid Build Coastguard Worker auto& modes = trace_offcpu_.supported_modes;
321*288bf522SAndroid Build Coastguard Worker if (std::find(modes.begin(), modes.end(), mode_value) == modes.end()) {
322*288bf522SAndroid Build Coastguard Worker return false;
323*288bf522SAndroid Build Coastguard Worker }
324*288bf522SAndroid Build Coastguard Worker trace_offcpu_.mode = mode_value;
325*288bf522SAndroid Build Coastguard Worker return true;
326*288bf522SAndroid Build Coastguard Worker }
327*288bf522SAndroid Build Coastguard Worker
SetSampleFilter(const char ** filters,int filters_len)328*288bf522SAndroid Build Coastguard Worker bool ReportLib::SetSampleFilter(const char** filters, int filters_len) {
329*288bf522SAndroid Build Coastguard Worker std::vector<std::string> args;
330*288bf522SAndroid Build Coastguard Worker for (int i = 0; i < filters_len; i++) {
331*288bf522SAndroid Build Coastguard Worker args.emplace_back(filters[i]);
332*288bf522SAndroid Build Coastguard Worker }
333*288bf522SAndroid Build Coastguard Worker OptionFormatMap option_formats = GetRecordFilterOptionFormats(false);
334*288bf522SAndroid Build Coastguard Worker OptionValueMap options;
335*288bf522SAndroid Build Coastguard Worker std::vector<std::pair<OptionName, OptionValue>> ordered_options;
336*288bf522SAndroid Build Coastguard Worker if (!ConvertArgsToOptions(args, option_formats, "", &options, &ordered_options, nullptr)) {
337*288bf522SAndroid Build Coastguard Worker return false;
338*288bf522SAndroid Build Coastguard Worker }
339*288bf522SAndroid Build Coastguard Worker return record_filter_.ParseOptions(options);
340*288bf522SAndroid Build Coastguard Worker }
341*288bf522SAndroid Build Coastguard Worker
AggregateThreads(const char ** thread_name_regex,int thread_name_regex_len)342*288bf522SAndroid Build Coastguard Worker bool ReportLib::AggregateThreads(const char** thread_name_regex, int thread_name_regex_len) {
343*288bf522SAndroid Build Coastguard Worker std::vector<std::string> regs(thread_name_regex_len);
344*288bf522SAndroid Build Coastguard Worker for (int i = 0; i < thread_name_regex_len; ++i) {
345*288bf522SAndroid Build Coastguard Worker regs[i] = thread_name_regex[i];
346*288bf522SAndroid Build Coastguard Worker }
347*288bf522SAndroid Build Coastguard Worker return thread_report_builder_.AggregateThreads(regs);
348*288bf522SAndroid Build Coastguard Worker }
349*288bf522SAndroid Build Coastguard Worker
OpenRecordFileIfNecessary()350*288bf522SAndroid Build Coastguard Worker bool ReportLib::OpenRecordFileIfNecessary() {
351*288bf522SAndroid Build Coastguard Worker if (record_file_reader_ == nullptr) {
352*288bf522SAndroid Build Coastguard Worker record_file_reader_ = RecordFileReader::CreateInstance(record_filename_);
353*288bf522SAndroid Build Coastguard Worker if (record_file_reader_ == nullptr) {
354*288bf522SAndroid Build Coastguard Worker return false;
355*288bf522SAndroid Build Coastguard Worker }
356*288bf522SAndroid Build Coastguard Worker if (!record_file_reader_->LoadBuildIdAndFileFeatures(thread_tree_)) {
357*288bf522SAndroid Build Coastguard Worker return false;
358*288bf522SAndroid Build Coastguard Worker }
359*288bf522SAndroid Build Coastguard Worker auto& meta_info = record_file_reader_->GetMetaInfoFeature();
360*288bf522SAndroid Build Coastguard Worker if (auto it = meta_info.find("trace_offcpu"); it != meta_info.end() && it->second == "true") {
361*288bf522SAndroid Build Coastguard Worker // If recorded with --trace-offcpu, default is to report on-off-cpu samples.
362*288bf522SAndroid Build Coastguard Worker std::string event_name = GetEventNameByAttr(record_file_reader_->AttrSection()[0].attr);
363*288bf522SAndroid Build Coastguard Worker if (!android::base::StartsWith(event_name, "cpu-clock") &&
364*288bf522SAndroid Build Coastguard Worker !android::base::StartsWith(event_name, "task-clock")) {
365*288bf522SAndroid Build Coastguard Worker LOG(ERROR) << "Recording file " << record_filename_ << " is no longer supported. "
366*288bf522SAndroid Build Coastguard Worker << "--trace-offcpu must be used with `-e cpu-clock` or `-e task-clock`.";
367*288bf522SAndroid Build Coastguard Worker return false;
368*288bf522SAndroid Build Coastguard Worker }
369*288bf522SAndroid Build Coastguard Worker trace_offcpu_.mode = TraceOffCpuMode::MIXED_ON_OFF_CPU;
370*288bf522SAndroid Build Coastguard Worker trace_offcpu_.supported_modes.push_back(TraceOffCpuMode::MIXED_ON_OFF_CPU);
371*288bf522SAndroid Build Coastguard Worker trace_offcpu_.supported_modes.push_back(TraceOffCpuMode::ON_OFF_CPU);
372*288bf522SAndroid Build Coastguard Worker trace_offcpu_.supported_modes.push_back(TraceOffCpuMode::ON_CPU);
373*288bf522SAndroid Build Coastguard Worker trace_offcpu_.supported_modes.push_back(TraceOffCpuMode::OFF_CPU);
374*288bf522SAndroid Build Coastguard Worker }
375*288bf522SAndroid Build Coastguard Worker if (!record_filter_.CheckClock(record_file_reader_->GetClockId())) {
376*288bf522SAndroid Build Coastguard Worker LOG(ERROR) << "Recording file " << record_filename_ << " doesn't match the clock of filter.";
377*288bf522SAndroid Build Coastguard Worker return false;
378*288bf522SAndroid Build Coastguard Worker }
379*288bf522SAndroid Build Coastguard Worker }
380*288bf522SAndroid Build Coastguard Worker return true;
381*288bf522SAndroid Build Coastguard Worker }
382*288bf522SAndroid Build Coastguard Worker
GetNextSample()383*288bf522SAndroid Build Coastguard Worker Sample* ReportLib::GetNextSample() {
384*288bf522SAndroid Build Coastguard Worker if (!OpenRecordFileIfNecessary()) {
385*288bf522SAndroid Build Coastguard Worker return nullptr;
386*288bf522SAndroid Build Coastguard Worker }
387*288bf522SAndroid Build Coastguard Worker
388*288bf522SAndroid Build Coastguard Worker while (true) {
389*288bf522SAndroid Build Coastguard Worker std::unique_ptr<SampleRecord> r = GetNextSampleRecord();
390*288bf522SAndroid Build Coastguard Worker if (!r) {
391*288bf522SAndroid Build Coastguard Worker break;
392*288bf522SAndroid Build Coastguard Worker }
393*288bf522SAndroid Build Coastguard Worker if (SetCurrentSample(std::move(r))) {
394*288bf522SAndroid Build Coastguard Worker return ¤t_sample_;
395*288bf522SAndroid Build Coastguard Worker }
396*288bf522SAndroid Build Coastguard Worker }
397*288bf522SAndroid Build Coastguard Worker return nullptr;
398*288bf522SAndroid Build Coastguard Worker }
399*288bf522SAndroid Build Coastguard Worker
GetNextSampleRecord()400*288bf522SAndroid Build Coastguard Worker std::unique_ptr<SampleRecord> ReportLib::GetNextSampleRecord() {
401*288bf522SAndroid Build Coastguard Worker while (sample_record_queue_.empty()) {
402*288bf522SAndroid Build Coastguard Worker std::unique_ptr<Record> record;
403*288bf522SAndroid Build Coastguard Worker if (!record_file_reader_->ReadRecord(record) || record == nullptr) {
404*288bf522SAndroid Build Coastguard Worker return nullptr;
405*288bf522SAndroid Build Coastguard Worker }
406*288bf522SAndroid Build Coastguard Worker thread_tree_.Update(*record);
407*288bf522SAndroid Build Coastguard Worker if (record->type() == PERF_RECORD_SAMPLE) {
408*288bf522SAndroid Build Coastguard Worker ProcessSampleRecord(std::move(record));
409*288bf522SAndroid Build Coastguard Worker } else if (record->type() == PERF_RECORD_SWITCH ||
410*288bf522SAndroid Build Coastguard Worker record->type() == PERF_RECORD_SWITCH_CPU_WIDE) {
411*288bf522SAndroid Build Coastguard Worker ProcessSwitchRecord(std::move(record));
412*288bf522SAndroid Build Coastguard Worker } else if (record->type() == PERF_RECORD_TRACING_DATA ||
413*288bf522SAndroid Build Coastguard Worker record->type() == SIMPLE_PERF_RECORD_TRACING_DATA) {
414*288bf522SAndroid Build Coastguard Worker const auto& r = *static_cast<TracingDataRecord*>(record.get());
415*288bf522SAndroid Build Coastguard Worker tracing_ = Tracing::Create(std::vector<char>(r.data, r.data + r.data_size));
416*288bf522SAndroid Build Coastguard Worker if (!tracing_) {
417*288bf522SAndroid Build Coastguard Worker return nullptr;
418*288bf522SAndroid Build Coastguard Worker }
419*288bf522SAndroid Build Coastguard Worker }
420*288bf522SAndroid Build Coastguard Worker }
421*288bf522SAndroid Build Coastguard Worker std::unique_ptr<SampleRecord> result = std::move(sample_record_queue_.front());
422*288bf522SAndroid Build Coastguard Worker sample_record_queue_.pop();
423*288bf522SAndroid Build Coastguard Worker return result;
424*288bf522SAndroid Build Coastguard Worker }
425*288bf522SAndroid Build Coastguard Worker
ProcessSampleRecord(std::unique_ptr<Record> r)426*288bf522SAndroid Build Coastguard Worker void ReportLib::ProcessSampleRecord(std::unique_ptr<Record> r) {
427*288bf522SAndroid Build Coastguard Worker auto sr = static_cast<SampleRecord*>(r.get());
428*288bf522SAndroid Build Coastguard Worker if (!trace_offcpu_.mode) {
429*288bf522SAndroid Build Coastguard Worker r.release();
430*288bf522SAndroid Build Coastguard Worker AddSampleRecordToQueue(sr);
431*288bf522SAndroid Build Coastguard Worker return;
432*288bf522SAndroid Build Coastguard Worker }
433*288bf522SAndroid Build Coastguard Worker size_t attr_index = record_file_reader_->GetAttrIndexOfRecord(sr);
434*288bf522SAndroid Build Coastguard Worker bool offcpu_sample = attr_index > 0;
435*288bf522SAndroid Build Coastguard Worker if (trace_offcpu_.mode == TraceOffCpuMode::ON_CPU) {
436*288bf522SAndroid Build Coastguard Worker if (!offcpu_sample) {
437*288bf522SAndroid Build Coastguard Worker r.release();
438*288bf522SAndroid Build Coastguard Worker AddSampleRecordToQueue(sr);
439*288bf522SAndroid Build Coastguard Worker }
440*288bf522SAndroid Build Coastguard Worker return;
441*288bf522SAndroid Build Coastguard Worker }
442*288bf522SAndroid Build Coastguard Worker uint32_t tid = sr->tid_data.tid;
443*288bf522SAndroid Build Coastguard Worker auto it = trace_offcpu_.thread_map.find(tid);
444*288bf522SAndroid Build Coastguard Worker if (it == trace_offcpu_.thread_map.end() || !it->second) {
445*288bf522SAndroid Build Coastguard Worker // If there is no previous off-cpu sample, then store the current off-cpu sample.
446*288bf522SAndroid Build Coastguard Worker if (offcpu_sample) {
447*288bf522SAndroid Build Coastguard Worker r.release();
448*288bf522SAndroid Build Coastguard Worker if (it == trace_offcpu_.thread_map.end()) {
449*288bf522SAndroid Build Coastguard Worker trace_offcpu_.thread_map[tid].reset(sr);
450*288bf522SAndroid Build Coastguard Worker } else {
451*288bf522SAndroid Build Coastguard Worker it->second.reset(sr);
452*288bf522SAndroid Build Coastguard Worker }
453*288bf522SAndroid Build Coastguard Worker }
454*288bf522SAndroid Build Coastguard Worker } else {
455*288bf522SAndroid Build Coastguard Worker // If there is a previous off-cpu sample, update its period.
456*288bf522SAndroid Build Coastguard Worker SampleRecord* prev_sr = it->second.get();
457*288bf522SAndroid Build Coastguard Worker prev_sr->period_data.period =
458*288bf522SAndroid Build Coastguard Worker (prev_sr->Timestamp() < sr->Timestamp()) ? (sr->Timestamp() - prev_sr->Timestamp()) : 1;
459*288bf522SAndroid Build Coastguard Worker it->second.release();
460*288bf522SAndroid Build Coastguard Worker AddSampleRecordToQueue(prev_sr);
461*288bf522SAndroid Build Coastguard Worker if (offcpu_sample) {
462*288bf522SAndroid Build Coastguard Worker r.release();
463*288bf522SAndroid Build Coastguard Worker it->second.reset(sr);
464*288bf522SAndroid Build Coastguard Worker }
465*288bf522SAndroid Build Coastguard Worker }
466*288bf522SAndroid Build Coastguard Worker if (!offcpu_sample && (trace_offcpu_.mode == TraceOffCpuMode::ON_OFF_CPU ||
467*288bf522SAndroid Build Coastguard Worker trace_offcpu_.mode == TraceOffCpuMode::MIXED_ON_OFF_CPU)) {
468*288bf522SAndroid Build Coastguard Worker r.release();
469*288bf522SAndroid Build Coastguard Worker AddSampleRecordToQueue(sr);
470*288bf522SAndroid Build Coastguard Worker }
471*288bf522SAndroid Build Coastguard Worker }
472*288bf522SAndroid Build Coastguard Worker
ProcessSwitchRecord(std::unique_ptr<Record> r)473*288bf522SAndroid Build Coastguard Worker void ReportLib::ProcessSwitchRecord(std::unique_ptr<Record> r) {
474*288bf522SAndroid Build Coastguard Worker if (r->header.misc & PERF_RECORD_MISC_SWITCH_OUT) {
475*288bf522SAndroid Build Coastguard Worker return;
476*288bf522SAndroid Build Coastguard Worker }
477*288bf522SAndroid Build Coastguard Worker uint32_t tid = r->sample_id.tid_data.tid;
478*288bf522SAndroid Build Coastguard Worker auto it = trace_offcpu_.thread_map.find(tid);
479*288bf522SAndroid Build Coastguard Worker if (it != trace_offcpu_.thread_map.end() && it->second) {
480*288bf522SAndroid Build Coastguard Worker // If there is a previous off-cpu sample, update its period.
481*288bf522SAndroid Build Coastguard Worker SampleRecord* prev_sr = it->second.get();
482*288bf522SAndroid Build Coastguard Worker prev_sr->period_data.period =
483*288bf522SAndroid Build Coastguard Worker (prev_sr->Timestamp() < r->Timestamp()) ? (r->Timestamp() - prev_sr->Timestamp()) : 1;
484*288bf522SAndroid Build Coastguard Worker it->second.release();
485*288bf522SAndroid Build Coastguard Worker AddSampleRecordToQueue(prev_sr);
486*288bf522SAndroid Build Coastguard Worker }
487*288bf522SAndroid Build Coastguard Worker }
488*288bf522SAndroid Build Coastguard Worker
AddSampleRecordToQueue(SampleRecord * r)489*288bf522SAndroid Build Coastguard Worker void ReportLib::AddSampleRecordToQueue(SampleRecord* r) {
490*288bf522SAndroid Build Coastguard Worker if (record_filter_.Check(*r)) {
491*288bf522SAndroid Build Coastguard Worker sample_record_queue_.emplace(r);
492*288bf522SAndroid Build Coastguard Worker }
493*288bf522SAndroid Build Coastguard Worker }
494*288bf522SAndroid Build Coastguard Worker
SetCurrentSample(std::unique_ptr<SampleRecord> sample_record)495*288bf522SAndroid Build Coastguard Worker bool ReportLib::SetCurrentSample(std::unique_ptr<SampleRecord> sample_record) {
496*288bf522SAndroid Build Coastguard Worker const SampleRecord& r = *sample_record;
497*288bf522SAndroid Build Coastguard Worker current_mappings_.clear();
498*288bf522SAndroid Build Coastguard Worker callchain_entries_.clear();
499*288bf522SAndroid Build Coastguard Worker current_sample_.ip = r.ip_data.ip;
500*288bf522SAndroid Build Coastguard Worker current_thread_ = thread_tree_.FindThreadOrNew(r.tid_data.pid, r.tid_data.tid);
501*288bf522SAndroid Build Coastguard Worker ThreadReport thread_report = thread_report_builder_.Build(*current_thread_);
502*288bf522SAndroid Build Coastguard Worker current_sample_.pid = thread_report.pid;
503*288bf522SAndroid Build Coastguard Worker current_sample_.tid = thread_report.tid;
504*288bf522SAndroid Build Coastguard Worker current_sample_.thread_comm = thread_report.thread_name;
505*288bf522SAndroid Build Coastguard Worker current_sample_.time = r.time_data.time;
506*288bf522SAndroid Build Coastguard Worker current_sample_.in_kernel = r.InKernel();
507*288bf522SAndroid Build Coastguard Worker current_sample_.cpu = r.cpu_data.cpu;
508*288bf522SAndroid Build Coastguard Worker current_sample_.period = r.period_data.period;
509*288bf522SAndroid Build Coastguard Worker
510*288bf522SAndroid Build Coastguard Worker size_t kernel_ip_count;
511*288bf522SAndroid Build Coastguard Worker std::vector<uint64_t> ips = r.GetCallChain(&kernel_ip_count);
512*288bf522SAndroid Build Coastguard Worker std::vector<CallChainReportEntry> report_entries =
513*288bf522SAndroid Build Coastguard Worker callchain_report_builder_.Build(current_thread_, ips, kernel_ip_count);
514*288bf522SAndroid Build Coastguard Worker if (report_entries.empty()) {
515*288bf522SAndroid Build Coastguard Worker // Skip samples with callchain fully removed by RemoveMethod().
516*288bf522SAndroid Build Coastguard Worker return false;
517*288bf522SAndroid Build Coastguard Worker }
518*288bf522SAndroid Build Coastguard Worker
519*288bf522SAndroid Build Coastguard Worker for (const auto& report_entry : report_entries) {
520*288bf522SAndroid Build Coastguard Worker callchain_entries_.resize(callchain_entries_.size() + 1);
521*288bf522SAndroid Build Coastguard Worker CallChainEntry& entry = callchain_entries_.back();
522*288bf522SAndroid Build Coastguard Worker entry.ip = report_entry.ip;
523*288bf522SAndroid Build Coastguard Worker if (report_entry.dso_name != nullptr) {
524*288bf522SAndroid Build Coastguard Worker entry.symbol.dso_name = report_entry.dso_name;
525*288bf522SAndroid Build Coastguard Worker } else {
526*288bf522SAndroid Build Coastguard Worker entry.symbol.dso_name = report_entry.dso->GetReportPath().data();
527*288bf522SAndroid Build Coastguard Worker }
528*288bf522SAndroid Build Coastguard Worker entry.symbol.vaddr_in_file = report_entry.vaddr_in_file;
529*288bf522SAndroid Build Coastguard Worker entry.symbol.symbol_name = report_entry.symbol->DemangledName();
530*288bf522SAndroid Build Coastguard Worker entry.symbol.symbol_addr = report_entry.symbol->addr;
531*288bf522SAndroid Build Coastguard Worker entry.symbol.symbol_len = report_entry.symbol->len;
532*288bf522SAndroid Build Coastguard Worker entry.symbol.mapping = AddMapping(*report_entry.map);
533*288bf522SAndroid Build Coastguard Worker }
534*288bf522SAndroid Build Coastguard Worker current_sample_.ip = callchain_entries_[0].ip;
535*288bf522SAndroid Build Coastguard Worker current_symbol_ = &(callchain_entries_[0].symbol);
536*288bf522SAndroid Build Coastguard Worker current_callchain_.nr = callchain_entries_.size() - 1;
537*288bf522SAndroid Build Coastguard Worker current_callchain_.entries = &callchain_entries_[1];
538*288bf522SAndroid Build Coastguard Worker const EventInfo& event = FindEvent(r);
539*288bf522SAndroid Build Coastguard Worker current_event_.name = event.name.c_str();
540*288bf522SAndroid Build Coastguard Worker current_event_.tracing_data_format = event.tracing_info.data_format;
541*288bf522SAndroid Build Coastguard Worker if (current_event_.tracing_data_format.size > 0u && (r.sample_type & PERF_SAMPLE_RAW)) {
542*288bf522SAndroid Build Coastguard Worker CHECK_GE(r.raw_data.size, current_event_.tracing_data_format.size);
543*288bf522SAndroid Build Coastguard Worker current_tracing_data_ = r.raw_data.data;
544*288bf522SAndroid Build Coastguard Worker } else {
545*288bf522SAndroid Build Coastguard Worker current_tracing_data_ = nullptr;
546*288bf522SAndroid Build Coastguard Worker }
547*288bf522SAndroid Build Coastguard Worker SetEventCounters(r);
548*288bf522SAndroid Build Coastguard Worker return true;
549*288bf522SAndroid Build Coastguard Worker }
550*288bf522SAndroid Build Coastguard Worker
SetEventCounters(const SampleRecord & r)551*288bf522SAndroid Build Coastguard Worker void ReportLib::SetEventCounters(const SampleRecord& r) {
552*288bf522SAndroid Build Coastguard Worker const std::vector<uint64_t>& ids = r.read_data.ids;
553*288bf522SAndroid Build Coastguard Worker const std::vector<uint64_t>& counts = r.read_data.counts;
554*288bf522SAndroid Build Coastguard Worker CHECK_EQ(ids.size(), counts.size());
555*288bf522SAndroid Build Coastguard Worker
556*288bf522SAndroid Build Coastguard Worker event_counters_.clear();
557*288bf522SAndroid Build Coastguard Worker for (size_t i = 0; i < ids.size(); i++) {
558*288bf522SAndroid Build Coastguard Worker uint64_t event_id = ids[i];
559*288bf522SAndroid Build Coastguard Worker uint64_t count = counts[i];
560*288bf522SAndroid Build Coastguard Worker std::optional<size_t> attr_index = record_file_reader_->GetAttrIndexByEventId(event_id);
561*288bf522SAndroid Build Coastguard Worker if (!attr_index) {
562*288bf522SAndroid Build Coastguard Worker LOG(ERROR) << "Failed to find event name for event id " << event_id;
563*288bf522SAndroid Build Coastguard Worker continue;
564*288bf522SAndroid Build Coastguard Worker }
565*288bf522SAndroid Build Coastguard Worker
566*288bf522SAndroid Build Coastguard Worker event_counters_.emplace_back(events_[*attr_index].name.c_str(), event_id, count);
567*288bf522SAndroid Build Coastguard Worker }
568*288bf522SAndroid Build Coastguard Worker }
569*288bf522SAndroid Build Coastguard Worker
FindEvent(const SampleRecord & r)570*288bf522SAndroid Build Coastguard Worker const EventInfo& ReportLib::FindEvent(const SampleRecord& r) {
571*288bf522SAndroid Build Coastguard Worker if (events_.empty()) {
572*288bf522SAndroid Build Coastguard Worker CreateEvents();
573*288bf522SAndroid Build Coastguard Worker }
574*288bf522SAndroid Build Coastguard Worker if (trace_offcpu_.mode == TraceOffCpuMode::MIXED_ON_OFF_CPU) {
575*288bf522SAndroid Build Coastguard Worker // To mix on-cpu and off-cpu samples, pretend they are from the same event type.
576*288bf522SAndroid Build Coastguard Worker // Otherwise, some report scripts may split them.
577*288bf522SAndroid Build Coastguard Worker return events_[0];
578*288bf522SAndroid Build Coastguard Worker }
579*288bf522SAndroid Build Coastguard Worker size_t attr_index = record_file_reader_->GetAttrIndexOfRecord(&r);
580*288bf522SAndroid Build Coastguard Worker return events_[attr_index];
581*288bf522SAndroid Build Coastguard Worker }
582*288bf522SAndroid Build Coastguard Worker
CreateEvents()583*288bf522SAndroid Build Coastguard Worker void ReportLib::CreateEvents() {
584*288bf522SAndroid Build Coastguard Worker const EventAttrIds& attrs = record_file_reader_->AttrSection();
585*288bf522SAndroid Build Coastguard Worker events_.resize(attrs.size());
586*288bf522SAndroid Build Coastguard Worker for (size_t i = 0; i < attrs.size(); ++i) {
587*288bf522SAndroid Build Coastguard Worker events_[i].attr = attrs[i].attr;
588*288bf522SAndroid Build Coastguard Worker events_[i].name = GetEventNameByAttr(events_[i].attr);
589*288bf522SAndroid Build Coastguard Worker EventInfo::TracingInfo& tracing_info = events_[i].tracing_info;
590*288bf522SAndroid Build Coastguard Worker tracing_info.data_format.size = 0;
591*288bf522SAndroid Build Coastguard Worker tracing_info.data_format.field_count = 0;
592*288bf522SAndroid Build Coastguard Worker tracing_info.data_format.fields = nullptr;
593*288bf522SAndroid Build Coastguard Worker
594*288bf522SAndroid Build Coastguard Worker if (events_[i].attr.type == PERF_TYPE_TRACEPOINT && tracing_) {
595*288bf522SAndroid Build Coastguard Worker std::optional<TracingFormat> opt_format =
596*288bf522SAndroid Build Coastguard Worker tracing_->GetTracingFormatHavingId(events_[i].attr.config);
597*288bf522SAndroid Build Coastguard Worker if (!opt_format.has_value() || opt_format.value().fields.empty()) {
598*288bf522SAndroid Build Coastguard Worker continue;
599*288bf522SAndroid Build Coastguard Worker }
600*288bf522SAndroid Build Coastguard Worker const TracingFormat& format = opt_format.value();
601*288bf522SAndroid Build Coastguard Worker tracing_info.field_names.resize(format.fields.size());
602*288bf522SAndroid Build Coastguard Worker tracing_info.fields.resize(format.fields.size());
603*288bf522SAndroid Build Coastguard Worker for (size_t i = 0; i < format.fields.size(); ++i) {
604*288bf522SAndroid Build Coastguard Worker tracing_info.field_names[i] = format.fields[i].name;
605*288bf522SAndroid Build Coastguard Worker TracingFieldFormat& field = tracing_info.fields[i];
606*288bf522SAndroid Build Coastguard Worker field.name = tracing_info.field_names[i].c_str();
607*288bf522SAndroid Build Coastguard Worker field.offset = format.fields[i].offset;
608*288bf522SAndroid Build Coastguard Worker field.elem_size = format.fields[i].elem_size;
609*288bf522SAndroid Build Coastguard Worker field.elem_count = format.fields[i].elem_count;
610*288bf522SAndroid Build Coastguard Worker field.is_signed = format.fields[i].is_signed;
611*288bf522SAndroid Build Coastguard Worker field.is_dynamic = format.fields[i].is_dynamic;
612*288bf522SAndroid Build Coastguard Worker }
613*288bf522SAndroid Build Coastguard Worker TracingFieldFormat& field = tracing_info.fields.back();
614*288bf522SAndroid Build Coastguard Worker tracing_info.data_format.size = field.offset + field.elem_size * field.elem_count;
615*288bf522SAndroid Build Coastguard Worker tracing_info.data_format.field_count = tracing_info.fields.size();
616*288bf522SAndroid Build Coastguard Worker tracing_info.data_format.fields = &tracing_info.fields[0];
617*288bf522SAndroid Build Coastguard Worker }
618*288bf522SAndroid Build Coastguard Worker }
619*288bf522SAndroid Build Coastguard Worker }
620*288bf522SAndroid Build Coastguard Worker
AddMapping(const MapEntry & map)621*288bf522SAndroid Build Coastguard Worker Mapping* ReportLib::AddMapping(const MapEntry& map) {
622*288bf522SAndroid Build Coastguard Worker current_mappings_.emplace_back(std::unique_ptr<Mapping>(new Mapping));
623*288bf522SAndroid Build Coastguard Worker Mapping* mapping = current_mappings_.back().get();
624*288bf522SAndroid Build Coastguard Worker mapping->start = map.start_addr;
625*288bf522SAndroid Build Coastguard Worker mapping->end = map.start_addr + map.len;
626*288bf522SAndroid Build Coastguard Worker mapping->pgoff = map.pgoff;
627*288bf522SAndroid Build Coastguard Worker return mapping;
628*288bf522SAndroid Build Coastguard Worker }
629*288bf522SAndroid Build Coastguard Worker
GetBuildIdForPath(const char * path)630*288bf522SAndroid Build Coastguard Worker const char* ReportLib::GetBuildIdForPath(const char* path) {
631*288bf522SAndroid Build Coastguard Worker if (!OpenRecordFileIfNecessary()) {
632*288bf522SAndroid Build Coastguard Worker build_id_string_.clear();
633*288bf522SAndroid Build Coastguard Worker return build_id_string_.c_str();
634*288bf522SAndroid Build Coastguard Worker }
635*288bf522SAndroid Build Coastguard Worker BuildId build_id = Dso::FindExpectedBuildIdForPath(path);
636*288bf522SAndroid Build Coastguard Worker if (build_id.IsEmpty()) {
637*288bf522SAndroid Build Coastguard Worker build_id_string_.clear();
638*288bf522SAndroid Build Coastguard Worker } else {
639*288bf522SAndroid Build Coastguard Worker build_id_string_ = build_id.ToString();
640*288bf522SAndroid Build Coastguard Worker }
641*288bf522SAndroid Build Coastguard Worker return build_id_string_.c_str();
642*288bf522SAndroid Build Coastguard Worker }
643*288bf522SAndroid Build Coastguard Worker
GetFeatureSection(const char * feature_name)644*288bf522SAndroid Build Coastguard Worker FeatureSection* ReportLib::GetFeatureSection(const char* feature_name) {
645*288bf522SAndroid Build Coastguard Worker if (!OpenRecordFileIfNecessary()) {
646*288bf522SAndroid Build Coastguard Worker return nullptr;
647*288bf522SAndroid Build Coastguard Worker }
648*288bf522SAndroid Build Coastguard Worker int feature = PerfFileFormat::GetFeatureId(feature_name);
649*288bf522SAndroid Build Coastguard Worker if (feature == -1 || !record_file_reader_->ReadFeatureSection(feature, &feature_section_data_)) {
650*288bf522SAndroid Build Coastguard Worker return nullptr;
651*288bf522SAndroid Build Coastguard Worker }
652*288bf522SAndroid Build Coastguard Worker feature_section_.data = feature_section_data_.data();
653*288bf522SAndroid Build Coastguard Worker feature_section_.data_size = feature_section_data_.size();
654*288bf522SAndroid Build Coastguard Worker return &feature_section_;
655*288bf522SAndroid Build Coastguard Worker }
656*288bf522SAndroid Build Coastguard Worker
657*288bf522SAndroid Build Coastguard Worker } // namespace simpleperf
658*288bf522SAndroid Build Coastguard Worker
659*288bf522SAndroid Build Coastguard Worker using ReportLib = simpleperf::ReportLib;
660*288bf522SAndroid Build Coastguard Worker
661*288bf522SAndroid Build Coastguard Worker extern "C" {
662*288bf522SAndroid Build Coastguard Worker
663*288bf522SAndroid Build Coastguard Worker #define EXPORT __attribute__((visibility("default")))
664*288bf522SAndroid Build Coastguard Worker
665*288bf522SAndroid Build Coastguard Worker // Create a new instance,
666*288bf522SAndroid Build Coastguard Worker // pass the instance to the other functions below.
667*288bf522SAndroid Build Coastguard Worker ReportLib* CreateReportLib() EXPORT;
668*288bf522SAndroid Build Coastguard Worker void DestroyReportLib(ReportLib* report_lib) EXPORT;
669*288bf522SAndroid Build Coastguard Worker
670*288bf522SAndroid Build Coastguard Worker // Set log severity, different levels are:
671*288bf522SAndroid Build Coastguard Worker // verbose, debug, info, warning, error, fatal.
672*288bf522SAndroid Build Coastguard Worker bool SetLogSeverity(ReportLib* report_lib, const char* log_level) EXPORT;
673*288bf522SAndroid Build Coastguard Worker bool SetSymfs(ReportLib* report_lib, const char* symfs_dir) EXPORT;
674*288bf522SAndroid Build Coastguard Worker bool SetRecordFile(ReportLib* report_lib, const char* record_file) EXPORT;
675*288bf522SAndroid Build Coastguard Worker bool SetKallsymsFile(ReportLib* report_lib, const char* kallsyms_file) EXPORT;
676*288bf522SAndroid Build Coastguard Worker void ShowIpForUnknownSymbol(ReportLib* report_lib) EXPORT;
677*288bf522SAndroid Build Coastguard Worker void ShowArtFrames(ReportLib* report_lib, bool show) EXPORT;
678*288bf522SAndroid Build Coastguard Worker bool RemoveMethod(ReportLib* report_lib, const char* method_name_regex) EXPORT;
679*288bf522SAndroid Build Coastguard Worker void MergeJavaMethods(ReportLib* report_lib, bool merge) EXPORT;
680*288bf522SAndroid Build Coastguard Worker bool AddProguardMappingFile(ReportLib* report_lib, const char* mapping_file) EXPORT;
681*288bf522SAndroid Build Coastguard Worker const char* GetSupportedTraceOffCpuModes(ReportLib* report_lib) EXPORT;
682*288bf522SAndroid Build Coastguard Worker bool SetTraceOffCpuMode(ReportLib* report_lib, const char* mode) EXPORT;
683*288bf522SAndroid Build Coastguard Worker bool SetSampleFilter(ReportLib* report_lib, const char** filters, int filters_len) EXPORT;
684*288bf522SAndroid Build Coastguard Worker bool AggregateThreads(ReportLib* report_lib, const char** thread_name_regex,
685*288bf522SAndroid Build Coastguard Worker int thread_name_regex_len) EXPORT;
686*288bf522SAndroid Build Coastguard Worker
687*288bf522SAndroid Build Coastguard Worker Sample* GetNextSample(ReportLib* report_lib) EXPORT;
688*288bf522SAndroid Build Coastguard Worker Event* GetEventOfCurrentSample(ReportLib* report_lib) EXPORT;
689*288bf522SAndroid Build Coastguard Worker SymbolEntry* GetSymbolOfCurrentSample(ReportLib* report_lib) EXPORT;
690*288bf522SAndroid Build Coastguard Worker CallChain* GetCallChainOfCurrentSample(ReportLib* report_lib) EXPORT;
691*288bf522SAndroid Build Coastguard Worker EventCountersView* GetEventCountersOfCurrentSample(ReportLib* report_lib) EXPORT;
692*288bf522SAndroid Build Coastguard Worker const char* GetTracingDataOfCurrentSample(ReportLib* report_lib) EXPORT;
693*288bf522SAndroid Build Coastguard Worker const char* GetProcessNameOfCurrentSample(ReportLib* report_lib) EXPORT;
694*288bf522SAndroid Build Coastguard Worker
695*288bf522SAndroid Build Coastguard Worker const char* GetBuildIdForPath(ReportLib* report_lib, const char* path) EXPORT;
696*288bf522SAndroid Build Coastguard Worker FeatureSection* GetFeatureSection(ReportLib* report_lib, const char* feature_name) EXPORT;
697*288bf522SAndroid Build Coastguard Worker }
698*288bf522SAndroid Build Coastguard Worker
699*288bf522SAndroid Build Coastguard Worker // Exported methods working with a client created instance
CreateReportLib()700*288bf522SAndroid Build Coastguard Worker ReportLib* CreateReportLib() {
701*288bf522SAndroid Build Coastguard Worker return new ReportLib();
702*288bf522SAndroid Build Coastguard Worker }
703*288bf522SAndroid Build Coastguard Worker
DestroyReportLib(ReportLib * report_lib)704*288bf522SAndroid Build Coastguard Worker void DestroyReportLib(ReportLib* report_lib) {
705*288bf522SAndroid Build Coastguard Worker delete report_lib;
706*288bf522SAndroid Build Coastguard Worker }
707*288bf522SAndroid Build Coastguard Worker
SetLogSeverity(ReportLib * report_lib,const char * log_level)708*288bf522SAndroid Build Coastguard Worker bool SetLogSeverity(ReportLib* report_lib, const char* log_level) {
709*288bf522SAndroid Build Coastguard Worker return report_lib->SetLogSeverity(log_level);
710*288bf522SAndroid Build Coastguard Worker }
711*288bf522SAndroid Build Coastguard Worker
SetSymfs(ReportLib * report_lib,const char * symfs_dir)712*288bf522SAndroid Build Coastguard Worker bool SetSymfs(ReportLib* report_lib, const char* symfs_dir) {
713*288bf522SAndroid Build Coastguard Worker return report_lib->SetSymfs(symfs_dir);
714*288bf522SAndroid Build Coastguard Worker }
715*288bf522SAndroid Build Coastguard Worker
SetRecordFile(ReportLib * report_lib,const char * record_file)716*288bf522SAndroid Build Coastguard Worker bool SetRecordFile(ReportLib* report_lib, const char* record_file) {
717*288bf522SAndroid Build Coastguard Worker return report_lib->SetRecordFile(record_file);
718*288bf522SAndroid Build Coastguard Worker }
719*288bf522SAndroid Build Coastguard Worker
ShowIpForUnknownSymbol(ReportLib * report_lib)720*288bf522SAndroid Build Coastguard Worker void ShowIpForUnknownSymbol(ReportLib* report_lib) {
721*288bf522SAndroid Build Coastguard Worker return report_lib->ShowIpForUnknownSymbol();
722*288bf522SAndroid Build Coastguard Worker }
723*288bf522SAndroid Build Coastguard Worker
ShowArtFrames(ReportLib * report_lib,bool show)724*288bf522SAndroid Build Coastguard Worker void ShowArtFrames(ReportLib* report_lib, bool show) {
725*288bf522SAndroid Build Coastguard Worker return report_lib->ShowArtFrames(show);
726*288bf522SAndroid Build Coastguard Worker }
727*288bf522SAndroid Build Coastguard Worker
RemoveMethod(ReportLib * report_lib,const char * method_name_regex)728*288bf522SAndroid Build Coastguard Worker bool RemoveMethod(ReportLib* report_lib, const char* method_name_regex) {
729*288bf522SAndroid Build Coastguard Worker return report_lib->RemoveMethod(method_name_regex);
730*288bf522SAndroid Build Coastguard Worker }
731*288bf522SAndroid Build Coastguard Worker
MergeJavaMethods(ReportLib * report_lib,bool merge)732*288bf522SAndroid Build Coastguard Worker void MergeJavaMethods(ReportLib* report_lib, bool merge) {
733*288bf522SAndroid Build Coastguard Worker return report_lib->MergeJavaMethods(merge);
734*288bf522SAndroid Build Coastguard Worker }
735*288bf522SAndroid Build Coastguard Worker
SetKallsymsFile(ReportLib * report_lib,const char * kallsyms_file)736*288bf522SAndroid Build Coastguard Worker bool SetKallsymsFile(ReportLib* report_lib, const char* kallsyms_file) {
737*288bf522SAndroid Build Coastguard Worker return report_lib->SetKallsymsFile(kallsyms_file);
738*288bf522SAndroid Build Coastguard Worker }
739*288bf522SAndroid Build Coastguard Worker
AddProguardMappingFile(ReportLib * report_lib,const char * mapping_file)740*288bf522SAndroid Build Coastguard Worker bool AddProguardMappingFile(ReportLib* report_lib, const char* mapping_file) {
741*288bf522SAndroid Build Coastguard Worker return report_lib->AddProguardMappingFile(mapping_file);
742*288bf522SAndroid Build Coastguard Worker }
743*288bf522SAndroid Build Coastguard Worker
GetSupportedTraceOffCpuModes(ReportLib * report_lib)744*288bf522SAndroid Build Coastguard Worker const char* GetSupportedTraceOffCpuModes(ReportLib* report_lib) {
745*288bf522SAndroid Build Coastguard Worker return report_lib->GetSupportedTraceOffCpuModes();
746*288bf522SAndroid Build Coastguard Worker }
747*288bf522SAndroid Build Coastguard Worker
SetTraceOffCpuMode(ReportLib * report_lib,const char * mode)748*288bf522SAndroid Build Coastguard Worker bool SetTraceOffCpuMode(ReportLib* report_lib, const char* mode) {
749*288bf522SAndroid Build Coastguard Worker return report_lib->SetTraceOffCpuMode(mode);
750*288bf522SAndroid Build Coastguard Worker }
751*288bf522SAndroid Build Coastguard Worker
SetSampleFilter(ReportLib * report_lib,const char ** filters,int filters_len)752*288bf522SAndroid Build Coastguard Worker bool SetSampleFilter(ReportLib* report_lib, const char** filters, int filters_len) {
753*288bf522SAndroid Build Coastguard Worker return report_lib->SetSampleFilter(filters, filters_len);
754*288bf522SAndroid Build Coastguard Worker }
755*288bf522SAndroid Build Coastguard Worker
AggregateThreads(ReportLib * report_lib,const char ** thread_name_regex,int thread_name_regex_len)756*288bf522SAndroid Build Coastguard Worker bool AggregateThreads(ReportLib* report_lib, const char** thread_name_regex,
757*288bf522SAndroid Build Coastguard Worker int thread_name_regex_len) {
758*288bf522SAndroid Build Coastguard Worker return report_lib->AggregateThreads(thread_name_regex, thread_name_regex_len);
759*288bf522SAndroid Build Coastguard Worker }
760*288bf522SAndroid Build Coastguard Worker
GetNextSample(ReportLib * report_lib)761*288bf522SAndroid Build Coastguard Worker Sample* GetNextSample(ReportLib* report_lib) {
762*288bf522SAndroid Build Coastguard Worker return report_lib->GetNextSample();
763*288bf522SAndroid Build Coastguard Worker }
764*288bf522SAndroid Build Coastguard Worker
GetEventOfCurrentSample(ReportLib * report_lib)765*288bf522SAndroid Build Coastguard Worker Event* GetEventOfCurrentSample(ReportLib* report_lib) {
766*288bf522SAndroid Build Coastguard Worker return report_lib->GetEventOfCurrentSample();
767*288bf522SAndroid Build Coastguard Worker }
768*288bf522SAndroid Build Coastguard Worker
GetSymbolOfCurrentSample(ReportLib * report_lib)769*288bf522SAndroid Build Coastguard Worker SymbolEntry* GetSymbolOfCurrentSample(ReportLib* report_lib) {
770*288bf522SAndroid Build Coastguard Worker return report_lib->GetSymbolOfCurrentSample();
771*288bf522SAndroid Build Coastguard Worker }
772*288bf522SAndroid Build Coastguard Worker
GetCallChainOfCurrentSample(ReportLib * report_lib)773*288bf522SAndroid Build Coastguard Worker CallChain* GetCallChainOfCurrentSample(ReportLib* report_lib) {
774*288bf522SAndroid Build Coastguard Worker return report_lib->GetCallChainOfCurrentSample();
775*288bf522SAndroid Build Coastguard Worker }
776*288bf522SAndroid Build Coastguard Worker
GetEventCountersOfCurrentSample(ReportLib * report_lib)777*288bf522SAndroid Build Coastguard Worker EventCountersView* GetEventCountersOfCurrentSample(ReportLib* report_lib) {
778*288bf522SAndroid Build Coastguard Worker return report_lib->GetEventCountersOfCurrentSample();
779*288bf522SAndroid Build Coastguard Worker }
780*288bf522SAndroid Build Coastguard Worker
GetTracingDataOfCurrentSample(ReportLib * report_lib)781*288bf522SAndroid Build Coastguard Worker const char* GetTracingDataOfCurrentSample(ReportLib* report_lib) {
782*288bf522SAndroid Build Coastguard Worker return report_lib->GetTracingDataOfCurrentSample();
783*288bf522SAndroid Build Coastguard Worker }
784*288bf522SAndroid Build Coastguard Worker
GetProcessNameOfCurrentSample(ReportLib * report_lib)785*288bf522SAndroid Build Coastguard Worker const char* GetProcessNameOfCurrentSample(ReportLib* report_lib) {
786*288bf522SAndroid Build Coastguard Worker return report_lib->GetProcessNameOfCurrentSample();
787*288bf522SAndroid Build Coastguard Worker }
788*288bf522SAndroid Build Coastguard Worker
GetBuildIdForPath(ReportLib * report_lib,const char * path)789*288bf522SAndroid Build Coastguard Worker const char* GetBuildIdForPath(ReportLib* report_lib, const char* path) {
790*288bf522SAndroid Build Coastguard Worker return report_lib->GetBuildIdForPath(path);
791*288bf522SAndroid Build Coastguard Worker }
792*288bf522SAndroid Build Coastguard Worker
GetFeatureSection(ReportLib * report_lib,const char * feature_name)793*288bf522SAndroid Build Coastguard Worker FeatureSection* GetFeatureSection(ReportLib* report_lib, const char* feature_name) {
794*288bf522SAndroid Build Coastguard Worker return report_lib->GetFeatureSection(feature_name);
795*288bf522SAndroid Build Coastguard Worker }
796