#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.
PlatformOpenBSD::GetPluginNameStatic(false),
PlatformOpenBSD::GetPluginDescriptionStatic(false),
PlatformOpenBSD::CreateInstance, nullptr);
+ ProcessOpenBSDKernel::Initialize();
}
}
if (g_initialize_count > 0) {
if (--g_initialize_count == 0) {
PluginManager::UnregisterPlugin(PlatformOpenBSD::CreateInstance);
+ ProcessOpenBSDKernel::Terminate();
}
}
add_subdirectory(mach-core)
add_subdirectory(minidump)
add_subdirectory(FreeBSDKernel)
+add_subdirectory(OpenBSDKernel)\r
--- /dev/null
+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
+ )
--- /dev/null
+//===-- 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 <kvm.h>
+#define _KERNEL
+#include <machine/cpu.h>
+#include <sys/proc.h>
+#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<ProcessOpenBSDKernelKVM>(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<size_t>(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__)
--- /dev/null
+//===-- 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
--- /dev/null
+//===-- 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 <sys/types.h>
+#include <sys/time.h>
+#define _KERNEL
+#include <machine/cpu.h>
+#undef _KERNEL
+#include <machine/pcb.h>
+#include <frame.h>
+#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<RegisterInfoPOSIX_arm64> 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;
+}
--- /dev/null
+//===-- 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<RegisterInfoPOSIX_arm64> 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
--- /dev/null
+//===-- 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 <sys/types.h>
+#include <sys/time.h>
+#define _KERNEL
+#include <machine/cpu.h>
+#undef _KERNEL
+#include <machine/pcb.h>
+#include <frame.h>
+#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;
+}
--- /dev/null
+//===-- 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
--- /dev/null
+//===-- 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 <sys/types.h>
+#include <sys/time.h>
+#define _KERNEL
+#include <machine/cpu.h>
+#undef _KERNEL
+#include <machine/pcb.h>
+#include <frame.h>
+#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;
+}
--- /dev/null
+//===-- 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
--- /dev/null
+//===-- 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<ProcessOpenBSDKernel *>(GetProcess().get());
+ ArchSpec arch = process->GetTarget().GetArchitecture();
+
+ switch (arch.GetMachine()) {
+ case llvm::Triple::aarch64:
+ m_thread_reg_ctx_sp =
+ std::make_shared<RegisterContextOpenBSDKernel_arm64>(
+ *this, std::make_unique<RegisterInfoPOSIX_arm64>(arch, 0),
+ m_pcb);
+ break;
+ case llvm::Triple::x86:
+ m_thread_reg_ctx_sp = std::make_shared<RegisterContextOpenBSDKernel_i386>(
+ *this, new RegisterContextOpenBSD_i386(arch), m_pcb);
+ break;
+ case llvm::Triple::x86_64:
+ m_thread_reg_ctx_sp =
+ std::make_shared<RegisterContextOpenBSDKernel_x86_64>(
+ *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; }
--- /dev/null
+//===-- 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
-# $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=
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
.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 ...
-# $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 <bsd.own.mk>
Platform.cpp \
Version.cpp
-LDADD+= -lcurses -ledit -lpanel
+LDADD+= -lcurses -ledit -lpanel -lkvm
CPPFLAGS+= ${LLDB_INCLUDES}
CPPFLAGS+= ${CLANG_INCLUDES}