// Copyright 2017 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#pragma once

#include <string>
#include <unordered_set>
#include <vector>

#include "garnet/lib/debugger_utils/build_ids.h"
#include "garnet/lib/debugger_utils/elf_reader.h"
#include "garnet/lib/debugger_utils/elf_symtab.h"
#include "garnet/lib/debugger_utils/ktrace_reader.h"
#include "garnet/lib/debugger_utils/load_maps.h"

#include "third_party/processor-trace/libipt/include/intel-pt.h"

#include "third_party/simple-pt/symtab.h"

namespace intel_processor_trace {

// Parameters needed to drive the decoder.

struct DecoderConfig {
  // Path to the kernel ELF file.
  std::string kernel_file_name;

  // Ideally this should come from sideband data, but it can be manually
  // specified.
  uint64_t kernel_cr3 = pt_asid_no_cr3;

  // Path to the raw processor trace dump.
  // This file is produced by the "ipt" program.
  std::string pt_file_name;

  // Path to a text file containing a mapping of "id" values and their
  // corresponding PT dump files.
  // The format of each line is "id /path/to/pt-file".
  // "id" is either a cpu number for cpu-based tracing, or thread id for
  // thread-based tracing; in decimal.
  std::string pt_list_file_name;

  // Path to needed ktrace data.
  // This file is produced by the "ipt" program.
  std::string ktrace_file_name;

  // Optional additional files passed on the command line.
  std::vector<std::string> elf_file_names;

  // Path to the "ids.txt" files from the build.
  std::vector<std::string> ids_file_names;

  // Path to file containing linker map output.
  std::vector<std::string> map_file_names;
};

struct Process {
  Process(zx_koid_t p, uint64_t c, uint64_t start, uint64_t end);
  zx_koid_t pid;
  uint64_t cr3;
  // The time, in units ktrace uses, when the process was live.
  // An end time of zero means "unknown".
  uint64_t start_time, end_time;
};

struct PtFile {
  PtFile(uint64_t i, const std::string& f);

  // The id of the cpu we are processing. Cpus are numbered 0...N.
  static constexpr uint64_t kIdUnset = ~(uint64_t)0;

  uint64_t id;
  std::string file;
};

using SymbolTable = simple_pt::SymbolTable;
using Symbol = simple_pt::Symbol;
using LoadMap = debugger_utils::LoadMap;
using BuildId = debugger_utils::BuildId;

class DecoderState {
 public:
  static std::unique_ptr<DecoderState> Create(const DecoderConfig& config);

  ~DecoderState();

  const Process* LookupProcessByPid(zx_koid_t pid);
  const Process* LookupProcessByCr3(uint64_t cr3);

  const LoadMap* LookupMapEntry(zx_koid_t pid, uint64_t addr);

  const BuildId* LookupBuildId(const std::string& bid);

  std::string LookupFile(const std::string& file);

  const SymbolTable* FindSymbolTable(uint64_t cr3, uint64_t pc);
  const Symbol* FindSymbol(uint64_t cr3, uint64_t pc, const SymbolTable** out_symtab);
  const char* FindPcFileName(uint64_t cr3, uint64_t pc);

  bool SeenCr3(uint64_t cr3);

  uint64_t kernel_cr3() const { return kernel_cr3_; }
  void set_kernel_cr3(uint64_t cr3) { kernel_cr3_ = cr3; }

  const pt_config& config() const { return config_; }
  void set_nom_freq(uint8_t nom_freq) { config_.nom_freq = nom_freq; }
  void set_family(uint32_t family) { config_.cpu.family = family; }
  void set_model(uint32_t model) { config_.cpu.model = model; }
  void set_stepping(uint32_t stepping) { config_.cpu.stepping = stepping; }

  bool AllocDecoder(const std::string& pt_file);
  void FreeDecoder();
  pt_insn_decoder* decoder() const { return decoder_; }

  const std::vector<Process>& processes() const { return processes_; }

  const std::vector<PtFile>& pt_files() const { return pt_files_; }

  const std::unordered_set<uint64_t>& unknown_cr3s() const { return unknown_cr3s_; }

 private:
  DecoderState();

  bool AllocImage(const std::string& name);

  bool ReadKtraceFile(const std::string& file);
  bool ReadMapFile(const std::string& file);
  bool ReadIdsFile(const std::string& file);
  bool ReadPtListFile(const std::string& file);

  void AddSymtab(std::unique_ptr<SymbolTable> symtab);
  bool ReadElf(const std::string& file, uint64_t base, uint64_t cr3, uint64_t file_off,
               uint64_t map_len);
  bool ReadKernelElf(const std::string& file, uint64_t cr3);

  void SetKernelCr3(uint64_t cr3) { kernel_cr3_ = cr3; }

  static int ReadMemCallback(uint8_t* buffer, size_t size, const struct pt_asid* asid,
                             uint64_t addr, void* context);

  static int ProcessKtraceRecord(debugger_utils::KtraceRecord* rec, void* arg);

  bool AddProcess(zx_koid_t pid, uint64_t cr3, uint64_t start_time);
  bool MarkProcessExited(zx_koid_t pid, uint64_t end_time);

  void AddPtFile(const std::string& file_dir, uint64_t id, const std::string& path);

  pt_config config_;
  pt_image* image_;
  pt_insn_decoder* decoder_;

  uint64_t kernel_cr3_;

  std::vector<Process> processes_;
  debugger_utils::LoadMapTable load_maps_;
  debugger_utils::BuildIdTable build_ids_;
  std::vector<PtFile> pt_files_;

  // List of cr3 values seen that we don't have processes for.
  // This helps printers explain the results to human readers.
  std::unordered_set<uint64_t> unknown_cr3s_;

  std::vector<std::unique_ptr<SymbolTable>> symtabs_;
};

}  // namespace intel_processor_trace
