From 513cf72f82c16dd38f89b0e7a0ec4a163d87f81f Mon Sep 17 00:00:00 2001 From: asou Date: Sat, 13 Jul 2024 07:25:38 +0000 Subject: [PATCH] Implement investigate kernel corefile to lldb. --- .../Platform/OpenBSD/PlatformOpenBSD.cpp | 3 + .../source/Plugins/Process/CMakeLists.txt | 1 + .../Process/OpenBSDKernel/CMakeLists.txt | 14 ++ .../OpenBSDKernel/ProcessOpenBSDKernel.cpp | 223 ++++++++++++++++++ .../OpenBSDKernel/ProcessOpenBSDKernel.h | 53 +++++ .../RegisterContextOpenBSDKernel_arm64.cpp | 107 +++++++++ .../RegisterContextOpenBSDKernel_arm64.h | 41 ++++ .../RegisterContextOpenBSDKernel_i386.cpp | 110 +++++++++ .../RegisterContextOpenBSDKernel_i386.h | 41 ++++ .../RegisterContextOpenBSDKernel_x86_64.cpp | 111 +++++++++ .../RegisterContextOpenBSDKernel_x86_64.h | 41 ++++ .../OpenBSDKernel/ThreadOpenBSDKernel.cpp | 86 +++++++ .../OpenBSDKernel/ThreadOpenBSDKernel.h | 50 ++++ .../clang/liblldbPluginProcess/Makefile | 10 +- gnu/usr.bin/clang/lldb/Makefile | 4 +- 15 files changed, 892 insertions(+), 3 deletions(-) create mode 100644 gnu/llvm/lldb/source/Plugins/Process/OpenBSDKernel/CMakeLists.txt create mode 100644 gnu/llvm/lldb/source/Plugins/Process/OpenBSDKernel/ProcessOpenBSDKernel.cpp create mode 100644 gnu/llvm/lldb/source/Plugins/Process/OpenBSDKernel/ProcessOpenBSDKernel.h create mode 100644 gnu/llvm/lldb/source/Plugins/Process/OpenBSDKernel/RegisterContextOpenBSDKernel_arm64.cpp create mode 100644 gnu/llvm/lldb/source/Plugins/Process/OpenBSDKernel/RegisterContextOpenBSDKernel_arm64.h create mode 100644 gnu/llvm/lldb/source/Plugins/Process/OpenBSDKernel/RegisterContextOpenBSDKernel_i386.cpp create mode 100644 gnu/llvm/lldb/source/Plugins/Process/OpenBSDKernel/RegisterContextOpenBSDKernel_i386.h create mode 100644 gnu/llvm/lldb/source/Plugins/Process/OpenBSDKernel/RegisterContextOpenBSDKernel_x86_64.cpp create mode 100644 gnu/llvm/lldb/source/Plugins/Process/OpenBSDKernel/RegisterContextOpenBSDKernel_x86_64.h create mode 100644 gnu/llvm/lldb/source/Plugins/Process/OpenBSDKernel/ThreadOpenBSDKernel.cpp create mode 100644 gnu/llvm/lldb/source/Plugins/Process/OpenBSDKernel/ThreadOpenBSDKernel.h diff --git a/gnu/llvm/lldb/source/Plugins/Platform/OpenBSD/PlatformOpenBSD.cpp b/gnu/llvm/lldb/source/Plugins/Platform/OpenBSD/PlatformOpenBSD.cpp index 7aa5620b14d..4d284df3cc4 100644 --- a/gnu/llvm/lldb/source/Plugins/Platform/OpenBSD/PlatformOpenBSD.cpp +++ b/gnu/llvm/lldb/source/Plugins/Platform/OpenBSD/PlatformOpenBSD.cpp @@ -25,6 +25,7 @@ #include "lldb/Utility/State.h" #include "lldb/Utility/Status.h" #include "lldb/Utility/StreamString.h" +#include "Plugins/Process/OpenBSDKernel/ProcessOpenBSDKernel.h" // Define these constants from OpenBSD mman.h for use when targeting remote // openbsd systems even when host has different values. @@ -91,6 +92,7 @@ void PlatformOpenBSD::Initialize() { PlatformOpenBSD::GetPluginNameStatic(false), PlatformOpenBSD::GetPluginDescriptionStatic(false), PlatformOpenBSD::CreateInstance, nullptr); + ProcessOpenBSDKernel::Initialize(); } } @@ -98,6 +100,7 @@ void PlatformOpenBSD::Terminate() { if (g_initialize_count > 0) { if (--g_initialize_count == 0) { PluginManager::UnregisterPlugin(PlatformOpenBSD::CreateInstance); + ProcessOpenBSDKernel::Terminate(); } } diff --git a/gnu/llvm/lldb/source/Plugins/Process/CMakeLists.txt b/gnu/llvm/lldb/source/Plugins/Process/CMakeLists.txt index ec35a428a88..687a7690a39 100644 --- a/gnu/llvm/lldb/source/Plugins/Process/CMakeLists.txt +++ b/gnu/llvm/lldb/source/Plugins/Process/CMakeLists.txt @@ -22,3 +22,4 @@ add_subdirectory(elf-core) add_subdirectory(mach-core) add_subdirectory(minidump) add_subdirectory(FreeBSDKernel) +add_subdirectory(OpenBSDKernel) diff --git a/gnu/llvm/lldb/source/Plugins/Process/OpenBSDKernel/CMakeLists.txt b/gnu/llvm/lldb/source/Plugins/Process/OpenBSDKernel/CMakeLists.txt new file mode 100644 index 00000000000..40976662fb3 --- /dev/null +++ b/gnu/llvm/lldb/source/Plugins/Process/OpenBSDKernel/CMakeLists.txt @@ -0,0 +1,14 @@ +add_lldb_library(lldbPluginProcessOpenBSDKernel PLUGIN + ProcessOpenBSDKernel.cpp + RegisterContextOpenBSDKernel_arm64.cpp + RegisterContextOpenBSDKernel_i386.cpp + RegisterContextOpenBSDKernel_x86_64.cpp + ThreadOpenBSDKernel.cpp + + LINK_LIBS + lldbCore + lldbTarget + kvm + LINK_COMPONENTS + Support + ) diff --git a/gnu/llvm/lldb/source/Plugins/Process/OpenBSDKernel/ProcessOpenBSDKernel.cpp b/gnu/llvm/lldb/source/Plugins/Process/OpenBSDKernel/ProcessOpenBSDKernel.cpp new file mode 100644 index 00000000000..57724ca9efb --- /dev/null +++ b/gnu/llvm/lldb/source/Plugins/Process/OpenBSDKernel/ProcessOpenBSDKernel.cpp @@ -0,0 +1,223 @@ +//===-- ProcessOpenBSDKernel.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 "lldb/Core/Module.h" +#include "lldb/Core/PluginManager.h" +#include "lldb/Target/DynamicLoader.h" + +#include "Plugins/DynamicLoader/Static/DynamicLoaderStatic.h" +#include "ProcessOpenBSDKernel.h" +#include "ThreadOpenBSDKernel.h" + +#if defined(__OpenBSD__) +#include +#define _KERNEL +#include +#include +#undef _KERNEL +#endif + +using namespace lldb; +using namespace lldb_private; + +LLDB_PLUGIN_DEFINE(ProcessOpenBSDKernel) + +namespace { + +#if defined(__OpenBSD__) +class ProcessOpenBSDKernelKVM : public ProcessOpenBSDKernel { +public: + ProcessOpenBSDKernelKVM(lldb::TargetSP target_sp, lldb::ListenerSP listener, + kvm_t *fvc); + + ~ProcessOpenBSDKernelKVM(); + + size_t DoReadMemory(lldb::addr_t addr, void *buf, size_t size, + lldb_private::Status &error) override; + +private: + kvm_t *m_kvm; + + const char *GetError(); +}; +#endif // defined(__OpenBSD__) + +} // namespace + +ProcessOpenBSDKernel::ProcessOpenBSDKernel(lldb::TargetSP target_sp, + ListenerSP listener_sp) + : PostMortemProcess(target_sp, listener_sp) {} + +lldb::ProcessSP ProcessOpenBSDKernel::CreateInstance(lldb::TargetSP target_sp, + ListenerSP listener_sp, + const FileSpec *crash_file, + bool can_connect) { + ModuleSP executable = target_sp->GetExecutableModule(); + if (crash_file && !can_connect && executable) { +#if defined(__OpenBSD__) + kvm_t *kvm = + kvm_open(executable->GetFileSpec().GetPath().c_str(), + crash_file->GetPath().c_str(), nullptr, O_RDONLY, nullptr); + if (kvm) + return std::make_shared(target_sp, listener_sp, + kvm); +#endif + } + return nullptr; +} + +void ProcessOpenBSDKernel::Initialize() { + static llvm::once_flag g_once_flag; + + llvm::call_once(g_once_flag, []() { + PluginManager::RegisterPlugin(GetPluginNameStatic(), + GetPluginDescriptionStatic(), CreateInstance); + }); +} + +void ProcessOpenBSDKernel::Terminate() { + PluginManager::UnregisterPlugin(ProcessOpenBSDKernel::CreateInstance); +} + +Status ProcessOpenBSDKernel::DoDestroy() { return Status(); } + +bool ProcessOpenBSDKernel::CanDebug(lldb::TargetSP target_sp, + bool plugin_specified_by_name) { + return true; +} + +void ProcessOpenBSDKernel::RefreshStateAfterStop() {} + +bool ProcessOpenBSDKernel::DoUpdateThreadList(ThreadList &old_thread_list, + ThreadList &new_thread_list) { + if (old_thread_list.GetSize(false) == 0) { + // Make up the thread the first time this is called so we can set our one + // and only core thread state up. + + // We cannot construct a thread without a register context as that crashes + // LLDB but we can construct a process without threads to provide minimal + // memory reading support. + switch (GetTarget().GetArchitecture().GetMachine()) { + case llvm::Triple::aarch64: + case llvm::Triple::x86: + case llvm::Triple::x86_64: + break; + default: + return false; + } + + Status error; + int32_t i; + lldb::addr_t dumppcb = FindSymbol("dumppcb"); + uint32_t offset_p_list = offsetof(proc, p_list); + uint32_t offset_p_addr = offsetof(proc, p_addr); + uint32_t offset_p_tid = offsetof(proc, p_tid); + uint32_t offset_p_p = offsetof(proc, p_p); + uint32_t offset_ps_comm = offsetof(process, ps_comm); + uint32_t offset_ps_pid = offsetof(process, ps_pid); + uint32_t offset_ci_curproc = offsetof(cpu_info, ci_curproc); + char comm[_MAXCOMLEN]; + + int32_t ncpu = ReadSignedIntegerFromMemory(FindSymbol("ncpus"), + 4, -1, error); + if (ncpu < 0) + return false; + + lldb::addr_t cpu_procs[ncpu]; + + if (dumppcb != LLDB_INVALID_ADDRESS) { + std::string thread_desc = llvm::formatv("Crashed Thread"); + ThreadSP thread_sp { + new ThreadOpenBSDKernel(*this, 0, dumppcb, thread_desc)}; + new_thread_list.AddThread(thread_sp); + } + + lldb::addr_t cpu_info = FindSymbol("cpu_info"); + lldb::addr_t cpu_info_array = (cpu_info == LLDB_INVALID_ADDRESS) ? + ReadPointerFromMemory(FindSymbol("cpu_info_list"), error) : cpu_info; + for (i = 0; i < ncpu ; i++) { + lldb::addr_t ci = + ReadPointerFromMemory(cpu_info_array + sizeof(void*) * i, error); + cpu_procs[i] = ReadPointerFromMemory(ci + offset_ci_curproc, error); + } + + for (lldb::addr_t proc = ReadPointerFromMemory(FindSymbol("allproc"), error); + proc != 0 && proc != LLDB_INVALID_ADDRESS; + proc = ReadPointerFromMemory(proc + offset_p_list, error)) { + + lldb::tid_t tid = ReadSignedIntegerFromMemory(proc + offset_p_tid, 4, -1, + error); + lldb::addr_t process = ReadPointerFromMemory(proc + offset_p_p, error); + ReadMemory(process + offset_ps_comm, &comm, sizeof(comm), error); + u_int32_t pid = ReadSignedIntegerFromMemory(process + offset_ps_pid, 4, + -1, error); + lldb::addr_t p_addr = ReadPointerFromMemory(proc + offset_p_addr, error); + for (i = 0; i < ncpu; i++) + if (cpu_procs[i] == proc) + break; + std::string thread_desc; + if (i == ncpu) + thread_desc = llvm::formatv("(pid:{0}) {1}", pid, comm); + else + thread_desc = llvm::formatv("(pid:{0}) {1} (cpu {2})", pid, comm, i); + ThreadSP thread_sp { + new ThreadOpenBSDKernel(*this, tid, p_addr, thread_desc)}; + new_thread_list.AddThread(thread_sp); + } + } else { + const uint32_t num_threads = old_thread_list.GetSize(false); + for (uint32_t i = 0; i < num_threads; ++i) + new_thread_list.AddThread(old_thread_list.GetThreadAtIndex(i, false)); + } + return new_thread_list.GetSize(false) > 0; +} + +Status ProcessOpenBSDKernel::DoLoadCore() { + // The core is already loaded by CreateInstance(). + return Status(); +} + +DynamicLoader *ProcessOpenBSDKernel::GetDynamicLoader() { + if (m_dyld_up.get() == nullptr) + m_dyld_up.reset(DynamicLoader::FindPlugin( + this, DynamicLoaderStatic::GetPluginNameStatic())); + return m_dyld_up.get(); +} + +lldb::addr_t ProcessOpenBSDKernel::FindSymbol(const char *name) { + ModuleSP mod_sp = GetTarget().GetExecutableModule(); + const Symbol *sym = mod_sp->FindFirstSymbolWithNameAndType(ConstString(name)); + return sym ? sym->GetLoadAddress(&GetTarget()) : LLDB_INVALID_ADDRESS; +} + +#if defined(__OpenBSD__) + +ProcessOpenBSDKernelKVM::ProcessOpenBSDKernelKVM(lldb::TargetSP target_sp, + ListenerSP listener_sp, + kvm_t *fvc) + : ProcessOpenBSDKernel(target_sp, listener_sp), m_kvm(fvc) {} + +ProcessOpenBSDKernelKVM::~ProcessOpenBSDKernelKVM() { + if (m_kvm) + kvm_close(m_kvm); +} + +size_t ProcessOpenBSDKernelKVM::DoReadMemory(lldb::addr_t addr, void *buf, + size_t size, Status &error) { + ssize_t rd = 0; + rd = kvm_read(m_kvm, addr, buf, size); + if (rd < 0 || static_cast(rd) != size) { + error.SetErrorStringWithFormat("Reading memory failed: %s", GetError()); + return rd > 0 ? rd : 0; + } + return rd; +} + +const char *ProcessOpenBSDKernelKVM::GetError() { return kvm_geterr(m_kvm); } + +#endif // defined(__OpenBSD__) diff --git a/gnu/llvm/lldb/source/Plugins/Process/OpenBSDKernel/ProcessOpenBSDKernel.h b/gnu/llvm/lldb/source/Plugins/Process/OpenBSDKernel/ProcessOpenBSDKernel.h new file mode 100644 index 00000000000..64d90a39751 --- /dev/null +++ b/gnu/llvm/lldb/source/Plugins/Process/OpenBSDKernel/ProcessOpenBSDKernel.h @@ -0,0 +1,53 @@ +//===-- ProcessOpenBSDKernel.h ----------------------------------*- C++ -*-===// +// +// 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_OPENBSDKERNEL_PROCESSOPENBSDKERNEL_H +#define LLDB_SOURCE_PLUGINS_PROCESS_OPENBSDKERNEL_PROCESSOPENBSDKERNEL_H + +#include "lldb/Target/PostMortemProcess.h" + +class ProcessOpenBSDKernel : public lldb_private::PostMortemProcess { +public: + ProcessOpenBSDKernel(lldb::TargetSP target_sp, lldb::ListenerSP listener); + + static lldb::ProcessSP + CreateInstance(lldb::TargetSP target_sp, lldb::ListenerSP listener, + const lldb_private::FileSpec *crash_file_path, + bool can_connect); + + static void Initialize(); + + static void Terminate(); + + static llvm::StringRef GetPluginNameStatic() { return "openbsd-kernel"; } + + static llvm::StringRef GetPluginDescriptionStatic() { + return "OpenBSD kernel vmcore debugging plug-in."; + } + + llvm::StringRef GetPluginName() override { return GetPluginNameStatic(); } + + lldb_private::Status DoDestroy() override; + + bool CanDebug(lldb::TargetSP target_sp, + bool plugin_specified_by_name) override; + + void RefreshStateAfterStop() override; + + lldb_private::Status DoLoadCore() override; + + lldb_private::DynamicLoader *GetDynamicLoader() override; + +protected: + bool DoUpdateThreadList(lldb_private::ThreadList &old_thread_list, + lldb_private::ThreadList &new_thread_list) override; + + lldb::addr_t FindSymbol(const char* name); +}; + +#endif // LLDB_SOURCE_PLUGINS_PROCESS_OPENBSDKERNEL_PROCESSOPENBSDKERNEL_H diff --git a/gnu/llvm/lldb/source/Plugins/Process/OpenBSDKernel/RegisterContextOpenBSDKernel_arm64.cpp b/gnu/llvm/lldb/source/Plugins/Process/OpenBSDKernel/RegisterContextOpenBSDKernel_arm64.cpp new file mode 100644 index 00000000000..1ebfc6a799f --- /dev/null +++ b/gnu/llvm/lldb/source/Plugins/Process/OpenBSDKernel/RegisterContextOpenBSDKernel_arm64.cpp @@ -0,0 +1,107 @@ +//===-- RegisterContextOpenBSDKernel_arm64.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 +// +//===----------------------------------------------------------------------===// + +#if defined(__OpenBSD__) +#include +#include +#define _KERNEL +#include +#undef _KERNEL +#include +#include +#endif + +#include "RegisterContextOpenBSDKernel_arm64.h" +#include "Plugins/Process/Utility/lldb-arm64-register-enums.h" + +#include "lldb/Target/Process.h" +#include "lldb/Target/Thread.h" +#include "lldb/Utility/RegisterValue.h" +#include "llvm/Support/Endian.h" + +using namespace lldb; +using namespace lldb_private; + +RegisterContextOpenBSDKernel_arm64::RegisterContextOpenBSDKernel_arm64( + Thread &thread, std::unique_ptr register_info_up, + lldb::addr_t pcb_addr) + : RegisterContextPOSIX_arm64(thread, std::move(register_info_up)), + m_pcb_addr(pcb_addr) {} + +bool RegisterContextOpenBSDKernel_arm64::ReadGPR() { return true; } + +bool RegisterContextOpenBSDKernel_arm64::ReadFPR() { return true; } + +bool RegisterContextOpenBSDKernel_arm64::WriteGPR() { + assert(0); + return false; +} + +bool RegisterContextOpenBSDKernel_arm64::WriteFPR() { + assert(0); + return false; +} + +bool RegisterContextOpenBSDKernel_arm64::ReadRegister( + const RegisterInfo *reg_info, RegisterValue &value) { + if (m_pcb_addr == LLDB_INVALID_ADDRESS) + return false; + +#ifdef __aarch64__ + Status error; + struct pcb pcb; + size_t rd = m_thread.GetProcess()->ReadMemory(m_pcb_addr, &pcb, sizeof(pcb), + error); + if (rd != sizeof(pcb)) + return false; + + /* + Usually pcb is written in `cpu_switchto` function. This function writes + registers as same as the structure of `swichframe` in the stack. + We read the frame if it is. + */ + struct switchframe sf; + rd = m_thread.GetProcess()->ReadMemory(pcb.pcb_sp, &sf, sizeof(sf), error); + if (rd != sizeof(sf)) + return false; + + uint32_t reg = reg_info->kinds[lldb::eRegisterKindLLDB]; + switch (reg) { +#define REG(x) \ + case gpr_##x##_arm64: \ + value = (u_int64_t)sf.sf_##x; \ + return true; + + REG(x19); + REG(x20); + REG(x21); + REG(x22); + REG(x23); + REG(x24); + REG(x25); + REG(x26); + REG(x27); + REG(x28); + case gpr_fp_arm64: + value = (u_int64_t)sf.sf_x29; + return true; + case gpr_sp_arm64: + value = (u_int64_t)pcb.pcb_sp; + return true; + case gpr_pc_arm64: + value = (u_int64_t)sf.sf_lr; + return true; + } +#endif + return false; +} + +bool RegisterContextOpenBSDKernel_arm64::WriteRegister( + const RegisterInfo *reg_info, const RegisterValue &value) { + return false; +} diff --git a/gnu/llvm/lldb/source/Plugins/Process/OpenBSDKernel/RegisterContextOpenBSDKernel_arm64.h b/gnu/llvm/lldb/source/Plugins/Process/OpenBSDKernel/RegisterContextOpenBSDKernel_arm64.h new file mode 100644 index 00000000000..96ab55b29e0 --- /dev/null +++ b/gnu/llvm/lldb/source/Plugins/Process/OpenBSDKernel/RegisterContextOpenBSDKernel_arm64.h @@ -0,0 +1,41 @@ +//===-- RegisterContextOpenBSDKernel_arm64.h --------------------*- C++ -*-===// +// +// 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_OPENBSDKERNEL_REGISTERCONTEXTOPENBSDKERNEL_ARM64_H +#define LLDB_SOURCE_PLUGINS_PROCESS_OPENBSDKERNEL_REGISTERCONTEXTOPENBSDKERNEL_ARM64_H + +#include "Plugins/Process/Utility/RegisterContextPOSIX_arm64.h" +#include "Plugins/Process/elf-core/RegisterUtilities.h" + +class RegisterContextOpenBSDKernel_arm64 : public RegisterContextPOSIX_arm64 { +public: + RegisterContextOpenBSDKernel_arm64( + lldb_private::Thread &thread, + std::unique_ptr register_info_up, + lldb::addr_t pcb_addr); + + bool ReadRegister(const lldb_private::RegisterInfo *reg_info, + lldb_private::RegisterValue &value) override; + + bool WriteRegister(const lldb_private::RegisterInfo *reg_info, + const lldb_private::RegisterValue &value) override; + +protected: + bool ReadGPR() override; + + bool ReadFPR() override; + + bool WriteGPR() override; + + bool WriteFPR() override; + +private: + lldb::addr_t m_pcb_addr; +}; + +#endif // LLDB_SOURCE_PLUGINS_PROCESS_OPENBSDKERNEL_REGISTERCONTEXTOPENBSDKERNEL_ARM64_H diff --git a/gnu/llvm/lldb/source/Plugins/Process/OpenBSDKernel/RegisterContextOpenBSDKernel_i386.cpp b/gnu/llvm/lldb/source/Plugins/Process/OpenBSDKernel/RegisterContextOpenBSDKernel_i386.cpp new file mode 100644 index 00000000000..9a909a4e07d --- /dev/null +++ b/gnu/llvm/lldb/source/Plugins/Process/OpenBSDKernel/RegisterContextOpenBSDKernel_i386.cpp @@ -0,0 +1,110 @@ +//===-- RegisterContextOpenBSDKernel_i386.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 +// +//===----------------------------------------------------------------------===// + +#if defined(__OpenBSD__) +#include +#include +#define _KERNEL +#include +#undef _KERNEL +#include +#include +#endif + +#include "RegisterContextOpenBSDKernel_i386.h" + +#include "lldb/Target/Process.h" +#include "lldb/Target/Thread.h" +#include "lldb/Utility/RegisterValue.h" +#include "llvm/Support/Endian.h" + +using namespace lldb; +using namespace lldb_private; + +RegisterContextOpenBSDKernel_i386::RegisterContextOpenBSDKernel_i386( + Thread &thread, RegisterInfoInterface *register_info, lldb::addr_t pcb_addr) + : RegisterContextPOSIX_x86(thread, 0, register_info), m_pcb_addr(pcb_addr) { +} + +bool RegisterContextOpenBSDKernel_i386::ReadGPR() { return true; } + +bool RegisterContextOpenBSDKernel_i386::ReadFPR() { return true; } + +bool RegisterContextOpenBSDKernel_i386::WriteGPR() { + assert(0); + return false; +} + +bool RegisterContextOpenBSDKernel_i386::WriteFPR() { + assert(0); + return false; +} + +bool RegisterContextOpenBSDKernel_i386::ReadRegister( + const RegisterInfo *reg_info, RegisterValue &value) { + if (m_pcb_addr == LLDB_INVALID_ADDRESS) + return false; + +#ifdef __i386__ + struct pcb pcb; + + Status error; + size_t rd = + m_thread.GetProcess()->ReadMemory(m_pcb_addr, &pcb, sizeof(pcb), error); + if (rd != sizeof(pcb)) + return false; + + if ((pcb.pcb_flags & PCB_SAVECTX) != 0) { + uint32_t reg = reg_info->kinds[lldb::eRegisterKindLLDB]; + switch (reg) { +#define PCBREG(x) \ + case lldb_##x##_i386: \ + value = pcb.pcb_##x; \ + return true; + PCBREG(ebp); + PCBREG(esp); + case lldb_eip_i386: + value = m_thread.GetProcess()->ReadPointerFromMemory(pcb.pcb_ebp + 4, + error); + return true; + } + return false; + } + + /* + Usually pcb is written in `cpu_switchto` function. This function writes + registers as same as the structure of `swichframe` in the stack. + We read the frame if it is. + */ + struct switchframe sf; + rd = m_thread.GetProcess()->ReadMemory(pcb.pcb_esp, &sf, sizeof(sf), error); + if (rd != sizeof(sf)) + return false; + + uint32_t reg = reg_info->kinds[lldb::eRegisterKindLLDB]; + switch (reg) { +#define SFREG(x) \ + case lldb_##x##_i386: \ + value = sf.sf_##x; \ + return true; + + SFREG(edi); + SFREG(esi); + SFREG(ebx); + SFREG(eip); + PCBREG(ebp); + PCBREG(esp); + } +#endif + return false; +} + +bool RegisterContextOpenBSDKernel_i386::WriteRegister( + const RegisterInfo *reg_info, const RegisterValue &value) { + return false; +} diff --git a/gnu/llvm/lldb/source/Plugins/Process/OpenBSDKernel/RegisterContextOpenBSDKernel_i386.h b/gnu/llvm/lldb/source/Plugins/Process/OpenBSDKernel/RegisterContextOpenBSDKernel_i386.h new file mode 100644 index 00000000000..da6d9a7a062 --- /dev/null +++ b/gnu/llvm/lldb/source/Plugins/Process/OpenBSDKernel/RegisterContextOpenBSDKernel_i386.h @@ -0,0 +1,41 @@ +//===-- RegisterContextOpenBSDKernel_i386.h ---------------------*- C++ -*-===// +// +// 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_OPENBSDKERNEL_REGISTERCONTEXTOPENBSDKERNEL_I386_H +#define LLDB_SOURCE_PLUGINS_PROCESS_OPENBSDKERNEL_REGISTERCONTEXTOPENBSDKERNEL_I386_H + +#include "Plugins/Process/Utility/RegisterContextPOSIX_x86.h" +#include "Plugins/Process/elf-core/RegisterUtilities.h" + +class RegisterContextOpenBSDKernel_i386 : public RegisterContextPOSIX_x86 { +public: + RegisterContextOpenBSDKernel_i386( + lldb_private::Thread &thread, + lldb_private::RegisterInfoInterface *register_info, + lldb::addr_t pcb_addr); + + bool ReadRegister(const lldb_private::RegisterInfo *reg_info, + lldb_private::RegisterValue &value) override; + + bool WriteRegister(const lldb_private::RegisterInfo *reg_info, + const lldb_private::RegisterValue &value) override; + +protected: + bool ReadGPR() override; + + bool ReadFPR() override; + + bool WriteGPR() override; + + bool WriteFPR() override; + +private: + lldb::addr_t m_pcb_addr; +}; + +#endif // LLDB_SOURCE_PLUGINS_PROCESS_OPENBSDKERNEL_REGISTERCONTEXTOPENBSDKERNEL_I386_H diff --git a/gnu/llvm/lldb/source/Plugins/Process/OpenBSDKernel/RegisterContextOpenBSDKernel_x86_64.cpp b/gnu/llvm/lldb/source/Plugins/Process/OpenBSDKernel/RegisterContextOpenBSDKernel_x86_64.cpp new file mode 100644 index 00000000000..501fa858a92 --- /dev/null +++ b/gnu/llvm/lldb/source/Plugins/Process/OpenBSDKernel/RegisterContextOpenBSDKernel_x86_64.cpp @@ -0,0 +1,111 @@ +//===-- RegisterContextOpenBSDKernel_x86_64.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 +// +//===----------------------------------------------------------------------===// + +#if defined(__OpenBSD__) +#include +#include +#define _KERNEL +#include +#undef _KERNEL +#include +#include +#endif + +#include "RegisterContextOpenBSDKernel_x86_64.h" + +#include "lldb/Target/Process.h" +#include "lldb/Target/Thread.h" +#include "lldb/Utility/RegisterValue.h" +#include "llvm/Support/Endian.h" + +using namespace lldb; +using namespace lldb_private; + +RegisterContextOpenBSDKernel_x86_64::RegisterContextOpenBSDKernel_x86_64( + Thread &thread, RegisterInfoInterface *register_info, + lldb::addr_t pcb) + : RegisterContextPOSIX_x86(thread, 0, register_info), + m_pcb_addr(pcb) { +} + +bool RegisterContextOpenBSDKernel_x86_64::ReadGPR() { return true; } + +bool RegisterContextOpenBSDKernel_x86_64::ReadFPR() { return true; } + +bool RegisterContextOpenBSDKernel_x86_64::WriteGPR() { + assert(0); + return false; +} + +bool RegisterContextOpenBSDKernel_x86_64::WriteFPR() { + assert(0); + return false; +} + +bool RegisterContextOpenBSDKernel_x86_64::ReadRegister( + const RegisterInfo *reg_info, RegisterValue &value) { + Status error; + + if (m_pcb_addr == LLDB_INVALID_ADDRESS) + return false; + +#ifdef __amd64__ + struct pcb pcb; + size_t rd = m_thread.GetProcess()->ReadMemory(m_pcb_addr, &pcb, sizeof(pcb), + error); + if (rd != sizeof(pcb)) + return false; + + /* + Usually pcb is written in `cpu_switchto` function. This function writes + registers as same as the structure of `swichframe` in the stack. + We read the frame if it is. + */ + struct switchframe sf; + rd = m_thread.GetProcess()->ReadMemory(pcb.pcb_rsp, &sf, sizeof(sf), error); + if (rd != sizeof(sf)) + return false; + + uint32_t reg = reg_info->kinds[lldb::eRegisterKindLLDB]; + if (pcb.pcb_rbp == (u_int64_t)sf.sf_rbp) { +#define SFREG(x) \ + case lldb_##x##_x86_64: \ + value = (u_int64_t)sf.sf_##x; \ + return true; +#define PCBREG(x) \ + case lldb_##x##_x86_64: \ + value = pcb.pcb_##x; \ + return true; + switch (reg) { + SFREG(r15); + SFREG(r14); + SFREG(r13); + SFREG(r12); + SFREG(rbp); + SFREG(rbx); + SFREG(rip); + PCBREG(rsp); + } + } else { + switch (reg) { + PCBREG(rbp); + PCBREG(rsp); + case lldb_rip_x86_64: + value = m_thread.GetProcess()->ReadPointerFromMemory(pcb.pcb_rbp + 8, + error); + return true; + } + } +#endif + return false; +} + +bool RegisterContextOpenBSDKernel_x86_64::WriteRegister( + const RegisterInfo *reg_info, const RegisterValue &value) { + return false; +} diff --git a/gnu/llvm/lldb/source/Plugins/Process/OpenBSDKernel/RegisterContextOpenBSDKernel_x86_64.h b/gnu/llvm/lldb/source/Plugins/Process/OpenBSDKernel/RegisterContextOpenBSDKernel_x86_64.h new file mode 100644 index 00000000000..7a7d26ffdba --- /dev/null +++ b/gnu/llvm/lldb/source/Plugins/Process/OpenBSDKernel/RegisterContextOpenBSDKernel_x86_64.h @@ -0,0 +1,41 @@ +//===-- RegisterContextOpenBSDKernel_x86_64.h -------------------*- C++ -*-===// +// +// 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_OPENBSDKERNEL_REGISTERCONTEXTOPENBSDKERNEL_X86_64_H +#define LLDB_SOURCE_PLUGINS_PROCESS_OPENBSDKERNEL_REGISTERCONTEXTOPENBSDKERNEL_X86_64_H + +#include "Plugins/Process/Utility/RegisterContextPOSIX_x86.h" +#include "Plugins/Process/elf-core/RegisterUtilities.h" + +class RegisterContextOpenBSDKernel_x86_64 : public RegisterContextPOSIX_x86 { +public: + RegisterContextOpenBSDKernel_x86_64( + lldb_private::Thread &thread, + lldb_private::RegisterInfoInterface *register_info, + lldb::addr_t pcb); + + bool ReadRegister(const lldb_private::RegisterInfo *reg_info, + lldb_private::RegisterValue &value) override; + + bool WriteRegister(const lldb_private::RegisterInfo *reg_info, + const lldb_private::RegisterValue &value) override; + +protected: + bool ReadGPR() override; + + bool ReadFPR() override; + + bool WriteGPR() override; + + bool WriteFPR() override; + +private: + lldb::addr_t m_pcb_addr; +}; + +#endif // LLDB_SOURCE_PLUGINS_PROCESS_OPENBSDKERNEL_REGISTERCONTEXTOPENBSDKERNEL_X86_64_H diff --git a/gnu/llvm/lldb/source/Plugins/Process/OpenBSDKernel/ThreadOpenBSDKernel.cpp b/gnu/llvm/lldb/source/Plugins/Process/OpenBSDKernel/ThreadOpenBSDKernel.cpp new file mode 100644 index 00000000000..fec0b6cfc88 --- /dev/null +++ b/gnu/llvm/lldb/source/Plugins/Process/OpenBSDKernel/ThreadOpenBSDKernel.cpp @@ -0,0 +1,86 @@ +//===-- ThreadOpenBSDKernel.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 "ThreadOpenBSDKernel.h" + +#include "lldb/Target/Unwind.h" +#include "lldb/Utility/Log.h" + +#include "Plugins/Process/Utility/RegisterContextOpenBSD_i386.h" +#include "Plugins/Process/Utility/RegisterContextOpenBSD_x86_64.h" +#include "Plugins/Process/Utility/RegisterInfoPOSIX_arm64.h" +#include "ProcessOpenBSDKernel.h" +#include "RegisterContextOpenBSDKernel_arm64.h" +#include "RegisterContextOpenBSDKernel_i386.h" +#include "RegisterContextOpenBSDKernel_x86_64.h" +#include "ThreadOpenBSDKernel.h" + +using namespace lldb; +using namespace lldb_private; + +ThreadOpenBSDKernel::ThreadOpenBSDKernel(Process &process, lldb::tid_t tid, + lldb::addr_t pcb, + std::string thread_name) + : Thread(process, tid), m_thread_name(std::move(thread_name)), + m_pcb(pcb) {} + +ThreadOpenBSDKernel::~ThreadOpenBSDKernel() {} + +void ThreadOpenBSDKernel::RefreshStateAfterStop() {} + +lldb::RegisterContextSP ThreadOpenBSDKernel::GetRegisterContext() { + if (!m_reg_context_sp) + m_reg_context_sp = CreateRegisterContextForFrame(nullptr); + return m_reg_context_sp; +} + +lldb::RegisterContextSP +ThreadOpenBSDKernel::CreateRegisterContextForFrame(StackFrame *frame) { + RegisterContextSP reg_ctx_sp; + uint32_t concrete_frame_idx = 0; + + if (frame) + concrete_frame_idx = frame->GetConcreteFrameIndex(); + + if (concrete_frame_idx == 0) { + if (m_thread_reg_ctx_sp) + return m_thread_reg_ctx_sp; + + ProcessOpenBSDKernel *process = + static_cast(GetProcess().get()); + ArchSpec arch = process->GetTarget().GetArchitecture(); + + switch (arch.GetMachine()) { + case llvm::Triple::aarch64: + m_thread_reg_ctx_sp = + std::make_shared( + *this, std::make_unique(arch, 0), + m_pcb); + break; + case llvm::Triple::x86: + m_thread_reg_ctx_sp = std::make_shared( + *this, new RegisterContextOpenBSD_i386(arch), m_pcb); + break; + case llvm::Triple::x86_64: + m_thread_reg_ctx_sp = + std::make_shared( + *this, new RegisterContextOpenBSD_x86_64(arch), m_pcb); + break; + default: + assert(false && "Unsupported architecture passed to ThreadOpenBSDKernel"); + break; + } + + reg_ctx_sp = m_thread_reg_ctx_sp; + } else { + reg_ctx_sp = GetUnwinder().CreateRegisterContextForFrame(frame); + } + return reg_ctx_sp; +} + +bool ThreadOpenBSDKernel::CalculateStopInfo() { return false; } diff --git a/gnu/llvm/lldb/source/Plugins/Process/OpenBSDKernel/ThreadOpenBSDKernel.h b/gnu/llvm/lldb/source/Plugins/Process/OpenBSDKernel/ThreadOpenBSDKernel.h new file mode 100644 index 00000000000..5372e0afd37 --- /dev/null +++ b/gnu/llvm/lldb/source/Plugins/Process/OpenBSDKernel/ThreadOpenBSDKernel.h @@ -0,0 +1,50 @@ +//===-- ThreadOpenBSDKernel.h ------------------------------------- C++ -*-===// +// +// 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_OPENBSDKERNEL_THREADOPENBSDKERNEL_H +#define LLDB_SOURCE_PLUGINS_PROCESS_OPENBSDKERNEL_THREADOPENBSDKERNEL_H + +#include "lldb/Target/Thread.h" + +class ThreadOpenBSDKernel : public lldb_private::Thread { +public: + ThreadOpenBSDKernel(lldb_private::Process &process, lldb::tid_t tid, + lldb::addr_t pcb, std::string thread_name); + + ~ThreadOpenBSDKernel() override; + + void RefreshStateAfterStop() override; + + lldb::RegisterContextSP GetRegisterContext() override; + + lldb::RegisterContextSP + CreateRegisterContextForFrame(lldb_private::StackFrame *frame) override; + + const char *GetName() override { + if (m_thread_name.empty()) + return nullptr; + return m_thread_name.c_str(); + } + + void SetName(const char *name) override { + if (name && name[0]) + m_thread_name.assign(name); + else + m_thread_name.clear(); + } + +protected: + bool CalculateStopInfo() override; + +private: + std::string m_thread_name; + lldb::RegisterContextSP m_thread_reg_ctx_sp; + lldb::addr_t m_pcb; +}; + +#endif // LLDB_SOURCE_PLUGINS_PROCESS_OPENBSDKERNEL_THREADOPENBSDKERNEL_H diff --git a/gnu/usr.bin/clang/liblldbPluginProcess/Makefile b/gnu/usr.bin/clang/liblldbPluginProcess/Makefile index a075e152c07..af448a42d15 100644 --- a/gnu/usr.bin/clang/liblldbPluginProcess/Makefile +++ b/gnu/usr.bin/clang/liblldbPluginProcess/Makefile @@ -1,4 +1,4 @@ -# $OpenBSD: Makefile,v 1.11 2023/11/11 18:35:39 robert Exp $ +# $OpenBSD: Makefile,v 1.12 2024/07/13 07:25:38 asou Exp $ LIB= lldbPluginProcess NOPIC= @@ -124,6 +124,13 @@ SRCS+= MinidumpTypes.cpp \ SRCS+= ScriptedProcess.cpp \ ScriptedThread.cpp +# Process/OpenBSDKernel +SRCS+= ProcessOpenBSDKernel.cpp \ + RegisterContextOpenBSDKernel_arm64.cpp \ + RegisterContextOpenBSDKernel_i386.cpp \ + RegisterContextOpenBSDKernel_x86_64.cpp \ + ThreadOpenBSDKernel.cpp + .PATH: ${.CURDIR}/../../../llvm/lldb/source/Plugins/Process/OpenBSD .PATH: ${.CURDIR}/../../../llvm/lldb/source/Plugins/Process/POSIX .PATH: ${.CURDIR}/../../../llvm/lldb/source/Plugins/Process/gdb-remote @@ -132,6 +139,7 @@ SRCS+= ScriptedProcess.cpp \ .PATH: ${.CURDIR}/../../../llvm/lldb/source/Plugins/Process/mach-core .PATH: ${.CURDIR}/../../../llvm/lldb/source/Plugins/Process/minidump .PATH: ${.CURDIR}/../../../llvm/lldb/source/Plugins/Process/scripted +.PATH: ${.CURDIR}/../../../llvm/lldb/source/Plugins/Process/OpenBSDKernel install: @# Nothing here so far ... diff --git a/gnu/usr.bin/clang/lldb/Makefile b/gnu/usr.bin/clang/lldb/Makefile index 31a1ffc7b8b..9afc1efa738 100644 --- a/gnu/usr.bin/clang/lldb/Makefile +++ b/gnu/usr.bin/clang/lldb/Makefile @@ -1,4 +1,4 @@ -# $OpenBSD: Makefile,v 1.16 2024/02/08 20:28:54 miod Exp $ +# $OpenBSD: Makefile,v 1.17 2024/07/13 07:25:38 asou Exp $ .include @@ -10,7 +10,7 @@ SRCS= Driver.cpp \ Platform.cpp \ Version.cpp -LDADD+= -lcurses -ledit -lpanel +LDADD+= -lcurses -ledit -lpanel -lkvm CPPFLAGS+= ${LLDB_INCLUDES} CPPFLAGS+= ${CLANG_INCLUDES} -- 2.20.1