sync with OpenBSD -current
This commit is contained in:
parent
ae019f102d
commit
bc7421a947
142 changed files with 4267 additions and 1365 deletions
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -22,3 +22,4 @@ add_subdirectory(elf-core)
|
|||
add_subdirectory(mach-core)
|
||||
add_subdirectory(minidump)
|
||||
add_subdirectory(FreeBSDKernel)
|
||||
add_subdirectory(OpenBSDKernel)
|
||||
|
|
|
@ -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
|
||||
)
|
|
@ -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__)
|
|
@ -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
|
|
@ -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;
|
||||
}
|
|
@ -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
|
|
@ -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;
|
||||
}
|
|
@ -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
|
|
@ -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;
|
||||
}
|
|
@ -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
|
|
@ -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; }
|
|
@ -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
|
Loading…
Add table
Add a link
Reference in a new issue