1*288bf522SAndroid Build Coastguard Worker /*
2*288bf522SAndroid Build Coastguard Worker * Copyright (C) 2020 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 #include <inttypes.h>
17*288bf522SAndroid Build Coastguard Worker #include <libgen.h>
18*288bf522SAndroid Build Coastguard Worker #include <signal.h>
19*288bf522SAndroid Build Coastguard Worker #include <sys/mman.h>
20*288bf522SAndroid Build Coastguard Worker #include <sys/prctl.h>
21*288bf522SAndroid Build Coastguard Worker #include <sys/utsname.h>
22*288bf522SAndroid Build Coastguard Worker #include <time.h>
23*288bf522SAndroid Build Coastguard Worker #include <unistd.h>
24*288bf522SAndroid Build Coastguard Worker #include <optional>
25*288bf522SAndroid Build Coastguard Worker #include <set>
26*288bf522SAndroid Build Coastguard Worker #include <string>
27*288bf522SAndroid Build Coastguard Worker #include <unordered_map>
28*288bf522SAndroid Build Coastguard Worker #include <unordered_set>
29*288bf522SAndroid Build Coastguard Worker #include <vector>
30*288bf522SAndroid Build Coastguard Worker
31*288bf522SAndroid Build Coastguard Worker #include <android-base/file.h>
32*288bf522SAndroid Build Coastguard Worker #include <android-base/logging.h>
33*288bf522SAndroid Build Coastguard Worker #include <android-base/parseint.h>
34*288bf522SAndroid Build Coastguard Worker #include <android-base/stringprintf.h>
35*288bf522SAndroid Build Coastguard Worker #include <android-base/strings.h>
36*288bf522SAndroid Build Coastguard Worker #include <android-base/unique_fd.h>
37*288bf522SAndroid Build Coastguard Worker #if defined(__ANDROID__)
38*288bf522SAndroid Build Coastguard Worker #include <android-base/properties.h>
39*288bf522SAndroid Build Coastguard Worker #endif
40*288bf522SAndroid Build Coastguard Worker
41*288bf522SAndroid Build Coastguard Worker #include "IOEventLoop.h"
42*288bf522SAndroid Build Coastguard Worker #include "MapRecordReader.h"
43*288bf522SAndroid Build Coastguard Worker #include "OfflineUnwinder.h"
44*288bf522SAndroid Build Coastguard Worker #include "RecordFilter.h"
45*288bf522SAndroid Build Coastguard Worker #include "command.h"
46*288bf522SAndroid Build Coastguard Worker #include "dso.h"
47*288bf522SAndroid Build Coastguard Worker #include "environment.h"
48*288bf522SAndroid Build Coastguard Worker #include "event_selection_set.h"
49*288bf522SAndroid Build Coastguard Worker #include "event_type.h"
50*288bf522SAndroid Build Coastguard Worker #include "read_elf.h"
51*288bf522SAndroid Build Coastguard Worker #include "read_symbol_map.h"
52*288bf522SAndroid Build Coastguard Worker #include "record.h"
53*288bf522SAndroid Build Coastguard Worker #include "thread_tree.h"
54*288bf522SAndroid Build Coastguard Worker #include "tracing.h"
55*288bf522SAndroid Build Coastguard Worker #include "utils.h"
56*288bf522SAndroid Build Coastguard Worker
57*288bf522SAndroid Build Coastguard Worker namespace simpleperf {
58*288bf522SAndroid Build Coastguard Worker namespace {
59*288bf522SAndroid Build Coastguard Worker
60*288bf522SAndroid Build Coastguard Worker using android::base::ParseUint;
61*288bf522SAndroid Build Coastguard Worker using android::base::Realpath;
62*288bf522SAndroid Build Coastguard Worker using android::base::StringAppendF;
63*288bf522SAndroid Build Coastguard Worker
64*288bf522SAndroid Build Coastguard Worker struct SymbolInfo {
65*288bf522SAndroid Build Coastguard Worker Dso* dso;
66*288bf522SAndroid Build Coastguard Worker const Symbol* symbol;
67*288bf522SAndroid Build Coastguard Worker uint64_t vaddr_in_file;
68*288bf522SAndroid Build Coastguard Worker };
69*288bf522SAndroid Build Coastguard Worker
70*288bf522SAndroid Build Coastguard Worker // The max size of records dumped by kernel is 65535, and dump stack size
71*288bf522SAndroid Build Coastguard Worker // should be a multiply of 8, so MAX_DUMP_STACK_SIZE is 65528.
72*288bf522SAndroid Build Coastguard Worker constexpr uint32_t MAX_DUMP_STACK_SIZE = 65528;
73*288bf522SAndroid Build Coastguard Worker
74*288bf522SAndroid Build Coastguard Worker // The max allowed pages in mapped buffer is decided by rlimit(RLIMIT_MEMLOCK).
75*288bf522SAndroid Build Coastguard Worker // Here 1024 is a desired value for pages in mapped buffer. If mapped
76*288bf522SAndroid Build Coastguard Worker // successfully, the buffer size = 1024 * 4K (page size) = 4M.
77*288bf522SAndroid Build Coastguard Worker constexpr size_t DESIRED_PAGES_IN_MAPPED_BUFFER = 1024;
78*288bf522SAndroid Build Coastguard Worker
79*288bf522SAndroid Build Coastguard Worker // Currently, the record buffer size in user-space is set to match the kernel
80*288bf522SAndroid Build Coastguard Worker // buffer size on a 8 core system. For system-wide recording, it is 8K pages *
81*288bf522SAndroid Build Coastguard Worker // 4K page_size * 8 cores = 256MB. For non system-wide recording, it is 1K pages
82*288bf522SAndroid Build Coastguard Worker // * 4K page_size * 8 cores = 64MB.
83*288bf522SAndroid Build Coastguard Worker static constexpr size_t kRecordBufferSize = 64 * kMegabyte;
84*288bf522SAndroid Build Coastguard Worker static constexpr size_t kSystemWideRecordBufferSize = 256 * kMegabyte;
85*288bf522SAndroid Build Coastguard Worker
86*288bf522SAndroid Build Coastguard Worker class MonitorCommand : public Command {
87*288bf522SAndroid Build Coastguard Worker public:
MonitorCommand()88*288bf522SAndroid Build Coastguard Worker MonitorCommand()
89*288bf522SAndroid Build Coastguard Worker : Command(
90*288bf522SAndroid Build Coastguard Worker "monitor", "monitor events and print their textual representations to stdout",
91*288bf522SAndroid Build Coastguard Worker // clang-format off
92*288bf522SAndroid Build Coastguard Worker "Usage: simpleperf monitor [options]\n"
93*288bf522SAndroid Build Coastguard Worker " Gather sampling information and print the events on stdout.\n"
94*288bf522SAndroid Build Coastguard Worker " For precise recording, prefer the record command.\n"
95*288bf522SAndroid Build Coastguard Worker " Currently, only supports system-wide collection.\n"
96*288bf522SAndroid Build Coastguard Worker "\n"
97*288bf522SAndroid Build Coastguard Worker "Select monitored threads:\n"
98*288bf522SAndroid Build Coastguard Worker "-a System-wide collection. Use with --exclude-perf to exclude\n"
99*288bf522SAndroid Build Coastguard Worker " samples for simpleperf process.\n"
100*288bf522SAndroid Build Coastguard Worker "\n"
101*288bf522SAndroid Build Coastguard Worker "Select monitored event types:\n"
102*288bf522SAndroid Build Coastguard Worker "-e event1[:modifier1],event2[:modifier2],...\n"
103*288bf522SAndroid Build Coastguard Worker " Select a list of events to record. An event can be:\n"
104*288bf522SAndroid Build Coastguard Worker " 1) an event name listed in `simpleperf list`;\n"
105*288bf522SAndroid Build Coastguard Worker " 2) a raw PMU event in rN format. N is a hex number.\n"
106*288bf522SAndroid Build Coastguard Worker " For example, r1b selects event number 0x1b.\n"
107*288bf522SAndroid Build Coastguard Worker " Modifiers can be added to define how the event should be\n"
108*288bf522SAndroid Build Coastguard Worker " monitored. Possible modifiers are:\n"
109*288bf522SAndroid Build Coastguard Worker " u - monitor user space events only\n"
110*288bf522SAndroid Build Coastguard Worker " k - monitor kernel space events only\n"
111*288bf522SAndroid Build Coastguard Worker "\n"
112*288bf522SAndroid Build Coastguard Worker "Select monitoring options:\n"
113*288bf522SAndroid Build Coastguard Worker "-f freq Set event sample frequency. It means recording at most [freq]\n"
114*288bf522SAndroid Build Coastguard Worker " samples every second. For non-tracepoint events, the default\n"
115*288bf522SAndroid Build Coastguard Worker " option is -f 4000. A -f/-c option affects all event types\n"
116*288bf522SAndroid Build Coastguard Worker " following it until meeting another -f/-c option. For example,\n"
117*288bf522SAndroid Build Coastguard Worker " for \"-f 1000 -e cpu-cycles -c 1 -e sched:sched_switch\", cpu-cycles\n"
118*288bf522SAndroid Build Coastguard Worker " has sample freq 1000, sched:sched_switch event has sample period 1.\n"
119*288bf522SAndroid Build Coastguard Worker "-c count Set event sample period. It means recording one sample when\n"
120*288bf522SAndroid Build Coastguard Worker " [count] events happen. For tracepoint events, the default option\n"
121*288bf522SAndroid Build Coastguard Worker " is -c 1.\n"
122*288bf522SAndroid Build Coastguard Worker "--call-graph fp | dwarf[,<dump_stack_size>]\n"
123*288bf522SAndroid Build Coastguard Worker " Enable call graph recording. Use frame pointer or dwarf debug\n"
124*288bf522SAndroid Build Coastguard Worker " frame as the method to parse call graph in stack.\n"
125*288bf522SAndroid Build Coastguard Worker " Default is dwarf,65528.\n"
126*288bf522SAndroid Build Coastguard Worker "-g Same as '--call-graph dwarf'.\n"
127*288bf522SAndroid Build Coastguard Worker "--duration time_in_sec Monitor for time_in_sec seconds. Here time_in_sec"
128*288bf522SAndroid Build Coastguard Worker " may be any positive floating point number.\n"
129*288bf522SAndroid Build Coastguard Worker "--cpu-percent <percent> Set the max percent of cpu time used for recording.\n"
130*288bf522SAndroid Build Coastguard Worker " percent is in range [1-100], default is 25.\n"
131*288bf522SAndroid Build Coastguard Worker "\n"
132*288bf522SAndroid Build Coastguard Worker "Sample filter options:\n"
133*288bf522SAndroid Build Coastguard Worker "--exclude-perf Exclude samples for simpleperf process.\n"
134*288bf522SAndroid Build Coastguard Worker RECORD_FILTER_OPTION_HELP_MSG_FOR_RECORDING
135*288bf522SAndroid Build Coastguard Worker "\n"
136*288bf522SAndroid Build Coastguard Worker // clang-format on
137*288bf522SAndroid Build Coastguard Worker ),
138*288bf522SAndroid Build Coastguard Worker system_wide_collection_(false),
139*288bf522SAndroid Build Coastguard Worker fp_callchain_sampling_(false),
140*288bf522SAndroid Build Coastguard Worker dwarf_callchain_sampling_(false),
141*288bf522SAndroid Build Coastguard Worker dump_stack_size_in_dwarf_sampling_(MAX_DUMP_STACK_SIZE),
142*288bf522SAndroid Build Coastguard Worker unwind_dwarf_callchain_(true),
143*288bf522SAndroid Build Coastguard Worker duration_in_sec_(0),
144*288bf522SAndroid Build Coastguard Worker event_selection_set_(false),
145*288bf522SAndroid Build Coastguard Worker mmap_page_range_(std::make_pair(1, DESIRED_PAGES_IN_MAPPED_BUFFER)),
146*288bf522SAndroid Build Coastguard Worker sample_record_count_(0),
147*288bf522SAndroid Build Coastguard Worker last_record_timestamp_(0u),
148*288bf522SAndroid Build Coastguard Worker record_filter_(thread_tree_) {
149*288bf522SAndroid Build Coastguard Worker // If we run `adb shell simpleperf record xxx` and stop profiling by ctrl-c,
150*288bf522SAndroid Build Coastguard Worker // adb closes sockets connecting simpleperf. After that, simpleperf will
151*288bf522SAndroid Build Coastguard Worker // receive SIGPIPE when writing to stdout/stderr, which is a problem when we
152*288bf522SAndroid Build Coastguard Worker // use '--app' option. So ignore SIGPIPE to finish properly.
153*288bf522SAndroid Build Coastguard Worker signal(SIGPIPE, SIG_IGN);
154*288bf522SAndroid Build Coastguard Worker }
155*288bf522SAndroid Build Coastguard Worker
156*288bf522SAndroid Build Coastguard Worker bool Run(const std::vector<std::string>& args);
157*288bf522SAndroid Build Coastguard Worker
158*288bf522SAndroid Build Coastguard Worker private:
159*288bf522SAndroid Build Coastguard Worker bool ParseOptions(const std::vector<std::string>& args);
160*288bf522SAndroid Build Coastguard Worker bool AdjustPerfEventLimit();
161*288bf522SAndroid Build Coastguard Worker bool PrepareMonitoring();
162*288bf522SAndroid Build Coastguard Worker bool DoMonitoring();
163*288bf522SAndroid Build Coastguard Worker bool SetEventSelectionFlags();
164*288bf522SAndroid Build Coastguard Worker bool DumpProcessMaps(pid_t pid, const std::unordered_set<pid_t>& tids);
165*288bf522SAndroid Build Coastguard Worker void DumpSampleRecord(const SampleRecord& sr);
166*288bf522SAndroid Build Coastguard Worker void DumpSampleCallchain(const SampleRecord& sr);
167*288bf522SAndroid Build Coastguard Worker bool ProcessRecord(Record* record);
168*288bf522SAndroid Build Coastguard Worker SymbolInfo GetSymbolInfo(uint32_t pid, uint32_t tid, uint64_t ip, bool in_kernel);
169*288bf522SAndroid Build Coastguard Worker bool DumpMapsForRecord(Record* record);
170*288bf522SAndroid Build Coastguard Worker void UpdateRecord(Record* record);
171*288bf522SAndroid Build Coastguard Worker bool UnwindRecord(SampleRecord& r);
172*288bf522SAndroid Build Coastguard Worker
173*288bf522SAndroid Build Coastguard Worker uint64_t max_sample_freq_ = DEFAULT_SAMPLE_FREQ_FOR_NONTRACEPOINT_EVENT;
174*288bf522SAndroid Build Coastguard Worker size_t cpu_time_max_percent_ = 25;
175*288bf522SAndroid Build Coastguard Worker
176*288bf522SAndroid Build Coastguard Worker bool system_wide_collection_;
177*288bf522SAndroid Build Coastguard Worker bool fp_callchain_sampling_;
178*288bf522SAndroid Build Coastguard Worker bool dwarf_callchain_sampling_;
179*288bf522SAndroid Build Coastguard Worker uint32_t dump_stack_size_in_dwarf_sampling_;
180*288bf522SAndroid Build Coastguard Worker bool unwind_dwarf_callchain_;
181*288bf522SAndroid Build Coastguard Worker std::unique_ptr<OfflineUnwinder> offline_unwinder_;
182*288bf522SAndroid Build Coastguard Worker double duration_in_sec_;
183*288bf522SAndroid Build Coastguard Worker EventSelectionSet event_selection_set_;
184*288bf522SAndroid Build Coastguard Worker std::pair<size_t, size_t> mmap_page_range_;
185*288bf522SAndroid Build Coastguard Worker ThreadTree thread_tree_;
186*288bf522SAndroid Build Coastguard Worker uint64_t sample_record_count_;
187*288bf522SAndroid Build Coastguard Worker uint64_t last_record_timestamp_; // used to insert Mmap2Records for JIT debug info
188*288bf522SAndroid Build Coastguard Worker // In system wide recording, record if we have dumped map info for a process.
189*288bf522SAndroid Build Coastguard Worker std::unordered_set<pid_t> dumped_processes_;
190*288bf522SAndroid Build Coastguard Worker bool exclude_perf_ = false;
191*288bf522SAndroid Build Coastguard Worker RecordFilter record_filter_;
192*288bf522SAndroid Build Coastguard Worker std::unordered_map<uint64_t, std::string> event_names_;
193*288bf522SAndroid Build Coastguard Worker
194*288bf522SAndroid Build Coastguard Worker std::optional<MapRecordReader> map_record_reader_;
195*288bf522SAndroid Build Coastguard Worker };
196*288bf522SAndroid Build Coastguard Worker
Run(const std::vector<std::string> & args)197*288bf522SAndroid Build Coastguard Worker bool MonitorCommand::Run(const std::vector<std::string>& args) {
198*288bf522SAndroid Build Coastguard Worker ScopedCurrentArch scoped_arch(GetMachineArch());
199*288bf522SAndroid Build Coastguard Worker if (!CheckPerfEventLimit()) {
200*288bf522SAndroid Build Coastguard Worker return false;
201*288bf522SAndroid Build Coastguard Worker }
202*288bf522SAndroid Build Coastguard Worker AllowMoreOpenedFiles();
203*288bf522SAndroid Build Coastguard Worker
204*288bf522SAndroid Build Coastguard Worker if (!ParseOptions(args)) {
205*288bf522SAndroid Build Coastguard Worker return false;
206*288bf522SAndroid Build Coastguard Worker }
207*288bf522SAndroid Build Coastguard Worker if (!AdjustPerfEventLimit()) {
208*288bf522SAndroid Build Coastguard Worker return false;
209*288bf522SAndroid Build Coastguard Worker }
210*288bf522SAndroid Build Coastguard Worker
211*288bf522SAndroid Build Coastguard Worker if (!PrepareMonitoring()) {
212*288bf522SAndroid Build Coastguard Worker return false;
213*288bf522SAndroid Build Coastguard Worker }
214*288bf522SAndroid Build Coastguard Worker return DoMonitoring();
215*288bf522SAndroid Build Coastguard Worker }
216*288bf522SAndroid Build Coastguard Worker
PrepareMonitoring()217*288bf522SAndroid Build Coastguard Worker bool MonitorCommand::PrepareMonitoring() {
218*288bf522SAndroid Build Coastguard Worker // 1. Process options before opening perf event files.
219*288bf522SAndroid Build Coastguard Worker if (!SetEventSelectionFlags()) {
220*288bf522SAndroid Build Coastguard Worker return false;
221*288bf522SAndroid Build Coastguard Worker }
222*288bf522SAndroid Build Coastguard Worker if (unwind_dwarf_callchain_) {
223*288bf522SAndroid Build Coastguard Worker offline_unwinder_ = OfflineUnwinder::Create(false);
224*288bf522SAndroid Build Coastguard Worker }
225*288bf522SAndroid Build Coastguard Worker
226*288bf522SAndroid Build Coastguard Worker // 2. Add monitored targets.
227*288bf522SAndroid Build Coastguard Worker if (system_wide_collection_) {
228*288bf522SAndroid Build Coastguard Worker event_selection_set_.AddMonitoredThreads({-1});
229*288bf522SAndroid Build Coastguard Worker } else {
230*288bf522SAndroid Build Coastguard Worker LOG(ERROR) << "No threads to monitor. Try `simpleperf help monitor` for help";
231*288bf522SAndroid Build Coastguard Worker return false;
232*288bf522SAndroid Build Coastguard Worker }
233*288bf522SAndroid Build Coastguard Worker
234*288bf522SAndroid Build Coastguard Worker // 3. Open perf event files and create mapped buffers.
235*288bf522SAndroid Build Coastguard Worker if (!event_selection_set_.OpenEventFiles()) {
236*288bf522SAndroid Build Coastguard Worker return false;
237*288bf522SAndroid Build Coastguard Worker }
238*288bf522SAndroid Build Coastguard Worker size_t record_buffer_size =
239*288bf522SAndroid Build Coastguard Worker system_wide_collection_ ? kSystemWideRecordBufferSize : kRecordBufferSize;
240*288bf522SAndroid Build Coastguard Worker if (!event_selection_set_.MmapEventFiles(mmap_page_range_.first, mmap_page_range_.second,
241*288bf522SAndroid Build Coastguard Worker 0 /* aux_buffer_size */, record_buffer_size,
242*288bf522SAndroid Build Coastguard Worker false /* allow_truncating_samples */, exclude_perf_)) {
243*288bf522SAndroid Build Coastguard Worker return false;
244*288bf522SAndroid Build Coastguard Worker }
245*288bf522SAndroid Build Coastguard Worker auto callback = std::bind(&MonitorCommand::ProcessRecord, this, std::placeholders::_1);
246*288bf522SAndroid Build Coastguard Worker if (!event_selection_set_.PrepareToReadMmapEventData(callback)) {
247*288bf522SAndroid Build Coastguard Worker return false;
248*288bf522SAndroid Build Coastguard Worker }
249*288bf522SAndroid Build Coastguard Worker
250*288bf522SAndroid Build Coastguard Worker // Keep track of the event names per id.
251*288bf522SAndroid Build Coastguard Worker event_names_ = event_selection_set_.GetEventNamesById();
252*288bf522SAndroid Build Coastguard Worker
253*288bf522SAndroid Build Coastguard Worker // Use first perf_event_attr and first event id to dump mmap and comm records.
254*288bf522SAndroid Build Coastguard Worker EventAttrWithId dumping_attr_id = event_selection_set_.GetEventAttrWithId()[0];
255*288bf522SAndroid Build Coastguard Worker map_record_reader_.emplace(dumping_attr_id.attr, dumping_attr_id.ids[0],
256*288bf522SAndroid Build Coastguard Worker event_selection_set_.RecordNotExecutableMaps());
257*288bf522SAndroid Build Coastguard Worker map_record_reader_->SetCallback([this](Record* r) { return ProcessRecord(r); });
258*288bf522SAndroid Build Coastguard Worker
259*288bf522SAndroid Build Coastguard Worker // 4. Load kallsyms, if possible.
260*288bf522SAndroid Build Coastguard Worker std::string kallsyms;
261*288bf522SAndroid Build Coastguard Worker if (LoadKernelSymbols(&kallsyms)) {
262*288bf522SAndroid Build Coastguard Worker Dso::SetKallsyms(std::move(kallsyms));
263*288bf522SAndroid Build Coastguard Worker }
264*288bf522SAndroid Build Coastguard Worker map_record_reader_->ReadKernelMaps();
265*288bf522SAndroid Build Coastguard Worker
266*288bf522SAndroid Build Coastguard Worker // 5. Add read/signal/periodic Events.
267*288bf522SAndroid Build Coastguard Worker IOEventLoop* loop = event_selection_set_.GetIOEventLoop();
268*288bf522SAndroid Build Coastguard Worker auto exit_loop_callback = [loop]() { return loop->ExitLoop(); };
269*288bf522SAndroid Build Coastguard Worker if (!loop->AddSignalEvents({SIGCHLD, SIGINT, SIGTERM}, exit_loop_callback, IOEventHighPriority)) {
270*288bf522SAndroid Build Coastguard Worker return false;
271*288bf522SAndroid Build Coastguard Worker }
272*288bf522SAndroid Build Coastguard Worker
273*288bf522SAndroid Build Coastguard Worker // Only add an event for SIGHUP if we didn't inherit SIG_IGN (e.g. from
274*288bf522SAndroid Build Coastguard Worker // nohup).
275*288bf522SAndroid Build Coastguard Worker if (!SignalIsIgnored(SIGHUP)) {
276*288bf522SAndroid Build Coastguard Worker if (!loop->AddSignalEvent(SIGHUP, exit_loop_callback, IOEventHighPriority)) {
277*288bf522SAndroid Build Coastguard Worker return false;
278*288bf522SAndroid Build Coastguard Worker }
279*288bf522SAndroid Build Coastguard Worker }
280*288bf522SAndroid Build Coastguard Worker
281*288bf522SAndroid Build Coastguard Worker if (duration_in_sec_ != 0) {
282*288bf522SAndroid Build Coastguard Worker if (!loop->AddPeriodicEvent(
283*288bf522SAndroid Build Coastguard Worker SecondToTimeval(duration_in_sec_), [loop]() { return loop->ExitLoop(); },
284*288bf522SAndroid Build Coastguard Worker IOEventHighPriority)) {
285*288bf522SAndroid Build Coastguard Worker return false;
286*288bf522SAndroid Build Coastguard Worker }
287*288bf522SAndroid Build Coastguard Worker }
288*288bf522SAndroid Build Coastguard Worker return true;
289*288bf522SAndroid Build Coastguard Worker }
290*288bf522SAndroid Build Coastguard Worker
DoMonitoring()291*288bf522SAndroid Build Coastguard Worker bool MonitorCommand::DoMonitoring() {
292*288bf522SAndroid Build Coastguard Worker if (!event_selection_set_.GetIOEventLoop()->RunLoop()) {
293*288bf522SAndroid Build Coastguard Worker return false;
294*288bf522SAndroid Build Coastguard Worker }
295*288bf522SAndroid Build Coastguard Worker if (!event_selection_set_.SyncKernelBuffer()) {
296*288bf522SAndroid Build Coastguard Worker return false;
297*288bf522SAndroid Build Coastguard Worker }
298*288bf522SAndroid Build Coastguard Worker event_selection_set_.CloseEventFiles();
299*288bf522SAndroid Build Coastguard Worker if (!event_selection_set_.FinishReadMmapEventData()) {
300*288bf522SAndroid Build Coastguard Worker return false;
301*288bf522SAndroid Build Coastguard Worker }
302*288bf522SAndroid Build Coastguard Worker LOG(ERROR) << "Processed samples: " << sample_record_count_;
303*288bf522SAndroid Build Coastguard Worker return true;
304*288bf522SAndroid Build Coastguard Worker }
305*288bf522SAndroid Build Coastguard Worker
GetMonitorCmdOptionFormats()306*288bf522SAndroid Build Coastguard Worker inline const OptionFormatMap& GetMonitorCmdOptionFormats() {
307*288bf522SAndroid Build Coastguard Worker static OptionFormatMap option_formats;
308*288bf522SAndroid Build Coastguard Worker if (option_formats.empty()) {
309*288bf522SAndroid Build Coastguard Worker option_formats = {
310*288bf522SAndroid Build Coastguard Worker {"-a", {OptionValueType::NONE, OptionType::SINGLE, AppRunnerType::NOT_ALLOWED}},
311*288bf522SAndroid Build Coastguard Worker {"-c", {OptionValueType::UINT, OptionType::ORDERED, AppRunnerType::ALLOWED}},
312*288bf522SAndroid Build Coastguard Worker {"--call-graph", {OptionValueType::STRING, OptionType::ORDERED, AppRunnerType::ALLOWED}},
313*288bf522SAndroid Build Coastguard Worker {"--cpu-percent", {OptionValueType::UINT, OptionType::SINGLE, AppRunnerType::ALLOWED}},
314*288bf522SAndroid Build Coastguard Worker {"--duration", {OptionValueType::DOUBLE, OptionType::SINGLE, AppRunnerType::ALLOWED}},
315*288bf522SAndroid Build Coastguard Worker {"-e", {OptionValueType::STRING, OptionType::ORDERED, AppRunnerType::ALLOWED}},
316*288bf522SAndroid Build Coastguard Worker {"--exclude-perf", {OptionValueType::NONE, OptionType::SINGLE, AppRunnerType::ALLOWED}},
317*288bf522SAndroid Build Coastguard Worker {"-f", {OptionValueType::UINT, OptionType::ORDERED, AppRunnerType::ALLOWED}},
318*288bf522SAndroid Build Coastguard Worker {"-g", {OptionValueType::NONE, OptionType::ORDERED, AppRunnerType::ALLOWED}},
319*288bf522SAndroid Build Coastguard Worker {"-t", {OptionValueType::STRING, OptionType::MULTIPLE, AppRunnerType::ALLOWED}},
320*288bf522SAndroid Build Coastguard Worker };
321*288bf522SAndroid Build Coastguard Worker OptionFormatMap record_filter_options = GetRecordFilterOptionFormats(true);
322*288bf522SAndroid Build Coastguard Worker option_formats.insert(record_filter_options.begin(), record_filter_options.end());
323*288bf522SAndroid Build Coastguard Worker }
324*288bf522SAndroid Build Coastguard Worker return option_formats;
325*288bf522SAndroid Build Coastguard Worker }
326*288bf522SAndroid Build Coastguard Worker
ParseOptions(const std::vector<std::string> & args)327*288bf522SAndroid Build Coastguard Worker bool MonitorCommand::ParseOptions(const std::vector<std::string>& args) {
328*288bf522SAndroid Build Coastguard Worker OptionValueMap options;
329*288bf522SAndroid Build Coastguard Worker std::vector<std::pair<OptionName, OptionValue>> ordered_options;
330*288bf522SAndroid Build Coastguard Worker
331*288bf522SAndroid Build Coastguard Worker if (!PreprocessOptions(args, GetMonitorCmdOptionFormats(), &options, &ordered_options, nullptr)) {
332*288bf522SAndroid Build Coastguard Worker return false;
333*288bf522SAndroid Build Coastguard Worker }
334*288bf522SAndroid Build Coastguard Worker
335*288bf522SAndroid Build Coastguard Worker // Process options.
336*288bf522SAndroid Build Coastguard Worker system_wide_collection_ = options.PullBoolValue("-a");
337*288bf522SAndroid Build Coastguard Worker
338*288bf522SAndroid Build Coastguard Worker if (!options.PullUintValue("--cpu-percent", &cpu_time_max_percent_, 1, 100)) {
339*288bf522SAndroid Build Coastguard Worker return false;
340*288bf522SAndroid Build Coastguard Worker }
341*288bf522SAndroid Build Coastguard Worker
342*288bf522SAndroid Build Coastguard Worker if (!options.PullDoubleValue("--duration", &duration_in_sec_, 1e-9)) {
343*288bf522SAndroid Build Coastguard Worker return false;
344*288bf522SAndroid Build Coastguard Worker }
345*288bf522SAndroid Build Coastguard Worker
346*288bf522SAndroid Build Coastguard Worker exclude_perf_ = options.PullBoolValue("--exclude-perf");
347*288bf522SAndroid Build Coastguard Worker if (!record_filter_.ParseOptions(options)) {
348*288bf522SAndroid Build Coastguard Worker return false;
349*288bf522SAndroid Build Coastguard Worker }
350*288bf522SAndroid Build Coastguard Worker
351*288bf522SAndroid Build Coastguard Worker CHECK(options.values.empty());
352*288bf522SAndroid Build Coastguard Worker
353*288bf522SAndroid Build Coastguard Worker // Process ordered options.
354*288bf522SAndroid Build Coastguard Worker for (const auto& pair : ordered_options) {
355*288bf522SAndroid Build Coastguard Worker const OptionName& name = pair.first;
356*288bf522SAndroid Build Coastguard Worker const OptionValue& value = pair.second;
357*288bf522SAndroid Build Coastguard Worker
358*288bf522SAndroid Build Coastguard Worker if (name == "-c" || name == "-f") {
359*288bf522SAndroid Build Coastguard Worker if (value.uint_value < 1) {
360*288bf522SAndroid Build Coastguard Worker LOG(ERROR) << "invalid " << name << ": " << value.uint_value;
361*288bf522SAndroid Build Coastguard Worker return false;
362*288bf522SAndroid Build Coastguard Worker }
363*288bf522SAndroid Build Coastguard Worker SampleRate rate;
364*288bf522SAndroid Build Coastguard Worker if (name == "-c") {
365*288bf522SAndroid Build Coastguard Worker rate.sample_period = value.uint_value;
366*288bf522SAndroid Build Coastguard Worker } else {
367*288bf522SAndroid Build Coastguard Worker if (value.uint_value >= INT_MAX) {
368*288bf522SAndroid Build Coastguard Worker LOG(ERROR) << "sample freq can't be bigger than INT_MAX: " << value.uint_value;
369*288bf522SAndroid Build Coastguard Worker return false;
370*288bf522SAndroid Build Coastguard Worker }
371*288bf522SAndroid Build Coastguard Worker rate.sample_freq = value.uint_value;
372*288bf522SAndroid Build Coastguard Worker }
373*288bf522SAndroid Build Coastguard Worker event_selection_set_.SetSampleRateForNewEvents(rate);
374*288bf522SAndroid Build Coastguard Worker
375*288bf522SAndroid Build Coastguard Worker } else if (name == "--call-graph") {
376*288bf522SAndroid Build Coastguard Worker std::vector<std::string> strs = android::base::Split(value.str_value, ",");
377*288bf522SAndroid Build Coastguard Worker if (strs[0] == "fp") {
378*288bf522SAndroid Build Coastguard Worker fp_callchain_sampling_ = true;
379*288bf522SAndroid Build Coastguard Worker dwarf_callchain_sampling_ = false;
380*288bf522SAndroid Build Coastguard Worker } else if (strs[0] == "dwarf") {
381*288bf522SAndroid Build Coastguard Worker fp_callchain_sampling_ = false;
382*288bf522SAndroid Build Coastguard Worker dwarf_callchain_sampling_ = true;
383*288bf522SAndroid Build Coastguard Worker if (strs.size() > 1) {
384*288bf522SAndroid Build Coastguard Worker uint64_t size;
385*288bf522SAndroid Build Coastguard Worker if (!ParseUint(strs[1], &size)) {
386*288bf522SAndroid Build Coastguard Worker LOG(ERROR) << "invalid dump stack size in --call-graph option: " << strs[1];
387*288bf522SAndroid Build Coastguard Worker return false;
388*288bf522SAndroid Build Coastguard Worker }
389*288bf522SAndroid Build Coastguard Worker if ((size & 7) != 0) {
390*288bf522SAndroid Build Coastguard Worker LOG(ERROR) << "dump stack size " << size << " is not 8-byte aligned.";
391*288bf522SAndroid Build Coastguard Worker return false;
392*288bf522SAndroid Build Coastguard Worker }
393*288bf522SAndroid Build Coastguard Worker if (size >= MAX_DUMP_STACK_SIZE) {
394*288bf522SAndroid Build Coastguard Worker LOG(ERROR) << "dump stack size " << size << " is bigger than max allowed size "
395*288bf522SAndroid Build Coastguard Worker << MAX_DUMP_STACK_SIZE << ".";
396*288bf522SAndroid Build Coastguard Worker return false;
397*288bf522SAndroid Build Coastguard Worker }
398*288bf522SAndroid Build Coastguard Worker dump_stack_size_in_dwarf_sampling_ = static_cast<uint32_t>(size);
399*288bf522SAndroid Build Coastguard Worker }
400*288bf522SAndroid Build Coastguard Worker }
401*288bf522SAndroid Build Coastguard Worker
402*288bf522SAndroid Build Coastguard Worker } else if (name == "-e") {
403*288bf522SAndroid Build Coastguard Worker std::vector<std::string> event_types = android::base::Split(value.str_value, ",");
404*288bf522SAndroid Build Coastguard Worker for (auto& event_type : event_types) {
405*288bf522SAndroid Build Coastguard Worker if (!event_selection_set_.AddEventType(event_type)) {
406*288bf522SAndroid Build Coastguard Worker return false;
407*288bf522SAndroid Build Coastguard Worker }
408*288bf522SAndroid Build Coastguard Worker }
409*288bf522SAndroid Build Coastguard Worker
410*288bf522SAndroid Build Coastguard Worker } else if (name == "-g") {
411*288bf522SAndroid Build Coastguard Worker fp_callchain_sampling_ = false;
412*288bf522SAndroid Build Coastguard Worker dwarf_callchain_sampling_ = true;
413*288bf522SAndroid Build Coastguard Worker } else {
414*288bf522SAndroid Build Coastguard Worker CHECK(false) << "unprocessed option: " << name;
415*288bf522SAndroid Build Coastguard Worker }
416*288bf522SAndroid Build Coastguard Worker }
417*288bf522SAndroid Build Coastguard Worker
418*288bf522SAndroid Build Coastguard Worker if (event_selection_set_.empty()) {
419*288bf522SAndroid Build Coastguard Worker LOG(ERROR) << "No event to record. Use `-e` to specify which event should be monitored.";
420*288bf522SAndroid Build Coastguard Worker return false;
421*288bf522SAndroid Build Coastguard Worker }
422*288bf522SAndroid Build Coastguard Worker
423*288bf522SAndroid Build Coastguard Worker if (fp_callchain_sampling_) {
424*288bf522SAndroid Build Coastguard Worker if (GetTargetArch() == ARCH_ARM) {
425*288bf522SAndroid Build Coastguard Worker LOG(WARNING) << "`--callgraph fp` option doesn't work well on arm architecture, "
426*288bf522SAndroid Build Coastguard Worker << "consider using `-g` option or profiling on aarch64 architecture.";
427*288bf522SAndroid Build Coastguard Worker }
428*288bf522SAndroid Build Coastguard Worker }
429*288bf522SAndroid Build Coastguard Worker
430*288bf522SAndroid Build Coastguard Worker if (system_wide_collection_ && event_selection_set_.HasMonitoredTarget()) {
431*288bf522SAndroid Build Coastguard Worker LOG(ERROR) << "Record system wide and existing processes/threads can't be "
432*288bf522SAndroid Build Coastguard Worker "used at the same time.";
433*288bf522SAndroid Build Coastguard Worker return false;
434*288bf522SAndroid Build Coastguard Worker }
435*288bf522SAndroid Build Coastguard Worker
436*288bf522SAndroid Build Coastguard Worker if (system_wide_collection_ && !IsRoot()) {
437*288bf522SAndroid Build Coastguard Worker LOG(ERROR) << "System wide profiling needs root privilege.";
438*288bf522SAndroid Build Coastguard Worker return false;
439*288bf522SAndroid Build Coastguard Worker }
440*288bf522SAndroid Build Coastguard Worker return true;
441*288bf522SAndroid Build Coastguard Worker }
442*288bf522SAndroid Build Coastguard Worker
AdjustPerfEventLimit()443*288bf522SAndroid Build Coastguard Worker bool MonitorCommand::AdjustPerfEventLimit() {
444*288bf522SAndroid Build Coastguard Worker bool set_prop = false;
445*288bf522SAndroid Build Coastguard Worker // 1. Adjust max_sample_rate.
446*288bf522SAndroid Build Coastguard Worker uint64_t cur_max_freq;
447*288bf522SAndroid Build Coastguard Worker if (GetMaxSampleFrequency(&cur_max_freq) && cur_max_freq < max_sample_freq_ &&
448*288bf522SAndroid Build Coastguard Worker !SetMaxSampleFrequency(max_sample_freq_)) {
449*288bf522SAndroid Build Coastguard Worker set_prop = true;
450*288bf522SAndroid Build Coastguard Worker }
451*288bf522SAndroid Build Coastguard Worker // 2. Adjust perf_cpu_time_max_percent.
452*288bf522SAndroid Build Coastguard Worker size_t cur_percent;
453*288bf522SAndroid Build Coastguard Worker if (GetCpuTimeMaxPercent(&cur_percent) && cur_percent != cpu_time_max_percent_ &&
454*288bf522SAndroid Build Coastguard Worker !SetCpuTimeMaxPercent(cpu_time_max_percent_)) {
455*288bf522SAndroid Build Coastguard Worker set_prop = true;
456*288bf522SAndroid Build Coastguard Worker }
457*288bf522SAndroid Build Coastguard Worker // 3. Adjust perf_event_mlock_kb.
458*288bf522SAndroid Build Coastguard Worker long cpus = sysconf(_SC_NPROCESSORS_CONF);
459*288bf522SAndroid Build Coastguard Worker uint64_t mlock_kb = cpus * (mmap_page_range_.second + 1) * 4;
460*288bf522SAndroid Build Coastguard Worker
461*288bf522SAndroid Build Coastguard Worker uint64_t cur_mlock_kb;
462*288bf522SAndroid Build Coastguard Worker if (GetPerfEventMlockKb(&cur_mlock_kb) && cur_mlock_kb < mlock_kb &&
463*288bf522SAndroid Build Coastguard Worker !SetPerfEventMlockKb(mlock_kb)) {
464*288bf522SAndroid Build Coastguard Worker set_prop = true;
465*288bf522SAndroid Build Coastguard Worker }
466*288bf522SAndroid Build Coastguard Worker
467*288bf522SAndroid Build Coastguard Worker if (GetAndroidVersion() >= kAndroidVersionQ && set_prop) {
468*288bf522SAndroid Build Coastguard Worker return SetPerfEventLimits(std::max(max_sample_freq_, cur_max_freq), cpu_time_max_percent_,
469*288bf522SAndroid Build Coastguard Worker std::max(mlock_kb, cur_mlock_kb));
470*288bf522SAndroid Build Coastguard Worker }
471*288bf522SAndroid Build Coastguard Worker return true;
472*288bf522SAndroid Build Coastguard Worker }
473*288bf522SAndroid Build Coastguard Worker
SetEventSelectionFlags()474*288bf522SAndroid Build Coastguard Worker bool MonitorCommand::SetEventSelectionFlags() {
475*288bf522SAndroid Build Coastguard Worker event_selection_set_.SampleIdAll();
476*288bf522SAndroid Build Coastguard Worker event_selection_set_.WakeupPerSample();
477*288bf522SAndroid Build Coastguard Worker if (fp_callchain_sampling_) {
478*288bf522SAndroid Build Coastguard Worker event_selection_set_.EnableFpCallChainSampling();
479*288bf522SAndroid Build Coastguard Worker } else if (dwarf_callchain_sampling_) {
480*288bf522SAndroid Build Coastguard Worker if (!event_selection_set_.EnableDwarfCallChainSampling(dump_stack_size_in_dwarf_sampling_)) {
481*288bf522SAndroid Build Coastguard Worker return false;
482*288bf522SAndroid Build Coastguard Worker }
483*288bf522SAndroid Build Coastguard Worker }
484*288bf522SAndroid Build Coastguard Worker return true;
485*288bf522SAndroid Build Coastguard Worker }
486*288bf522SAndroid Build Coastguard Worker
ProcessRecord(Record * record)487*288bf522SAndroid Build Coastguard Worker bool MonitorCommand::ProcessRecord(Record* record) {
488*288bf522SAndroid Build Coastguard Worker UpdateRecord(record);
489*288bf522SAndroid Build Coastguard Worker last_record_timestamp_ = std::max(last_record_timestamp_, record->Timestamp());
490*288bf522SAndroid Build Coastguard Worker // In system wide recording, maps are dumped when they are needed by records.
491*288bf522SAndroid Build Coastguard Worker if (system_wide_collection_ && !DumpMapsForRecord(record)) {
492*288bf522SAndroid Build Coastguard Worker return false;
493*288bf522SAndroid Build Coastguard Worker }
494*288bf522SAndroid Build Coastguard Worker if (record->type() == PERF_RECORD_SAMPLE) {
495*288bf522SAndroid Build Coastguard Worker auto& r = *static_cast<SampleRecord*>(record);
496*288bf522SAndroid Build Coastguard Worker
497*288bf522SAndroid Build Coastguard Worker // Record filter check should go after DumpMapsForRecord(). Otherwise, process/thread name
498*288bf522SAndroid Build Coastguard Worker // filters don't work in system wide collection.
499*288bf522SAndroid Build Coastguard Worker if (!record_filter_.Check(r)) {
500*288bf522SAndroid Build Coastguard Worker return true;
501*288bf522SAndroid Build Coastguard Worker }
502*288bf522SAndroid Build Coastguard Worker
503*288bf522SAndroid Build Coastguard Worker // AdjustCallChainGeneratedByKernel() should go before UnwindRecord().
504*288bf522SAndroid Build Coastguard Worker // Because we don't want to adjust callchains generated by dwarf unwinder.
505*288bf522SAndroid Build Coastguard Worker if (fp_callchain_sampling_ || dwarf_callchain_sampling_) {
506*288bf522SAndroid Build Coastguard Worker r.AdjustCallChainGeneratedByKernel();
507*288bf522SAndroid Build Coastguard Worker if (!UnwindRecord(r)) {
508*288bf522SAndroid Build Coastguard Worker return false;
509*288bf522SAndroid Build Coastguard Worker }
510*288bf522SAndroid Build Coastguard Worker }
511*288bf522SAndroid Build Coastguard Worker DumpSampleRecord(r);
512*288bf522SAndroid Build Coastguard Worker if (fp_callchain_sampling_ || dwarf_callchain_sampling_) {
513*288bf522SAndroid Build Coastguard Worker DumpSampleCallchain(r);
514*288bf522SAndroid Build Coastguard Worker }
515*288bf522SAndroid Build Coastguard Worker sample_record_count_++;
516*288bf522SAndroid Build Coastguard Worker } else {
517*288bf522SAndroid Build Coastguard Worker // Other types of record are forwarded to the thread tree to build the
518*288bf522SAndroid Build Coastguard Worker // representation of each processes (mmap, comm, etc).
519*288bf522SAndroid Build Coastguard Worker thread_tree_.Update(*record);
520*288bf522SAndroid Build Coastguard Worker }
521*288bf522SAndroid Build Coastguard Worker return true;
522*288bf522SAndroid Build Coastguard Worker }
523*288bf522SAndroid Build Coastguard Worker
DumpSampleRecord(const SampleRecord & sr)524*288bf522SAndroid Build Coastguard Worker void MonitorCommand::DumpSampleRecord(const SampleRecord& sr) {
525*288bf522SAndroid Build Coastguard Worker std::string output("sample");
526*288bf522SAndroid Build Coastguard Worker StringAppendF(&output, " name=%s", event_names_[sr.id_data.id].c_str());
527*288bf522SAndroid Build Coastguard Worker StringAppendF(&output, " ip=%p", reinterpret_cast<void*>(sr.ip_data.ip));
528*288bf522SAndroid Build Coastguard Worker SymbolInfo s = GetSymbolInfo(sr.tid_data.pid, sr.tid_data.tid, sr.ip_data.ip, sr.InKernel());
529*288bf522SAndroid Build Coastguard Worker StringAppendF(&output, " symbol=%s (%s[+%" PRIx64 "])", s.symbol->DemangledName(),
530*288bf522SAndroid Build Coastguard Worker s.dso->Path().c_str(), s.vaddr_in_file);
531*288bf522SAndroid Build Coastguard Worker StringAppendF(&output, " pid=%u tid=%u", sr.tid_data.pid, sr.tid_data.tid);
532*288bf522SAndroid Build Coastguard Worker StringAppendF(&output, " cpu=%u", sr.cpu_data.cpu);
533*288bf522SAndroid Build Coastguard Worker printf("%s\n", output.c_str());
534*288bf522SAndroid Build Coastguard Worker fflush(stdout);
535*288bf522SAndroid Build Coastguard Worker }
536*288bf522SAndroid Build Coastguard Worker
DumpSampleCallchain(const SampleRecord & sr)537*288bf522SAndroid Build Coastguard Worker void MonitorCommand::DumpSampleCallchain(const SampleRecord& sr) {
538*288bf522SAndroid Build Coastguard Worker bool in_kernel = sr.InKernel();
539*288bf522SAndroid Build Coastguard Worker if (sr.sample_type & PERF_SAMPLE_CALLCHAIN) {
540*288bf522SAndroid Build Coastguard Worker for (size_t i = 0; i < sr.callchain_data.ip_nr; ++i) {
541*288bf522SAndroid Build Coastguard Worker if (sr.callchain_data.ips[i] >= PERF_CONTEXT_MAX) {
542*288bf522SAndroid Build Coastguard Worker if (sr.callchain_data.ips[i] == PERF_CONTEXT_USER) {
543*288bf522SAndroid Build Coastguard Worker in_kernel = false;
544*288bf522SAndroid Build Coastguard Worker }
545*288bf522SAndroid Build Coastguard Worker continue;
546*288bf522SAndroid Build Coastguard Worker }
547*288bf522SAndroid Build Coastguard Worker SymbolInfo s =
548*288bf522SAndroid Build Coastguard Worker GetSymbolInfo(sr.tid_data.pid, sr.tid_data.tid, sr.callchain_data.ips[i], in_kernel);
549*288bf522SAndroid Build Coastguard Worker std::string output("sample callchain");
550*288bf522SAndroid Build Coastguard Worker StringAppendF(&output, " %s (%s[+%" PRIx64 "])", s.symbol->DemangledName(),
551*288bf522SAndroid Build Coastguard Worker s.dso->Path().c_str(), s.vaddr_in_file);
552*288bf522SAndroid Build Coastguard Worker printf("%s\n", output.c_str());
553*288bf522SAndroid Build Coastguard Worker }
554*288bf522SAndroid Build Coastguard Worker fflush(stdout);
555*288bf522SAndroid Build Coastguard Worker }
556*288bf522SAndroid Build Coastguard Worker }
557*288bf522SAndroid Build Coastguard Worker
GetSymbolInfo(uint32_t pid,uint32_t tid,uint64_t ip,bool in_kernel)558*288bf522SAndroid Build Coastguard Worker SymbolInfo MonitorCommand::GetSymbolInfo(uint32_t pid, uint32_t tid, uint64_t ip, bool in_kernel) {
559*288bf522SAndroid Build Coastguard Worker ThreadEntry* thread = thread_tree_.FindThreadOrNew(pid, tid);
560*288bf522SAndroid Build Coastguard Worker const MapEntry* map = thread_tree_.FindMap(thread, ip, in_kernel);
561*288bf522SAndroid Build Coastguard Worker SymbolInfo info;
562*288bf522SAndroid Build Coastguard Worker info.symbol = thread_tree_.FindSymbol(map, ip, &info.vaddr_in_file, &info.dso);
563*288bf522SAndroid Build Coastguard Worker return info;
564*288bf522SAndroid Build Coastguard Worker }
565*288bf522SAndroid Build Coastguard Worker
DumpMapsForRecord(Record * record)566*288bf522SAndroid Build Coastguard Worker bool MonitorCommand::DumpMapsForRecord(Record* record) {
567*288bf522SAndroid Build Coastguard Worker if (record->type() == PERF_RECORD_SAMPLE) {
568*288bf522SAndroid Build Coastguard Worker pid_t pid = static_cast<SampleRecord*>(record)->tid_data.pid;
569*288bf522SAndroid Build Coastguard Worker if (dumped_processes_.find(pid) == dumped_processes_.end()) {
570*288bf522SAndroid Build Coastguard Worker // Dump map info and all thread names for that process.
571*288bf522SAndroid Build Coastguard Worker if (!map_record_reader_->ReadProcessMaps(pid, last_record_timestamp_)) {
572*288bf522SAndroid Build Coastguard Worker return false;
573*288bf522SAndroid Build Coastguard Worker }
574*288bf522SAndroid Build Coastguard Worker dumped_processes_.insert(pid);
575*288bf522SAndroid Build Coastguard Worker }
576*288bf522SAndroid Build Coastguard Worker }
577*288bf522SAndroid Build Coastguard Worker return true;
578*288bf522SAndroid Build Coastguard Worker }
579*288bf522SAndroid Build Coastguard Worker
UpdateRecord(Record * record)580*288bf522SAndroid Build Coastguard Worker void MonitorCommand::UpdateRecord(Record* record) {
581*288bf522SAndroid Build Coastguard Worker if (record->type() == PERF_RECORD_COMM) {
582*288bf522SAndroid Build Coastguard Worker auto r = static_cast<CommRecord*>(record);
583*288bf522SAndroid Build Coastguard Worker if (r->data->pid == r->data->tid) {
584*288bf522SAndroid Build Coastguard Worker std::string s = GetCompleteProcessName(r->data->pid);
585*288bf522SAndroid Build Coastguard Worker if (!s.empty()) {
586*288bf522SAndroid Build Coastguard Worker r->SetCommandName(s);
587*288bf522SAndroid Build Coastguard Worker }
588*288bf522SAndroid Build Coastguard Worker }
589*288bf522SAndroid Build Coastguard Worker }
590*288bf522SAndroid Build Coastguard Worker }
591*288bf522SAndroid Build Coastguard Worker
UnwindRecord(SampleRecord & r)592*288bf522SAndroid Build Coastguard Worker bool MonitorCommand::UnwindRecord(SampleRecord& r) {
593*288bf522SAndroid Build Coastguard Worker if ((r.sample_type & PERF_SAMPLE_CALLCHAIN) && (r.sample_type & PERF_SAMPLE_REGS_USER) &&
594*288bf522SAndroid Build Coastguard Worker (r.regs_user_data.reg_mask != 0) && (r.sample_type & PERF_SAMPLE_STACK_USER) &&
595*288bf522SAndroid Build Coastguard Worker (r.GetValidStackSize() > 0)) {
596*288bf522SAndroid Build Coastguard Worker ThreadEntry* thread = thread_tree_.FindThreadOrNew(r.tid_data.pid, r.tid_data.tid);
597*288bf522SAndroid Build Coastguard Worker RegSet regs(r.regs_user_data.abi, r.regs_user_data.reg_mask, r.regs_user_data.regs);
598*288bf522SAndroid Build Coastguard Worker std::vector<uint64_t> ips;
599*288bf522SAndroid Build Coastguard Worker std::vector<uint64_t> sps;
600*288bf522SAndroid Build Coastguard Worker if (!offline_unwinder_->UnwindCallChain(*thread, regs, r.stack_user_data.data,
601*288bf522SAndroid Build Coastguard Worker r.GetValidStackSize(), &ips, &sps)) {
602*288bf522SAndroid Build Coastguard Worker return false;
603*288bf522SAndroid Build Coastguard Worker }
604*288bf522SAndroid Build Coastguard Worker r.ReplaceRegAndStackWithCallChain(ips);
605*288bf522SAndroid Build Coastguard Worker }
606*288bf522SAndroid Build Coastguard Worker return true;
607*288bf522SAndroid Build Coastguard Worker }
608*288bf522SAndroid Build Coastguard Worker } // namespace
609*288bf522SAndroid Build Coastguard Worker
RegisterMonitorCommand()610*288bf522SAndroid Build Coastguard Worker void RegisterMonitorCommand() {
611*288bf522SAndroid Build Coastguard Worker RegisterCommand("monitor", [] { return std::unique_ptr<Command>(new MonitorCommand()); });
612*288bf522SAndroid Build Coastguard Worker }
613*288bf522SAndroid Build Coastguard Worker
614*288bf522SAndroid Build Coastguard Worker } // namespace simpleperf
615