sync with OpenBSD -current

This commit is contained in:
purplerain 2024-07-13 21:15:57 +02:00
parent ae019f102d
commit bc7421a947
Signed by: purplerain
GPG key ID: F42C07F07E2E35B7
142 changed files with 4267 additions and 1365 deletions

View file

@ -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();
}
}

View file

@ -22,3 +22,4 @@ add_subdirectory(elf-core)
add_subdirectory(mach-core)
add_subdirectory(minidump)
add_subdirectory(FreeBSDKernel)
add_subdirectory(OpenBSDKernel)

View file

@ -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
)

View file

@ -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__)

View file

@ -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

View file

@ -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;
}

View file

@ -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

View file

@ -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;
}

View file

@ -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

View file

@ -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;
}

View file

@ -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

View file

@ -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; }

View file

@ -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