/*
 * Copyright (C) 2015 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include <libgen.h>
#include <poll.h>
#include <signal.h>
#include <sys/utsname.h>
#include <unistd.h>
#include <set>
#include <string>
#include <unordered_map>
#include <vector>

#include <android-base/logging.h>
#include <android-base/file.h>
#include <android-base/strings.h>

#include "command.h"
#include "dwarf_unwind.h"
#include "environment.h"
#include "event_selection_set.h"
#include "event_type.h"
#include "read_apk.h"
#include "read_elf.h"
#include "record.h"
#include "record_file.h"
#include "scoped_signal_handler.h"
#include "thread_tree.h"
#include "tracing.h"
#include "utils.h"
#include "workload.h"

static std::string default_measured_event_type = "cpu-cycles";

static std::unordered_map<std::string, uint64_t> branch_sampling_type_map = {
    {"u", PERF_SAMPLE_BRANCH_USER},
    {"k", PERF_SAMPLE_BRANCH_KERNEL},
    {"any", PERF_SAMPLE_BRANCH_ANY},
    {"any_call", PERF_SAMPLE_BRANCH_ANY_CALL},
    {"any_ret", PERF_SAMPLE_BRANCH_ANY_RETURN},
    {"ind_call", PERF_SAMPLE_BRANCH_IND_CALL},
};

static volatile bool signaled;
static void signal_handler(int) { signaled = true; }

constexpr uint64_t DEFAULT_SAMPLE_FREQ_FOR_NONTRACEPOINT_EVENT = 4000;
constexpr uint64_t DEFAULT_SAMPLE_PERIOD_FOR_TRACEPOINT_EVENT = 1;

class RecordCommand : public Command {
 public:
  RecordCommand()
      : Command(
            "record", "record sampling info in perf.data",
            // clang-format off
"Usage: simpleperf record [options] [command [command-args]]\n"
"       Gather sampling information when running [command].\n"
"-a     System-wide collection.\n"
"-b     Enable take branch stack sampling. Same as '-j any'\n"
"-c count     Set event sample period. It means recording one sample when\n"
"             [count] events happen. Can't be used with -f/-F option.\n"
"             For tracepoint events, the default option is -c 1.\n"
"--call-graph fp | dwarf[,<dump_stack_size>]\n"
"             Enable call graph recording. Use frame pointer or dwarf debug\n"
"             frame as the method to parse call graph in stack.\n"
"             Default is dwarf,8192.\n"
"--cpu cpu_item1,cpu_item2,...\n"
"             Collect samples only on the selected cpus. cpu_item can be cpu\n"
"             number like 1, or cpu range like 0-3.\n"
"--dump-symbols  Dump symbols in perf.data. By default perf.data doesn't contain\n"
"                symbol information for samples. This option is used when there\n"
"                is no symbol information in report environment.\n"
"-e event1[:modifier1],event2[:modifier2],...\n"
"             Select the event list to sample. Use `simpleperf list` to find\n"
"             all possible event names. Modifiers can be added to define how\n"
"             the event should be monitored.\n"
"             Possible modifiers are:\n"
"                u - monitor user space events only\n"
"                k - monitor kernel space events only\n"
"-f freq      Set event sample frequency. It means recording at most [freq]\n"
"             samples every second. For non-tracepoint events, the default\n"
"             option is -f 4000.\n"
"-F freq      Same as '-f freq'.\n"
"-g           Same as '--call-graph dwarf'.\n"
"--group event1[:modifier],event2[:modifier2],...\n"
"             Similar to -e option. But events specified in the same --group\n"
"             option are monitored as a group, and scheduled in and out at the\n"
"             same time.\n"
"-j branch_filter1,branch_filter2,...\n"
"             Enable taken branch stack sampling. Each sample captures a series\n"
"             of consecutive taken branches.\n"
"             The following filters are defined:\n"
"                any: any type of branch\n"
"                any_call: any function call or system call\n"
"                any_ret: any function return or system call return\n"
"                ind_call: any indirect branch\n"
"                u: only when the branch target is at the user level\n"
"                k: only when the branch target is in the kernel\n"
"             This option requires at least one branch type among any, any_call,\n"
"             any_ret, ind_call.\n"
"-m mmap_pages   Set the size of the buffer used to receiving sample data from\n"
"                the kernel. It should be a power of 2. The default value is 16.\n"
"--no-dump-kernel-symbols  Don't dump kernel symbols in perf.data. By default\n"
"                          kernel symbols will be dumped when needed.\n"
"--no-inherit  Don't record created child threads/processes.\n"
"--no-unwind   If `--call-graph dwarf` option is used, then the user's stack\n"
"              will be unwound by default. Use this option to disable the\n"
"              unwinding of the user's stack.\n"
"-o record_file_name    Set record file name, default is perf.data.\n"
"-p pid1,pid2,...       Record events on existing processes. Mutually exclusive\n"
"                       with -a.\n"
"--post-unwind  If `--call-graph dwarf` option is used, then the user's stack\n"
"               will be unwound while recording by default. But it may lose\n"
"               records as stacking unwinding can be time consuming. Use this\n"
"               option to unwind the user's stack after recording.\n"
"-t tid1,tid2,... Record events on existing threads. Mutually exclusive with -a.\n"
            // clang-format on
            ),
        use_sample_freq_(false),
        sample_freq_(0),
        use_sample_period_(false),
        sample_period_(0),
        system_wide_collection_(false),
        branch_sampling_(0),
        fp_callchain_sampling_(false),
        dwarf_callchain_sampling_(false),
        dump_stack_size_in_dwarf_sampling_(8192),
        unwind_dwarf_callchain_(true),
        post_unwind_(false),
        child_inherit_(true),
        can_dump_kernel_symbols_(true),
        dump_symbols_(false),
        perf_mmap_pages_(16),
        record_filename_("perf.data"),
        sample_record_count_(0) {
    signaled = false;
    scoped_signal_handler_.reset(
        new ScopedSignalHandler({SIGCHLD, SIGINT, SIGTERM}, signal_handler));
  }

  bool Run(const std::vector<std::string>& args);

 private:
  bool ParseOptions(const std::vector<std::string>& args,
                    std::vector<std::string>* non_option_args);
  bool SetEventSelectionFlags();
  bool CreateAndInitRecordFile();
  std::unique_ptr<RecordFileWriter> CreateRecordFile(
      const std::string& filename);
  bool DumpKernelSymbol();
  bool DumpTracingData();
  bool DumpKernelAndModuleMmaps(const perf_event_attr& attr, uint64_t event_id);
  bool DumpThreadCommAndMmaps(const perf_event_attr& attr, uint64_t event_id,
                              bool all_threads,
                              const std::vector<pid_t>& selected_threads);
  bool ProcessRecord(Record* record);
  bool DumpSymbolForRecord(const SampleRecord& r, bool for_callchain);
  void UpdateRecordForEmbeddedElfPath(Record* record);
  bool UnwindRecord(Record* record);
  bool PostUnwind(const std::vector<std::string>& args);
  bool DumpAdditionalFeatures(const std::vector<std::string>& args);
  bool DumpBuildIdFeature();
  void CollectHitFileInfo(Record* record);
  std::pair<std::string, uint64_t> TestForEmbeddedElf(Dso* dso, uint64_t pgoff);

  bool use_sample_freq_;
  uint64_t sample_freq_;  // Sample 'sample_freq_' times per second.
  bool use_sample_period_;
  uint64_t sample_period_;  // Sample once when 'sample_period_' events occur.

  bool system_wide_collection_;
  uint64_t branch_sampling_;
  bool fp_callchain_sampling_;
  bool dwarf_callchain_sampling_;
  uint32_t dump_stack_size_in_dwarf_sampling_;
  bool unwind_dwarf_callchain_;
  bool post_unwind_;
  bool child_inherit_;
  bool can_dump_kernel_symbols_;
  bool dump_symbols_;
  std::vector<pid_t> monitored_threads_;
  std::vector<int> cpus_;
  EventSelectionSet event_selection_set_;

  // mmap pages used by each perf event file, should be a power of 2.
  size_t perf_mmap_pages_;

  ThreadTree thread_tree_;
  std::string record_filename_;
  std::unique_ptr<RecordFileWriter> record_file_writer_;

  std::set<std::string> hit_kernel_modules_;
  std::set<std::string> hit_user_files_;

  std::unique_ptr<ScopedSignalHandler> scoped_signal_handler_;
  uint64_t sample_record_count_;
};

bool RecordCommand::Run(const std::vector<std::string>& args) {
  if (!CheckPerfEventLimit()) {
    return false;
  }

  // 1. Parse options, and use default measured event type if not given.
  std::vector<std::string> workload_args;
  if (!ParseOptions(args, &workload_args)) {
    return false;
  }
  if (event_selection_set_.empty()) {
    if (!event_selection_set_.AddEventType(default_measured_event_type)) {
      return false;
    }
  }
  if (!SetEventSelectionFlags()) {
    return false;
  }

  // 2. Create workload.
  std::unique_ptr<Workload> workload;
  if (!workload_args.empty()) {
    workload = Workload::CreateWorkload(workload_args);
    if (workload == nullptr) {
      return false;
    }
  }
  if (!system_wide_collection_ && monitored_threads_.empty()) {
    if (workload != nullptr) {
      monitored_threads_.push_back(workload->GetPid());
      event_selection_set_.SetEnableOnExec(true);
    } else {
      LOG(ERROR)
          << "No threads to monitor. Try `simpleperf help record` for help\n";
      return false;
    }
  }

  // 3. Open perf_event_files, create memory mapped buffers for
  //    perf_event_files, add prepare poll for perf_event_files.
  if (system_wide_collection_) {
    if (!event_selection_set_.OpenEventFilesForCpus(cpus_)) {
      return false;
    }
  } else {
    if (!event_selection_set_.OpenEventFilesForThreadsOnCpus(monitored_threads_,
                                                             cpus_)) {
      return false;
    }
  }
  if (!event_selection_set_.MmapEventFiles(perf_mmap_pages_)) {
    return false;
  }
  std::vector<pollfd> pollfds;
  event_selection_set_.PrepareToPollForEventFiles(&pollfds);

  // 4. Create perf.data.
  if (!CreateAndInitRecordFile()) {
    return false;
  }

  // 5. Write records in mmap buffers of perf_event_files to output file while
  //    workload is running.
  if (workload != nullptr && !workload->Start()) {
    return false;
  }
  auto callback =
      std::bind(&RecordCommand::ProcessRecord, this, std::placeholders::_1);
  event_selection_set_.PrepareToReadMmapEventData(callback);
  while (true) {
    if (!event_selection_set_.ReadMmapEventData()) {
      return false;
    }
    if (signaled) {
      break;
    }
    poll(&pollfds[0], pollfds.size(), -1);
  }
  event_selection_set_.FinishReadMmapEventData();

  // 6. Dump additional features, and close record file.
  if (!DumpAdditionalFeatures(args)) {
    return false;
  }
  if (!record_file_writer_->Close()) {
    return false;
  }

  // 7. Unwind dwarf callchain.
  if (post_unwind_) {
    if (!PostUnwind(args)) {
      return false;
    }
  }
  LOG(VERBOSE) << "Record " << sample_record_count_ << " samples.";
  return true;
}

bool RecordCommand::ParseOptions(const std::vector<std::string>& args,
                                 std::vector<std::string>* non_option_args) {
  std::set<pid_t> tid_set;
  size_t i;
  for (i = 0; i < args.size() && !args[i].empty() && args[i][0] == '-'; ++i) {
    if (args[i] == "-a") {
      system_wide_collection_ = true;
    } else if (args[i] == "-b") {
      branch_sampling_ = branch_sampling_type_map["any"];
    } else if (args[i] == "-c") {
      if (!NextArgumentOrError(args, &i)) {
        return false;
      }
      char* endptr;
      sample_period_ = strtoull(args[i].c_str(), &endptr, 0);
      if (*endptr != '\0' || sample_period_ == 0) {
        LOG(ERROR) << "Invalid sample period: '" << args[i] << "'";
        return false;
      }
      use_sample_period_ = true;
    } else if (args[i] == "--call-graph") {
      if (!NextArgumentOrError(args, &i)) {
        return false;
      }
      std::vector<std::string> strs = android::base::Split(args[i], ",");
      if (strs[0] == "fp") {
        fp_callchain_sampling_ = true;
        dwarf_callchain_sampling_ = false;
      } else if (strs[0] == "dwarf") {
        fp_callchain_sampling_ = false;
        dwarf_callchain_sampling_ = true;
        if (strs.size() > 1) {
          char* endptr;
          uint64_t size = strtoull(strs[1].c_str(), &endptr, 0);
          if (*endptr != '\0' || size > UINT_MAX) {
            LOG(ERROR) << "invalid dump stack size in --call-graph option: "
                       << strs[1];
            return false;
          }
          if ((size & 7) != 0) {
            LOG(ERROR) << "dump stack size " << size
                       << " is not 8-byte aligned.";
            return false;
          }
          dump_stack_size_in_dwarf_sampling_ = static_cast<uint32_t>(size);
        }
      } else {
        LOG(ERROR) << "unexpected argument for --call-graph option: "
                   << args[i];
        return false;
      }
    } else if (args[i] == "--cpu") {
      if (!NextArgumentOrError(args, &i)) {
        return false;
      }
      cpus_ = GetCpusFromString(args[i]);
    } else if (args[i] == "--dump-symbols") {
      dump_symbols_ = true;
    } else if (args[i] == "-e") {
      if (!NextArgumentOrError(args, &i)) {
        return false;
      }
      std::vector<std::string> event_types = android::base::Split(args[i], ",");
      for (auto& event_type : event_types) {
        if (!event_selection_set_.AddEventType(event_type)) {
          return false;
        }
      }
    } else if (args[i] == "-f" || args[i] == "-F") {
      if (!NextArgumentOrError(args, &i)) {
        return false;
      }
      char* endptr;
      sample_freq_ = strtoull(args[i].c_str(), &endptr, 0);
      if (*endptr != '\0' || sample_freq_ == 0) {
        LOG(ERROR) << "Invalid sample frequency: '" << args[i] << "'";
        return false;
      }
      use_sample_freq_ = true;
    } else if (args[i] == "-g") {
      fp_callchain_sampling_ = false;
      dwarf_callchain_sampling_ = true;
    } else if (args[i] == "--group") {
      if (!NextArgumentOrError(args, &i)) {
        return false;
      }
      std::vector<std::string> event_types = android::base::Split(args[i], ",");
      if (!event_selection_set_.AddEventGroup(event_types)) {
        return false;
      }
    } else if (args[i] == "-j") {
      if (!NextArgumentOrError(args, &i)) {
        return false;
      }
      std::vector<std::string> branch_sampling_types =
          android::base::Split(args[i], ",");
      for (auto& type : branch_sampling_types) {
        auto it = branch_sampling_type_map.find(type);
        if (it == branch_sampling_type_map.end()) {
          LOG(ERROR) << "unrecognized branch sampling filter: " << type;
          return false;
        }
        branch_sampling_ |= it->second;
      }
    } else if (args[i] == "-m") {
      if (!NextArgumentOrError(args, &i)) {
        return false;
      }
      char* endptr;
      uint64_t pages = strtoull(args[i].c_str(), &endptr, 0);
      if (*endptr != '\0' || !IsPowerOfTwo(pages)) {
        LOG(ERROR) << "Invalid mmap_pages: '" << args[i] << "'";
        return false;
      }
      perf_mmap_pages_ = pages;
    } else if (args[i] == "--no-dump-kernel-symbols") {
      can_dump_kernel_symbols_ = false;
    } else if (args[i] == "--no-inherit") {
      child_inherit_ = false;
    } else if (args[i] == "--no-unwind") {
      unwind_dwarf_callchain_ = false;
    } else if (args[i] == "-o") {
      if (!NextArgumentOrError(args, &i)) {
        return false;
      }
      record_filename_ = args[i];
    } else if (args[i] == "-p") {
      if (!NextArgumentOrError(args, &i)) {
        return false;
      }
      if (!GetValidThreadsFromProcessString(args[i], &tid_set)) {
        return false;
      }
    } else if (args[i] == "--post-unwind") {
      post_unwind_ = true;
    } else if (args[i] == "-t") {
      if (!NextArgumentOrError(args, &i)) {
        return false;
      }
      if (!GetValidThreadsFromThreadString(args[i], &tid_set)) {
        return false;
      }
    } else {
      ReportUnknownOption(args, i);
      return false;
    }
  }

  if (use_sample_freq_ && use_sample_period_) {
    LOG(ERROR) << "-f option can't be used with -c option.";
    return false;
  }

  if (!dwarf_callchain_sampling_) {
    if (!unwind_dwarf_callchain_) {
      LOG(ERROR)
          << "--no-unwind is only used with `--call-graph dwarf` option.";
      return false;
    }
    unwind_dwarf_callchain_ = false;
  }
  if (post_unwind_) {
    if (!dwarf_callchain_sampling_) {
      LOG(ERROR)
          << "--post-unwind is only used with `--call-graph dwarf` option.";
      return false;
    }
    if (!unwind_dwarf_callchain_) {
      LOG(ERROR) << "--post-unwind can't be used with `--no-unwind` option.";
      return false;
    }
  }

  monitored_threads_.insert(monitored_threads_.end(), tid_set.begin(),
                            tid_set.end());
  if (system_wide_collection_ && !monitored_threads_.empty()) {
    LOG(ERROR) << "Record system wide and existing processes/threads can't be "
                  "used at the same time.";
    return false;
  }

  if (system_wide_collection_ && !IsRoot()) {
    LOG(ERROR) << "System wide profiling needs root privilege.";
    return false;
  }

  if (dump_symbols_ && can_dump_kernel_symbols_) {
    // No need to dump kernel symbols as we will dump all required symbols.
    can_dump_kernel_symbols_ = false;
  }

  if (non_option_args != nullptr) {
    non_option_args->clear();
    for (; i < args.size(); ++i) {
      non_option_args->push_back(args[i]);
    }
  }
  return true;
}

bool RecordCommand::SetEventSelectionFlags() {
  for (const auto& group : event_selection_set_.groups()) {
    for (const auto& selection : group) {
      if (use_sample_freq_) {
        event_selection_set_.SetSampleFreq(selection, sample_freq_);
      } else if (use_sample_period_) {
        event_selection_set_.SetSamplePeriod(selection, sample_period_);
      } else {
        if (selection.event_type_modifier.event_type.type ==
            PERF_TYPE_TRACEPOINT) {
          event_selection_set_.SetSamplePeriod(
              selection, DEFAULT_SAMPLE_PERIOD_FOR_TRACEPOINT_EVENT);
        } else {
          event_selection_set_.SetSampleFreq(
              selection, DEFAULT_SAMPLE_FREQ_FOR_NONTRACEPOINT_EVENT);
        }
      }
    }
  }
  event_selection_set_.SampleIdAll();
  if (!event_selection_set_.SetBranchSampling(branch_sampling_)) {
    return false;
  }
  if (fp_callchain_sampling_) {
    event_selection_set_.EnableFpCallChainSampling();
  } else if (dwarf_callchain_sampling_) {
    if (!event_selection_set_.EnableDwarfCallChainSampling(
            dump_stack_size_in_dwarf_sampling_)) {
      return false;
    }
  }
  event_selection_set_.SetInherit(child_inherit_);
  return true;
}

bool RecordCommand::CreateAndInitRecordFile() {
  record_file_writer_ = CreateRecordFile(record_filename_);
  if (record_file_writer_ == nullptr) {
    return false;
  }
  // Use first perf_event_attr and first event id to dump mmap and comm records.
  const EventSelection& selection = event_selection_set_.groups()[0][0];
  const perf_event_attr& attr = selection.event_attr;
  const std::vector<std::unique_ptr<EventFd>>& fds = selection.event_fds;
  uint64_t event_id = fds[0]->Id();
  if (!DumpKernelSymbol()) {
    return false;
  }
  if (!DumpTracingData()) {
    return false;
  }
  if (!DumpKernelAndModuleMmaps(attr, event_id)) {
    return false;
  }
  if (!DumpThreadCommAndMmaps(attr, event_id, system_wide_collection_,
                              monitored_threads_)) {
    return false;
  }
  return true;
}

std::unique_ptr<RecordFileWriter> RecordCommand::CreateRecordFile(
    const std::string& filename) {
  std::unique_ptr<RecordFileWriter> writer =
      RecordFileWriter::CreateInstance(filename);
  if (writer == nullptr) {
    return nullptr;
  }

  std::vector<AttrWithId> attr_ids;
  for (const auto& group : event_selection_set_.groups()) {
    for (const auto& selection : group) {
      AttrWithId attr_id;
      attr_id.attr = &selection.event_attr;
      CHECK(attr_id.attr != nullptr);
      const std::vector<std::unique_ptr<EventFd>>& fds = selection.event_fds;
      for (const auto& fd : fds) {
        attr_id.ids.push_back(fd->Id());
      }
      attr_ids.push_back(attr_id);
    }
  }
  if (!writer->WriteAttrSection(attr_ids)) {
    return nullptr;
  }
  return writer;
}

bool RecordCommand::DumpKernelSymbol() {
  if (can_dump_kernel_symbols_) {
    std::string kallsyms;
    bool need_kernel_symbol = false;
    for (const auto& group : event_selection_set_.groups()) {
      for (const auto& selection : group) {
        if (!selection.event_type_modifier.exclude_kernel) {
          need_kernel_symbol = true;
        }
      }
    }
    if (need_kernel_symbol) {
      if (!android::base::ReadFileToString("/proc/kallsyms", &kallsyms)) {
        PLOG(ERROR) << "failed to read /proc/kallsyms";
        return false;
      }
    }
    std::vector<KernelSymbolRecord> records =
        KernelSymbolRecord::Create(std::move(kallsyms));
    for (auto& r : records) {
      if (!ProcessRecord(&r)) {
        return false;
      }
    }
  }
  return true;
}

bool RecordCommand::DumpTracingData() {
  std::vector<const EventType*> tracepoint_event_types;
  for (const auto& group : event_selection_set_.groups()) {
    for (const auto& selection : group) {
      if (selection.event_type_modifier.event_type.type ==
          PERF_TYPE_TRACEPOINT) {
        tracepoint_event_types.push_back(
            &selection.event_type_modifier.event_type);
      }
    }
  }
  if (tracepoint_event_types.empty()) {
    return true;  // No need to dump tracing data.
  }
  std::vector<char> tracing_data;
  if (!GetTracingData(tracepoint_event_types, &tracing_data)) {
    return false;
  }
  TracingDataRecord record = TracingDataRecord::Create(std::move(tracing_data));
  if (!ProcessRecord(&record)) {
    return false;
  }
  return true;
}

bool RecordCommand::DumpKernelAndModuleMmaps(const perf_event_attr& attr,
                                             uint64_t event_id) {
  KernelMmap kernel_mmap;
  std::vector<KernelMmap> module_mmaps;
  GetKernelAndModuleMmaps(&kernel_mmap, &module_mmaps);

  MmapRecord mmap_record =
      MmapRecord::Create(attr, true, UINT_MAX, 0, kernel_mmap.start_addr,
                         kernel_mmap.len, 0, kernel_mmap.filepath, event_id);
  if (!ProcessRecord(&mmap_record)) {
    return false;
  }
  for (auto& module_mmap : module_mmaps) {
    MmapRecord mmap_record =
        MmapRecord::Create(attr, true, UINT_MAX, 0, module_mmap.start_addr,
                           module_mmap.len, 0, module_mmap.filepath, event_id);
    if (!ProcessRecord(&mmap_record)) {
      return false;
    }
  }
  return true;
}

bool RecordCommand::DumpThreadCommAndMmaps(
    const perf_event_attr& attr, uint64_t event_id, bool all_threads,
    const std::vector<pid_t>& selected_threads) {
  std::vector<ThreadComm> thread_comms;
  if (!GetThreadComms(&thread_comms)) {
    return false;
  }
  // Decide which processes and threads to dump.
  std::set<pid_t> dump_processes;
  std::set<pid_t> dump_threads;
  for (auto& tid : selected_threads) {
    dump_threads.insert(tid);
  }
  for (auto& thread : thread_comms) {
    if (dump_threads.find(thread.tid) != dump_threads.end()) {
      dump_processes.insert(thread.pid);
    }
  }

  // Dump processes.
  for (auto& thread : thread_comms) {
    if (thread.pid != thread.tid) {
      continue;
    }
    if (!all_threads &&
        dump_processes.find(thread.pid) == dump_processes.end()) {
      continue;
    }
    CommRecord record =
        CommRecord::Create(attr, thread.pid, thread.tid, thread.comm, event_id);
    if (!ProcessRecord(&record)) {
      return false;
    }
    std::vector<ThreadMmap> thread_mmaps;
    if (!GetThreadMmapsInProcess(thread.pid, &thread_mmaps)) {
      // The thread may exit before we get its info.
      continue;
    }
    for (auto& thread_mmap : thread_mmaps) {
      if (thread_mmap.executable == 0) {
        continue;  // No need to dump non-executable mmap info.
      }
      MmapRecord record = MmapRecord::Create(
          attr, false, thread.pid, thread.tid, thread_mmap.start_addr,
          thread_mmap.len, thread_mmap.pgoff, thread_mmap.name, event_id);
      if (!ProcessRecord(&record)) {
        return false;
      }
    }
  }

  // Dump threads.
  for (auto& thread : thread_comms) {
    if (thread.pid == thread.tid) {
      continue;
    }
    if (!all_threads && dump_threads.find(thread.tid) == dump_threads.end()) {
      continue;
    }
    ForkRecord fork_record = ForkRecord::Create(
        attr, thread.pid, thread.tid, thread.pid, thread.pid, event_id);
    if (!ProcessRecord(&fork_record)) {
      return false;
    }
    CommRecord comm_record =
        CommRecord::Create(attr, thread.pid, thread.tid, thread.comm, event_id);
    if (!ProcessRecord(&comm_record)) {
      return false;
    }
  }
  return true;
}

bool RecordCommand::ProcessRecord(Record* record) {
  UpdateRecordForEmbeddedElfPath(record);
  thread_tree_.Update(*record);
  CollectHitFileInfo(record);
  if (unwind_dwarf_callchain_ && !post_unwind_) {
    if (!UnwindRecord(record)) {
      return false;
    }
  }
  if (record->type() == PERF_RECORD_SAMPLE) {
    sample_record_count_++;
    if (dump_symbols_) {
      auto& r = *static_cast<SampleRecord*>(record);
      if (!DumpSymbolForRecord(r, false)) {
        return false;
      }
    }
  }
  bool result = record_file_writer_->WriteData(record->BinaryFormat());
  return result;
}

bool RecordCommand::DumpSymbolForRecord(const SampleRecord& r,
                                        bool for_callchain) {
  const ThreadEntry* thread =
      thread_tree_.FindThreadOrNew(r.tid_data.pid, r.tid_data.tid);
  const std::vector<uint64_t>& ips = for_callchain
                                         ? r.callchain_data.ips
                                         : std::vector<uint64_t>{r.ip_data.ip};
  for (auto& ip : ips) {
    const MapEntry* map = thread_tree_.FindMap(thread, ip, r.InKernel());
    if (!map->dso->HasDumped()) {
      map->dso->SetDumped();
      DsoRecord dso_record =
          DsoRecord::Create(map->dso->type(), map->dso->id(), map->dso->Path());
      if (!record_file_writer_->WriteData(dso_record.BinaryFormat())) {
        return false;
      }
    }
    const Symbol* symbol = thread_tree_.FindSymbol(map, ip);
    if (!symbol->HasDumped()) {
      symbol->SetDumped();
      SymbolRecord symbol_record = SymbolRecord::Create(
          symbol->addr, symbol->len, symbol->Name(), map->dso->id());
      if (!record_file_writer_->WriteData(symbol_record.BinaryFormat())) {
        return false;
      }
    }
  }
  return true;
}

template <class RecordType>
void UpdateMmapRecordForEmbeddedElfPath(RecordType* record) {
  RecordType& r = *record;
  if (!r.InKernel() && r.data.pgoff != 0) {
    // For the case of a shared library "foobar.so" embedded
    // inside an APK, we rewrite the original MMAP from
    // ["path.apk" offset=X] to ["path.apk!/foobar.so" offset=W]
    // so as to make the library name explicit. This update is
    // done here (as part of the record operation) as opposed to
    // on the host during the report, since we want to report
    // the correct library name even if the the APK in question
    // is not present on the host. The new offset W is
    // calculated to be with respect to the start of foobar.so,
    // not to the start of path.apk.
    EmbeddedElf* ee =
        ApkInspector::FindElfInApkByOffset(r.filename, r.data.pgoff);
    if (ee != nullptr) {
      // Compute new offset relative to start of elf in APK.
      r.data.pgoff -= ee->entry_offset();
      r.filename = GetUrlInApk(r.filename, ee->entry_name());
      r.AdjustSizeBasedOnData();
    }
  }
}

void RecordCommand::UpdateRecordForEmbeddedElfPath(Record* record) {
  if (record->type() == PERF_RECORD_MMAP) {
    UpdateMmapRecordForEmbeddedElfPath(static_cast<MmapRecord*>(record));
  } else if (record->type() == PERF_RECORD_MMAP2) {
    UpdateMmapRecordForEmbeddedElfPath(static_cast<Mmap2Record*>(record));
  }
}

bool RecordCommand::UnwindRecord(Record* record) {
  if (record->type() == PERF_RECORD_SAMPLE) {
    SampleRecord& r = *static_cast<SampleRecord*>(record);
    if ((r.sample_type & PERF_SAMPLE_CALLCHAIN) &&
        (r.sample_type & PERF_SAMPLE_REGS_USER) &&
        (r.regs_user_data.reg_mask != 0) &&
        (r.sample_type & PERF_SAMPLE_STACK_USER) &&
        (!r.stack_user_data.data.empty())) {
      ThreadEntry* thread =
          thread_tree_.FindThreadOrNew(r.tid_data.pid, r.tid_data.tid);
      RegSet regs =
          CreateRegSet(r.regs_user_data.reg_mask, r.regs_user_data.regs);
      std::vector<char>& stack = r.stack_user_data.data;
      ArchType arch = GetArchForAbi(GetBuildArch(), r.regs_user_data.abi);
      // Normally do strict arch check when unwinding stack. But allow unwinding
      // 32-bit processes on 64-bit devices for system wide profiling.
      bool strict_arch_check = !system_wide_collection_;
      std::vector<uint64_t> unwind_ips =
          UnwindCallChain(arch, *thread, regs, stack, strict_arch_check);
      r.callchain_data.ips.push_back(PERF_CONTEXT_USER);
      r.callchain_data.ips.insert(r.callchain_data.ips.end(),
                                  unwind_ips.begin(), unwind_ips.end());
      r.regs_user_data.abi = 0;
      r.regs_user_data.reg_mask = 0;
      r.regs_user_data.regs.clear();
      r.stack_user_data.data.clear();
      r.stack_user_data.dyn_size = 0;
      r.AdjustSizeBasedOnData();
      if (!DumpSymbolForRecord(r, true)) {
        return false;
      }
    }
  }
  return true;
}

bool RecordCommand::PostUnwind(const std::vector<std::string>& args) {
  thread_tree_.ClearThreadAndMap();
  std::unique_ptr<RecordFileReader> reader =
      RecordFileReader::CreateInstance(record_filename_);
  if (reader == nullptr) {
    return false;
  }
  std::string tmp_filename = record_filename_ + ".tmp";
  record_file_writer_ = CreateRecordFile(tmp_filename);
  if (record_file_writer_ == nullptr) {
    return false;
  }
  bool result = reader->ReadDataSection(
      [this](std::unique_ptr<Record> record) {
        thread_tree_.Update(*record);
        if (!UnwindRecord(record.get())) {
          return false;
        }
        return record_file_writer_->WriteData(record->BinaryFormat());
      },
      false);
  if (!result) {
    return false;
  }
  if (!DumpAdditionalFeatures(args)) {
    return false;
  }
  if (!record_file_writer_->Close()) {
    return false;
  }

  if (unlink(record_filename_.c_str()) != 0) {
    PLOG(ERROR) << "failed to remove " << record_filename_;
    return false;
  }
  if (rename(tmp_filename.c_str(), record_filename_.c_str()) != 0) {
    PLOG(ERROR) << "failed to rename " << tmp_filename << " to "
                << record_filename_;
    return false;
  }
  return true;
}

bool RecordCommand::DumpAdditionalFeatures(
    const std::vector<std::string>& args) {
  size_t feature_count = (branch_sampling_ != 0 ? 5 : 4);
  if (!record_file_writer_->WriteFeatureHeader(feature_count)) {
    return false;
  }
  if (!DumpBuildIdFeature()) {
    return false;
  }
  utsname uname_buf;
  if (TEMP_FAILURE_RETRY(uname(&uname_buf)) != 0) {
    PLOG(ERROR) << "uname() failed";
    return false;
  }
  if (!record_file_writer_->WriteFeatureString(PerfFileFormat::FEAT_OSRELEASE,
                                               uname_buf.release)) {
    return false;
  }
  if (!record_file_writer_->WriteFeatureString(PerfFileFormat::FEAT_ARCH,
                                               uname_buf.machine)) {
    return false;
  }

  std::string exec_path = "simpleperf";
  GetExecPath(&exec_path);
  std::vector<std::string> cmdline;
  cmdline.push_back(exec_path);
  cmdline.push_back("record");
  cmdline.insert(cmdline.end(), args.begin(), args.end());
  if (!record_file_writer_->WriteCmdlineFeature(cmdline)) {
    return false;
  }
  if (branch_sampling_ != 0 &&
      !record_file_writer_->WriteBranchStackFeature()) {
    return false;
  }
  return true;
}

bool RecordCommand::DumpBuildIdFeature() {
  std::vector<BuildIdRecord> build_id_records;
  BuildId build_id;
  // Add build_ids for kernel/modules.
  for (const auto& filename : hit_kernel_modules_) {
    if (filename == DEFAULT_KERNEL_FILENAME_FOR_BUILD_ID) {
      if (!GetKernelBuildId(&build_id)) {
        LOG(DEBUG) << "can't read build_id for kernel";
        continue;
      }
      build_id_records.push_back(BuildIdRecord::Create(
          true, UINT_MAX, build_id, DEFAULT_KERNEL_FILENAME_FOR_BUILD_ID));
    } else {
      std::string path = filename;
      std::string module_name = basename(&path[0]);
      if (android::base::EndsWith(module_name, ".ko")) {
        module_name = module_name.substr(0, module_name.size() - 3);
      }
      if (!GetModuleBuildId(module_name, &build_id)) {
        LOG(DEBUG) << "can't read build_id for module " << module_name;
        continue;
      }
      build_id_records.push_back(
          BuildIdRecord::Create(true, UINT_MAX, build_id, filename));
    }
  }
  // Add build_ids for user elf files.
  for (const auto& filename : hit_user_files_) {
    if (filename == DEFAULT_EXECNAME_FOR_THREAD_MMAP) {
      continue;
    }
    auto tuple = SplitUrlInApk(filename);
    if (std::get<0>(tuple)) {
      if (!GetBuildIdFromApkFile(std::get<1>(tuple), std::get<2>(tuple),
                                 &build_id)) {
        LOG(DEBUG) << "can't read build_id from file " << filename;
        continue;
      }
    } else {
      if (!GetBuildIdFromElfFile(filename, &build_id)) {
        LOG(DEBUG) << "can't read build_id from file " << filename;
        continue;
      }
    }
    build_id_records.push_back(
        BuildIdRecord::Create(false, UINT_MAX, build_id, filename));
  }
  if (!record_file_writer_->WriteBuildIdFeature(build_id_records)) {
    return false;
  }
  return true;
}

void RecordCommand::CollectHitFileInfo(Record* record) {
  if (record->type() == PERF_RECORD_SAMPLE) {
    auto r = *static_cast<SampleRecord*>(record);
    bool in_kernel = r.InKernel();
    const ThreadEntry* thread =
        thread_tree_.FindThreadOrNew(r.tid_data.pid, r.tid_data.tid);
    const MapEntry* map = thread_tree_.FindMap(thread, r.ip_data.ip, in_kernel);
    if (in_kernel) {
      hit_kernel_modules_.insert(map->dso->Path());
    } else {
      hit_user_files_.insert(map->dso->Path());
    }
  }
}

void RegisterRecordCommand() {
  RegisterCommand("record",
                  [] { return std::unique_ptr<Command>(new RecordCommand()); });
}
