LLDB mainline
RegisterContextWasm.cpp
Go to the documentation of this file.
1//===----------------------------------------------------------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
11#include "ProcessWasm.h"
12#include "ThreadWasm.h"
14#include "lldb/Utility/Log.h"
16#include "llvm/Support/Error.h"
17#include <memory>
18
19using namespace lldb;
20using namespace lldb_private;
22using namespace lldb_private::wasm;
23
25 uint32_t concrete_frame_idx,
26 DynamicRegisterInfoSP reg_info_sp)
27 : GDBRemoteRegisterContext(thread, concrete_frame_idx, reg_info_sp, false,
28 false) {}
29
31
35
37 lldb::RegisterKind kind, uint32_t num) {
38 return num;
39}
40
42 // Wasm has no registers.
43 return 0;
44}
45
47 uint32_t tag = GetWasmVirtualRegisterTag(reg);
48 if (tag == eWasmTagNotAWasmLocation)
49 return m_reg_info_sp->GetRegisterInfoAtIndex(
51
52 auto it = m_register_map.find(reg);
53 if (it == m_register_map.end()) {
55 std::tie(it, std::ignore) = m_register_map.insert(
56 {reg, std::make_unique<WasmVirtualRegisterInfo>(
57 kind, GetWasmVirtualRegisterIndex(reg))});
58 }
59 return it->second.get();
60}
61
63
65 // Wasm has no registers.
66 return nullptr;
67}
68
69/// A local and an operand stack value belong to the frame, while a global
70/// belongs to the module instance the frame is executing, which is named
71/// directly wherever the stub accepts one.
72static llvm::Expected<DataBufferSP>
74 uint32_t frame_index, uint32_t module_id) {
75 if (reg_info.kind != eWasmTagGlobal)
76 return process.GetWasmVariable(reg_info.kind, frame_index, reg_info.index);
77
78 if (process.CanNameInstance(module_id))
79 return process.GetWasmGlobalForModule(module_id, reg_info.index);
80
81 return process.GetWasmGlobalForFrame(frame_index, reg_info.index);
82}
83
85 RegisterValue &value) {
86 ThreadWasm &wasm_thread = static_cast<ThreadWasm &>(GetThread());
87
88 // The only real register is the PC.
89 if (reg_info->name) {
90 // A caller frame's PC is the unwound return address, which the base
91 // register context cannot provide because it only sees the innermost
92 // frame's live PC. Use the PC the unwinder recorded for this frame.
93 if (m_concrete_frame_idx > 0) {
95 if (pc != LLDB_INVALID_ADDRESS) {
96 value.SetUInt(pc, reg_info->byte_size);
97 return true;
98 }
99 }
100 return GDBRemoteRegisterContext::ReadRegister(reg_info, value);
101 }
102
103 // Read the virtual registers.
104 ProcessWasm *process =
105 static_cast<ProcessWasm *>(wasm_thread.GetProcess().get());
106 if (!process)
107 return false;
108
109 uint32_t frame_index = m_concrete_frame_idx;
110 WasmVirtualRegisterInfo *wasm_reg_info =
111 static_cast<WasmVirtualRegisterInfo *>(
112 const_cast<RegisterInfo *>(reg_info));
113
114 llvm::Expected<DataBufferSP> maybe_buffer =
115 ReadWasmValue(*process, *wasm_reg_info, frame_index, GetModuleID());
116 if (!maybe_buffer) {
117 LLDB_LOG_ERROR(GetLog(LLDBLog::Process), maybe_buffer.takeError(),
118 "Failed to read Wasm value: {0}");
119 return false;
120 }
121
122 DataBufferSP buffer_sp = *maybe_buffer;
123 DataExtractor reg_data(buffer_sp, process->GetByteOrder(),
124 process->GetAddressByteSize());
125 wasm_reg_info->byte_size = buffer_sp->GetByteSize();
126 wasm_reg_info->encoding = lldb::eEncodingUint;
127
129 *reg_info, reg_data, reg_info->byte_offset, /*partial_data_ok=*/false);
130 return error.Success();
131}
132
134
136 const RegisterValue &value) {
137 // The only real registers is the PC.
138 if (reg_info->name)
139 return GDBRemoteRegisterContext::WriteRegister(reg_info, value);
140 return false;
141}
static llvm::raw_ostream & error(Stream &strm)
#define LLDB_LOG_ERROR(log, error,...)
Definition Log.h:405
static llvm::Expected< DataBufferSP > ReadWasmValue(ProcessWasm &process, const WasmVirtualRegisterInfo &reg_info, uint32_t frame_index, uint32_t module_id)
A local and an operand stack value belong to the frame, while a global belongs to the module instance...
An data extractor class.
lldb::ByteOrder GetByteOrder() const
Definition Process.cpp:3928
uint32_t GetAddressByteSize() const
Definition Process.cpp:3932
uint64_t GetPC(uint64_t fail_value=LLDB_INVALID_ADDRESS)
bool SetUInt(uint64_t uint, uint32_t byte_size)
Status SetValueFromData(const RegisterInfo &reg_info, DataExtractor &data, lldb::offset_t offset, bool partial_data_ok)
An error handling class.
Definition Status.h:118
lldb::ProcessSP GetProcess() const
Definition Thread.h:162
bool ReadRegister(const RegisterInfo *reg_info, RegisterValue &value) override
bool WriteRegister(const RegisterInfo *reg_info, const RegisterValue &value) override
GDBRemoteRegisterContext(ThreadGDBRemote &thread, uint32_t concrete_frame_idx, lldb::DynamicRegisterInfoSP reg_info_sp, bool read_all_at_once, bool write_all_at_once)
ProcessWasm provides the access to the Wasm program state retrieved from the Wasm engine.
Definition ProcessWasm.h:21
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::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...
const RegisterInfo * GetRegisterInfoAtIndex(size_t reg) override
const RegisterSet * GetRegisterSet(size_t reg_set) override
bool WriteRegister(const RegisterInfo *reg_info, const RegisterValue &value) override
RegisterContextWasm(process_gdb_remote::ThreadGDBRemote &thread, uint32_t concrete_frame_idx, lldb::DynamicRegisterInfoSP reg_info_sp)
uint32_t GetModuleID()
The module whose code this context's frame is executing.
uint32_t ConvertRegisterKindToRegisterNumber(lldb::RegisterKind kind, uint32_t num) override
Convert from a given register numbering scheme to the lldb register numbering scheme.
bool ReadRegister(const RegisterInfo *reg_info, RegisterValue &value) override
std::unordered_map< size_t, std::unique_ptr< WasmVirtualRegisterInfo > > m_register_map
ProcessWasm provides the access to the Wasm program state retrieved from the Wasm engine.
Definition ThreadWasm.h:19
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
uint32_t GetWasmModuleID(lldb::addr_t addr)
The module an address belongs to, or kWasmInvalidModuleID for an invalid address.
Definition WasmAddress.h:94
A class that represents a running process on the host machine.
Log * GetLog(Cat mask)
Retrieve the Log object for the channel associated with the given log enum.
Definition Log.h:338
uint32_t GetWasmVirtualRegisterTag(size_t reg)
uint32_t GetWasmVirtualRegisterIndex(size_t reg)
std::shared_ptr< lldb_private::DynamicRegisterInfo > DynamicRegisterInfoSP
@ eEncodingUint
unsigned integer
std::shared_ptr< lldb_private::DataBuffer > DataBufferSP
uint64_t addr_t
Definition lldb-types.h:80
RegisterKind
Register numbering types.
Every register is described in detail including its name, alternate name (optional),...
lldb::Encoding encoding
Encoding of the register bits.
uint32_t byte_offset
The byte offset in the register context data where this register's value is found.
uint32_t byte_size
Size in bytes of the register.
const char * name
Name of this register, can't be NULL.
Registers are grouped into register sets.