/*
 * Copyright (C) 2016 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 <memory>
#include <utility>

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

#include "dso.h"
#include "event_attr.h"
#include "event_type.h"
#include "record_file.h"
#include "thread_tree.h"
#include "tracing.h"
#include "utils.h"

class ReportLib;

extern "C" {

#define EXPORT __attribute__((visibility("default")))

struct Sample {
  uint64_t ip;
  uint32_t pid;
  uint32_t tid;
  const char* thread_comm;
  uint64_t time;
  uint32_t in_kernel;
  uint32_t cpu;
  uint64_t period;
};

struct TracingFieldFormat {
  const char* name;
  uint32_t offset;
  uint32_t elem_size;
  uint32_t elem_count;
  uint32_t is_signed;
};

struct TracingDataFormat {
  uint32_t size;
  uint32_t field_count;
  TracingFieldFormat* fields;
};

struct Event {
  const char* name;
  TracingDataFormat tracing_data_format;
};

struct Mapping {
  uint64_t start;
  uint64_t end;
  uint64_t pgoff;
};

struct SymbolEntry {
  const char* dso_name;
  uint64_t vaddr_in_file;
  const char* symbol_name;
  uint64_t symbol_addr;
  uint64_t symbol_len;
  Mapping* mapping;
};

struct CallChainEntry {
  uint64_t ip;
  SymbolEntry symbol;
};

struct CallChain {
  uint32_t nr;
  CallChainEntry* entries;
};

struct FeatureSection {
  const char* data;
  uint32_t data_size;
};

// Create a new instance,
// pass the instance to the other functions below.
ReportLib* CreateReportLib() EXPORT;
void DestroyReportLib(ReportLib* report_lib) EXPORT;

// Set log severity, different levels are:
// verbose, debug, info, warning, error, fatal.
bool SetLogSeverity(ReportLib* report_lib, const char* log_level) EXPORT;
bool SetSymfs(ReportLib* report_lib, const char* symfs_dir) EXPORT;
bool SetRecordFile(ReportLib* report_lib, const char* record_file) EXPORT;
bool SetKallsymsFile(ReportLib* report_lib, const char* kallsyms_file) EXPORT;
void ShowIpForUnknownSymbol(ReportLib* report_lib) EXPORT;
void ShowArtFrames(ReportLib* report_lib, bool show) EXPORT;
void MergeJavaMethods(ReportLib* report_lib, bool merge) EXPORT;

Sample* GetNextSample(ReportLib* report_lib) EXPORT;
Event* GetEventOfCurrentSample(ReportLib* report_lib) EXPORT;
SymbolEntry* GetSymbolOfCurrentSample(ReportLib* report_lib) EXPORT;
CallChain* GetCallChainOfCurrentSample(ReportLib* report_lib) EXPORT;
const char* GetTracingDataOfCurrentSample(ReportLib* report_lib) EXPORT;

const char* GetBuildIdForPath(ReportLib* report_lib, const char* path) EXPORT;
FeatureSection* GetFeatureSection(ReportLib* report_lib, const char* feature_name) EXPORT;
}

struct EventInfo {
  perf_event_attr attr;
  std::string name;

  struct TracingInfo {
    TracingDataFormat data_format;
    std::vector<std::string> field_names;
    std::vector<TracingFieldFormat> fields;
  } tracing_info;
};

class ReportLib {
 public:
  ReportLib()
      : log_severity_(
            new android::base::ScopedLogSeverity(android::base::INFO)),
        record_filename_("perf.data"),
        current_thread_(nullptr),
        trace_offcpu_(false),
        show_art_frames_(false) {
  }

  bool SetLogSeverity(const char* log_level);

  bool SetSymfs(const char* symfs_dir) { return Dso::SetSymFsDir(symfs_dir); }

  bool SetRecordFile(const char* record_file) {
    record_filename_ = record_file;
    return true;
  }

  bool SetKallsymsFile(const char* kallsyms_file);

  void ShowIpForUnknownSymbol() { thread_tree_.ShowIpForUnknownSymbol(); }
  void ShowArtFrames(bool show) { show_art_frames_ = show; }
  void MergeJavaMethods(bool merge) { merge_java_methods_ = merge; }

  Sample* GetNextSample();
  Event* GetEventOfCurrentSample() { return &current_event_; }
  SymbolEntry* GetSymbolOfCurrentSample() { return current_symbol_; }
  CallChain* GetCallChainOfCurrentSample() { return &current_callchain_; }
  const char* GetTracingDataOfCurrentSample() { return current_tracing_data_; }

  const char* GetBuildIdForPath(const char* path);
  FeatureSection* GetFeatureSection(const char* feature_name);

 private:
  void SetCurrentSample();
  const EventInfo* FindEventOfCurrentSample();
  void CreateEvents();

  bool OpenRecordFileIfNecessary();
  Mapping* AddMapping(const MapEntry& map);

  std::unique_ptr<android::base::ScopedLogSeverity> log_severity_;
  std::string record_filename_;
  std::unique_ptr<RecordFileReader> record_file_reader_;
  ThreadTree thread_tree_;
  std::unique_ptr<SampleRecord> current_record_;
  const ThreadEntry* current_thread_;
  Sample current_sample_;
  Event current_event_;
  SymbolEntry* current_symbol_;
  CallChain current_callchain_;
  const char* current_tracing_data_;
  std::vector<std::unique_ptr<Mapping>> current_mappings_;
  std::vector<CallChainEntry> callchain_entries_;
  std::string build_id_string_;
  std::vector<EventInfo> events_;
  bool trace_offcpu_;
  std::unordered_map<pid_t, std::unique_ptr<SampleRecord>> next_sample_cache_;
  FeatureSection feature_section_;
  std::vector<char> feature_section_data_;
  bool show_art_frames_;
  bool merge_java_methods_ = true;
  // Map from a java method name to it's dex file, start_addr and len.
  std::unordered_map<std::string, std::tuple<Dso*, uint64_t, uint64_t>> java_methods_;
  std::unique_ptr<Tracing> tracing_;
};

bool ReportLib::SetLogSeverity(const char* log_level) {
  android::base::LogSeverity severity;
  if (!GetLogSeverity(log_level, &severity)) {
    LOG(ERROR) << "Unknown log severity: " << log_level;
    return false;
  }
  log_severity_ = nullptr;
  log_severity_.reset(new android::base::ScopedLogSeverity(severity));
  return true;
}

bool ReportLib::SetKallsymsFile(const char* kallsyms_file) {
  std::string kallsyms;
  if (!android::base::ReadFileToString(kallsyms_file, &kallsyms)) {
    LOG(WARNING) << "Failed to read in kallsyms file from " << kallsyms_file;
    return false;
  }
  Dso::SetKallsyms(std::move(kallsyms));
  return true;
}

bool ReportLib::OpenRecordFileIfNecessary() {
  if (record_file_reader_ == nullptr) {
    record_file_reader_ = RecordFileReader::CreateInstance(record_filename_);
    if (record_file_reader_ == nullptr) {
      return false;
    }
    record_file_reader_->LoadBuildIdAndFileFeatures(thread_tree_);
    auto& meta_info = record_file_reader_->GetMetaInfoFeature();
    if (auto it = meta_info.find("trace_offcpu"); it != meta_info.end()) {
      trace_offcpu_ = it->second == "true";
    }
    if (merge_java_methods_) {
      for (Dso* dso : thread_tree_.GetAllDsos()) {
        if (dso->type() == DSO_DEX_FILE) {
          for (auto& symbol : dso->GetSymbols()) {
            java_methods_[symbol.Name()] = std::make_tuple(dso, symbol.addr, symbol.len);
          }
        }
      }
    }
  }
  return true;
}

Sample* ReportLib::GetNextSample() {
  if (!OpenRecordFileIfNecessary()) {
    return nullptr;
  }
  while (true) {
    std::unique_ptr<Record> record;
    if (!record_file_reader_->ReadRecord(record)) {
      return nullptr;
    }
    if (record == nullptr) {
      return nullptr;
    }
    thread_tree_.Update(*record);
    if (record->type() == PERF_RECORD_SAMPLE) {
      if (trace_offcpu_) {
        SampleRecord* r = static_cast<SampleRecord*>(record.release());
        auto it = next_sample_cache_.find(r->tid_data.tid);
        if (it == next_sample_cache_.end()) {
          next_sample_cache_[r->tid_data.tid].reset(r);
          continue;
        } else {
          record.reset(it->second.release());
          it->second.reset(r);
        }
      }
      current_record_.reset(static_cast<SampleRecord*>(record.release()));
      break;
    } else if (record->type() == PERF_RECORD_TRACING_DATA ||
               record->type() == SIMPLE_PERF_RECORD_TRACING_DATA) {
      const auto& r = *static_cast<TracingDataRecord*>(record.get());
      tracing_.reset(new Tracing(std::vector<char>(r.data, r.data + r.data_size)));
    }
  }
  SetCurrentSample();
  return &current_sample_;
}

void ReportLib::SetCurrentSample() {
  current_mappings_.clear();
  callchain_entries_.clear();
  SampleRecord& r = *current_record_;
  current_sample_.ip = r.ip_data.ip;
  current_sample_.pid = r.tid_data.pid;
  current_sample_.tid = r.tid_data.tid;
  current_thread_ = thread_tree_.FindThreadOrNew(r.tid_data.pid, r.tid_data.tid);
  current_sample_.thread_comm = current_thread_->comm;
  current_sample_.time = r.time_data.time;
  current_sample_.in_kernel = r.InKernel();
  current_sample_.cpu = r.cpu_data.cpu;
  if (trace_offcpu_) {
    uint64_t next_time = std::max(next_sample_cache_[r.tid_data.tid]->time_data.time,
                                  r.time_data.time + 1);
    current_sample_.period = next_time - r.time_data.time;
  } else {
    current_sample_.period = r.period_data.period;
  }

  size_t kernel_ip_count;
  std::vector<uint64_t> ips = r.GetCallChain(&kernel_ip_count);
  std::vector<std::pair<uint64_t, const MapEntry*>> ip_maps;
  bool near_java_method = false;
  auto is_map_for_interpreter = [](const MapEntry* map) {
    return android::base::EndsWith(map->dso->Path(), "/libart.so") ||
      android::base::EndsWith(map->dso->Path(), "/libartd.so");
  };
  for (size_t i = 0; i < ips.size(); ++i) {
    const MapEntry* map = thread_tree_.FindMap(current_thread_, ips[i], i < kernel_ip_count);
    if (!show_art_frames_) {
      // Remove interpreter frames both before and after the Java frame.
      if (map->dso->IsForJavaMethod()) {
        near_java_method = true;
        while (!ip_maps.empty() && is_map_for_interpreter(ip_maps.back().second)) {
          ip_maps.pop_back();
        }
      } else if (is_map_for_interpreter(map)){
        if (near_java_method) {
          continue;
        }
      } else {
        near_java_method = false;
      }
    }
    ip_maps.push_back(std::make_pair(ips[i], map));
  }
  for (auto& pair : ip_maps) {
    uint64_t ip = pair.first;
    const MapEntry* map = pair.second;
    uint64_t vaddr_in_file;
    const Symbol* symbol = thread_tree_.FindSymbol(map, ip, &vaddr_in_file);
    CallChainEntry entry;
    entry.ip = ip;
    entry.symbol.dso_name = map->dso->Path().c_str();
    entry.symbol.vaddr_in_file = vaddr_in_file;
    entry.symbol.symbol_name = symbol->DemangledName();
    entry.symbol.symbol_addr = symbol->addr;
    entry.symbol.symbol_len = symbol->len;
    entry.symbol.mapping = AddMapping(*map);

    if (merge_java_methods_ && map->dso->type() == DSO_ELF_FILE && map->dso->IsForJavaMethod()) {
      // This is a jitted java method, merge it with the interpreted java method having the same
      // name if possible. Otherwise, merge it with other jitted java methods having the same name
      // by assigning a common dso_name.
      if (auto it = java_methods_.find(entry.symbol.symbol_name); it != java_methods_.end()) {
        entry.symbol.dso_name = std::get<0>(it->second)->Path().c_str();
        entry.symbol.symbol_addr = std::get<1>(it->second);
        entry.symbol.symbol_len = std::get<2>(it->second);
        // Not enough info to map an offset in a jitted method to an offset in a dex file. So just
        // use the symbol_addr.
        entry.symbol.vaddr_in_file = entry.symbol.symbol_addr;
      } else {
        entry.symbol.dso_name = "[JIT cache]";
      }
    }

    callchain_entries_.push_back(entry);
  }
  current_sample_.ip = callchain_entries_[0].ip;
  current_symbol_ = &(callchain_entries_[0].symbol);
  current_callchain_.nr = callchain_entries_.size() - 1;
  current_callchain_.entries = &callchain_entries_[1];
  const EventInfo* event = FindEventOfCurrentSample();
  current_event_.name = event->name.c_str();
  current_event_.tracing_data_format = event->tracing_info.data_format;
  if (current_event_.tracing_data_format.size > 0u && (r.sample_type & PERF_SAMPLE_RAW)) {
    CHECK_GE(r.raw_data.size, current_event_.tracing_data_format.size);
    current_tracing_data_ = r.raw_data.data;
  } else {
    current_tracing_data_ = nullptr;
  }
}

const EventInfo* ReportLib::FindEventOfCurrentSample() {
  if (events_.empty()) {
    CreateEvents();
  }
  size_t attr_index;
  if (trace_offcpu_) {
    // For trace-offcpu, we don't want to show event sched:sched_switch.
    attr_index = 0;
  } else {
    attr_index = record_file_reader_->GetAttrIndexOfRecord(current_record_.get());
  }
  return &events_[attr_index];
}

void ReportLib::CreateEvents() {
  std::vector<EventAttrWithId> attrs = record_file_reader_->AttrSection();
  events_.resize(attrs.size());
  for (size_t i = 0; i < attrs.size(); ++i) {
    events_[i].attr = *attrs[i].attr;
    events_[i].name = GetEventNameByAttr(events_[i].attr);
    EventInfo::TracingInfo& tracing_info = events_[i].tracing_info;
    if (events_[i].attr.type == PERF_TYPE_TRACEPOINT && tracing_) {
      TracingFormat format = tracing_->GetTracingFormatHavingId(events_[i].attr.config);
      tracing_info.field_names.resize(format.fields.size());
      tracing_info.fields.resize(format.fields.size());
      for (size_t i = 0; i < format.fields.size(); ++i) {
        tracing_info.field_names[i] = format.fields[i].name;
        TracingFieldFormat& field = tracing_info.fields[i];
        field.name = tracing_info.field_names[i].c_str();
        field.offset = format.fields[i].offset;
        field.elem_size = format.fields[i].elem_size;
        field.elem_count = format.fields[i].elem_count;
        field.is_signed = format.fields[i].is_signed;
      }
      if (tracing_info.fields.empty()) {
        tracing_info.data_format.size = 0;
      } else {
        TracingFieldFormat& field = tracing_info.fields.back();
        tracing_info.data_format.size = field.offset + field.elem_size * field.elem_count;
      }
      tracing_info.data_format.field_count = tracing_info.fields.size();
      tracing_info.data_format.fields = &tracing_info.fields[0];
    } else {
      tracing_info.data_format.size = 0;
      tracing_info.data_format.field_count = 0;
      tracing_info.data_format.fields = nullptr;
    }
  }
}

Mapping* ReportLib::AddMapping(const MapEntry& map) {
  current_mappings_.emplace_back(std::unique_ptr<Mapping>(new Mapping));
  Mapping* mapping = current_mappings_.back().get();
  mapping->start = map.start_addr;
  mapping->end = map.start_addr + map.len;
  mapping->pgoff = map.pgoff;
  return mapping;
}

const char* ReportLib::GetBuildIdForPath(const char* path) {
  if (!OpenRecordFileIfNecessary()) {
    build_id_string_.clear();
    return build_id_string_.c_str();
  }
  BuildId build_id = Dso::FindExpectedBuildIdForPath(path);
  if (build_id.IsEmpty()) {
    build_id_string_.clear();
  } else {
    build_id_string_ = build_id.ToString();
  }
  return build_id_string_.c_str();
}

FeatureSection* ReportLib::GetFeatureSection(const char* feature_name) {
  if (!OpenRecordFileIfNecessary()) {
    return nullptr;
  }
  int feature = PerfFileFormat::GetFeatureId(feature_name);
  if (feature == -1 || !record_file_reader_->ReadFeatureSection(feature, &feature_section_data_)) {
    return nullptr;
  }
  feature_section_.data = feature_section_data_.data();
  feature_section_.data_size = feature_section_data_.size();
  return &feature_section_;
}

// Exported methods working with a client created instance
ReportLib* CreateReportLib() {
  return new ReportLib();
}

void DestroyReportLib(ReportLib* report_lib) {
  delete report_lib;
}

bool SetLogSeverity(ReportLib* report_lib, const char* log_level) {
  return report_lib->SetLogSeverity(log_level);
}

bool SetSymfs(ReportLib* report_lib, const char* symfs_dir) {
  return report_lib->SetSymfs(symfs_dir);
}

bool SetRecordFile(ReportLib* report_lib, const char* record_file) {
  return report_lib->SetRecordFile(record_file);
}

void ShowIpForUnknownSymbol(ReportLib* report_lib) {
  return report_lib->ShowIpForUnknownSymbol();
}

void ShowArtFrames(ReportLib* report_lib, bool show) {
  return report_lib->ShowArtFrames(show);
}

void MergeJavaMethods(ReportLib* report_lib, bool merge) {
  return report_lib->MergeJavaMethods(merge);
}

bool SetKallsymsFile(ReportLib* report_lib, const char* kallsyms_file) {
  return report_lib->SetKallsymsFile(kallsyms_file);
}

Sample* GetNextSample(ReportLib* report_lib) {
  return report_lib->GetNextSample();
}

Event* GetEventOfCurrentSample(ReportLib* report_lib) {
  return report_lib->GetEventOfCurrentSample();
}

SymbolEntry* GetSymbolOfCurrentSample(ReportLib* report_lib) {
  return report_lib->GetSymbolOfCurrentSample();
}

CallChain* GetCallChainOfCurrentSample(ReportLib* report_lib) {
  return report_lib->GetCallChainOfCurrentSample();
}

const char* GetTracingDataOfCurrentSample(ReportLib* report_lib) {
  return report_lib->GetTracingDataOfCurrentSample();
}

const char* GetBuildIdForPath(ReportLib* report_lib, const char* path) {
  return report_lib->GetBuildIdForPath(path);
}

FeatureSection* GetFeatureSection(ReportLib* report_lib, const char* feature_name) {
  return report_lib->GetFeatureSection(feature_name);
}
