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

#ifndef V8_DEBUG_WASM_GDB_SERVER_GDB_SERVER_H_
#define V8_DEBUG_WASM_GDB_SERVER_GDB_SERVER_H_

#include <map>
#include <memory>
#include "src/debug/wasm/gdb-server/gdb-server-thread.h"
#include "src/debug/wasm/gdb-server/wasm-module-debug.h"

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

class TaskRunner;

// class GdbServer acts as a manager for the GDB-remote stub. It is instantiated
// as soon as the first Wasm module is loaded in the Wasm engine and spawns a
// separate thread to accept connections and exchange messages with a debugger.
// It will contain the logic to serve debugger queries and access the state of
// the Wasm engine.
class GdbServer {
 public:
  // Factory method: creates and returns a GdbServer. Spawns a "GDB-remote"
  // thread that will be used to communicate with the debugger.
  // May return null on failure.
  // This should be called once, the first time a Wasm module is loaded in the
  // Wasm engine.
  static std::unique_ptr<GdbServer> Create();

  // Stops the "GDB-remote" thread and waits for it to complete. This should be
  // called once, when the Wasm engine shuts down.
  ~GdbServer();

  // Queries the set of the Wasm modules currently loaded. Each module is
  // identified by a unique integer module id.
  struct WasmModuleInfo {
    uint32_t module_id;
    std::string module_name;
  };
  std::vector<WasmModuleInfo> GetLoadedModules();

  // Queries the value of the {index} global value in the Wasm module identified
  // by {frame_index}.
  //
  bool GetWasmGlobal(uint32_t frame_index, uint32_t index, uint8_t* buffer,
                     uint32_t buffer_size, uint32_t* size);

  // Queries the value of the {index} local value in the {frame_index}th stack
  // frame in the Wasm module identified by {frame_index}.
  //
  bool GetWasmLocal(uint32_t frame_index, uint32_t index, uint8_t* buffer,
                    uint32_t buffer_size, uint32_t* size);

  // Queries the value of the {index} value in the operand stack.
  //
  bool GetWasmStackValue(uint32_t frame_index, uint32_t index, uint8_t* buffer,
                         uint32_t buffer_size, uint32_t* size);

  // Reads {size} bytes, starting from {offset}, from the Memory instance
  // associated to the Wasm module identified by {frame_index}.
  // Returns the number of bytes copied to {buffer}, or 0 is case of error.
  // Note: only one Memory for Module is currently supported.
  //
  uint32_t GetWasmMemory(uint32_t frame_index, uint32_t offset, uint8_t* buffer,
                         uint32_t size);

  // Reads {size} bytes, starting from the low dword of {address}, from the Code
  // space of th Wasm module identified by high dword of {address}.
  // Returns the number of bytes copied to {buffer}, or 0 is case of error.
  uint32_t GetWasmModuleBytes(wasm_addr_t address, uint8_t* buffer,
                              uint32_t size);

  // Inserts a breakpoint at the offset {offset} of the Wasm module identified
  // by {wasm_module_id}.
  // Returns true if the breakpoint was successfully added.
  bool AddBreakpoint(uint32_t wasm_module_id, uint32_t offset);

  // Removes a breakpoint at the offset {offset} of the Wasm module identified
  // by {wasm_module_id}.
  // Returns true if the breakpoint was successfully removed.
  bool RemoveBreakpoint(uint32_t wasm_module_id, uint32_t offset);

  // Returns the current call stack as a vector of program counters.
  std::vector<wasm_addr_t> GetWasmCallStack() const;

  // Manage the set of Isolates for this GdbServer.
  void AddIsolate(Isolate* isolate);
  void RemoveIsolate(Isolate* isolate);

  // Requests that the thread suspend execution at the next Wasm instruction.
  void Suspend();

  // Handle stepping in wasm functions via the wasm interpreter.
  void PrepareStep();

  // Called when the target debuggee can resume execution (for example after
  // having been suspended on a breakpoint). Terminates the task runner leaving
  // all pending tasks in the queue.
  void QuitMessageLoopOnPause();

 private:
  GdbServer();

  // When the target debuggee is suspended for a breakpoint or exception, blocks
  // the main (isolate) thread and enters in a message loop. Here it waits on a
  // queue of Task objects that are posted by the GDB-stub thread and that
  // represent queries received from the debugger via the GDB-remote protocol.
  void RunMessageLoopOnPause();

  // Post a task to run a callback in the isolate thread.
  template <typename Callback>
  auto RunSyncTask(Callback&& callback) const;

  void AddWasmModule(uint32_t module_id, Local<debug::WasmScript> wasm_script);

  // Given a Wasm module id, retrieves the corresponding debugging WasmScript
  // object.
  bool GetModuleDebugHandler(uint32_t module_id,
                             WasmModuleDebug** wasm_module_debug);

  // Returns the debugging target.
  Target& GetTarget() const;

  // Class DebugDelegate implements the debug::DebugDelegate interface to
  // receive notifications when debug events happen in a given isolate, like a
  // script being loaded, a breakpoint being hit, an exception being thrown.
  class DebugDelegate : public debug::DebugDelegate {
   public:
    DebugDelegate(Isolate* isolate, GdbServer* gdb_server);
    ~DebugDelegate();

    // debug::DebugDelegate
    void ScriptCompiled(Local<debug::Script> script, bool is_live_edited,
                        bool has_compile_error) override;
    void BreakProgramRequested(Local<v8::Context> paused_context,
                               const std::vector<debug::BreakpointId>&
                                   inspector_break_points_hit) override;
    void ExceptionThrown(Local<v8::Context> paused_context,
                         Local<Value> exception, Local<Value> promise,
                         bool is_uncaught,
                         debug::ExceptionType exception_type) override;
    bool IsFunctionBlackboxed(Local<debug::Script> script,
                              const debug::Location& start,
                              const debug::Location& end) override;

   private:
    // Calculates module_id as:
    // +--------------------+------------------- +
    // | DebugDelegate::id_ |    Script::Id()    |
    // +--------------------+------------------- +
    //  <----- 16 bit -----> <----- 16 bit ----->
    uint32_t GetModuleId(uint32_t script_id) const {
      DCHECK_LT(script_id, 0x10000);
      DCHECK_LT(id_, 0x10000);
      return id_ << 16 | script_id;
    }

    Isolate* isolate_;
    uint32_t id_;
    GdbServer* gdb_server_;

    static std::atomic<uint32_t> id_s;
  };

  // The GDB-stub thread where all the communication with the debugger happens.
  std::unique_ptr<GdbServerThread> thread_;

  // Used to transform the queries that arrive in the GDB-stub thread into
  // tasks executed in the main (isolate) thread.
  std::unique_ptr<TaskRunner> task_runner_;

  //////////////////////////////////////////////////////////////////////////////
  // Always accessed in the isolate thread.

  // Set of breakpoints currently defines in Wasm code.
  typedef std::map<uint64_t, int> BreakpointsMap;
  BreakpointsMap breakpoints_;

  typedef std::map<uint32_t, WasmModuleDebug> ScriptsMap;
  ScriptsMap scripts_;

  typedef std::map<Isolate*, std::unique_ptr<DebugDelegate>>
      IsolateDebugDelegateMap;
  IsolateDebugDelegateMap isolate_delegates_;

  // End of fields always accessed in the isolate thread.
  //////////////////////////////////////////////////////////////////////////////

  DISALLOW_COPY_AND_ASSIGN(GdbServer);
};

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

#endif  // V8_DEBUG_WASM_GDB_SERVER_GDB_SERVER_H_
