// Copyright 2019 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.

#include "tools/fidlcat/lib/syscall_decoder_dispatcher.h"

#include <sys/time.h>
#include <zircon/errors.h>
#include <zircon/types.h>

#include <cstdint>
#include <fstream>
#include <memory>
#include <sstream>

#include "src/developer/debug/zxdb/client/process.h"
#include "src/developer/debug/zxdb/client/thread.h"
#include "src/lib/fidl_codec/semantic.h"
#include "tools/fidlcat/lib/inference.h"
#include "tools/fidlcat/lib/interception_workflow.h"
#include "tools/fidlcat/lib/syscall_decoder.h"
#include "tools/fidlcat/lib/top.h"
#include "tools/fidlcat/proto/session.pb.h"

namespace fidlcat {

std::unique_ptr<fidl_codec::Struct> uint128_struct_definition = nullptr;

const fidl_codec::Struct& GetUint128StructDefinition() {
  if (uint128_struct_definition == nullptr) {
    uint128_struct_definition = std::make_unique<fidl_codec::Struct>("zx.uint128");
    uint128_struct_definition->AddMember("low",
                                         SyscallTypeToFidlCodecType(SyscallType::kUint64Hexa));
    uint128_struct_definition->AddMember("high",
                                         SyscallTypeToFidlCodecType(SyscallType::kUint64Hexa));
  }
  return *uint128_struct_definition;
}

std::unique_ptr<fidl_codec::Type> SyscallTypeToFidlCodecType(fidlcat::SyscallType syscall_type) {
  switch (syscall_type) {
    case SyscallType::kBool:
      return std::make_unique<fidl_codec::BoolType>();
    case SyscallType::kBtiPerm:
      return std::make_unique<fidl_codec::Uint32Type>(fidl_codec::Uint32Type::Kind::kBtiPerm);
    case SyscallType::kCachePolicy:
      return std::make_unique<fidl_codec::Uint32Type>(fidl_codec::Uint32Type::Kind::kCachePolicy);
    case SyscallType::kChannelOption:
      return std::make_unique<fidl_codec::Uint32Type>(fidl_codec::Uint32Type::Kind::kChannelOption);
    case SyscallType::kChar:
      return std::make_unique<fidl_codec::Int8Type>(fidl_codec::Int8Type::Kind::kChar);
    case SyscallType::kClock:
      return std::make_unique<fidl_codec::Uint32Type>(fidl_codec::Uint32Type::Kind::kClock);
    case SyscallType::kDuration:
      return std::make_unique<fidl_codec::Int64Type>(fidl_codec::Int64Type::Kind::kDuration);
    case SyscallType::kExceptionChannelType:
      return std::make_unique<fidl_codec::Uint32Type>(
          fidl_codec::Uint32Type::Kind::kExceptionChannelType);
    case SyscallType::kExceptionState:
      return std::make_unique<fidl_codec::Uint32Type>(
          fidl_codec::Uint32Type::Kind::kExceptionState);
    case SyscallType::kFeatureKind:
      return std::make_unique<fidl_codec::Uint32Type>(fidl_codec::Uint32Type::Kind::kFeatureKind);
    case SyscallType::kFutex:
      return std::make_unique<fidl_codec::Int32Type>(fidl_codec::Int32Type::Kind::kFutex);
    case SyscallType::kGpAddr:
      return std::make_unique<fidl_codec::Uint64Type>(fidl_codec::Uint64Type::Kind::kGpAddr);
    case SyscallType::kGuestTrap:
      return std::make_unique<fidl_codec::Uint32Type>(fidl_codec::Uint32Type::Kind::kGuestTrap);
    case SyscallType::kHandle:
      return std::make_unique<fidl_codec::HandleType>();
    case SyscallType::kInfoMapsType:
      return std::make_unique<fidl_codec::Uint32Type>(fidl_codec::Uint32Type::Kind::kInfoMapsType);
    case SyscallType::kInt32:
      return std::make_unique<fidl_codec::Int32Type>();
    case SyscallType::kInt64:
      return std::make_unique<fidl_codec::Int64Type>();
    case SyscallType::kInterruptFlags:
      return std::make_unique<fidl_codec::Uint32Type>(
          fidl_codec::Uint32Type::Kind::kInterruptFlags);
    case SyscallType::kIommuType:
      return std::make_unique<fidl_codec::Uint32Type>(fidl_codec::Uint32Type::Kind::kIommuType);
    case SyscallType::kKoid:
      return std::make_unique<fidl_codec::Uint64Type>(fidl_codec::Uint64Type::Kind::kKoid);
    case SyscallType::kKtraceControlAction:
      return std::make_unique<fidl_codec::Uint32Type>(
          fidl_codec::Uint32Type::Kind::kKtraceControlAction);
    case SyscallType::kMonotonicTime:
      return std::make_unique<fidl_codec::Int64Type>(fidl_codec::Int64Type::Kind::kMonotonicTime);
    case SyscallType::kObjectInfoTopic:
      return std::make_unique<fidl_codec::Uint32Type>(
          fidl_codec::Uint32Type::Kind::kObjectInfoTopic);
    case SyscallType::kObjType:
      return std::make_unique<fidl_codec::Uint32Type>(fidl_codec::Uint32Type::Kind::kObjType);
    case SyscallType::kPacketGuestVcpuType:
      return std::make_unique<fidl_codec::Uint8Type>(
          fidl_codec::Uint8Type::Kind::kPacketGuestVcpuType);
    case SyscallType::kPacketPageRequestCommand:
      return std::make_unique<fidl_codec::Uint16Type>(
          fidl_codec::Uint16Type::Kind::kPacketPageRequestCommand);
    case SyscallType::kPaddr:
      return std::make_unique<fidl_codec::Uint64Type>(fidl_codec::Uint64Type::Kind::kPaddr);
    case SyscallType::kPciBarType:
      return std::make_unique<fidl_codec::Uint32Type>(fidl_codec::Uint32Type::Kind::kPciBarType);
    case SyscallType::kPolicyAction:
      return std::make_unique<fidl_codec::Uint32Type>(fidl_codec::Uint32Type::Kind::kPolicyAction);
    case SyscallType::kPolicyCondition:
      return std::make_unique<fidl_codec::Uint32Type>(
          fidl_codec::Uint32Type::Kind::kPolicyCondition);
    case SyscallType::kPolicyTopic:
      return std::make_unique<fidl_codec::Uint32Type>(fidl_codec::Uint32Type::Kind::kPolicyTopic);
    case SyscallType::kPortPacketType:
      return std::make_unique<fidl_codec::Uint32Type>(
          fidl_codec::Uint32Type::Kind::kPortPacketType);
    case SyscallType::kProfileInfoFlags:
      return std::make_unique<fidl_codec::Uint32Type>(
          fidl_codec::Uint32Type::Kind::kProfileInfoFlags);
    case SyscallType::kPropType:
      return std::make_unique<fidl_codec::Uint32Type>(fidl_codec::Uint32Type::Kind::kPropType);
    case SyscallType::kRights:
      return std::make_unique<fidl_codec::Uint32Type>(fidl_codec::Uint32Type::Kind::kRights);
    case SyscallType::kRsrcKind:
      return std::make_unique<fidl_codec::Uint32Type>(fidl_codec::Uint32Type::Kind::kRsrcKind);
    case SyscallType::kSignals:
      return std::make_unique<fidl_codec::Uint32Type>(fidl_codec::Uint32Type::Kind::kSignals);
    case SyscallType::kSize:
      return std::make_unique<fidl_codec::Uint64Type>(fidl_codec::Uint64Type::Kind::kSize);
    case SyscallType::kSocketCreateOptions:
      return std::make_unique<fidl_codec::Uint32Type>(
          fidl_codec::Uint32Type::Kind::kSocketCreateOptions);
    case SyscallType::kSocketReadOptions:
      return std::make_unique<fidl_codec::Uint32Type>(
          fidl_codec::Uint32Type::Kind::kSocketReadOptions);
    case SyscallType::kSocketDisposition:
      return std::make_unique<fidl_codec::Uint32Type>(
          fidl_codec::Uint32Type::Kind::kSocketDisposition);
    case SyscallType::kStatus:
      return std::make_unique<fidl_codec::Uint32Type>(fidl_codec::Uint32Type::Kind::kStatus);
    case SyscallType::kSystemEventType:
      return std::make_unique<fidl_codec::Uint32Type>(
          fidl_codec::Uint32Type::Kind::kSystemEventType);
    case SyscallType::kSystemPowerctl:
      return std::make_unique<fidl_codec::Uint32Type>(
          fidl_codec::Uint32Type::Kind::kSystemPowerctl);
    case SyscallType::kThreadState:
      return std::make_unique<fidl_codec::Uint32Type>(fidl_codec::Uint32Type::Kind::kThreadState);
    case SyscallType::kThreadStateTopic:
      return std::make_unique<fidl_codec::Uint32Type>(
          fidl_codec::Uint32Type::Kind::kThreadStateTopic);
    case SyscallType::kTime:
      return std::make_unique<fidl_codec::Int64Type>(fidl_codec::Int64Type::Kind::kTime);
    case SyscallType::kTimerOption:
      return std::make_unique<fidl_codec::Uint32Type>(fidl_codec::Uint32Type::Kind::kTimerOption);
    case SyscallType::kUint8:
      return std::make_unique<fidl_codec::Uint8Type>();
    case SyscallType::kUint8Hexa:
      return std::make_unique<fidl_codec::Uint8Type>(fidl_codec::Uint8Type::Kind::kHexaDecimal);
    case SyscallType::kUint16:
      return std::make_unique<fidl_codec::Uint16Type>();
    case SyscallType::kUint16Hexa:
      return std::make_unique<fidl_codec::Uint16Type>(fidl_codec::Uint16Type::Kind::kHexaDecimal);
    case SyscallType::kUint32:
      return std::make_unique<fidl_codec::Uint32Type>();
    case SyscallType::kUint32Hexa:
      return std::make_unique<fidl_codec::Uint32Type>(fidl_codec::Uint32Type::Kind::kHexaDecimal);
    case SyscallType::kUint64:
      return std::make_unique<fidl_codec::Uint64Type>();
    case SyscallType::kUint64Hexa:
      return std::make_unique<fidl_codec::Uint64Type>(fidl_codec::Uint64Type::Kind::kHexaDecimal);
    case SyscallType::kUint128Hexa:
      return std::make_unique<fidl_codec::StructType>(GetUint128StructDefinition(), false);
    case SyscallType::kUintptr:
      return std::make_unique<fidl_codec::Uint64Type>(fidl_codec::Uint64Type::Kind::kUintptr);
    case SyscallType::kVaddr:
      return std::make_unique<fidl_codec::Uint64Type>(fidl_codec::Uint64Type::Kind::kVaddr);
    case SyscallType::kVcpu:
      return std::make_unique<fidl_codec::Uint32Type>(fidl_codec::Uint32Type::Kind::kVcpu);
    case SyscallType::kVmOption:
      return std::make_unique<fidl_codec::Uint32Type>(fidl_codec::Uint32Type::Kind::kVmOption);
    case SyscallType::kVmoCreationOption:
      return std::make_unique<fidl_codec::Uint32Type>(
          fidl_codec::Uint32Type::Kind::kVmoCreationOption);
    case SyscallType::kVmoOp:
      return std::make_unique<fidl_codec::Uint32Type>(fidl_codec::Uint32Type::Kind::kVmoOp);
    case SyscallType::kVmoOption:
      return std::make_unique<fidl_codec::Uint32Type>(fidl_codec::Uint32Type::Kind::kVmoOption);
    case SyscallType::kVmoType:
      return std::make_unique<fidl_codec::Uint32Type>(fidl_codec::Uint32Type::Kind::kVmoType);
    default:
      return nullptr;
  }
}

std::unique_ptr<fidl_codec::Type> AccessBase::ComputeType() const {
  return SyscallTypeToFidlCodecType(GetSyscallType());
}

std::unique_ptr<fidl_codec::Type> SyscallInputOutputBase::ComputeType() const { return nullptr; }

std::unique_ptr<fidl_codec::Value> SyscallInputOutputBase::GenerateValue(
    SyscallDecoderInterface* decoder, Stage stage) const {
  return std::make_unique<fidl_codec::InvalidValue>();
}

bool SyscallInputOutputBase::GetAutomationInstructions(
    const std::vector<debug::RegisterID>& argument_indexes, bool is_invoked,
    const std::vector<debug_ipc::AutomationCondition>& conditions, Syscall& syscall) {
  return false;
}

void SyscallFidlMessageBase::LoadBytes(SyscallDecoderInterface* decoder, Stage stage) const {
  handle_->Load(decoder, stage);
  options_->Load(decoder, stage);
  num_bytes_->Load(decoder, stage);
  if (num_bytes_->Loaded(decoder, stage)) {
    uint32_t count = num_bytes_->Value(decoder, stage);
    bool use_iovec = false;
    if ((type_ == fidl_codec::SyscallFidlType::kOutputMessage) ||
        (type_ == fidl_codec::SyscallFidlType::kOutputRequest)) {
      uint32_t options = options_->Value(decoder, stage);
      if ((options & ZX_CHANNEL_WRITE_USE_IOVEC) != 0) {
        use_iovec = true;
      }
    }
    if (count > 0) {
      if (use_iovec) {
        bytes_->LoadArray(decoder, stage, count * sizeof(zx_channel_iovec_t));
        if (bytes_->ArrayLoaded(decoder, stage, count * sizeof(zx_channel_iovec_t))) {
          auto iovec = reinterpret_cast<const zx_channel_iovec_t*>(bytes_->Content(decoder, stage));
          for (uint32_t buffer = 0; buffer < count; ++buffer) {
            decoder->LoadBuffer(stage, reinterpret_cast<uint64_t>(iovec[buffer].buffer),
                                iovec[buffer].capacity);
          }
        }
      } else {
        bytes_->LoadArray(decoder, stage, count);
      }
    }
  }
}

SyscallFidlMessageBase::ByteBuffer::ByteBuffer(SyscallDecoderInterface* decoder, Stage stage,
                                               const SyscallFidlMessageBase* from) {
  uint32_t options_value = from->options()->Value(decoder, stage);
  if (((from->type() == fidl_codec::SyscallFidlType::kOutputMessage) ||
       (from->type() == fidl_codec::SyscallFidlType::kOutputRequest)) &&
      ((options_value & ZX_CHANNEL_WRITE_USE_IOVEC) != 0)) {
    // For the iovec case, we need to concatanate all the buffers into one.
    const zx_channel_iovec_t* iovec =
        reinterpret_cast<const zx_channel_iovec_t*>(from->bytes()->Content(decoder, stage));
    uint32_t iovec_count = from->num_bytes()->Value(decoder, stage);
    for (uint32_t i = 0; i < iovec_count; ++i) {
      count_ += static_cast<uint32_t>(iovec[i].capacity);
    }
    buffer_ = new uint8_t[count_];
    uint8_t* dst = buffer_;
    for (uint32_t i = 0; i < iovec_count; ++i) {
      const uint8_t* data =
          decoder->BufferContent(stage, reinterpret_cast<uint64_t>(iovec[i].buffer));
      memcpy(dst, data, iovec[i].capacity);
      dst += iovec[i].capacity;
    }
    bytes_ = buffer_;
  } else {
    bytes_ = from->bytes()->Content(decoder, stage);
    count_ = from->num_bytes()->Value(decoder, stage);
  }
}

std::unique_ptr<fidl_codec::Type> SyscallFidlMessageHandle::ComputeType() const {
  return std::make_unique<fidl_codec::FidlMessageType>();
}

std::unique_ptr<fidl_codec::Value> SyscallFidlMessageHandle::GenerateValue(
    SyscallDecoderInterface* decoder, Stage stage) const {
  zx_handle_t handle_value = handle()->Value(decoder, stage);
  ByteBuffer buffer(decoder, stage, this);
  const zx_handle_t* handles_value = handles()->Content(decoder, stage);
  uint32_t num_handles_value = num_handles()->Value(decoder, stage);
  zx_handle_disposition_t* handle_dispositions_value = nullptr;
  if (num_handles_value > 0) {
    handle_dispositions_value = new zx_handle_disposition_t[num_handles_value];
    for (uint32_t i = 0; i < num_handles_value; ++i) {
      handle_dispositions_value[i].operation = fidl_codec::kNoHandleDisposition;
      handle_dispositions_value[i].handle = handles_value[i];
      handle_dispositions_value[i].rights = 0;
      handle_dispositions_value[i].type = ZX_OBJ_TYPE_NONE;
      handle_dispositions_value[i].result = ZX_OK;
    }
  }
  fidl_codec::DecodedMessage message;
  std::stringstream error_stream;
  message.DecodeMessage(decoder->dispatcher()->MessageDecoderDispatcher(),
                        decoder->fidlcat_thread()->process()->koid(), handle_value, buffer.bytes(),
                        buffer.count(), handle_dispositions_value, num_handles_value, type(),
                        error_stream);
  auto result = std::make_unique<fidl_codec::FidlMessageValue>(
      &message, error_stream.str(), buffer.bytes(), buffer.count(), handle_dispositions_value,
      num_handles_value);
  delete[] handle_dispositions_value;
  if (result->is_request()) {
    if (result->matched_request()) {
      decoder->set_semantic(result->method()->semantic());
      decoder->set_decoded_request(result->decoded_request());
    }
    if (result->matched_response()) {
      decoder->set_semantic(result->method()->semantic());
      decoder->set_decoded_response(result->decoded_response());
    }
  }
  return result;
}

std::unique_ptr<fidl_codec::Type> SyscallFidlMessageHandleInfo::ComputeType() const {
  return std::make_unique<fidl_codec::FidlMessageType>();
}

std::unique_ptr<fidl_codec::Value> SyscallFidlMessageHandleInfo::GenerateValue(
    SyscallDecoderInterface* decoder, Stage stage) const {
  zx_handle_t handle_value = handle()->Value(decoder, stage);
  ByteBuffer buffer(decoder, stage, this);
  const zx_handle_info_t* handle_infos_value = handles()->Content(decoder, stage);
  uint32_t num_handles_value = num_handles()->Value(decoder, stage);
  zx_handle_disposition_t* handle_dispositions_value = nullptr;
  if (num_handles_value > 0) {
    handle_dispositions_value = new zx_handle_disposition_t[num_handles_value];
    for (uint32_t i = 0; i < num_handles_value; ++i) {
      handle_dispositions_value[i].operation = fidl_codec::kNoHandleDisposition;
      handle_dispositions_value[i].handle = handle_infos_value[i].handle;
      handle_dispositions_value[i].type = handle_infos_value[i].type;
      handle_dispositions_value[i].rights = handle_infos_value[i].rights;
      handle_dispositions_value[i].result = ZX_OK;
    }
  }
  fidl_codec::DecodedMessage message;
  std::stringstream error_stream;
  message.DecodeMessage(decoder->dispatcher()->MessageDecoderDispatcher(),
                        decoder->fidlcat_thread()->process()->koid(), handle_value, buffer.bytes(),
                        buffer.count(), handle_dispositions_value, num_handles_value, type(),
                        error_stream);
  auto result = std::make_unique<fidl_codec::FidlMessageValue>(
      &message, error_stream.str(), buffer.bytes(), buffer.count(), handle_dispositions_value,
      num_handles_value);
  delete[] handle_dispositions_value;
  if (result->is_request()) {
    if (result->matched_request()) {
      decoder->set_semantic(result->method()->semantic());
      decoder->set_decoded_request(result->decoded_request());
    }
    if (result->matched_response()) {
      decoder->set_semantic(result->method()->semantic());
      decoder->set_decoded_response(result->decoded_response());
    }
  }
  return result;
}

std::unique_ptr<fidl_codec::Type> SyscallFidlMessageHandleDisposition::ComputeType() const {
  return std::make_unique<fidl_codec::FidlMessageType>();
}

std::unique_ptr<fidl_codec::Value> SyscallFidlMessageHandleDisposition::GenerateValue(
    SyscallDecoderInterface* decoder, Stage stage) const {
  zx_handle_t handle_value = handle()->Value(decoder, stage);
  ByteBuffer buffer(decoder, stage, this);
  const zx_handle_disposition_t* handle_dispositions_value = handles()->Content(decoder, stage);
  uint32_t num_handles_value = num_handles()->Value(decoder, stage);
  fidl_codec::DecodedMessage message;
  std::stringstream error_stream;
  message.DecodeMessage(decoder->dispatcher()->MessageDecoderDispatcher(),
                        decoder->fidlcat_thread()->process()->koid(), handle_value, buffer.bytes(),
                        buffer.count(), handle_dispositions_value, num_handles_value, type(),
                        error_stream);
  auto result = std::make_unique<fidl_codec::FidlMessageValue>(
      &message, error_stream.str(), buffer.bytes(), buffer.count(), handle_dispositions_value,
      num_handles_value);
  if (result->is_request()) {
    if (result->matched_request()) {
      decoder->set_semantic(result->method()->semantic());
      decoder->set_decoded_request(result->decoded_request());
    }
    if (result->matched_response()) {
      decoder->set_semantic(result->method()->semantic());
      decoder->set_decoded_response(result->decoded_response());
    }
  }
  return result;
}

void ComputeTypes(const std::vector<std::unique_ptr<SyscallInputOutputBase>>& fields,
                  std::vector<std::unique_ptr<fidl_codec::StructMember>>* inline_members,
                  std::vector<std::unique_ptr<fidl_codec::StructMember>>* outline_members) {
  for (const auto& field : fields) {
    std::unique_ptr<fidl_codec::Type> type = field->ComputeType();
    if (field->InlineValue()) {
      inline_members->emplace_back(
          std::make_unique<fidl_codec::StructMember>(field->name(), std::move(type), field->id()));
    } else {
      outline_members->emplace_back(
          std::make_unique<fidl_codec::StructMember>(field->name(), std::move(type), field->id()));
    }
  }
}

void Syscall::ComputeTypes() {
  fidlcat::ComputeTypes(inputs_, &input_inline_members_, &input_outline_members_);
  fidlcat::ComputeTypes(outputs_, &output_inline_members_, &output_outline_members_);
}

const fidl_codec::StructMember* Syscall::SearchInlineMember(const std::string& name,
                                                            bool invoked) const {
  if (invoked) {
    for (const auto& member : input_inline_members_) {
      if (member->name() == name) {
        return member.get();
      }
    }
  } else {
    for (const auto& member : output_inline_members_) {
      if (member->name() == name) {
        return member.get();
      }
    }
  }
  return nullptr;
}

const fidl_codec::StructMember* Syscall::SearchInlineMember(uint32_t id, bool invoked) const {
  if (invoked) {
    for (const auto& member : input_inline_members_) {
      if (member->id() == id) {
        return member.get();
      }
    }
  } else {
    for (const auto& member : output_inline_members_) {
      if (member->id() == id) {
        return member.get();
      }
    }
  }
  return nullptr;
}

const fidl_codec::StructMember* Syscall::SearchOutlineMember(const std::string& name,
                                                             bool invoked) const {
  if (invoked) {
    for (const auto& member : input_outline_members_) {
      if (member->name() == name) {
        return member.get();
      }
    }
  } else {
    for (const auto& member : output_outline_members_) {
      if (member->name() == name) {
        return member.get();
      }
    }
  }
  return nullptr;
}

const fidl_codec::StructMember* Syscall::SearchOutlineMember(uint32_t id, bool invoked) const {
  if (invoked) {
    for (const auto& member : input_outline_members_) {
      if (member->id() == id) {
        return member.get();
      }
    }
  } else {
    for (const auto& member : output_outline_members_) {
      if (member->id() == id) {
        return member.get();
      }
    }
  }
  return nullptr;
}

void Syscall::ComputeStatistics(const OutputEvent* event) const {
  if (compute_statistics_ != nullptr) {
    (*compute_statistics_)(event);
  }
}

bool ComputeAutomation(const std::vector<debug::RegisterID>& argument_indexes, debug::Arch arch,
                       const std::vector<std::unique_ptr<SyscallInputOutputBase>>& fields,
                       bool is_invoked, Syscall& syscall) {
  bool fully_automated = true;
  for (const auto& field : fields) {
    std::vector<debug_ipc::AutomationCondition> automation_conditions;
    for (const auto& condition : *(field->conditions())) {
      if (!condition->ComputeAutomationCondition(argument_indexes, is_invoked, arch, syscall,
                                                 automation_conditions)) {
        continue;
      }
    }
    if (!field->GetAutomationInstructions(argument_indexes, is_invoked, automation_conditions,
                                          syscall)) {
      fully_automated = false;
    }
  }
  return fully_automated;
}

void Syscall::ComputeAutomation(debug::Arch arch) {
  if (invoked_bp_instructions_.size() + exit_bp_instructions_.size() > 0) {
    return;
  }

  static const std::vector<debug::RegisterID> amd64_argument_indexes = {
      debug::RegisterID::kX64_rdi, debug::RegisterID::kX64_rsi, debug::RegisterID::kX64_rdx,
      debug::RegisterID::kX64_rcx, debug::RegisterID::kX64_r8,  debug::RegisterID::kX64_r9};

  static const std::vector<debug::RegisterID> arm64_argument_indexes = {
      debug::RegisterID::kARMv8_x0, debug::RegisterID::kARMv8_x1, debug::RegisterID::kARMv8_x2,
      debug::RegisterID::kARMv8_x3, debug::RegisterID::kARMv8_x4, debug::RegisterID::kARMv8_x5,
      debug::RegisterID::kARMv8_x6, debug::RegisterID::kARMv8_x7};
  const std::vector<debug::RegisterID>* arg_index;
  if (arch == debug::Arch::kX64) {
    arg_index = &amd64_argument_indexes;
  } else if (arch == debug::Arch::kArm64) {
    arg_index = &arm64_argument_indexes;
  } else {
    FX_LOGS(ERROR) << "Unknown architecture";
    return;
  }

  bool initial_automated = fidlcat::ComputeAutomation(*arg_index, arch, inputs_, true, *this);
  bool exit_automated = fidlcat::ComputeAutomation(*arg_index, arch, outputs_, false, *this);
  fully_automated_ = initial_automated && exit_automated;
  debug_ipc::AutomationInstruction clear_instr;
  if (invoked_bp_instructions_.size() + exit_bp_instructions_.size() > 0) {
    clear_instr.InitClearStoredValues(std::vector<debug_ipc::AutomationCondition>());
    exit_bp_instructions_.emplace_back(clear_instr);
  }
}

SyscallDecoderDispatcher::SyscallDecoderDispatcher(const DecodeOptions& decode_options)
    : decode_options_(decode_options), inference_(this) {
  Populate();
  ComputeTypes();
  if (!decode_options.trigger_filters.empty()) {
    // We have at least one trigger => wait for a message satisfying the trigger before displaying
    // any syscall.
    display_started_ = false;
  }
  if (!decode_options.message_filters.empty() || !decode_options.exclude_message_filters.empty()) {
    has_filter_ = true;
  }
  if ((decode_options.stack_level != kNoStack) || !decode_options_.save.empty()) {
    needs_stack_frame_ = true;
  }
  if (!decode_options_.save.empty()) {
    needs_to_save_events_ = true;
  } else {
    switch (decode_options_.output_mode) {
      case OutputMode::kNone:
      case OutputMode::kStandard:
        break;
      case OutputMode::kTextProtobuf:
        needs_to_save_events_ = true;
        break;
    }
  }
}

HandleInfo* SyscallDecoderDispatcher::CreateHandleInfo(Thread* thread, uint32_t handle,
                                                       int64_t creation_time, bool startup) {
  auto old_value = thread->process()->SearchHandleInfo(handle);
  if (old_value != nullptr) {
    return old_value;
  }
  auto result = std::make_unique<HandleInfo>(thread, handle, creation_time, startup);
  auto returned_value = result.get();
  thread->process()->handle_infos().emplace_back(result.get());
  thread->process()->handle_info_map().emplace(std::make_pair(handle, result.get()));
  handle_infos_.emplace_back(std::move(result));
  return returned_value;
}

void SyscallDecoderDispatcher::DecodeSyscall(InterceptingThreadObserver* thread_observer,
                                             zxdb::Thread* thread, Syscall* syscall,
                                             uint64_t timestamp) {
  uint64_t thread_id = thread->GetKoid();
  auto current = syscall_decoders_.find(thread_id);
  if (current != syscall_decoders_.end()) {
    FX_LOGS(ERROR) << thread->GetProcess()->GetName() << ' ' << thread->GetProcess()->GetKoid()
                   << ':' << thread_id << ": Internal error: already decoding the thread";
    return;
  }
  auto decoder =
      std::make_unique<SyscallDecoder>(this, thread_observer, thread, syscall, timestamp);
  auto tmp = decoder.get();
  syscall_decoders_[thread_id] = std::move(decoder);
  tmp->Decode();
}

void SyscallDecoderDispatcher::DecodeException(InterceptionWorkflow* workflow, zxdb::Thread* thread,
                                               uint64_t timestamp) {
  uint64_t thread_id = thread->GetKoid();
  auto current = exception_decoders_.find(thread_id);
  if (current != exception_decoders_.end()) {
    FX_LOGS(ERROR) << thread->GetProcess()->GetName() << ' ' << thread->GetProcess()->GetKoid()
                   << ':' << thread_id
                   << ": Internal error: already decoding an exception for the thread";
    return;
  }
  auto decoder = std::make_unique<ExceptionDecoder>(workflow, this, thread, timestamp);
  auto tmp = decoder.get();
  exception_decoders_[thread_id] = std::move(decoder);
  tmp->Decode();
}

void SyscallDecoderDispatcher::DeleteDecoder(SyscallDecoder* decoder) {
  if (!decoder->aborted()) {
    zxdb::Thread* thread = decoder->get_thread();
    if (thread != nullptr) {
      thread->Continue(false);
    }
  }
  syscall_decoders_.erase(decoder->fidlcat_thread()->koid());
}

void SyscallDecoderDispatcher::DeleteDecoder(ExceptionDecoder* decoder) {
  zxdb::Thread* thread = decoder->get_thread();
  if (thread != nullptr) {
    thread->Continue(false);
  }
  exception_decoders_.erase(decoder->thread_id());
}

void SyscallDecoderDispatcher::AddStopMonitoringEvent(std::shared_ptr<StopMonitoringEvent> event) {
  for (const auto& decoder : syscall_decoders_) {
    if (decoder.second->fidlcat_thread()->process() == event->process()) {
      decoder.second->set_aborted();
    }
  }
}

void SyscallDecoderDispatcher::SaveEvent(std::shared_ptr<Event> event) {
  if (needs_to_save_events()) {
    decoded_events_.emplace_back(std::move(event));
  }
}

void SyscallDecoderDispatcher::SessionEnded() {
  bool generate_proto_session = false;
  if (!decode_options_.save.empty()) {
    generate_proto_session = true;
  } else {
    switch (decode_options_.output_mode) {
      case OutputMode::kNone:
      case OutputMode::kStandard:
        break;
      case OutputMode::kTextProtobuf:
        generate_proto_session = true;
        break;
    }
  }
  if (generate_proto_session) {
    proto::Session session;
    GenerateProtoSession(&session);
    if (!decode_options_.save.empty()) {
      std::fstream output(decode_options_.save, std::ios::out | std::ios::trunc | std::ios::binary);
      if (output.fail()) {
        FX_LOGS(ERROR) << "Can't open <" << decode_options_.save << "> for writing.";
      } else if (!session.SerializeToOstream(&output)) {
        FX_LOGS(ERROR) << "Failed to write session to protobuf file <" << decode_options_.save
                       << ">.";
      }
    }
    switch (decode_options_.output_mode) {
      case OutputMode::kNone:
      case OutputMode::kStandard:
        break;
      case OutputMode::kTextProtobuf:
        std::cout << session.DebugString();
        break;
    }
  }
}

void SyscallDecoderDispatcher::GenerateProtoSession(proto::Session* session) {
  for (const auto& process : processes_) {
    proto::Process* proto_process = session->add_process();
    proto_process->set_koid(process.second->koid());
    proto_process->set_name(process.second->name());
    auto process_semantic = inference().GetProcessSemantic(process.second->koid());
    if (process_semantic != nullptr) {
      for (const auto& linked_handles : process_semantic->linked_handles) {
        if (linked_handles.first < linked_handles.second) {
          proto::LinkedHandles* proto_linked_handles = proto_process->add_linked_handles();
          proto_linked_handles->set_handle_0(linked_handles.first);
          proto_linked_handles->set_handle_1(linked_handles.second);
        }
      }
    }
  }
  for (const auto& thread : threads_) {
    proto::Thread* proto_thread = session->add_thread();
    proto_thread->set_koid(thread.second->koid());
    proto_thread->set_process_koid(thread.second->process()->koid());
  }
  for (const auto& handle_info : handle_infos_) {
    fidl_codec::semantic::InferredHandleInfo* inferred_handle_info =
        inference().GetInferredHandleInfo(handle_info->thread()->process()->koid(),
                                          handle_info->handle());
    proto::HandleDescription* proto_handle_description = session->add_handle_description();
    proto_handle_description->set_handle(handle_info->handle());
    proto_handle_description->set_thread_koid(handle_info->thread()->koid());
    proto_handle_description->set_creation_time(handle_info->creation_time());
    proto_handle_description->set_startup(handle_info->startup());
    if (inferred_handle_info != nullptr) {
      proto_handle_description->set_type(inferred_handle_info->type());
      proto_handle_description->set_fd(inferred_handle_info->fd());
      proto_handle_description->set_path(inferred_handle_info->path());
      proto_handle_description->set_attributes(inferred_handle_info->attributes());
    }
    proto_handle_description->set_koid(handle_info->koid());
    proto_handle_description->set_object_type(handle_info->object_type());
  }
  for (const auto& linked_koids : inference().linked_koids()) {
    if (linked_koids.first < linked_koids.second) {
      proto::LinkedKoids* proto_linked_koids = session->add_linked_koids();
      proto_linked_koids->set_koid_0(linked_koids.first);
      proto_linked_koids->set_koid_1(linked_koids.second);
    }
  }
  for (const auto& event : decoded_events_) {
    event->Write(session->add_event());
  }
}

void SyscallDecoderDispatcher::ComputeTypes() {
  for (const auto& syscall : syscalls_) {
    syscall.second->ComputeTypes();
  }
}

double SyscallDisplayDispatcher::GetTime(int64_t timestamp) {
  return static_cast<double>(timestamp) / 1000000000;
}

void SyscallDisplayDispatcher::AddProcessLaunchedEvent(
    std::shared_ptr<ProcessLaunchedEvent> event) {
  if (decode_options().output_mode == OutputMode::kStandard) {
    if (!decode_options().thread_filters.empty()) {
      return;
    }
    os_ << '\n' << colors().green << GetTime(event->timestamp()) << colors().reset << ' ';
    if (event->error_message().empty()) {
      os_ << colors().green << "Launched " << colors().blue << event->command() << colors().reset
          << '\n';
    } else {
      os_ << colors().red << "Can't launch " << colors().blue << event->command() << colors().reset
          << " : " << colors().red << event->error_message() << colors().reset << '\n';
    }
  }

  SaveEvent(std::move(event));
}

void SyscallDisplayDispatcher::AddProcessMonitoredEvent(
    std::shared_ptr<ProcessMonitoredEvent> event) {
  if (!decode_options().thread_filters.empty()) {
    return;
  }
  if (decode_options().output_mode == OutputMode::kStandard) {
    os_ << '\n' << colors().green << GetTime(event->timestamp()) << colors().reset << ' ';
    if (event->error_message().empty()) {
      os_ << colors().green << "Monitoring ";
    } else {
      os_ << colors().red << "Can't monitor ";
    }

    if (event->process()->name().empty()) {
      os_ << colors().reset << "process with koid ";
    } else {
      os_ << colors().blue << event->process()->name() << colors().reset << " koid=";
    }

    os_ << colors().red << event->process()->koid() << colors().reset;
    if (!event->error_message().empty()) {
      os_ << " : " << colors().red << event->error_message() << colors().reset;
    }
    os_ << '\n';
  }

  SaveEvent(std::move(event));
}

void SyscallDisplayDispatcher::AddStopMonitoringEvent(std::shared_ptr<StopMonitoringEvent> event) {
  if (!decode_options().thread_filters.empty()) {
    return;
  }
  if (decode_options().output_mode == OutputMode::kStandard) {
    os_ << '\n' << colors().green << GetTime(event->timestamp()) << colors().reset << ' ';
    if (event->process()->name().empty()) {
      os_ << colors().green << "Stop monitoring process with koid" << colors().reset;
    } else {
      os_ << colors().green << "Stop monitoring" << colors().reset << ' ' << colors().blue
          << event->process()->name() << colors().reset << " koid";
    }
    os_ << ' ' << colors().red << event->process()->koid() << colors().reset << '\n';
  }

  SaveEvent(event);

  SyscallDecoderDispatcher::AddStopMonitoringEvent(std::move(event));
}

void SyscallDisplayDispatcher::SyscallDecodingError(const fidlcat::Thread* fidlcat_thread,
                                                    const Syscall* syscall,
                                                    const DecoderError& error) {
  std::string message = error.message();
  size_t pos = 0;
  for (;;) {
    size_t end = message.find('\n', pos);
    os_ << fidlcat_thread->process()->name() << ' ' << colors().red
        << fidlcat_thread->process()->koid() << colors().reset << ':' << colors().red
        << fidlcat_thread->koid() << colors().reset << ' ' << syscall->name() << ": "
        << colors().red << error.message().substr(pos, end) << colors().reset << '\n';
    if (end == std::string::npos) {
      break;
    }
    pos = end + 1;
  }
  os_ << '\n';
}

void SyscallDisplayDispatcher::AddInvokedEvent(std::shared_ptr<InvokedEvent> invoked_event) {
  invoked_event->set_id(GetNextInvokedEventId());
  if (!extra_generation().empty()) {
    invoked_event->ComputeHandleInfo(this);
  }
  if (!invoked_event->thread()->displayed()) {
    return;
  }
  if (!display_started()) {
    // The user specified a trigger. Check if this is a message which satisfies one of the triggers.
    const fidl_codec::FidlMessageValue* message = invoked_event->GetMessage();
    if ((message == nullptr) || (message->method() == nullptr) ||
        !decode_options().IsTrigger(message->method()->fully_qualified_name())) {
      return;
    }
    // We found a trigger => allow the display.
    set_display_started();
  }
  if (has_filter() && invoked_event->syscall()->has_fidl_message()) {
    // We have filters and this is a syscalls with a FIDL message.
    // Only display the syscall if the message satifies the conditions.
    const fidl_codec::FidlMessageValue* message = invoked_event->GetMessage();
    if ((message == nullptr) || (message->method() == nullptr) ||
        !decode_options().SatisfiesMessageFilters(message->method()->fully_qualified_name())) {
      return;
    }
  }
  invoked_event->set_displayed();
  DisplayInvokedEvent(invoked_event.get());

  SaveEvent(std::move(invoked_event));
}

void SyscallDisplayDispatcher::AddOutputEvent(std::shared_ptr<OutputEvent> output_event) {
  if (!output_event->thread()->displayed()) {
    return;
  }
  if (!extra_generation().empty()) {
    if (output_event->invoked_event()->handle_info() != nullptr) {
      output_event->invoked_event()->handle_info()->AddEvent(output_event.get());
    }
    output_event->syscall()->ComputeStatistics(output_event.get());
  }
  if (!output_event->invoked_event()->displayed()) {
    // The display of the syscall wasn't allowed by the input arguments. Check if the output
    // arguments allows its display.
    if (!display_started()) {
      // The user specified a trigger. Check if this is a message which satisfies one of the
      // triggers.
      const fidl_codec::FidlMessageValue* message = output_event->GetMessage();
      if ((message == nullptr) || (message->method() == nullptr) ||
          !decode_options().IsTrigger(message->method()->fully_qualified_name())) {
        return;
      }
      set_display_started();
    }
    if (has_filter() && output_event->syscall()->has_fidl_message()) {
      // We have filters and this is a syscalls with a FIDL message.
      // Only display the syscall if the message satifies the conditions.
      const fidl_codec::FidlMessageValue* message = output_event->GetMessage();
      if ((message == nullptr) || (message->method() == nullptr) ||
          !decode_options().SatisfiesMessageFilters(message->method()->fully_qualified_name())) {
        return;
      }
    }
    // We can display the syscall but the inputs have not been displayed => display the inputs
    // before displaying the outputs.
    DisplayInvokedEvent(output_event->invoked_event());
  }

  DisplayOutputEvent(output_event.get());

  SaveEvent(std::move(output_event));
}

void SyscallDisplayDispatcher::AddExceptionEvent(std::shared_ptr<ExceptionEvent> exception_event) {
  if (!exception_event->thread()->displayed()) {
    return;
  }

  DisplayExceptionEvent(exception_event.get());

  SaveEvent(std::move(exception_event));
}

void SyscallDisplayDispatcher::SessionEnded() {
  SyscallDecoderDispatcher::SessionEnded();
  if (!decoded_events().empty()) {
    // Uses the first event for the timestamp reference.
    GetTime(decoded_events().front()->timestamp());
  }
  const char* separator = "";
  for (const auto& extra_generation : extra_generation()) {
    if (extra_generation.path.empty()) {
      os_ << separator;
      switch (extra_generation.kind) {
        case ExtraGeneration::Kind::kSummary:
          DisplaySummary(os_);
          break;
        case ExtraGeneration::Kind::kTop: {
          Top top(this);
          top.Display(os_);
          break;
        }
        case ExtraGeneration::Kind::kThreads:
          DisplayThreads(os_);
          break;
      }
      separator = "\n";
    } else {
      std::fstream output(extra_generation.path, std::ios::out | std::ios::trunc);
      if (output.fail()) {
        FX_LOGS(ERROR) << "Can't open <" << extra_generation.path << "> for writing.";
      } else {
        switch (extra_generation.kind) {
          case ExtraGeneration::Kind::kSummary:
            DisplaySummary(output);
            break;
          case ExtraGeneration::Kind::kTop: {
            Top top(this);
            top.Display(output);
            break;
          }
          case ExtraGeneration::Kind::kThreads:
            DisplayThreads(output);
            break;
        }
      }
    }
  }
}

void SyscallDisplayDispatcher::DisplayInvokedEvent(const InvokedEvent* invoked_event) {
  if (decode_options().output_mode != OutputMode::kStandard) {
    return;
  }
  std::string line_header =
      colors().green + std::to_string(GetTime(invoked_event->timestamp())) + colors().reset + ' ' +
      invoked_event->thread()->process()->name() + ' ' + colors().red +
      std::to_string(invoked_event->thread()->process()->koid()) + colors().reset + ':' +
      colors().red + std::to_string(invoked_event->thread()->koid()) + colors().reset + ' ';
  if (with_process_info()) {
    os_ << line_header;
  }
  os_ << '\n';

  FidlcatPrinter printer(this, invoked_event->thread()->process(), os_, line_header);

  // We have been able to create values from the syscall => print them.
  invoked_event->PrettyPrint(printer);
  last_displayed_event_ = invoked_event;
}

void SyscallDisplayDispatcher::DisplayOutputEvent(const OutputEvent* output_event) {
  if (decode_options().output_mode != OutputMode::kStandard) {
    return;
  }
  if (output_event->syscall()->return_type() != SyscallReturnType::kNoReturn) {
    if (last_displayed_event_ != output_event->invoked_event()) {
      // Add a blank line to tell the user that this display is not linked to the
      // previous displayed lines.
      os_ << "\n";
    }
    std::string line_header;
    if (with_process_info() || (last_displayed_event_ != output_event->invoked_event())) {
      line_header = colors().green + std::to_string(GetTime(output_event->timestamp())) +
                    colors().reset + ' ' + output_event->thread()->process()->name() + ' ' +
                    colors().red + std::to_string(output_event->thread()->process()->koid()) +
                    colors().reset + ':' + colors().red +
                    std::to_string(output_event->thread()->koid()) + colors().reset + ' ';
    } else {
      line_header = colors().green + std::to_string(GetTime(output_event->timestamp())) +
                    colors().reset + ' ';
    }
    FidlcatPrinter printer(this, output_event->thread()->process(), os_, line_header);
    // We have been able to create values from the syscall => print them.
    output_event->PrettyPrint(printer);

    last_displayed_event_ = output_event;
  }
}

void SyscallDisplayDispatcher::DisplayExceptionEvent(const ExceptionEvent* exception_event) {
  if (decode_options().output_mode != OutputMode::kStandard) {
    return;
  }
  os_ << '\n';

  std::string line_header =
      colors().green + std::to_string(GetTime(exception_event->timestamp())) + colors().reset +
      ' ' + exception_event->thread()->process()->name() + ' ' + colors().red +
      std::to_string(exception_event->thread()->process()->koid()) + colors().reset + ':' +
      colors().red + std::to_string(exception_event->thread()->koid()) + colors().reset + ' ';
  FidlcatPrinter printer(this, exception_event->thread()->process(), os_, line_header);
  exception_event->PrettyPrint(printer);
}

void SyscallCompareDispatcher::SyscallDecodingError(const fidlcat::Thread* fidlcat_thread,
                                                    const Syscall* syscall,
                                                    const DecoderError& error) {
  os_.clear();
  os_.str("");
  SyscallDisplayDispatcher::SyscallDecodingError(fidlcat_thread, syscall, error);
  comparator_->DecodingError(os_.str());
}

void SyscallCompareDispatcher::DisplayInvokedEvent(const InvokedEvent* invoked_event) {
  os_.clear();
  os_.str("");
  SyscallDisplayDispatcher::DisplayInvokedEvent(invoked_event);
  comparator_->CompareInput(os_.str(), invoked_event->thread()->process()->name(),
                            invoked_event->thread()->process()->koid(),
                            invoked_event->thread()->koid());
}

void SyscallCompareDispatcher::DisplayOutputEvent(const OutputEvent* output_event) {
  os_.clear();
  os_.str("");
  SyscallDisplayDispatcher::DisplayOutputEvent(output_event);
  if (output_event->syscall()->return_type() != SyscallReturnType::kNoReturn) {
    comparator_->CompareOutput(os_.str(), output_event->thread()->process()->name(),
                               output_event->thread()->process()->koid(),
                               output_event->thread()->koid());
  }
}

}  // namespace fidlcat
