//===-- Decoder.cpp ---------------------------------------------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#include "Decoder.h"

// C/C++ Includes
#include <cinttypes>
#include <cstring>

#include "lldb/API/SBModule.h"
#include "lldb/API/SBProcess.h"
#include "lldb/API/SBThread.h"

using namespace ptdecoder_private;

// This function removes entries of all the processes/threads which were once
// registered in the class but are not alive anymore because they died or
// finished executing.
void Decoder::RemoveDeadProcessesAndThreads(lldb::SBProcess &sbprocess) {
  lldb::SBTarget sbtarget = sbprocess.GetTarget();
  lldb::SBDebugger sbdebugger = sbtarget.GetDebugger();
  uint32_t num_targets = sbdebugger.GetNumTargets();

  auto itr_process = m_mapProcessUID_mapThreadID_TraceInfo.begin();
  while (itr_process != m_mapProcessUID_mapThreadID_TraceInfo.end()) {
    bool process_found = false;
    lldb::SBTarget target;
    lldb::SBProcess process;
    for (uint32_t i = 0; i < num_targets; i++) {
      target = sbdebugger.GetTargetAtIndex(i);
      process = target.GetProcess();
      if (process.GetUniqueID() == itr_process->first) {
        process_found = true;
        break;
      }
    }

    // Remove the process's entry if it was not found in SBDebugger
    if (!process_found) {
      itr_process = m_mapProcessUID_mapThreadID_TraceInfo.erase(itr_process);
      continue;
    }

    // If the state of the process is exited or detached then remove process's
    // entry. If not then remove entry for all those registered threads of this
    // process that are not alive anymore.
    lldb::StateType state = process.GetState();
    if ((state == lldb::StateType::eStateDetached) ||
        (state == lldb::StateType::eStateExited))
      itr_process = m_mapProcessUID_mapThreadID_TraceInfo.erase(itr_process);
    else {
      auto itr_thread = itr_process->second.begin();
      while (itr_thread != itr_process->second.end()) {
        if (itr_thread->first == LLDB_INVALID_THREAD_ID) {
          ++itr_thread;
          continue;
        }

        lldb::SBThread thread = process.GetThreadByID(itr_thread->first);
        if (!thread.IsValid())
          itr_thread = itr_process->second.erase(itr_thread);
        else
          ++itr_thread;
      }
      ++itr_process;
    }
  }
}

void Decoder::StartProcessorTrace(lldb::SBProcess &sbprocess,
                                  lldb::SBTraceOptions &sbtraceoptions,
                                  lldb::SBError &sberror) {
  sberror.Clear();
  CheckDebuggerID(sbprocess, sberror);
  if (!sberror.Success())
    return;

  std::lock_guard<std::mutex> guard(
      m_mapProcessUID_mapThreadID_TraceInfo_mutex);
  RemoveDeadProcessesAndThreads(sbprocess);

  if (sbtraceoptions.getType() != lldb::TraceType::eTraceTypeProcessorTrace) {
    sberror.SetErrorStringWithFormat("SBTraceOptions::TraceType not set to "
                                     "eTraceTypeProcessorTrace; ProcessID = "
                                     "%" PRIu64,
                                     sbprocess.GetProcessID());
    return;
  }
  lldb::SBStructuredData sbstructdata = sbtraceoptions.getTraceParams(sberror);
  if (!sberror.Success())
    return;

  const char *trace_tech_key = "trace-tech";
  std::string trace_tech_value("intel-pt");
  lldb::SBStructuredData value = sbstructdata.GetValueForKey(trace_tech_key);
  if (!value.IsValid()) {
    sberror.SetErrorStringWithFormat(
        "key \"%s\" not set in custom trace parameters", trace_tech_key);
    return;
  }

  char string_value[9];
  size_t bytes_written = value.GetStringValue(
      string_value, sizeof(string_value) / sizeof(*string_value));
  if (!bytes_written ||
      (bytes_written > (sizeof(string_value) / sizeof(*string_value)))) {
    sberror.SetErrorStringWithFormat(
        "key \"%s\" not set in custom trace parameters", trace_tech_key);
    return;
  }

  std::size_t pos =
      trace_tech_value.find((const char *)string_value, 0, bytes_written);
  if ((pos == std::string::npos)) {
    sberror.SetErrorStringWithFormat(
        "key \"%s\" not set to \"%s\" in custom trace parameters",
        trace_tech_key, trace_tech_value.c_str());
    return;
  }

  // Start Tracing
  lldb::SBError error;
  uint32_t unique_id = sbprocess.GetUniqueID();
  lldb::tid_t tid = sbtraceoptions.getThreadID();
  lldb::SBTrace trace = sbprocess.StartTrace(sbtraceoptions, error);
  if (!error.Success()) {
    if (tid == LLDB_INVALID_THREAD_ID)
      sberror.SetErrorStringWithFormat("%s; ProcessID = %" PRIu64,
                                       error.GetCString(),
                                       sbprocess.GetProcessID());
    else
      sberror.SetErrorStringWithFormat(
          "%s; thread_id = %" PRIu64 ", ProcessID = %" PRIu64,
          error.GetCString(), tid, sbprocess.GetProcessID());
    return;
  }

  MapThreadID_TraceInfo &mapThreadID_TraceInfo =
      m_mapProcessUID_mapThreadID_TraceInfo[unique_id];
  ThreadTraceInfo &trace_info = mapThreadID_TraceInfo[tid];
  trace_info.SetUniqueTraceInstance(trace);
  trace_info.SetStopID(sbprocess.GetStopID());
}

void Decoder::StopProcessorTrace(lldb::SBProcess &sbprocess,
                                 lldb::SBError &sberror, lldb::tid_t tid) {
  sberror.Clear();
  CheckDebuggerID(sbprocess, sberror);
  if (!sberror.Success()) {
    return;
  }

  std::lock_guard<std::mutex> guard(
      m_mapProcessUID_mapThreadID_TraceInfo_mutex);
  RemoveDeadProcessesAndThreads(sbprocess);

  uint32_t unique_id = sbprocess.GetUniqueID();
  auto itr_process = m_mapProcessUID_mapThreadID_TraceInfo.find(unique_id);
  if (itr_process == m_mapProcessUID_mapThreadID_TraceInfo.end()) {
    sberror.SetErrorStringWithFormat(
        "tracing not active for this process; ProcessID = %" PRIu64,
        sbprocess.GetProcessID());
    return;
  }

  lldb::SBError error;
  if (tid == LLDB_INVALID_THREAD_ID) {
    // This implies to stop tracing on the whole process
    lldb::user_id_t id_to_be_ignored = LLDB_INVALID_UID;
    auto itr_thread = itr_process->second.begin();
    while (itr_thread != itr_process->second.end()) {
      // In the case when user started trace on the entire process and then
      // registered newly spawned threads of this process in the class later,
      // these newly spawned threads will have same trace id. If we stopped
      // trace on the entire process then tracing stops automatically for these
      // newly spawned registered threads. Stopping trace on them again will
      // return error and therefore we need to skip stopping trace on them
      // again.
      lldb::SBTrace &trace = itr_thread->second.GetUniqueTraceInstance();
      lldb::user_id_t lldb_pt_user_id = trace.GetTraceUID();
      if (lldb_pt_user_id != id_to_be_ignored) {
        trace.StopTrace(error, itr_thread->first);
        if (!error.Success()) {
          std::string error_string(error.GetCString());
          if ((error_string.find("tracing not active for this process") ==
               std::string::npos) &&
              (error_string.find("tracing not active for this thread") ==
               std::string::npos)) {
            sberror.SetErrorStringWithFormat(
                "%s; thread id=%" PRIu64 ", ProcessID = %" PRIu64,
                error_string.c_str(), itr_thread->first,
                sbprocess.GetProcessID());
            return;
          }
        }

        if (itr_thread->first == LLDB_INVALID_THREAD_ID)
          id_to_be_ignored = lldb_pt_user_id;
      }
      itr_thread = itr_process->second.erase(itr_thread);
    }
    m_mapProcessUID_mapThreadID_TraceInfo.erase(itr_process);
  } else {
    // This implies to stop tracing on a single thread.
    // if 'tid' is registered in the class then get the trace id and stop trace
    // on it. If it is not then check if tracing was ever started on the entire
    // process (because there is a possibility that trace is still running for
    // 'tid' but it was not registered in the class because user had started
    // trace on the whole process and 'tid' spawned later). In that case, get
    // the trace id of the process trace instance and stop trace on this thread.
    // If tracing was never started on the entire process then return error
    // because there is no way tracing is active on 'tid'.
    MapThreadID_TraceInfo &mapThreadID_TraceInfo = itr_process->second;
    lldb::SBTrace trace;
    auto itr = mapThreadID_TraceInfo.find(tid);
    if (itr != mapThreadID_TraceInfo.end()) {
      trace = itr->second.GetUniqueTraceInstance();
    } else {
      auto itr = mapThreadID_TraceInfo.find(LLDB_INVALID_THREAD_ID);
      if (itr != mapThreadID_TraceInfo.end()) {
        trace = itr->second.GetUniqueTraceInstance();
      } else {
        sberror.SetErrorStringWithFormat(
            "tracing not active for this thread; thread id=%" PRIu64
            ", ProcessID = %" PRIu64,
            tid, sbprocess.GetProcessID());
        return;
      }
    }

    // Stop Tracing
    trace.StopTrace(error, tid);
    if (!error.Success()) {
      std::string error_string(error.GetCString());
      sberror.SetErrorStringWithFormat(
          "%s; thread id=%" PRIu64 ", ProcessID = %" PRIu64,
          error_string.c_str(), tid, sbprocess.GetProcessID());
      if (error_string.find("tracing not active") == std::string::npos)
        return;
    }
    // Delete the entry of 'tid' from this class (if any)
    mapThreadID_TraceInfo.erase(tid);
  }
}

void Decoder::ReadTraceDataAndImageInfo(lldb::SBProcess &sbprocess,
                                        lldb::tid_t tid, lldb::SBError &sberror,
                                        ThreadTraceInfo &threadTraceInfo) {
  // Allocate trace data buffer and parse cpu info for 'tid' if it is registered
  // for the first time in class
  lldb::SBTrace &trace = threadTraceInfo.GetUniqueTraceInstance();
  Buffer &pt_buffer = threadTraceInfo.GetPTBuffer();
  lldb::SBError error;
  if (pt_buffer.size() == 0) {
    lldb::SBTraceOptions traceoptions;
    traceoptions.setThreadID(tid);
    trace.GetTraceConfig(traceoptions, error);
    if (!error.Success()) {
      sberror.SetErrorStringWithFormat("%s; ProcessID = %" PRIu64,
                                       error.GetCString(),
                                       sbprocess.GetProcessID());
      return;
    }
    if (traceoptions.getType() != lldb::TraceType::eTraceTypeProcessorTrace) {
      sberror.SetErrorStringWithFormat("invalid TraceType received from LLDB "
                                       "for this thread; thread id=%" PRIu64
                                       ", ProcessID = %" PRIu64,
                                       tid, sbprocess.GetProcessID());
      return;
    }

    threadTraceInfo.AllocatePTBuffer(traceoptions.getTraceBufferSize());
    lldb::SBStructuredData sbstructdata = traceoptions.getTraceParams(sberror);
    if (!sberror.Success())
      return;
    CPUInfo &pt_cpu = threadTraceInfo.GetCPUInfo();
    ParseCPUInfo(pt_cpu, sbstructdata, sberror);
    if (!sberror.Success())
      return;
  }

  // Call LLDB API to get raw trace data for this thread
  size_t bytes_written = trace.GetTraceData(error, (void *)pt_buffer.data(),
                                            pt_buffer.size(), 0, tid);
  if (!error.Success()) {
    sberror.SetErrorStringWithFormat(
        "%s; thread_id = %" PRIu64 ",  ProcessID = %" PRIu64,
        error.GetCString(), tid, sbprocess.GetProcessID());
    return;
  }
  std::fill(pt_buffer.begin() + bytes_written, pt_buffer.end(), 0);

  // Get information of all the modules of the inferior
  lldb::SBTarget sbtarget = sbprocess.GetTarget();
  ReadExecuteSectionInfos &readExecuteSectionInfos =
      threadTraceInfo.GetReadExecuteSectionInfos();
  GetTargetModulesInfo(sbtarget, readExecuteSectionInfos, sberror);
  if (!sberror.Success())
    return;
}

void Decoder::DecodeProcessorTrace(lldb::SBProcess &sbprocess, lldb::tid_t tid,
                                   lldb::SBError &sberror,
                                   ThreadTraceInfo &threadTraceInfo) {
  // Initialize instruction decoder
  struct pt_insn_decoder *decoder = nullptr;
  struct pt_config config;
  Buffer &pt_buffer = threadTraceInfo.GetPTBuffer();
  CPUInfo &pt_cpu = threadTraceInfo.GetCPUInfo();
  ReadExecuteSectionInfos &readExecuteSectionInfos =
      threadTraceInfo.GetReadExecuteSectionInfos();

  InitializePTInstDecoder(&decoder, &config, pt_cpu, pt_buffer,
                          readExecuteSectionInfos, sberror);
  if (!sberror.Success())
    return;

  // Start raw trace decoding
  Instructions &instruction_list = threadTraceInfo.GetInstructionLog();
  instruction_list.clear();
  DecodeTrace(decoder, instruction_list, sberror);
}

// Raw trace decoding requires information of Read & Execute sections of each
// module of the inferior. This function updates internal state of the class to
// store this information.
void Decoder::GetTargetModulesInfo(
    lldb::SBTarget &sbtarget, ReadExecuteSectionInfos &readExecuteSectionInfos,
    lldb::SBError &sberror) {
  if (!sbtarget.IsValid()) {
    sberror.SetErrorStringWithFormat("Can't get target's modules info from "
                                     "LLDB; process has an invalid target");
    return;
  }

  lldb::SBFileSpec target_file_spec = sbtarget.GetExecutable();
  if (!target_file_spec.IsValid()) {
    sberror.SetErrorStringWithFormat("Target has an invalid file spec");
    return;
  }

  uint32_t num_modules = sbtarget.GetNumModules();
  readExecuteSectionInfos.clear();

  // Store information of all RX sections of each module of inferior
  for (uint32_t i = 0; i < num_modules; i++) {
    lldb::SBModule module = sbtarget.GetModuleAtIndex(i);
    if (!module.IsValid()) {
      sberror.SetErrorStringWithFormat(
          "Can't get module info [ %" PRIu32
          " ] of target \"%s\" from LLDB, invalid module",
          i, target_file_spec.GetFilename());
      return;
    }

    lldb::SBFileSpec module_file_spec = module.GetPlatformFileSpec();
    if (!module_file_spec.IsValid()) {
      sberror.SetErrorStringWithFormat(
          "Can't get module info [ %" PRIu32
          " ] of target \"%s\" from LLDB, invalid file spec",
          i, target_file_spec.GetFilename());
      return;
    }

    const char *image(module_file_spec.GetFilename());
    lldb::SBError error;
    char image_complete_path[1024];
    uint32_t path_length = module_file_spec.GetPath(
        image_complete_path, sizeof(image_complete_path));
    size_t num_sections = module.GetNumSections();

    // Store information of only RX sections
    for (size_t idx = 0; idx < num_sections; idx++) {
      lldb::SBSection section = module.GetSectionAtIndex(idx);
      uint32_t section_permission = section.GetPermissions();
      if ((section_permission & lldb::Permissions::ePermissionsReadable) &&
          (section_permission & lldb::Permissions::ePermissionsExecutable)) {
        lldb::SBData section_data = section.GetSectionData();
        if (!section_data.IsValid()) {
          sberror.SetErrorStringWithFormat(
              "Can't get module info [ %" PRIu32 " ]   \"%s\"  of target "
              "\"%s\" from LLDB, invalid "
              "data in \"%s\" section",
              i, image, target_file_spec.GetFilename(), section.GetName());
          return;
        }

        // In case section has no data, skip it.
        if (section_data.GetByteSize() == 0)
          continue;

        if (!path_length) {
          sberror.SetErrorStringWithFormat(
              "Can't get module info [ %" PRIu32 " ]   \"%s\"  of target "
              "\"%s\" from LLDB, module "
              "has an invalid path length",
              i, image, target_file_spec.GetFilename());
          return;
        }

        std::string image_path(image_complete_path, path_length);
        readExecuteSectionInfos.emplace_back(
            section.GetLoadAddress(sbtarget), section.GetFileOffset(),
            section_data.GetByteSize(), image_path);
      }
    }
  }
}

// Raw trace decoding requires information of the target cpu on which inferior
// is running. This function gets the Trace Configuration from LLDB, parses it
// for cpu model, family, stepping and vendor id info and updates the internal
// state of the class to store this information.
void Decoder::ParseCPUInfo(CPUInfo &pt_cpu, lldb::SBStructuredData &s,
                           lldb::SBError &sberror) {
  lldb::SBStructuredData custom_trace_params = s.GetValueForKey("intel-pt");
  if (!custom_trace_params.IsValid()) {
    sberror.SetErrorStringWithFormat("lldb couldn't provide cpuinfo");
    return;
  }

  uint64_t family = 0, model = 0, stepping = 0;
  char vendor[32];
  const char *key_family = "cpu_family";
  const char *key_model = "cpu_model";
  const char *key_stepping = "cpu_stepping";
  const char *key_vendor = "cpu_vendor";

  // parse family
  lldb::SBStructuredData struct_family =
      custom_trace_params.GetValueForKey(key_family);
  if (!struct_family.IsValid()) {
    sberror.SetErrorStringWithFormat(
        "%s info missing in custom trace parameters", key_family);
    return;
  }
  family = struct_family.GetIntegerValue(0x10000);
  if (family > UINT16_MAX) {
    sberror.SetErrorStringWithFormat(
        "invalid CPU family value extracted from custom trace parameters");
    return;
  }
  pt_cpu.family = (uint16_t)family;

  // parse model
  lldb::SBStructuredData struct_model =
      custom_trace_params.GetValueForKey(key_model);
  if (!struct_model.IsValid()) {
    sberror.SetErrorStringWithFormat(
        "%s info missing in custom trace parameters; family=%" PRIu16,
        key_model, pt_cpu.family);
    return;
  }
  model = struct_model.GetIntegerValue(0x100);
  if (model > UINT8_MAX) {
    sberror.SetErrorStringWithFormat("invalid CPU model value extracted from "
                                     "custom trace parameters; family=%" PRIu16,
                                     pt_cpu.family);
    return;
  }
  pt_cpu.model = (uint8_t)model;

  // parse stepping
  lldb::SBStructuredData struct_stepping =
      custom_trace_params.GetValueForKey(key_stepping);
  if (!struct_stepping.IsValid()) {
    sberror.SetErrorStringWithFormat(
        "%s info missing in custom trace parameters; family=%" PRIu16
        ", model=%" PRIu8,
        key_stepping, pt_cpu.family, pt_cpu.model);
    return;
  }
  stepping = struct_stepping.GetIntegerValue(0x100);
  if (stepping > UINT8_MAX) {
    sberror.SetErrorStringWithFormat("invalid CPU stepping value extracted "
                                     "from custom trace parameters; "
                                     "family=%" PRIu16 ", model=%" PRIu8,
                                     pt_cpu.family, pt_cpu.model);
    return;
  }
  pt_cpu.stepping = (uint8_t)stepping;

  // parse vendor info
  pt_cpu.vendor = pcv_unknown;
  lldb::SBStructuredData struct_vendor =
      custom_trace_params.GetValueForKey(key_vendor);
  if (!struct_vendor.IsValid()) {
    sberror.SetErrorStringWithFormat(
        "%s info missing in custom trace parameters; family=%" PRIu16
        ", model=%" PRIu8 ", stepping=%" PRIu8,
        key_vendor, pt_cpu.family, pt_cpu.model, pt_cpu.stepping);
    return;
  }
  auto length = struct_vendor.GetStringValue(vendor, sizeof(vendor));
  if (length && strstr(vendor, "GenuineIntel"))
    pt_cpu.vendor = pcv_intel;
}

// Initialize trace decoder with pt_config structure and populate its image
// structure with inferior's memory image information. pt_config structure is
// initialized with trace buffer and cpu info of the inferior before storing it
// in trace decoder.
void Decoder::InitializePTInstDecoder(
    struct pt_insn_decoder **decoder, struct pt_config *config,
    const CPUInfo &pt_cpu, Buffer &pt_buffer,
    const ReadExecuteSectionInfos &readExecuteSectionInfos,
    lldb::SBError &sberror) const {
  if (!decoder || !config) {
    sberror.SetErrorStringWithFormat("internal error");
    return;
  }

  // Load cpu info of inferior's target in pt_config struct
  pt_config_init(config);
  config->cpu = pt_cpu;
  int errcode = pt_cpu_errata(&(config->errata), &(config->cpu));
  if (errcode < 0) {
    sberror.SetErrorStringWithFormat("processor trace decoding library: "
                                     "pt_cpu_errata() failed with error: "
                                     "\"%s\"",
                                     pt_errstr(pt_errcode(errcode)));
    return;
  }

  // Load trace buffer's starting and end address in pt_config struct
  config->begin = pt_buffer.data();
  config->end = pt_buffer.data() + pt_buffer.size();

  // Fill trace decoder with pt_config struct
  *decoder = pt_insn_alloc_decoder(config);
  if (*decoder == nullptr) {
    sberror.SetErrorStringWithFormat("processor trace decoding library:  "
                                     "pt_insn_alloc_decoder() returned null "
                                     "pointer");
    return;
  }

  // Fill trace decoder's image with inferior's memory image information
  struct pt_image *image = pt_insn_get_image(*decoder);
  if (!image) {
    sberror.SetErrorStringWithFormat("processor trace decoding library:  "
                                     "pt_insn_get_image() returned null "
                                     "pointer");
    pt_insn_free_decoder(*decoder);
    return;
  }

  for (auto &itr : readExecuteSectionInfos) {
    errcode = pt_image_add_file(image, itr.image_path.c_str(), itr.file_offset,
                                itr.size, nullptr, itr.load_address);
    if (errcode < 0) {
      sberror.SetErrorStringWithFormat("processor trace decoding library:  "
                                       "pt_image_add_file() failed with error: "
                                       "\"%s\"",
                                       pt_errstr(pt_errcode(errcode)));
      pt_insn_free_decoder(*decoder);
      return;
    }
  }
}

void Decoder::AppendErrorWithOffsetToInstructionList(
    int errcode, uint64_t decoder_offset, Instructions &instruction_list,
    lldb::SBError &sberror) {
  sberror.SetErrorStringWithFormat(
      "processor trace decoding library: \"%s\"  [decoder_offset] => "
      "[0x%" PRIu64 "]",
      pt_errstr(pt_errcode(errcode)), decoder_offset);
  instruction_list.emplace_back(sberror.GetCString());
}

void Decoder::AppendErrorWithoutOffsetToInstructionList(
    int errcode, Instructions &instruction_list, lldb::SBError &sberror) {
  sberror.SetErrorStringWithFormat("processor trace decoding library: \"%s\"",
                                   pt_errstr(pt_errcode(errcode)));
  instruction_list.emplace_back(sberror.GetCString());
}

int Decoder::AppendErrorToInstructionList(int errcode, pt_insn_decoder *decoder,
                                          Instructions &instruction_list,
                                          lldb::SBError &sberror) {
  uint64_t decoder_offset = 0;
  int errcode_off = pt_insn_get_offset(decoder, &decoder_offset);
  if (errcode_off < 0) {
    AppendErrorWithoutOffsetToInstructionList(errcode, instruction_list,
                                              sberror);
    return errcode_off;
  }
  AppendErrorWithOffsetToInstructionList(errcode, decoder_offset,
                                         instruction_list, sberror);
  return 0;
}

int Decoder::HandlePTInstructionEvents(pt_insn_decoder *decoder, int errcode,
                                       Instructions &instruction_list,
                                       lldb::SBError &sberror) {
  while (errcode & pts_event_pending) {
    pt_event event;
    errcode = pt_insn_event(decoder, &event, sizeof(event));
    if (errcode < 0)
      return errcode;

    // The list of events are in
    // https://github.com/intel/libipt/blob/master/doc/man/pt_qry_event.3.md
    if (event.type == ptev_overflow) {
      int append_errcode = AppendErrorToInstructionList(
          errcode, decoder, instruction_list, sberror);
      if (append_errcode < 0)
        return append_errcode;
    }
    // Other events don't signal stream errors
  }

  return 0;
}

// Start actual decoding of raw trace
void Decoder::DecodeTrace(struct pt_insn_decoder *decoder,
                          Instructions &instruction_list,
                          lldb::SBError &sberror) {
  uint64_t decoder_offset = 0;

  while (1) {
    struct pt_insn insn;

    // Try to sync the decoder. If it fails then get the decoder_offset and try
    // to sync again. If the new_decoder_offset is same as decoder_offset then
    // we will not succeed in syncing for any number of pt_insn_sync_forward()
    // operations. Return in that case. Else keep resyncing until either end of
    // trace stream is reached or pt_insn_sync_forward() passes.
    int errcode = pt_insn_sync_forward(decoder);
    if (errcode < 0) {
      if (errcode == -pte_eos)
        return;

      int errcode_off = pt_insn_get_offset(decoder, &decoder_offset);
      if (errcode_off < 0) {
        AppendErrorWithoutOffsetToInstructionList(errcode, instruction_list,
                                                  sberror);
        return;
      }

      sberror.SetErrorStringWithFormat(
          "processor trace decoding library: \"%s\"  [decoder_offset] => "
          "[0x%" PRIu64 "]",
          pt_errstr(pt_errcode(errcode)), decoder_offset);
      instruction_list.emplace_back(sberror.GetCString());
      while (1) {
        errcode = pt_insn_sync_forward(decoder);
        if (errcode >= 0)
          break;

        if (errcode == -pte_eos)
          return;

        uint64_t new_decoder_offset = 0;
        errcode_off = pt_insn_get_offset(decoder, &new_decoder_offset);
        if (errcode_off < 0) {
          sberror.SetErrorStringWithFormat(
              "processor trace decoding library: \"%s\"",
              pt_errstr(pt_errcode(errcode)));
          instruction_list.emplace_back(sberror.GetCString());
          return;
        } else if (new_decoder_offset <= decoder_offset) {
          // We tried resyncing the decoder and decoder didn't make any
          // progress because the offset didn't change. We will not make any
          // progress further. Hence, returning in this situation.
          return;
        }
        AppendErrorWithOffsetToInstructionList(errcode, new_decoder_offset,
                                               instruction_list, sberror);
        decoder_offset = new_decoder_offset;
      }
    }

    while (1) {
      errcode = HandlePTInstructionEvents(decoder, errcode, instruction_list,
                                          sberror);
      if (errcode < 0) {
        int append_errcode = AppendErrorToInstructionList(
            errcode, decoder, instruction_list, sberror);
        if (append_errcode < 0)
          return;
        break;
      }
      errcode = pt_insn_next(decoder, &insn, sizeof(insn));
      if (errcode < 0) {
        if (insn.iclass == ptic_error)
          break;

        instruction_list.emplace_back(insn);

        if (errcode == -pte_eos)
          return;

        Diagnose(decoder, errcode, sberror, &insn);
        instruction_list.emplace_back(sberror.GetCString());
        break;
      }
      instruction_list.emplace_back(insn);
      if (errcode & pts_eos)
        return;
    }
  }
}

// Function to diagnose and indicate errors during raw trace decoding
void Decoder::Diagnose(struct pt_insn_decoder *decoder, int decode_error,
                       lldb::SBError &sberror, const struct pt_insn *insn) {
  int errcode;
  uint64_t offset;

  errcode = pt_insn_get_offset(decoder, &offset);
  if (insn) {
    if (errcode < 0)
      sberror.SetErrorStringWithFormat(
          "processor trace decoding library: \"%s\"  [decoder_offset, "
          "last_successful_decoded_ip] => [?, 0x%" PRIu64 "]",
          pt_errstr(pt_errcode(decode_error)), insn->ip);
    else
      sberror.SetErrorStringWithFormat(
          "processor trace decoding library: \"%s\"  [decoder_offset, "
          "last_successful_decoded_ip] => [0x%" PRIu64 ", 0x%" PRIu64 "]",
          pt_errstr(pt_errcode(decode_error)), offset, insn->ip);
  } else {
    if (errcode < 0)
      sberror.SetErrorStringWithFormat(
          "processor trace decoding library: \"%s\"",
          pt_errstr(pt_errcode(decode_error)));
    else
      sberror.SetErrorStringWithFormat(
          "processor trace decoding library: \"%s\"  [decoder_offset] => "
          "[0x%" PRIu64 "]",
          pt_errstr(pt_errcode(decode_error)), offset);
  }
}

void Decoder::GetInstructionLogAtOffset(lldb::SBProcess &sbprocess,
                                        lldb::tid_t tid, uint32_t offset,
                                        uint32_t count,
                                        InstructionList &result_list,
                                        lldb::SBError &sberror) {
  sberror.Clear();
  CheckDebuggerID(sbprocess, sberror);
  if (!sberror.Success()) {
    return;
  }

  std::lock_guard<std::mutex> guard(
      m_mapProcessUID_mapThreadID_TraceInfo_mutex);
  RemoveDeadProcessesAndThreads(sbprocess);

  ThreadTraceInfo *threadTraceInfo = nullptr;
  FetchAndDecode(sbprocess, tid, sberror, &threadTraceInfo);
  if (!sberror.Success()) {
    return;
  }
  if (threadTraceInfo == nullptr) {
    sberror.SetErrorStringWithFormat("internal error");
    return;
  }

  // Return instruction log by populating 'result_list'
  Instructions &insn_list = threadTraceInfo->GetInstructionLog();
  uint64_t sum = (uint64_t)offset + 1;
  if (((insn_list.size() <= offset) && (count <= sum) &&
       ((sum - count) >= insn_list.size())) ||
      (count < 1)) {
    sberror.SetErrorStringWithFormat(
        "Instruction Log not available for offset=%" PRIu32
        " and count=%" PRIu32 ", ProcessID = %" PRIu64,
        offset, count, sbprocess.GetProcessID());
    return;
  }

  Instructions::iterator itr_first =
      (insn_list.size() <= offset) ? insn_list.begin()
                                   : insn_list.begin() + insn_list.size() - sum;
  Instructions::iterator itr_last =
      (count <= sum) ? insn_list.begin() + insn_list.size() - (sum - count)
                     : insn_list.end();
  Instructions::iterator itr = itr_first;
  while (itr != itr_last) {
    result_list.AppendInstruction(*itr);
    ++itr;
  }
}

void Decoder::GetProcessorTraceInfo(lldb::SBProcess &sbprocess, lldb::tid_t tid,
                                    TraceOptions &options,
                                    lldb::SBError &sberror) {
  sberror.Clear();
  CheckDebuggerID(sbprocess, sberror);
  if (!sberror.Success()) {
    return;
  }

  std::lock_guard<std::mutex> guard(
      m_mapProcessUID_mapThreadID_TraceInfo_mutex);
  RemoveDeadProcessesAndThreads(sbprocess);

  ThreadTraceInfo *threadTraceInfo = nullptr;
  FetchAndDecode(sbprocess, tid, sberror, &threadTraceInfo);
  if (!sberror.Success()) {
    return;
  }
  if (threadTraceInfo == nullptr) {
    sberror.SetErrorStringWithFormat("internal error");
    return;
  }

  // Get SBTraceOptions from LLDB for 'tid', populate 'traceoptions' with it
  lldb::SBTrace &trace = threadTraceInfo->GetUniqueTraceInstance();
  lldb::SBTraceOptions traceoptions;
  lldb::SBError error;
  traceoptions.setThreadID(tid);
  trace.GetTraceConfig(traceoptions, error);
  if (!error.Success()) {
    std::string error_string(error.GetCString());
    if (error_string.find("tracing not active") != std::string::npos) {
      uint32_t unique_id = sbprocess.GetUniqueID();
      auto itr_process = m_mapProcessUID_mapThreadID_TraceInfo.find(unique_id);
      if (itr_process == m_mapProcessUID_mapThreadID_TraceInfo.end())
        return;
      itr_process->second.erase(tid);
    }
    sberror.SetErrorStringWithFormat("%s; ProcessID = %" PRIu64,
                                     error_string.c_str(),
                                     sbprocess.GetProcessID());
    return;
  }
  if (traceoptions.getType() != lldb::TraceType::eTraceTypeProcessorTrace) {
    sberror.SetErrorStringWithFormat("invalid TraceType received from LLDB "
                                     "for this thread; thread id=%" PRIu64
                                     ", ProcessID = %" PRIu64,
                                     tid, sbprocess.GetProcessID());
    return;
  }
  options.setType(traceoptions.getType());
  options.setTraceBufferSize(traceoptions.getTraceBufferSize());
  options.setMetaDataBufferSize(traceoptions.getMetaDataBufferSize());
  lldb::SBStructuredData sbstructdata = traceoptions.getTraceParams(sberror);
  if (!sberror.Success())
    return;
  options.setTraceParams(sbstructdata);
  options.setInstructionLogSize(threadTraceInfo->GetInstructionLog().size());
}

void Decoder::FetchAndDecode(lldb::SBProcess &sbprocess, lldb::tid_t tid,
                             lldb::SBError &sberror,
                             ThreadTraceInfo **threadTraceInfo) {
  // Return with error if 'sbprocess' is not registered in the class
  uint32_t unique_id = sbprocess.GetUniqueID();
  auto itr_process = m_mapProcessUID_mapThreadID_TraceInfo.find(unique_id);
  if (itr_process == m_mapProcessUID_mapThreadID_TraceInfo.end()) {
    sberror.SetErrorStringWithFormat(
        "tracing not active for this process; ProcessID = %" PRIu64,
        sbprocess.GetProcessID());
    return;
  }

  if (tid == LLDB_INVALID_THREAD_ID) {
    sberror.SetErrorStringWithFormat(
        "invalid thread id provided; thread_id = %" PRIu64
        ", ProcessID = %" PRIu64,
        tid, sbprocess.GetProcessID());
    return;
  }

  // Check whether 'tid' thread is registered in the class. If it is then in
  // case StopID didn't change then return without doing anything (no need to
  // read and decode trace data then). Otherwise, save new StopID and proceed
  // with reading and decoding trace.
  if (threadTraceInfo == nullptr) {
    sberror.SetErrorStringWithFormat("internal error");
    return;
  }

  MapThreadID_TraceInfo &mapThreadID_TraceInfo = itr_process->second;
  auto itr_thread = mapThreadID_TraceInfo.find(tid);
  if (itr_thread != mapThreadID_TraceInfo.end()) {
    if (itr_thread->second.GetStopID() == sbprocess.GetStopID()) {
      *threadTraceInfo = &(itr_thread->second);
      return;
    }
    itr_thread->second.SetStopID(sbprocess.GetStopID());
  } else {
    // Implies 'tid' is not registered in the class. If tracing was never
    // started on the entire process then return an error. Else try to register
    // this thread and proceed with reading and decoding trace.
    lldb::SBError error;
    itr_thread = mapThreadID_TraceInfo.find(LLDB_INVALID_THREAD_ID);
    if (itr_thread == mapThreadID_TraceInfo.end()) {
      sberror.SetErrorStringWithFormat(
          "tracing not active for this thread; ProcessID = %" PRIu64,
          sbprocess.GetProcessID());
      return;
    }

    lldb::SBTrace &trace = itr_thread->second.GetUniqueTraceInstance();
    ThreadTraceInfo &trace_info = mapThreadID_TraceInfo[tid];
    trace_info.SetUniqueTraceInstance(trace);
    trace_info.SetStopID(sbprocess.GetStopID());
    itr_thread = mapThreadID_TraceInfo.find(tid);
  }

  // Get raw trace data and inferior image from LLDB for the registered thread
  ReadTraceDataAndImageInfo(sbprocess, tid, sberror, itr_thread->second);
  if (!sberror.Success()) {
    std::string error_string(sberror.GetCString());
    if (error_string.find("tracing not active") != std::string::npos)
      mapThreadID_TraceInfo.erase(itr_thread);
    return;
  }
  // Decode raw trace data
  DecodeProcessorTrace(sbprocess, tid, sberror, itr_thread->second);
  if (!sberror.Success()) {
    return;
  }
  *threadTraceInfo = &(itr_thread->second);
}

// This function checks whether the provided SBProcess instance belongs to same
// SBDebugger with which this tool instance is associated.
void Decoder::CheckDebuggerID(lldb::SBProcess &sbprocess,
                              lldb::SBError &sberror) {
  if (!sbprocess.IsValid()) {
    sberror.SetErrorStringWithFormat("invalid process instance");
    return;
  }

  lldb::SBTarget sbtarget = sbprocess.GetTarget();
  if (!sbtarget.IsValid()) {
    sberror.SetErrorStringWithFormat(
        "process contains an invalid target; ProcessID = %" PRIu64,
        sbprocess.GetProcessID());
    return;
  }

  lldb::SBDebugger sbdebugger = sbtarget.GetDebugger();
  if (!sbdebugger.IsValid()) {
    sberror.SetErrorStringWithFormat("process's target contains an invalid "
                                     "debugger instance; ProcessID = %" PRIu64,
                                     sbprocess.GetProcessID());
    return;
  }

  if (sbdebugger.GetID() != m_debugger_user_id) {
    sberror.SetErrorStringWithFormat(
        "process belongs to a different SBDebugger instance than the one for "
        "which the tool is instantiated; ProcessID = %" PRIu64,
        sbprocess.GetProcessID());
    return;
  }
}
