blob: 1af81d3dbecc3e55d5ac421e5e5438115089294f [file] [log] [blame]
// 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 <atomic>
#include <map>
#include "src/base/macros.h"
#include "src/debug/wasm/gdb-server/gdb-remote-util.h"
namespace v8 {
namespace internal {
namespace wasm {
namespace gdb_server {
class GdbServer;
class Packet;
class Session;
// Class Target represents a debugging target. It contains the logic to decode
// incoming GDB-remote packets, execute them forwarding the debugger commands
// and queries to the Wasm engine, and send back GDB-remote packets.
class Target {
// Contruct a Target object.
explicit Target(GdbServer* gdb_server);
// This function spin on a debugging session, until it closes.
void Run(Session* ses);
void Terminate();
bool IsTerminated() const { return status_ == Status::Terminated; }
// Notifies that the debuggee thread suspended at a breakpoint.
void OnProgramBreak(Isolate* isolate,
const std::vector<wasm_addr_t>& call_frames);
// Notifies that the debuggee thread suspended because of an unhandled
// exception.
void OnException(Isolate* isolate,
const std::vector<wasm_addr_t>& call_frames);
// Returns the state at the moment of the thread suspension.
const std::vector<wasm_addr_t> GetCallStack() const;
wasm_addr_t GetCurrentPc() const;
Isolate* GetCurrentIsolate() const { return current_isolate_; }
void OnSuspended(Isolate* isolate, int signal,
const std::vector<wasm_addr_t>& call_frames);
// Initializes a map used to make fast lookups when handling query packets
// that have a constant response.
void InitQueryPropertyMap();
// Blocks waiting for one of these two events to occur:
// - A network packet arrives from the debugger, or the debugger connection is
// closed;
// - The debuggee suspends execution because of a trap or breakpoint.
void WaitForDebugEvent();
void ProcessDebugEvent();
// Processes GDB-remote packets that arrive from the debugger.
// This method should be called when the debuggee has suspended its execution.
void ProcessCommands();
// Requests that the thread suspends execution at the next Wasm instruction.
void Suspend();
enum class ErrorCode { None = 0, BadFormat = 1, BadArgs = 2, Failed = 3 };
enum class ProcessPacketResult {
Paused, // The command was processed, debuggee still paused.
Continue, // The debuggee should resume execution.
Detach, // Request to detach from the debugger.
Kill // Request to terminate the debuggee process.
// This function always succeedes, since all errors are reported as an error
// string "Exx" where xx is a two digit number.
// The return value indicates if the target can resume execution or it is
// still paused.
ProcessPacketResult ProcessPacket(Packet* pkt_in, Packet* pkt_out);
// Processes a general query packet
ErrorCode ProcessQueryPacket(const Packet* pkt_in, Packet* pkt_out);
// Formats a 'Stop-reply' packet, which is sent in response of a 'c'
// (continue), 's' (step) and '?' (query halt reason) commands.
void SetStopReply(Packet* pkt_out) const;
enum class Status { Running, WaitingForSuspension, Suspended, Terminated };
void SetStatus(Status status, int8_t signal = 0,
std::vector<wasm_addr_t> call_frames_ = {},
Isolate* isolate = nullptr);
GdbServer* gdb_server_;
std::atomic<Status> status_;
// Signal being processed.
std::atomic<int8_t> cur_signal_;
// Session object not owned by the Target.
Session* session_;
// Map used to make fast lookups when handling query packets.
typedef std::map<std::string, std::string> QueryPropertyMap;
QueryPropertyMap query_properties_;
bool debugger_initial_suspension_;
// Used to block waiting for suspension
v8::base::Semaphore semaphore_;
mutable v8::base::Mutex mutex_;
// Protected by {mutex_}:
// Current isolate. This is not null only when the target is in a Suspended
// state and it is the isolate associated to the current call stack and used
// for all debugging activities.
Isolate* current_isolate_;
// Call stack when the execution is suspended.
std::vector<wasm_addr_t> call_frames_;
// End of fields protected by {mutex_}.
} // namespace gdb_server
} // namespace wasm
} // namespace internal
} // namespace v8