cmd_record.cpp 62 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719
  1. /*
  2. * Copyright (C) 2015 The Android Open Source Project
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. #include <inttypes.h>
  17. #include <libgen.h>
  18. #include <signal.h>
  19. #include <sys/mman.h>
  20. #include <sys/prctl.h>
  21. #include <sys/utsname.h>
  22. #include <time.h>
  23. #include <unistd.h>
  24. #include <set>
  25. #include <string>
  26. #include <unordered_map>
  27. #include <unordered_set>
  28. #include <vector>
  29. #include <android-base/logging.h>
  30. #include <android-base/file.h>
  31. #include <android-base/parseint.h>
  32. #include <android-base/strings.h>
  33. #include <android-base/unique_fd.h>
  34. #if defined(__ANDROID__)
  35. #include <android-base/properties.h>
  36. #endif
  37. #include "CallChainJoiner.h"
  38. #include "command.h"
  39. #include "environment.h"
  40. #include "event_selection_set.h"
  41. #include "event_type.h"
  42. #include "IOEventLoop.h"
  43. #include "JITDebugReader.h"
  44. #include "OfflineUnwinder.h"
  45. #include "read_apk.h"
  46. #include "read_elf.h"
  47. #include "record.h"
  48. #include "record_file.h"
  49. #include "thread_tree.h"
  50. #include "tracing.h"
  51. #include "utils.h"
  52. #include "workload.h"
  53. using namespace simpleperf;
  54. static std::string default_measured_event_type = "cpu-cycles";
  55. static std::unordered_map<std::string, uint64_t> branch_sampling_type_map = {
  56. {"u", PERF_SAMPLE_BRANCH_USER},
  57. {"k", PERF_SAMPLE_BRANCH_KERNEL},
  58. {"any", PERF_SAMPLE_BRANCH_ANY},
  59. {"any_call", PERF_SAMPLE_BRANCH_ANY_CALL},
  60. {"any_ret", PERF_SAMPLE_BRANCH_ANY_RETURN},
  61. {"ind_call", PERF_SAMPLE_BRANCH_IND_CALL},
  62. };
  63. static std::unordered_map<std::string, int> clockid_map = {
  64. {"realtime", CLOCK_REALTIME},
  65. {"monotonic", CLOCK_MONOTONIC},
  66. {"monotonic_raw", CLOCK_MONOTONIC_RAW},
  67. {"boottime", CLOCK_BOOTTIME},
  68. };
  69. // The max size of records dumped by kernel is 65535, and dump stack size
  70. // should be a multiply of 8, so MAX_DUMP_STACK_SIZE is 65528.
  71. constexpr uint32_t MAX_DUMP_STACK_SIZE = 65528;
  72. // The max allowed pages in mapped buffer is decided by rlimit(RLIMIT_MEMLOCK).
  73. // Here 1024 is a desired value for pages in mapped buffer. If mapped
  74. // successfully, the buffer size = 1024 * 4K (page size) = 4M.
  75. constexpr size_t DESIRED_PAGES_IN_MAPPED_BUFFER = 1024;
  76. // Cache size used by CallChainJoiner to cache call chains in memory.
  77. constexpr size_t DEFAULT_CALL_CHAIN_JOINER_CACHE_SIZE = 8 * 1024 * 1024;
  78. // Currently, the record buffer size in user-space is set to match the kernel buffer size on a
  79. // 8 core system. For system-wide recording, it is 8K pages * 4K page_size * 8 cores = 256MB.
  80. // For non system-wide recording, it is 1K pages * 4K page_size * 8 cores = 64MB.
  81. static constexpr size_t kRecordBufferSize = 64 * 1024 * 1024;
  82. static constexpr size_t kSystemWideRecordBufferSize = 256 * 1024 * 1024;
  83. struct TimeStat {
  84. uint64_t prepare_recording_time = 0;
  85. uint64_t start_recording_time = 0;
  86. uint64_t stop_recording_time = 0;
  87. uint64_t finish_recording_time = 0;
  88. uint64_t post_process_time = 0;
  89. };
  90. class RecordCommand : public Command {
  91. public:
  92. RecordCommand()
  93. : Command(
  94. "record", "record sampling info in perf.data",
  95. // clang-format off
  96. "Usage: simpleperf record [options] [--] [command [command-args]]\n"
  97. " Gather sampling information of running [command]. And -a/-p/-t option\n"
  98. " can be used to change target of sampling information.\n"
  99. " The default options are: -e cpu-cycles -f 4000 -o perf.data.\n"
  100. "Select monitored threads:\n"
  101. "-a System-wide collection.\n"
  102. #if defined(__ANDROID__)
  103. "--app package_name Profile the process of an Android application.\n"
  104. " On non-rooted devices, the app must be debuggable,\n"
  105. " because we use run-as to switch to the app's context.\n"
  106. #endif
  107. "-p pid1,pid2,... Record events on existing processes. Mutually exclusive\n"
  108. " with -a.\n"
  109. "-t tid1,tid2,... Record events on existing threads. Mutually exclusive with -a.\n"
  110. "\n"
  111. "Select monitored event types:\n"
  112. "-e event1[:modifier1],event2[:modifier2],...\n"
  113. " Select a list of events to record. An event can be:\n"
  114. " 1) an event name listed in `simpleperf list`;\n"
  115. " 2) a raw PMU event in rN format. N is a hex number.\n"
  116. " For example, r1b selects event number 0x1b.\n"
  117. " Modifiers can be added to define how the event should be\n"
  118. " monitored. Possible modifiers are:\n"
  119. " u - monitor user space events only\n"
  120. " k - monitor kernel space events only\n"
  121. "--group event1[:modifier],event2[:modifier2],...\n"
  122. " Similar to -e option. But events specified in the same --group\n"
  123. " option are monitored as a group, and scheduled in and out at the\n"
  124. " same time.\n"
  125. "--trace-offcpu Generate samples when threads are scheduled off cpu.\n"
  126. " Similar to \"-c 1 -e sched:sched_switch\".\n"
  127. "\n"
  128. "Select monitoring options:\n"
  129. "-f freq Set event sample frequency. It means recording at most [freq]\n"
  130. " samples every second. For non-tracepoint events, the default\n"
  131. " option is -f 4000. A -f/-c option affects all event types\n"
  132. " following it until meeting another -f/-c option. For example,\n"
  133. " for \"-f 1000 cpu-cycles -c 1 -e sched:sched_switch\", cpu-cycles\n"
  134. " has sample freq 1000, sched:sched_switch event has sample period 1.\n"
  135. "-c count Set event sample period. It means recording one sample when\n"
  136. " [count] events happen. For tracepoint events, the default option\n"
  137. " is -c 1.\n"
  138. "--call-graph fp | dwarf[,<dump_stack_size>]\n"
  139. " Enable call graph recording. Use frame pointer or dwarf debug\n"
  140. " frame as the method to parse call graph in stack.\n"
  141. " Default is dwarf,65528.\n"
  142. "-g Same as '--call-graph dwarf'.\n"
  143. "--clockid clock_id Generate timestamps of samples using selected clock.\n"
  144. " Possible values are: realtime, monotonic,\n"
  145. " monotonic_raw, boottime, perf. If supported, default\n"
  146. " is monotonic, otherwise is perf.\n"
  147. "--cpu cpu_item1,cpu_item2,...\n"
  148. " Collect samples only on the selected cpus. cpu_item can be cpu\n"
  149. " number like 1, or cpu range like 0-3.\n"
  150. "--duration time_in_sec Monitor for time_in_sec seconds instead of running\n"
  151. " [command]. Here time_in_sec may be any positive\n"
  152. " floating point number.\n"
  153. "-j branch_filter1,branch_filter2,...\n"
  154. " Enable taken branch stack sampling. Each sample captures a series\n"
  155. " of consecutive taken branches.\n"
  156. " The following filters are defined:\n"
  157. " any: any type of branch\n"
  158. " any_call: any function call or system call\n"
  159. " any_ret: any function return or system call return\n"
  160. " ind_call: any indirect branch\n"
  161. " u: only when the branch target is at the user level\n"
  162. " k: only when the branch target is in the kernel\n"
  163. " This option requires at least one branch type among any, any_call,\n"
  164. " any_ret, ind_call.\n"
  165. "-b Enable taken branch stack sampling. Same as '-j any'.\n"
  166. "-m mmap_pages Set the size of the buffer used to receiving sample data from\n"
  167. " the kernel. It should be a power of 2. If not set, the max\n"
  168. " possible value <= 1024 will be used.\n"
  169. "--no-inherit Don't record created child threads/processes.\n"
  170. "--cpu-percent <percent> Set the max percent of cpu time used for recording.\n"
  171. " percent is in range [1-100], default is 25.\n"
  172. "\n"
  173. "Dwarf unwinding options:\n"
  174. "--post-unwind=(yes|no) If `--call-graph dwarf` option is used, then the user's\n"
  175. " stack will be recorded in perf.data and unwound while\n"
  176. " recording by default. Use --post-unwind=yes to switch\n"
  177. " to unwind after recording.\n"
  178. "--no-unwind If `--call-graph dwarf` option is used, then the user's stack\n"
  179. " will be unwound by default. Use this option to disable the\n"
  180. " unwinding of the user's stack.\n"
  181. "--no-callchain-joiner If `--call-graph dwarf` option is used, then by default\n"
  182. " callchain joiner is used to break the 64k stack limit\n"
  183. " and build more complete call graphs. However, the built\n"
  184. " call graphs may not be correct in all cases.\n"
  185. "--callchain-joiner-min-matching-nodes count\n"
  186. " When callchain joiner is used, set the matched nodes needed to join\n"
  187. " callchains. The count should be >= 1. By default it is 1.\n"
  188. "\n"
  189. "Recording file options:\n"
  190. "--no-dump-kernel-symbols Don't dump kernel symbols in perf.data. By default\n"
  191. " kernel symbols will be dumped when needed.\n"
  192. "--no-dump-symbols Don't dump symbols in perf.data. By default symbols are\n"
  193. " dumped in perf.data, to support reporting in another\n"
  194. " environment.\n"
  195. "-o record_file_name Set record file name, default is perf.data.\n"
  196. "--size-limit SIZE[K|M|G] Stop recording after SIZE bytes of records.\n"
  197. " Default is unlimited.\n"
  198. "--symfs <dir> Look for files with symbols relative to this directory.\n"
  199. " This option is used to provide files with symbol table and\n"
  200. " debug information, which are used for unwinding and dumping symbols.\n"
  201. "\n"
  202. "Other options:\n"
  203. "--exit-with-parent Stop recording when the process starting\n"
  204. " simpleperf dies.\n"
  205. "--start_profiling_fd fd_no After starting profiling, write \"STARTED\" to\n"
  206. " <fd_no>, then close <fd_no>.\n"
  207. "--stdio-controls-profiling Use stdin/stdout to pause/resume profiling.\n"
  208. #if defined(__ANDROID__)
  209. "--in-app We are already running in the app's context.\n"
  210. "--tracepoint-events file_name Read tracepoint events from [file_name] instead of tracefs.\n"
  211. #endif
  212. #if 0
  213. // Below options are only used internally and shouldn't be visible to the public.
  214. "--out-fd <fd> Write perf.data to a file descriptor.\n"
  215. "--stop-signal-fd <fd> Stop recording when fd is readable.\n"
  216. #endif
  217. // clang-format on
  218. ),
  219. system_wide_collection_(false),
  220. branch_sampling_(0),
  221. fp_callchain_sampling_(false),
  222. dwarf_callchain_sampling_(false),
  223. dump_stack_size_in_dwarf_sampling_(MAX_DUMP_STACK_SIZE),
  224. unwind_dwarf_callchain_(true),
  225. post_unwind_(false),
  226. child_inherit_(true),
  227. duration_in_sec_(0),
  228. can_dump_kernel_symbols_(true),
  229. dump_symbols_(true),
  230. event_selection_set_(false),
  231. mmap_page_range_(std::make_pair(1, DESIRED_PAGES_IN_MAPPED_BUFFER)),
  232. record_filename_("perf.data"),
  233. sample_record_count_(0),
  234. lost_record_count_(0),
  235. in_app_context_(false),
  236. trace_offcpu_(false),
  237. exclude_kernel_callchain_(false),
  238. allow_callchain_joiner_(true),
  239. callchain_joiner_min_matching_nodes_(1u),
  240. last_record_timestamp_(0u) {
  241. // If we run `adb shell simpleperf record xxx` and stop profiling by ctrl-c, adb closes
  242. // sockets connecting simpleperf. After that, simpleperf will receive SIGPIPE when writing
  243. // to stdout/stderr, which is a problem when we use '--app' option. So ignore SIGPIPE to
  244. // finish properly.
  245. signal(SIGPIPE, SIG_IGN);
  246. }
  247. bool Run(const std::vector<std::string>& args);
  248. private:
  249. bool ParseOptions(const std::vector<std::string>& args,
  250. std::vector<std::string>* non_option_args);
  251. bool AdjustPerfEventLimit();
  252. bool PrepareRecording(Workload* workload);
  253. bool DoRecording(Workload* workload);
  254. bool PostProcessRecording(const std::vector<std::string>& args);
  255. bool TraceOffCpu();
  256. bool SetEventSelectionFlags();
  257. bool CreateAndInitRecordFile();
  258. std::unique_ptr<RecordFileWriter> CreateRecordFile(
  259. const std::string& filename);
  260. bool DumpKernelSymbol();
  261. bool DumpTracingData();
  262. bool DumpKernelMaps();
  263. bool DumpUserSpaceMaps();
  264. bool DumpProcessMaps(pid_t pid, const std::unordered_set<pid_t>& tids);
  265. bool ProcessRecord(Record* record);
  266. bool ShouldOmitRecord(Record* record);
  267. bool DumpMapsForRecord(Record* record);
  268. bool SaveRecordForPostUnwinding(Record* record);
  269. bool SaveRecordAfterUnwinding(Record* record);
  270. bool SaveRecordWithoutUnwinding(Record* record);
  271. bool ProcessJITDebugInfo(const std::vector<JITDebugInfo>& debug_info, bool sync_kernel_records);
  272. bool ProcessControlCmd(IOEventLoop* loop);
  273. void UpdateRecord(Record* record);
  274. bool UnwindRecord(SampleRecord& r);
  275. bool PostUnwindRecords();
  276. bool JoinCallChains();
  277. bool DumpAdditionalFeatures(const std::vector<std::string>& args);
  278. bool DumpBuildIdFeature();
  279. bool DumpFileFeature();
  280. bool DumpMetaInfoFeature(bool kernel_symbols_available);
  281. void CollectHitFileInfo(const SampleRecord& r);
  282. std::unique_ptr<SampleSpeed> sample_speed_;
  283. bool system_wide_collection_;
  284. uint64_t branch_sampling_;
  285. bool fp_callchain_sampling_;
  286. bool dwarf_callchain_sampling_;
  287. uint32_t dump_stack_size_in_dwarf_sampling_;
  288. bool unwind_dwarf_callchain_;
  289. bool post_unwind_;
  290. std::unique_ptr<OfflineUnwinder> offline_unwinder_;
  291. bool child_inherit_;
  292. double duration_in_sec_;
  293. bool can_dump_kernel_symbols_;
  294. bool dump_symbols_;
  295. std::string clockid_;
  296. std::vector<int> cpus_;
  297. EventSelectionSet event_selection_set_;
  298. std::pair<size_t, size_t> mmap_page_range_;
  299. ThreadTree thread_tree_;
  300. std::string record_filename_;
  301. android::base::unique_fd out_fd_;
  302. std::unique_ptr<RecordFileWriter> record_file_writer_;
  303. android::base::unique_fd stop_signal_fd_;
  304. uint64_t sample_record_count_;
  305. uint64_t lost_record_count_;
  306. android::base::unique_fd start_profiling_fd_;
  307. bool stdio_controls_profiling_ = false;
  308. std::string app_package_name_;
  309. bool in_app_context_;
  310. bool trace_offcpu_;
  311. bool exclude_kernel_callchain_;
  312. uint64_t size_limit_in_bytes_ = 0;
  313. uint64_t max_sample_freq_ = DEFAULT_SAMPLE_FREQ_FOR_NONTRACEPOINT_EVENT;
  314. size_t cpu_time_max_percent_ = 25;
  315. // For CallChainJoiner
  316. bool allow_callchain_joiner_;
  317. size_t callchain_joiner_min_matching_nodes_;
  318. std::unique_ptr<CallChainJoiner> callchain_joiner_;
  319. std::unique_ptr<JITDebugReader> jit_debug_reader_;
  320. uint64_t last_record_timestamp_; // used to insert Mmap2Records for JIT debug info
  321. TimeStat time_stat_;
  322. EventAttrWithId dumping_attr_id_;
  323. // In system wide recording, record if we have dumped map info for a process.
  324. std::unordered_set<pid_t> dumped_processes_;
  325. };
  326. bool RecordCommand::Run(const std::vector<std::string>& args) {
  327. ScopedCurrentArch scoped_arch(GetMachineArch());
  328. if (!CheckPerfEventLimit()) {
  329. return false;
  330. }
  331. AllowMoreOpenedFiles();
  332. std::vector<std::string> workload_args;
  333. if (!ParseOptions(args, &workload_args)) {
  334. return false;
  335. }
  336. if (!AdjustPerfEventLimit()) {
  337. return false;
  338. }
  339. ScopedTempFiles scoped_temp_files(android::base::Dirname(record_filename_));
  340. if (!app_package_name_.empty() && !in_app_context_) {
  341. // Some users want to profile non debuggable apps on rooted devices. If we use run-as,
  342. // it will be impossible when using --app. So don't switch to app's context when we are
  343. // root.
  344. if (!IsRoot()) {
  345. return RunInAppContext(app_package_name_, "record", args, workload_args.size(),
  346. record_filename_, true);
  347. }
  348. }
  349. std::unique_ptr<Workload> workload;
  350. if (!workload_args.empty()) {
  351. workload = Workload::CreateWorkload(workload_args);
  352. if (workload == nullptr) {
  353. return false;
  354. }
  355. }
  356. time_stat_.prepare_recording_time = GetSystemClock();
  357. if (!PrepareRecording(workload.get())) {
  358. return false;
  359. }
  360. time_stat_.start_recording_time = GetSystemClock();
  361. if (!DoRecording(workload.get())) {
  362. return false;
  363. }
  364. return PostProcessRecording(args);
  365. }
  366. bool RecordCommand::PrepareRecording(Workload* workload) {
  367. // 1. Prepare in other modules.
  368. PrepareVdsoFile();
  369. // 2. Add default event type.
  370. if (event_selection_set_.empty()) {
  371. size_t group_id;
  372. if (!event_selection_set_.AddEventType(default_measured_event_type, &group_id)) {
  373. return false;
  374. }
  375. if (sample_speed_) {
  376. event_selection_set_.SetSampleSpeed(group_id, *sample_speed_);
  377. }
  378. }
  379. // 3. Process options before opening perf event files.
  380. exclude_kernel_callchain_ = event_selection_set_.ExcludeKernel();
  381. if (trace_offcpu_ && !TraceOffCpu()) {
  382. return false;
  383. }
  384. if (!SetEventSelectionFlags()) {
  385. return false;
  386. }
  387. if (unwind_dwarf_callchain_) {
  388. offline_unwinder_.reset(new OfflineUnwinder(false));
  389. }
  390. if (unwind_dwarf_callchain_ && allow_callchain_joiner_) {
  391. callchain_joiner_.reset(new CallChainJoiner(DEFAULT_CALL_CHAIN_JOINER_CACHE_SIZE,
  392. callchain_joiner_min_matching_nodes_,
  393. false));
  394. }
  395. // 4. Add monitored targets.
  396. bool need_to_check_targets = false;
  397. if (system_wide_collection_) {
  398. event_selection_set_.AddMonitoredThreads({-1});
  399. } else if (!event_selection_set_.HasMonitoredTarget()) {
  400. if (workload != nullptr) {
  401. event_selection_set_.AddMonitoredProcesses({workload->GetPid()});
  402. event_selection_set_.SetEnableOnExec(true);
  403. if (event_selection_set_.HasInplaceSampler()) {
  404. // Start worker early, because the worker process has to setup inplace-sampler server
  405. // before we try to connect it.
  406. if (!workload->Start()) {
  407. return false;
  408. }
  409. }
  410. } else if (!app_package_name_.empty()) {
  411. // If app process is not created, wait for it. This allows simpleperf starts before
  412. // app process. In this way, we can have a better support of app start-up time profiling.
  413. std::set<pid_t> pids = WaitForAppProcesses(app_package_name_);
  414. event_selection_set_.AddMonitoredProcesses(pids);
  415. need_to_check_targets = true;
  416. } else {
  417. LOG(ERROR)
  418. << "No threads to monitor. Try `simpleperf help record` for help";
  419. return false;
  420. }
  421. } else {
  422. need_to_check_targets = true;
  423. }
  424. // Profiling JITed/interpreted Java code is supported starting from Android P.
  425. if (GetAndroidVersion() >= kAndroidVersionP) {
  426. // JIT symfiles are stored in temporary files, and are deleted after recording. But if
  427. // `-g --no-unwind` option is used, we want to keep symfiles to support unwinding in
  428. // the debug-unwind cmd.
  429. bool keep_symfiles = dwarf_callchain_sampling_ && !unwind_dwarf_callchain_;
  430. bool sync_with_records = clockid_ == "monotonic";
  431. jit_debug_reader_.reset(new JITDebugReader(keep_symfiles, sync_with_records));
  432. // To profile java code, need to dump maps containing vdex files, which are not executable.
  433. event_selection_set_.SetRecordNotExecutableMaps(true);
  434. }
  435. // 5. Open perf event files and create mapped buffers.
  436. if (!event_selection_set_.OpenEventFiles(cpus_)) {
  437. return false;
  438. }
  439. size_t record_buffer_size = system_wide_collection_ ? kSystemWideRecordBufferSize
  440. : kRecordBufferSize;
  441. if (!event_selection_set_.MmapEventFiles(mmap_page_range_.first, mmap_page_range_.second,
  442. record_buffer_size)) {
  443. return false;
  444. }
  445. auto callback =
  446. std::bind(&RecordCommand::ProcessRecord, this, std::placeholders::_1);
  447. if (!event_selection_set_.PrepareToReadMmapEventData(callback)) {
  448. return false;
  449. }
  450. // 6. Create perf.data.
  451. if (!CreateAndInitRecordFile()) {
  452. return false;
  453. }
  454. // 7. Add read/signal/periodic Events.
  455. if (need_to_check_targets && !event_selection_set_.StopWhenNoMoreTargets()) {
  456. return false;
  457. }
  458. IOEventLoop* loop = event_selection_set_.GetIOEventLoop();
  459. auto exit_loop_callback = [loop]() {
  460. return loop->ExitLoop();
  461. };
  462. if (!loop->AddSignalEvents({SIGCHLD, SIGINT, SIGTERM}, exit_loop_callback)) {
  463. return false;
  464. }
  465. // Only add an event for SIGHUP if we didn't inherit SIG_IGN (e.g. from nohup).
  466. if (!SignalIsIgnored(SIGHUP)) {
  467. if (!loop->AddSignalEvent(SIGHUP, exit_loop_callback)) {
  468. return false;
  469. }
  470. }
  471. if (stop_signal_fd_ != -1) {
  472. if (!loop->AddReadEvent(stop_signal_fd_, exit_loop_callback)) {
  473. return false;
  474. }
  475. }
  476. if (duration_in_sec_ != 0) {
  477. if (!loop->AddPeriodicEvent(SecondToTimeval(duration_in_sec_),
  478. [loop]() { return loop->ExitLoop(); })) {
  479. return false;
  480. }
  481. }
  482. if (stdio_controls_profiling_) {
  483. if (!loop->AddReadEvent(0, [&]() { return ProcessControlCmd(loop); })) {
  484. return false;
  485. }
  486. }
  487. if (jit_debug_reader_) {
  488. auto callback = [this](const std::vector<JITDebugInfo>& debug_info, bool sync_kernel_records) {
  489. return ProcessJITDebugInfo(debug_info, sync_kernel_records);
  490. };
  491. if (!jit_debug_reader_->RegisterDebugInfoCallback(loop, callback)) {
  492. return false;
  493. }
  494. if (!app_package_name_.empty()) {
  495. std::set<pid_t> pids = event_selection_set_.GetMonitoredProcesses();
  496. for (pid_t tid : event_selection_set_.GetMonitoredThreads()) {
  497. pid_t pid;
  498. if (GetProcessForThread(tid, &pid)) {
  499. pids.insert(pid);
  500. }
  501. }
  502. for (pid_t pid : pids) {
  503. if (!jit_debug_reader_->MonitorProcess(pid)) {
  504. return false;
  505. }
  506. }
  507. if (!jit_debug_reader_->ReadAllProcesses()) {
  508. return false;
  509. }
  510. }
  511. }
  512. return true;
  513. }
  514. bool RecordCommand::DoRecording(Workload* workload) {
  515. // Write records in mapped buffers of perf_event_files to output file while workload is running.
  516. if (workload != nullptr && !workload->IsStarted() && !workload->Start()) {
  517. return false;
  518. }
  519. if (start_profiling_fd_.get() != -1) {
  520. if (!android::base::WriteStringToFd("STARTED", start_profiling_fd_)) {
  521. PLOG(ERROR) << "failed to write to start_profiling_fd_";
  522. }
  523. start_profiling_fd_.reset();
  524. }
  525. if (stdio_controls_profiling_) {
  526. printf("started\n");
  527. fflush(stdout);
  528. }
  529. if (!event_selection_set_.GetIOEventLoop()->RunLoop()) {
  530. return false;
  531. }
  532. time_stat_.stop_recording_time = GetSystemClock();
  533. if (!event_selection_set_.FinishReadMmapEventData()) {
  534. return false;
  535. }
  536. time_stat_.finish_recording_time = GetSystemClock();
  537. return true;
  538. }
  539. static bool WriteRecordDataToOutFd(const std::string& in_filename, android::base::unique_fd out_fd) {
  540. android::base::unique_fd in_fd(FileHelper::OpenReadOnly(in_filename));
  541. if (in_fd == -1) {
  542. PLOG(ERROR) << "Failed to open " << in_filename;
  543. return false;
  544. }
  545. char buf[8192];
  546. while (true) {
  547. ssize_t n = TEMP_FAILURE_RETRY(read(in_fd, buf, sizeof(buf)));
  548. if (n < 0) {
  549. PLOG(ERROR) << "Failed to read " << in_filename;
  550. return false;
  551. }
  552. if (n == 0) {
  553. break;
  554. }
  555. if (!android::base::WriteFully(out_fd, buf, n)) {
  556. PLOG(ERROR) << "Failed to write to out_fd";
  557. return false;
  558. }
  559. }
  560. unlink(in_filename.c_str());
  561. return true;
  562. }
  563. bool RecordCommand::PostProcessRecording(const std::vector<std::string>& args) {
  564. // 1. Post unwind dwarf callchain.
  565. if (unwind_dwarf_callchain_ && post_unwind_) {
  566. if (!PostUnwindRecords()) {
  567. return false;
  568. }
  569. }
  570. // 2. Optionally join Callchains.
  571. if (callchain_joiner_) {
  572. JoinCallChains();
  573. }
  574. // 3. Dump additional features, and close record file.
  575. if (!DumpAdditionalFeatures(args)) {
  576. return false;
  577. }
  578. if (!record_file_writer_->Close()) {
  579. return false;
  580. }
  581. if (out_fd_ != -1 && !WriteRecordDataToOutFd(record_filename_, std::move(out_fd_))) {
  582. return false;
  583. }
  584. time_stat_.post_process_time = GetSystemClock();
  585. // 4. Show brief record result.
  586. size_t lost_samples;
  587. size_t lost_non_samples;
  588. size_t cut_stack_samples;
  589. event_selection_set_.GetLostRecords(&lost_samples, &lost_non_samples, &cut_stack_samples);
  590. std::string cut_samples;
  591. if (cut_stack_samples > 0) {
  592. cut_samples = android::base::StringPrintf(" (cut %zu)", cut_stack_samples);
  593. }
  594. lost_record_count_ += lost_samples + lost_non_samples;
  595. LOG(INFO) << "Samples recorded: " << sample_record_count_ << cut_samples
  596. << ". Samples lost: " << lost_record_count_ << ".";
  597. LOG(DEBUG) << "In user space, dropped " << lost_samples << " samples, " << lost_non_samples
  598. << " non samples, cut stack of " << cut_stack_samples << " samples.";
  599. if (sample_record_count_ + lost_record_count_ != 0) {
  600. double lost_percent = static_cast<double>(lost_record_count_) /
  601. (lost_record_count_ + sample_record_count_);
  602. constexpr double LOST_PERCENT_WARNING_BAR = 0.1;
  603. if (lost_percent >= LOST_PERCENT_WARNING_BAR) {
  604. LOG(WARNING) << "Lost " << (lost_percent * 100) << "% of samples, "
  605. << "consider increasing mmap_pages(-m), "
  606. << "or decreasing sample frequency(-f), "
  607. << "or increasing sample period(-c).";
  608. }
  609. }
  610. if (callchain_joiner_) {
  611. callchain_joiner_->DumpStat();
  612. }
  613. LOG(DEBUG) << "Prepare recording time "
  614. << (time_stat_.start_recording_time - time_stat_.prepare_recording_time) / 1e6
  615. << " ms, recording time "
  616. << (time_stat_.stop_recording_time - time_stat_.start_recording_time) / 1e6
  617. << " ms, stop recording time "
  618. << (time_stat_.finish_recording_time - time_stat_.stop_recording_time) / 1e6
  619. << " ms, post process time "
  620. << (time_stat_.post_process_time - time_stat_.finish_recording_time) / 1e6 << " ms.";
  621. return true;
  622. }
  623. bool RecordCommand::ParseOptions(const std::vector<std::string>& args,
  624. std::vector<std::string>* non_option_args) {
  625. std::vector<size_t> wait_setting_speed_event_groups_;
  626. size_t i;
  627. for (i = 0; i < args.size() && !args[i].empty() && args[i][0] == '-'; ++i) {
  628. if (args[i] == "-a") {
  629. system_wide_collection_ = true;
  630. } else if (args[i] == "--app") {
  631. if (!NextArgumentOrError(args, &i)) {
  632. return false;
  633. }
  634. app_package_name_ = args[i];
  635. } else if (args[i] == "-b") {
  636. branch_sampling_ = branch_sampling_type_map["any"];
  637. } else if (args[i] == "-c" || args[i] == "-f") {
  638. uint64_t value;
  639. if (!GetUintOption(args, &i, &value, 1)) {
  640. return false;
  641. }
  642. if (args[i-1] == "-c") {
  643. sample_speed_.reset(new SampleSpeed(0, value));
  644. } else {
  645. if (value >= INT_MAX) {
  646. LOG(ERROR) << "sample freq can't be bigger than INT_MAX.";
  647. return false;
  648. }
  649. sample_speed_.reset(new SampleSpeed(value, 0));
  650. max_sample_freq_ = std::max(max_sample_freq_, value);
  651. }
  652. for (auto group_id : wait_setting_speed_event_groups_) {
  653. event_selection_set_.SetSampleSpeed(group_id, *sample_speed_);
  654. }
  655. wait_setting_speed_event_groups_.clear();
  656. } else if (args[i] == "--call-graph") {
  657. if (!NextArgumentOrError(args, &i)) {
  658. return false;
  659. }
  660. std::vector<std::string> strs = android::base::Split(args[i], ",");
  661. if (strs[0] == "fp") {
  662. fp_callchain_sampling_ = true;
  663. dwarf_callchain_sampling_ = false;
  664. } else if (strs[0] == "dwarf") {
  665. fp_callchain_sampling_ = false;
  666. dwarf_callchain_sampling_ = true;
  667. if (strs.size() > 1) {
  668. uint64_t size;
  669. if (!android::base::ParseUint(strs[1], &size)) {
  670. LOG(ERROR) << "invalid dump stack size in --call-graph option: " << strs[1];
  671. return false;
  672. }
  673. if ((size & 7) != 0) {
  674. LOG(ERROR) << "dump stack size " << size
  675. << " is not 8-byte aligned.";
  676. return false;
  677. }
  678. if (size >= MAX_DUMP_STACK_SIZE) {
  679. LOG(ERROR) << "dump stack size " << size
  680. << " is bigger than max allowed size "
  681. << MAX_DUMP_STACK_SIZE << ".";
  682. return false;
  683. }
  684. dump_stack_size_in_dwarf_sampling_ = static_cast<uint32_t>(size);
  685. }
  686. } else {
  687. LOG(ERROR) << "unexpected argument for --call-graph option: "
  688. << args[i];
  689. return false;
  690. }
  691. } else if (args[i] == "--clockid") {
  692. if (!NextArgumentOrError(args, &i)) {
  693. return false;
  694. }
  695. if (args[i] != "perf") {
  696. if (!IsSettingClockIdSupported()) {
  697. LOG(ERROR) << "Setting clockid is not supported by the kernel.";
  698. return false;
  699. }
  700. if (clockid_map.find(args[i]) == clockid_map.end()) {
  701. LOG(ERROR) << "Invalid clockid: " << args[i];
  702. return false;
  703. }
  704. }
  705. clockid_ = args[i];
  706. } else if (args[i] == "--cpu") {
  707. if (!NextArgumentOrError(args, &i)) {
  708. return false;
  709. }
  710. cpus_ = GetCpusFromString(args[i]);
  711. } else if (args[i] == "--cpu-percent") {
  712. if (!GetUintOption(args, &i, &cpu_time_max_percent_, 1, 100)) {
  713. return false;
  714. }
  715. } else if (args[i] == "--duration") {
  716. if (!GetDoubleOption(args, &i, &duration_in_sec_, 1e-9)) {
  717. return false;
  718. }
  719. } else if (args[i] == "-e") {
  720. if (!NextArgumentOrError(args, &i)) {
  721. return false;
  722. }
  723. std::vector<std::string> event_types = android::base::Split(args[i], ",");
  724. for (auto& event_type : event_types) {
  725. size_t group_id;
  726. if (!event_selection_set_.AddEventType(event_type, &group_id)) {
  727. return false;
  728. }
  729. if (sample_speed_) {
  730. event_selection_set_.SetSampleSpeed(group_id, *sample_speed_);
  731. } else {
  732. wait_setting_speed_event_groups_.push_back(group_id);
  733. }
  734. }
  735. } else if (args[i] == "--exit-with-parent") {
  736. prctl(PR_SET_PDEATHSIG, SIGHUP, 0, 0, 0);
  737. } else if (args[i] == "-g") {
  738. fp_callchain_sampling_ = false;
  739. dwarf_callchain_sampling_ = true;
  740. } else if (args[i] == "--group") {
  741. if (!NextArgumentOrError(args, &i)) {
  742. return false;
  743. }
  744. std::vector<std::string> event_types = android::base::Split(args[i], ",");
  745. size_t group_id;
  746. if (!event_selection_set_.AddEventGroup(event_types, &group_id)) {
  747. return false;
  748. }
  749. if (sample_speed_) {
  750. event_selection_set_.SetSampleSpeed(group_id, *sample_speed_);
  751. } else {
  752. wait_setting_speed_event_groups_.push_back(group_id);
  753. }
  754. } else if (args[i] == "--in-app") {
  755. in_app_context_ = true;
  756. } else if (args[i] == "-j") {
  757. if (!NextArgumentOrError(args, &i)) {
  758. return false;
  759. }
  760. std::vector<std::string> branch_sampling_types =
  761. android::base::Split(args[i], ",");
  762. for (auto& type : branch_sampling_types) {
  763. auto it = branch_sampling_type_map.find(type);
  764. if (it == branch_sampling_type_map.end()) {
  765. LOG(ERROR) << "unrecognized branch sampling filter: " << type;
  766. return false;
  767. }
  768. branch_sampling_ |= it->second;
  769. }
  770. } else if (args[i] == "-m") {
  771. uint64_t pages;
  772. if (!GetUintOption(args, &i, &pages)) {
  773. return false;
  774. }
  775. if (!IsPowerOfTwo(pages)) {
  776. LOG(ERROR) << "Invalid mmap_pages: '" << args[i] << "'";
  777. return false;
  778. }
  779. mmap_page_range_.first = mmap_page_range_.second = pages;
  780. } else if (args[i] == "--no-dump-kernel-symbols") {
  781. can_dump_kernel_symbols_ = false;
  782. } else if (args[i] == "--no-dump-symbols") {
  783. dump_symbols_ = false;
  784. } else if (args[i] == "--no-inherit") {
  785. child_inherit_ = false;
  786. } else if (args[i] == "--no-unwind") {
  787. unwind_dwarf_callchain_ = false;
  788. } else if (args[i] == "--no-callchain-joiner") {
  789. allow_callchain_joiner_ = false;
  790. } else if (args[i] == "--callchain-joiner-min-matching-nodes") {
  791. if (!GetUintOption(args, &i, &callchain_joiner_min_matching_nodes_, 1)) {
  792. return false;
  793. }
  794. } else if (args[i] == "-o") {
  795. if (!NextArgumentOrError(args, &i)) {
  796. return false;
  797. }
  798. record_filename_ = args[i];
  799. } else if (args[i] == "--out-fd") {
  800. int fd;
  801. if (!GetUintOption(args, &i, &fd)) {
  802. return false;
  803. }
  804. out_fd_.reset(fd);
  805. } else if (args[i] == "-p") {
  806. if (!NextArgumentOrError(args, &i)) {
  807. return false;
  808. }
  809. std::set<pid_t> pids;
  810. if (!GetValidThreadsFromThreadString(args[i], &pids)) {
  811. return false;
  812. }
  813. event_selection_set_.AddMonitoredProcesses(pids);
  814. } else if (android::base::StartsWith(args[i], "--post-unwind")) {
  815. if (args[i] == "--post-unwind" || args[i] == "--post-unwind=yes") {
  816. post_unwind_ = true;
  817. } else if (args[i] == "--post-unwind=no") {
  818. post_unwind_ = false;
  819. } else {
  820. LOG(ERROR) << "unexpected option " << args[i];
  821. return false;
  822. }
  823. } else if (args[i] == "--size-limit") {
  824. if (!GetUintOption(args, &i, &size_limit_in_bytes_, 1, std::numeric_limits<uint64_t>::max(),
  825. true)) {
  826. return false;
  827. }
  828. } else if (args[i] == "--start_profiling_fd") {
  829. int fd;
  830. if (!GetUintOption(args, &i, &fd)) {
  831. return false;
  832. }
  833. start_profiling_fd_.reset(fd);
  834. } else if (args[i] == "--stdio-controls-profiling") {
  835. stdio_controls_profiling_ = true;
  836. } else if (args[i] == "--stop-signal-fd") {
  837. int fd;
  838. if (!GetUintOption(args, &i, &fd)) {
  839. return false;
  840. }
  841. stop_signal_fd_.reset(fd);
  842. } else if (args[i] == "--symfs") {
  843. if (!NextArgumentOrError(args, &i)) {
  844. return false;
  845. }
  846. if (!Dso::SetSymFsDir(args[i])) {
  847. return false;
  848. }
  849. } else if (args[i] == "-t") {
  850. if (!NextArgumentOrError(args, &i)) {
  851. return false;
  852. }
  853. std::set<pid_t> tids;
  854. if (!GetValidThreadsFromThreadString(args[i], &tids)) {
  855. return false;
  856. }
  857. event_selection_set_.AddMonitoredThreads(tids);
  858. } else if (args[i] == "--trace-offcpu") {
  859. trace_offcpu_ = true;
  860. } else if (args[i] == "--tracepoint-events") {
  861. if (!NextArgumentOrError(args, &i)) {
  862. return false;
  863. }
  864. if (!SetTracepointEventsFilePath(args[i])) {
  865. return false;
  866. }
  867. } else if (args[i] == "--") {
  868. i++;
  869. break;
  870. } else {
  871. ReportUnknownOption(args, i);
  872. return false;
  873. }
  874. }
  875. if (!dwarf_callchain_sampling_) {
  876. if (!unwind_dwarf_callchain_) {
  877. LOG(ERROR)
  878. << "--no-unwind is only used with `--call-graph dwarf` option.";
  879. return false;
  880. }
  881. unwind_dwarf_callchain_ = false;
  882. }
  883. if (post_unwind_) {
  884. if (!dwarf_callchain_sampling_ || !unwind_dwarf_callchain_) {
  885. post_unwind_ = false;
  886. }
  887. }
  888. if (fp_callchain_sampling_) {
  889. if (GetBuildArch() == ARCH_ARM) {
  890. LOG(WARNING) << "`--callgraph fp` option doesn't work well on arm architecture, "
  891. << "consider using `-g` option or profiling on aarch64 architecture.";
  892. }
  893. }
  894. if (system_wide_collection_ && event_selection_set_.HasMonitoredTarget()) {
  895. LOG(ERROR) << "Record system wide and existing processes/threads can't be "
  896. "used at the same time.";
  897. return false;
  898. }
  899. if (system_wide_collection_ && !IsRoot()) {
  900. LOG(ERROR) << "System wide profiling needs root privilege.";
  901. return false;
  902. }
  903. if (dump_symbols_ && can_dump_kernel_symbols_) {
  904. // No need to dump kernel symbols as we will dump all required symbols.
  905. can_dump_kernel_symbols_ = false;
  906. }
  907. if (clockid_.empty()) {
  908. clockid_ = IsSettingClockIdSupported() ? "monotonic" : "perf";
  909. }
  910. non_option_args->clear();
  911. for (; i < args.size(); ++i) {
  912. non_option_args->push_back(args[i]);
  913. }
  914. return true;
  915. }
  916. bool RecordCommand::AdjustPerfEventLimit() {
  917. bool set_prop = false;
  918. // 1. Adjust max_sample_rate.
  919. uint64_t cur_max_freq;
  920. if (GetMaxSampleFrequency(&cur_max_freq) && cur_max_freq < max_sample_freq_ &&
  921. !SetMaxSampleFrequency(max_sample_freq_)) {
  922. set_prop = true;
  923. }
  924. // 2. Adjust perf_cpu_time_max_percent.
  925. size_t cur_percent;
  926. if (GetCpuTimeMaxPercent(&cur_percent) && cur_percent != cpu_time_max_percent_ &&
  927. !SetCpuTimeMaxPercent(cpu_time_max_percent_)) {
  928. set_prop = true;
  929. }
  930. // 3. Adjust perf_event_mlock_kb.
  931. uint64_t mlock_kb = sysconf(_SC_NPROCESSORS_CONF) * (mmap_page_range_.second + 1) * 4;
  932. uint64_t cur_mlock_kb;
  933. if (GetPerfEventMlockKb(&cur_mlock_kb) && cur_mlock_kb < mlock_kb &&
  934. !SetPerfEventMlockKb(mlock_kb)) {
  935. set_prop = true;
  936. }
  937. if (GetAndroidVersion() >= kAndroidVersionP + 1 && set_prop && !in_app_context_) {
  938. return SetPerfEventLimits(std::max(max_sample_freq_, cur_max_freq), cpu_time_max_percent_,
  939. std::max(mlock_kb, cur_mlock_kb));
  940. }
  941. return true;
  942. }
  943. bool RecordCommand::TraceOffCpu() {
  944. if (FindEventTypeByName("sched:sched_switch") == nullptr) {
  945. LOG(ERROR) << "Can't trace off cpu because sched:sched_switch event is not available";
  946. return false;
  947. }
  948. for (auto& event_type : event_selection_set_.GetTracepointEvents()) {
  949. if (event_type->name == "sched:sched_switch") {
  950. LOG(ERROR) << "Trace offcpu can't be used together with sched:sched_switch event";
  951. return false;
  952. }
  953. }
  954. if (!IsDumpingRegsForTracepointEventsSupported()) {
  955. LOG(ERROR) << "Dumping regs for tracepoint events is not supported by the kernel";
  956. return false;
  957. }
  958. return event_selection_set_.AddEventType("sched:sched_switch");
  959. }
  960. bool RecordCommand::SetEventSelectionFlags() {
  961. event_selection_set_.SampleIdAll();
  962. if (!event_selection_set_.SetBranchSampling(branch_sampling_)) {
  963. return false;
  964. }
  965. if (fp_callchain_sampling_) {
  966. event_selection_set_.EnableFpCallChainSampling();
  967. } else if (dwarf_callchain_sampling_) {
  968. if (!event_selection_set_.EnableDwarfCallChainSampling(
  969. dump_stack_size_in_dwarf_sampling_)) {
  970. return false;
  971. }
  972. }
  973. event_selection_set_.SetInherit(child_inherit_);
  974. if (clockid_ != "perf") {
  975. event_selection_set_.SetClockId(clockid_map[clockid_]);
  976. }
  977. return true;
  978. }
  979. bool RecordCommand::CreateAndInitRecordFile() {
  980. record_file_writer_ = CreateRecordFile(record_filename_);
  981. if (record_file_writer_ == nullptr) {
  982. return false;
  983. }
  984. // Use first perf_event_attr and first event id to dump mmap and comm records.
  985. dumping_attr_id_ = event_selection_set_.GetEventAttrWithId()[0];
  986. return DumpKernelSymbol() && DumpTracingData() && DumpKernelMaps() && DumpUserSpaceMaps();
  987. }
  988. std::unique_ptr<RecordFileWriter> RecordCommand::CreateRecordFile(
  989. const std::string& filename) {
  990. std::unique_ptr<RecordFileWriter> writer =
  991. RecordFileWriter::CreateInstance(filename);
  992. if (writer == nullptr) {
  993. return nullptr;
  994. }
  995. if (!writer->WriteAttrSection(event_selection_set_.GetEventAttrWithId())) {
  996. return nullptr;
  997. }
  998. return writer;
  999. }
  1000. bool RecordCommand::DumpKernelSymbol() {
  1001. if (can_dump_kernel_symbols_) {
  1002. std::string kallsyms;
  1003. if (event_selection_set_.NeedKernelSymbol() &&
  1004. CheckKernelSymbolAddresses()) {
  1005. if (!android::base::ReadFileToString("/proc/kallsyms", &kallsyms)) {
  1006. PLOG(ERROR) << "failed to read /proc/kallsyms";
  1007. return false;
  1008. }
  1009. KernelSymbolRecord r(kallsyms);
  1010. if (!ProcessRecord(&r)) {
  1011. return false;
  1012. }
  1013. }
  1014. }
  1015. return true;
  1016. }
  1017. bool RecordCommand::DumpTracingData() {
  1018. std::vector<const EventType*> tracepoint_event_types =
  1019. event_selection_set_.GetTracepointEvents();
  1020. if (tracepoint_event_types.empty() || !CanRecordRawData() || in_app_context_) {
  1021. return true; // No need to dump tracing data, or can't do it.
  1022. }
  1023. std::vector<char> tracing_data;
  1024. if (!GetTracingData(tracepoint_event_types, &tracing_data)) {
  1025. return false;
  1026. }
  1027. TracingDataRecord record(tracing_data);
  1028. if (!ProcessRecord(&record)) {
  1029. return false;
  1030. }
  1031. return true;
  1032. }
  1033. bool RecordCommand::DumpKernelMaps() {
  1034. KernelMmap kernel_mmap;
  1035. std::vector<KernelMmap> module_mmaps;
  1036. GetKernelAndModuleMmaps(&kernel_mmap, &module_mmaps);
  1037. MmapRecord mmap_record(*dumping_attr_id_.attr, true, UINT_MAX, 0, kernel_mmap.start_addr,
  1038. kernel_mmap.len, 0, kernel_mmap.filepath, dumping_attr_id_.ids[0]);
  1039. if (!ProcessRecord(&mmap_record)) {
  1040. return false;
  1041. }
  1042. for (auto& module_mmap : module_mmaps) {
  1043. MmapRecord mmap_record(*dumping_attr_id_.attr, true, UINT_MAX, 0, module_mmap.start_addr,
  1044. module_mmap.len, 0, module_mmap.filepath, dumping_attr_id_.ids[0]);
  1045. if (!ProcessRecord(&mmap_record)) {
  1046. return false;
  1047. }
  1048. }
  1049. return true;
  1050. }
  1051. bool RecordCommand::DumpUserSpaceMaps() {
  1052. // For system_wide profiling, maps of a process is dumped when needed (first time a sample hits
  1053. // that process).
  1054. if (system_wide_collection_) {
  1055. return true;
  1056. }
  1057. // Map from process id to a set of thread ids in that process.
  1058. std::unordered_map<pid_t, std::unordered_set<pid_t>> process_map;
  1059. for (pid_t pid : event_selection_set_.GetMonitoredProcesses()) {
  1060. std::vector<pid_t> tids = GetThreadsInProcess(pid);
  1061. process_map[pid].insert(tids.begin(), tids.end());
  1062. }
  1063. for (pid_t tid : event_selection_set_.GetMonitoredThreads()) {
  1064. pid_t pid;
  1065. if (GetProcessForThread(tid, &pid)) {
  1066. process_map[pid].insert(tid);
  1067. }
  1068. }
  1069. // Dump each process.
  1070. for (auto& pair : process_map) {
  1071. if (!DumpProcessMaps(pair.first, pair.second)) {
  1072. return false;
  1073. }
  1074. }
  1075. return true;
  1076. }
  1077. bool RecordCommand::DumpProcessMaps(pid_t pid, const std::unordered_set<pid_t>& tids) {
  1078. // Dump mmap records.
  1079. std::vector<ThreadMmap> thread_mmaps;
  1080. if (!GetThreadMmapsInProcess(pid, &thread_mmaps)) {
  1081. // The process may exit before we get its info.
  1082. return true;
  1083. }
  1084. const perf_event_attr& attr = *dumping_attr_id_.attr;
  1085. uint64_t event_id = dumping_attr_id_.ids[0];
  1086. for (const auto& map : thread_mmaps) {
  1087. if (!(map.prot & PROT_EXEC) && !event_selection_set_.RecordNotExecutableMaps()) {
  1088. continue;
  1089. }
  1090. Mmap2Record record(attr, false, pid, pid, map.start_addr, map.len,
  1091. map.pgoff, map.prot, map.name, event_id, last_record_timestamp_);
  1092. if (!ProcessRecord(&record)) {
  1093. return false;
  1094. }
  1095. }
  1096. // Dump process name.
  1097. std::string name = GetCompleteProcessName(pid);
  1098. if (!name.empty()) {
  1099. CommRecord record(attr, pid, pid, name, event_id, last_record_timestamp_);
  1100. if (!ProcessRecord(&record)) {
  1101. return false;
  1102. }
  1103. }
  1104. // Dump thread info.
  1105. for (const auto& tid : tids) {
  1106. if (tid != pid && GetThreadName(tid, &name)) {
  1107. CommRecord comm_record(attr, pid, tid, name, event_id, last_record_timestamp_);
  1108. if (!ProcessRecord(&comm_record)) {
  1109. return false;
  1110. }
  1111. }
  1112. }
  1113. return true;
  1114. }
  1115. bool RecordCommand::ProcessRecord(Record* record) {
  1116. UpdateRecord(record);
  1117. if (ShouldOmitRecord(record)) {
  1118. return true;
  1119. }
  1120. if (size_limit_in_bytes_ > 0u) {
  1121. if (size_limit_in_bytes_ < record_file_writer_->GetDataSectionSize()) {
  1122. return event_selection_set_.GetIOEventLoop()->ExitLoop();
  1123. }
  1124. }
  1125. if (jit_debug_reader_ && !jit_debug_reader_->UpdateRecord(record)) {
  1126. return false;
  1127. }
  1128. last_record_timestamp_ = std::max(last_record_timestamp_, record->Timestamp());
  1129. // In system wide recording, maps are dumped when they are needed by records.
  1130. if (system_wide_collection_ && !DumpMapsForRecord(record)) {
  1131. return false;
  1132. }
  1133. if (unwind_dwarf_callchain_) {
  1134. if (post_unwind_) {
  1135. return SaveRecordForPostUnwinding(record);
  1136. }
  1137. return SaveRecordAfterUnwinding(record);
  1138. }
  1139. return SaveRecordWithoutUnwinding(record);
  1140. }
  1141. template <typename MmapRecordType>
  1142. bool MapOnlyExistInMemory(MmapRecordType* record) {
  1143. return !record->InKernel() && MappedFileOnlyExistInMemory(record->filename);
  1144. }
  1145. bool RecordCommand::ShouldOmitRecord(Record* record) {
  1146. if (jit_debug_reader_) {
  1147. // To profile jitted Java code, we need PROT_JIT_SYMFILE_MAP maps not overlapped by maps for
  1148. // [anon:dalvik-jit-code-cache]. To profile interpreted Java code, we record maps that
  1149. // are not executable. Some non-exec maps (like those for stack, heap) provide misleading map
  1150. // entries for unwinding, as in http://b/77236599. So it is better to remove
  1151. // dalvik-jit-code-cache and other maps that only exist in memory.
  1152. switch (record->type()) {
  1153. case PERF_RECORD_MMAP:
  1154. return MapOnlyExistInMemory(static_cast<MmapRecord*>(record));
  1155. case PERF_RECORD_MMAP2:
  1156. return MapOnlyExistInMemory(static_cast<Mmap2Record*>(record));
  1157. }
  1158. }
  1159. return false;
  1160. }
  1161. bool RecordCommand::DumpMapsForRecord(Record* record) {
  1162. if (record->type() == PERF_RECORD_SAMPLE) {
  1163. pid_t pid = static_cast<SampleRecord*>(record)->tid_data.pid;
  1164. if (dumped_processes_.find(pid) == dumped_processes_.end()) {
  1165. // Dump map info and all thread names for that process.
  1166. std::vector<pid_t> tids = GetThreadsInProcess(pid);
  1167. if (!tids.empty() &&
  1168. !DumpProcessMaps(pid, std::unordered_set<pid_t>(tids.begin(), tids.end()))) {
  1169. return false;
  1170. }
  1171. dumped_processes_.insert(pid);
  1172. }
  1173. }
  1174. return true;
  1175. }
  1176. bool RecordCommand::SaveRecordForPostUnwinding(Record* record) {
  1177. if (!record_file_writer_->WriteRecord(*record)) {
  1178. LOG(ERROR) << "If there isn't enough space for storing profiling data, consider using "
  1179. << "--no-post-unwind option.";
  1180. return false;
  1181. }
  1182. return true;
  1183. }
  1184. bool RecordCommand::SaveRecordAfterUnwinding(Record* record) {
  1185. if (record->type() == PERF_RECORD_SAMPLE) {
  1186. auto& r = *static_cast<SampleRecord*>(record);
  1187. // AdjustCallChainGeneratedByKernel() should go before UnwindRecord(). Because we don't want
  1188. // to adjust callchains generated by dwarf unwinder.
  1189. r.AdjustCallChainGeneratedByKernel();
  1190. if (!UnwindRecord(r)) {
  1191. return false;
  1192. }
  1193. // ExcludeKernelCallChain() should go after UnwindRecord() to notice the generated user call
  1194. // chain.
  1195. if (r.InKernel() && exclude_kernel_callchain_ && !r.ExcludeKernelCallChain()) {
  1196. // If current record contains no user callchain, skip it.
  1197. return true;
  1198. }
  1199. sample_record_count_++;
  1200. } else if (record->type() == PERF_RECORD_LOST) {
  1201. lost_record_count_ += static_cast<LostRecord*>(record)->lost;
  1202. } else {
  1203. thread_tree_.Update(*record);
  1204. }
  1205. return record_file_writer_->WriteRecord(*record);
  1206. }
  1207. bool RecordCommand::SaveRecordWithoutUnwinding(Record* record) {
  1208. if (record->type() == PERF_RECORD_SAMPLE) {
  1209. auto& r = *static_cast<SampleRecord*>(record);
  1210. if (fp_callchain_sampling_ || dwarf_callchain_sampling_) {
  1211. r.AdjustCallChainGeneratedByKernel();
  1212. }
  1213. if (r.InKernel() && exclude_kernel_callchain_ && !r.ExcludeKernelCallChain()) {
  1214. // If current record contains no user callchain, skip it.
  1215. return true;
  1216. }
  1217. sample_record_count_++;
  1218. } else if (record->type() == PERF_RECORD_LOST) {
  1219. lost_record_count_ += static_cast<LostRecord*>(record)->lost;
  1220. }
  1221. return record_file_writer_->WriteRecord(*record);
  1222. }
  1223. bool RecordCommand::ProcessJITDebugInfo(const std::vector<JITDebugInfo>& debug_info,
  1224. bool sync_kernel_records) {
  1225. EventAttrWithId attr_id = event_selection_set_.GetEventAttrWithId()[0];
  1226. for (auto& info : debug_info) {
  1227. if (info.type == JITDebugInfo::JIT_DEBUG_JIT_CODE) {
  1228. uint64_t timestamp = jit_debug_reader_->SyncWithRecords() ? info.timestamp
  1229. : last_record_timestamp_;
  1230. Mmap2Record record(*attr_id.attr, false, info.pid, info.pid,
  1231. info.jit_code_addr, info.jit_code_len, 0, map_flags::PROT_JIT_SYMFILE_MAP,
  1232. info.file_path, attr_id.ids[0], timestamp);
  1233. if (!ProcessRecord(&record)) {
  1234. return false;
  1235. }
  1236. } else {
  1237. thread_tree_.AddDexFileOffset(info.file_path, info.dex_file_offset);
  1238. }
  1239. }
  1240. // We want to let samples see the most recent JIT maps generated before them, but no JIT maps
  1241. // generated after them. So process existing samples each time generating new JIT maps. We prefer
  1242. // to process samples after processing JIT maps. Because some of the samples may hit the new JIT
  1243. // maps, and we want to report them properly.
  1244. if (sync_kernel_records && !event_selection_set_.SyncKernelBuffer()) {
  1245. return false;
  1246. }
  1247. return true;
  1248. }
  1249. bool RecordCommand::ProcessControlCmd(IOEventLoop* loop) {
  1250. char* line = nullptr;
  1251. size_t line_length = 0;
  1252. if (getline(&line, &line_length, stdin) == -1) {
  1253. free(line);
  1254. // When the simpleperf Java API destroys the simpleperf process, it also closes the stdin pipe.
  1255. // So we may see EOF of stdin.
  1256. return loop->ExitLoop();
  1257. }
  1258. std::string cmd = android::base::Trim(line);
  1259. free(line);
  1260. LOG(DEBUG) << "process control cmd: " << cmd;
  1261. bool result = false;
  1262. if (cmd == "pause") {
  1263. result = event_selection_set_.SetEnableEvents(false);
  1264. } else if (cmd == "resume") {
  1265. result = event_selection_set_.SetEnableEvents(true);
  1266. } else {
  1267. LOG(ERROR) << "unknown control cmd: " << cmd;
  1268. }
  1269. printf("%s\n", result ? "ok" : "error");
  1270. fflush(stdout);
  1271. return result;
  1272. }
  1273. template <class RecordType>
  1274. void UpdateMmapRecordForEmbeddedPath(RecordType& r, bool has_prot, uint32_t prot) {
  1275. if (r.InKernel()) {
  1276. return;
  1277. }
  1278. std::string filename = r.filename;
  1279. bool name_changed = false;
  1280. // Some vdex files in map files are marked with deleted flag, but they exist in the file system.
  1281. // It may be because a new file is used to replace the old one, but still worth to try.
  1282. if (android::base::EndsWith(filename, " (deleted)")) {
  1283. filename.resize(filename.size() - 10);
  1284. name_changed = true;
  1285. }
  1286. if (r.data->pgoff != 0 && (!has_prot || (prot & PROT_EXEC))) {
  1287. // For the case of a shared library "foobar.so" embedded
  1288. // inside an APK, we rewrite the original MMAP from
  1289. // ["path.apk" offset=X] to ["path.apk!/foobar.so" offset=W]
  1290. // so as to make the library name explicit. This update is
  1291. // done here (as part of the record operation) as opposed to
  1292. // on the host during the report, since we want to report
  1293. // the correct library name even if the the APK in question
  1294. // is not present on the host. The new offset W is
  1295. // calculated to be with respect to the start of foobar.so,
  1296. // not to the start of path.apk.
  1297. EmbeddedElf* ee = ApkInspector::FindElfInApkByOffset(filename, r.data->pgoff);
  1298. if (ee != nullptr) {
  1299. // Compute new offset relative to start of elf in APK.
  1300. auto data = *r.data;
  1301. data.pgoff -= ee->entry_offset();
  1302. r.SetDataAndFilename(data, GetUrlInApk(filename, ee->entry_name()));
  1303. return;
  1304. }
  1305. }
  1306. std::string zip_path;
  1307. std::string entry_name;
  1308. if (ParseExtractedInMemoryPath(filename, &zip_path, &entry_name)) {
  1309. filename = GetUrlInApk(zip_path, entry_name);
  1310. name_changed = true;
  1311. }
  1312. if (name_changed) {
  1313. auto data = *r.data;
  1314. r.SetDataAndFilename(data, filename);
  1315. }
  1316. }
  1317. void RecordCommand::UpdateRecord(Record* record) {
  1318. if (record->type() == PERF_RECORD_MMAP) {
  1319. UpdateMmapRecordForEmbeddedPath(*static_cast<MmapRecord*>(record), false, 0);
  1320. } else if (record->type() == PERF_RECORD_MMAP2) {
  1321. auto r = static_cast<Mmap2Record*>(record);
  1322. UpdateMmapRecordForEmbeddedPath(*r, true, r->data->prot);
  1323. } else if (record->type() == PERF_RECORD_COMM) {
  1324. auto r = static_cast<CommRecord*>(record);
  1325. if (r->data->pid == r->data->tid) {
  1326. std::string s = GetCompleteProcessName(r->data->pid);
  1327. if (!s.empty()) {
  1328. r->SetCommandName(s);
  1329. }
  1330. }
  1331. }
  1332. }
  1333. bool RecordCommand::UnwindRecord(SampleRecord& r) {
  1334. if ((r.sample_type & PERF_SAMPLE_CALLCHAIN) &&
  1335. (r.sample_type & PERF_SAMPLE_REGS_USER) &&
  1336. (r.regs_user_data.reg_mask != 0) &&
  1337. (r.sample_type & PERF_SAMPLE_STACK_USER) &&
  1338. (r.GetValidStackSize() > 0)) {
  1339. ThreadEntry* thread =
  1340. thread_tree_.FindThreadOrNew(r.tid_data.pid, r.tid_data.tid);
  1341. RegSet regs(r.regs_user_data.abi, r.regs_user_data.reg_mask, r.regs_user_data.regs);
  1342. std::vector<uint64_t> ips;
  1343. std::vector<uint64_t> sps;
  1344. if (!offline_unwinder_->UnwindCallChain(*thread, regs, r.stack_user_data.data,
  1345. r.GetValidStackSize(), &ips, &sps)) {
  1346. return false;
  1347. }
  1348. // The unwinding may fail if JIT debug info isn't the latest. In this case, read JIT debug info
  1349. // from the process and retry unwinding.
  1350. if (jit_debug_reader_ && !post_unwind_ &&
  1351. offline_unwinder_->IsCallChainBrokenForIncompleteJITDebugInfo()) {
  1352. jit_debug_reader_->ReadProcess(r.tid_data.pid);
  1353. jit_debug_reader_->FlushDebugInfo(r.Timestamp());
  1354. if (!offline_unwinder_->UnwindCallChain(*thread, regs, r.stack_user_data.data,
  1355. r.GetValidStackSize(), &ips, &sps)) {
  1356. return false;
  1357. }
  1358. }
  1359. r.ReplaceRegAndStackWithCallChain(ips);
  1360. if (callchain_joiner_) {
  1361. return callchain_joiner_->AddCallChain(r.tid_data.pid, r.tid_data.tid,
  1362. CallChainJoiner::ORIGINAL_OFFLINE, ips, sps);
  1363. }
  1364. }
  1365. return true;
  1366. }
  1367. bool RecordCommand::PostUnwindRecords() {
  1368. // 1. Move records from record_filename_ to a temporary file.
  1369. if (!record_file_writer_->Close()) {
  1370. return false;
  1371. }
  1372. record_file_writer_.reset();
  1373. std::unique_ptr<TemporaryFile> tmp_file = ScopedTempFiles::CreateTempFile();
  1374. if (!Workload::RunCmd({"mv", record_filename_, tmp_file->path})) {
  1375. return false;
  1376. }
  1377. std::unique_ptr<RecordFileReader> reader = RecordFileReader::CreateInstance(tmp_file->path);
  1378. if (!reader) {
  1379. return false;
  1380. }
  1381. // 2. Read records from the temporary file, and write unwound records back to record_filename_.
  1382. record_file_writer_ = CreateRecordFile(record_filename_);
  1383. if (!record_file_writer_) {
  1384. return false;
  1385. }
  1386. sample_record_count_ = 0;
  1387. lost_record_count_ = 0;
  1388. auto callback = [this](std::unique_ptr<Record> record) {
  1389. return SaveRecordAfterUnwinding(record.get());
  1390. };
  1391. return reader->ReadDataSection(callback);
  1392. }
  1393. bool RecordCommand::JoinCallChains() {
  1394. // 1. Prepare joined callchains.
  1395. if (!callchain_joiner_->JoinCallChains()) {
  1396. return false;
  1397. }
  1398. // 2. Move records from record_filename_ to a temporary file.
  1399. if (!record_file_writer_->Close()) {
  1400. return false;
  1401. }
  1402. record_file_writer_.reset();
  1403. std::unique_ptr<TemporaryFile> tmp_file = ScopedTempFiles::CreateTempFile();
  1404. if (!Workload::RunCmd({"mv", record_filename_, tmp_file->path})) {
  1405. return false;
  1406. }
  1407. // 3. Read records from the temporary file, and write record with joined call chains back
  1408. // to record_filename_.
  1409. std::unique_ptr<RecordFileReader> reader = RecordFileReader::CreateInstance(tmp_file->path);
  1410. record_file_writer_ = CreateRecordFile(record_filename_);
  1411. if (!reader || !record_file_writer_) {
  1412. return false;
  1413. }
  1414. auto record_callback = [&](std::unique_ptr<Record> r) {
  1415. if (r->type() != PERF_RECORD_SAMPLE) {
  1416. return record_file_writer_->WriteRecord(*r);
  1417. }
  1418. SampleRecord& sr = *static_cast<SampleRecord*>(r.get());
  1419. if (!sr.HasUserCallChain()) {
  1420. return record_file_writer_->WriteRecord(sr);
  1421. }
  1422. pid_t pid;
  1423. pid_t tid;
  1424. CallChainJoiner::ChainType type;
  1425. std::vector<uint64_t> ips;
  1426. std::vector<uint64_t> sps;
  1427. if (!callchain_joiner_->GetNextCallChain(pid, tid, type, ips, sps)) {
  1428. return false;
  1429. }
  1430. CHECK_EQ(type, CallChainJoiner::JOINED_OFFLINE);
  1431. CHECK_EQ(pid, static_cast<pid_t>(sr.tid_data.pid));
  1432. CHECK_EQ(tid, static_cast<pid_t>(sr.tid_data.tid));
  1433. sr.UpdateUserCallChain(ips);
  1434. return record_file_writer_->WriteRecord(sr);
  1435. };
  1436. return reader->ReadDataSection(record_callback);
  1437. }
  1438. bool RecordCommand::DumpAdditionalFeatures(
  1439. const std::vector<std::string>& args) {
  1440. // Read data section of perf.data to collect hit file information.
  1441. thread_tree_.ClearThreadAndMap();
  1442. bool kernel_symbols_available = false;
  1443. if (CheckKernelSymbolAddresses()) {
  1444. Dso::ReadKernelSymbolsFromProc();
  1445. kernel_symbols_available = true;
  1446. }
  1447. auto callback = [&](const Record* r) {
  1448. thread_tree_.Update(*r);
  1449. if (r->type() == PERF_RECORD_SAMPLE) {
  1450. CollectHitFileInfo(*reinterpret_cast<const SampleRecord*>(r));
  1451. }
  1452. };
  1453. if (!record_file_writer_->ReadDataSection(callback)) {
  1454. return false;
  1455. }
  1456. size_t feature_count = 6;
  1457. if (branch_sampling_) {
  1458. feature_count++;
  1459. }
  1460. if (!record_file_writer_->BeginWriteFeatures(feature_count)) {
  1461. return false;
  1462. }
  1463. if (!DumpBuildIdFeature()) {
  1464. return false;
  1465. }
  1466. if (!DumpFileFeature()) {
  1467. return false;
  1468. }
  1469. utsname uname_buf;
  1470. if (TEMP_FAILURE_RETRY(uname(&uname_buf)) != 0) {
  1471. PLOG(ERROR) << "uname() failed";
  1472. return false;
  1473. }
  1474. if (!record_file_writer_->WriteFeatureString(PerfFileFormat::FEAT_OSRELEASE,
  1475. uname_buf.release)) {
  1476. return false;
  1477. }
  1478. if (!record_file_writer_->WriteFeatureString(PerfFileFormat::FEAT_ARCH,
  1479. uname_buf.machine)) {
  1480. return false;
  1481. }
  1482. std::string exec_path = android::base::GetExecutablePath();
  1483. if (exec_path.empty()) exec_path = "simpleperf";
  1484. std::vector<std::string> cmdline;
  1485. cmdline.push_back(exec_path);
  1486. cmdline.push_back("record");
  1487. cmdline.insert(cmdline.end(), args.begin(), args.end());
  1488. if (!record_file_writer_->WriteCmdlineFeature(cmdline)) {
  1489. return false;
  1490. }
  1491. if (branch_sampling_ != 0 &&
  1492. !record_file_writer_->WriteBranchStackFeature()) {
  1493. return false;
  1494. }
  1495. if (!DumpMetaInfoFeature(kernel_symbols_available)) {
  1496. return false;
  1497. }
  1498. if (!record_file_writer_->EndWriteFeatures()) {
  1499. return false;
  1500. }
  1501. return true;
  1502. }
  1503. bool RecordCommand::DumpBuildIdFeature() {
  1504. std::vector<BuildIdRecord> build_id_records;
  1505. BuildId build_id;
  1506. std::vector<Dso*> dso_v = thread_tree_.GetAllDsos();
  1507. for (Dso* dso : dso_v) {
  1508. if (!dso->HasDumpId()) {
  1509. continue;
  1510. }
  1511. if (dso->type() == DSO_KERNEL) {
  1512. if (!GetKernelBuildId(&build_id)) {
  1513. continue;
  1514. }
  1515. build_id_records.push_back(
  1516. BuildIdRecord(true, UINT_MAX, build_id, dso->Path()));
  1517. } else if (dso->type() == DSO_KERNEL_MODULE) {
  1518. std::string path = dso->Path();
  1519. std::string module_name = basename(&path[0]);
  1520. if (android::base::EndsWith(module_name, ".ko")) {
  1521. module_name = module_name.substr(0, module_name.size() - 3);
  1522. }
  1523. if (!GetModuleBuildId(module_name, &build_id)) {
  1524. LOG(DEBUG) << "can't read build_id for module " << module_name;
  1525. continue;
  1526. }
  1527. build_id_records.push_back(BuildIdRecord(true, UINT_MAX, build_id, path));
  1528. } else if (dso->type() == DSO_ELF_FILE) {
  1529. if (dso->Path() == DEFAULT_EXECNAME_FOR_THREAD_MMAP) {
  1530. continue;
  1531. }
  1532. if (!GetBuildIdFromDsoPath(dso->Path(), &build_id)) {
  1533. LOG(DEBUG) << "Can't read build_id from file " << dso->Path();
  1534. continue;
  1535. }
  1536. build_id_records.push_back(
  1537. BuildIdRecord(false, UINT_MAX, build_id, dso->Path()));
  1538. }
  1539. }
  1540. if (!record_file_writer_->WriteBuildIdFeature(build_id_records)) {
  1541. return false;
  1542. }
  1543. return true;
  1544. }
  1545. bool RecordCommand::DumpFileFeature() {
  1546. std::vector<Dso*> dso_v = thread_tree_.GetAllDsos();
  1547. return record_file_writer_->WriteFileFeatures(thread_tree_.GetAllDsos());
  1548. }
  1549. bool RecordCommand::DumpMetaInfoFeature(bool kernel_symbols_available) {
  1550. std::unordered_map<std::string, std::string> info_map;
  1551. info_map["simpleperf_version"] = GetSimpleperfVersion();
  1552. info_map["system_wide_collection"] = system_wide_collection_ ? "true" : "false";
  1553. info_map["trace_offcpu"] = trace_offcpu_ ? "true" : "false";
  1554. // By storing event types information in perf.data, the readers of perf.data have the same
  1555. // understanding of event types, even if they are on another machine.
  1556. info_map["event_type_info"] = ScopedEventTypes::BuildString(event_selection_set_.GetEvents());
  1557. #if defined(__ANDROID__)
  1558. info_map["product_props"] = android::base::StringPrintf("%s:%s:%s",
  1559. android::base::GetProperty("ro.product.manufacturer", "").c_str(),
  1560. android::base::GetProperty("ro.product.model", "").c_str(),
  1561. android::base::GetProperty("ro.product.name", "").c_str());
  1562. info_map["android_version"] = android::base::GetProperty("ro.build.version.release", "");
  1563. if (!app_package_name_.empty()) {
  1564. info_map["app_package_name"] = app_package_name_;
  1565. }
  1566. #endif
  1567. info_map["clockid"] = clockid_;
  1568. info_map["timestamp"] = std::to_string(time(nullptr));
  1569. info_map["kernel_symbols_available"] = kernel_symbols_available ? "true" : "false";
  1570. return record_file_writer_->WriteMetaInfoFeature(info_map);
  1571. }
  1572. void RecordCommand::CollectHitFileInfo(const SampleRecord& r) {
  1573. const ThreadEntry* thread =
  1574. thread_tree_.FindThreadOrNew(r.tid_data.pid, r.tid_data.tid);
  1575. const MapEntry* map =
  1576. thread_tree_.FindMap(thread, r.ip_data.ip, r.InKernel());
  1577. Dso* dso = map->dso;
  1578. const Symbol* symbol;
  1579. if (dump_symbols_) {
  1580. symbol = thread_tree_.FindSymbol(map, r.ip_data.ip, nullptr, &dso);
  1581. if (!symbol->HasDumpId()) {
  1582. dso->CreateSymbolDumpId(symbol);
  1583. }
  1584. }
  1585. if (!dso->HasDumpId() && dso->type() != DSO_UNKNOWN_FILE) {
  1586. dso->CreateDumpId();
  1587. }
  1588. if (r.sample_type & PERF_SAMPLE_CALLCHAIN) {
  1589. bool in_kernel = r.InKernel();
  1590. bool first_ip = true;
  1591. for (uint64_t i = 0; i < r.callchain_data.ip_nr; ++i) {
  1592. uint64_t ip = r.callchain_data.ips[i];
  1593. if (ip >= PERF_CONTEXT_MAX) {
  1594. switch (ip) {
  1595. case PERF_CONTEXT_KERNEL:
  1596. in_kernel = true;
  1597. break;
  1598. case PERF_CONTEXT_USER:
  1599. in_kernel = false;
  1600. break;
  1601. default:
  1602. LOG(DEBUG) << "Unexpected perf_context in callchain: " << std::hex
  1603. << ip;
  1604. }
  1605. } else {
  1606. if (first_ip) {
  1607. first_ip = false;
  1608. // Remove duplication with sample ip.
  1609. if (ip == r.ip_data.ip) {
  1610. continue;
  1611. }
  1612. }
  1613. map = thread_tree_.FindMap(thread, ip, in_kernel);
  1614. dso = map->dso;
  1615. if (dump_symbols_) {
  1616. symbol = thread_tree_.FindSymbol(map, ip, nullptr, &dso);
  1617. if (!symbol->HasDumpId()) {
  1618. dso->CreateSymbolDumpId(symbol);
  1619. }
  1620. }
  1621. if (!dso->HasDumpId() && dso->type() != DSO_UNKNOWN_FILE) {
  1622. dso->CreateDumpId();
  1623. }
  1624. }
  1625. }
  1626. }
  1627. }
  1628. void RegisterRecordCommand() {
  1629. RegisterCommand("record",
  1630. [] { return std::unique_ptr<Command>(new RecordCommand()); });
  1631. }