/*
 * Copyright (C) 2020 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 <inttypes.h>
#include <libgen.h>
#include <signal.h>
#include <sys/mman.h>
#include <sys/prctl.h>
#include <sys/utsname.h>
#include <time.h>
#include <unistd.h>
#include <optional>
#include <set>
#include <string>
#include <unordered_map>
#include <unordered_set>
#include <vector>

#include <android-base/file.h>
#include <android-base/logging.h>
#include <android-base/parseint.h>
#include <android-base/stringprintf.h>
#include <android-base/strings.h>
#include <android-base/unique_fd.h>
#if defined(__ANDROID__)
#include <android-base/properties.h>
#endif

#include "IOEventLoop.h"
#include "MapRecordReader.h"
#include "OfflineUnwinder.h"
#include "RecordFilter.h"
#include "command.h"
#include "dso.h"
#include "environment.h"
#include "event_selection_set.h"
#include "event_type.h"
#include "read_elf.h"
#include "read_symbol_map.h"
#include "record.h"
#include "thread_tree.h"
#include "tracing.h"
#include "utils.h"

namespace simpleperf {
namespace {

using android::base::ParseUint;
using android::base::Realpath;
using android::base::StringAppendF;

struct SymbolInfo {
  Dso* dso;
  const Symbol* symbol;
  uint64_t vaddr_in_file;
};

// The max size of records dumped by kernel is 65535, and dump stack size
// should be a multiply of 8, so MAX_DUMP_STACK_SIZE is 65528.
constexpr uint32_t MAX_DUMP_STACK_SIZE = 65528;

// The max allowed pages in mapped buffer is decided by rlimit(RLIMIT_MEMLOCK).
// Here 1024 is a desired value for pages in mapped buffer. If mapped
// successfully, the buffer size = 1024 * 4K (page size) = 4M.
constexpr size_t DESIRED_PAGES_IN_MAPPED_BUFFER = 1024;

// Currently, the record buffer size in user-space is set to match the kernel
// buffer size on a 8 core system. For system-wide recording, it is 8K pages *
// 4K page_size * 8 cores = 256MB. For non system-wide recording, it is 1K pages
// * 4K page_size * 8 cores = 64MB.
static constexpr size_t kRecordBufferSize = 64 * kMegabyte;
static constexpr size_t kSystemWideRecordBufferSize = 256 * kMegabyte;

class MonitorCommand : public Command {
 public:
  MonitorCommand()
      : Command(
            "monitor", "monitor events and print their textual representations to stdout",
            // clang-format off
"Usage: simpleperf monitor [options]\n"
"       Gather sampling information and print the events on stdout.\n"
"       For precise recording, prefer the record command.\n"
"       Currently, only supports system-wide collection.\n"
"\n"
"Select monitored threads:\n"
"-a               System-wide collection. Use with --exclude-perf to exclude\n"
"                 samples for simpleperf process.\n"
"\n"
"Select monitored event types:\n"
"-e event1[:modifier1],event2[:modifier2],...\n"
"             Select a list of events to record. An event can be:\n"
"               1) an event name listed in `simpleperf list`;\n"
"               2) a raw PMU event in rN format. N is a hex number.\n"
"                  For example, r1b selects event number 0x1b.\n"
"             Modifiers can be added to define how the event should be\n"
"             monitored. Possible modifiers are:\n"
"                u - monitor user space events only\n"
"                k - monitor kernel space events only\n"
"\n"
"Select monitoring options:\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. A -f/-c option affects all event types\n"
"             following it until meeting another -f/-c option. For example,\n"
"             for \"-f 1000 -e cpu-cycles -c 1 -e sched:sched_switch\", cpu-cycles\n"
"             has sample freq 1000, sched:sched_switch event has sample period 1.\n"
"-c count     Set event sample period. It means recording one sample when\n"
"             [count] events happen. For tracepoint events, the default option\n"
"             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,65528.\n"
"-g           Same as '--call-graph dwarf'.\n"
"--duration time_in_sec  Monitor for time_in_sec seconds. Here time_in_sec"
"                        may be any positive floating point number.\n"
"--cpu-percent <percent>  Set the max percent of cpu time used for recording.\n"
"                         percent is in range [1-100], default is 25.\n"
"\n"
"Sample filter options:\n"
"--exclude-perf                Exclude samples for simpleperf process.\n"
RECORD_FILTER_OPTION_HELP_MSG_FOR_RECORDING
"\n"
            // clang-format on
            ),
        system_wide_collection_(false),
        fp_callchain_sampling_(false),
        dwarf_callchain_sampling_(false),
        dump_stack_size_in_dwarf_sampling_(MAX_DUMP_STACK_SIZE),
        unwind_dwarf_callchain_(true),
        duration_in_sec_(0),
        event_selection_set_(false),
        mmap_page_range_(std::make_pair(1, DESIRED_PAGES_IN_MAPPED_BUFFER)),
        sample_record_count_(0),
        last_record_timestamp_(0u),
        record_filter_(thread_tree_) {
    // If we run `adb shell simpleperf record xxx` and stop profiling by ctrl-c,
    // adb closes sockets connecting simpleperf. After that, simpleperf will
    // receive SIGPIPE when writing to stdout/stderr, which is a problem when we
    // use '--app' option. So ignore SIGPIPE to finish properly.
    signal(SIGPIPE, SIG_IGN);
  }

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

 private:
  bool ParseOptions(const std::vector<std::string>& args);
  bool AdjustPerfEventLimit();
  bool PrepareMonitoring();
  bool DoMonitoring();
  bool SetEventSelectionFlags();
  bool DumpProcessMaps(pid_t pid, const std::unordered_set<pid_t>& tids);
  void DumpSampleRecord(const SampleRecord& sr);
  void DumpSampleCallchain(const SampleRecord& sr);
  bool ProcessRecord(Record* record);
  SymbolInfo GetSymbolInfo(uint32_t pid, uint32_t tid, uint64_t ip, bool in_kernel);
  bool DumpMapsForRecord(Record* record);
  void UpdateRecord(Record* record);
  bool UnwindRecord(SampleRecord& r);

  uint64_t max_sample_freq_ = DEFAULT_SAMPLE_FREQ_FOR_NONTRACEPOINT_EVENT;
  size_t cpu_time_max_percent_ = 25;

  bool system_wide_collection_;
  bool fp_callchain_sampling_;
  bool dwarf_callchain_sampling_;
  uint32_t dump_stack_size_in_dwarf_sampling_;
  bool unwind_dwarf_callchain_;
  std::unique_ptr<OfflineUnwinder> offline_unwinder_;
  double duration_in_sec_;
  EventSelectionSet event_selection_set_;
  std::pair<size_t, size_t> mmap_page_range_;
  ThreadTree thread_tree_;
  uint64_t sample_record_count_;
  uint64_t last_record_timestamp_;  // used to insert Mmap2Records for JIT debug info
  // In system wide recording, record if we have dumped map info for a process.
  std::unordered_set<pid_t> dumped_processes_;
  bool exclude_perf_ = false;
  RecordFilter record_filter_;
  std::unordered_map<uint64_t, std::string> event_names_;

  std::optional<MapRecordReader> map_record_reader_;
};

bool MonitorCommand::Run(const std::vector<std::string>& args) {
  ScopedCurrentArch scoped_arch(GetMachineArch());
  if (!CheckPerfEventLimit()) {
    return false;
  }
  AllowMoreOpenedFiles();

  if (!ParseOptions(args)) {
    return false;
  }
  if (!AdjustPerfEventLimit()) {
    return false;
  }

  if (!PrepareMonitoring()) {
    return false;
  }
  return DoMonitoring();
}

bool MonitorCommand::PrepareMonitoring() {
  // 1. Process options before opening perf event files.
  if (!SetEventSelectionFlags()) {
    return false;
  }
  if (unwind_dwarf_callchain_) {
    offline_unwinder_ = OfflineUnwinder::Create(false);
  }

  // 2. Add monitored targets.
  if (system_wide_collection_) {
    event_selection_set_.AddMonitoredThreads({-1});
  } else {
    LOG(ERROR) << "No threads to monitor. Try `simpleperf help monitor` for help";
    return false;
  }

  // 3. Open perf event files and create mapped buffers.
  if (!event_selection_set_.OpenEventFiles()) {
    return false;
  }
  size_t record_buffer_size =
      system_wide_collection_ ? kSystemWideRecordBufferSize : kRecordBufferSize;
  if (!event_selection_set_.MmapEventFiles(mmap_page_range_.first, mmap_page_range_.second,
                                           0 /* aux_buffer_size */, record_buffer_size,
                                           false /* allow_truncating_samples */, exclude_perf_)) {
    return false;
  }
  auto callback = std::bind(&MonitorCommand::ProcessRecord, this, std::placeholders::_1);
  if (!event_selection_set_.PrepareToReadMmapEventData(callback)) {
    return false;
  }

  // Keep track of the event names per id.
  event_names_ = event_selection_set_.GetEventNamesById();

  // Use first perf_event_attr and first event id to dump mmap and comm records.
  EventAttrWithId dumping_attr_id = event_selection_set_.GetEventAttrWithId()[0];
  map_record_reader_.emplace(dumping_attr_id.attr, dumping_attr_id.ids[0],
                             event_selection_set_.RecordNotExecutableMaps());
  map_record_reader_->SetCallback([this](Record* r) { return ProcessRecord(r); });

  // 4. Load kallsyms, if possible.
  std::string kallsyms;
  if (LoadKernelSymbols(&kallsyms)) {
    Dso::SetKallsyms(std::move(kallsyms));
  }
  map_record_reader_->ReadKernelMaps();

  // 5. Add read/signal/periodic Events.
  IOEventLoop* loop = event_selection_set_.GetIOEventLoop();
  auto exit_loop_callback = [loop]() { return loop->ExitLoop(); };
  if (!loop->AddSignalEvents({SIGCHLD, SIGINT, SIGTERM}, exit_loop_callback, IOEventHighPriority)) {
    return false;
  }

  // Only add an event for SIGHUP if we didn't inherit SIG_IGN (e.g. from
  // nohup).
  if (!SignalIsIgnored(SIGHUP)) {
    if (!loop->AddSignalEvent(SIGHUP, exit_loop_callback, IOEventHighPriority)) {
      return false;
    }
  }

  if (duration_in_sec_ != 0) {
    if (!loop->AddPeriodicEvent(
            SecondToTimeval(duration_in_sec_), [loop]() { return loop->ExitLoop(); },
            IOEventHighPriority)) {
      return false;
    }
  }
  return true;
}

bool MonitorCommand::DoMonitoring() {
  if (!event_selection_set_.GetIOEventLoop()->RunLoop()) {
    return false;
  }
  if (!event_selection_set_.SyncKernelBuffer()) {
    return false;
  }
  event_selection_set_.CloseEventFiles();
  if (!event_selection_set_.FinishReadMmapEventData()) {
    return false;
  }
  LOG(ERROR) << "Processed samples: " << sample_record_count_;
  return true;
}

inline const OptionFormatMap& GetMonitorCmdOptionFormats() {
  static OptionFormatMap option_formats;
  if (option_formats.empty()) {
    option_formats = {
        {"-a", {OptionValueType::NONE, OptionType::SINGLE, AppRunnerType::NOT_ALLOWED}},
        {"-c", {OptionValueType::UINT, OptionType::ORDERED, AppRunnerType::ALLOWED}},
        {"--call-graph", {OptionValueType::STRING, OptionType::ORDERED, AppRunnerType::ALLOWED}},
        {"--cpu-percent", {OptionValueType::UINT, OptionType::SINGLE, AppRunnerType::ALLOWED}},
        {"--duration", {OptionValueType::DOUBLE, OptionType::SINGLE, AppRunnerType::ALLOWED}},
        {"-e", {OptionValueType::STRING, OptionType::ORDERED, AppRunnerType::ALLOWED}},
        {"--exclude-perf", {OptionValueType::NONE, OptionType::SINGLE, AppRunnerType::ALLOWED}},
        {"-f", {OptionValueType::UINT, OptionType::ORDERED, AppRunnerType::ALLOWED}},
        {"-g", {OptionValueType::NONE, OptionType::ORDERED, AppRunnerType::ALLOWED}},
        {"-t", {OptionValueType::STRING, OptionType::MULTIPLE, AppRunnerType::ALLOWED}},
    };
    OptionFormatMap record_filter_options = GetRecordFilterOptionFormats(true);
    option_formats.insert(record_filter_options.begin(), record_filter_options.end());
  }
  return option_formats;
}

bool MonitorCommand::ParseOptions(const std::vector<std::string>& args) {
  OptionValueMap options;
  std::vector<std::pair<OptionName, OptionValue>> ordered_options;

  if (!PreprocessOptions(args, GetMonitorCmdOptionFormats(), &options, &ordered_options, nullptr)) {
    return false;
  }

  // Process options.
  system_wide_collection_ = options.PullBoolValue("-a");

  if (!options.PullUintValue("--cpu-percent", &cpu_time_max_percent_, 1, 100)) {
    return false;
  }

  if (!options.PullDoubleValue("--duration", &duration_in_sec_, 1e-9)) {
    return false;
  }

  exclude_perf_ = options.PullBoolValue("--exclude-perf");
  if (!record_filter_.ParseOptions(options)) {
    return false;
  }

  CHECK(options.values.empty());

  // Process ordered options.
  for (const auto& pair : ordered_options) {
    const OptionName& name = pair.first;
    const OptionValue& value = pair.second;

    if (name == "-c" || name == "-f") {
      if (value.uint_value < 1) {
        LOG(ERROR) << "invalid " << name << ": " << value.uint_value;
        return false;
      }
      SampleRate rate;
      if (name == "-c") {
        rate.sample_period = value.uint_value;
      } else {
        if (value.uint_value >= INT_MAX) {
          LOG(ERROR) << "sample freq can't be bigger than INT_MAX: " << value.uint_value;
          return false;
        }
        rate.sample_freq = value.uint_value;
      }
      event_selection_set_.SetSampleRateForNewEvents(rate);

    } else if (name == "--call-graph") {
      std::vector<std::string> strs = android::base::Split(*value.str_value, ",");
      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) {
          uint64_t size;
          if (!ParseUint(strs[1], &size)) {
            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;
          }
          if (size >= MAX_DUMP_STACK_SIZE) {
            LOG(ERROR) << "dump stack size " << size << " is bigger than max allowed size "
                       << MAX_DUMP_STACK_SIZE << ".";
            return false;
          }
          dump_stack_size_in_dwarf_sampling_ = static_cast<uint32_t>(size);
        }
      }

    } else if (name == "-e") {
      std::vector<std::string> event_types = android::base::Split(*value.str_value, ",");
      for (auto& event_type : event_types) {
        if (!event_selection_set_.AddEventType(event_type)) {
          return false;
        }
      }

    } else if (name == "-g") {
      fp_callchain_sampling_ = false;
      dwarf_callchain_sampling_ = true;
    } else {
      CHECK(false) << "unprocessed option: " << name;
    }
  }

  if (event_selection_set_.empty()) {
    LOG(ERROR) << "No event to record. Use `-e` to specify which event should be monitored.";
    return false;
  }

  if (fp_callchain_sampling_) {
    if (GetTargetArch() == ARCH_ARM) {
      LOG(WARNING) << "`--callgraph fp` option doesn't work well on arm architecture, "
                   << "consider using `-g` option or profiling on aarch64 architecture.";
    }
  }

  if (system_wide_collection_ && event_selection_set_.HasMonitoredTarget()) {
    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;
  }
  return true;
}

bool MonitorCommand::AdjustPerfEventLimit() {
  bool set_prop = false;
  // 1. Adjust max_sample_rate.
  uint64_t cur_max_freq;
  if (GetMaxSampleFrequency(&cur_max_freq) && cur_max_freq < max_sample_freq_ &&
      !SetMaxSampleFrequency(max_sample_freq_)) {
    set_prop = true;
  }
  // 2. Adjust perf_cpu_time_max_percent.
  size_t cur_percent;
  if (GetCpuTimeMaxPercent(&cur_percent) && cur_percent != cpu_time_max_percent_ &&
      !SetCpuTimeMaxPercent(cpu_time_max_percent_)) {
    set_prop = true;
  }
  // 3. Adjust perf_event_mlock_kb.
  long cpus = sysconf(_SC_NPROCESSORS_CONF);
  uint64_t mlock_kb = cpus * (mmap_page_range_.second + 1) * 4;

  uint64_t cur_mlock_kb;
  if (GetPerfEventMlockKb(&cur_mlock_kb) && cur_mlock_kb < mlock_kb &&
      !SetPerfEventMlockKb(mlock_kb)) {
    set_prop = true;
  }

  if (GetAndroidVersion() >= kAndroidVersionQ && set_prop) {
    return SetPerfEventLimits(std::max(max_sample_freq_, cur_max_freq), cpu_time_max_percent_,
                              std::max(mlock_kb, cur_mlock_kb));
  }
  return true;
}

bool MonitorCommand::SetEventSelectionFlags() {
  event_selection_set_.SampleIdAll();
  event_selection_set_.WakeupPerSample();
  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;
    }
  }
  return true;
}

bool MonitorCommand::ProcessRecord(Record* record) {
  UpdateRecord(record);
  last_record_timestamp_ = std::max(last_record_timestamp_, record->Timestamp());
  // In system wide recording, maps are dumped when they are needed by records.
  if (system_wide_collection_ && !DumpMapsForRecord(record)) {
    return false;
  }
  if (record->type() == PERF_RECORD_SAMPLE) {
    auto& r = *static_cast<SampleRecord*>(record);

    // Record filter check should go after DumpMapsForRecord(). Otherwise, process/thread name
    // filters don't work in system wide collection.
    if (!record_filter_.Check(r)) {
      return true;
    }

    // AdjustCallChainGeneratedByKernel() should go before UnwindRecord().
    // Because we don't want to adjust callchains generated by dwarf unwinder.
    if (fp_callchain_sampling_ || dwarf_callchain_sampling_) {
      r.AdjustCallChainGeneratedByKernel();
      if (!UnwindRecord(r)) {
        return false;
      }
    }
    DumpSampleRecord(r);
    if (fp_callchain_sampling_ || dwarf_callchain_sampling_) {
      DumpSampleCallchain(r);
    }
    sample_record_count_++;
  } else {
    // Other types of record are forwarded to the thread tree to build the
    // representation of each processes (mmap, comm, etc).
    thread_tree_.Update(*record);
  }
  return true;
}

void MonitorCommand::DumpSampleRecord(const SampleRecord& sr) {
  std::string output("sample");
  StringAppendF(&output, " name=%s", event_names_[sr.id_data.id].c_str());
  StringAppendF(&output, " ip=%p", reinterpret_cast<void*>(sr.ip_data.ip));
  SymbolInfo s = GetSymbolInfo(sr.tid_data.pid, sr.tid_data.tid, sr.ip_data.ip, sr.InKernel());
  StringAppendF(&output, " symbol=%s (%s[+%" PRIx64 "])", s.symbol->DemangledName(),
                s.dso->Path().c_str(), s.vaddr_in_file);
  StringAppendF(&output, " pid=%u tid=%u", sr.tid_data.pid, sr.tid_data.tid);
  StringAppendF(&output, " cpu=%u", sr.cpu_data.cpu);
  printf("%s\n", output.c_str());
  fflush(stdout);
}

void MonitorCommand::DumpSampleCallchain(const SampleRecord& sr) {
  bool in_kernel = sr.InKernel();
  if (sr.sample_type & PERF_SAMPLE_CALLCHAIN) {
    for (size_t i = 0; i < sr.callchain_data.ip_nr; ++i) {
      if (sr.callchain_data.ips[i] >= PERF_CONTEXT_MAX) {
        if (sr.callchain_data.ips[i] == PERF_CONTEXT_USER) {
          in_kernel = false;
        }
        continue;
      }
      SymbolInfo s =
          GetSymbolInfo(sr.tid_data.pid, sr.tid_data.tid, sr.callchain_data.ips[i], in_kernel);
      std::string output("sample callchain");
      StringAppendF(&output, " %s (%s[+%" PRIx64 "])", s.symbol->DemangledName(),
                    s.dso->Path().c_str(), s.vaddr_in_file);
      printf("%s\n", output.c_str());
    }
    fflush(stdout);
  }
}

SymbolInfo MonitorCommand::GetSymbolInfo(uint32_t pid, uint32_t tid, uint64_t ip, bool in_kernel) {
  ThreadEntry* thread = thread_tree_.FindThreadOrNew(pid, tid);
  const MapEntry* map = thread_tree_.FindMap(thread, ip, in_kernel);
  SymbolInfo info;
  info.symbol = thread_tree_.FindSymbol(map, ip, &info.vaddr_in_file, &info.dso);
  return info;
}

bool MonitorCommand::DumpMapsForRecord(Record* record) {
  if (record->type() == PERF_RECORD_SAMPLE) {
    pid_t pid = static_cast<SampleRecord*>(record)->tid_data.pid;
    if (dumped_processes_.find(pid) == dumped_processes_.end()) {
      // Dump map info and all thread names for that process.
      if (!map_record_reader_->ReadProcessMaps(pid, last_record_timestamp_)) {
        return false;
      }
      dumped_processes_.insert(pid);
    }
  }
  return true;
}

void MonitorCommand::UpdateRecord(Record* record) {
  if (record->type() == PERF_RECORD_COMM) {
    auto r = static_cast<CommRecord*>(record);
    if (r->data->pid == r->data->tid) {
      std::string s = GetCompleteProcessName(r->data->pid);
      if (!s.empty()) {
        r->SetCommandName(s);
      }
    }
  }
}

bool MonitorCommand::UnwindRecord(SampleRecord& r) {
  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.GetValidStackSize() > 0)) {
    ThreadEntry* thread = thread_tree_.FindThreadOrNew(r.tid_data.pid, r.tid_data.tid);
    RegSet regs(r.regs_user_data.abi, r.regs_user_data.reg_mask, r.regs_user_data.regs);
    std::vector<uint64_t> ips;
    std::vector<uint64_t> sps;
    if (!offline_unwinder_->UnwindCallChain(*thread, regs, r.stack_user_data.data,
                                            r.GetValidStackSize(), &ips, &sps)) {
      return false;
    }
    r.ReplaceRegAndStackWithCallChain(ips);
  }
  return true;
}
}  // namespace

void RegisterMonitorCommand() {
  RegisterCommand("monitor", [] { return std::unique_ptr<Command>(new MonitorCommand()); });
}

}  // namespace simpleperf
