16#include "llvm/Support/ErrorExtras.h"
54 return "GDB Remote protocol based WebAssembly debugging plug-in.";
65 if (crash_file_path ==
nullptr)
66 return std::make_shared<ProcessWasm>(target_sp, listener_sp);
71 bool plugin_specified_by_name) {
72 if (plugin_specified_by_name)
75 if (
Module *exe_module = target_sp->GetExecutableModulePointer()) {
76 if (
ObjectFile *exe_objfile = exe_module->GetObjectFile())
77 return exe_objfile->GetArchitecture().GetTriple().isWasm();
86 if (!
GetTarget().GetArchitecture().GetTriple().isWasm())
89 return std::make_shared<ThreadWasm>(*
this, tid);
92static size_t CopyGlobal(llvm::Expected<lldb::DataBufferSP> global,
void *buf,
101 const size_t global_size = (*global)->GetByteSize();
102 if (size > global_size) {
104 "Wasm global read failed: requested {0} bytes from a {1}-byte global",
109 std::memcpy(buf, (*global)->GetBytes(), size);
131llvm::Expected<uint32_t>
134 return llvm::createStringError(
135 "the global belongs to no known module instance");
142 const uint32_t frame_index = frame->GetConcreteFrameIndex();
149 return llvm::createStringErrorV(
150 "the Wasm stub can only read a global through a frame, and no frame is "
151 "executing module {0:x}",
176 "Wasm read failed for invalid address {0:x} (type = {1:x}, module = "
177 "{2:x}, offset = {3:x})",
183llvm::Expected<std::vector<lldb::addr_t>>
186 packet.
Printf(
"qWasmCallStack:");
187 packet.
Printf(
"%" PRIx64, tid);
192 return llvm::createStringError(
"failed to send qWasmCallStack");
195 return llvm::createStringError(
"failed to get response for qWasmCallStack");
198 std::make_shared<DataBufferHeap>(response.
GetStringRef().size() / 2, 0);
199 const size_t bytes = response.
GetHexBytes(data_buffer_sp->GetData(),
'\xcc');
200 if (bytes == 0 || bytes %
sizeof(uint64_t) != 0)
201 return llvm::createStringError(
"invalid response for qWasmCallStack");
208 std::vector<lldb::addr_t> call_stack_pcs;
209 while (offset < bytes)
210 call_stack_pcs.push_back(data.
GetU64(&offset));
212 return call_stack_pcs;
215llvm::Expected<lldb::DataBufferSP>
218 if (
m_gdb_comm.SendPacketAndWaitForResponse(packet, response) !=
220 return llvm::createStringErrorV(
"failed to send {0}", packet);
223 return llvm::createStringErrorV(
"failed to get response for {0}", packet);
227 response.
GetHexBytes(buffer_sp->GetData(),
'\xcc');
231llvm::Expected<lldb::DataBufferSP>
233 uint32_t frame_index, uint32_t index) {
237 llvm::formatv(
"qWasmLocal:{0};{1}", frame_index, index).str());
240 llvm::formatv(
"qWasmStackValue:{0};{1}", frame_index, index).str());
242 return llvm::createStringError(
"a Wasm global does not belong to a frame");
244 return llvm::createStringError(
"not a Wasm location");
246 llvm_unreachable(
"unhandled Wasm virtual register kind");
249llvm::Expected<lldb::DataBufferSP>
252 llvm::formatv(
"qWasmGlobal:{0};instance:{1};", index, module_id).str());
255llvm::Expected<lldb::DataBufferSP>
258 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
ThreadList & GetThreadList()
virtual size_t ReadMemory(const ProcessAddress &process_addr, void *buf, size_t size, Status &error)
Read of memory from a process.
void SetCanJIT(bool can_jit)
Sets whether executing JIT-compiled code in this process is possible.
lldb::UnixSignalsSP m_unix_signals_sp
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.
lldb::ThreadSP GetSelectedThread()
static lldb::UnixSignalsSP Create(const ArchSpec &arch)
virtual std::shared_ptr< ThreadGDBRemote > CreateThread(lldb::tid_t tid)
GDBRemoteCommunicationClient m_gdb_comm
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...
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)
size_t ReadMemory(const ProcessAddress &vm_addr, void *buf, size_t size, Status &error) override
Read of memory from a process.
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...
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,...
@ DoNoSelectMostRelevantFrame
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::StackFrame > StackFrameSP
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