// 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/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
