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