-
Notifications
You must be signed in to change notification settings - Fork 14.7k
[lldb] Implement RegisterContextWasm #151056
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
@llvm/pr-subscribers-lldb Author: Jonas Devlieghere (JDevlieghere) ChangesThis PR implements a register context for Wasm, which uses virtual Patch is 97.48 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/151056.diff 32 Files Affected:
diff --git a/lldb/docs/resources/lldbgdbremote.md b/lldb/docs/resources/lldbgdbremote.md
index 80c68091ecd07..0b63d56d37acf 100644
--- a/lldb/docs/resources/lldbgdbremote.md
+++ b/lldb/docs/resources/lldbgdbremote.md
@@ -1998,6 +1998,61 @@ threads (live system debug) / cores (JTAG) in your program have
stopped and allows LLDB to display and control your program
correctly.
+## qWasmCallStack
+
+Get the Wasm call stack for the given thread id. This returns a hex-encoded
+list of PC values, one for each frame of the call stack. To match the Wasm
+specification, the addresses are encoded in little endian byte order, even if
+the endian of the Wasm runtime's host is not little endian.
+
+```
+send packet: $qWasmCallStack:202dbe040#08
+read packet: $9c01000000000040e501000000000040fe01000000000040#
+```
+
+**Priority to Implement:** Only required for Wasm support. This packed is
+supported by the [WAMR](https://github.com/bytecodealliance/wasm-micro-runtime)
+and [V8](https://v8.dev) Wasm runtimes.
+
+## qWasmGlobal
+
+Get the value of a Wasm global variable for the given frame index at the given
+variable index. This returns a hex-encoded value.
+
+send packet: qWasmGlobal:frame_index;index
+read packet: ...
+
+**Priority to Implement:** Only required for Wasm support. This packed is
+supported by the [WAMR](https://github.com/bytecodealliance/wasm-micro-runtime)
+and [V8](https://v8.dev) Wasm runtimes.
+
+
+## qWasmLocal
+
+Get the value of a Wasm function argument or local variable for the given frame
+index at the given variable index. This returns a hex-encoded value.
+
+send packet: qWasmGlobal:frame_index;index
+read packet: ...
+
+**Priority to Implement:** Only required for Wasm support. This packed is
+supported by the [WAMR](https://github.com/bytecodealliance/wasm-micro-runtime)
+and [V8](https://v8.dev) Wasm runtimes.
+
+
+## qWasmStackValue
+
+Get the value of a Wasm local variable from the Wasm operand stack, for the
+given frame index at the given variable index. This returns a hex-encoded
+value.
+
+send packet: qWasmStackValue:frame_index;index
+read packet: ...
+
+**Priority to Implement:** Only required for Wasm support. This packed is
+supported by the [WAMR](https://github.com/bytecodealliance/wasm-micro-runtime)
+and [V8](https://v8.dev) Wasm runtimes.
+
## qWatchpointSupportInfo
Get the number of hardware watchpoints available on the remote target.
diff --git a/lldb/include/lldb/Expression/DWARFExpression.h b/lldb/include/lldb/Expression/DWARFExpression.h
index 37853c0b5a8fc..8fcc5d37b91c9 100644
--- a/lldb/include/lldb/Expression/DWARFExpression.h
+++ b/lldb/include/lldb/Expression/DWARFExpression.h
@@ -52,10 +52,10 @@ class DWARFExpression {
GetVendorDWARFOpcodeSize(const DataExtractor &data,
const lldb::offset_t data_offset,
const uint8_t op) const = 0;
- virtual bool ParseVendorDWARFOpcode(uint8_t op,
- const DataExtractor &opcodes,
- lldb::offset_t &offset,
- Stack &stack) const = 0;
+ virtual bool
+ ParseVendorDWARFOpcode(uint8_t op, const DataExtractor &opcodes,
+ lldb::offset_t &offset, RegisterContext *reg_ctx,
+ lldb::RegisterKind reg_kind, Stack &stack) const = 0;
Delegate(const Delegate &) = delete;
Delegate &operator=(const Delegate &) = delete;
@@ -163,6 +163,10 @@ class DWARFExpression {
bool MatchesOperand(StackFrame &frame, const Instruction::Operand &op) const;
+ static llvm::Error ReadRegisterValueAsScalar(RegisterContext *reg_ctx,
+ lldb::RegisterKind reg_kind,
+ uint32_t reg_num, Value &value);
+
private:
/// A data extractor capable of reading opcode bytes
DataExtractor m_data;
diff --git a/lldb/packages/Python/lldbsuite/test/lldbgdbclient.py b/lldb/packages/Python/lldbsuite/test/lldbgdbclient.py
index 459460b84fbae..599f7878e6edb 100644
--- a/lldb/packages/Python/lldbsuite/test/lldbgdbclient.py
+++ b/lldb/packages/Python/lldbsuite/test/lldbgdbclient.py
@@ -45,7 +45,7 @@ def createTarget(self, yaml_path):
self.yaml2obj(yaml_path, obj_path)
return self.dbg.CreateTarget(obj_path)
- def connect(self, target):
+ def connect(self, target, plugin="gdb-remote"):
"""
Create a process by connecting to the mock GDB server.
@@ -54,7 +54,7 @@ def connect(self, target):
listener = self.dbg.GetListener()
error = lldb.SBError()
process = target.ConnectRemote(
- listener, self.server.get_connect_url(), "gdb-remote", error
+ listener, self.server.get_connect_url(), plugin, error
)
self.assertTrue(error.Success(), error.description)
self.assertTrue(process, PROCESS_IS_VALID)
diff --git a/lldb/source/Expression/DWARFExpression.cpp b/lldb/source/Expression/DWARFExpression.cpp
index 79bc6c87fa9c5..68093e9710a28 100644
--- a/lldb/source/Expression/DWARFExpression.cpp
+++ b/lldb/source/Expression/DWARFExpression.cpp
@@ -91,9 +91,10 @@ void DWARFExpression::SetRegisterKind(RegisterKind reg_kind) {
m_reg_kind = reg_kind;
}
-static llvm::Error ReadRegisterValueAsScalar(RegisterContext *reg_ctx,
- lldb::RegisterKind reg_kind,
- uint32_t reg_num, Value &value) {
+llvm::Error
+DWARFExpression::ReadRegisterValueAsScalar(RegisterContext *reg_ctx,
+ lldb::RegisterKind reg_kind,
+ uint32_t reg_num, Value &value) {
if (reg_ctx == nullptr)
return llvm::createStringError("no register context in frame");
@@ -2300,9 +2301,40 @@ llvm::Expected<Value> DWARFExpression::Evaluate(
break;
}
+ case DW_OP_WASM_location: {
+ uint8_t wasm_op = opcodes.GetU8(&offset);
+ uint32_t index;
+
+ /* LLDB doesn't have an address space to represents WebAssembly locals,
+ * globals and operand stacks.
+ * We encode these elements into virtual registers:
+ * | tag: 2 bits | index: 30 bits |
+ * where tag is:
+ * 0: Not a WebAssembly location
+ * 1: Local
+ * 2: Global
+ * 3: Operand stack value
+ */
+ if (wasm_op == 3) {
+ index = opcodes.GetU32(&offset);
+ wasm_op = 2; // Global
+ } else {
+ index = opcodes.GetULEB128(&offset);
+ }
+
+ reg_num = (((wasm_op + 1) & 0x03) << 30) | (index & 0x3fffffff);
+
+ if (llvm::Error error =
+ ReadRegisterValueAsScalar(reg_ctx, reg_kind, reg_num, tmp))
+ return std::move(error);
+ stack.push_back(tmp);
+ break;
+ }
+
default:
if (dwarf_cu) {
- if (dwarf_cu->ParseVendorDWARFOpcode(op, opcodes, offset, stack)) {
+ if (dwarf_cu->ParseVendorDWARFOpcode(op, opcodes, offset, reg_ctx,
+ reg_kind, stack)) {
break;
}
}
diff --git a/lldb/source/Plugins/ObjectFile/wasm/ObjectFileWasm.cpp b/lldb/source/Plugins/ObjectFile/wasm/ObjectFileWasm.cpp
index 67963a790a4fe..b1efd25949379 100644
--- a/lldb/source/Plugins/ObjectFile/wasm/ObjectFileWasm.cpp
+++ b/lldb/source/Plugins/ObjectFile/wasm/ObjectFileWasm.cpp
@@ -376,9 +376,13 @@ DataExtractor ObjectFileWasm::ReadImageData(offset_t offset, uint32_t size) {
DataBufferSP buffer_sp(data_up.release());
data.SetData(buffer_sp, 0, buffer_sp->GetByteSize());
}
+ } else if (offset < m_data.GetByteSize()) {
+ size =
+ std::min(static_cast<uint64_t>(size), m_data.GetByteSize() - offset);
+ return DataExtractor(m_data.GetDataStart() + offset, size, GetByteOrder(),
+ GetAddressByteSize());
}
}
-
data.SetByteOrder(GetByteOrder());
return data;
}
diff --git a/lldb/source/Plugins/Process/CMakeLists.txt b/lldb/source/Plugins/Process/CMakeLists.txt
index bd9b1b86dbf13..3413360e975fb 100644
--- a/lldb/source/Plugins/Process/CMakeLists.txt
+++ b/lldb/source/Plugins/Process/CMakeLists.txt
@@ -29,3 +29,4 @@ add_subdirectory(elf-core)
add_subdirectory(mach-core)
add_subdirectory(minidump)
add_subdirectory(FreeBSDKernel)
+add_subdirectory(wasm)
diff --git a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
index a2c34ddfc252e..14dfdec6a6f62 100644
--- a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
+++ b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
@@ -323,6 +323,11 @@ ProcessGDBRemote::~ProcessGDBRemote() {
KillDebugserverProcess();
}
+std::shared_ptr<ThreadGDBRemote>
+ProcessGDBRemote::CreateThread(lldb::tid_t tid) {
+ return std::make_shared<ThreadGDBRemote>(*this, tid);
+}
+
bool ProcessGDBRemote::ParsePythonTargetDefinition(
const FileSpec &target_definition_fspec) {
ScriptInterpreter *interpreter =
@@ -1594,7 +1599,7 @@ bool ProcessGDBRemote::DoUpdateThreadList(ThreadList &old_thread_list,
ThreadSP thread_sp(
old_thread_list_copy.RemoveThreadByProtocolID(tid, false));
if (!thread_sp) {
- thread_sp = std::make_shared<ThreadGDBRemote>(*this, tid);
+ thread_sp = CreateThread(tid);
LLDB_LOGV(log, "Making new thread: {0} for thread ID: {1:x}.",
thread_sp.get(), thread_sp->GetID());
} else {
@@ -1726,7 +1731,7 @@ ThreadSP ProcessGDBRemote::SetThreadStopInfo(
if (!thread_sp) {
// Create the thread if we need to
- thread_sp = std::make_shared<ThreadGDBRemote>(*this, tid);
+ thread_sp = CreateThread(tid);
m_thread_list_real.AddThread(thread_sp);
}
}
diff --git a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h
index 7ae33837fd067..7c3dfb179a4b3 100644
--- a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h
+++ b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h
@@ -246,6 +246,8 @@ class ProcessGDBRemote : public Process,
ProcessGDBRemote(lldb::TargetSP target_sp, lldb::ListenerSP listener_sp);
+ virtual std::shared_ptr<ThreadGDBRemote> CreateThread(lldb::tid_t tid);
+
bool SupportsMemoryTagging() override;
/// Broadcaster event bits definitions.
diff --git a/lldb/source/Plugins/Process/wasm/CMakeLists.txt b/lldb/source/Plugins/Process/wasm/CMakeLists.txt
new file mode 100644
index 0000000000000..779b97ec90d08
--- /dev/null
+++ b/lldb/source/Plugins/Process/wasm/CMakeLists.txt
@@ -0,0 +1,11 @@
+add_lldb_library(lldbPluginProcessWasm PLUGIN
+ ProcessWasm.cpp
+ RegisterContextWasm.cpp
+ ThreadWasm.cpp
+ UnwindWasm.cpp
+
+ LINK_LIBS
+ lldbCore
+ LINK_COMPONENTS
+ Support
+ )
diff --git a/lldb/source/Plugins/Process/wasm/ProcessWasm.cpp b/lldb/source/Plugins/Process/wasm/ProcessWasm.cpp
new file mode 100644
index 0000000000000..e244ab10f9faf
--- /dev/null
+++ b/lldb/source/Plugins/Process/wasm/ProcessWasm.cpp
@@ -0,0 +1,194 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+#include "ProcessWasm.h"
+#include "ThreadWasm.h"
+#include "lldb/Core/Module.h"
+#include "lldb/Core/PluginManager.h"
+#include "lldb/Core/Value.h"
+#include "lldb/Utility/DataBufferHeap.h"
+
+#include "lldb/Target/UnixSignals.h"
+
+using namespace lldb;
+using namespace lldb_private;
+using namespace lldb_private::process_gdb_remote;
+using namespace lldb_private::wasm;
+
+LLDB_PLUGIN_DEFINE(ProcessWasm)
+
+ProcessWasm::ProcessWasm(lldb::TargetSP target_sp, ListenerSP listener_sp)
+ : ProcessGDBRemote(target_sp, listener_sp) {
+ assert(target_sp);
+ // Wasm doesn't have any Unix-like signals as a platform concept, but pretend
+ // like it does to appease LLDB.
+ m_unix_signals_sp = UnixSignals::Create(target_sp->GetArchitecture());
+}
+
+void ProcessWasm::Initialize() {
+ static llvm::once_flag g_once_flag;
+
+ llvm::call_once(g_once_flag, []() {
+ PluginManager::RegisterPlugin(GetPluginNameStatic(),
+ GetPluginDescriptionStatic(), CreateInstance,
+ DebuggerInitialize);
+ });
+}
+
+void ProcessWasm::DebuggerInitialize(Debugger &debugger) {
+ ProcessGDBRemote::DebuggerInitialize(debugger);
+}
+
+llvm::StringRef ProcessWasm::GetPluginName() { return GetPluginNameStatic(); }
+
+llvm::StringRef ProcessWasm::GetPluginNameStatic() { return "wasm"; }
+
+llvm::StringRef ProcessWasm::GetPluginDescriptionStatic() {
+ return "GDB Remote protocol based WebAssembly debugging plug-in.";
+}
+
+void ProcessWasm::Terminate() {
+ PluginManager::UnregisterPlugin(ProcessWasm::CreateInstance);
+}
+
+lldb::ProcessSP ProcessWasm::CreateInstance(lldb::TargetSP target_sp,
+ ListenerSP listener_sp,
+ const FileSpec *crash_file_path,
+ bool can_connect) {
+ if (crash_file_path == nullptr)
+ return std::make_shared<ProcessWasm>(target_sp, listener_sp);
+ return {};
+}
+
+bool ProcessWasm::CanDebug(lldb::TargetSP target_sp,
+ bool plugin_specified_by_name) {
+ if (plugin_specified_by_name)
+ return true;
+
+ if (Module *exe_module = target_sp->GetExecutableModulePointer()) {
+ if (ObjectFile *exe_objfile = exe_module->GetObjectFile())
+ return exe_objfile->GetArchitecture().GetMachine() ==
+ llvm::Triple::wasm32;
+ }
+
+ // However, if there is no wasm module, we return false, otherwise,
+ // we might use ProcessWasm to attach gdb remote.
+ return false;
+}
+
+std::shared_ptr<ThreadGDBRemote> ProcessWasm::CreateThread(lldb::tid_t tid) {
+ return std::make_shared<ThreadWasm>(*this, tid);
+}
+
+size_t ProcessWasm::ReadMemory(lldb::addr_t vm_addr, void *buf, size_t size,
+ Status &error) {
+ wasm_addr_t wasm_addr(vm_addr);
+
+ switch (wasm_addr.GetType()) {
+ case WasmAddressType::Memory:
+ case WasmAddressType::Object:
+ return ProcessGDBRemote::ReadMemory(vm_addr, buf, size, error);
+ case WasmAddressType::Invalid:
+ error.FromErrorStringWithFormat(
+ "Wasm read failed for invalid address 0x%" PRIx64, vm_addr);
+ return 0;
+ }
+}
+
+llvm::Expected<std::vector<lldb::addr_t>>
+ProcessWasm::GetWasmCallStack(lldb::tid_t tid) {
+ StreamString packet;
+ packet.Printf("qWasmCallStack:");
+ packet.Printf("%llx", tid);
+
+ StringExtractorGDBRemote response;
+ if (m_gdb_comm.SendPacketAndWaitForResponse(packet.GetString(), response) !=
+ GDBRemoteCommunication::PacketResult::Success)
+ return llvm::createStringError("failed to send qWasmCallStack");
+
+ if (!response.IsNormalResponse())
+ return llvm::createStringError("failed to get response for qWasmCallStack");
+
+ WritableDataBufferSP data_buffer_sp =
+ std::make_shared<DataBufferHeap>(response.GetStringRef().size() / 2, 0);
+ const size_t bytes = response.GetHexBytes(data_buffer_sp->GetData(), '\xcc');
+ if (bytes == 0 || bytes % sizeof(uint64_t) != 0)
+ return llvm::createStringError("invalid response for qWasmCallStack");
+
+ // To match the Wasm specification, the addresses are encoded in little endian
+ // byte order.
+ DataExtractor data(data_buffer_sp, lldb::eByteOrderLittle,
+ GetAddressByteSize());
+ lldb::offset_t offset = 0;
+ std::vector<lldb::addr_t> call_stack_pcs;
+ while (offset < bytes)
+ call_stack_pcs.push_back(data.GetU64(&offset));
+
+ return call_stack_pcs;
+}
+
+llvm::Expected<lldb::DataBufferSP> ProcessWasm::GetWasmLocal(int frame_index,
+ int index) {
+ StreamString packet;
+ packet.Printf("qWasmLocal:");
+ packet.Printf("%d;%d", frame_index, index);
+
+ StringExtractorGDBRemote response;
+ if (m_gdb_comm.SendPacketAndWaitForResponse(packet.GetString(), response) !=
+ GDBRemoteCommunication::PacketResult::Success)
+ return llvm::createStringError("failed to send qWasmLocal");
+
+ if (!response.IsNormalResponse())
+ return llvm::createStringError("failed to get response for qWasmLocal");
+
+ WritableDataBufferSP buffer_sp(
+ new DataBufferHeap(response.GetStringRef().size() / 2, 0));
+ response.GetHexBytes(buffer_sp->GetData(), '\xcc');
+ return buffer_sp;
+}
+
+llvm::Expected<lldb::DataBufferSP> ProcessWasm::GetWasmGlobal(int frame_index,
+ int index) {
+ StreamString packet;
+ packet.PutCString("qWasmGlobal:");
+ packet.Printf("%d;%d", frame_index, index);
+
+ StringExtractorGDBRemote response;
+ if (m_gdb_comm.SendPacketAndWaitForResponse(packet.GetString(), response) !=
+ GDBRemoteCommunication::PacketResult::Success)
+ return llvm::createStringError("failed to send qWasmGlobal");
+
+ if (!response.IsNormalResponse())
+ return llvm::createStringError("failed to get response for qWasmGlobal");
+
+ WritableDataBufferSP buffer_sp(
+ new DataBufferHeap(response.GetStringRef().size() / 2, 0));
+ response.GetHexBytes(buffer_sp->GetData(), '\xcc');
+ return buffer_sp;
+}
+
+llvm::Expected<lldb::DataBufferSP>
+ProcessWasm::GetWasmStackValue(int frame_index, int index) {
+ StreamString packet;
+ packet.PutCString("qWasmStackValue:");
+ packet.Printf("%d;%d", frame_index, index);
+
+ StringExtractorGDBRemote response;
+ if (m_gdb_comm.SendPacketAndWaitForResponse(packet.GetString(), response) !=
+ GDBRemoteCommunication::PacketResult::Success)
+ return llvm::createStringError("failed to send qWasmStackValue");
+
+ if (!response.IsNormalResponse())
+ return llvm::createStringError(
+ "failed to get response for qWasmStackValue");
+
+ WritableDataBufferSP buffer_sp(
+ new DataBufferHeap(response.GetStringRef().size() / 2, 0));
+ response.GetHexBytes(buffer_sp->GetData(), '\xcc');
+ return buffer_sp;
+}
diff --git a/lldb/source/Plugins/Process/wasm/ProcessWasm.h b/lldb/source/Plugins/Process/wasm/ProcessWasm.h
new file mode 100644
index 0000000000000..81682eac27997
--- /dev/null
+++ b/lldb/source/Plugins/Process/wasm/ProcessWasm.h
@@ -0,0 +1,106 @@
+//===----------------------------------------------------------------------===//
+//
+// 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/Process/gdb-remote/ProcessGDBRemote.h"
+
+namespace lldb_private {
+namespace wasm {
+
+/// Each WebAssembly module has separated address spaces for Code and Memory.
+/// A WebAssembly module also has a Data section which, when the module is
+/// loaded, gets mapped into a region in the module Memory.
+enum WasmAddressType : uint8_t { Memory = 0x00, Object = 0x01, Invalid = 0xff };
+
+/// For the purpose of debugging, we can represent all these separated 32-bit
+/// address spaces with a single virtual 64-bit address space. The
+/// wasm_addr_t provides this encoding using bitfields.
+struct wasm_addr_t {
+ uint64_t offset : 32;
+ uint64_t module_id : 30;
+ uint64_t type : 2;
+
+ wasm_addr_t(lldb::addr_t addr)
+ : offset(addr & 0x00000000ffffffff),
+ module_id((addr & 0x00ffffff00000000) >> 32), type(addr >> 62) {}
+
+ wasm_addr_t(WasmAddressType type, uint32_t module_id, uint32_t offset)
+ : offset(offset), module_id(module_id), type(type) {}
+
+ WasmAddressType GetType() { return static_cast<WasmAddressType>(type); }
+
+ operator lldb::addr_t() { return *(uint64_t *)this; }
+};
+
+static_assert(sizeof(wasm_addr_t) == 8, "");
+
+/// ProcessWasm provides the access to the Wasm program state
+/// retrieved from the Wasm engine.
+c...
[truncated]
|
ProcessWasm::GetWasmStackValue(int frame_index, int index) { | ||
StreamString packet; | ||
packet.PutCString("qWasmStackValue:"); | ||
packet.Printf("%d;%d", frame_index, index); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Are these fields sent in base10 or base16? I wasn't clear from the packet description in the doc. same thing for qWasmGlobal
and qWasmLocal
. (I'd expect to see a base16 without a 0x prefix in a gdb-remote packet for a field like this)
(I've tried to sneak some 0x's in to gdb-remote packets but Pavel always notices and slaps my hand. it's easy to not see the base when you're testing with small numbers.)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Second this.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This impl https://github.com/bytecodealliance/wasm-micro-runtime/blob/23799a2cb6778896e5e7797d17bc826e1afdbf6e/core/iwasm/libraries/debug-engine/handler.c#L165
seems to be expecting base10. quite unusual for the gdb remote serial protocol, but what you gonna do, if that's the choice they made.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think our doc is now clear on this topic.
Feels like they encoded it based on how easy it was to read each bit. Indexes are usually numbers and addresses are better in hex? It is what it is anyway.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks to be a stacked PR, so I just looked at the last commit.
As I understand it, we internally are adding virtual registers, because that's the metaphor lldb is used to. For users, Correct? Because I think if we're going to show what are conceptually variables as registers, that's worth a discussion, but I think this is not what you are doing here. This is just an internal convenience. |
Because we report zero registers, we don't show any registers when you do |
9148f6b
to
fed4d8b
Compare
That's fine then. The pedant line here is that if Wasm calls it literally a register in the spec, then it should show up in register read. But I have not checked and if no one notices it's missing then no point changing it. It's not like people outside of us manually write the PC that often anyway. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
supprot -> support, in the PR description.
LGTM.
This PR implements a register context for Wasm, which uses virtual registers to resolve Wasm local, globals and stack values. The registers are used to implement supprot for `DW_OP_WASM_location` in the DWARF expression evaluator (llvm#151010). This also adds a more comprehensive test, showing that we can use this to show local variables.
b35b16b
to
1c70fa8
Compare
This PR implements a register context for Wasm, which uses virtual registers to resolve Wasm local, globals and stack values. The registers are used to implement support for `DW_OP_WASM_location` in the DWARF expression evaluator (llvm#151010). This also adds a more comprehensive test, showing that we can use this to show local variables. (cherry picked from commit f623702)
This PR implements a register context for Wasm, which uses virtual registers to resolve Wasm local, globals and stack values. The registers are used to implement support for `DW_OP_WASM_location` in the DWARF expression evaluator (llvm#151010). This also adds a more comprehensive test, showing that we can use this to show local variables.
This PR implements a register context for Wasm, which uses virtual
registers to resolve Wasm local, globals and stack values. The registers
are used to implement support for
DW_OP_WASM_location
in the DWARFexpression evaluator (#151010). This also adds a more comprehensive
test, showing that we can use this to show local variables.