blob: d44c1fc6defd094df1f9ba25a7397f696d3727ab [file]
//===----------------------------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
#ifndef LLDB_SOURCE_PLUGINS_PROCESS_WASM_PROCESSWASM_H
#define LLDB_SOURCE_PLUGINS_PROCESS_WASM_PROCESSWASM_H
#include "Plugins/ObjectFile/wasm/WasmAddress.h"
#include "Plugins/Process/gdb-remote/ProcessGDBRemote.h"
#include "Utility/WasmVirtualRegisters.h"
namespace lldb_private {
namespace wasm {
/// ProcessWasm provides the access to the Wasm program state
/// retrieved from the Wasm engine.
class ProcessWasm : public process_gdb_remote::ProcessGDBRemote {
public:
ProcessWasm(lldb::TargetSP target_sp, lldb::ListenerSP listener_sp);
~ProcessWasm() override = default;
static lldb::ProcessSP CreateInstance(lldb::TargetSP target_sp,
lldb::ListenerSP listener_sp,
const FileSpec *crash_file_path,
bool can_connect);
static void Initialize();
static void DebuggerInitialize(Debugger &debugger);
static void Terminate();
static llvm::StringRef GetPluginNameStatic() { return "wasm"; }
static llvm::StringRef GetPluginDescriptionStatic();
llvm::StringRef GetPluginName() override;
size_t ReadMemory(const ProcessAddress &vm_addr, void *buf, size_t size,
Status &error) override;
bool CanDebug(lldb::TargetSP target_sp,
bool plugin_specified_by_name) override;
/// Retrieve the current call stack from the WebAssembly remote process.
llvm::Expected<std::vector<lldb::addr_t>> GetWasmCallStack(lldb::tid_t tid);
/// Query the value of a frame-scoped WebAssembly variable, which is a local
/// or a value on the operand stack.
llvm::Expected<lldb::DataBufferSP>
GetWasmVariable(WasmVirtualRegisterKinds kind, uint32_t frame_index,
uint32_t index);
/// Query the value of the global at \a index in the global index space of the
/// module instance \a module_id names. An index only names a global together
/// with an instance. Only a stub that advertises "qWasmInstance+" can be told
/// which instance to read, so see CanNameInstance first.
llvm::Expected<lldb::DataBufferSP> GetWasmGlobalForModule(uint32_t module_id,
uint32_t index);
/// Query the value of a WebAssembly global through the frame at \a
/// frame_index, which reaches only the globals of the module instance that
/// frame is executing. This is the only scope a stub that cannot be told
/// which instance to read offers.
llvm::Expected<lldb::DataBufferSP> GetWasmGlobalForFrame(uint32_t frame_index,
uint32_t index);
/// Whether the instance holding a global can be named to the stub, which
/// needs both a valid id to name it by and a stub that accepts one. Where it
/// cannot, a frame executing that instance has to stand in for it.
bool CanNameInstance(uint32_t module_id);
protected:
std::shared_ptr<process_gdb_remote::ThreadGDBRemote>
CreateThread(lldb::tid_t tid) override;
private:
friend class UnwindWasm;
friend class ThreadWasm;
/// Ask the WebAssembly stub for a single value, which comes back as the
/// hex-encoded bytes of the whole value.
llvm::Expected<lldb::DataBufferSP> SendWasmValueQuery(llvm::StringRef packet);
/// Read a WebAssembly global of the module instance \a module_id names,
/// through whichever scope that stub can be asked for it in.
size_t ReadGlobal(uint32_t module_id, uint32_t index, void *buf, size_t size,
Status &error);
/// The frame to read a global of \a module_id through, for a stub that cannot
/// be told which instance to read. Fails when no frame is executing that
/// module, which leaves its globals out of reach.
llvm::Expected<uint32_t> GetFallbackFrameIndex(uint32_t module_id);
lldb::DynamicRegisterInfoSP &GetRegisterInfo() { return m_register_info_sp; }
ProcessWasm(const ProcessWasm &);
const ProcessWasm &operator=(const ProcessWasm &) = delete;
};
} // namespace wasm
} // namespace lldb_private
#endif