================ @@ -0,0 +1,295 @@ +// This file comes from https://reviews.llvm.org/D78978. +// Author: [@paolosev](https://reviews.llvm.org/p/paolosev/). + +//===-- ProcessWasm.cpp ---------------------------------------------------===// +// +// 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/Utility/DataBufferHeap.h" + +#include "lldb/Target/UnixSignals.h" +#include "llvm/ADT/ArrayRef.h" + +using namespace lldb; +using namespace lldb_private; +using namespace lldb_private::process_gdb_remote; +using namespace lldb_private::wasm; + +LLDB_PLUGIN_DEFINE(ProcessWasm) + +// ProcessGDBRemote constructor +ProcessWasm::ProcessWasm(lldb::TargetSP target_sp, ListenerSP listener_sp) + : ProcessGDBRemote(target_sp, listener_sp) { + /* always use linux signals for wasm process */ + m_unix_signals_sp = UnixSignals::Create(ArchSpec{"wasm32-unknown-unknown-wasm"}); +} + +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); +} + +// PluginInterface +llvm::StringRef ProcessWasm::GetPluginName() { return GetPluginNameStatic(); } + +ConstString ProcessWasm::GetPluginNameStatic() { + static ConstString g_name("wasm"); + return g_name; +} + +const char *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) { + lldb::ProcessSP process_sp; + if (crash_file_path == nullptr) + process_sp = std::make_shared<ProcessWasm>(target_sp, listener_sp); + return process_sp; +} + +bool ProcessWasm::CanDebug(lldb::TargetSP target_sp, + bool plugin_specified_by_name) { + if (plugin_specified_by_name) + return true; + + Module *exe_module = target_sp->GetExecutableModulePointer(); + if (exe_module) { + 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: + return ProcessGDBRemote::ReadMemory(vm_addr, buf, size, error); + case WasmAddressType::Object: + // TODO ? + return ProcessGDBRemote::ReadMemory(vm_addr, buf, size, error); + case WasmAddressType::Invalid: + default: + error.SetErrorStringWithFormat( + "Wasm read failed for invalid address 0x%" PRIx64, vm_addr); + return 0; + } +} + +size_t ProcessWasm::ReadMemory(lldb::addr_t vm_addr, void *buf, size_t size, + ExecutionContext *exe_ctx, Status &error) { + wasm_addr_t wasm_addr(vm_addr); + + switch (wasm_addr.GetType()) { + case WasmAddressType::Memory: { + // If we don't have a valid module_id, this is actually a read from the + // Wasm memory space. We can calculate the module_id from the execution + // context. + if (wasm_addr.module_id == 0 && exe_ctx != nullptr) { + StackFrame *frame = exe_ctx->GetFramePtr(); + assert(frame->CalculateTarget()->GetArchitecture().GetMachine() == + llvm::Triple::wasm32); + wasm_addr.module_id = wasm_addr_t(frame->GetStackID().GetPC()).module_id; + wasm_addr.type = WasmAddressType::Memory; + } + if (WasmReadMemory(wasm_addr.module_id, wasm_addr.offset, buf, size)) + return size; + error.SetErrorStringWithFormat("Wasm memory read failed for 0x%" PRIx64, + vm_addr); + return 0; + } + case WasmAddressType::Object: + // TODO ? + return ProcessGDBRemote::ReadMemory(vm_addr, buf, size, error); + case WasmAddressType::Invalid: + default: + error.SetErrorStringWithFormat( + "Wasm read failed for invalid address 0x%" PRIx64, vm_addr); + return 0; + } +} + +size_t ProcessWasm::WasmReadMemory(uint32_t wasm_module_id, lldb::addr_t addr, + void *buf, size_t buffer_size) { + char packet[64]; + int packet_len = + ::snprintf(packet, sizeof(packet), "qWasmMem:%d;%" PRIx64 ";%" PRIx64, + wasm_module_id, static_cast<uint64_t>(addr), + static_cast<uint64_t>(buffer_size)); + assert(packet_len + 1 < (int)sizeof(packet)); + UNUSED_IF_ASSERT_DISABLED(packet_len); + StringExtractorGDBRemote response; + if (m_gdb_comm.SendPacketAndWaitForResponse(packet, response, GetInterruptTimeout()) == ---------------- JDevlieghere wrote:
Merge conflict marker? https://github.com/llvm/llvm-project/pull/76683 _______________________________________________ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits