// 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/debug/wasm/gdb-server/wasm-module-debug.h"

#include "src/api/api-inl.h"
#include "src/api/api.h"
#include "src/base/platform/wrappers.h"
#include "src/execution/frames-inl.h"
#include "src/execution/frames.h"
#include "src/objects/script.h"
#include "src/wasm/wasm-debug.h"
#include "src/wasm/wasm-value.h"

namespace v8 {
namespace internal {
namespace wasm {
namespace gdb_server {

WasmModuleDebug::WasmModuleDebug(v8::Isolate* isolate,
                                 Local<debug::WasmScript> wasm_script) {
  DCHECK_EQ(Script::TYPE_WASM, Utils::OpenHandle(*wasm_script)->type());

  isolate_ = isolate;
  wasm_script_ = Global<debug::WasmScript>(isolate, wasm_script);
}

std::string WasmModuleDebug::GetModuleName() const {
  v8::Local<debug::WasmScript> wasm_script = wasm_script_.Get(isolate_);
  v8::Local<v8::String> name;
  std::string module_name;
  if (wasm_script->Name().ToLocal(&name)) {
    module_name = *(v8::String::Utf8Value(isolate_, name));
  }
  return module_name;
}

Handle<WasmInstanceObject> WasmModuleDebug::GetFirstWasmInstance() {
  v8::Local<debug::WasmScript> wasm_script = wasm_script_.Get(isolate_);
  Handle<Script> script = Utils::OpenHandle(*wasm_script);

  Handle<WeakArrayList> weak_instance_list(script->wasm_weak_instance_list(),
                                           GetIsolate());
  if (weak_instance_list->length() > 0) {
    MaybeObject maybe_instance = weak_instance_list->Get(0);
    if (maybe_instance->IsWeak()) {
      Handle<WasmInstanceObject> instance(
          WasmInstanceObject::cast(maybe_instance->GetHeapObjectAssumeWeak()),
          GetIsolate());
      return instance;
    }
  }
  return Handle<WasmInstanceObject>::null();
}

int GetLEB128Size(Vector<const uint8_t> module_bytes, int offset) {
  int index = offset;
  while (module_bytes[index] & 0x80) index++;
  return index + 1 - offset;
}

int ReturnPc(const NativeModule* native_module, int pc) {
  Vector<const uint8_t> wire_bytes = native_module->wire_bytes();
  uint8_t opcode = wire_bytes[pc];
  switch (opcode) {
    case kExprCallFunction: {
      // skip opcode
      pc++;
      // skip function index
      return pc + GetLEB128Size(wire_bytes, pc);
    }
    case kExprCallIndirect: {
      // skip opcode
      pc++;
      // skip signature index
      pc += GetLEB128Size(wire_bytes, pc);
      // skip table index
      return pc + GetLEB128Size(wire_bytes, pc);
    }
    default:
      UNREACHABLE();
  }
}

// static
std::vector<wasm_addr_t> WasmModuleDebug::GetCallStack(
    uint32_t debug_context_id, Isolate* isolate) {
  std::vector<wasm_addr_t> call_stack;
  for (StackFrameIterator frame_it(isolate); !frame_it.done();
       frame_it.Advance()) {
    StackFrame* const frame = frame_it.frame();
    switch (frame->type()) {
      case StackFrame::JAVA_SCRIPT_BUILTIN_CONTINUATION:
      case StackFrame::JAVA_SCRIPT_BUILTIN_CONTINUATION_WITH_CATCH:
      case StackFrame::OPTIMIZED:
      case StackFrame::INTERPRETED:
      case StackFrame::BUILTIN:
      case StackFrame::WASM: {
        // A standard frame may include many summarized frames, due to inlining.
        std::vector<FrameSummary> frames;
        CommonFrame::cast(frame)->Summarize(&frames);
        for (size_t i = frames.size(); i-- != 0;) {
          int offset = 0;
          Handle<Script> script;

          auto& summary = frames[i];
          if (summary.IsJavaScript()) {
            FrameSummary::JavaScriptFrameSummary const& java_script =
                summary.AsJavaScript();
            offset = java_script.code_offset();
            script = Handle<Script>::cast(java_script.script());
          } else if (summary.IsWasm()) {
            FrameSummary::WasmFrameSummary const& wasm = summary.AsWasm();
            offset = GetWasmFunctionOffset(wasm.wasm_instance()->module(),
                                           wasm.function_index()) +
                     wasm.byte_offset();
            script = wasm.script();

            bool zeroth_frame = call_stack.empty();
            if (!zeroth_frame) {
              const NativeModule* native_module =
                  wasm.wasm_instance()->module_object().native_module();
              offset = ReturnPc(native_module, offset);
            }
          }

          if (offset > 0) {
            call_stack.push_back(
                {debug_context_id << 16 | script->id(), uint32_t(offset)});
          }
        }
        break;
      }

      case StackFrame::BUILTIN_EXIT:
      default:
        // ignore the frame.
        break;
    }
  }
  if (call_stack.empty()) call_stack.push_back({1, 0});
  return call_stack;
}

// static
std::vector<FrameSummary> WasmModuleDebug::FindWasmFrame(
    StackTraceFrameIterator* frame_it, uint32_t* frame_index) {
  while (!frame_it->done()) {
    StackFrame* const frame = frame_it->frame();
    switch (frame->type()) {
      case StackFrame::JAVA_SCRIPT_BUILTIN_CONTINUATION:
      case StackFrame::JAVA_SCRIPT_BUILTIN_CONTINUATION_WITH_CATCH:
      case StackFrame::OPTIMIZED:
      case StackFrame::INTERPRETED:
      case StackFrame::BUILTIN:
      case StackFrame::WASM: {
        // A standard frame may include many summarized frames, due to inlining.
        std::vector<FrameSummary> frames;
        CommonFrame::cast(frame)->Summarize(&frames);
        const size_t frame_count = frames.size();
        DCHECK_GT(frame_count, 0);

        if (frame_count > *frame_index) {
          if (frame_it->is_wasm())
            return frames;
          else
            return {};
        } else {
          *frame_index -= frame_count;
          frame_it->Advance();
        }
        break;
      }

      case StackFrame::BUILTIN_EXIT:
      default:
        // ignore the frame.
        break;
    }
  }
  return {};
}

// static
Handle<WasmInstanceObject> WasmModuleDebug::GetWasmInstance(
    Isolate* isolate, uint32_t frame_index) {
  StackTraceFrameIterator frame_it(isolate);
  std::vector<FrameSummary> frames = FindWasmFrame(&frame_it, &frame_index);
  if (frames.empty()) {
    return Handle<WasmInstanceObject>::null();
  }

  int reversed_index = static_cast<int>(frames.size() - 1 - frame_index);
  const FrameSummary::WasmFrameSummary& summary =
      frames[reversed_index].AsWasm();
  return summary.wasm_instance();
}

// static
bool WasmModuleDebug::GetWasmGlobal(Isolate* isolate, uint32_t frame_index,
                                    uint32_t index, uint8_t* buffer,
                                    uint32_t buffer_size, uint32_t* size) {
  HandleScope handles(isolate);

  Handle<WasmInstanceObject> instance = GetWasmInstance(isolate, frame_index);
  if (!instance.is_null()) {
    Handle<WasmModuleObject> module_object(instance->module_object(), isolate);
    const wasm::WasmModule* module = module_object->module();
    if (index < module->globals.size()) {
      wasm::WasmValue wasm_value =
          WasmInstanceObject::GetGlobalValue(instance, module->globals[index]);
      return GetWasmValue(wasm_value, buffer, buffer_size, size);
    }
  }
  return false;
}

// static
bool WasmModuleDebug::GetWasmLocal(Isolate* isolate, uint32_t frame_index,
                                   uint32_t index, uint8_t* buffer,
                                   uint32_t buffer_size, uint32_t* size) {
  HandleScope handles(isolate);

  StackTraceFrameIterator frame_it(isolate);
  std::vector<FrameSummary> frames = FindWasmFrame(&frame_it, &frame_index);
  if (frames.empty()) {
    return false;
  }

  int reversed_index = static_cast<int>(frames.size() - 1 - frame_index);
  const FrameSummary& summary = frames[reversed_index];
  if (summary.IsWasm()) {
    Handle<WasmInstanceObject> instance = summary.AsWasm().wasm_instance();
    if (!instance.is_null()) {
      Handle<WasmModuleObject> module_object(instance->module_object(),
                                             isolate);
      wasm::NativeModule* native_module = module_object->native_module();
      DebugInfo* debug_info = native_module->GetDebugInfo();
      if (static_cast<uint32_t>(debug_info->GetNumLocals(
              isolate, frame_it.frame()->pc())) > index) {
        wasm::WasmValue wasm_value = debug_info->GetLocalValue(
            index, isolate, frame_it.frame()->pc(), frame_it.frame()->fp(),
            frame_it.frame()->callee_fp());
        return GetWasmValue(wasm_value, buffer, buffer_size, size);
      }
    }
  }
  return false;
}

// static
bool WasmModuleDebug::GetWasmStackValue(Isolate* isolate, uint32_t frame_index,
                                        uint32_t index, uint8_t* buffer,
                                        uint32_t buffer_size, uint32_t* size) {
  HandleScope handles(isolate);

  StackTraceFrameIterator frame_it(isolate);
  std::vector<FrameSummary> frames = FindWasmFrame(&frame_it, &frame_index);
  if (frames.empty()) {
    return false;
  }

  int reversed_index = static_cast<int>(frames.size() - 1 - frame_index);
  const FrameSummary& summary = frames[reversed_index];
  if (summary.IsWasm()) {
    Handle<WasmInstanceObject> instance = summary.AsWasm().wasm_instance();
    if (!instance.is_null()) {
      Handle<WasmModuleObject> module_object(instance->module_object(),
                                             isolate);
      wasm::NativeModule* native_module = module_object->native_module();
      DebugInfo* debug_info = native_module->GetDebugInfo();
      if (static_cast<uint32_t>(debug_info->GetStackDepth(
              isolate, frame_it.frame()->pc())) > index) {
        WasmValue wasm_value = debug_info->GetStackValue(
            index, isolate, frame_it.frame()->pc(), frame_it.frame()->fp(),
            frame_it.frame()->callee_fp());
        return GetWasmValue(wasm_value, buffer, buffer_size, size);
      }
    }
  }
  return false;
}

// static
uint32_t WasmModuleDebug::GetWasmMemory(Isolate* isolate, uint32_t frame_index,
                                        uint32_t offset, uint8_t* buffer,
                                        uint32_t size) {
  HandleScope handles(isolate);

  uint32_t bytes_read = 0;
  Handle<WasmInstanceObject> instance = GetWasmInstance(isolate, frame_index);
  if (!instance.is_null()) {
    uint8_t* mem_start = instance->memory_start();
    size_t mem_size = instance->memory_size();
    if (static_cast<uint64_t>(offset) + size <= mem_size) {
      memcpy(buffer, mem_start + offset, size);
      bytes_read = size;
    } else if (offset < mem_size) {
      bytes_read = static_cast<uint32_t>(mem_size) - offset;
      memcpy(buffer, mem_start + offset, bytes_read);
    }
  }
  return bytes_read;
}

uint32_t WasmModuleDebug::GetWasmModuleBytes(wasm_addr_t wasm_addr,
                                             uint8_t* buffer, uint32_t size) {
  uint32_t bytes_read = 0;
  // Any instance will work.
  Handle<WasmInstanceObject> instance = GetFirstWasmInstance();
  if (!instance.is_null()) {
    Handle<WasmModuleObject> module_object(instance->module_object(),
                                           GetIsolate());
    wasm::NativeModule* native_module = module_object->native_module();
    const wasm::ModuleWireBytes wire_bytes(native_module->wire_bytes());
    uint32_t offset = wasm_addr.Offset();
    if (offset < wire_bytes.length()) {
      uint32_t module_size = static_cast<uint32_t>(wire_bytes.length());
      bytes_read = module_size - offset >= size ? size : module_size - offset;
      memcpy(buffer, wire_bytes.start() + offset, bytes_read);
    }
  }
  return bytes_read;
}

bool WasmModuleDebug::AddBreakpoint(uint32_t offset, int* breakpoint_id) {
  v8::Local<debug::WasmScript> wasm_script = wasm_script_.Get(isolate_);
  Handle<Script> script = Utils::OpenHandle(*wasm_script);
  Handle<String> condition = GetIsolate()->factory()->empty_string();
  int breakpoint_address = static_cast<int>(offset);
  return GetIsolate()->debug()->SetBreakPointForScript(
      script, condition, &breakpoint_address, breakpoint_id);
}

void WasmModuleDebug::RemoveBreakpoint(uint32_t offset, int breakpoint_id) {
  v8::Local<debug::WasmScript> wasm_script = wasm_script_.Get(isolate_);
  Handle<Script> script = Utils::OpenHandle(*wasm_script);
  GetIsolate()->debug()->RemoveBreakpointForWasmScript(script, breakpoint_id);
}

void WasmModuleDebug::PrepareStep() {
  i::Isolate* isolate = GetIsolate();
  DebugScope debug_scope(isolate->debug());
  debug::PrepareStep(reinterpret_cast<v8::Isolate*>(isolate),
                     debug::StepAction::StepIn);
}

template <typename T>
bool StoreValue(const T& value, uint8_t* buffer, uint32_t buffer_size,
                uint32_t* size) {
  *size = sizeof(value);
  if (*size > buffer_size) return false;
  memcpy(buffer, &value, *size);
  return true;
}

// static
bool WasmModuleDebug::GetWasmValue(const wasm::WasmValue& wasm_value,
                                   uint8_t* buffer, uint32_t buffer_size,
                                   uint32_t* size) {
  switch (wasm_value.type().kind()) {
    case wasm::kWasmI32.kind():
      return StoreValue(wasm_value.to_i32(), buffer, buffer_size, size);
    case wasm::kWasmI64.kind():
      return StoreValue(wasm_value.to_i64(), buffer, buffer_size, size);
    case wasm::kWasmF32.kind():
      return StoreValue(wasm_value.to_f32(), buffer, buffer_size, size);
    case wasm::kWasmF64.kind():
      return StoreValue(wasm_value.to_f64(), buffer, buffer_size, size);
    case wasm::kWasmS128.kind():
      return StoreValue(wasm_value.to_s128(), buffer, buffer_size, size);

    case wasm::kWasmStmt.kind():
    case wasm::kWasmExternRef.kind():
    case wasm::kWasmFuncRef.kind():
    case wasm::kWasmExnRef.kind():
    case wasm::kWasmBottom.kind():
    default:
      // Not supported
      return false;
  }
}

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