-
Notifications
You must be signed in to change notification settings - Fork 14.8k
[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
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -131,3 +131,36 @@ ProcessWasm::GetWasmCallStack(lldb::tid_t tid) { | |
|
||
return call_stack_pcs; | ||
} | ||
|
||
llvm::Expected<lldb::DataBufferSP> | ||
ProcessWasm::GetWasmVariable(WasmVirtualRegisterKinds kind, int frame_index, | ||
int index) { | ||
StreamString packet; | ||
switch (kind) { | ||
case eWasmTagLocal: | ||
packet.Printf("qWasmLocal:"); | ||
break; | ||
case eWasmTagGlobal: | ||
packet.Printf("qWasmGlobal:"); | ||
break; | ||
case eWasmTagOperandStack: | ||
packet.PutCString("qWasmStackValue:"); | ||
break; | ||
case eWasmTagNotAWasmLocation: | ||
return llvm::createStringError("not a Wasm location"); | ||
} | ||
packet.Printf("%d;%d", frame_index, index); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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 There was a problem hiding this comment. Choose a reason for hiding this commentThe 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 commentThe 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 There was a problem hiding this comment. Choose a reason for hiding this commentThe 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. |
||
|
||
StringExtractorGDBRemote response; | ||
if (m_gdb_comm.SendPacketAndWaitForResponse(packet.GetString(), response) != | ||
GDBRemoteCommunication::PacketResult::Success) | ||
return llvm::createStringError("failed to send Wasm variable"); | ||
|
||
if (!response.IsNormalResponse()) | ||
return llvm::createStringError("failed to get response for Wasm variable"); | ||
|
||
WritableDataBufferSP buffer_sp( | ||
new DataBufferHeap(response.GetStringRef().size() / 2, 0)); | ||
response.GetHexBytes(buffer_sp->GetData(), '\xcc'); | ||
return buffer_sp; | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,109 @@ | ||
//===----------------------------------------------------------------------===// | ||
// | ||
// 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 "RegisterContextWasm.h" | ||
#include "Plugins/Process/gdb-remote/GDBRemoteRegisterContext.h" | ||
#include "ProcessWasm.h" | ||
#include "ThreadWasm.h" | ||
#include "lldb/Utility/LLDBLog.h" | ||
#include "lldb/Utility/Log.h" | ||
#include "lldb/Utility/RegisterValue.h" | ||
#include "llvm/Support/Error.h" | ||
#include <memory> | ||
|
||
using namespace lldb; | ||
using namespace lldb_private; | ||
using namespace lldb_private::process_gdb_remote; | ||
using namespace lldb_private::wasm; | ||
|
||
RegisterContextWasm::RegisterContextWasm( | ||
wasm::ThreadWasm &thread, uint32_t concrete_frame_idx, | ||
GDBRemoteDynamicRegisterInfoSP reg_info_sp) | ||
: GDBRemoteRegisterContext(thread, concrete_frame_idx, reg_info_sp, false, | ||
false) {} | ||
|
||
RegisterContextWasm::~RegisterContextWasm() = default; | ||
|
||
uint32_t RegisterContextWasm::ConvertRegisterKindToRegisterNumber( | ||
lldb::RegisterKind kind, uint32_t num) { | ||
return num; | ||
} | ||
|
||
size_t RegisterContextWasm::GetRegisterCount() { | ||
// Wasm has no registers. | ||
return 0; | ||
} | ||
|
||
const RegisterInfo *RegisterContextWasm::GetRegisterInfoAtIndex(size_t reg) { | ||
uint32_t tag = GetWasmVirtualRegisterTag(reg); | ||
if (tag == eWasmTagNotAWasmLocation) | ||
return m_reg_info_sp->GetRegisterInfoAtIndex( | ||
GetWasmVirtualRegisterIndex(reg)); | ||
|
||
auto it = m_register_map.find(reg); | ||
if (it == m_register_map.end()) { | ||
WasmVirtualRegisterKinds kind = static_cast<WasmVirtualRegisterKinds>(tag); | ||
std::tie(it, std::ignore) = m_register_map.insert( | ||
{reg, std::make_unique<WasmVirtualRegisterInfo>( | ||
kind, GetWasmVirtualRegisterIndex(reg))}); | ||
} | ||
return it->second.get(); | ||
} | ||
|
||
size_t RegisterContextWasm::GetRegisterSetCount() { return 0; } | ||
|
||
const RegisterSet *RegisterContextWasm::GetRegisterSet(size_t reg_set) { | ||
// Wasm has no registers. | ||
return nullptr; | ||
} | ||
|
||
bool RegisterContextWasm::ReadRegister(const RegisterInfo *reg_info, | ||
RegisterValue &value) { | ||
// The only real registers is the PC. | ||
if (reg_info->name) | ||
return GDBRemoteRegisterContext::ReadRegister(reg_info, value); | ||
DavidSpickett marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
// Read the virtual registers. | ||
ThreadWasm *thread = static_cast<ThreadWasm *>(&GetThread()); | ||
ProcessWasm *process = static_cast<ProcessWasm *>(thread->GetProcess().get()); | ||
if (!thread) | ||
return false; | ||
|
||
uint32_t frame_index = m_concrete_frame_idx; | ||
WasmVirtualRegisterInfo *wasm_reg_info = | ||
static_cast<WasmVirtualRegisterInfo *>( | ||
const_cast<RegisterInfo *>(reg_info)); | ||
|
||
llvm::Expected<DataBufferSP> maybe_buffer = process->GetWasmVariable( | ||
wasm_reg_info->kind, frame_index, wasm_reg_info->index); | ||
if (!maybe_buffer) { | ||
LLDB_LOG_ERROR(GetLog(LLDBLog::Process), maybe_buffer.takeError(), | ||
"Failed to read Wasm local: {0}"); | ||
return false; | ||
} | ||
|
||
DataBufferSP buffer_sp = *maybe_buffer; | ||
DataExtractor reg_data(buffer_sp, process->GetByteOrder(), | ||
process->GetAddressByteSize()); | ||
wasm_reg_info->byte_size = buffer_sp->GetByteSize(); | ||
wasm_reg_info->encoding = lldb::eEncodingUint; | ||
|
||
Status error = value.SetValueFromData( | ||
*reg_info, reg_data, reg_info->byte_offset, /*partial_data_ok=*/false); | ||
return error.Success(); | ||
} | ||
|
||
void RegisterContextWasm::InvalidateAllRegisters() {} | ||
|
||
bool RegisterContextWasm::WriteRegister(const RegisterInfo *reg_info, | ||
const RegisterValue &value) { | ||
// The only real registers is the PC. | ||
if (reg_info->name) | ||
return GDBRemoteRegisterContext::WriteRegister(reg_info, value); | ||
return false; | ||
DavidSpickett marked this conversation as resolved.
Show resolved
Hide resolved
|
||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,69 @@ | ||
//===----------------------------------------------------------------------===// | ||
// | ||
// 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_REGISTERCONTEXTWASM_H | ||
#define LLDB_SOURCE_PLUGINS_PROCESS_WASM_REGISTERCONTEXTWASM_H | ||
|
||
#include "Plugins/Process/gdb-remote/GDBRemoteRegisterContext.h" | ||
#include "ThreadWasm.h" | ||
#include "Utility/WasmVirtualRegisters.h" | ||
#include "lldb/lldb-private-types.h" | ||
#include <unordered_map> | ||
|
||
namespace lldb_private { | ||
namespace wasm { | ||
|
||
class RegisterContextWasm; | ||
|
||
typedef std::shared_ptr<RegisterContextWasm> RegisterContextWasmSP; | ||
|
||
struct WasmVirtualRegisterInfo : public RegisterInfo { | ||
WasmVirtualRegisterKinds kind; | ||
uint32_t index; | ||
|
||
WasmVirtualRegisterInfo(WasmVirtualRegisterKinds kind, uint32_t index) | ||
: RegisterInfo(), kind(kind), index(index) {} | ||
}; | ||
|
||
class RegisterContextWasm | ||
: public process_gdb_remote::GDBRemoteRegisterContext { | ||
public: | ||
RegisterContextWasm( | ||
wasm::ThreadWasm &thread, uint32_t concrete_frame_idx, | ||
process_gdb_remote::GDBRemoteDynamicRegisterInfoSP reg_info_sp); | ||
|
||
~RegisterContextWasm() override; | ||
|
||
uint32_t ConvertRegisterKindToRegisterNumber(lldb::RegisterKind kind, | ||
uint32_t num) override; | ||
|
||
void InvalidateAllRegisters() override; | ||
|
||
size_t GetRegisterCount() override; | ||
|
||
const RegisterInfo *GetRegisterInfoAtIndex(size_t reg) override; | ||
|
||
size_t GetRegisterSetCount() override; | ||
|
||
const RegisterSet *GetRegisterSet(size_t reg_set) override; | ||
|
||
bool ReadRegister(const RegisterInfo *reg_info, | ||
RegisterValue &value) override; | ||
|
||
bool WriteRegister(const RegisterInfo *reg_info, | ||
const RegisterValue &value) override; | ||
|
||
private: | ||
std::unordered_map<size_t, std::unique_ptr<WasmVirtualRegisterInfo>> | ||
m_register_map; | ||
}; | ||
|
||
} // namespace wasm | ||
} // namespace lldb_private | ||
|
||
#endif |
Uh oh!
There was an error while loading. Please reload this page.