// 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/inference.h"

#include <zircon/system/public/zircon/processargs.h>
#include <zircon/system/public/zircon/types.h>

#include <ios>
#include <ostream>

#include "src/lib/fidl_codec/printer.h"
#include "tools/fidlcat/lib/syscall_decoder.h"

namespace fidlcat {

// This is the first function which is intercepted. This gives us information about
// all the handles an application have at startup. However, for directory handles,
// we don't have the name of the directory.
void Inference::ExtractHandles(SyscallDecoder* decoder) {
  constexpr int kNhandles = 0;
  constexpr int kHandles = 1;
  constexpr int kHandleInfo = 2;
  // Get the values which have been harvest by the debugger using they argument number.
  uint32_t nhandles = decoder->ArgumentValue(kNhandles);
  const zx_handle_t* handles =
      reinterpret_cast<const zx_handle_t*>(decoder->ArgumentContent(Stage::kEntry, kHandles));
  const uint32_t* handle_info =
      reinterpret_cast<const zx_handle_t*>(decoder->ArgumentContent(Stage::kEntry, kHandleInfo));
  // Get the information about all the handles.
  // The meaning of handle info is described in zircon/system/public/zircon/processargs.h
  for (uint32_t handle = 0; handle < nhandles; ++handle) {
    if (handles[handle] != 0) {
      uint32_t type = PA_HND_TYPE(handle_info[handle]);
      switch (type) {
        case PA_FD:
          AddHandleDescription(decoder->process_id(), handles[handle], "fd",
                               PA_HND_ARG(handle_info[handle]));
          break;
        case PA_DIRECTORY_REQUEST:
          AddHandleDescription(decoder->process_id(), handles[handle], "directory-request", "/");
          break;
        default:
          AddHandleDescription(decoder->process_id(), handles[handle], type);
          break;
      }
    }
  }
}

// This is the second function which is intercepted. This gives us information about
// all the handles which have not been used by processargs_extract_handles.
// This only adds information about directories.
void Inference::LibcExtensionsInit(SyscallDecoder* decoder) {
  constexpr int kHandleCount = 0;
  constexpr int kHandles = 1;
  constexpr int kHandleInfo = 2;
  constexpr int kNameCount = 3;
  constexpr int kNames = 4;
  // Get the values which have been harvest by the debugger using they argument number.
  uint32_t handle_count = decoder->ArgumentValue(kHandleCount);
  const zx_handle_t* handles =
      reinterpret_cast<const zx_handle_t*>(decoder->ArgumentContent(Stage::kEntry, kHandles));
  const uint32_t* handle_info =
      reinterpret_cast<const zx_handle_t*>(decoder->ArgumentContent(Stage::kEntry, kHandleInfo));
  uint32_t name_count = decoder->ArgumentValue(kNameCount);
  const uint64_t* names =
      reinterpret_cast<const uint64_t*>(decoder->ArgumentContent(Stage::kEntry, kNames));
  // Get the information about the remaining handles.
  // The meaning of handle info is described in zircon/system/public/zircon/processargs.h
  for (uint32_t handle = 0; handle < handle_count; ++handle) {
    if (handles[handle] != 0) {
      uint32_t type = PA_HND_TYPE(handle_info[handle]);
      switch (type) {
        case PA_NS_DIR: {
          uint32_t index = PA_HND_ARG(handle_info[handle]);
          AddHandleDescription(decoder->process_id(), handles[handle], "dir",
                               (index < name_count)
                                   ? reinterpret_cast<const char*>(
                                         decoder->BufferContent(Stage::kEntry, names[index]))
                                   : "");
          break;
        }
        case PA_FD:
          AddHandleDescription(decoder->process_id(), handles[handle], "fd",
                               PA_HND_ARG(handle_info[handle]));
          break;
        case PA_DIRECTORY_REQUEST:
          AddHandleDescription(decoder->process_id(), handles[handle], "directory-request", "/");
          break;
        default:
          AddHandleDescription(decoder->process_id(), handles[handle], type);
          break;
      }
    }
  }
}

void Inference::InferMessage(SyscallDecoder* decoder,
                             fidl_codec::semantic::ContextType context_type) {
  if (decoder->semantic() == nullptr) {
    return;
  }
  constexpr int kHandle = 0;
  zx_handle_t handle = decoder->ArgumentValue(kHandle);
  if (handle != ZX_HANDLE_INVALID) {
    fidl_codec::semantic::SemanticContext context(this, decoder->process_id(), handle, context_type,
                                                  decoder->decoded_request(),
                                                  decoder->decoded_response());
    decoder->semantic()->ExecuteAssignments(&context);
  }
}

void Inference::ZxChannelCreate(SyscallDecoder* decoder) {
  constexpr int kOut0 = 1;
  constexpr int kOut1 = 2;
  zx_handle_t* out0 = reinterpret_cast<zx_handle_t*>(decoder->ArgumentContent(Stage::kExit, kOut0));
  zx_handle_t* out1 = reinterpret_cast<zx_handle_t*>(decoder->ArgumentContent(Stage::kExit, kOut1));
  if ((out0 != nullptr) && (*out0 != ZX_HANDLE_INVALID) && (out1 != nullptr) &&
      (*out1 != ZX_HANDLE_INVALID)) {
    // Provides the minimal semantic for both handles (that is they are channels).
    AddHandleDescription(decoder->process_id(), *out0, "channel", next_channel_++);
    AddHandleDescription(decoder->process_id(), *out1, "channel", next_channel_++);
    // Links the two channels.
    AddLinkedHandles(decoder->process_id(), *out0, *out1);
  }
}

void Inference::ZxPortCreate(SyscallDecoder* decoder) {
  constexpr int kOut = 1;
  zx_handle_t* out = reinterpret_cast<zx_handle_t*>(decoder->ArgumentContent(Stage::kExit, kOut));
  if ((out != nullptr) && (*out != ZX_HANDLE_INVALID)) {
    // Provides the minimal semantic for the handle (that is it's a port).
    AddHandleDescription(decoder->process_id(), *out, "port", next_port_++);
  }
}

void Inference::ZxTimerCreate(SyscallDecoder* decoder) {
  constexpr int kOut = 2;
  zx_handle_t* out = reinterpret_cast<zx_handle_t*>(decoder->ArgumentContent(Stage::kExit, kOut));
  if ((out != nullptr) && (*out != ZX_HANDLE_INVALID)) {
    // Provides the minimal semantic for the handle (that is it's a timer).
    AddHandleDescription(decoder->process_id(), *out, "timer", next_timer_++);
  }
}

}  // namespace fidlcat
