xref: /aosp_15_r20/system/extras/simpleperf/cmd_monitor.cpp (revision 288bf5226967eb3dac5cce6c939ccc2a7f2b4fe5)
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