15#include "llvm/Support/ErrorExtras.h"
51 return "GDB Remote protocol based WebAssembly debugging plug-in.";
62 if (crash_file_path ==
nullptr)
63 return std::make_shared<ProcessWasm>(target_sp, listener_sp);
68 bool plugin_specified_by_name) {
69 if (plugin_specified_by_name)
72 if (
Module *exe_module = target_sp->GetExecutableModulePointer()) {
73 if (
ObjectFile *exe_objfile = exe_module->GetObjectFile())
74 return exe_objfile->GetArchitecture().GetTriple().isWasm();
83 if (!
GetTarget().GetArchitecture().GetTriple().isWasm())
86 return std::make_shared<ThreadWasm>(*
this, tid);
89static size_t CopyGlobal(llvm::Expected<lldb::DataBufferSP> global,
void *buf,
98 const size_t global_size = (*global)->GetByteSize();
99 if (size > global_size) {
101 "Wasm global read failed: requested {0} bytes from a {1}-byte global",
106 std::memcpy(buf, (*global)->GetBytes(), size);
128llvm::Expected<uint32_t>
131 return llvm::createStringError(
132 "the global belongs to no known module instance");
138 for (uint32_t frame_index = 0;; ++frame_index) {
147 return llvm::createStringErrorV(
148 "the Wasm stub can only read a global through a frame, and no frame is "
149 "executing module {0:x}",
166 llvm_unreachable(
"Fully covered switch above!");
186 "Wasm read failed for invalid address {0:x} (type = {1:x}, module = "
187 "{2:x}, offset = {3:x})",
193llvm::Expected<std::vector<lldb::addr_t>>
196 packet.
Printf(
"qWasmCallStack:");
197 packet.
Printf(
"%" PRIx64, tid);
202 return llvm::createStringError(
"failed to send qWasmCallStack");
205 return llvm::createStringError(
"failed to get response for qWasmCallStack");
208 std::make_shared<DataBufferHeap>(response.
GetStringRef().size() / 2, 0);
209 const size_t bytes = response.
GetHexBytes(data_buffer_sp->GetData(),
'\xcc');
210 if (bytes == 0 || bytes %
sizeof(uint64_t) != 0)
211 return llvm::createStringError(
"invalid response for qWasmCallStack");
218 std::vector<lldb::addr_t> call_stack_pcs;
219 while (offset < bytes)
220 call_stack_pcs.push_back(data.
GetU64(&offset));
222 return call_stack_pcs;
225llvm::Expected<lldb::DataBufferSP>
228 if (
m_gdb_comm.SendPacketAndWaitForResponse(packet, response) !=
230 return llvm::createStringErrorV(
"failed to send {0}", packet);
233 return llvm::createStringErrorV(
"failed to get response for {0}", packet);
237 response.
GetHexBytes(buffer_sp->GetData(),
'\xcc');
241llvm::Expected<lldb::DataBufferSP>
243 uint32_t frame_index, uint32_t index) {
247 llvm::formatv(
"qWasmLocal:{0};{1}", frame_index, index).str());
250 llvm::formatv(
"qWasmStackValue:{0};{1}", frame_index, index).str());
252 return llvm::createStringError(
"a Wasm global does not belong to a frame");
254 return llvm::createStringError(
"not a Wasm location");
256 llvm_unreachable(
"unhandled Wasm virtual register kind");
259llvm::Expected<lldb::DataBufferSP>
262 llvm::formatv(
"qWasmGlobal:{0};instance:{1};", index, module_id).str());
265llvm::Expected<lldb::DataBufferSP>
268 llvm::formatv(
"qWasmGlobal:{0};{1}", frame_index, index).str());
static llvm::raw_ostream & error(Stream &strm)
#define LLDB_PLUGIN_DEFINE(PluginName)
static size_t CopyGlobal(llvm::Expected< lldb::DataBufferSP > global, void *buf, size_t size, Status &error)
A subclass of DataBuffer that stores a data buffer on the heap.
A class that describes an executable image and its associated object and symbol files.
A plug-in interface definition class for object file parsers.
static bool RegisterPlugin(llvm::StringRef name, llvm::StringRef description, ABICreateInstance create_callback)
static bool UnregisterPlugin(ABICreateInstance create_callback)
An address in a process, qualified by an address space.
lldb::addr_t GetValue() const
void SetCanJIT(bool can_jit)
Sets whether executing JIT-compiled code in this process is possible.
lldb::UnixSignalsSP m_unix_signals_sp
virtual bool ShouldUseMemoryCache(const ProcessAddress &process_addr)
Whether ReadMemory should serve reads of process_addr out of the memory cache.
ThreadList m_thread_list_real
The threads for this process as are known to the protocol we are debugging with.
uint32_t GetAddressByteSize() const
Target & GetTarget()
Get the target object pointer for this module.
static Status static Status FromErrorStringWithFormatv(const char *format, Args &&...args)
static Status FromError(llvm::Error error)
Avoid using this in new code. Migrate APIs to llvm::Expected instead.
llvm::StringRef GetString() const
size_t Printf(const char *format,...) __attribute__((format(printf
Output printf formatted output to the stream.
static lldb::UnixSignalsSP Create(const ArchSpec &arch)
virtual std::shared_ptr< ThreadGDBRemote > CreateThread(lldb::tid_t tid)
GDBRemoteCommunicationClient m_gdb_comm
size_t DoReadMemory(const ProcessAddress &process_addr, void *buf, size_t size, Status &error) override
Actually do the reading of memory from a process.
static void DebuggerInitialize(Debugger &debugger)
ProcessGDBRemote(lldb::TargetSP target_sp, lldb::ListenerSP listener_sp)
ProcessWasm provides the access to the Wasm program state retrieved from the Wasm engine.
llvm::Expected< uint32_t > GetFallbackFrameIndex(uint32_t module_id)
The frame to read a global of module_id through, for a stub that cannot be told which instance to rea...
size_t ReadGlobal(uint32_t module_id, uint32_t index, void *buf, size_t size, Status &error)
Read a WebAssembly global of the module instance module_id names, through whichever scope that stub c...
llvm::Expected< lldb::DataBufferSP > GetWasmGlobalForModule(uint32_t module_id, uint32_t index)
Query the value of the global at index in the global index space of the module instance module_id nam...
llvm::Expected< lldb::DataBufferSP > GetWasmVariable(WasmVirtualRegisterKinds kind, uint32_t frame_index, uint32_t index)
Query the value of a frame-scoped WebAssembly variable, which is a local or a value on the operand st...
bool ShouldUseMemoryCache(const ProcessAddress &process_addr) override
Whether ReadMemory should serve reads of process_addr out of the memory cache.
llvm::StringRef GetPluginName() override
std::shared_ptr< process_gdb_remote::ThreadGDBRemote > CreateThread(lldb::tid_t tid) override
llvm::Expected< lldb::DataBufferSP > GetWasmGlobalForFrame(uint32_t frame_index, uint32_t index)
Query the value of a WebAssembly global through the frame at frame_index, which reaches only the glob...
bool CanNameInstance(uint32_t module_id)
Whether the instance holding a global can be named to the stub, which needs both a valid id to name i...
static llvm::StringRef GetPluginNameStatic()
bool CanDebug(lldb::TargetSP target_sp, bool plugin_specified_by_name) override
Check if a plug-in instance can debug the file in module.
static void DebuggerInitialize(Debugger &debugger)
static lldb::ProcessSP CreateInstance(lldb::TargetSP target_sp, lldb::ListenerSP listener_sp, const FileSpec *crash_file_path, bool can_connect)
llvm::Expected< std::vector< lldb::addr_t > > GetWasmCallStack(lldb::tid_t tid)
Retrieve the current call stack from the WebAssembly remote process.
llvm::Expected< lldb::DataBufferSP > SendWasmValueQuery(llvm::StringRef packet)
Ask the WebAssembly stub for a single value, which comes back as the hex-encoded bytes of the whole v...
size_t DoReadMemory(const ProcessAddress &vm_addr, void *buf, size_t size, Status &error) override
Actually do the reading of memory from a process.
ProcessWasm(lldb::TargetSP target_sp, lldb::ListenerSP listener_sp)
static llvm::StringRef GetPluginDescriptionStatic()
lldb::addr_t GetConcreteFramePC(uint32_t concrete_frame_idx)
Return the program counter the Wasm unwinder recorded for the given concrete frame index,...
#define LLDB_INVALID_ADDRESS
static constexpr uint32_t kWasmInvalidModuleID
A value that names no module.
uint32_t GetWasmModuleID(lldb::addr_t addr)
The module an address belongs to, or kWasmInvalidModuleID for an invalid address.
A class that represents a running process on the host machine.
@ eWasmTagNotAWasmLocation
std::shared_ptr< lldb_private::Thread > ThreadSP
std::shared_ptr< lldb_private::Process > ProcessSP
std::shared_ptr< lldb_private::Listener > ListenerSP
std::shared_ptr< lldb_private::WritableDataBuffer > WritableDataBufferSP
std::shared_ptr< lldb_private::Target > TargetSP
For the purpose of debugging, we can represent all these separated 32-bit address spaces with a singl...
uint32_t GetModuleID() const
uint32_t GetOffset() const
WasmAddressType GetType() const