OSDN Git Service

resolve merge conflicts of 836476d90d to mnc-dr2-dev-plus-aosp.
[android-x86/system-extras.git] / simpleperf / cmd_record.cpp
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
17 #include <libgen.h>
18 #include <poll.h>
19 #include <signal.h>
20 #include <sys/utsname.h>
21 #include <unistd.h>
22 #include <set>
23 #include <string>
24 #include <unordered_map>
25 #include <vector>
26
27 #include <android-base/logging.h>
28 #include <android-base/strings.h>
29
30 #include "command.h"
31 #include "dwarf_unwind.h"
32 #include "environment.h"
33 #include "event_selection_set.h"
34 #include "event_type.h"
35 #include "read_elf.h"
36 #include "record.h"
37 #include "record_file.h"
38 #include "thread_tree.h"
39 #include "utils.h"
40 #include "workload.h"
41
42 static std::string default_measured_event_type = "cpu-cycles";
43
44 static std::unordered_map<std::string, uint64_t> branch_sampling_type_map = {
45     {"u", PERF_SAMPLE_BRANCH_USER},
46     {"k", PERF_SAMPLE_BRANCH_KERNEL},
47     {"any", PERF_SAMPLE_BRANCH_ANY},
48     {"any_call", PERF_SAMPLE_BRANCH_ANY_CALL},
49     {"any_ret", PERF_SAMPLE_BRANCH_ANY_RETURN},
50     {"ind_call", PERF_SAMPLE_BRANCH_IND_CALL},
51 };
52
53 static volatile bool signaled;
54 static void signal_handler(int) {
55   signaled = true;
56 }
57
58 // Used in cpu-hotplug test.
59 bool system_wide_perf_event_open_failed = false;
60
61 class RecordCommand : public Command {
62  public:
63   RecordCommand()
64       : Command(
65             "record", "record sampling info in perf.data",
66             "Usage: simpleperf record [options] [command [command-args]]\n"
67             "    Gather sampling information when running [command].\n"
68             "    -a           System-wide collection.\n"
69             "    -b           Enable take branch stack sampling. Same as '-j any'\n"
70             "    -c count     Set event sample period.\n"
71             "    --call-graph fp | dwarf[,<dump_stack_size>]\n"
72             "                 Enable call graph recording. Use frame pointer or dwarf as the\n"
73             "                 method to parse call graph in stack. Default is dwarf,8192.\n"
74             "    --cpu cpu_item1,cpu_item2,...\n"
75             "                 Collect samples only on the selected cpus. cpu_item can be cpu\n"
76             "                 number like 1, or cpu range like 0-3.\n"
77             "    -e event1[:modifier1],event2[:modifier2],...\n"
78             "                 Select the event list to sample. Use `simpleperf list` to find\n"
79             "                 all possible event names. Modifiers can be added to define\n"
80             "                 how the event should be monitored. Possible modifiers are:\n"
81             "                   u - monitor user space events only\n"
82             "                   k - monitor kernel space events only\n"
83             "    -f freq      Set event sample frequency.\n"
84             "    -F freq      Same as '-f freq'.\n"
85             "    -g           Same as '--call-graph dwarf'.\n"
86             "    -j branch_filter1,branch_filter2,...\n"
87             "                 Enable taken branch stack sampling. Each sample\n"
88             "                 captures a series of consecutive taken branches.\n"
89             "                 The following filters are defined:\n"
90             "                   any: any type of branch\n"
91             "                   any_call: any function call or system call\n"
92             "                   any_ret: any function return or system call return\n"
93             "                   ind_call: any indirect branch\n"
94             "                   u: only when the branch target is at the user level\n"
95             "                   k: only when the branch target is in the kernel\n"
96             "                 This option requires at least one branch type among any,\n"
97             "                 any_call, any_ret, ind_call.\n"
98             "    --no-inherit\n"
99             "                 Don't record created child threads/processes.\n"
100             "    --no-unwind  If `--call-graph dwarf` option is used, then the user's stack will\n"
101             "                 be unwound by default. Use this option to disable the unwinding of\n"
102             "                 the user's stack.\n"
103             "    -o record_file_name    Set record file name, default is perf.data.\n"
104             "    -p pid1,pid2,...\n"
105             "                 Record events on existing processes. Mutually exclusive with -a.\n"
106             "    --post-unwind\n"
107             "                 If `--call-graph dwarf` option is used, then the user's stack will\n"
108             "                 be unwound while recording by default. But it may lose records as\n"
109             "                 stacking unwinding can be time consuming. Use this option to unwind\n"
110             "                 the user's stack after recording.\n"
111             "    -t tid1,tid2,...\n"
112             "                 Record events on existing threads. Mutually exclusive with -a.\n"),
113         use_sample_freq_(true),
114         sample_freq_(4000),
115         system_wide_collection_(false),
116         branch_sampling_(0),
117         fp_callchain_sampling_(false),
118         dwarf_callchain_sampling_(false),
119         dump_stack_size_in_dwarf_sampling_(8192),
120         unwind_dwarf_callchain_(true),
121         post_unwind_(false),
122         child_inherit_(true),
123         perf_mmap_pages_(256),
124         record_filename_("perf.data") {
125     signaled = false;
126     signal_handler_register_.reset(
127         new SignalHandlerRegister({SIGCHLD, SIGINT, SIGTERM}, signal_handler));
128   }
129
130   bool Run(const std::vector<std::string>& args);
131
132   static bool ReadMmapDataCallback(const char* data, size_t size);
133
134  private:
135   bool ParseOptions(const std::vector<std::string>& args, std::vector<std::string>* non_option_args);
136   bool AddMeasuredEventType(const std::string& event_type_name);
137   bool SetEventSelection();
138   bool CreateAndInitRecordFile();
139   std::unique_ptr<RecordFileWriter> CreateRecordFile(const std::string& filename);
140   bool DumpKernelAndModuleMmaps();
141   bool DumpThreadCommAndMmaps(bool all_threads, const std::vector<pid_t>& selected_threads);
142   bool CollectRecordsFromKernel(const char* data, size_t size);
143   bool ProcessRecord(Record* record);
144   void UnwindRecord(Record* record);
145   bool PostUnwind(const std::vector<std::string>& args);
146   bool DumpAdditionalFeatures(const std::vector<std::string>& args);
147   bool DumpBuildIdFeature();
148   void CollectHitFileInfo(const Record* record);
149
150   bool use_sample_freq_;    // Use sample_freq_ when true, otherwise using sample_period_.
151   uint64_t sample_freq_;    // Sample 'sample_freq_' times per second.
152   uint64_t sample_period_;  // Sample once when 'sample_period_' events occur.
153
154   bool system_wide_collection_;
155   uint64_t branch_sampling_;
156   bool fp_callchain_sampling_;
157   bool dwarf_callchain_sampling_;
158   uint32_t dump_stack_size_in_dwarf_sampling_;
159   bool unwind_dwarf_callchain_;
160   bool post_unwind_;
161   bool child_inherit_;
162   std::vector<pid_t> monitored_threads_;
163   std::vector<int> cpus_;
164   std::vector<EventTypeAndModifier> measured_event_types_;
165   EventSelectionSet event_selection_set_;
166
167   // mmap pages used by each perf event file, should be power of 2.
168   const size_t perf_mmap_pages_;
169
170   std::unique_ptr<RecordCache> record_cache_;
171   ThreadTree thread_tree_;
172   std::string record_filename_;
173   std::unique_ptr<RecordFileWriter> record_file_writer_;
174
175   std::set<std::string> hit_kernel_modules_;
176   std::set<std::string> hit_user_files_;
177
178   std::unique_ptr<SignalHandlerRegister> signal_handler_register_;
179 };
180
181 bool RecordCommand::Run(const std::vector<std::string>& args) {
182   // 1. Parse options, and use default measured event type if not given.
183   std::vector<std::string> workload_args;
184   if (!ParseOptions(args, &workload_args)) {
185     return false;
186   }
187   if (measured_event_types_.empty()) {
188     if (!AddMeasuredEventType(default_measured_event_type)) {
189       return false;
190     }
191   }
192   if (!SetEventSelection()) {
193     return false;
194   }
195
196   // 2. Create workload.
197   std::unique_ptr<Workload> workload;
198   if (!workload_args.empty()) {
199     workload = Workload::CreateWorkload(workload_args);
200     if (workload == nullptr) {
201       return false;
202     }
203   }
204   if (!system_wide_collection_ && monitored_threads_.empty()) {
205     if (workload != nullptr) {
206       monitored_threads_.push_back(workload->GetPid());
207       event_selection_set_.SetEnableOnExec(true);
208     } else {
209       LOG(ERROR) << "No threads to monitor. Try `simpleperf help record` for help\n";
210       return false;
211     }
212   }
213
214   // 3. Open perf_event_files, create memory mapped buffers for perf_event_files, add prepare poll
215   //    for perf_event_files.
216   if (system_wide_collection_) {
217     if (!event_selection_set_.OpenEventFilesForCpus(cpus_)) {
218       system_wide_perf_event_open_failed = true;
219       return false;
220     }
221   } else {
222     if (!event_selection_set_.OpenEventFilesForThreadsOnCpus(monitored_threads_, cpus_)) {
223       return false;
224     }
225   }
226   if (!event_selection_set_.MmapEventFiles(perf_mmap_pages_)) {
227     return false;
228   }
229   std::vector<pollfd> pollfds;
230   event_selection_set_.PreparePollForEventFiles(&pollfds);
231
232   // 4. Create perf.data.
233   if (!CreateAndInitRecordFile()) {
234     return false;
235   }
236
237   // 5. Write records in mmap buffers of perf_event_files to output file while workload is running.
238   if (workload != nullptr && !workload->Start()) {
239     return false;
240   }
241   record_cache_.reset(
242       new RecordCache(*event_selection_set_.FindEventAttrByType(measured_event_types_[0])));
243   auto callback = std::bind(&RecordCommand::CollectRecordsFromKernel, this, std::placeholders::_1,
244                             std::placeholders::_2);
245   while (true) {
246     if (!event_selection_set_.ReadMmapEventData(callback)) {
247       return false;
248     }
249     if (signaled) {
250       break;
251     }
252     poll(&pollfds[0], pollfds.size(), -1);
253   }
254   std::vector<std::unique_ptr<Record>> records = record_cache_->PopAll();
255   for (auto& r : records) {
256     if (!ProcessRecord(r.get())) {
257       return false;
258     }
259   }
260
261   // 6. Dump additional features, and close record file.
262   if (!DumpAdditionalFeatures(args)) {
263     return false;
264   }
265   if (!record_file_writer_->Close()) {
266     return false;
267   }
268
269   // 7. Unwind dwarf callchain.
270   if (post_unwind_) {
271     if (!PostUnwind(args)) {
272       return false;
273     }
274   }
275
276   return true;
277 }
278
279 bool RecordCommand::ParseOptions(const std::vector<std::string>& args,
280                                  std::vector<std::string>* non_option_args) {
281   std::set<pid_t> tid_set;
282   size_t i;
283   for (i = 0; i < args.size() && args[i].size() > 0 && args[i][0] == '-'; ++i) {
284     if (args[i] == "-a") {
285       system_wide_collection_ = true;
286     } else if (args[i] == "-b") {
287       branch_sampling_ = branch_sampling_type_map["any"];
288     } else if (args[i] == "-c") {
289       if (!NextArgumentOrError(args, &i)) {
290         return false;
291       }
292       char* endptr;
293       sample_period_ = strtoull(args[i].c_str(), &endptr, 0);
294       if (*endptr != '\0' || sample_period_ == 0) {
295         LOG(ERROR) << "Invalid sample period: '" << args[i] << "'";
296         return false;
297       }
298       use_sample_freq_ = false;
299     } else if (args[i] == "--call-graph") {
300       if (!NextArgumentOrError(args, &i)) {
301         return false;
302       }
303       std::vector<std::string> strs = android::base::Split(args[i], ",");
304       if (strs[0] == "fp") {
305         fp_callchain_sampling_ = true;
306         dwarf_callchain_sampling_ = false;
307       } else if (strs[0] == "dwarf") {
308         fp_callchain_sampling_ = false;
309         dwarf_callchain_sampling_ = true;
310         if (strs.size() > 1) {
311           char* endptr;
312           uint64_t size = strtoull(strs[1].c_str(), &endptr, 0);
313           if (*endptr != '\0' || size > UINT_MAX) {
314             LOG(ERROR) << "invalid dump stack size in --call-graph option: " << strs[1];
315             return false;
316           }
317           if ((size & 7) != 0) {
318             LOG(ERROR) << "dump stack size " << size << " is not 8-byte aligned.";
319             return false;
320           }
321           dump_stack_size_in_dwarf_sampling_ = static_cast<uint32_t>(size);
322         }
323       } else {
324         LOG(ERROR) << "unexpected argument for --call-graph option: " << args[i];
325         return false;
326       }
327     } else if (args[i] == "--cpu") {
328       if (!NextArgumentOrError(args, &i)) {
329         return false;
330       }
331       cpus_ = GetCpusFromString(args[i]);
332     } else if (args[i] == "-e") {
333       if (!NextArgumentOrError(args, &i)) {
334         return false;
335       }
336       std::vector<std::string> event_types = android::base::Split(args[i], ",");
337       for (auto& event_type : event_types) {
338         if (!AddMeasuredEventType(event_type)) {
339           return false;
340         }
341       }
342     } else if (args[i] == "-f" || args[i] == "-F") {
343       if (!NextArgumentOrError(args, &i)) {
344         return false;
345       }
346       char* endptr;
347       sample_freq_ = strtoull(args[i].c_str(), &endptr, 0);
348       if (*endptr != '\0' || sample_freq_ == 0) {
349         LOG(ERROR) << "Invalid sample frequency: '" << args[i] << "'";
350         return false;
351       }
352       use_sample_freq_ = true;
353     } else if (args[i] == "-g") {
354       fp_callchain_sampling_ = false;
355       dwarf_callchain_sampling_ = true;
356     } else if (args[i] == "-j") {
357       if (!NextArgumentOrError(args, &i)) {
358         return false;
359       }
360       std::vector<std::string> branch_sampling_types = android::base::Split(args[i], ",");
361       for (auto& type : branch_sampling_types) {
362         auto it = branch_sampling_type_map.find(type);
363         if (it == branch_sampling_type_map.end()) {
364           LOG(ERROR) << "unrecognized branch sampling filter: " << type;
365           return false;
366         }
367         branch_sampling_ |= it->second;
368       }
369     } else if (args[i] == "--no-inherit") {
370       child_inherit_ = false;
371     } else if (args[i] == "--no-unwind") {
372       unwind_dwarf_callchain_ = false;
373     } else if (args[i] == "-o") {
374       if (!NextArgumentOrError(args, &i)) {
375         return false;
376       }
377       record_filename_ = args[i];
378     } else if (args[i] == "-p") {
379       if (!NextArgumentOrError(args, &i)) {
380         return false;
381       }
382       if (!GetValidThreadsFromProcessString(args[i], &tid_set)) {
383         return false;
384       }
385     } else if (args[i] == "--post-unwind") {
386       post_unwind_ = true;
387     } else if (args[i] == "-t") {
388       if (!NextArgumentOrError(args, &i)) {
389         return false;
390       }
391       if (!GetValidThreadsFromThreadString(args[i], &tid_set)) {
392         return false;
393       }
394     } else {
395       ReportUnknownOption(args, i);
396       return false;
397     }
398   }
399
400   if (!dwarf_callchain_sampling_) {
401     if (!unwind_dwarf_callchain_) {
402       LOG(ERROR) << "--no-unwind is only used with `--call-graph dwarf` option.";
403       return false;
404     }
405     unwind_dwarf_callchain_ = false;
406   }
407   if (post_unwind_) {
408     if (!dwarf_callchain_sampling_) {
409       LOG(ERROR) << "--post-unwind is only used with `--call-graph dwarf` option.";
410       return false;
411     }
412     if (!unwind_dwarf_callchain_) {
413       LOG(ERROR) << "--post-unwind can't be used with `--no-unwind` option.";
414       return false;
415     }
416   }
417
418   monitored_threads_.insert(monitored_threads_.end(), tid_set.begin(), tid_set.end());
419   if (system_wide_collection_ && !monitored_threads_.empty()) {
420     LOG(ERROR)
421         << "Record system wide and existing processes/threads can't be used at the same time.";
422     return false;
423   }
424
425   if (non_option_args != nullptr) {
426     non_option_args->clear();
427     for (; i < args.size(); ++i) {
428       non_option_args->push_back(args[i]);
429     }
430   }
431   return true;
432 }
433
434 bool RecordCommand::AddMeasuredEventType(const std::string& event_type_name) {
435   std::unique_ptr<EventTypeAndModifier> event_type_modifier = ParseEventType(event_type_name);
436   if (event_type_modifier == nullptr) {
437     return false;
438   }
439   measured_event_types_.push_back(*event_type_modifier);
440   return true;
441 }
442
443 bool RecordCommand::SetEventSelection() {
444   for (auto& event_type : measured_event_types_) {
445     if (!event_selection_set_.AddEventType(event_type)) {
446       return false;
447     }
448   }
449   if (use_sample_freq_) {
450     event_selection_set_.SetSampleFreq(sample_freq_);
451   } else {
452     event_selection_set_.SetSamplePeriod(sample_period_);
453   }
454   event_selection_set_.SampleIdAll();
455   if (!event_selection_set_.SetBranchSampling(branch_sampling_)) {
456     return false;
457   }
458   if (fp_callchain_sampling_) {
459     event_selection_set_.EnableFpCallChainSampling();
460   } else if (dwarf_callchain_sampling_) {
461     if (!event_selection_set_.EnableDwarfCallChainSampling(dump_stack_size_in_dwarf_sampling_)) {
462       return false;
463     }
464   }
465   event_selection_set_.SetInherit(child_inherit_);
466   return true;
467 }
468
469 bool RecordCommand::CreateAndInitRecordFile() {
470   record_file_writer_ = CreateRecordFile(record_filename_);
471   if (record_file_writer_ == nullptr) {
472     return false;
473   }
474   if (!DumpKernelAndModuleMmaps()) {
475     return false;
476   }
477   if (!DumpThreadCommAndMmaps(system_wide_collection_, monitored_threads_)) {
478     return false;
479   }
480   return true;
481 }
482
483 std::unique_ptr<RecordFileWriter> RecordCommand::CreateRecordFile(const std::string& filename) {
484   std::unique_ptr<RecordFileWriter> writer = RecordFileWriter::CreateInstance(filename);
485   if (writer == nullptr) {
486     return nullptr;
487   }
488
489   std::vector<AttrWithId> attr_ids;
490   for (auto& event_type : measured_event_types_) {
491     AttrWithId attr_id;
492     attr_id.attr = event_selection_set_.FindEventAttrByType(event_type);
493     CHECK(attr_id.attr != nullptr);
494     const std::vector<std::unique_ptr<EventFd>>* fds =
495         event_selection_set_.FindEventFdsByType(event_type);
496     CHECK(fds != nullptr);
497     for (auto& fd : *fds) {
498       attr_id.ids.push_back(fd->Id());
499     }
500     attr_ids.push_back(attr_id);
501   }
502   if (!writer->WriteAttrSection(attr_ids)) {
503     return nullptr;
504   }
505   return writer;
506 }
507
508 bool RecordCommand::DumpKernelAndModuleMmaps() {
509   KernelMmap kernel_mmap;
510   std::vector<ModuleMmap> module_mmaps;
511   if (!GetKernelAndModuleMmaps(&kernel_mmap, &module_mmaps)) {
512     return false;
513   }
514   const perf_event_attr* attr = event_selection_set_.FindEventAttrByType(measured_event_types_[0]);
515   CHECK(attr != nullptr);
516   MmapRecord mmap_record = CreateMmapRecord(*attr, true, UINT_MAX, 0, kernel_mmap.start_addr,
517                                             kernel_mmap.len, kernel_mmap.pgoff, kernel_mmap.name);
518   if (!ProcessRecord(&mmap_record)) {
519     return false;
520   }
521   for (auto& module_mmap : module_mmaps) {
522     std::string filename = module_mmap.filepath;
523     if (filename.empty()) {
524       filename = "[" + module_mmap.name + "]";
525     }
526     MmapRecord mmap_record = CreateMmapRecord(*attr, true, UINT_MAX, 0, module_mmap.start_addr,
527                                               module_mmap.len, 0, filename);
528     if (!ProcessRecord(&mmap_record)) {
529       return false;
530     }
531   }
532   return true;
533 }
534
535 bool RecordCommand::DumpThreadCommAndMmaps(bool all_threads,
536                                            const std::vector<pid_t>& selected_threads) {
537   std::vector<ThreadComm> thread_comms;
538   if (!GetThreadComms(&thread_comms)) {
539     return false;
540   }
541   // Decide which processes and threads to dump.
542   std::set<pid_t> dump_processes;
543   std::set<pid_t> dump_threads;
544   for (auto& tid : selected_threads) {
545     dump_threads.insert(tid);
546   }
547   for (auto& thread : thread_comms) {
548     if (dump_threads.find(thread.tid) != dump_threads.end()) {
549       dump_processes.insert(thread.pid);
550     }
551   }
552
553   const perf_event_attr* attr = event_selection_set_.FindEventAttrByType(measured_event_types_[0]);
554   CHECK(attr != nullptr);
555
556   // Dump processes.
557   for (auto& thread : thread_comms) {
558     if (thread.pid != thread.tid) {
559       continue;
560     }
561     if (!all_threads && dump_processes.find(thread.pid) == dump_processes.end()) {
562       continue;
563     }
564     CommRecord record = CreateCommRecord(*attr, thread.pid, thread.tid, thread.comm);
565     if (!ProcessRecord(&record)) {
566       return false;
567     }
568     std::vector<ThreadMmap> thread_mmaps;
569     if (!GetThreadMmapsInProcess(thread.pid, &thread_mmaps)) {
570       // The thread may exit before we get its info.
571       continue;
572     }
573     for (auto& thread_mmap : thread_mmaps) {
574       if (thread_mmap.executable == 0) {
575         continue;  // No need to dump non-executable mmap info.
576       }
577       MmapRecord record =
578           CreateMmapRecord(*attr, false, thread.pid, thread.tid, thread_mmap.start_addr,
579                            thread_mmap.len, thread_mmap.pgoff, thread_mmap.name);
580       if (!ProcessRecord(&record)) {
581         return false;
582       }
583     }
584   }
585
586   // Dump threads.
587   for (auto& thread : thread_comms) {
588     if (thread.pid == thread.tid) {
589       continue;
590     }
591     if (!all_threads && dump_threads.find(thread.tid) == dump_threads.end()) {
592       continue;
593     }
594     ForkRecord fork_record = CreateForkRecord(*attr, thread.pid, thread.tid, thread.pid, thread.pid);
595     if (!ProcessRecord(&fork_record)) {
596       return false;
597     }
598     CommRecord comm_record = CreateCommRecord(*attr, thread.pid, thread.tid, thread.comm);
599     if (!ProcessRecord(&comm_record)) {
600       return false;
601     }
602   }
603   return true;
604 }
605
606 bool RecordCommand::CollectRecordsFromKernel(const char* data, size_t size) {
607   record_cache_->Push(data, size);
608   while (true) {
609     std::unique_ptr<Record> r = record_cache_->Pop();
610     if (r == nullptr) {
611       break;
612     }
613     if (!ProcessRecord(r.get())) {
614       return false;
615     }
616   }
617   return true;
618 }
619
620 bool RecordCommand::ProcessRecord(Record* record) {
621   BuildThreadTree(*record, &thread_tree_);
622   CollectHitFileInfo(record);
623   if (unwind_dwarf_callchain_ && !post_unwind_) {
624     UnwindRecord(record);
625   }
626   bool result = record_file_writer_->WriteData(record->BinaryFormat());
627   return result;
628 }
629
630 void RecordCommand::UnwindRecord(Record* record) {
631   if (record->type() == PERF_RECORD_SAMPLE) {
632     SampleRecord& r = *static_cast<SampleRecord*>(record);
633     if ((r.sample_type & PERF_SAMPLE_CALLCHAIN) && (r.sample_type & PERF_SAMPLE_REGS_USER) &&
634         (r.regs_user_data.reg_mask != 0) && (r.sample_type & PERF_SAMPLE_STACK_USER) &&
635         (!r.stack_user_data.data.empty())) {
636       ThreadEntry* thread = thread_tree_.FindThreadOrNew(r.tid_data.pid, r.tid_data.tid);
637       RegSet regs = CreateRegSet(r.regs_user_data.reg_mask, r.regs_user_data.regs);
638       std::vector<char>& stack = r.stack_user_data.data;
639       std::vector<uint64_t> unwind_ips = UnwindCallChain(*thread, regs, stack);
640       r.callchain_data.ips.push_back(PERF_CONTEXT_USER);
641       r.callchain_data.ips.insert(r.callchain_data.ips.end(), unwind_ips.begin(), unwind_ips.end());
642       r.regs_user_data.abi = 0;
643       r.regs_user_data.reg_mask = 0;
644       r.regs_user_data.regs.clear();
645       r.stack_user_data.data.clear();
646       r.stack_user_data.dyn_size = 0;
647       r.AdjustSizeBasedOnData();
648     }
649   }
650 }
651
652 bool RecordCommand::PostUnwind(const std::vector<std::string>& args) {
653   thread_tree_.Clear();
654   std::unique_ptr<RecordFileReader> reader = RecordFileReader::CreateInstance(record_filename_);
655   if (reader == nullptr) {
656     return false;
657   }
658   std::string tmp_filename = record_filename_ + ".tmp";
659   record_file_writer_ = CreateRecordFile(tmp_filename);
660   if (record_file_writer_ == nullptr) {
661     return false;
662   }
663   bool result = reader->ReadDataSection(
664       [this](std::unique_ptr<Record> record) {
665         BuildThreadTree(*record, &thread_tree_);
666         UnwindRecord(record.get());
667         return record_file_writer_->WriteData(record->BinaryFormat());
668       },
669       false);
670   if (!result) {
671     return false;
672   }
673   if (!DumpAdditionalFeatures(args)) {
674     return false;
675   }
676   if (!record_file_writer_->Close()) {
677     return false;
678   }
679
680   if (unlink(record_filename_.c_str()) != 0) {
681     PLOG(ERROR) << "failed to remove " << record_filename_;
682     return false;
683   }
684   if (rename(tmp_filename.c_str(), record_filename_.c_str()) != 0) {
685     PLOG(ERROR) << "failed to rename " << tmp_filename << " to " << record_filename_;
686     return false;
687   }
688   return true;
689 }
690
691 bool RecordCommand::DumpAdditionalFeatures(const std::vector<std::string>& args) {
692   size_t feature_count = (branch_sampling_ != 0 ? 5 : 4);
693   if (!record_file_writer_->WriteFeatureHeader(feature_count)) {
694     return false;
695   }
696   if (!DumpBuildIdFeature()) {
697     return false;
698   }
699   utsname uname_buf;
700   if (TEMP_FAILURE_RETRY(uname(&uname_buf)) != 0) {
701     PLOG(ERROR) << "uname() failed";
702     return false;
703   }
704   if (!record_file_writer_->WriteFeatureString(PerfFileFormat::FEAT_OSRELEASE, uname_buf.release)) {
705     return false;
706   }
707   if (!record_file_writer_->WriteFeatureString(PerfFileFormat::FEAT_ARCH, uname_buf.machine)) {
708     return false;
709   }
710
711   std::string exec_path = "simpleperf";
712   GetExecPath(&exec_path);
713   std::vector<std::string> cmdline;
714   cmdline.push_back(exec_path);
715   cmdline.push_back("record");
716   cmdline.insert(cmdline.end(), args.begin(), args.end());
717   if (!record_file_writer_->WriteCmdlineFeature(cmdline)) {
718     return false;
719   }
720   if (branch_sampling_ != 0 && !record_file_writer_->WriteBranchStackFeature()) {
721     return false;
722   }
723   return true;
724 }
725
726 bool RecordCommand::DumpBuildIdFeature() {
727   std::vector<BuildIdRecord> build_id_records;
728   BuildId build_id;
729   // Add build_ids for kernel/modules.
730   for (auto& filename : hit_kernel_modules_) {
731     if (filename == DEFAULT_KERNEL_FILENAME_FOR_BUILD_ID) {
732       if (!GetKernelBuildId(&build_id)) {
733         LOG(DEBUG) << "can't read build_id for kernel";
734         continue;
735       }
736       build_id_records.push_back(
737           CreateBuildIdRecord(true, UINT_MAX, build_id, DEFAULT_KERNEL_FILENAME_FOR_BUILD_ID));
738     } else {
739       std::string path = filename;
740       std::string module_name = basename(&path[0]);
741       if (android::base::EndsWith(module_name, ".ko")) {
742         module_name = module_name.substr(0, module_name.size() - 3);
743       }
744       if (!GetModuleBuildId(module_name, &build_id)) {
745         LOG(DEBUG) << "can't read build_id for module " << module_name;
746         continue;
747       }
748       build_id_records.push_back(CreateBuildIdRecord(true, UINT_MAX, build_id, filename));
749     }
750   }
751   // Add build_ids for user elf files.
752   for (auto& filename : hit_user_files_) {
753     if (filename == DEFAULT_EXECNAME_FOR_THREAD_MMAP) {
754       continue;
755     }
756     if (!GetBuildIdFromElfFile(filename, &build_id)) {
757       LOG(DEBUG) << "can't read build_id from file " << filename;
758       continue;
759     }
760     build_id_records.push_back(CreateBuildIdRecord(false, UINT_MAX, build_id, filename));
761   }
762   if (!record_file_writer_->WriteBuildIdFeature(build_id_records)) {
763     return false;
764   }
765   return true;
766 }
767
768 void RecordCommand::CollectHitFileInfo(const Record* record) {
769   if (record->type() == PERF_RECORD_SAMPLE) {
770     auto r = *static_cast<const SampleRecord*>(record);
771     bool in_kernel = ((r.header.misc & PERF_RECORD_MISC_CPUMODE_MASK) == PERF_RECORD_MISC_KERNEL);
772     const ThreadEntry* thread = thread_tree_.FindThreadOrNew(r.tid_data.pid, r.tid_data.tid);
773     const MapEntry* map = thread_tree_.FindMap(thread, r.ip_data.ip, in_kernel);
774     if (in_kernel) {
775       hit_kernel_modules_.insert(map->dso->Path());
776     } else {
777       hit_user_files_.insert(map->dso->Path());
778     }
779   }
780 }
781
782 __attribute__((constructor)) static void RegisterRecordCommand() {
783   RegisterCommand("record", [] { return std::unique_ptr<Command>(new RecordCommand()); });
784 }