19759e1b1ce76185aa539aeea2fb1cbd8382156e7Yabin Cui/*
29759e1b1ce76185aa539aeea2fb1cbd8382156e7Yabin Cui * Copyright (C) 2015 The Android Open Source Project
39759e1b1ce76185aa539aeea2fb1cbd8382156e7Yabin Cui *
49759e1b1ce76185aa539aeea2fb1cbd8382156e7Yabin Cui * Licensed under the Apache License, Version 2.0 (the "License");
59759e1b1ce76185aa539aeea2fb1cbd8382156e7Yabin Cui * you may not use this file except in compliance with the License.
69759e1b1ce76185aa539aeea2fb1cbd8382156e7Yabin Cui * You may obtain a copy of the License at
79759e1b1ce76185aa539aeea2fb1cbd8382156e7Yabin Cui *
89759e1b1ce76185aa539aeea2fb1cbd8382156e7Yabin Cui *      http://www.apache.org/licenses/LICENSE-2.0
99759e1b1ce76185aa539aeea2fb1cbd8382156e7Yabin Cui *
109759e1b1ce76185aa539aeea2fb1cbd8382156e7Yabin Cui * Unless required by applicable law or agreed to in writing, software
119759e1b1ce76185aa539aeea2fb1cbd8382156e7Yabin Cui * distributed under the License is distributed on an "AS IS" BASIS,
129759e1b1ce76185aa539aeea2fb1cbd8382156e7Yabin Cui * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
139759e1b1ce76185aa539aeea2fb1cbd8382156e7Yabin Cui * See the License for the specific language governing permissions and
149759e1b1ce76185aa539aeea2fb1cbd8382156e7Yabin Cui * limitations under the License.
159759e1b1ce76185aa539aeea2fb1cbd8382156e7Yabin Cui */
169759e1b1ce76185aa539aeea2fb1cbd8382156e7Yabin Cui
178f6225147c5b6cb2159a7f5cb0dab952ee0759dfYabin Cui#include <libgen.h>
189759e1b1ce76185aa539aeea2fb1cbd8382156e7Yabin Cui#include <signal.h>
19987d9abbea8863d51dac461d366471b4a2e7b8acYabin Cui#include <sys/prctl.h>
2076769e502d8f0ebf5d2c81b00246727fb0a59925Yabin Cui#include <sys/utsname.h>
2176769e502d8f0ebf5d2c81b00246727fb0a59925Yabin Cui#include <unistd.h>
22b032de7a9e1975a838cd6df2e7c8df3c7f70a3ceYabin Cui#include <set>
239759e1b1ce76185aa539aeea2fb1cbd8382156e7Yabin Cui#include <string>
24ddddc06d1f1d15d49e1eb43201b73beb29cf4cdeYabin Cui#include <unordered_map>
259759e1b1ce76185aa539aeea2fb1cbd8382156e7Yabin Cui#include <vector>
269759e1b1ce76185aa539aeea2fb1cbd8382156e7Yabin Cui
2766dd09e8e2407082ce93bf0784de641298131912Elliott Hughes#include <android-base/logging.h>
28b42129797f17f990ea5a88c6bdc7446000cc361cYabin Cui#include <android-base/file.h>
29c0565bb21e2997d7a01dda40ea2b16e067e7e28cYabin Cui#include <android-base/parsedouble.h>
30b891549ed16a91b6db52e8500bb6816fc9293bacYabin Cui#include <android-base/parseint.h>
3166dd09e8e2407082ce93bf0784de641298131912Elliott Hughes#include <android-base/strings.h>
3263a1c3d83a68e9d94f37b71afe76d0769d744448Yabin Cui#include <android-base/test_utils.h>
339759e1b1ce76185aa539aeea2fb1cbd8382156e7Yabin Cui
349759e1b1ce76185aa539aeea2fb1cbd8382156e7Yabin Cui#include "command.h"
35cb84c9885e7a9f82cefba566d74e5c71214ab4c9Yabin Cui#include "dwarf_unwind.h"
369759e1b1ce76185aa539aeea2fb1cbd8382156e7Yabin Cui#include "environment.h"
379759e1b1ce76185aa539aeea2fb1cbd8382156e7Yabin Cui#include "event_selection_set.h"
389759e1b1ce76185aa539aeea2fb1cbd8382156e7Yabin Cui#include "event_type.h"
39dbbda3020c483a8da2e9ce985c1e9d8b7bcc8ec0Yabin Cui#include "IOEventLoop.h"
40aa65c8b250b99f1684f46e2c40b77e42bf7c5f31Yabin Cui#include "perf_clock.h"
41f831e6d12ca2298cb34b155a9d91ef002d0482f3Than McIntosh#include "read_apk.h"
428f6225147c5b6cb2159a7f5cb0dab952ee0759dfYabin Cui#include "read_elf.h"
437d59bb49fb47fbc82ef5c77d7aebf7174fd996e1Yabin Cui#include "record.h"
449759e1b1ce76185aa539aeea2fb1cbd8382156e7Yabin Cui#include "record_file.h"
4573d8078e6e5ef92b2301386ce96260bd99efacbbYabin Cui#include "thread_tree.h"
464f41df6f68efc3b9b534014a8cfb6ee8ac4d5c91Yabin Cui#include "tracing.h"
47621a533ec28dbbf8634211c684456b4bbc1bc0fbYabin Cui#include "utils.h"
489759e1b1ce76185aa539aeea2fb1cbd8382156e7Yabin Cui#include "workload.h"
499759e1b1ce76185aa539aeea2fb1cbd8382156e7Yabin Cui
509759e1b1ce76185aa539aeea2fb1cbd8382156e7Yabin Cuistatic std::string default_measured_event_type = "cpu-cycles";
519759e1b1ce76185aa539aeea2fb1cbd8382156e7Yabin Cui
52ddddc06d1f1d15d49e1eb43201b73beb29cf4cdeYabin Cuistatic std::unordered_map<std::string, uint64_t> branch_sampling_type_map = {
53ddddc06d1f1d15d49e1eb43201b73beb29cf4cdeYabin Cui    {"u", PERF_SAMPLE_BRANCH_USER},
54ddddc06d1f1d15d49e1eb43201b73beb29cf4cdeYabin Cui    {"k", PERF_SAMPLE_BRANCH_KERNEL},
55ddddc06d1f1d15d49e1eb43201b73beb29cf4cdeYabin Cui    {"any", PERF_SAMPLE_BRANCH_ANY},
56ddddc06d1f1d15d49e1eb43201b73beb29cf4cdeYabin Cui    {"any_call", PERF_SAMPLE_BRANCH_ANY_CALL},
57ddddc06d1f1d15d49e1eb43201b73beb29cf4cdeYabin Cui    {"any_ret", PERF_SAMPLE_BRANCH_ANY_RETURN},
58ddddc06d1f1d15d49e1eb43201b73beb29cf4cdeYabin Cui    {"ind_call", PERF_SAMPLE_BRANCH_IND_CALL},
59ddddc06d1f1d15d49e1eb43201b73beb29cf4cdeYabin Cui};
60ddddc06d1f1d15d49e1eb43201b73beb29cf4cdeYabin Cui
61e9f06a6582d70b06a01e8e183081112b109776f6Yabin Cui// The max size of records dumped by kernel is 65535, and dump stack size
62e9f06a6582d70b06a01e8e183081112b109776f6Yabin Cui// should be a multiply of 8, so MAX_DUMP_STACK_SIZE is 65528.
63e9f06a6582d70b06a01e8e183081112b109776f6Yabin Cuiconstexpr uint32_t MAX_DUMP_STACK_SIZE = 65528;
64e9f06a6582d70b06a01e8e183081112b109776f6Yabin Cui
650a072cda021e5dfbdbb39f4d8d30771a851b3c3aYabin Cui// The max allowed pages in mapped buffer is decided by rlimit(RLIMIT_MEMLOCK).
660a072cda021e5dfbdbb39f4d8d30771a851b3c3aYabin Cui// Here 1024 is a desired value for pages in mapped buffer. If mapped
670a072cda021e5dfbdbb39f4d8d30771a851b3c3aYabin Cui// successfully, the buffer size = 1024 * 4K (page size) = 4M.
680a072cda021e5dfbdbb39f4d8d30771a851b3c3aYabin Cuiconstexpr size_t DESIRED_PAGES_IN_MAPPED_BUFFER = 1024;
690a072cda021e5dfbdbb39f4d8d30771a851b3c3aYabin Cui
70f79f07e13c56f7ca3be1435cea7f8861daf7efaaYabin Cuiclass RecordCommand : public Command {
719759e1b1ce76185aa539aeea2fb1cbd8382156e7Yabin Cui public:
72f79f07e13c56f7ca3be1435cea7f8861daf7efaaYabin Cui  RecordCommand()
73b032de7a9e1975a838cd6df2e7c8df3c7f70a3ceYabin Cui      : Command(
74b032de7a9e1975a838cd6df2e7c8df3c7f70a3ceYabin Cui            "record", "record sampling info in perf.data",
75b42129797f17f990ea5a88c6bdc7446000cc361cYabin Cui            // clang-format off
76b42129797f17f990ea5a88c6bdc7446000cc361cYabin Cui"Usage: simpleperf record [options] [command [command-args]]\n"
778a599d7c95f2a8207fb3fe90e824aab1f30abe62Yabin Cui"       Gather sampling information of running [command]. And -a/-p/-t option\n"
788a599d7c95f2a8207fb3fe90e824aab1f30abe62Yabin Cui"       can be used to change target of sampling information.\n"
79dcb2a3e580f155bb28621c4cbad019d104e8f300Yabin Cui"       The default options are: -e cpu-cycles -f 4000 -o perf.data.\n"
80b42129797f17f990ea5a88c6bdc7446000cc361cYabin Cui"-a     System-wide collection.\n"
81a80f8f707e9b6f9d4fb79714be1c887445c4511fYabin Cui#if defined(__ANDROID__)
82a80f8f707e9b6f9d4fb79714be1c887445c4511fYabin Cui"--app package_name    Profile the process of an Android application.\n"
83a80f8f707e9b6f9d4fb79714be1c887445c4511fYabin Cui"                      On non-rooted devices, the app must be debuggable,\n"
84a80f8f707e9b6f9d4fb79714be1c887445c4511fYabin Cui"                      because we use run-as to switch to the app's context.\n"
85a80f8f707e9b6f9d4fb79714be1c887445c4511fYabin Cui#endif
86b42129797f17f990ea5a88c6bdc7446000cc361cYabin Cui"-b     Enable take branch stack sampling. Same as '-j any'\n"
874f41df6f68efc3b9b534014a8cfb6ee8ac4d5c91Yabin Cui"-c count     Set event sample period. It means recording one sample when\n"
884f41df6f68efc3b9b534014a8cfb6ee8ac4d5c91Yabin Cui"             [count] events happen. Can't be used with -f/-F option.\n"
894f41df6f68efc3b9b534014a8cfb6ee8ac4d5c91Yabin Cui"             For tracepoint events, the default option is -c 1.\n"
90b42129797f17f990ea5a88c6bdc7446000cc361cYabin Cui"--call-graph fp | dwarf[,<dump_stack_size>]\n"
91b42129797f17f990ea5a88c6bdc7446000cc361cYabin Cui"             Enable call graph recording. Use frame pointer or dwarf debug\n"
92b42129797f17f990ea5a88c6bdc7446000cc361cYabin Cui"             frame as the method to parse call graph in stack.\n"
93e9f06a6582d70b06a01e8e183081112b109776f6Yabin Cui"             Default is dwarf,65528.\n"
94b42129797f17f990ea5a88c6bdc7446000cc361cYabin Cui"--cpu cpu_item1,cpu_item2,...\n"
95b42129797f17f990ea5a88c6bdc7446000cc361cYabin Cui"             Collect samples only on the selected cpus. cpu_item can be cpu\n"
96b42129797f17f990ea5a88c6bdc7446000cc361cYabin Cui"             number like 1, or cpu range like 0-3.\n"
978a599d7c95f2a8207fb3fe90e824aab1f30abe62Yabin Cui"--duration time_in_sec  Monitor for time_in_sec seconds instead of running\n"
988a599d7c95f2a8207fb3fe90e824aab1f30abe62Yabin Cui"                        [command]. Here time_in_sec may be any positive\n"
998a599d7c95f2a8207fb3fe90e824aab1f30abe62Yabin Cui"                        floating point number.\n"
100b42129797f17f990ea5a88c6bdc7446000cc361cYabin Cui"-e event1[:modifier1],event2[:modifier2],...\n"
101b42129797f17f990ea5a88c6bdc7446000cc361cYabin Cui"             Select the event list to sample. Use `simpleperf list` to find\n"
102b42129797f17f990ea5a88c6bdc7446000cc361cYabin Cui"             all possible event names. Modifiers can be added to define how\n"
103b42129797f17f990ea5a88c6bdc7446000cc361cYabin Cui"             the event should be monitored.\n"
104b42129797f17f990ea5a88c6bdc7446000cc361cYabin Cui"             Possible modifiers are:\n"
105b42129797f17f990ea5a88c6bdc7446000cc361cYabin Cui"                u - monitor user space events only\n"
106b42129797f17f990ea5a88c6bdc7446000cc361cYabin Cui"                k - monitor kernel space events only\n"
1074f41df6f68efc3b9b534014a8cfb6ee8ac4d5c91Yabin Cui"-f freq      Set event sample frequency. It means recording at most [freq]\n"
1084f41df6f68efc3b9b534014a8cfb6ee8ac4d5c91Yabin Cui"             samples every second. For non-tracepoint events, the default\n"
1094f41df6f68efc3b9b534014a8cfb6ee8ac4d5c91Yabin Cui"             option is -f 4000.\n"
110b42129797f17f990ea5a88c6bdc7446000cc361cYabin Cui"-F freq      Same as '-f freq'.\n"
111b42129797f17f990ea5a88c6bdc7446000cc361cYabin Cui"-g           Same as '--call-graph dwarf'.\n"
112877751bbae11e009070e036ee1cd16e88135fff5Yabin Cui"--group event1[:modifier],event2[:modifier2],...\n"
113877751bbae11e009070e036ee1cd16e88135fff5Yabin Cui"             Similar to -e option. But events specified in the same --group\n"
114877751bbae11e009070e036ee1cd16e88135fff5Yabin Cui"             option are monitored as a group, and scheduled in and out at the\n"
115877751bbae11e009070e036ee1cd16e88135fff5Yabin Cui"             same time.\n"
116b42129797f17f990ea5a88c6bdc7446000cc361cYabin Cui"-j branch_filter1,branch_filter2,...\n"
117b42129797f17f990ea5a88c6bdc7446000cc361cYabin Cui"             Enable taken branch stack sampling. Each sample captures a series\n"
118b42129797f17f990ea5a88c6bdc7446000cc361cYabin Cui"             of consecutive taken branches.\n"
119b42129797f17f990ea5a88c6bdc7446000cc361cYabin Cui"             The following filters are defined:\n"
120b42129797f17f990ea5a88c6bdc7446000cc361cYabin Cui"                any: any type of branch\n"
121b42129797f17f990ea5a88c6bdc7446000cc361cYabin Cui"                any_call: any function call or system call\n"
122b42129797f17f990ea5a88c6bdc7446000cc361cYabin Cui"                any_ret: any function return or system call return\n"
123b42129797f17f990ea5a88c6bdc7446000cc361cYabin Cui"                ind_call: any indirect branch\n"
124b42129797f17f990ea5a88c6bdc7446000cc361cYabin Cui"                u: only when the branch target is at the user level\n"
125b42129797f17f990ea5a88c6bdc7446000cc361cYabin Cui"                k: only when the branch target is in the kernel\n"
126b42129797f17f990ea5a88c6bdc7446000cc361cYabin Cui"             This option requires at least one branch type among any, any_call,\n"
127b42129797f17f990ea5a88c6bdc7446000cc361cYabin Cui"             any_ret, ind_call.\n"
128b42129797f17f990ea5a88c6bdc7446000cc361cYabin Cui"-m mmap_pages   Set the size of the buffer used to receiving sample data from\n"
1290a072cda021e5dfbdbb39f4d8d30771a851b3c3aYabin Cui"                the kernel. It should be a power of 2. If not set, the max\n"
1300a072cda021e5dfbdbb39f4d8d30771a851b3c3aYabin Cui"                possible value <= 1024 will be used.\n"
131b42129797f17f990ea5a88c6bdc7446000cc361cYabin Cui"--no-dump-kernel-symbols  Don't dump kernel symbols in perf.data. By default\n"
132b42129797f17f990ea5a88c6bdc7446000cc361cYabin Cui"                          kernel symbols will be dumped when needed.\n"
133dcb2a3e580f155bb28621c4cbad019d104e8f300Yabin Cui"--no-dump-symbols       Don't dump symbols in perf.data. By default symbols are\n"
134dcb2a3e580f155bb28621c4cbad019d104e8f300Yabin Cui"                        dumped in perf.data, to support reporting in another\n"
135dcb2a3e580f155bb28621c4cbad019d104e8f300Yabin Cui"                        environment.\n"
136b42129797f17f990ea5a88c6bdc7446000cc361cYabin Cui"--no-inherit  Don't record created child threads/processes.\n"
137b42129797f17f990ea5a88c6bdc7446000cc361cYabin Cui"--no-unwind   If `--call-graph dwarf` option is used, then the user's stack\n"
138b42129797f17f990ea5a88c6bdc7446000cc361cYabin Cui"              will be unwound by default. Use this option to disable the\n"
139b42129797f17f990ea5a88c6bdc7446000cc361cYabin Cui"              unwinding of the user's stack.\n"
140b42129797f17f990ea5a88c6bdc7446000cc361cYabin Cui"-o record_file_name    Set record file name, default is perf.data.\n"
141b42129797f17f990ea5a88c6bdc7446000cc361cYabin Cui"-p pid1,pid2,...       Record events on existing processes. Mutually exclusive\n"
142b42129797f17f990ea5a88c6bdc7446000cc361cYabin Cui"                       with -a.\n"
143b42129797f17f990ea5a88c6bdc7446000cc361cYabin Cui"--post-unwind  If `--call-graph dwarf` option is used, then the user's stack\n"
144b42129797f17f990ea5a88c6bdc7446000cc361cYabin Cui"               will be unwound while recording by default. But it may lose\n"
145b42129797f17f990ea5a88c6bdc7446000cc361cYabin Cui"               records as stacking unwinding can be time consuming. Use this\n"
146b42129797f17f990ea5a88c6bdc7446000cc361cYabin Cui"               option to unwind the user's stack after recording.\n"
147e1c33a9a73075d72e9056fc9a1d275ce2e60b1f2Yabin Cui"--start_profiling_fd fd_no    After starting profiling, write \"STARTED\" to\n"
148e1c33a9a73075d72e9056fc9a1d275ce2e60b1f2Yabin Cui"                              <fd_no>, then close <fd_no>.\n"
149faa512630a79455bde7b5b56929ea371c6f612bdYabin Cui"--symfs <dir>    Look for files with symbols relative to this directory.\n"
150faa512630a79455bde7b5b56929ea371c6f612bdYabin Cui"                 This option is used to provide files with symbol table and\n"
151dcb2a3e580f155bb28621c4cbad019d104e8f300Yabin Cui"                 debug information, which are used for unwinding and dumping symbols.\n"
152b42129797f17f990ea5a88c6bdc7446000cc361cYabin Cui"-t tid1,tid2,... Record events on existing threads. Mutually exclusive with -a.\n"
153a80f8f707e9b6f9d4fb79714be1c887445c4511fYabin Cui#if 0
154a80f8f707e9b6f9d4fb79714be1c887445c4511fYabin Cui// Below options are only used internally and shouldn't be visible to the public.
155a80f8f707e9b6f9d4fb79714be1c887445c4511fYabin Cui"--in-app         We are already running in the app's context.\n"
156f897452e2305dc19e9f6689029da74cdf07045f5Yabin Cui"--tracepoint-events file_name   Read tracepoint events from [file_name] instead of tracefs.\n"
157a80f8f707e9b6f9d4fb79714be1c887445c4511fYabin Cui#endif
158b42129797f17f990ea5a88c6bdc7446000cc361cYabin Cui            // clang-format on
159b42129797f17f990ea5a88c6bdc7446000cc361cYabin Cui            ),
1604f41df6f68efc3b9b534014a8cfb6ee8ac4d5c91Yabin Cui        use_sample_freq_(false),
1614f41df6f68efc3b9b534014a8cfb6ee8ac4d5c91Yabin Cui        sample_freq_(0),
1624f41df6f68efc3b9b534014a8cfb6ee8ac4d5c91Yabin Cui        use_sample_period_(false),
1634f41df6f68efc3b9b534014a8cfb6ee8ac4d5c91Yabin Cui        sample_period_(0),
1649759e1b1ce76185aa539aeea2fb1cbd8382156e7Yabin Cui        system_wide_collection_(false),
165ddddc06d1f1d15d49e1eb43201b73beb29cf4cdeYabin Cui        branch_sampling_(0),
16676769e502d8f0ebf5d2c81b00246727fb0a59925Yabin Cui        fp_callchain_sampling_(false),
16776769e502d8f0ebf5d2c81b00246727fb0a59925Yabin Cui        dwarf_callchain_sampling_(false),
168e9f06a6582d70b06a01e8e183081112b109776f6Yabin Cui        dump_stack_size_in_dwarf_sampling_(MAX_DUMP_STACK_SIZE),
169cb84c9885e7a9f82cefba566d74e5c71214ab4c9Yabin Cui        unwind_dwarf_callchain_(true),
170f469c3d7f4466a2a31c3e837969c43c1e3bc4c90Yabin Cui        post_unwind_(false),
1714be412615fa6b6a7bf0afd5f620b249e98b2cab8Yabin Cui        child_inherit_(true),
172dbbda3020c483a8da2e9ce985c1e9d8b7bcc8ec0Yabin Cui        duration_in_sec_(0),
173b42129797f17f990ea5a88c6bdc7446000cc361cYabin Cui        can_dump_kernel_symbols_(true),
174dcb2a3e580f155bb28621c4cbad019d104e8f300Yabin Cui        dump_symbols_(true),
1754cf37d1583a605785b7677c1935ce316c2097fa2Yabin Cui        event_selection_set_(false),
1760a072cda021e5dfbdbb39f4d8d30771a851b3c3aYabin Cui        mmap_page_range_(std::make_pair(1, DESIRED_PAGES_IN_MAPPED_BUFFER)),
177b1a885b014540a2f7798b5a35ea0f0ec150d93eeYabin Cui        record_filename_("perf.data"),
17857fb220017ae91f028ff2fbc819c07849c7c4f58Yabin Cui        start_sampling_time_in_ns_(0),
179e5adc13cda8dd413f86d0dc8d187052efcaff7e5Yabin Cui        sample_record_count_(0),
180e1c33a9a73075d72e9056fc9a1d275ce2e60b1f2Yabin Cui        lost_record_count_(0),
181a80f8f707e9b6f9d4fb79714be1c887445c4511fYabin Cui        start_profiling_fd_(-1),
182a80f8f707e9b6f9d4fb79714be1c887445c4511fYabin Cui        in_app_context_(false) {
1835f43fc4ac870b49542b4cf530a3729f9f1e0e9abYabin Cui    // Stop profiling if parent exits.
184987d9abbea8863d51dac461d366471b4a2e7b8acYabin Cui    prctl(PR_SET_PDEATHSIG, SIGHUP, 0, 0, 0);
185616b3a020bf708f364e0608107ded083930ac6b4Yabin Cui    app_package_name_ = GetDefaultAppPackageName();
1869759e1b1ce76185aa539aeea2fb1cbd8382156e7Yabin Cui  }
1879759e1b1ce76185aa539aeea2fb1cbd8382156e7Yabin Cui
1889759e1b1ce76185aa539aeea2fb1cbd8382156e7Yabin Cui  bool Run(const std::vector<std::string>& args);
1899759e1b1ce76185aa539aeea2fb1cbd8382156e7Yabin Cui
1909759e1b1ce76185aa539aeea2fb1cbd8382156e7Yabin Cui private:
191b42129797f17f990ea5a88c6bdc7446000cc361cYabin Cui  bool ParseOptions(const std::vector<std::string>& args,
192b42129797f17f990ea5a88c6bdc7446000cc361cYabin Cui                    std::vector<std::string>* non_option_args);
193877751bbae11e009070e036ee1cd16e88135fff5Yabin Cui  bool SetEventSelectionFlags();
194b7f481f59126456b0e708a76f40fa88224f3531bYabin Cui  bool CreateAndInitRecordFile();
195b42129797f17f990ea5a88c6bdc7446000cc361cYabin Cui  std::unique_ptr<RecordFileWriter> CreateRecordFile(
196b42129797f17f990ea5a88c6bdc7446000cc361cYabin Cui      const std::string& filename);
197b42129797f17f990ea5a88c6bdc7446000cc361cYabin Cui  bool DumpKernelSymbol();
1984f41df6f68efc3b9b534014a8cfb6ee8ac4d5c91Yabin Cui  bool DumpTracingData();
199877751bbae11e009070e036ee1cd16e88135fff5Yabin Cui  bool DumpKernelAndModuleMmaps(const perf_event_attr& attr, uint64_t event_id);
200bc2a1022e1ea0a8c17691594d39fa53021de9166Yabin Cui  bool DumpThreadCommAndMmaps(const perf_event_attr& attr, uint64_t event_id);
201f469c3d7f4466a2a31c3e837969c43c1e3bc4c90Yabin Cui  bool ProcessRecord(Record* record);
202b1a885b014540a2f7798b5a35ea0f0ec150d93eeYabin Cui  void UpdateRecordForEmbeddedElfPath(Record* record);
203767dd17947f1ae9dd3d02f738d442a23ed76f2f6Yabin Cui  bool UnwindRecord(Record* record);
204b7f481f59126456b0e708a76f40fa88224f3531bYabin Cui  bool PostUnwind(const std::vector<std::string>& args);
205d713f959ec1fe07ed993e2c9f4166b52aa98a58cYabin Cui  bool DumpAdditionalFeatures(const std::vector<std::string>& args);
2068f6225147c5b6cb2159a7f5cb0dab952ee0759dfYabin Cui  bool DumpBuildIdFeature();
207c5b4a3106a0845d1bd8fd2c1b1c724eeb719ec62Yabin Cui  bool DumpFileFeature();
2080f6df013be40459a1b4013bdad8ec0a82c18ce9aYabin Cui  void CollectHitFileInfo(const SampleRecord& r);
209f831e6d12ca2298cb34b155a9d91ef002d0482f3Than McIntosh
210b42129797f17f990ea5a88c6bdc7446000cc361cYabin Cui  bool use_sample_freq_;
2114f41df6f68efc3b9b534014a8cfb6ee8ac4d5c91Yabin Cui  uint64_t sample_freq_;  // Sample 'sample_freq_' times per second.
2124f41df6f68efc3b9b534014a8cfb6ee8ac4d5c91Yabin Cui  bool use_sample_period_;
2139759e1b1ce76185aa539aeea2fb1cbd8382156e7Yabin Cui  uint64_t sample_period_;  // Sample once when 'sample_period_' events occur.
2149759e1b1ce76185aa539aeea2fb1cbd8382156e7Yabin Cui
2159759e1b1ce76185aa539aeea2fb1cbd8382156e7Yabin Cui  bool system_wide_collection_;
216ddddc06d1f1d15d49e1eb43201b73beb29cf4cdeYabin Cui  uint64_t branch_sampling_;
21776769e502d8f0ebf5d2c81b00246727fb0a59925Yabin Cui  bool fp_callchain_sampling_;
21876769e502d8f0ebf5d2c81b00246727fb0a59925Yabin Cui  bool dwarf_callchain_sampling_;
21976769e502d8f0ebf5d2c81b00246727fb0a59925Yabin Cui  uint32_t dump_stack_size_in_dwarf_sampling_;
220cb84c9885e7a9f82cefba566d74e5c71214ab4c9Yabin Cui  bool unwind_dwarf_callchain_;
221f469c3d7f4466a2a31c3e837969c43c1e3bc4c90Yabin Cui  bool post_unwind_;
2224be412615fa6b6a7bf0afd5f620b249e98b2cab8Yabin Cui  bool child_inherit_;
223dbbda3020c483a8da2e9ce985c1e9d8b7bcc8ec0Yabin Cui  double duration_in_sec_;
224b42129797f17f990ea5a88c6bdc7446000cc361cYabin Cui  bool can_dump_kernel_symbols_;
225767dd17947f1ae9dd3d02f738d442a23ed76f2f6Yabin Cui  bool dump_symbols_;
226cb4c17ea53269ced994a2d849cbafb1afd5296e1Yabin Cui  std::vector<int> cpus_;
2279759e1b1ce76185aa539aeea2fb1cbd8382156e7Yabin Cui  EventSelectionSet event_selection_set_;
2289759e1b1ce76185aa539aeea2fb1cbd8382156e7Yabin Cui
2290a072cda021e5dfbdbb39f4d8d30771a851b3c3aYabin Cui  std::pair<size_t, size_t> mmap_page_range_;
2309759e1b1ce76185aa539aeea2fb1cbd8382156e7Yabin Cui
231f469c3d7f4466a2a31c3e837969c43c1e3bc4c90Yabin Cui  ThreadTree thread_tree_;
2329759e1b1ce76185aa539aeea2fb1cbd8382156e7Yabin Cui  std::string record_filename_;
2339759e1b1ce76185aa539aeea2fb1cbd8382156e7Yabin Cui  std::unique_ptr<RecordFileWriter> record_file_writer_;
2349759e1b1ce76185aa539aeea2fb1cbd8382156e7Yabin Cui
23557fb220017ae91f028ff2fbc819c07849c7c4f58Yabin Cui  uint64_t start_sampling_time_in_ns_;  // nanoseconds from machine starting
23657fb220017ae91f028ff2fbc819c07849c7c4f58Yabin Cui
237b1a885b014540a2f7798b5a35ea0f0ec150d93eeYabin Cui  uint64_t sample_record_count_;
238e5adc13cda8dd413f86d0dc8d187052efcaff7e5Yabin Cui  uint64_t lost_record_count_;
239e1c33a9a73075d72e9056fc9a1d275ce2e60b1f2Yabin Cui  int start_profiling_fd_;
240a80f8f707e9b6f9d4fb79714be1c887445c4511fYabin Cui  std::string app_package_name_;
241a80f8f707e9b6f9d4fb79714be1c887445c4511fYabin Cui  bool in_app_context_;
2429759e1b1ce76185aa539aeea2fb1cbd8382156e7Yabin Cui};
2439759e1b1ce76185aa539aeea2fb1cbd8382156e7Yabin Cui
244f79f07e13c56f7ca3be1435cea7f8861daf7efaaYabin Cuibool RecordCommand::Run(const std::vector<std::string>& args) {
245ebf79f3a65c81ef0f8cd7a3b875771be88157fccYabin Cui  if (!CheckPerfEventLimit()) {
246ebf79f3a65c81ef0f8cd7a3b875771be88157fccYabin Cui    return false;
247ebf79f3a65c81ef0f8cd7a3b875771be88157fccYabin Cui  }
248ebf79f3a65c81ef0f8cd7a3b875771be88157fccYabin Cui
2499759e1b1ce76185aa539aeea2fb1cbd8382156e7Yabin Cui  // 1. Parse options, and use default measured event type if not given.
2509759e1b1ce76185aa539aeea2fb1cbd8382156e7Yabin Cui  std::vector<std::string> workload_args;
2519759e1b1ce76185aa539aeea2fb1cbd8382156e7Yabin Cui  if (!ParseOptions(args, &workload_args)) {
2529759e1b1ce76185aa539aeea2fb1cbd8382156e7Yabin Cui    return false;
2539759e1b1ce76185aa539aeea2fb1cbd8382156e7Yabin Cui  }
254a80f8f707e9b6f9d4fb79714be1c887445c4511fYabin Cui  if (!app_package_name_.empty() && !in_app_context_) {
255a80f8f707e9b6f9d4fb79714be1c887445c4511fYabin Cui    // Some users want to profile non debuggable apps on rooted devices. If we use run-as,
256a80f8f707e9b6f9d4fb79714be1c887445c4511fYabin Cui    // it will be impossible when using --app. So don't switch to app's context when we are
257a80f8f707e9b6f9d4fb79714be1c887445c4511fYabin Cui    // root.
258a80f8f707e9b6f9d4fb79714be1c887445c4511fYabin Cui    if (!IsRoot()) {
259a80f8f707e9b6f9d4fb79714be1c887445c4511fYabin Cui      return RunInAppContext(app_package_name_, "record", args, workload_args.size(),
260f897452e2305dc19e9f6689029da74cdf07045f5Yabin Cui                             record_filename_, !event_selection_set_.GetTracepointEvents().empty());
261a80f8f707e9b6f9d4fb79714be1c887445c4511fYabin Cui    }
262a80f8f707e9b6f9d4fb79714be1c887445c4511fYabin Cui  }
263877751bbae11e009070e036ee1cd16e88135fff5Yabin Cui  if (event_selection_set_.empty()) {
264877751bbae11e009070e036ee1cd16e88135fff5Yabin Cui    if (!event_selection_set_.AddEventType(default_measured_event_type)) {
2659759e1b1ce76185aa539aeea2fb1cbd8382156e7Yabin Cui      return false;
2669759e1b1ce76185aa539aeea2fb1cbd8382156e7Yabin Cui    }
2679759e1b1ce76185aa539aeea2fb1cbd8382156e7Yabin Cui  }
268877751bbae11e009070e036ee1cd16e88135fff5Yabin Cui  if (!SetEventSelectionFlags()) {
269ddddc06d1f1d15d49e1eb43201b73beb29cf4cdeYabin Cui    return false;
270ddddc06d1f1d15d49e1eb43201b73beb29cf4cdeYabin Cui  }
271f897452e2305dc19e9f6689029da74cdf07045f5Yabin Cui
272f897452e2305dc19e9f6689029da74cdf07045f5Yabin Cui  // 2. Do some environment preparation.
273417df291499b37f63fa9b930e081d80a25bf38ecYabin Cui  ScopedCurrentArch scoped_arch(GetMachineArch());
274f897452e2305dc19e9f6689029da74cdf07045f5Yabin Cui  if (!InitPerfClock()) {
275f897452e2305dc19e9f6689029da74cdf07045f5Yabin Cui    return false;
276f897452e2305dc19e9f6689029da74cdf07045f5Yabin Cui  }
277f897452e2305dc19e9f6689029da74cdf07045f5Yabin Cui  PrepareVdsoFile();
2789759e1b1ce76185aa539aeea2fb1cbd8382156e7Yabin Cui
279f897452e2305dc19e9f6689029da74cdf07045f5Yabin Cui  // 3. Create workload.
280b032de7a9e1975a838cd6df2e7c8df3c7f70a3ceYabin Cui  std::unique_ptr<Workload> workload;
281b032de7a9e1975a838cd6df2e7c8df3c7f70a3ceYabin Cui  if (!workload_args.empty()) {
282b032de7a9e1975a838cd6df2e7c8df3c7f70a3ceYabin Cui    workload = Workload::CreateWorkload(workload_args);
283b032de7a9e1975a838cd6df2e7c8df3c7f70a3ceYabin Cui    if (workload == nullptr) {
284b032de7a9e1975a838cd6df2e7c8df3c7f70a3ceYabin Cui      return false;
285b032de7a9e1975a838cd6df2e7c8df3c7f70a3ceYabin Cui    }
2869759e1b1ce76185aa539aeea2fb1cbd8382156e7Yabin Cui  }
2875f43fc4ac870b49542b4cf530a3729f9f1e0e9abYabin Cui  bool need_to_check_targets = false;
288bc2a1022e1ea0a8c17691594d39fa53021de9166Yabin Cui  if (system_wide_collection_) {
289bc2a1022e1ea0a8c17691594d39fa53021de9166Yabin Cui    event_selection_set_.AddMonitoredThreads({-1});
290bc2a1022e1ea0a8c17691594d39fa53021de9166Yabin Cui  } else if (!event_selection_set_.HasMonitoredTarget()) {
291b032de7a9e1975a838cd6df2e7c8df3c7f70a3ceYabin Cui    if (workload != nullptr) {
292bc2a1022e1ea0a8c17691594d39fa53021de9166Yabin Cui      event_selection_set_.AddMonitoredProcesses({workload->GetPid()});
293b032de7a9e1975a838cd6df2e7c8df3c7f70a3ceYabin Cui      event_selection_set_.SetEnableOnExec(true);
29426968e6c48dea2eaa217991ade5a04e801f1be8fYabin Cui      if (event_selection_set_.HasInplaceSampler()) {
29526968e6c48dea2eaa217991ade5a04e801f1be8fYabin Cui        // Start worker early, because the worker process has to setup inplace-sampler server
29626968e6c48dea2eaa217991ade5a04e801f1be8fYabin Cui        // before we try to connect it.
29726968e6c48dea2eaa217991ade5a04e801f1be8fYabin Cui        if (!workload->Start()) {
29826968e6c48dea2eaa217991ade5a04e801f1be8fYabin Cui          return false;
29926968e6c48dea2eaa217991ade5a04e801f1be8fYabin Cui        }
30026968e6c48dea2eaa217991ade5a04e801f1be8fYabin Cui      }
301a80f8f707e9b6f9d4fb79714be1c887445c4511fYabin Cui    } else if (!app_package_name_.empty()) {
302a80f8f707e9b6f9d4fb79714be1c887445c4511fYabin Cui      // If app process is not created, wait for it. This allows simpleperf starts before
303a80f8f707e9b6f9d4fb79714be1c887445c4511fYabin Cui      // app process. In this way, we can have a better support of app start-up time profiling.
304a80f8f707e9b6f9d4fb79714be1c887445c4511fYabin Cui      int pid = WaitForAppProcess(app_package_name_);
305a80f8f707e9b6f9d4fb79714be1c887445c4511fYabin Cui      event_selection_set_.AddMonitoredProcesses({pid});
306b032de7a9e1975a838cd6df2e7c8df3c7f70a3ceYabin Cui    } else {
307b42129797f17f990ea5a88c6bdc7446000cc361cYabin Cui      LOG(ERROR)
3080a072cda021e5dfbdbb39f4d8d30771a851b3c3aYabin Cui          << "No threads to monitor. Try `simpleperf help record` for help";
309b032de7a9e1975a838cd6df2e7c8df3c7f70a3ceYabin Cui      return false;
310b032de7a9e1975a838cd6df2e7c8df3c7f70a3ceYabin Cui    }
3115f43fc4ac870b49542b4cf530a3729f9f1e0e9abYabin Cui  } else {
3125f43fc4ac870b49542b4cf530a3729f9f1e0e9abYabin Cui    need_to_check_targets = true;
3139759e1b1ce76185aa539aeea2fb1cbd8382156e7Yabin Cui  }
3149759e1b1ce76185aa539aeea2fb1cbd8382156e7Yabin Cui
315f897452e2305dc19e9f6689029da74cdf07045f5Yabin Cui  // 4. Open perf_event_files, create mapped buffers for perf_event_files.
316bc2a1022e1ea0a8c17691594d39fa53021de9166Yabin Cui  if (!event_selection_set_.OpenEventFiles(cpus_)) {
317bc2a1022e1ea0a8c17691594d39fa53021de9166Yabin Cui    return false;
3189759e1b1ce76185aa539aeea2fb1cbd8382156e7Yabin Cui  }
3190a072cda021e5dfbdbb39f4d8d30771a851b3c3aYabin Cui  if (!event_selection_set_.MmapEventFiles(mmap_page_range_.first,
320dbbda3020c483a8da2e9ce985c1e9d8b7bcc8ec0Yabin Cui                                           mmap_page_range_.second)) {
3219759e1b1ce76185aa539aeea2fb1cbd8382156e7Yabin Cui    return false;
3229759e1b1ce76185aa539aeea2fb1cbd8382156e7Yabin Cui  }
3239759e1b1ce76185aa539aeea2fb1cbd8382156e7Yabin Cui
324f897452e2305dc19e9f6689029da74cdf07045f5Yabin Cui  // 5. Create perf.data.
325b7f481f59126456b0e708a76f40fa88224f3531bYabin Cui  if (!CreateAndInitRecordFile()) {
3267d59bb49fb47fbc82ef5c77d7aebf7174fd996e1Yabin Cui    return false;
3277d59bb49fb47fbc82ef5c77d7aebf7174fd996e1Yabin Cui  }
3289759e1b1ce76185aa539aeea2fb1cbd8382156e7Yabin Cui
329f897452e2305dc19e9f6689029da74cdf07045f5Yabin Cui  // 6. Add read/signal/periodic Events.
330b42129797f17f990ea5a88c6bdc7446000cc361cYabin Cui  auto callback =
331b42129797f17f990ea5a88c6bdc7446000cc361cYabin Cui      std::bind(&RecordCommand::ProcessRecord, this, std::placeholders::_1);
3325f43fc4ac870b49542b4cf530a3729f9f1e0e9abYabin Cui  if (!event_selection_set_.PrepareToReadMmapEventData(callback)) {
333dbbda3020c483a8da2e9ce985c1e9d8b7bcc8ec0Yabin Cui    return false;
334dbbda3020c483a8da2e9ce985c1e9d8b7bcc8ec0Yabin Cui  }
3355f43fc4ac870b49542b4cf530a3729f9f1e0e9abYabin Cui  if (!event_selection_set_.HandleCpuHotplugEvents(cpus_)) {
336994cb626a9b0ad6cb723a9dfa7c5e05849647c87Yabin Cui    return false;
337994cb626a9b0ad6cb723a9dfa7c5e05849647c87Yabin Cui  }
3385f43fc4ac870b49542b4cf530a3729f9f1e0e9abYabin Cui  if (need_to_check_targets && !event_selection_set_.StopWhenNoMoreTargets()) {
3395f43fc4ac870b49542b4cf530a3729f9f1e0e9abYabin Cui    return false;
3405f43fc4ac870b49542b4cf530a3729f9f1e0e9abYabin Cui  }
34126968e6c48dea2eaa217991ade5a04e801f1be8fYabin Cui  IOEventLoop* loop = event_selection_set_.GetIOEventLoop();
34226968e6c48dea2eaa217991ade5a04e801f1be8fYabin Cui  if (!loop->AddSignalEvents({SIGCHLD, SIGINT, SIGTERM, SIGHUP},
34326968e6c48dea2eaa217991ade5a04e801f1be8fYabin Cui                             [&]() { return loop->ExitLoop(); })) {
344dbbda3020c483a8da2e9ce985c1e9d8b7bcc8ec0Yabin Cui    return false;
345dbbda3020c483a8da2e9ce985c1e9d8b7bcc8ec0Yabin Cui  }
346dbbda3020c483a8da2e9ce985c1e9d8b7bcc8ec0Yabin Cui  if (duration_in_sec_ != 0) {
34726968e6c48dea2eaa217991ade5a04e801f1be8fYabin Cui    if (!loop->AddPeriodicEvent(SecondToTimeval(duration_in_sec_),
34826968e6c48dea2eaa217991ade5a04e801f1be8fYabin Cui                                [&]() { return loop->ExitLoop(); })) {
3499759e1b1ce76185aa539aeea2fb1cbd8382156e7Yabin Cui      return false;
3509759e1b1ce76185aa539aeea2fb1cbd8382156e7Yabin Cui    }
3519759e1b1ce76185aa539aeea2fb1cbd8382156e7Yabin Cui  }
3529759e1b1ce76185aa539aeea2fb1cbd8382156e7Yabin Cui
353f897452e2305dc19e9f6689029da74cdf07045f5Yabin Cui  // 7. Write records in mapped buffers of perf_event_files to output file while
354dbbda3020c483a8da2e9ce985c1e9d8b7bcc8ec0Yabin Cui  //    workload is running.
355003b245939bae5e86ed53b3c6b333637dbc571b4Yabin Cui  start_sampling_time_in_ns_ = GetPerfClock();
356aa65c8b250b99f1684f46e2c40b77e42bf7c5f31Yabin Cui  LOG(VERBOSE) << "start_sampling_time is " << start_sampling_time_in_ns_
357aa65c8b250b99f1684f46e2c40b77e42bf7c5f31Yabin Cui               << " ns";
35826968e6c48dea2eaa217991ade5a04e801f1be8fYabin Cui  if (workload != nullptr && !workload->IsStarted() && !workload->Start()) {
359dbbda3020c483a8da2e9ce985c1e9d8b7bcc8ec0Yabin Cui    return false;
360dbbda3020c483a8da2e9ce985c1e9d8b7bcc8ec0Yabin Cui  }
361e1c33a9a73075d72e9056fc9a1d275ce2e60b1f2Yabin Cui  if (start_profiling_fd_ != -1) {
362e1c33a9a73075d72e9056fc9a1d275ce2e60b1f2Yabin Cui    if (!android::base::WriteStringToFd("STARTED", start_profiling_fd_)) {
363e1c33a9a73075d72e9056fc9a1d275ce2e60b1f2Yabin Cui      PLOG(ERROR) << "failed to write to start_profiling_fd_";
364e1c33a9a73075d72e9056fc9a1d275ce2e60b1f2Yabin Cui    }
365e1c33a9a73075d72e9056fc9a1d275ce2e60b1f2Yabin Cui    close(start_profiling_fd_);
366e1c33a9a73075d72e9056fc9a1d275ce2e60b1f2Yabin Cui  }
36726968e6c48dea2eaa217991ade5a04e801f1be8fYabin Cui  if (!loop->RunLoop()) {
368dbbda3020c483a8da2e9ce985c1e9d8b7bcc8ec0Yabin Cui    return false;
369dbbda3020c483a8da2e9ce985c1e9d8b7bcc8ec0Yabin Cui  }
370dbbda3020c483a8da2e9ce985c1e9d8b7bcc8ec0Yabin Cui  if (!event_selection_set_.FinishReadMmapEventData()) {
371dbbda3020c483a8da2e9ce985c1e9d8b7bcc8ec0Yabin Cui    return false;
372dbbda3020c483a8da2e9ce985c1e9d8b7bcc8ec0Yabin Cui  }
373dbbda3020c483a8da2e9ce985c1e9d8b7bcc8ec0Yabin Cui
374f897452e2305dc19e9f6689029da74cdf07045f5Yabin Cui  // 8. Dump additional features, and close record file.
375d713f959ec1fe07ed993e2c9f4166b52aa98a58cYabin Cui  if (!DumpAdditionalFeatures(args)) {
3768f6225147c5b6cb2159a7f5cb0dab952ee0759dfYabin Cui    return false;
3778f6225147c5b6cb2159a7f5cb0dab952ee0759dfYabin Cui  }
3789759e1b1ce76185aa539aeea2fb1cbd8382156e7Yabin Cui  if (!record_file_writer_->Close()) {
3799759e1b1ce76185aa539aeea2fb1cbd8382156e7Yabin Cui    return false;
3809759e1b1ce76185aa539aeea2fb1cbd8382156e7Yabin Cui  }
381b7f481f59126456b0e708a76f40fa88224f3531bYabin Cui
382f897452e2305dc19e9f6689029da74cdf07045f5Yabin Cui  // 9. Unwind dwarf callchain.
383b7f481f59126456b0e708a76f40fa88224f3531bYabin Cui  if (post_unwind_) {
384b7f481f59126456b0e708a76f40fa88224f3531bYabin Cui    if (!PostUnwind(args)) {
385b7f481f59126456b0e708a76f40fa88224f3531bYabin Cui      return false;
386b7f481f59126456b0e708a76f40fa88224f3531bYabin Cui    }
387b7f481f59126456b0e708a76f40fa88224f3531bYabin Cui  }
388e5adc13cda8dd413f86d0dc8d187052efcaff7e5Yabin Cui
389f897452e2305dc19e9f6689029da74cdf07045f5Yabin Cui  // 10. Show brief record result.
390e5adc13cda8dd413f86d0dc8d187052efcaff7e5Yabin Cui  LOG(INFO) << "Samples recorded: " << sample_record_count_
391e5adc13cda8dd413f86d0dc8d187052efcaff7e5Yabin Cui            << ". Samples lost: " << lost_record_count_ << ".";
392e5adc13cda8dd413f86d0dc8d187052efcaff7e5Yabin Cui  if (sample_record_count_ + lost_record_count_ != 0) {
393e5adc13cda8dd413f86d0dc8d187052efcaff7e5Yabin Cui    double lost_percent = static_cast<double>(lost_record_count_) /
394e5adc13cda8dd413f86d0dc8d187052efcaff7e5Yabin Cui                          (lost_record_count_ + sample_record_count_);
395e5adc13cda8dd413f86d0dc8d187052efcaff7e5Yabin Cui    constexpr double LOST_PERCENT_WARNING_BAR = 0.1;
396e5adc13cda8dd413f86d0dc8d187052efcaff7e5Yabin Cui    if (lost_percent >= LOST_PERCENT_WARNING_BAR) {
397e5adc13cda8dd413f86d0dc8d187052efcaff7e5Yabin Cui      LOG(WARNING) << "Lost " << (lost_percent * 100) << "% of samples, "
398e5adc13cda8dd413f86d0dc8d187052efcaff7e5Yabin Cui                   << "consider increasing mmap_pages(-m), "
399e5adc13cda8dd413f86d0dc8d187052efcaff7e5Yabin Cui                   << "or decreasing sample frequency(-f), "
400e5adc13cda8dd413f86d0dc8d187052efcaff7e5Yabin Cui                   << "or increasing sample period(-c).";
401e5adc13cda8dd413f86d0dc8d187052efcaff7e5Yabin Cui    }
402e5adc13cda8dd413f86d0dc8d187052efcaff7e5Yabin Cui  }
4039759e1b1ce76185aa539aeea2fb1cbd8382156e7Yabin Cui  return true;
4049759e1b1ce76185aa539aeea2fb1cbd8382156e7Yabin Cui}
4059759e1b1ce76185aa539aeea2fb1cbd8382156e7Yabin Cui
406f79f07e13c56f7ca3be1435cea7f8861daf7efaaYabin Cuibool RecordCommand::ParseOptions(const std::vector<std::string>& args,
407f79f07e13c56f7ca3be1435cea7f8861daf7efaaYabin Cui                                 std::vector<std::string>* non_option_args) {
4089759e1b1ce76185aa539aeea2fb1cbd8382156e7Yabin Cui  size_t i;
409b42129797f17f990ea5a88c6bdc7446000cc361cYabin Cui  for (i = 0; i < args.size() && !args[i].empty() && args[i][0] == '-'; ++i) {
4109759e1b1ce76185aa539aeea2fb1cbd8382156e7Yabin Cui    if (args[i] == "-a") {
4119759e1b1ce76185aa539aeea2fb1cbd8382156e7Yabin Cui      system_wide_collection_ = true;
412a80f8f707e9b6f9d4fb79714be1c887445c4511fYabin Cui    } else if (args[i] == "--app") {
413a80f8f707e9b6f9d4fb79714be1c887445c4511fYabin Cui      if (!NextArgumentOrError(args, &i)) {
414a80f8f707e9b6f9d4fb79714be1c887445c4511fYabin Cui        return false;
415a80f8f707e9b6f9d4fb79714be1c887445c4511fYabin Cui      }
416a80f8f707e9b6f9d4fb79714be1c887445c4511fYabin Cui      app_package_name_ = args[i];
417ddddc06d1f1d15d49e1eb43201b73beb29cf4cdeYabin Cui    } else if (args[i] == "-b") {
418ddddc06d1f1d15d49e1eb43201b73beb29cf4cdeYabin Cui      branch_sampling_ = branch_sampling_type_map["any"];
4199759e1b1ce76185aa539aeea2fb1cbd8382156e7Yabin Cui    } else if (args[i] == "-c") {
4209759e1b1ce76185aa539aeea2fb1cbd8382156e7Yabin Cui      if (!NextArgumentOrError(args, &i)) {
4219759e1b1ce76185aa539aeea2fb1cbd8382156e7Yabin Cui        return false;
4229759e1b1ce76185aa539aeea2fb1cbd8382156e7Yabin Cui      }
4239759e1b1ce76185aa539aeea2fb1cbd8382156e7Yabin Cui      char* endptr;
4249759e1b1ce76185aa539aeea2fb1cbd8382156e7Yabin Cui      sample_period_ = strtoull(args[i].c_str(), &endptr, 0);
4259759e1b1ce76185aa539aeea2fb1cbd8382156e7Yabin Cui      if (*endptr != '\0' || sample_period_ == 0) {
4269759e1b1ce76185aa539aeea2fb1cbd8382156e7Yabin Cui        LOG(ERROR) << "Invalid sample period: '" << args[i] << "'";
4279759e1b1ce76185aa539aeea2fb1cbd8382156e7Yabin Cui        return false;
4289759e1b1ce76185aa539aeea2fb1cbd8382156e7Yabin Cui      }
4294f41df6f68efc3b9b534014a8cfb6ee8ac4d5c91Yabin Cui      use_sample_period_ = true;
43076769e502d8f0ebf5d2c81b00246727fb0a59925Yabin Cui    } else if (args[i] == "--call-graph") {
43176769e502d8f0ebf5d2c81b00246727fb0a59925Yabin Cui      if (!NextArgumentOrError(args, &i)) {
43276769e502d8f0ebf5d2c81b00246727fb0a59925Yabin Cui        return false;
43376769e502d8f0ebf5d2c81b00246727fb0a59925Yabin Cui      }
43476769e502d8f0ebf5d2c81b00246727fb0a59925Yabin Cui      std::vector<std::string> strs = android::base::Split(args[i], ",");
43576769e502d8f0ebf5d2c81b00246727fb0a59925Yabin Cui      if (strs[0] == "fp") {
43676769e502d8f0ebf5d2c81b00246727fb0a59925Yabin Cui        fp_callchain_sampling_ = true;
43776769e502d8f0ebf5d2c81b00246727fb0a59925Yabin Cui        dwarf_callchain_sampling_ = false;
43876769e502d8f0ebf5d2c81b00246727fb0a59925Yabin Cui      } else if (strs[0] == "dwarf") {
43976769e502d8f0ebf5d2c81b00246727fb0a59925Yabin Cui        fp_callchain_sampling_ = false;
44076769e502d8f0ebf5d2c81b00246727fb0a59925Yabin Cui        dwarf_callchain_sampling_ = true;
44176769e502d8f0ebf5d2c81b00246727fb0a59925Yabin Cui        if (strs.size() > 1) {
44276769e502d8f0ebf5d2c81b00246727fb0a59925Yabin Cui          char* endptr;
44376769e502d8f0ebf5d2c81b00246727fb0a59925Yabin Cui          uint64_t size = strtoull(strs[1].c_str(), &endptr, 0);
44476769e502d8f0ebf5d2c81b00246727fb0a59925Yabin Cui          if (*endptr != '\0' || size > UINT_MAX) {
445b42129797f17f990ea5a88c6bdc7446000cc361cYabin Cui            LOG(ERROR) << "invalid dump stack size in --call-graph option: "
446b42129797f17f990ea5a88c6bdc7446000cc361cYabin Cui                       << strs[1];
44776769e502d8f0ebf5d2c81b00246727fb0a59925Yabin Cui            return false;
44876769e502d8f0ebf5d2c81b00246727fb0a59925Yabin Cui          }
44976769e502d8f0ebf5d2c81b00246727fb0a59925Yabin Cui          if ((size & 7) != 0) {
450b42129797f17f990ea5a88c6bdc7446000cc361cYabin Cui            LOG(ERROR) << "dump stack size " << size
451b42129797f17f990ea5a88c6bdc7446000cc361cYabin Cui                       << " is not 8-byte aligned.";
45276769e502d8f0ebf5d2c81b00246727fb0a59925Yabin Cui            return false;
453e9f06a6582d70b06a01e8e183081112b109776f6Yabin Cui          }
454e9f06a6582d70b06a01e8e183081112b109776f6Yabin Cui          if (size >= MAX_DUMP_STACK_SIZE) {
455e9f06a6582d70b06a01e8e183081112b109776f6Yabin Cui            LOG(ERROR) << "dump stack size " << size
456e9f06a6582d70b06a01e8e183081112b109776f6Yabin Cui                       << " is bigger than max allowed size "
457e9f06a6582d70b06a01e8e183081112b109776f6Yabin Cui                       << MAX_DUMP_STACK_SIZE << ".";
458e9f06a6582d70b06a01e8e183081112b109776f6Yabin Cui            return false;
45976769e502d8f0ebf5d2c81b00246727fb0a59925Yabin Cui          }
46076769e502d8f0ebf5d2c81b00246727fb0a59925Yabin Cui          dump_stack_size_in_dwarf_sampling_ = static_cast<uint32_t>(size);
46176769e502d8f0ebf5d2c81b00246727fb0a59925Yabin Cui        }
46276769e502d8f0ebf5d2c81b00246727fb0a59925Yabin Cui      } else {
463b42129797f17f990ea5a88c6bdc7446000cc361cYabin Cui        LOG(ERROR) << "unexpected argument for --call-graph option: "
464b42129797f17f990ea5a88c6bdc7446000cc361cYabin Cui                   << args[i];
46576769e502d8f0ebf5d2c81b00246727fb0a59925Yabin Cui        return false;
46676769e502d8f0ebf5d2c81b00246727fb0a59925Yabin Cui      }
467cb4c17ea53269ced994a2d849cbafb1afd5296e1Yabin Cui    } else if (args[i] == "--cpu") {
468cb4c17ea53269ced994a2d849cbafb1afd5296e1Yabin Cui      if (!NextArgumentOrError(args, &i)) {
469cb4c17ea53269ced994a2d849cbafb1afd5296e1Yabin Cui        return false;
470cb4c17ea53269ced994a2d849cbafb1afd5296e1Yabin Cui      }
471cb4c17ea53269ced994a2d849cbafb1afd5296e1Yabin Cui      cpus_ = GetCpusFromString(args[i]);
4728a599d7c95f2a8207fb3fe90e824aab1f30abe62Yabin Cui    } else if (args[i] == "--duration") {
4738a599d7c95f2a8207fb3fe90e824aab1f30abe62Yabin Cui      if (!NextArgumentOrError(args, &i)) {
4748a599d7c95f2a8207fb3fe90e824aab1f30abe62Yabin Cui        return false;
4758a599d7c95f2a8207fb3fe90e824aab1f30abe62Yabin Cui      }
476c0565bb21e2997d7a01dda40ea2b16e067e7e28cYabin Cui      if (!android::base::ParseDouble(args[i].c_str(), &duration_in_sec_,
477c0565bb21e2997d7a01dda40ea2b16e067e7e28cYabin Cui                                      1e-9)) {
4788a599d7c95f2a8207fb3fe90e824aab1f30abe62Yabin Cui        LOG(ERROR) << "Invalid duration: " << args[i].c_str();
4798a599d7c95f2a8207fb3fe90e824aab1f30abe62Yabin Cui        return false;
4808a599d7c95f2a8207fb3fe90e824aab1f30abe62Yabin Cui      }
4819759e1b1ce76185aa539aeea2fb1cbd8382156e7Yabin Cui    } else if (args[i] == "-e") {
4829759e1b1ce76185aa539aeea2fb1cbd8382156e7Yabin Cui      if (!NextArgumentOrError(args, &i)) {
4839759e1b1ce76185aa539aeea2fb1cbd8382156e7Yabin Cui        return false;
4849759e1b1ce76185aa539aeea2fb1cbd8382156e7Yabin Cui      }
485afdb9cea28340e31142fd66a90c88ed8e18ebbfaYabin Cui      std::vector<std::string> event_types = android::base::Split(args[i], ",");
486afdb9cea28340e31142fd66a90c88ed8e18ebbfaYabin Cui      for (auto& event_type : event_types) {
487877751bbae11e009070e036ee1cd16e88135fff5Yabin Cui        if (!event_selection_set_.AddEventType(event_type)) {
488afdb9cea28340e31142fd66a90c88ed8e18ebbfaYabin Cui          return false;
489afdb9cea28340e31142fd66a90c88ed8e18ebbfaYabin Cui        }
4909759e1b1ce76185aa539aeea2fb1cbd8382156e7Yabin Cui      }
4919759e1b1ce76185aa539aeea2fb1cbd8382156e7Yabin Cui    } else if (args[i] == "-f" || args[i] == "-F") {
4929759e1b1ce76185aa539aeea2fb1cbd8382156e7Yabin Cui      if (!NextArgumentOrError(args, &i)) {
4939759e1b1ce76185aa539aeea2fb1cbd8382156e7Yabin Cui        return false;
4949759e1b1ce76185aa539aeea2fb1cbd8382156e7Yabin Cui      }
495b891549ed16a91b6db52e8500bb6816fc9293bacYabin Cui      if (!android::base::ParseUint(args[i].c_str(), &sample_freq_)) {
496b891549ed16a91b6db52e8500bb6816fc9293bacYabin Cui        LOG(ERROR) << "Invalid sample frequency: " << args[i];
497b891549ed16a91b6db52e8500bb6816fc9293bacYabin Cui        return false;
498b891549ed16a91b6db52e8500bb6816fc9293bacYabin Cui      }
499b891549ed16a91b6db52e8500bb6816fc9293bacYabin Cui      if (!CheckSampleFrequency(sample_freq_)) {
5009759e1b1ce76185aa539aeea2fb1cbd8382156e7Yabin Cui        return false;
5019759e1b1ce76185aa539aeea2fb1cbd8382156e7Yabin Cui      }
5029759e1b1ce76185aa539aeea2fb1cbd8382156e7Yabin Cui      use_sample_freq_ = true;
5036e8a9a4e52242f82104644bca0318284b3bbdd6bYabin Cui    } else if (args[i] == "-g") {
50476769e502d8f0ebf5d2c81b00246727fb0a59925Yabin Cui      fp_callchain_sampling_ = false;
50576769e502d8f0ebf5d2c81b00246727fb0a59925Yabin Cui      dwarf_callchain_sampling_ = true;
506877751bbae11e009070e036ee1cd16e88135fff5Yabin Cui    } else if (args[i] == "--group") {
507877751bbae11e009070e036ee1cd16e88135fff5Yabin Cui      if (!NextArgumentOrError(args, &i)) {
508877751bbae11e009070e036ee1cd16e88135fff5Yabin Cui        return false;
509877751bbae11e009070e036ee1cd16e88135fff5Yabin Cui      }
510877751bbae11e009070e036ee1cd16e88135fff5Yabin Cui      std::vector<std::string> event_types = android::base::Split(args[i], ",");
511877751bbae11e009070e036ee1cd16e88135fff5Yabin Cui      if (!event_selection_set_.AddEventGroup(event_types)) {
512877751bbae11e009070e036ee1cd16e88135fff5Yabin Cui        return false;
513877751bbae11e009070e036ee1cd16e88135fff5Yabin Cui      }
514a80f8f707e9b6f9d4fb79714be1c887445c4511fYabin Cui    } else if (args[i] == "--in-app") {
515a80f8f707e9b6f9d4fb79714be1c887445c4511fYabin Cui      in_app_context_ = true;
516ddddc06d1f1d15d49e1eb43201b73beb29cf4cdeYabin Cui    } else if (args[i] == "-j") {
517ddddc06d1f1d15d49e1eb43201b73beb29cf4cdeYabin Cui      if (!NextArgumentOrError(args, &i)) {
518ddddc06d1f1d15d49e1eb43201b73beb29cf4cdeYabin Cui        return false;
519ddddc06d1f1d15d49e1eb43201b73beb29cf4cdeYabin Cui      }
520b42129797f17f990ea5a88c6bdc7446000cc361cYabin Cui      std::vector<std::string> branch_sampling_types =
521b42129797f17f990ea5a88c6bdc7446000cc361cYabin Cui          android::base::Split(args[i], ",");
522ddddc06d1f1d15d49e1eb43201b73beb29cf4cdeYabin Cui      for (auto& type : branch_sampling_types) {
523ddddc06d1f1d15d49e1eb43201b73beb29cf4cdeYabin Cui        auto it = branch_sampling_type_map.find(type);
524ddddc06d1f1d15d49e1eb43201b73beb29cf4cdeYabin Cui        if (it == branch_sampling_type_map.end()) {
525ddddc06d1f1d15d49e1eb43201b73beb29cf4cdeYabin Cui          LOG(ERROR) << "unrecognized branch sampling filter: " << type;
526ddddc06d1f1d15d49e1eb43201b73beb29cf4cdeYabin Cui          return false;
527ddddc06d1f1d15d49e1eb43201b73beb29cf4cdeYabin Cui        }
528ddddc06d1f1d15d49e1eb43201b73beb29cf4cdeYabin Cui        branch_sampling_ |= it->second;
529ddddc06d1f1d15d49e1eb43201b73beb29cf4cdeYabin Cui      }
53042f37f04c53f537de748189b1c74e847bb69e934Yabin Cui    } else if (args[i] == "-m") {
53142f37f04c53f537de748189b1c74e847bb69e934Yabin Cui      if (!NextArgumentOrError(args, &i)) {
53242f37f04c53f537de748189b1c74e847bb69e934Yabin Cui        return false;
53342f37f04c53f537de748189b1c74e847bb69e934Yabin Cui      }
53442f37f04c53f537de748189b1c74e847bb69e934Yabin Cui      char* endptr;
53542f37f04c53f537de748189b1c74e847bb69e934Yabin Cui      uint64_t pages = strtoull(args[i].c_str(), &endptr, 0);
53642f37f04c53f537de748189b1c74e847bb69e934Yabin Cui      if (*endptr != '\0' || !IsPowerOfTwo(pages)) {
53742f37f04c53f537de748189b1c74e847bb69e934Yabin Cui        LOG(ERROR) << "Invalid mmap_pages: '" << args[i] << "'";
53842f37f04c53f537de748189b1c74e847bb69e934Yabin Cui        return false;
53942f37f04c53f537de748189b1c74e847bb69e934Yabin Cui      }
5400a072cda021e5dfbdbb39f4d8d30771a851b3c3aYabin Cui      mmap_page_range_.first = mmap_page_range_.second = pages;
541b42129797f17f990ea5a88c6bdc7446000cc361cYabin Cui    } else if (args[i] == "--no-dump-kernel-symbols") {
542b42129797f17f990ea5a88c6bdc7446000cc361cYabin Cui      can_dump_kernel_symbols_ = false;
543dcb2a3e580f155bb28621c4cbad019d104e8f300Yabin Cui    } else if (args[i] == "--no-dump-symbols") {
544dcb2a3e580f155bb28621c4cbad019d104e8f300Yabin Cui      dump_symbols_ = false;
5454be412615fa6b6a7bf0afd5f620b249e98b2cab8Yabin Cui    } else if (args[i] == "--no-inherit") {
5464be412615fa6b6a7bf0afd5f620b249e98b2cab8Yabin Cui      child_inherit_ = false;
547cb84c9885e7a9f82cefba566d74e5c71214ab4c9Yabin Cui    } else if (args[i] == "--no-unwind") {
548cb84c9885e7a9f82cefba566d74e5c71214ab4c9Yabin Cui      unwind_dwarf_callchain_ = false;
5499759e1b1ce76185aa539aeea2fb1cbd8382156e7Yabin Cui    } else if (args[i] == "-o") {
5509759e1b1ce76185aa539aeea2fb1cbd8382156e7Yabin Cui      if (!NextArgumentOrError(args, &i)) {
5519759e1b1ce76185aa539aeea2fb1cbd8382156e7Yabin Cui        return false;
5529759e1b1ce76185aa539aeea2fb1cbd8382156e7Yabin Cui      }
5539759e1b1ce76185aa539aeea2fb1cbd8382156e7Yabin Cui      record_filename_ = args[i];
554b032de7a9e1975a838cd6df2e7c8df3c7f70a3ceYabin Cui    } else if (args[i] == "-p") {
555b032de7a9e1975a838cd6df2e7c8df3c7f70a3ceYabin Cui      if (!NextArgumentOrError(args, &i)) {
556b032de7a9e1975a838cd6df2e7c8df3c7f70a3ceYabin Cui        return false;
557b032de7a9e1975a838cd6df2e7c8df3c7f70a3ceYabin Cui      }
558bc2a1022e1ea0a8c17691594d39fa53021de9166Yabin Cui      std::set<pid_t> pids;
559bc2a1022e1ea0a8c17691594d39fa53021de9166Yabin Cui      if (!GetValidThreadsFromThreadString(args[i], &pids)) {
560b032de7a9e1975a838cd6df2e7c8df3c7f70a3ceYabin Cui        return false;
561b032de7a9e1975a838cd6df2e7c8df3c7f70a3ceYabin Cui      }
562bc2a1022e1ea0a8c17691594d39fa53021de9166Yabin Cui      event_selection_set_.AddMonitoredProcesses(pids);
563f469c3d7f4466a2a31c3e837969c43c1e3bc4c90Yabin Cui    } else if (args[i] == "--post-unwind") {
564f469c3d7f4466a2a31c3e837969c43c1e3bc4c90Yabin Cui      post_unwind_ = true;
565e1c33a9a73075d72e9056fc9a1d275ce2e60b1f2Yabin Cui    } else if (args[i] == "--start_profiling_fd") {
566e1c33a9a73075d72e9056fc9a1d275ce2e60b1f2Yabin Cui      if (!NextArgumentOrError(args, &i)) {
567e1c33a9a73075d72e9056fc9a1d275ce2e60b1f2Yabin Cui        return false;
568e1c33a9a73075d72e9056fc9a1d275ce2e60b1f2Yabin Cui      }
569e1c33a9a73075d72e9056fc9a1d275ce2e60b1f2Yabin Cui      if (!android::base::ParseInt(args[i].c_str(), &start_profiling_fd_, 0)) {
570e1c33a9a73075d72e9056fc9a1d275ce2e60b1f2Yabin Cui        LOG(ERROR) << "Invalid start_profiling_fd: " << args[i];
571e1c33a9a73075d72e9056fc9a1d275ce2e60b1f2Yabin Cui        return false;
572e1c33a9a73075d72e9056fc9a1d275ce2e60b1f2Yabin Cui      }
573faa512630a79455bde7b5b56929ea371c6f612bdYabin Cui    } else if (args[i] == "--symfs") {
574faa512630a79455bde7b5b56929ea371c6f612bdYabin Cui      if (!NextArgumentOrError(args, &i)) {
575faa512630a79455bde7b5b56929ea371c6f612bdYabin Cui        return false;
576faa512630a79455bde7b5b56929ea371c6f612bdYabin Cui      }
577faa512630a79455bde7b5b56929ea371c6f612bdYabin Cui      if (!Dso::SetSymFsDir(args[i])) {
578faa512630a79455bde7b5b56929ea371c6f612bdYabin Cui        return false;
579faa512630a79455bde7b5b56929ea371c6f612bdYabin Cui      }
580b032de7a9e1975a838cd6df2e7c8df3c7f70a3ceYabin Cui    } else if (args[i] == "-t") {
581b032de7a9e1975a838cd6df2e7c8df3c7f70a3ceYabin Cui      if (!NextArgumentOrError(args, &i)) {
582b032de7a9e1975a838cd6df2e7c8df3c7f70a3ceYabin Cui        return false;
583b032de7a9e1975a838cd6df2e7c8df3c7f70a3ceYabin Cui      }
584bc2a1022e1ea0a8c17691594d39fa53021de9166Yabin Cui      std::set<pid_t> tids;
585bc2a1022e1ea0a8c17691594d39fa53021de9166Yabin Cui      if (!GetValidThreadsFromThreadString(args[i], &tids)) {
586b032de7a9e1975a838cd6df2e7c8df3c7f70a3ceYabin Cui        return false;
587b032de7a9e1975a838cd6df2e7c8df3c7f70a3ceYabin Cui      }
588bc2a1022e1ea0a8c17691594d39fa53021de9166Yabin Cui      event_selection_set_.AddMonitoredThreads(tids);
589f897452e2305dc19e9f6689029da74cdf07045f5Yabin Cui    } else if (args[i] == "--tracepoint-events") {
590f897452e2305dc19e9f6689029da74cdf07045f5Yabin Cui      if (!NextArgumentOrError(args, &i)) {
591f897452e2305dc19e9f6689029da74cdf07045f5Yabin Cui        return false;
592f897452e2305dc19e9f6689029da74cdf07045f5Yabin Cui      }
593f897452e2305dc19e9f6689029da74cdf07045f5Yabin Cui      if (!SetTracepointEventsFilePath(args[i])) {
594f897452e2305dc19e9f6689029da74cdf07045f5Yabin Cui        return false;
595f897452e2305dc19e9f6689029da74cdf07045f5Yabin Cui      }
5969759e1b1ce76185aa539aeea2fb1cbd8382156e7Yabin Cui    } else {
597f79f07e13c56f7ca3be1435cea7f8861daf7efaaYabin Cui      ReportUnknownOption(args, i);
5989759e1b1ce76185aa539aeea2fb1cbd8382156e7Yabin Cui      return false;
5999759e1b1ce76185aa539aeea2fb1cbd8382156e7Yabin Cui    }
6009759e1b1ce76185aa539aeea2fb1cbd8382156e7Yabin Cui  }
6019759e1b1ce76185aa539aeea2fb1cbd8382156e7Yabin Cui
6024f41df6f68efc3b9b534014a8cfb6ee8ac4d5c91Yabin Cui  if (use_sample_freq_ && use_sample_period_) {
6034f41df6f68efc3b9b534014a8cfb6ee8ac4d5c91Yabin Cui    LOG(ERROR) << "-f option can't be used with -c option.";
6044f41df6f68efc3b9b534014a8cfb6ee8ac4d5c91Yabin Cui    return false;
6054f41df6f68efc3b9b534014a8cfb6ee8ac4d5c91Yabin Cui  }
6064f41df6f68efc3b9b534014a8cfb6ee8ac4d5c91Yabin Cui
607cb84c9885e7a9f82cefba566d74e5c71214ab4c9Yabin Cui  if (!dwarf_callchain_sampling_) {
608cb84c9885e7a9f82cefba566d74e5c71214ab4c9Yabin Cui    if (!unwind_dwarf_callchain_) {
609b42129797f17f990ea5a88c6bdc7446000cc361cYabin Cui      LOG(ERROR)
610b42129797f17f990ea5a88c6bdc7446000cc361cYabin Cui          << "--no-unwind is only used with `--call-graph dwarf` option.";
611cb84c9885e7a9f82cefba566d74e5c71214ab4c9Yabin Cui      return false;
612cb84c9885e7a9f82cefba566d74e5c71214ab4c9Yabin Cui    }
613cb84c9885e7a9f82cefba566d74e5c71214ab4c9Yabin Cui    unwind_dwarf_callchain_ = false;
614cb84c9885e7a9f82cefba566d74e5c71214ab4c9Yabin Cui  }
615f469c3d7f4466a2a31c3e837969c43c1e3bc4c90Yabin Cui  if (post_unwind_) {
616f469c3d7f4466a2a31c3e837969c43c1e3bc4c90Yabin Cui    if (!dwarf_callchain_sampling_) {
617b42129797f17f990ea5a88c6bdc7446000cc361cYabin Cui      LOG(ERROR)
618b42129797f17f990ea5a88c6bdc7446000cc361cYabin Cui          << "--post-unwind is only used with `--call-graph dwarf` option.";
619f469c3d7f4466a2a31c3e837969c43c1e3bc4c90Yabin Cui      return false;
620f469c3d7f4466a2a31c3e837969c43c1e3bc4c90Yabin Cui    }
621f469c3d7f4466a2a31c3e837969c43c1e3bc4c90Yabin Cui    if (!unwind_dwarf_callchain_) {
622f469c3d7f4466a2a31c3e837969c43c1e3bc4c90Yabin Cui      LOG(ERROR) << "--post-unwind can't be used with `--no-unwind` option.";
623f469c3d7f4466a2a31c3e837969c43c1e3bc4c90Yabin Cui      return false;
624f469c3d7f4466a2a31c3e837969c43c1e3bc4c90Yabin Cui    }
625f469c3d7f4466a2a31c3e837969c43c1e3bc4c90Yabin Cui  }
626cb84c9885e7a9f82cefba566d74e5c71214ab4c9Yabin Cui
6276da361fd2ff9169954dcfb3588cacc3b4b6df19cYabin Cui  if (fp_callchain_sampling_) {
6286da361fd2ff9169954dcfb3588cacc3b4b6df19cYabin Cui    if (GetBuildArch() == ARCH_ARM) {
6296da361fd2ff9169954dcfb3588cacc3b4b6df19cYabin Cui      LOG(WARNING) << "`--callgraph fp` option doesn't work well on arm architecture, "
6306da361fd2ff9169954dcfb3588cacc3b4b6df19cYabin Cui                   << "consider using `-g` option or profiling on aarch64 architecture.";
6316da361fd2ff9169954dcfb3588cacc3b4b6df19cYabin Cui    }
6326da361fd2ff9169954dcfb3588cacc3b4b6df19cYabin Cui  }
6336da361fd2ff9169954dcfb3588cacc3b4b6df19cYabin Cui
634bc2a1022e1ea0a8c17691594d39fa53021de9166Yabin Cui  if (system_wide_collection_ && event_selection_set_.HasMonitoredTarget()) {
635b42129797f17f990ea5a88c6bdc7446000cc361cYabin Cui    LOG(ERROR) << "Record system wide and existing processes/threads can't be "
636b42129797f17f990ea5a88c6bdc7446000cc361cYabin Cui                  "used at the same time.";
637b032de7a9e1975a838cd6df2e7c8df3c7f70a3ceYabin Cui    return false;
638b032de7a9e1975a838cd6df2e7c8df3c7f70a3ceYabin Cui  }
639b032de7a9e1975a838cd6df2e7c8df3c7f70a3ceYabin Cui
640876809ac10a4b2e8020ad2bc1d28e3d786ef93eaYabin Cui  if (system_wide_collection_ && !IsRoot()) {
641876809ac10a4b2e8020ad2bc1d28e3d786ef93eaYabin Cui    LOG(ERROR) << "System wide profiling needs root privilege.";
642876809ac10a4b2e8020ad2bc1d28e3d786ef93eaYabin Cui    return false;
643876809ac10a4b2e8020ad2bc1d28e3d786ef93eaYabin Cui  }
644876809ac10a4b2e8020ad2bc1d28e3d786ef93eaYabin Cui
645767dd17947f1ae9dd3d02f738d442a23ed76f2f6Yabin Cui  if (dump_symbols_ && can_dump_kernel_symbols_) {
646767dd17947f1ae9dd3d02f738d442a23ed76f2f6Yabin Cui    // No need to dump kernel symbols as we will dump all required symbols.
647767dd17947f1ae9dd3d02f738d442a23ed76f2f6Yabin Cui    can_dump_kernel_symbols_ = false;
648767dd17947f1ae9dd3d02f738d442a23ed76f2f6Yabin Cui  }
649767dd17947f1ae9dd3d02f738d442a23ed76f2f6Yabin Cui
6508a599d7c95f2a8207fb3fe90e824aab1f30abe62Yabin Cui  non_option_args->clear();
6518a599d7c95f2a8207fb3fe90e824aab1f30abe62Yabin Cui  for (; i < args.size(); ++i) {
6528a599d7c95f2a8207fb3fe90e824aab1f30abe62Yabin Cui    non_option_args->push_back(args[i]);
6538a599d7c95f2a8207fb3fe90e824aab1f30abe62Yabin Cui  }
6549759e1b1ce76185aa539aeea2fb1cbd8382156e7Yabin Cui  return true;
6559759e1b1ce76185aa539aeea2fb1cbd8382156e7Yabin Cui}
6569759e1b1ce76185aa539aeea2fb1cbd8382156e7Yabin Cui
657877751bbae11e009070e036ee1cd16e88135fff5Yabin Cuibool RecordCommand::SetEventSelectionFlags() {
658003b245939bae5e86ed53b3c6b333637dbc571b4Yabin Cui  if (use_sample_freq_) {
659003b245939bae5e86ed53b3c6b333637dbc571b4Yabin Cui    event_selection_set_.SetSampleFreq(sample_freq_);
660003b245939bae5e86ed53b3c6b333637dbc571b4Yabin Cui  } else if (use_sample_period_) {
661003b245939bae5e86ed53b3c6b333637dbc571b4Yabin Cui    event_selection_set_.SetSamplePeriod(sample_period_);
662003b245939bae5e86ed53b3c6b333637dbc571b4Yabin Cui  } else {
663003b245939bae5e86ed53b3c6b333637dbc571b4Yabin Cui    event_selection_set_.UseDefaultSampleFreq();
6649759e1b1ce76185aa539aeea2fb1cbd8382156e7Yabin Cui  }
6659759e1b1ce76185aa539aeea2fb1cbd8382156e7Yabin Cui  event_selection_set_.SampleIdAll();
666ddddc06d1f1d15d49e1eb43201b73beb29cf4cdeYabin Cui  if (!event_selection_set_.SetBranchSampling(branch_sampling_)) {
667ddddc06d1f1d15d49e1eb43201b73beb29cf4cdeYabin Cui    return false;
668ddddc06d1f1d15d49e1eb43201b73beb29cf4cdeYabin Cui  }
66976769e502d8f0ebf5d2c81b00246727fb0a59925Yabin Cui  if (fp_callchain_sampling_) {
67076769e502d8f0ebf5d2c81b00246727fb0a59925Yabin Cui    event_selection_set_.EnableFpCallChainSampling();
67176769e502d8f0ebf5d2c81b00246727fb0a59925Yabin Cui  } else if (dwarf_callchain_sampling_) {
672b42129797f17f990ea5a88c6bdc7446000cc361cYabin Cui    if (!event_selection_set_.EnableDwarfCallChainSampling(
673b42129797f17f990ea5a88c6bdc7446000cc361cYabin Cui            dump_stack_size_in_dwarf_sampling_)) {
67476769e502d8f0ebf5d2c81b00246727fb0a59925Yabin Cui      return false;
67576769e502d8f0ebf5d2c81b00246727fb0a59925Yabin Cui    }
6766e8a9a4e52242f82104644bca0318284b3bbdd6bYabin Cui  }
6774be412615fa6b6a7bf0afd5f620b249e98b2cab8Yabin Cui  event_selection_set_.SetInherit(child_inherit_);
678ddddc06d1f1d15d49e1eb43201b73beb29cf4cdeYabin Cui  return true;
6799759e1b1ce76185aa539aeea2fb1cbd8382156e7Yabin Cui}
6809759e1b1ce76185aa539aeea2fb1cbd8382156e7Yabin Cui
681b7f481f59126456b0e708a76f40fa88224f3531bYabin Cuibool RecordCommand::CreateAndInitRecordFile() {
682b7f481f59126456b0e708a76f40fa88224f3531bYabin Cui  record_file_writer_ = CreateRecordFile(record_filename_);
683afdb9cea28340e31142fd66a90c88ed8e18ebbfaYabin Cui  if (record_file_writer_ == nullptr) {
684afdb9cea28340e31142fd66a90c88ed8e18ebbfaYabin Cui    return false;
685afdb9cea28340e31142fd66a90c88ed8e18ebbfaYabin Cui  }
6862d6efe4b167da4e6b77f168b1820239ee65599e2Yabin Cui  // Use first perf_event_attr and first event id to dump mmap and comm records.
687003b245939bae5e86ed53b3c6b333637dbc571b4Yabin Cui  EventAttrWithId attr_id = event_selection_set_.GetEventAttrWithId()[0];
688b42129797f17f990ea5a88c6bdc7446000cc361cYabin Cui  if (!DumpKernelSymbol()) {
689b42129797f17f990ea5a88c6bdc7446000cc361cYabin Cui    return false;
690b42129797f17f990ea5a88c6bdc7446000cc361cYabin Cui  }
6914f41df6f68efc3b9b534014a8cfb6ee8ac4d5c91Yabin Cui  if (!DumpTracingData()) {
6924f41df6f68efc3b9b534014a8cfb6ee8ac4d5c91Yabin Cui    return false;
6934f41df6f68efc3b9b534014a8cfb6ee8ac4d5c91Yabin Cui  }
694003b245939bae5e86ed53b3c6b333637dbc571b4Yabin Cui  if (!DumpKernelAndModuleMmaps(*attr_id.attr, attr_id.ids[0])) {
695b7f481f59126456b0e708a76f40fa88224f3531bYabin Cui    return false;
696b7f481f59126456b0e708a76f40fa88224f3531bYabin Cui  }
697003b245939bae5e86ed53b3c6b333637dbc571b4Yabin Cui  if (!DumpThreadCommAndMmaps(*attr_id.attr, attr_id.ids[0])) {
698b7f481f59126456b0e708a76f40fa88224f3531bYabin Cui    return false;
699b7f481f59126456b0e708a76f40fa88224f3531bYabin Cui  }
700b7f481f59126456b0e708a76f40fa88224f3531bYabin Cui  return true;
701b7f481f59126456b0e708a76f40fa88224f3531bYabin Cui}
702b7f481f59126456b0e708a76f40fa88224f3531bYabin Cui
703b42129797f17f990ea5a88c6bdc7446000cc361cYabin Cuistd::unique_ptr<RecordFileWriter> RecordCommand::CreateRecordFile(
704b42129797f17f990ea5a88c6bdc7446000cc361cYabin Cui    const std::string& filename) {
705b42129797f17f990ea5a88c6bdc7446000cc361cYabin Cui  std::unique_ptr<RecordFileWriter> writer =
706b42129797f17f990ea5a88c6bdc7446000cc361cYabin Cui      RecordFileWriter::CreateInstance(filename);
707b7f481f59126456b0e708a76f40fa88224f3531bYabin Cui  if (writer == nullptr) {
708b7f481f59126456b0e708a76f40fa88224f3531bYabin Cui    return nullptr;
709b7f481f59126456b0e708a76f40fa88224f3531bYabin Cui  }
710afdb9cea28340e31142fd66a90c88ed8e18ebbfaYabin Cui
711003b245939bae5e86ed53b3c6b333637dbc571b4Yabin Cui  if (!writer->WriteAttrSection(event_selection_set_.GetEventAttrWithId())) {
712b7f481f59126456b0e708a76f40fa88224f3531bYabin Cui    return nullptr;
713afdb9cea28340e31142fd66a90c88ed8e18ebbfaYabin Cui  }
714b7f481f59126456b0e708a76f40fa88224f3531bYabin Cui  return writer;
715afdb9cea28340e31142fd66a90c88ed8e18ebbfaYabin Cui}
716afdb9cea28340e31142fd66a90c88ed8e18ebbfaYabin Cui
717b42129797f17f990ea5a88c6bdc7446000cc361cYabin Cuibool RecordCommand::DumpKernelSymbol() {
718b42129797f17f990ea5a88c6bdc7446000cc361cYabin Cui  if (can_dump_kernel_symbols_) {
719b42129797f17f990ea5a88c6bdc7446000cc361cYabin Cui    std::string kallsyms;
720003b245939bae5e86ed53b3c6b333637dbc571b4Yabin Cui    if (event_selection_set_.NeedKernelSymbol() &&
721003b245939bae5e86ed53b3c6b333637dbc571b4Yabin Cui        CheckKernelSymbolAddresses()) {
722b42129797f17f990ea5a88c6bdc7446000cc361cYabin Cui      if (!android::base::ReadFileToString("/proc/kallsyms", &kallsyms)) {
723b42129797f17f990ea5a88c6bdc7446000cc361cYabin Cui        PLOG(ERROR) << "failed to read /proc/kallsyms";
724b42129797f17f990ea5a88c6bdc7446000cc361cYabin Cui        return false;
725b42129797f17f990ea5a88c6bdc7446000cc361cYabin Cui      }
726003b245939bae5e86ed53b3c6b333637dbc571b4Yabin Cui      KernelSymbolRecord r(kallsyms);
727003b245939bae5e86ed53b3c6b333637dbc571b4Yabin Cui      if (!ProcessRecord(&r)) {
728003b245939bae5e86ed53b3c6b333637dbc571b4Yabin Cui        return false;
729003b245939bae5e86ed53b3c6b333637dbc571b4Yabin Cui      }
730b42129797f17f990ea5a88c6bdc7446000cc361cYabin Cui    }
731b42129797f17f990ea5a88c6bdc7446000cc361cYabin Cui  }
732b42129797f17f990ea5a88c6bdc7446000cc361cYabin Cui  return true;
733b42129797f17f990ea5a88c6bdc7446000cc361cYabin Cui}
734b42129797f17f990ea5a88c6bdc7446000cc361cYabin Cui
7354f41df6f68efc3b9b534014a8cfb6ee8ac4d5c91Yabin Cuibool RecordCommand::DumpTracingData() {
736003b245939bae5e86ed53b3c6b333637dbc571b4Yabin Cui  std::vector<const EventType*> tracepoint_event_types =
737003b245939bae5e86ed53b3c6b333637dbc571b4Yabin Cui      event_selection_set_.GetTracepointEvents();
738f897452e2305dc19e9f6689029da74cdf07045f5Yabin Cui  if (tracepoint_event_types.empty() || !CanRecordRawData()) {
739f897452e2305dc19e9f6689029da74cdf07045f5Yabin Cui    return true;  // No need to dump tracing data, or can't do it.
7404f41df6f68efc3b9b534014a8cfb6ee8ac4d5c91Yabin Cui  }
7414f41df6f68efc3b9b534014a8cfb6ee8ac4d5c91Yabin Cui  std::vector<char> tracing_data;
742877751bbae11e009070e036ee1cd16e88135fff5Yabin Cui  if (!GetTracingData(tracepoint_event_types, &tracing_data)) {
7434f41df6f68efc3b9b534014a8cfb6ee8ac4d5c91Yabin Cui    return false;
7444f41df6f68efc3b9b534014a8cfb6ee8ac4d5c91Yabin Cui  }
745190a848fb2d4f502372b2528c55ca1f520e90609Yabin Cui  TracingDataRecord record(tracing_data);
7464f41df6f68efc3b9b534014a8cfb6ee8ac4d5c91Yabin Cui  if (!ProcessRecord(&record)) {
7474f41df6f68efc3b9b534014a8cfb6ee8ac4d5c91Yabin Cui    return false;
7484f41df6f68efc3b9b534014a8cfb6ee8ac4d5c91Yabin Cui  }
7494f41df6f68efc3b9b534014a8cfb6ee8ac4d5c91Yabin Cui  return true;
7504f41df6f68efc3b9b534014a8cfb6ee8ac4d5c91Yabin Cui}
7514f41df6f68efc3b9b534014a8cfb6ee8ac4d5c91Yabin Cui
752877751bbae11e009070e036ee1cd16e88135fff5Yabin Cuibool RecordCommand::DumpKernelAndModuleMmaps(const perf_event_attr& attr,
753b42129797f17f990ea5a88c6bdc7446000cc361cYabin Cui                                             uint64_t event_id) {
7547d59bb49fb47fbc82ef5c77d7aebf7174fd996e1Yabin Cui  KernelMmap kernel_mmap;
7557134f388ccdccb4a5e3025254002a85333a72a70Yabin Cui  std::vector<KernelMmap> module_mmaps;
7567134f388ccdccb4a5e3025254002a85333a72a70Yabin Cui  GetKernelAndModuleMmaps(&kernel_mmap, &module_mmaps);
7577134f388ccdccb4a5e3025254002a85333a72a70Yabin Cui
758190a848fb2d4f502372b2528c55ca1f520e90609Yabin Cui  MmapRecord mmap_record(attr, true, UINT_MAX, 0, kernel_mmap.start_addr,
759767dd17947f1ae9dd3d02f738d442a23ed76f2f6Yabin Cui                         kernel_mmap.len, 0, kernel_mmap.filepath, event_id);
760f469c3d7f4466a2a31c3e837969c43c1e3bc4c90Yabin Cui  if (!ProcessRecord(&mmap_record)) {
7617d59bb49fb47fbc82ef5c77d7aebf7174fd996e1Yabin Cui    return false;
7627d59bb49fb47fbc82ef5c77d7aebf7174fd996e1Yabin Cui  }
7637d59bb49fb47fbc82ef5c77d7aebf7174fd996e1Yabin Cui  for (auto& module_mmap : module_mmaps) {
764190a848fb2d4f502372b2528c55ca1f520e90609Yabin Cui    MmapRecord mmap_record(attr, true, UINT_MAX, 0, module_mmap.start_addr,
765767dd17947f1ae9dd3d02f738d442a23ed76f2f6Yabin Cui                           module_mmap.len, 0, module_mmap.filepath, event_id);
766f469c3d7f4466a2a31c3e837969c43c1e3bc4c90Yabin Cui    if (!ProcessRecord(&mmap_record)) {
7677d59bb49fb47fbc82ef5c77d7aebf7174fd996e1Yabin Cui      return false;
7687d59bb49fb47fbc82ef5c77d7aebf7174fd996e1Yabin Cui    }
7697d59bb49fb47fbc82ef5c77d7aebf7174fd996e1Yabin Cui  }
7707d59bb49fb47fbc82ef5c77d7aebf7174fd996e1Yabin Cui  return true;
7717d59bb49fb47fbc82ef5c77d7aebf7174fd996e1Yabin Cui}
7727d59bb49fb47fbc82ef5c77d7aebf7174fd996e1Yabin Cui
773bc2a1022e1ea0a8c17691594d39fa53021de9166Yabin Cuibool RecordCommand::DumpThreadCommAndMmaps(const perf_event_attr& attr,
774bc2a1022e1ea0a8c17691594d39fa53021de9166Yabin Cui                                           uint64_t event_id) {
7756bf8ca070ef6e2834b21cd0a4271fbc1b6fb92d2Yabin Cui  // Decide which processes and threads to dump.
7760a7a06d2fef05f497497219bf922a5db1980707eYabin Cui  // For system_wide profiling, dump all threads.
7770a7a06d2fef05f497497219bf922a5db1980707eYabin Cui  // For non system wide profiling, build dump_threads.
778bc2a1022e1ea0a8c17691594d39fa53021de9166Yabin Cui  bool all_threads = system_wide_collection_;
779bc2a1022e1ea0a8c17691594d39fa53021de9166Yabin Cui  std::set<pid_t> dump_threads = event_selection_set_.GetMonitoredThreads();
780bc2a1022e1ea0a8c17691594d39fa53021de9166Yabin Cui  for (const auto& pid : event_selection_set_.GetMonitoredProcesses()) {
781bc2a1022e1ea0a8c17691594d39fa53021de9166Yabin Cui    std::vector<pid_t> tids = GetThreadsInProcess(pid);
782bc2a1022e1ea0a8c17691594d39fa53021de9166Yabin Cui    dump_threads.insert(tids.begin(), tids.end());
7836bf8ca070ef6e2834b21cd0a4271fbc1b6fb92d2Yabin Cui  }
7840a7a06d2fef05f497497219bf922a5db1980707eYabin Cui
7850a7a06d2fef05f497497219bf922a5db1980707eYabin Cui  // Collect processes to dump.
7860a7a06d2fef05f497497219bf922a5db1980707eYabin Cui  std::vector<pid_t> processes;
7870a7a06d2fef05f497497219bf922a5db1980707eYabin Cui  if (all_threads) {
7880a7a06d2fef05f497497219bf922a5db1980707eYabin Cui    processes = GetAllProcesses();
7890a7a06d2fef05f497497219bf922a5db1980707eYabin Cui  } else {
7900a7a06d2fef05f497497219bf922a5db1980707eYabin Cui    std::set<pid_t> process_set;
7910a7a06d2fef05f497497219bf922a5db1980707eYabin Cui    for (const auto& tid : dump_threads) {
7920a7a06d2fef05f497497219bf922a5db1980707eYabin Cui      pid_t pid;
7930a7a06d2fef05f497497219bf922a5db1980707eYabin Cui      if (!GetProcessForThread(tid, &pid)) {
7940a7a06d2fef05f497497219bf922a5db1980707eYabin Cui        continue;
7950a7a06d2fef05f497497219bf922a5db1980707eYabin Cui      }
7960a7a06d2fef05f497497219bf922a5db1980707eYabin Cui      process_set.insert(pid);
7976bf8ca070ef6e2834b21cd0a4271fbc1b6fb92d2Yabin Cui    }
7980a7a06d2fef05f497497219bf922a5db1980707eYabin Cui    processes.insert(processes.end(), process_set.begin(), process_set.end());
7996bf8ca070ef6e2834b21cd0a4271fbc1b6fb92d2Yabin Cui  }
8006bf8ca070ef6e2834b21cd0a4271fbc1b6fb92d2Yabin Cui
8010a7a06d2fef05f497497219bf922a5db1980707eYabin Cui  // Dump each process and its threads.
8020a7a06d2fef05f497497219bf922a5db1980707eYabin Cui  for (auto& pid : processes) {
8030a7a06d2fef05f497497219bf922a5db1980707eYabin Cui    // Dump mmap records.
80441d4ba9f6f2781155a0519a784606d5382cda88fYabin Cui    std::vector<ThreadMmap> thread_mmaps;
8050a7a06d2fef05f497497219bf922a5db1980707eYabin Cui    if (!GetThreadMmapsInProcess(pid, &thread_mmaps)) {
8060a7a06d2fef05f497497219bf922a5db1980707eYabin Cui      // The process may exit before we get its info.
80741d4ba9f6f2781155a0519a784606d5382cda88fYabin Cui      continue;
80841d4ba9f6f2781155a0519a784606d5382cda88fYabin Cui    }
8090a7a06d2fef05f497497219bf922a5db1980707eYabin Cui    for (const auto& map : thread_mmaps) {
8100a7a06d2fef05f497497219bf922a5db1980707eYabin Cui      if (map.executable == 0) {
81141d4ba9f6f2781155a0519a784606d5382cda88fYabin Cui        continue;  // No need to dump non-executable mmap info.
8127d59bb49fb47fbc82ef5c77d7aebf7174fd996e1Yabin Cui      }
8130a7a06d2fef05f497497219bf922a5db1980707eYabin Cui      MmapRecord record(attr, false, pid, pid, map.start_addr, map.len,
8140a7a06d2fef05f497497219bf922a5db1980707eYabin Cui                        map.pgoff, map.name, event_id);
815f469c3d7f4466a2a31c3e837969c43c1e3bc4c90Yabin Cui      if (!ProcessRecord(&record)) {
81641d4ba9f6f2781155a0519a784606d5382cda88fYabin Cui        return false;
8177d59bb49fb47fbc82ef5c77d7aebf7174fd996e1Yabin Cui      }
8187d59bb49fb47fbc82ef5c77d7aebf7174fd996e1Yabin Cui    }
8190a7a06d2fef05f497497219bf922a5db1980707eYabin Cui    // Dump process name.
8200a7a06d2fef05f497497219bf922a5db1980707eYabin Cui    std::string name;
8210a7a06d2fef05f497497219bf922a5db1980707eYabin Cui    if (GetThreadName(pid, &name)) {
8220a7a06d2fef05f497497219bf922a5db1980707eYabin Cui      CommRecord record(attr, pid, pid, name, event_id, 0);
8230a7a06d2fef05f497497219bf922a5db1980707eYabin Cui      if (!ProcessRecord(&record)) {
8240a7a06d2fef05f497497219bf922a5db1980707eYabin Cui        return false;
8250a7a06d2fef05f497497219bf922a5db1980707eYabin Cui      }
82641d4ba9f6f2781155a0519a784606d5382cda88fYabin Cui    }
8270a7a06d2fef05f497497219bf922a5db1980707eYabin Cui    // Dump thread info.
8280a7a06d2fef05f497497219bf922a5db1980707eYabin Cui    std::vector<pid_t> threads = GetThreadsInProcess(pid);
8290a7a06d2fef05f497497219bf922a5db1980707eYabin Cui    for (const auto& tid : threads) {
8300a7a06d2fef05f497497219bf922a5db1980707eYabin Cui      if (tid == pid) {
8310a7a06d2fef05f497497219bf922a5db1980707eYabin Cui        continue;
8320a7a06d2fef05f497497219bf922a5db1980707eYabin Cui      }
8330a7a06d2fef05f497497219bf922a5db1980707eYabin Cui      if (all_threads || dump_threads.find(tid) != dump_threads.end()) {
8340a7a06d2fef05f497497219bf922a5db1980707eYabin Cui        ForkRecord fork_record(attr, pid, tid, pid, pid, event_id);
8350a7a06d2fef05f497497219bf922a5db1980707eYabin Cui        if (!ProcessRecord(&fork_record)) {
8360a7a06d2fef05f497497219bf922a5db1980707eYabin Cui          return false;
8370a7a06d2fef05f497497219bf922a5db1980707eYabin Cui        }
8380a7a06d2fef05f497497219bf922a5db1980707eYabin Cui        if (GetThreadName(tid, &name)) {
8390a7a06d2fef05f497497219bf922a5db1980707eYabin Cui          CommRecord comm_record(attr, pid, tid, name, event_id, 0);
8400a7a06d2fef05f497497219bf922a5db1980707eYabin Cui          if (!ProcessRecord(&comm_record)) {
8410a7a06d2fef05f497497219bf922a5db1980707eYabin Cui            return false;
8420a7a06d2fef05f497497219bf922a5db1980707eYabin Cui          }
8430a7a06d2fef05f497497219bf922a5db1980707eYabin Cui        }
8440a7a06d2fef05f497497219bf922a5db1980707eYabin Cui      }
84541d4ba9f6f2781155a0519a784606d5382cda88fYabin Cui    }
84641d4ba9f6f2781155a0519a784606d5382cda88fYabin Cui  }
8477d59bb49fb47fbc82ef5c77d7aebf7174fd996e1Yabin Cui  return true;
8488f6225147c5b6cb2159a7f5cb0dab952ee0759dfYabin Cui}
8498f6225147c5b6cb2159a7f5cb0dab952ee0759dfYabin Cui
850f469c3d7f4466a2a31c3e837969c43c1e3bc4c90Yabin Cuibool RecordCommand::ProcessRecord(Record* record) {
851003b245939bae5e86ed53b3c6b333637dbc571b4Yabin Cui  if (system_wide_collection_ && record->type() == PERF_RECORD_SAMPLE) {
85257fb220017ae91f028ff2fbc819c07849c7c4f58Yabin Cui    auto& r = *static_cast<SampleRecord*>(record);
85357fb220017ae91f028ff2fbc819c07849c7c4f58Yabin Cui    // Omit samples get before start sampling time.
85457fb220017ae91f028ff2fbc819c07849c7c4f58Yabin Cui    if (r.time_data.time < start_sampling_time_in_ns_) {
85557fb220017ae91f028ff2fbc819c07849c7c4f58Yabin Cui      return true;
85657fb220017ae91f028ff2fbc819c07849c7c4f58Yabin Cui    }
85757fb220017ae91f028ff2fbc819c07849c7c4f58Yabin Cui  }
858b1a885b014540a2f7798b5a35ea0f0ec150d93eeYabin Cui  UpdateRecordForEmbeddedElfPath(record);
859f469c3d7f4466a2a31c3e837969c43c1e3bc4c90Yabin Cui  if (unwind_dwarf_callchain_ && !post_unwind_) {
860aba7e29f163b4a332a9d3fe9973d82c7d0db148fYabin Cui    thread_tree_.Update(*record);
861767dd17947f1ae9dd3d02f738d442a23ed76f2f6Yabin Cui    if (!UnwindRecord(record)) {
862767dd17947f1ae9dd3d02f738d442a23ed76f2f6Yabin Cui      return false;
863767dd17947f1ae9dd3d02f738d442a23ed76f2f6Yabin Cui    }
864f469c3d7f4466a2a31c3e837969c43c1e3bc4c90Yabin Cui  }
865b1a885b014540a2f7798b5a35ea0f0ec150d93eeYabin Cui  if (record->type() == PERF_RECORD_SAMPLE) {
866b1a885b014540a2f7798b5a35ea0f0ec150d93eeYabin Cui    sample_record_count_++;
867e5adc13cda8dd413f86d0dc8d187052efcaff7e5Yabin Cui  } else if (record->type() == PERF_RECORD_LOST) {
868e5adc13cda8dd413f86d0dc8d187052efcaff7e5Yabin Cui    lost_record_count_ += static_cast<LostRecord*>(record)->lost;
869b1a885b014540a2f7798b5a35ea0f0ec150d93eeYabin Cui  }
8701761a271faf98050891ba6e918993225782c811aYabin Cui  bool result = record_file_writer_->WriteRecord(*record);
871f469c3d7f4466a2a31c3e837969c43c1e3bc4c90Yabin Cui  return result;
872f469c3d7f4466a2a31c3e837969c43c1e3bc4c90Yabin Cui}
873f469c3d7f4466a2a31c3e837969c43c1e3bc4c90Yabin Cui
874b42129797f17f990ea5a88c6bdc7446000cc361cYabin Cuitemplate <class RecordType>
875b1a885b014540a2f7798b5a35ea0f0ec150d93eeYabin Cuivoid UpdateMmapRecordForEmbeddedElfPath(RecordType* record) {
876b1a885b014540a2f7798b5a35ea0f0ec150d93eeYabin Cui  RecordType& r = *record;
877190a848fb2d4f502372b2528c55ca1f520e90609Yabin Cui  if (!r.InKernel() && r.data->pgoff != 0) {
878b1a885b014540a2f7798b5a35ea0f0ec150d93eeYabin Cui    // For the case of a shared library "foobar.so" embedded
879b1a885b014540a2f7798b5a35ea0f0ec150d93eeYabin Cui    // inside an APK, we rewrite the original MMAP from
880b1a885b014540a2f7798b5a35ea0f0ec150d93eeYabin Cui    // ["path.apk" offset=X] to ["path.apk!/foobar.so" offset=W]
881b1a885b014540a2f7798b5a35ea0f0ec150d93eeYabin Cui    // so as to make the library name explicit. This update is
882b1a885b014540a2f7798b5a35ea0f0ec150d93eeYabin Cui    // done here (as part of the record operation) as opposed to
883b1a885b014540a2f7798b5a35ea0f0ec150d93eeYabin Cui    // on the host during the report, since we want to report
884b1a885b014540a2f7798b5a35ea0f0ec150d93eeYabin Cui    // the correct library name even if the the APK in question
885b1a885b014540a2f7798b5a35ea0f0ec150d93eeYabin Cui    // is not present on the host. The new offset W is
886b1a885b014540a2f7798b5a35ea0f0ec150d93eeYabin Cui    // calculated to be with respect to the start of foobar.so,
887b1a885b014540a2f7798b5a35ea0f0ec150d93eeYabin Cui    // not to the start of path.apk.
888b42129797f17f990ea5a88c6bdc7446000cc361cYabin Cui    EmbeddedElf* ee =
889190a848fb2d4f502372b2528c55ca1f520e90609Yabin Cui        ApkInspector::FindElfInApkByOffset(r.filename, r.data->pgoff);
890b1a885b014540a2f7798b5a35ea0f0ec150d93eeYabin Cui    if (ee != nullptr) {
891b1a885b014540a2f7798b5a35ea0f0ec150d93eeYabin Cui      // Compute new offset relative to start of elf in APK.
892190a848fb2d4f502372b2528c55ca1f520e90609Yabin Cui      auto data = *r.data;
893190a848fb2d4f502372b2528c55ca1f520e90609Yabin Cui      data.pgoff -= ee->entry_offset();
894190a848fb2d4f502372b2528c55ca1f520e90609Yabin Cui      r.SetDataAndFilename(data, GetUrlInApk(r.filename, ee->entry_name()));
895b1a885b014540a2f7798b5a35ea0f0ec150d93eeYabin Cui    }
896b1a885b014540a2f7798b5a35ea0f0ec150d93eeYabin Cui  }
897b1a885b014540a2f7798b5a35ea0f0ec150d93eeYabin Cui}
898b1a885b014540a2f7798b5a35ea0f0ec150d93eeYabin Cui
899b1a885b014540a2f7798b5a35ea0f0ec150d93eeYabin Cuivoid RecordCommand::UpdateRecordForEmbeddedElfPath(Record* record) {
900b1a885b014540a2f7798b5a35ea0f0ec150d93eeYabin Cui  if (record->type() == PERF_RECORD_MMAP) {
901b1a885b014540a2f7798b5a35ea0f0ec150d93eeYabin Cui    UpdateMmapRecordForEmbeddedElfPath(static_cast<MmapRecord*>(record));
902b1a885b014540a2f7798b5a35ea0f0ec150d93eeYabin Cui  } else if (record->type() == PERF_RECORD_MMAP2) {
903b1a885b014540a2f7798b5a35ea0f0ec150d93eeYabin Cui    UpdateMmapRecordForEmbeddedElfPath(static_cast<Mmap2Record*>(record));
904b1a885b014540a2f7798b5a35ea0f0ec150d93eeYabin Cui  }
905b1a885b014540a2f7798b5a35ea0f0ec150d93eeYabin Cui}
906b1a885b014540a2f7798b5a35ea0f0ec150d93eeYabin Cui
907767dd17947f1ae9dd3d02f738d442a23ed76f2f6Yabin Cuibool RecordCommand::UnwindRecord(Record* record) {
908b7f481f59126456b0e708a76f40fa88224f3531bYabin Cui  if (record->type() == PERF_RECORD_SAMPLE) {
909f469c3d7f4466a2a31c3e837969c43c1e3bc4c90Yabin Cui    SampleRecord& r = *static_cast<SampleRecord*>(record);
910b42129797f17f990ea5a88c6bdc7446000cc361cYabin Cui    if ((r.sample_type & PERF_SAMPLE_CALLCHAIN) &&
911b42129797f17f990ea5a88c6bdc7446000cc361cYabin Cui        (r.sample_type & PERF_SAMPLE_REGS_USER) &&
912b42129797f17f990ea5a88c6bdc7446000cc361cYabin Cui        (r.regs_user_data.reg_mask != 0) &&
913b42129797f17f990ea5a88c6bdc7446000cc361cYabin Cui        (r.sample_type & PERF_SAMPLE_STACK_USER) &&
914190a848fb2d4f502372b2528c55ca1f520e90609Yabin Cui        (r.GetValidStackSize() > 0)) {
915b42129797f17f990ea5a88c6bdc7446000cc361cYabin Cui      ThreadEntry* thread =
916b42129797f17f990ea5a88c6bdc7446000cc361cYabin Cui          thread_tree_.FindThreadOrNew(r.tid_data.pid, r.tid_data.tid);
917417df291499b37f63fa9b930e081d80a25bf38ecYabin Cui      RegSet regs = CreateRegSet(r.regs_user_data.abi,
918417df291499b37f63fa9b930e081d80a25bf38ecYabin Cui                                 r.regs_user_data.reg_mask,
919417df291499b37f63fa9b930e081d80a25bf38ecYabin Cui                                 r.regs_user_data.regs);
920b42129797f17f990ea5a88c6bdc7446000cc361cYabin Cui      // Normally do strict arch check when unwinding stack. But allow unwinding
921b42129797f17f990ea5a88c6bdc7446000cc361cYabin Cui      // 32-bit processes on 64-bit devices for system wide profiling.
9224b6720d137c15b9485318255e89ffcd3c76ab579Yabin Cui      bool strict_arch_check = !system_wide_collection_;
923b42129797f17f990ea5a88c6bdc7446000cc361cYabin Cui      std::vector<uint64_t> unwind_ips =
924417df291499b37f63fa9b930e081d80a25bf38ecYabin Cui          UnwindCallChain(r.regs_user_data.abi, *thread, regs,
925417df291499b37f63fa9b930e081d80a25bf38ecYabin Cui                          r.stack_user_data.data,
926cf31e9d83d3fff0c0970aa344366136e4d5126a7Yabin Cui                          r.GetValidStackSize(), strict_arch_check);
927190a848fb2d4f502372b2528c55ca1f520e90609Yabin Cui      r.ReplaceRegAndStackWithCallChain(unwind_ips);
928f469c3d7f4466a2a31c3e837969c43c1e3bc4c90Yabin Cui    }
929f469c3d7f4466a2a31c3e837969c43c1e3bc4c90Yabin Cui  }
930767dd17947f1ae9dd3d02f738d442a23ed76f2f6Yabin Cui  return true;
931f469c3d7f4466a2a31c3e837969c43c1e3bc4c90Yabin Cui}
932f469c3d7f4466a2a31c3e837969c43c1e3bc4c90Yabin Cui
933b7f481f59126456b0e708a76f40fa88224f3531bYabin Cuibool RecordCommand::PostUnwind(const std::vector<std::string>& args) {
934767dd17947f1ae9dd3d02f738d442a23ed76f2f6Yabin Cui  thread_tree_.ClearThreadAndMap();
935b42129797f17f990ea5a88c6bdc7446000cc361cYabin Cui  std::unique_ptr<RecordFileReader> reader =
936b42129797f17f990ea5a88c6bdc7446000cc361cYabin Cui      RecordFileReader::CreateInstance(record_filename_);
937b7f481f59126456b0e708a76f40fa88224f3531bYabin Cui  if (reader == nullptr) {
938cb84c9885e7a9f82cefba566d74e5c71214ab4c9Yabin Cui    return false;
939cb84c9885e7a9f82cefba566d74e5c71214ab4c9Yabin Cui  }
940b7f481f59126456b0e708a76f40fa88224f3531bYabin Cui  std::string tmp_filename = record_filename_ + ".tmp";
941b7f481f59126456b0e708a76f40fa88224f3531bYabin Cui  record_file_writer_ = CreateRecordFile(tmp_filename);
942b7f481f59126456b0e708a76f40fa88224f3531bYabin Cui  if (record_file_writer_ == nullptr) {
943b7f481f59126456b0e708a76f40fa88224f3531bYabin Cui    return false;
944b7f481f59126456b0e708a76f40fa88224f3531bYabin Cui  }
945b7f481f59126456b0e708a76f40fa88224f3531bYabin Cui  bool result = reader->ReadDataSection(
946b7f481f59126456b0e708a76f40fa88224f3531bYabin Cui      [this](std::unique_ptr<Record> record) {
947767dd17947f1ae9dd3d02f738d442a23ed76f2f6Yabin Cui        thread_tree_.Update(*record);
948767dd17947f1ae9dd3d02f738d442a23ed76f2f6Yabin Cui        if (!UnwindRecord(record.get())) {
949767dd17947f1ae9dd3d02f738d442a23ed76f2f6Yabin Cui          return false;
950767dd17947f1ae9dd3d02f738d442a23ed76f2f6Yabin Cui        }
9511761a271faf98050891ba6e918993225782c811aYabin Cui        return record_file_writer_->WriteRecord(*record);
952b7f481f59126456b0e708a76f40fa88224f3531bYabin Cui      },
953b7f481f59126456b0e708a76f40fa88224f3531bYabin Cui      false);
954b7f481f59126456b0e708a76f40fa88224f3531bYabin Cui  if (!result) {
955b7f481f59126456b0e708a76f40fa88224f3531bYabin Cui    return false;
956b7f481f59126456b0e708a76f40fa88224f3531bYabin Cui  }
957b7f481f59126456b0e708a76f40fa88224f3531bYabin Cui  if (!DumpAdditionalFeatures(args)) {
958b7f481f59126456b0e708a76f40fa88224f3531bYabin Cui    return false;
959b7f481f59126456b0e708a76f40fa88224f3531bYabin Cui  }
960b7f481f59126456b0e708a76f40fa88224f3531bYabin Cui  if (!record_file_writer_->Close()) {
961b7f481f59126456b0e708a76f40fa88224f3531bYabin Cui    return false;
962cb84c9885e7a9f82cefba566d74e5c71214ab4c9Yabin Cui  }
963b7f481f59126456b0e708a76f40fa88224f3531bYabin Cui
964b7f481f59126456b0e708a76f40fa88224f3531bYabin Cui  if (unlink(record_filename_.c_str()) != 0) {
965b7f481f59126456b0e708a76f40fa88224f3531bYabin Cui    PLOG(ERROR) << "failed to remove " << record_filename_;
966b7f481f59126456b0e708a76f40fa88224f3531bYabin Cui    return false;
967b7f481f59126456b0e708a76f40fa88224f3531bYabin Cui  }
968b7f481f59126456b0e708a76f40fa88224f3531bYabin Cui  if (rename(tmp_filename.c_str(), record_filename_.c_str()) != 0) {
969b42129797f17f990ea5a88c6bdc7446000cc361cYabin Cui    PLOG(ERROR) << "failed to rename " << tmp_filename << " to "
970b42129797f17f990ea5a88c6bdc7446000cc361cYabin Cui                << record_filename_;
971b7f481f59126456b0e708a76f40fa88224f3531bYabin Cui    return false;
972b7f481f59126456b0e708a76f40fa88224f3531bYabin Cui  }
973b7f481f59126456b0e708a76f40fa88224f3531bYabin Cui  return true;
974cb84c9885e7a9f82cefba566d74e5c71214ab4c9Yabin Cui}
975cb84c9885e7a9f82cefba566d74e5c71214ab4c9Yabin Cui
976b42129797f17f990ea5a88c6bdc7446000cc361cYabin Cuibool RecordCommand::DumpAdditionalFeatures(
977b42129797f17f990ea5a88c6bdc7446000cc361cYabin Cui    const std::vector<std::string>& args) {
978aba7e29f163b4a332a9d3fe9973d82c7d0db148fYabin Cui  // Read data section of perf.data to collect hit file information.
979aba7e29f163b4a332a9d3fe9973d82c7d0db148fYabin Cui  thread_tree_.ClearThreadAndMap();
980a90503d0ef3db354505c745071f925156e849e12Yabin Cui  if (CheckKernelSymbolAddresses()) {
981a90503d0ef3db354505c745071f925156e849e12Yabin Cui    Dso::ReadKernelSymbolsFromProc();
982a90503d0ef3db354505c745071f925156e849e12Yabin Cui  }
983aba7e29f163b4a332a9d3fe9973d82c7d0db148fYabin Cui  auto callback = [&](const Record* r) {
984aba7e29f163b4a332a9d3fe9973d82c7d0db148fYabin Cui    thread_tree_.Update(*r);
985aba7e29f163b4a332a9d3fe9973d82c7d0db148fYabin Cui    if (r->type() == PERF_RECORD_SAMPLE) {
986aba7e29f163b4a332a9d3fe9973d82c7d0db148fYabin Cui      CollectHitFileInfo(*reinterpret_cast<const SampleRecord*>(r));
987aba7e29f163b4a332a9d3fe9973d82c7d0db148fYabin Cui    }
988aba7e29f163b4a332a9d3fe9973d82c7d0db148fYabin Cui  };
989aba7e29f163b4a332a9d3fe9973d82c7d0db148fYabin Cui  if (!record_file_writer_->ReadDataSection(callback)) {
990aba7e29f163b4a332a9d3fe9973d82c7d0db148fYabin Cui    return false;
991aba7e29f163b4a332a9d3fe9973d82c7d0db148fYabin Cui  }
992aba7e29f163b4a332a9d3fe9973d82c7d0db148fYabin Cui
993df6333c5f5a34d4b7853c4671a53fcfd9e5a0b88Yabin Cui  size_t feature_count = 5;
994c5b4a3106a0845d1bd8fd2c1b1c724eeb719ec62Yabin Cui  if (branch_sampling_) {
995c5b4a3106a0845d1bd8fd2c1b1c724eeb719ec62Yabin Cui    feature_count++;
996c5b4a3106a0845d1bd8fd2c1b1c724eeb719ec62Yabin Cui  }
997c5b4a3106a0845d1bd8fd2c1b1c724eeb719ec62Yabin Cui  if (dump_symbols_) {
998c5b4a3106a0845d1bd8fd2c1b1c724eeb719ec62Yabin Cui    feature_count++;
999c5b4a3106a0845d1bd8fd2c1b1c724eeb719ec62Yabin Cui  }
1000c5b4a3106a0845d1bd8fd2c1b1c724eeb719ec62Yabin Cui  if (!record_file_writer_->BeginWriteFeatures(feature_count)) {
10018f6225147c5b6cb2159a7f5cb0dab952ee0759dfYabin Cui    return false;
10028f6225147c5b6cb2159a7f5cb0dab952ee0759dfYabin Cui  }
10036afc7e17d39ab294bdf625076777443a6b4c8e18Yabin Cui  if (!DumpBuildIdFeature()) {
10046afc7e17d39ab294bdf625076777443a6b4c8e18Yabin Cui    return false;
10056afc7e17d39ab294bdf625076777443a6b4c8e18Yabin Cui  }
1006c5b4a3106a0845d1bd8fd2c1b1c724eeb719ec62Yabin Cui  if (dump_symbols_ && !DumpFileFeature()) {
1007c5b4a3106a0845d1bd8fd2c1b1c724eeb719ec62Yabin Cui    return false;
1008c5b4a3106a0845d1bd8fd2c1b1c724eeb719ec62Yabin Cui  }
100976769e502d8f0ebf5d2c81b00246727fb0a59925Yabin Cui  utsname uname_buf;
101076769e502d8f0ebf5d2c81b00246727fb0a59925Yabin Cui  if (TEMP_FAILURE_RETRY(uname(&uname_buf)) != 0) {
101176769e502d8f0ebf5d2c81b00246727fb0a59925Yabin Cui    PLOG(ERROR) << "uname() failed";
101276769e502d8f0ebf5d2c81b00246727fb0a59925Yabin Cui    return false;
101376769e502d8f0ebf5d2c81b00246727fb0a59925Yabin Cui  }
1014b42129797f17f990ea5a88c6bdc7446000cc361cYabin Cui  if (!record_file_writer_->WriteFeatureString(PerfFileFormat::FEAT_OSRELEASE,
1015b42129797f17f990ea5a88c6bdc7446000cc361cYabin Cui                                               uname_buf.release)) {
101676769e502d8f0ebf5d2c81b00246727fb0a59925Yabin Cui    return false;
101776769e502d8f0ebf5d2c81b00246727fb0a59925Yabin Cui  }
1018b42129797f17f990ea5a88c6bdc7446000cc361cYabin Cui  if (!record_file_writer_->WriteFeatureString(PerfFileFormat::FEAT_ARCH,
1019b42129797f17f990ea5a88c6bdc7446000cc361cYabin Cui                                               uname_buf.machine)) {
102076769e502d8f0ebf5d2c81b00246727fb0a59925Yabin Cui    return false;
102176769e502d8f0ebf5d2c81b00246727fb0a59925Yabin Cui  }
102276769e502d8f0ebf5d2c81b00246727fb0a59925Yabin Cui
1023f30c96ff34a131a1c163aae746f7bb13e225371bElliott Hughes  std::string exec_path = android::base::GetExecutablePath();
1024f30c96ff34a131a1c163aae746f7bb13e225371bElliott Hughes  if (exec_path.empty()) exec_path = "simpleperf";
1025d713f959ec1fe07ed993e2c9f4166b52aa98a58cYabin Cui  std::vector<std::string> cmdline;
1026d713f959ec1fe07ed993e2c9f4166b52aa98a58cYabin Cui  cmdline.push_back(exec_path);
1027d713f959ec1fe07ed993e2c9f4166b52aa98a58cYabin Cui  cmdline.push_back("record");
1028d713f959ec1fe07ed993e2c9f4166b52aa98a58cYabin Cui  cmdline.insert(cmdline.end(), args.begin(), args.end());
1029d713f959ec1fe07ed993e2c9f4166b52aa98a58cYabin Cui  if (!record_file_writer_->WriteCmdlineFeature(cmdline)) {
1030d713f959ec1fe07ed993e2c9f4166b52aa98a58cYabin Cui    return false;
1031d713f959ec1fe07ed993e2c9f4166b52aa98a58cYabin Cui  }
1032b42129797f17f990ea5a88c6bdc7446000cc361cYabin Cui  if (branch_sampling_ != 0 &&
1033b42129797f17f990ea5a88c6bdc7446000cc361cYabin Cui      !record_file_writer_->WriteBranchStackFeature()) {
10346afc7e17d39ab294bdf625076777443a6b4c8e18Yabin Cui    return false;
10356afc7e17d39ab294bdf625076777443a6b4c8e18Yabin Cui  }
1036df6333c5f5a34d4b7853c4671a53fcfd9e5a0b88Yabin Cui
1037df6333c5f5a34d4b7853c4671a53fcfd9e5a0b88Yabin Cui  std::unordered_map<std::string, std::string> info_map;
1038df6333c5f5a34d4b7853c4671a53fcfd9e5a0b88Yabin Cui  info_map["simpleperf_version"] = GetSimpleperfVersion();
1039df6333c5f5a34d4b7853c4671a53fcfd9e5a0b88Yabin Cui  if (!record_file_writer_->WriteMetaInfoFeature(info_map)) {
1040df6333c5f5a34d4b7853c4671a53fcfd9e5a0b88Yabin Cui    return false;
1041df6333c5f5a34d4b7853c4671a53fcfd9e5a0b88Yabin Cui  }
1042df6333c5f5a34d4b7853c4671a53fcfd9e5a0b88Yabin Cui
1043c5b4a3106a0845d1bd8fd2c1b1c724eeb719ec62Yabin Cui  if (!record_file_writer_->EndWriteFeatures()) {
1044c5b4a3106a0845d1bd8fd2c1b1c724eeb719ec62Yabin Cui    return false;
1045c5b4a3106a0845d1bd8fd2c1b1c724eeb719ec62Yabin Cui  }
10466afc7e17d39ab294bdf625076777443a6b4c8e18Yabin Cui  return true;
10478f6225147c5b6cb2159a7f5cb0dab952ee0759dfYabin Cui}
10488f6225147c5b6cb2159a7f5cb0dab952ee0759dfYabin Cui
1049f79f07e13c56f7ca3be1435cea7f8861daf7efaaYabin Cuibool RecordCommand::DumpBuildIdFeature() {
10508f6225147c5b6cb2159a7f5cb0dab952ee0759dfYabin Cui  std::vector<BuildIdRecord> build_id_records;
10518f6225147c5b6cb2159a7f5cb0dab952ee0759dfYabin Cui  BuildId build_id;
105278fddd140931adf704061f82e3c9fcb03362f8d0Yabin Cui  std::vector<Dso*> dso_v = thread_tree_.GetAllDsos();
105378fddd140931adf704061f82e3c9fcb03362f8d0Yabin Cui  for (Dso* dso : dso_v) {
105416501ffbd73483c498dde1ea4ad2670da7c9df55Yabin Cui    if (!dso->HasDumpId()) {
105578fddd140931adf704061f82e3c9fcb03362f8d0Yabin Cui      continue;
105678fddd140931adf704061f82e3c9fcb03362f8d0Yabin Cui    }
105778fddd140931adf704061f82e3c9fcb03362f8d0Yabin Cui    if (dso->type() == DSO_KERNEL) {
10588f6225147c5b6cb2159a7f5cb0dab952ee0759dfYabin Cui      if (!GetKernelBuildId(&build_id)) {
10598f6225147c5b6cb2159a7f5cb0dab952ee0759dfYabin Cui        continue;
10608f6225147c5b6cb2159a7f5cb0dab952ee0759dfYabin Cui      }
10610f6df013be40459a1b4013bdad8ec0a82c18ce9aYabin Cui      build_id_records.push_back(
106278fddd140931adf704061f82e3c9fcb03362f8d0Yabin Cui          BuildIdRecord(true, UINT_MAX, build_id, dso->Path()));
106378fddd140931adf704061f82e3c9fcb03362f8d0Yabin Cui    } else if (dso->type() == DSO_KERNEL_MODULE) {
106478fddd140931adf704061f82e3c9fcb03362f8d0Yabin Cui      std::string path = dso->Path();
106573d8078e6e5ef92b2301386ce96260bd99efacbbYabin Cui      std::string module_name = basename(&path[0]);
10668f6225147c5b6cb2159a7f5cb0dab952ee0759dfYabin Cui      if (android::base::EndsWith(module_name, ".ko")) {
10678f6225147c5b6cb2159a7f5cb0dab952ee0759dfYabin Cui        module_name = module_name.substr(0, module_name.size() - 3);
10688f6225147c5b6cb2159a7f5cb0dab952ee0759dfYabin Cui      }
10698f6225147c5b6cb2159a7f5cb0dab952ee0759dfYabin Cui      if (!GetModuleBuildId(module_name, &build_id)) {
10708f6225147c5b6cb2159a7f5cb0dab952ee0759dfYabin Cui        LOG(DEBUG) << "can't read build_id for module " << module_name;
10718f6225147c5b6cb2159a7f5cb0dab952ee0759dfYabin Cui        continue;
10728f6225147c5b6cb2159a7f5cb0dab952ee0759dfYabin Cui      }
107378fddd140931adf704061f82e3c9fcb03362f8d0Yabin Cui      build_id_records.push_back(BuildIdRecord(true, UINT_MAX, build_id, path));
1074b1a885b014540a2f7798b5a35ea0f0ec150d93eeYabin Cui    } else {
107578fddd140931adf704061f82e3c9fcb03362f8d0Yabin Cui      if (dso->Path() == DEFAULT_EXECNAME_FOR_THREAD_MMAP) {
1076f831e6d12ca2298cb34b155a9d91ef002d0482f3Than McIntosh        continue;
1077f831e6d12ca2298cb34b155a9d91ef002d0482f3Than McIntosh      }
107878fddd140931adf704061f82e3c9fcb03362f8d0Yabin Cui      auto tuple = SplitUrlInApk(dso->Path());
107978fddd140931adf704061f82e3c9fcb03362f8d0Yabin Cui      if (std::get<0>(tuple)) {
108078fddd140931adf704061f82e3c9fcb03362f8d0Yabin Cui        ElfStatus result = GetBuildIdFromApkFile(std::get<1>(tuple),
108178fddd140931adf704061f82e3c9fcb03362f8d0Yabin Cui                                                 std::get<2>(tuple), &build_id);
108278fddd140931adf704061f82e3c9fcb03362f8d0Yabin Cui        if (result != ElfStatus::NO_ERROR) {
108378fddd140931adf704061f82e3c9fcb03362f8d0Yabin Cui          LOG(DEBUG) << "can't read build_id from file " << dso->Path() << ": "
108478fddd140931adf704061f82e3c9fcb03362f8d0Yabin Cui                     << result;
108578fddd140931adf704061f82e3c9fcb03362f8d0Yabin Cui          continue;
108678fddd140931adf704061f82e3c9fcb03362f8d0Yabin Cui        }
108778fddd140931adf704061f82e3c9fcb03362f8d0Yabin Cui      } else {
108878fddd140931adf704061f82e3c9fcb03362f8d0Yabin Cui        ElfStatus result = GetBuildIdFromElfFile(dso->Path(), &build_id);
108978fddd140931adf704061f82e3c9fcb03362f8d0Yabin Cui        if (result != ElfStatus::NO_ERROR) {
109078fddd140931adf704061f82e3c9fcb03362f8d0Yabin Cui          LOG(DEBUG) << "can't read build_id from file " << dso->Path() << ": "
109178fddd140931adf704061f82e3c9fcb03362f8d0Yabin Cui                     << result;
109278fddd140931adf704061f82e3c9fcb03362f8d0Yabin Cui          continue;
109378fddd140931adf704061f82e3c9fcb03362f8d0Yabin Cui        }
109478fddd140931adf704061f82e3c9fcb03362f8d0Yabin Cui      }
109578fddd140931adf704061f82e3c9fcb03362f8d0Yabin Cui      build_id_records.push_back(
109678fddd140931adf704061f82e3c9fcb03362f8d0Yabin Cui          BuildIdRecord(false, UINT_MAX, build_id, dso->Path()));
10978f6225147c5b6cb2159a7f5cb0dab952ee0759dfYabin Cui    }
10988f6225147c5b6cb2159a7f5cb0dab952ee0759dfYabin Cui  }
10998f6225147c5b6cb2159a7f5cb0dab952ee0759dfYabin Cui  if (!record_file_writer_->WriteBuildIdFeature(build_id_records)) {
11008f6225147c5b6cb2159a7f5cb0dab952ee0759dfYabin Cui    return false;
11018f6225147c5b6cb2159a7f5cb0dab952ee0759dfYabin Cui  }
11028f6225147c5b6cb2159a7f5cb0dab952ee0759dfYabin Cui  return true;
11039759e1b1ce76185aa539aeea2fb1cbd8382156e7Yabin Cui}
11049759e1b1ce76185aa539aeea2fb1cbd8382156e7Yabin Cui
1105c5b4a3106a0845d1bd8fd2c1b1c724eeb719ec62Yabin Cuibool RecordCommand::DumpFileFeature() {
1106c5b4a3106a0845d1bd8fd2c1b1c724eeb719ec62Yabin Cui  std::vector<Dso*> dso_v = thread_tree_.GetAllDsos();
1107c5b4a3106a0845d1bd8fd2c1b1c724eeb719ec62Yabin Cui  for (Dso* dso : dso_v) {
110816501ffbd73483c498dde1ea4ad2670da7c9df55Yabin Cui    if (!dso->HasDumpId()) {
1109c5b4a3106a0845d1bd8fd2c1b1c724eeb719ec62Yabin Cui      continue;
1110c5b4a3106a0845d1bd8fd2c1b1c724eeb719ec62Yabin Cui    }
1111c5b4a3106a0845d1bd8fd2c1b1c724eeb719ec62Yabin Cui    uint32_t dso_type = dso->type();
1112c5b4a3106a0845d1bd8fd2c1b1c724eeb719ec62Yabin Cui    uint64_t min_vaddr = dso->MinVirtualAddress();
1113aba7e29f163b4a332a9d3fe9973d82c7d0db148fYabin Cui
1114aba7e29f163b4a332a9d3fe9973d82c7d0db148fYabin Cui    // Dumping all symbols in hit files takes too much space, so only dump
1115aba7e29f163b4a332a9d3fe9973d82c7d0db148fYabin Cui    // needed symbols.
1116c5b4a3106a0845d1bd8fd2c1b1c724eeb719ec62Yabin Cui    const std::vector<Symbol>& symbols = dso->GetSymbols();
1117aba7e29f163b4a332a9d3fe9973d82c7d0db148fYabin Cui    std::vector<const Symbol*> dump_symbols;
1118aba7e29f163b4a332a9d3fe9973d82c7d0db148fYabin Cui    for (const auto& sym : symbols) {
1119aba7e29f163b4a332a9d3fe9973d82c7d0db148fYabin Cui      if (sym.HasDumpId()) {
1120aba7e29f163b4a332a9d3fe9973d82c7d0db148fYabin Cui        dump_symbols.push_back(&sym);
1121aba7e29f163b4a332a9d3fe9973d82c7d0db148fYabin Cui      }
1122aba7e29f163b4a332a9d3fe9973d82c7d0db148fYabin Cui    }
1123aba7e29f163b4a332a9d3fe9973d82c7d0db148fYabin Cui    std::sort(dump_symbols.begin(), dump_symbols.end(), Symbol::CompareByAddr);
1124aba7e29f163b4a332a9d3fe9973d82c7d0db148fYabin Cui
1125c5b4a3106a0845d1bd8fd2c1b1c724eeb719ec62Yabin Cui    if (!record_file_writer_->WriteFileFeature(dso->Path(), dso_type, min_vaddr,
1126aba7e29f163b4a332a9d3fe9973d82c7d0db148fYabin Cui                                               dump_symbols)) {
1127c5b4a3106a0845d1bd8fd2c1b1c724eeb719ec62Yabin Cui      return false;
1128c5b4a3106a0845d1bd8fd2c1b1c724eeb719ec62Yabin Cui    }
1129c5b4a3106a0845d1bd8fd2c1b1c724eeb719ec62Yabin Cui  }
1130c5b4a3106a0845d1bd8fd2c1b1c724eeb719ec62Yabin Cui  return true;
1131c5b4a3106a0845d1bd8fd2c1b1c724eeb719ec62Yabin Cui}
1132c5b4a3106a0845d1bd8fd2c1b1c724eeb719ec62Yabin Cui
11330f6df013be40459a1b4013bdad8ec0a82c18ce9aYabin Cuivoid RecordCommand::CollectHitFileInfo(const SampleRecord& r) {
11340f6df013be40459a1b4013bdad8ec0a82c18ce9aYabin Cui  const ThreadEntry* thread =
11350f6df013be40459a1b4013bdad8ec0a82c18ce9aYabin Cui      thread_tree_.FindThreadOrNew(r.tid_data.pid, r.tid_data.tid);
11360f6df013be40459a1b4013bdad8ec0a82c18ce9aYabin Cui  const MapEntry* map =
11370f6df013be40459a1b4013bdad8ec0a82c18ce9aYabin Cui      thread_tree_.FindMap(thread, r.ip_data.ip, r.InKernel());
1138aba7e29f163b4a332a9d3fe9973d82c7d0db148fYabin Cui  Dso* dso = map->dso;
1139aba7e29f163b4a332a9d3fe9973d82c7d0db148fYabin Cui  const Symbol* symbol;
1140aba7e29f163b4a332a9d3fe9973d82c7d0db148fYabin Cui  if (dump_symbols_) {
1141aba7e29f163b4a332a9d3fe9973d82c7d0db148fYabin Cui    symbol = thread_tree_.FindSymbol(map, r.ip_data.ip, nullptr, &dso);
1142aba7e29f163b4a332a9d3fe9973d82c7d0db148fYabin Cui    if (!symbol->HasDumpId()) {
1143aba7e29f163b4a332a9d3fe9973d82c7d0db148fYabin Cui      dso->CreateSymbolDumpId(symbol);
1144aba7e29f163b4a332a9d3fe9973d82c7d0db148fYabin Cui    }
1145aba7e29f163b4a332a9d3fe9973d82c7d0db148fYabin Cui  }
1146aba7e29f163b4a332a9d3fe9973d82c7d0db148fYabin Cui  if (!dso->HasDumpId()) {
1147aba7e29f163b4a332a9d3fe9973d82c7d0db148fYabin Cui    dso->CreateDumpId();
114816501ffbd73483c498dde1ea4ad2670da7c9df55Yabin Cui  }
11490f6df013be40459a1b4013bdad8ec0a82c18ce9aYabin Cui  if (r.sample_type & PERF_SAMPLE_CALLCHAIN) {
1150aba7e29f163b4a332a9d3fe9973d82c7d0db148fYabin Cui    bool in_kernel = r.InKernel();
1151aba7e29f163b4a332a9d3fe9973d82c7d0db148fYabin Cui    bool first_ip = true;
1152aba7e29f163b4a332a9d3fe9973d82c7d0db148fYabin Cui    for (uint64_t i = 0; i < r.callchain_data.ip_nr; ++i) {
1153aba7e29f163b4a332a9d3fe9973d82c7d0db148fYabin Cui      uint64_t ip = r.callchain_data.ips[i];
1154aba7e29f163b4a332a9d3fe9973d82c7d0db148fYabin Cui      if (ip >= PERF_CONTEXT_MAX) {
1155aba7e29f163b4a332a9d3fe9973d82c7d0db148fYabin Cui        switch (ip) {
1156aba7e29f163b4a332a9d3fe9973d82c7d0db148fYabin Cui          case PERF_CONTEXT_KERNEL:
1157aba7e29f163b4a332a9d3fe9973d82c7d0db148fYabin Cui            in_kernel = true;
1158aba7e29f163b4a332a9d3fe9973d82c7d0db148fYabin Cui            break;
1159aba7e29f163b4a332a9d3fe9973d82c7d0db148fYabin Cui          case PERF_CONTEXT_USER:
1160aba7e29f163b4a332a9d3fe9973d82c7d0db148fYabin Cui            in_kernel = false;
1161aba7e29f163b4a332a9d3fe9973d82c7d0db148fYabin Cui            break;
1162aba7e29f163b4a332a9d3fe9973d82c7d0db148fYabin Cui          default:
1163aba7e29f163b4a332a9d3fe9973d82c7d0db148fYabin Cui            LOG(DEBUG) << "Unexpected perf_context in callchain: " << std::hex
1164aba7e29f163b4a332a9d3fe9973d82c7d0db148fYabin Cui                       << ip;
1165aba7e29f163b4a332a9d3fe9973d82c7d0db148fYabin Cui        }
1166aba7e29f163b4a332a9d3fe9973d82c7d0db148fYabin Cui      } else {
1167aba7e29f163b4a332a9d3fe9973d82c7d0db148fYabin Cui        if (first_ip) {
1168aba7e29f163b4a332a9d3fe9973d82c7d0db148fYabin Cui          first_ip = false;
1169aba7e29f163b4a332a9d3fe9973d82c7d0db148fYabin Cui          // Remove duplication with sample ip.
1170aba7e29f163b4a332a9d3fe9973d82c7d0db148fYabin Cui          if (ip == r.ip_data.ip) {
1171aba7e29f163b4a332a9d3fe9973d82c7d0db148fYabin Cui            continue;
1172aba7e29f163b4a332a9d3fe9973d82c7d0db148fYabin Cui          }
1173aba7e29f163b4a332a9d3fe9973d82c7d0db148fYabin Cui        }
1174aba7e29f163b4a332a9d3fe9973d82c7d0db148fYabin Cui        map = thread_tree_.FindMap(thread, ip, in_kernel);
1175aba7e29f163b4a332a9d3fe9973d82c7d0db148fYabin Cui        dso = map->dso;
1176aba7e29f163b4a332a9d3fe9973d82c7d0db148fYabin Cui        if (dump_symbols_) {
1177aba7e29f163b4a332a9d3fe9973d82c7d0db148fYabin Cui          symbol = thread_tree_.FindSymbol(map, ip, nullptr, &dso);
1178aba7e29f163b4a332a9d3fe9973d82c7d0db148fYabin Cui          if (!symbol->HasDumpId()) {
1179aba7e29f163b4a332a9d3fe9973d82c7d0db148fYabin Cui            dso->CreateSymbolDumpId(symbol);
1180aba7e29f163b4a332a9d3fe9973d82c7d0db148fYabin Cui          }
1181aba7e29f163b4a332a9d3fe9973d82c7d0db148fYabin Cui        }
1182aba7e29f163b4a332a9d3fe9973d82c7d0db148fYabin Cui        if (!dso->HasDumpId()) {
1183aba7e29f163b4a332a9d3fe9973d82c7d0db148fYabin Cui          dso->CreateDumpId();
1184aba7e29f163b4a332a9d3fe9973d82c7d0db148fYabin Cui        }
118516501ffbd73483c498dde1ea4ad2670da7c9df55Yabin Cui      }
1186f831e6d12ca2298cb34b155a9d91ef002d0482f3Than McIntosh    }
1187f831e6d12ca2298cb34b155a9d91ef002d0482f3Than McIntosh  }
1188f831e6d12ca2298cb34b155a9d91ef002d0482f3Than McIntosh}
1189f831e6d12ca2298cb34b155a9d91ef002d0482f3Than McIntosh
1190ff7465c896ab90c162cbcf2b141c4cdd79bf437fYabin Cuivoid RegisterRecordCommand() {
1191b42129797f17f990ea5a88c6bdc7446000cc361cYabin Cui  RegisterCommand("record",
1192b42129797f17f990ea5a88c6bdc7446000cc361cYabin Cui                  [] { return std::unique_ptr<Command>(new RecordCommand()); });
1193f79f07e13c56f7ca3be1435cea7f8861daf7efaaYabin Cui}
1194