Download raw body.
lldb: Kernel corefile support
I tested this patch on following machines.
- AMD box (64 bits)
- Intel (64 bits) + ESXi virtual environment
- AMD (64 bits) + ESXi virtual environment
And it is fine for me. ok asou@.
The patch contain support arm64. However, I have no arm64
architecture. Can I commit this patch or anybody test on arm64
architecture?
--
ASOU Masato
2024年6月5日(水) 5:45 Yuichiro NAITO <naito.yuichiro@gmail.com>:
>
> Hi, I ported the lldb OpenBSD kernel core file plugin from FreeBSD.
> It works on amd64 architecture. I also ported i386 and arm64 architectures
> for my technical challenge to learn them. I know lldb is not compiled on i386
> and the 'dumpsys' kernel function doesn't work on arm64.
>
> My plugin reads the 'pcb' structure to get a stack frame of a crashed thread
> and all 'proc' threads. To read the 'pcb' structure, it needs to include
> <machine/pcb.h>. I'm not sure how to get the offsets of the stack pointer and
> the frame pointer of 'pcb' in another way.
>
> An example backtrace and thread list that is stopped by 'sysctl ddb.trigger=1'
> with a bsd.gdb kernel.
>
> Is my patch OK?
>
> # lldb bsd.1 -c bsd.1.core
> (lldb) target create "bsd.1" --core "bsd.1.core"
> Core file '/var/crash/bsd.1.core' (x86_64) was loaded.
> (lldb) bt
> * thread #1, name = 'Crashed Thread'
> * frame #0: 0xffffffff8114dcfc bsd.1`db_fncall(addr=<unavailable>, have_addr=<unavailable>, count=<unavailable>, modif=<unavailable>) at db_command.c:808:11
> frame #1: 0xffffffff8114dcfc bsd.1`db_fncall(addr=<unavailable>, have_addr=<unavailable>, count=<unavailable>, modif=<unavailable>) at db_command.c:808:11
> frame #2: 0xffffffff8114d96e bsd.1`db_command(last_cmdp=0xffffffff825a7fc0, cmd_table=<unavailable>) at db_command.c:292:3
> frame #3: 0xffffffff8114eb0a bsd.1`db_command_loop at db_command.c:738:3
> frame #4: 0xffffffff81fe6219 bsd.1`db_trap(type=<unavailable>, code=<unavailable>) at db_trap.c:92:3
> frame #5: 0xffffffff815c9a51 bsd.1`db_ktrap(type=1, code=0, regs=0xffff80001ca8a010) at db_interface.c:150:2
> frame #6: 0xffffffff81a303f7 bsd.1`kerntrap(frame=0x0000000000000000) at trap.c:323:7
> frame #7: 0xffffffff821001ce bsd.1`alltraps_kern + 126
> frame #8: 0xffffffff815ca5b4 bsd.1`db_enter [inlined] breakpoint at cpufunc.h:414:2
> frame #9: 0xffffffff815ca5b3 bsd.1`db_enter at db_interface.c:436:2
> frame #10: 0xffffffff81af3b7a bsd.1`ddb_sysctl(name=<unavailable>, namelen=<unavailable>, oldp=<unavailable>, oldlenp=<unavailable>, newp=<unavailable>, newlen=<unavailable>, p=0xffff80001ca52a68) at db_usrreq.c:81:5
> frame #11: 0xffffffff81db2a5b bsd.1`sys_sysctl(p=0x0000000000000001, v=0x00007be0397e0d30, retval=<unavailable>) at kern_sysctl.c:254:10
> frame #12: 0xffffffff81a30de1 bsd.1`syscall [inlined] mi_syscall(p=0xffff80001ca8a210, code=-2120020511, callp=<unavailable>, argp=0xffff80001ca8a2a0, retval=<unavailable>) at syscall_mi.h:180:10
> frame #13: 0xffffffff81a30dbc bsd.1`syscall(frame=0xffff80001ca8a2a0) at trap.c:577:10
> frame #14: 0xffffffff820ff134 bsd.1`Xsyscall_meltdown + 308
> frame #15: 0xffffffff820ff055 bsd.1`Xsyscall_meltdown + 85
> frame #16: 0xffff80001ca8a2a0
> frame #17: 0x00000ab61a54eedb
> (lldb) thread list
> Process 0 stopped
> * thread #1: tid = 0x0000, 0xffffffff8114dcfc bsd.1`db_fncall(addr=<unavailable>, have_addr=<unavailable>, count=<unavailable>, modif=<unavailable>) at db_command.c:808:11, name = 'Crashed Thread'
> thread #2: tid = 0x4d1b1, name = '(pid:27380) sysctl (cpu 0)'
> thread #3: tid = 0x33db6, 0xffffffff81f32cb8 bsd.1`mi_switch at sched_bsd.c:419:3, name = '(pid:4343) ksh'
> thread #4: tid = 0x2baf4, 0xffffffff81f32cb8 bsd.1`mi_switch at sched_bsd.c:419:3, name = '(pid:61728) cron'
> thread #5: tid = 0x3dde2, 0xffffffff81f32cb8 bsd.1`mi_switch at sched_bsd.c:419:3, name = '(pid:74120) avahi-daemon'
> thread #6: tid = 0x1f57f, 0xffffffff81f32cb8 bsd.1`mi_switch at sched_bsd.c:419:3, name = '(pid:62798) dbus-daemon'
> thread #7: tid = 0x329c, 0xffffffff81f32cb8 bsd.1`mi_switch at sched_bsd.c:419:3, name = '(pid:68716) sndiod'
> thread #8: tid = 0x7772, 0xffffffff81f32cb8 bsd.1`mi_switch at sched_bsd.c:419:3, name = '(pid:6352) sndiod'
> thread #9: tid = 0x16b9a, 0xffffffff81f32cb8 bsd.1`mi_switch at sched_bsd.c:419:3, name = '(pid:16751) smtpd'
> thread #10: tid = 0x23a11, 0xffffffff81f32cb8 bsd.1`mi_switch at sched_bsd.c:419:3, name = '(pid:47666) smtpd'
> thread #11: tid = 0x470ba, 0xffffffff81f32cb8 bsd.1`mi_switch at sched_bsd.c:419:3, name = '(pid:35809) smtpd'
> thread #12: tid = 0x517e5, 0xffffffff81f32cb8 bsd.1`mi_switch at sched_bsd.c:419:3, name = '(pid:23758) smtpd'
> thread #13: tid = 0x49bbc, 0xffffffff81f32cb8 bsd.1`mi_switch at sched_bsd.c:419:3, name = '(pid:50263) smtpd'
> thread #14: tid = 0x64ea2, 0xffffffff81f32cb8 bsd.1`mi_switch at sched_bsd.c:419:3, name = '(pid:64209) smtpd'
> thread #15: tid = 0x73ee5, 0xffffffff81f32cb8 bsd.1`mi_switch at sched_bsd.c:419:3, name = '(pid:9349) smtpd'
> thread #16: tid = 0x7fba2, 0xffffffff81f32cb8 bsd.1`mi_switch at sched_bsd.c:419:3, name = '(pid:77759) sshd'
> thread #17: tid = 0x19050, 0xffffffff81f32cb8 bsd.1`mi_switch at sched_bsd.c:419:3, name = '(pid:3913) ntpd'
> thread #18: tid = 0x41e7b, 0xffffffff81f32cb8 bsd.1`mi_switch at sched_bsd.c:419:3, name = '(pid:76783) ntpd'
> thread #19: tid = 0x1133, 0xffffffff81f32cb8 bsd.1`mi_switch at sched_bsd.c:419:3, name = '(pid:6608) ntpd'
> thread #20: tid = 0x30ec7, 0xffffffff81f32cb8 bsd.1`mi_switch at sched_bsd.c:419:3, name = '(pid:48134) pflogd'
> thread #21: tid = 0x4b79c, 0xffffffff81f32cb8 bsd.1`mi_switch at sched_bsd.c:419:3, name = '(pid:12813) pflogd'
> thread #22: tid = 0x611bf, 0xffffffff81f32cb8 bsd.1`mi_switch at sched_bsd.c:419:3, name = '(pid:74795) syslogd'
> thread #23: tid = 0x7a02d, 0xffffffff81f32cb8 bsd.1`mi_switch at sched_bsd.c:419:3, name = '(pid:12529) syslogd'
> thread #24: tid = 0x26d34, 0xffffffff81f32cb8 bsd.1`mi_switch at sched_bsd.c:419:3, name = '(pid:3765) resolvd'
> thread #25: tid = 0x5bfb, 0xffffffff81f32cb8 bsd.1`mi_switch at sched_bsd.c:419:3, name = '(pid:57496) dhcpleased'
> thread #26: tid = 0x7d804, 0xffffffff81f32cb8 bsd.1`mi_switch at sched_bsd.c:419:3, name = '(pid:49745) dhcpleased'
> thread #27: tid = 0x728f4, 0xffffffff81f32cb8 bsd.1`mi_switch at sched_bsd.c:419:3, name = '(pid:49185) dhcpleased'
> thread #28: tid = 0x7122c, 0xffffffff81f32cb8 bsd.1`mi_switch at sched_bsd.c:419:3, name = '(pid:68535) slaacd'
> thread #29: tid = 0x5fa71, 0xffffffff81f32cb8 bsd.1`mi_switch at sched_bsd.c:419:3, name = '(pid:7648) slaacd'
> thread #30: tid = 0x4cf5a, 0xffffffff81f32cb8 bsd.1`mi_switch at sched_bsd.c:419:3, name = '(pid:49587) slaacd'
> thread #31: tid = 0x7eeea, 0xffffffff81f32cb8 bsd.1`mi_switch at sched_bsd.c:419:3, name = '(pid:6793) smr'
> thread #32: tid = 0x5f4c9, 0xffffffff81f32cb8 bsd.1`mi_switch at sched_bsd.c:419:3, name = '(pid:73371) zerothread'
> thread #33: tid = 0x5e195, 0xffffffff81f32cb8 bsd.1`mi_switch at sched_bsd.c:419:3, name = '(pid:59627) aiodoned'
> thread #34: tid = 0x38817, 0xffffffff81f32cb8 bsd.1`mi_switch at sched_bsd.c:419:3, name = '(pid:47650) update'
> thread #35: tid = 0x773fb, 0xffffffff81f32cb8 bsd.1`mi_switch at sched_bsd.c:419:3, name = '(pid:83391) cleaner'
> thread #36: tid = 0x13986, 0xffffffff81f32cb8 bsd.1`mi_switch at sched_bsd.c:419:3, name = '(pid:4549) reaper'
> thread #37: tid = 0x2aa52, 0xffffffff81f32cb8 bsd.1`mi_switch at sched_bsd.c:419:3, name = '(pid:59949) pagedaemon'
> thread #38: tid = 0x6c4a2, 0xffffffff81f32cb8 bsd.1`mi_switch at sched_bsd.c:419:3, name = '(pid:62370) acpi0'
> thread #39: tid = 0x1d72e, 0xffffffff8196b002 bsd.1`sched_idle(v=<unavailable>) at kern_sched.c:183:27, name = '(pid:42019) idle3 (cpu 3)'
> thread #40: tid = 0x41e3, 0xffffffff8196b002 bsd.1`sched_idle(v=<unavailable>) at kern_sched.c:183:27, name = '(pid:57382) idle2 (cpu 2)'
> thread #41: tid = 0x2ff0d, 0xffffffff8196b002 bsd.1`sched_idle(v=<unavailable>) at kern_sched.c:183:27, name = '(pid:56434) idle1 (cpu 1)'
> thread #42: tid = 0x2d73b, 0xffffffff81f32cb8 bsd.1`mi_switch at sched_bsd.c:419:3, name = '(pid:8366) softnet3'
> thread #43: tid = 0x47810, 0xffffffff81f32cb8 bsd.1`mi_switch at sched_bsd.c:419:3, name = '(pid:63010) softnet2'
> thread #44: tid = 0xc228, 0xffffffff81f32cb8 bsd.1`mi_switch at sched_bsd.c:419:3, name = '(pid:80989) softnet1'
> thread #45: tid = 0x017b, 0xffffffff81f32cb8 bsd.1`mi_switch at sched_bsd.c:419:3, name = '(pid:44883) softnet0'
> thread #46: tid = 0x555b9, 0xffffffff81f32cb8 bsd.1`mi_switch at sched_bsd.c:419:3, name = '(pid:80021) systqmp'
> thread #47: tid = 0x3a5ce, 0xffffffff81f32cb8 bsd.1`mi_switch at sched_bsd.c:419:3, name = '(pid:32001) systq'
> thread #48: tid = 0x75b43, 0xffffffff81f32cb8 bsd.1`mi_switch at sched_bsd.c:419:3, name = '(pid:89538) softclockmp'
> thread #49: tid = 0x27cbd, 0xffffffff81f32cb8 bsd.1`mi_switch at sched_bsd.c:419:3, name = '(pid:56248) softclock'
> thread #50: tid = 0x55f80, 0xffffffff81f32cb8 bsd.1`mi_switch at sched_bsd.c:419:3, name = '(pid:73828) idle0'
> thread #51: tid = 0x6f358, 0xffffffff81f32cb8 bsd.1`mi_switch at sched_bsd.c:419:3, name = '(pid:1) init'
> * thread #1: tid = 0x0000, 0xffffffff8114dcfc bsd.1`db_fncall(addr=<unavailable>, have_addr=<unavailable>, count=<unavailable>, modif=<unavailable>) at db_command.c:808:11, name = 'Crashed Thread'
>
>
> diff --git a/gnu/llvm/lldb/source/Plugins/Platform/OpenBSD/PlatformOpenBSD.cpp b/gnu/llvm/lldb/source/Plugins/Platform/OpenBSD/PlatformOpenBSD.cpp
> index 7aa5620b14d..cec6c50a007 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..2c5f2cf59cb 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..300a35d4051
> --- /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 <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__)
> 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..666dd9c2c67
> --- /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 <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;
> +}
> 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..b21a074c3e7
> --- /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<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
> 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 <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;
> +}
> 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..1d44dedf0c5
> --- /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 <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;
> +}
> 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..63c06fd5d9c
> --- /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..921101a418f
> --- /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<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; }
> 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..9324eb50712
> --- /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..c7b240f6f12 100644
> --- a/gnu/usr.bin/clang/liblldbPluginProcess/Makefile
> +++ b/gnu/usr.bin/clang/liblldbPluginProcess/Makefile
> @@ -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..652769fd92b 100644
> --- a/gnu/usr.bin/clang/lldb/Makefile
> +++ b/gnu/usr.bin/clang/lldb/Makefile
> @@ -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}
>
> --
> Yuichiro NAITO (naito.yuichiro@gmail.com)
>
lldb: Kernel corefile support