// Copyright 2020 the V8 project 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 "src/wasm/wasm-debug-evaluate.h"

#include <algorithm>
#include <limits>

#include "src/api/api-inl.h"
#include "src/codegen/machine-type.h"
#include "src/compiler/wasm-compiler.h"
#include "src/execution/frames-inl.h"
#include "src/wasm/value-type.h"
#include "src/wasm/wasm-arguments.h"
#include "src/wasm/wasm-constants.h"
#include "src/wasm/wasm-debug.h"
#include "src/wasm/wasm-module.h"
#include "src/wasm/wasm-objects.h"
#include "src/wasm/wasm-result.h"
#include "src/wasm/wasm-value.h"

namespace v8 {
namespace internal {
namespace wasm {
namespace {

static Handle<String> V8String(Isolate* isolate, const char* str) {
  return isolate->factory()->NewStringFromAsciiChecked(str);
}

static bool CheckSignature(ValueType return_type,
                           std::initializer_list<ValueType> argument_types,
                           const FunctionSig* sig, ErrorThrower* thrower) {
  if (sig->return_count() != 1 && return_type != kWasmBottom) {
    thrower->CompileError("Invalid return type. Got none, expected %s",
                          return_type.name().c_str());
    return false;
  }

  if (sig->return_count() == 1) {
    if (sig->GetReturn(0) != return_type) {
      thrower->CompileError("Invalid return type. Got %s, expected %s",
                            sig->GetReturn(0).name().c_str(),
                            return_type.name().c_str());
      return false;
    }
  }

  if (sig->parameter_count() != argument_types.size()) {
    thrower->CompileError("Invalid number of arguments. Expected %zu, got %zu",
                          sig->parameter_count(), argument_types.size());
    return false;
  }
  size_t p = 0;
  for (ValueType argument_type : argument_types) {
    if (sig->GetParam(p) != argument_type) {
      thrower->CompileError(
          "Invalid argument type for argument %zu. Got %s, expected %s", p,
          sig->GetParam(p).name().c_str(), argument_type.name().c_str());
      return false;
    }
    ++p;
  }
  return true;
}

static bool CheckRangeOutOfBounds(uint32_t offset, uint32_t size,
                                  size_t allocation_size,
                                  wasm::ErrorThrower* thrower) {
  if (size > std::numeric_limits<uint32_t>::max() - offset) {
    thrower->RuntimeError("Overflowing memory range\n");
    return true;
  }
  if (offset + size > allocation_size) {
    thrower->RuntimeError("Illegal access to out-of-bounds memory");
    return true;
  }
  return false;
}

class DebugEvaluatorProxy {
 public:
  explicit DebugEvaluatorProxy(Isolate* isolate, CommonFrame* frame)
      : isolate_(isolate), frame_(frame) {}

  static void GetMemoryTrampoline(
      const v8::FunctionCallbackInfo<v8::Value>& args) {
    DebugEvaluatorProxy& proxy = GetProxy(args);

    uint32_t offset = proxy.GetArgAsUInt32(args, 0);
    uint32_t size = proxy.GetArgAsUInt32(args, 1);
    uint32_t result = proxy.GetArgAsUInt32(args, 2);

    proxy.GetMemory(offset, size, result);
  }

  // void __getMemory(uint32_t offset, uint32_t size, void* result);
  void GetMemory(uint32_t offset, uint32_t size, uint32_t result) {
    wasm::ScheduledErrorThrower thrower(isolate_, "debug evaluate proxy");
    // Check all overflows.
    if (CheckRangeOutOfBounds(offset, size, debuggee_->memory_size(),
                              &thrower) ||
        CheckRangeOutOfBounds(result, size, evaluator_->memory_size(),
                              &thrower)) {
      return;
    }

    std::memcpy(&evaluator_->memory_start()[result],
                &debuggee_->memory_start()[offset], size);
  }

  // void* __sbrk(intptr_t increment);
  uint32_t Sbrk(uint32_t increment) {
    if (increment > 0 && evaluator_->memory_size() <=
                             std::numeric_limits<uint32_t>::max() - increment) {
      Handle<WasmMemoryObject> memory(evaluator_->memory_object(), isolate_);
      uint32_t new_pages =
          (increment - 1 + wasm::kWasmPageSize) / wasm::kWasmPageSize;
      WasmMemoryObject::Grow(isolate_, memory, new_pages);
    }
    return static_cast<uint32_t>(evaluator_->memory_size());
  }

  static void SbrkTrampoline(const v8::FunctionCallbackInfo<v8::Value>& args) {
    DebugEvaluatorProxy& proxy = GetProxy(args);
    uint32_t size = proxy.GetArgAsUInt32(args, 0);

    uint32_t result = proxy.Sbrk(size);
    args.GetReturnValue().Set(result);
  }

  // void __getLocal(uint32_t local,  void* result);
  void GetLocal(uint32_t local, uint32_t result_offset) {
    DCHECK(frame_->is_wasm());
    wasm::DebugInfo* debug_info =
        WasmFrame::cast(frame_)->native_module()->GetDebugInfo();
    WasmValue result = debug_info->GetLocalValue(
        local, frame_->pc(), frame_->fp(), frame_->callee_fp());
    WriteResult(result, result_offset);
  }

  void GetGlobal(uint32_t global, uint32_t result_offset) {
    DCHECK(frame_->is_wasm());

    const WasmGlobal& global_variable =
        WasmFrame::cast(frame_)->native_module()->module()->globals.at(global);

    Handle<WasmInstanceObject> instance(
        WasmFrame::cast(frame_)->wasm_instance(), isolate_);
    WasmValue result =
        WasmInstanceObject::GetGlobalValue(instance, global_variable);
    WriteResult(result, result_offset);
  }

  void GetOperand(uint32_t operand, uint32_t result_offset) {
    DCHECK(frame_->is_wasm());
    wasm::DebugInfo* debug_info =
        WasmFrame::cast(frame_)->native_module()->GetDebugInfo();
    WasmValue result = debug_info->GetStackValue(
        operand, frame_->pc(), frame_->fp(), frame_->callee_fp());

    WriteResult(result, result_offset);
  }

  static void GetLocalTrampoline(
      const v8::FunctionCallbackInfo<v8::Value>& args) {
    DebugEvaluatorProxy& proxy = GetProxy(args);
    uint32_t local = proxy.GetArgAsUInt32(args, 0);
    uint32_t result = proxy.GetArgAsUInt32(args, 1);

    proxy.GetLocal(local, result);
  }

  static void GetGlobalTrampoline(
      const v8::FunctionCallbackInfo<v8::Value>& args) {
    DebugEvaluatorProxy& proxy = GetProxy(args);
    uint32_t global = proxy.GetArgAsUInt32(args, 0);
    uint32_t result = proxy.GetArgAsUInt32(args, 1);

    proxy.GetGlobal(global, result);
  }

  static void GetOperandTrampoline(
      const v8::FunctionCallbackInfo<v8::Value>& args) {
    DebugEvaluatorProxy& proxy = GetProxy(args);
    uint32_t operand = proxy.GetArgAsUInt32(args, 0);
    uint32_t result = proxy.GetArgAsUInt32(args, 1);

    proxy.GetOperand(operand, result);
  }

  Handle<JSObject> CreateImports() {
    Handle<JSObject> imports_obj =
        isolate_->factory()->NewJSObject(isolate_->object_function());
    Handle<JSObject> import_module_obj =
        isolate_->factory()->NewJSObject(isolate_->object_function());
    Object::SetProperty(isolate_, imports_obj, V8String(isolate_, "env"),
                        import_module_obj)
        .Assert();

    AddImport(import_module_obj, "__getOperand",
              DebugEvaluatorProxy::GetOperandTrampoline);
    AddImport(import_module_obj, "__getGlobal",
              DebugEvaluatorProxy::GetGlobalTrampoline);
    AddImport(import_module_obj, "__getLocal",
              DebugEvaluatorProxy::GetLocalTrampoline);
    AddImport(import_module_obj, "__getMemory",
              DebugEvaluatorProxy::GetMemoryTrampoline);
    AddImport(import_module_obj, "__sbrk", DebugEvaluatorProxy::SbrkTrampoline);

    return imports_obj;
  }

  void SetInstances(Handle<WasmInstanceObject> evaluator,
                    Handle<WasmInstanceObject> debuggee) {
    evaluator_ = evaluator;
    debuggee_ = debuggee;
  }

 private:
  template <typename T>
  void WriteResultImpl(const WasmValue& result, uint32_t result_offset) {
    wasm::ScheduledErrorThrower thrower(isolate_, "debug evaluate proxy");
    T val = result.to<T>();
    STATIC_ASSERT(static_cast<uint32_t>(sizeof(T)) == sizeof(T));
    if (CheckRangeOutOfBounds(result_offset, sizeof(T),
                              evaluator_->memory_size(), &thrower)) {
      return;
    }
    memcpy(&evaluator_->memory_start()[result_offset], &val, sizeof(T));
  }

  void WriteResult(const WasmValue& result, uint32_t result_offset) {
    switch (result.type().kind()) {
      case ValueType::kI32:
        WriteResultImpl<uint32_t>(result, result_offset);
        break;
      case ValueType::kI64:
        WriteResultImpl<int64_t>(result, result_offset);
        break;
      case ValueType::kF32:
        WriteResultImpl<float>(result, result_offset);
        break;
      case ValueType::kF64:
        WriteResultImpl<double>(result, result_offset);
        break;
      default:
        UNIMPLEMENTED();
    }
  }

  uint32_t GetArgAsUInt32(const v8::FunctionCallbackInfo<v8::Value>& args,
                          int index) {
    // No type/range checks needed on his because this is only called for {args}
    // where we have performed a signature check via {VerifyEvaluatorInterface}
    double number = Utils::OpenHandle(*args[index])->Number();
    return static_cast<uint32_t>(number);
  }

  static DebugEvaluatorProxy& GetProxy(
      const v8::FunctionCallbackInfo<v8::Value>& args) {
    return *reinterpret_cast<DebugEvaluatorProxy*>(
        args.Data().As<v8::External>()->Value());
  }

  template <typename CallableT>
  void AddImport(Handle<JSObject> import_module_obj, const char* function_name,
                 CallableT callback) {
    v8::Isolate* api_isolate = reinterpret_cast<v8::Isolate*>(isolate_);
    v8::Local<v8::Context> context = api_isolate->GetCurrentContext();
    std::string data;
    v8::Local<v8::Function> v8_function =
        v8::Function::New(context, callback,
                          v8::External::New(api_isolate, this))
            .ToLocalChecked();

    Handle<JSReceiver> wrapped_function = Utils::OpenHandle(*v8_function);

    Object::SetProperty(isolate_, import_module_obj,
                        V8String(isolate_, function_name), wrapped_function)
        .Assert();
  }

  Isolate* isolate_;
  CommonFrame* frame_;
  Handle<WasmInstanceObject> evaluator_;
  Handle<WasmInstanceObject> debuggee_;
};

static bool VerifyEvaluatorInterface(const WasmModule* raw_module,
                                     const ModuleWireBytes& bytes,
                                     ErrorThrower* thrower) {
  for (const WasmImport imported : raw_module->import_table) {
    if (imported.kind != ImportExportKindCode::kExternalFunction) continue;
    const WasmFunction& F = raw_module->functions.at(imported.index);
    std::string module_name(bytes.start() + imported.module_name.offset(),
                            bytes.start() + imported.module_name.end_offset());
    std::string field_name(bytes.start() + imported.field_name.offset(),
                           bytes.start() + imported.field_name.end_offset());

    if (module_name == "env") {
      if (field_name == "__getMemory") {
        // void __getMemory(uint32_t offset, uint32_t size, void* result);
        if (CheckSignature(kWasmBottom, {kWasmI32, kWasmI32, kWasmI32}, F.sig,
                           thrower)) {
          continue;
        }
      } else if (field_name == "__getOperand") {
        // void __getOperand(uint32_t local,  void* result)
        if (CheckSignature(kWasmBottom, {kWasmI32, kWasmI32}, F.sig, thrower)) {
          continue;
        }
      } else if (field_name == "__getGlobal") {
        // void __getGlobal(uint32_t local,  void* result)
        if (CheckSignature(kWasmBottom, {kWasmI32, kWasmI32}, F.sig, thrower)) {
          continue;
        }
      } else if (field_name == "__getLocal") {
        // void __getLocal(uint32_t local,  void* result)
        if (CheckSignature(kWasmBottom, {kWasmI32, kWasmI32}, F.sig, thrower)) {
          continue;
        }
      } else if (field_name == "__debug") {
        // void __debug(uint32_t flag, uint32_t value)
        if (CheckSignature(kWasmBottom, {kWasmI32, kWasmI32}, F.sig, thrower)) {
          continue;
        }
      } else if (field_name == "__sbrk") {
        // uint32_t __sbrk(uint32_t increment)
        if (CheckSignature(kWasmI32, {kWasmI32}, F.sig, thrower)) {
          continue;
        }
      }
    }

    if (!thrower->error()) {
      thrower->LinkError("Unknown import \"%s\" \"%s\"", module_name.c_str(),
                         field_name.c_str());
    }

    return false;
  }
  for (const WasmExport& exported : raw_module->export_table) {
    if (exported.kind != ImportExportKindCode::kExternalFunction) continue;
    const WasmFunction& F = raw_module->functions.at(exported.index);
    std::string field_name(bytes.start() + exported.name.offset(),
                           bytes.start() + exported.name.end_offset());
    if (field_name == "wasm_format") {
      if (!CheckSignature(kWasmI32, {}, F.sig, thrower)) return false;
    }
  }
  return true;
}
}  // namespace

Maybe<std::string> DebugEvaluateImpl(
    Vector<const byte> snippet, Handle<WasmInstanceObject> debuggee_instance,
    CommonFrame* frame) {
  Isolate* isolate = debuggee_instance->GetIsolate();
  HandleScope handle_scope(isolate);
  WasmEngine* engine = isolate->wasm_engine();
  wasm::ErrorThrower thrower(isolate, "wasm debug evaluate");

  // Create module object.
  wasm::ModuleWireBytes bytes(snippet);
  wasm::WasmFeatures features = wasm::WasmFeatures::FromIsolate(isolate);
  Handle<WasmModuleObject> evaluator_module;
  if (!engine->SyncCompile(isolate, features, &thrower, bytes)
           .ToHandle(&evaluator_module)) {
    return Nothing<std::string>();
  }

  // Verify interface.
  const WasmModule* raw_module = evaluator_module->module();
  if (!VerifyEvaluatorInterface(raw_module, bytes, &thrower)) {
    return Nothing<std::string>();
  }

  // Set up imports.
  DebugEvaluatorProxy proxy(isolate, frame);
  Handle<JSObject> imports = proxy.CreateImports();

  // Instantiate Module.
  Handle<WasmInstanceObject> evaluator_instance;
  if (!engine->SyncInstantiate(isolate, &thrower, evaluator_module, imports, {})
           .ToHandle(&evaluator_instance)) {
    return Nothing<std::string>();
  }

  proxy.SetInstances(evaluator_instance, debuggee_instance);

  Handle<JSObject> exports_obj(evaluator_instance->exports_object(), isolate);
  Handle<Object> entry_point_obj;
  bool get_property_success =
      Object::GetProperty(isolate, exports_obj,
                          V8String(isolate, "wasm_format"))
          .ToHandle(&entry_point_obj);
  if (!get_property_success ||
      !WasmExportedFunction::IsWasmExportedFunction(*entry_point_obj)) {
    thrower.LinkError("Missing export: \"wasm_format\"");
    return Nothing<std::string>();
  }
  Handle<WasmExportedFunction> entry_point =
      Handle<WasmExportedFunction>::cast(entry_point_obj);

  // TODO(wasm): Cache this code.
  Handle<Code> wasm_entry = compiler::CompileCWasmEntry(
      isolate, entry_point->sig(), debuggee_instance->module());

  CWasmArgumentsPacker packer(4 /* uint32_t return value, no parameters. */);
  Execution::CallWasm(isolate, wasm_entry, entry_point->GetWasmCallTarget(),
                      evaluator_instance, packer.argv());
  if (isolate->has_pending_exception()) return Nothing<std::string>();

  uint32_t offset = packer.Pop<uint32_t>();
  if (CheckRangeOutOfBounds(offset, 0, evaluator_instance->memory_size(),
                            &thrower)) {
    return Nothing<std::string>();
  }

  // Copy the zero-terminated string result but don't overflow.
  std::string result;
  byte* heap = evaluator_instance->memory_start() + offset;
  for (; offset < evaluator_instance->memory_size(); ++offset, ++heap) {
    if (*heap == 0) return Just(result);
    result.push_back(*heap);
  }

  thrower.RuntimeError("The evaluation returned an invalid result");
  return Nothing<std::string>();
}

MaybeHandle<String> DebugEvaluate(Vector<const byte> snippet,
                                  Handle<WasmInstanceObject> debuggee_instance,
                                  CommonFrame* frame) {
  Maybe<std::string> result =
      DebugEvaluateImpl(snippet, debuggee_instance, frame);
  if (result.IsNothing()) return {};
  std::string result_str = result.ToChecked();
  return V8String(debuggee_instance->GetIsolate(), result_str.c_str());
}

}  // namespace wasm
}  // namespace internal
}  // namespace v8
