//===----------------------------------------------------------------------===// // // 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 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(tag); std::tie(it, std::ignore) = m_register_map.insert( {reg, std::make_unique( 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); // Read the virtual registers. ThreadWasm *thread = static_cast(&GetThread()); ProcessWasm *process = static_cast(thread->GetProcess().get()); if (!thread) return false; uint32_t frame_index = m_concrete_frame_idx; WasmVirtualRegisterInfo *wasm_reg_info = static_cast( const_cast(reg_info)); llvm::Expected 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; }