Revert "[lldb] Introduce a FreeBSDKernel plugin for vmcores"

This reverts commit aedb328a4d.
I have failed to make the new tests conditional to the presence
of libfbsdvmcore.
This commit is contained in:
Michał Górny 2021-12-14 18:17:32 +01:00
parent 7598ac5ec5
commit 76c876e7e6
26 changed files with 1 additions and 1235 deletions

View File

@ -58,7 +58,6 @@ add_optional_dependency(LLDB_ENABLE_LZMA "Enable LZMA compression support in LLD
add_optional_dependency(LLDB_ENABLE_LUA "Enable Lua scripting support in LLDB" LuaAndSwig LUAANDSWIG_FOUND)
add_optional_dependency(LLDB_ENABLE_PYTHON "Enable Python scripting support in LLDB" PythonAndSwig PYTHONANDSWIG_FOUND)
add_optional_dependency(LLDB_ENABLE_LIBXML2 "Enable Libxml 2 support in LLDB" LibXml2 LIBXML2_FOUND VERSION 2.8)
add_optional_dependency(LLDB_ENABLE_FBSDVMCORE "Enable libfbsdvmcore support in LLDB" FBSDVMCore FBSDVMCORE_FOUND)
option(LLDB_USE_SYSTEM_SIX "Use six.py shipped with system and do not install a copy of it" OFF)
option(LLDB_USE_ENTITLEMENTS "When codesigning, use entitlements if available" ON)

View File

@ -1570,7 +1570,7 @@ class Base(unittest2.TestCase):
return os.environ["CC"]
def yaml2obj(self, yaml_path, obj_path, max_size=None):
def yaml2obj(self, yaml_path, obj_path):
"""
Create an object file at the given path from a yaml file.
@ -1580,8 +1580,6 @@ class Base(unittest2.TestCase):
if not yaml2obj_bin:
self.assertTrue(False, "No valid yaml2obj executable specified")
command = [yaml2obj_bin, "-o=%s" % obj_path, yaml_path]
if max_size is not None:
command += ["--max-size=%d" % max_size]
self.runBuildCommand(command)
def getBuildFlags(

View File

@ -18,4 +18,3 @@ add_subdirectory(Utility)
add_subdirectory(elf-core)
add_subdirectory(mach-core)
add_subdirectory(minidump)
add_subdirectory(FreeBSDKernel)

View File

@ -1,19 +0,0 @@
if (NOT FBSDVMCore_FOUND)
message(STATUS "Skipping FreeBSDKernel plugin due to missing libfbsdvmcore")
return()
endif()
add_lldb_library(lldbPluginProcessFreeBSDKernel PLUGIN
ProcessFreeBSDKernel.cpp
RegisterContextFreeBSDKernel_arm64.cpp
RegisterContextFreeBSDKernel_i386.cpp
RegisterContextFreeBSDKernel_x86_64.cpp
ThreadFreeBSDKernel.cpp
LINK_LIBS
lldbCore
lldbTarget
fbsdvmcore
LINK_COMPONENTS
Support
)

View File

@ -1,126 +0,0 @@
//===-- ProcessFreeBSDKernel.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 "ProcessFreeBSDKernel.h"
#include "ThreadFreeBSDKernel.h"
#include "Plugins/DynamicLoader/Static/DynamicLoaderStatic.h"
#include <fvc.h>
using namespace lldb;
using namespace lldb_private;
LLDB_PLUGIN_DEFINE(ProcessFreeBSDKernel)
ProcessFreeBSDKernel::ProcessFreeBSDKernel(lldb::TargetSP target_sp,
ListenerSP listener_sp,
const FileSpec &core_file, void *fvc)
: PostMortemProcess(target_sp, listener_sp), m_fvc(fvc) {}
ProcessFreeBSDKernel::~ProcessFreeBSDKernel() {
if (m_fvc)
fvc_close(static_cast<fvc_t *>(m_fvc));
}
lldb::ProcessSP ProcessFreeBSDKernel::CreateInstance(lldb::TargetSP target_sp,
ListenerSP listener_sp,
const FileSpec *crash_file,
bool can_connect) {
lldb::ProcessSP process_sp;
ModuleSP executable = target_sp->GetExecutableModule();
if (crash_file && !can_connect && executable) {
fvc_t *fvc = fvc_open(
executable->GetFileSpec().GetPath().c_str(),
crash_file->GetPath().c_str(), nullptr, nullptr, nullptr);
if (fvc)
process_sp = std::make_shared<ProcessFreeBSDKernel>(
target_sp, listener_sp, *crash_file, fvc);
}
return process_sp;
}
void ProcessFreeBSDKernel::Initialize() {
static llvm::once_flag g_once_flag;
llvm::call_once(g_once_flag, []() {
PluginManager::RegisterPlugin(GetPluginNameStatic(),
GetPluginDescriptionStatic(), CreateInstance);
});
}
void ProcessFreeBSDKernel::Terminate() {
PluginManager::UnregisterPlugin(ProcessFreeBSDKernel::CreateInstance);
}
Status ProcessFreeBSDKernel::DoDestroy() { return Status(); }
bool ProcessFreeBSDKernel::CanDebug(lldb::TargetSP target_sp,
bool plugin_specified_by_name) {
return true;
}
void ProcessFreeBSDKernel::RefreshStateAfterStop() {}
bool ProcessFreeBSDKernel::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;
}
const Symbol *pcb_sym =
GetTarget().GetExecutableModule()->FindFirstSymbolWithNameAndType(
ConstString("dumppcb"));
ThreadSP thread_sp(new ThreadFreeBSDKernel(
*this, 1, pcb_sym ? pcb_sym->GetFileAddress() : LLDB_INVALID_ADDRESS));
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 ProcessFreeBSDKernel::DoLoadCore() {
// The core is already loaded by CreateInstance().
return Status();
}
size_t ProcessFreeBSDKernel::DoReadMemory(lldb::addr_t addr, void *buf,
size_t size, Status &error) {
ssize_t rd = fvc_read(static_cast<fvc_t *>(m_fvc), addr, buf, size);
if (rd < 0 || static_cast<size_t>(rd) != size) {
error.SetErrorStringWithFormat("Reading memory failed: %s",
fvc_geterr(static_cast<fvc_t *>(m_fvc)));
return rd > 0 ? rd : 0;
}
return rd;
}
DynamicLoader *ProcessFreeBSDKernel::GetDynamicLoader() {
if (m_dyld_up.get() == nullptr)
m_dyld_up.reset(DynamicLoader::FindPlugin(
this, DynamicLoaderStatic::GetPluginNameStatic()));
return m_dyld_up.get();
}

View File

@ -1,60 +0,0 @@
//===-- ProcessFreeBSDKernel.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_FREEBSDKERNEL_PROCESSFREEBSDKERNEL_H
#define LLDB_SOURCE_PLUGINS_PROCESS_FREEBSDKERNEL_PROCESSFREEBSDKERNEL_H
#include "lldb/Target/PostMortemProcess.h"
class ProcessFreeBSDKernel : public lldb_private::PostMortemProcess {
public:
ProcessFreeBSDKernel(lldb::TargetSP target_sp, lldb::ListenerSP listener,
const lldb_private::FileSpec &core_file, void *fvc);
~ProcessFreeBSDKernel() override;
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 "freebsd-kernel"; }
static llvm::StringRef GetPluginDescriptionStatic() {
return "FreeBSD 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;
size_t DoReadMemory(lldb::addr_t addr, void *buf, size_t size,
lldb_private::Status &error) override;
lldb_private::DynamicLoader *GetDynamicLoader() override;
protected:
bool DoUpdateThreadList(lldb_private::ThreadList &old_thread_list,
lldb_private::ThreadList &new_thread_list) override;
private:
void *m_fvc;
};
#endif // LLDB_SOURCE_PLUGINS_PROCESS_FREEBSDKERNEL_PROCESSFREEBSDKERNEL_H

View File

@ -1,110 +0,0 @@
//===-- RegisterContextFreeBSDKernel_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
//
//===----------------------------------------------------------------------===//
#include "RegisterContextFreeBSDKernel_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;
RegisterContextFreeBSDKernel_arm64::RegisterContextFreeBSDKernel_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 RegisterContextFreeBSDKernel_arm64::ReadGPR() { return true; }
bool RegisterContextFreeBSDKernel_arm64::ReadFPR() { return true; }
bool RegisterContextFreeBSDKernel_arm64::WriteGPR() {
assert(0);
return false;
}
bool RegisterContextFreeBSDKernel_arm64::WriteFPR() {
assert(0);
return false;
}
bool RegisterContextFreeBSDKernel_arm64::ReadRegister(
const RegisterInfo *reg_info, RegisterValue &value) {
if (m_pcb_addr == LLDB_INVALID_ADDRESS)
return false;
struct {
llvm::support::ulittle64_t x[30];
llvm::support::ulittle64_t lr;
llvm::support::ulittle64_t _reserved;
llvm::support::ulittle64_t sp;
} pcb;
Status error;
size_t rd =
m_thread.GetProcess()->ReadMemory(m_pcb_addr, &pcb, sizeof(pcb), error);
if (rd != sizeof(pcb))
return false;
uint32_t reg = reg_info->kinds[lldb::eRegisterKindLLDB];
switch (reg) {
case gpr_x0_arm64:
case gpr_x1_arm64:
case gpr_x2_arm64:
case gpr_x3_arm64:
case gpr_x4_arm64:
case gpr_x5_arm64:
case gpr_x6_arm64:
case gpr_x7_arm64:
case gpr_x8_arm64:
case gpr_x9_arm64:
case gpr_x10_arm64:
case gpr_x11_arm64:
case gpr_x12_arm64:
case gpr_x13_arm64:
case gpr_x14_arm64:
case gpr_x15_arm64:
case gpr_x16_arm64:
case gpr_x17_arm64:
case gpr_x18_arm64:
case gpr_x19_arm64:
case gpr_x20_arm64:
case gpr_x21_arm64:
case gpr_x22_arm64:
case gpr_x23_arm64:
case gpr_x24_arm64:
case gpr_x25_arm64:
case gpr_x26_arm64:
case gpr_x27_arm64:
case gpr_x28_arm64:
case gpr_fp_arm64:
static_assert(gpr_fp_arm64 - gpr_x0_arm64 == 29,
"nonconsecutive arm64 register numbers");
value = pcb.x[reg - gpr_x0_arm64];
break;
case gpr_sp_arm64:
value = pcb.sp;
break;
case gpr_pc_arm64:
// The pc of crashing thread is stored in lr.
value = pcb.lr;
break;
default:
return false;
}
return true;
}
bool RegisterContextFreeBSDKernel_arm64::WriteRegister(
const RegisterInfo *reg_info, const RegisterValue &value) {
return false;
}

View File

@ -1,41 +0,0 @@
//===-- RegisterContextFreeBSDKernel_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_FREEBSDKERNEL_REGISTERCONTEXTFREEBSDKERNEL_ARM64_H
#define LLDB_SOURCE_PLUGINS_PROCESS_FREEBSDKERNEL_REGISTERCONTEXTFREEBSDKERNEL_ARM64_H
#include "Plugins/Process/Utility/RegisterContextPOSIX_arm64.h"
#include "Plugins/Process/elf-core/RegisterUtilities.h"
class RegisterContextFreeBSDKernel_arm64 : public RegisterContextPOSIX_arm64 {
public:
RegisterContextFreeBSDKernel_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_FREEBSDKERNEL_REGISTERCONTEXTFREEBSDKERNEL_ARM64_H

View File

@ -1,83 +0,0 @@
//===-- RegisterContextFreeBSDKernel_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
//
//===----------------------------------------------------------------------===//
#include "RegisterContextFreeBSDKernel_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;
RegisterContextFreeBSDKernel_i386::RegisterContextFreeBSDKernel_i386(
Thread &thread, RegisterInfoInterface *register_info, lldb::addr_t pcb_addr)
: RegisterContextPOSIX_x86(thread, 0, register_info), m_pcb_addr(pcb_addr) {
}
bool RegisterContextFreeBSDKernel_i386::ReadGPR() { return true; }
bool RegisterContextFreeBSDKernel_i386::ReadFPR() { return true; }
bool RegisterContextFreeBSDKernel_i386::WriteGPR() {
assert(0);
return false;
}
bool RegisterContextFreeBSDKernel_i386::WriteFPR() {
assert(0);
return false;
}
bool RegisterContextFreeBSDKernel_i386::ReadRegister(
const RegisterInfo *reg_info, RegisterValue &value) {
if (m_pcb_addr == LLDB_INVALID_ADDRESS)
return false;
struct {
llvm::support::ulittle32_t edi;
llvm::support::ulittle32_t esi;
llvm::support::ulittle32_t ebp;
llvm::support::ulittle32_t esp;
llvm::support::ulittle32_t ebx;
llvm::support::ulittle32_t eip;
} pcb;
Status error;
size_t rd =
m_thread.GetProcess()->ReadMemory(m_pcb_addr, &pcb, sizeof(pcb), error);
if (rd != sizeof(pcb))
return false;
uint32_t reg = reg_info->kinds[lldb::eRegisterKindLLDB];
switch (reg) {
#define REG(x) \
case lldb_##x##_i386: \
value = pcb.x; \
break;
REG(edi);
REG(esi);
REG(ebp);
REG(esp);
REG(eip);
#undef REG
default:
return false;
}
return true;
}
bool RegisterContextFreeBSDKernel_i386::WriteRegister(
const RegisterInfo *reg_info, const RegisterValue &value) {
return false;
}

View File

@ -1,41 +0,0 @@
//===-- RegisterContextFreeBSDKernel_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_FREEBSDKERNEL_REGISTERCONTEXTFREEBSDKERNEL_I386_H
#define LLDB_SOURCE_PLUGINS_PROCESS_FREEBSDKERNEL_REGISTERCONTEXTFREEBSDKERNEL_I386_H
#include "Plugins/Process/Utility/RegisterContextPOSIX_x86.h"
#include "Plugins/Process/elf-core/RegisterUtilities.h"
class RegisterContextFreeBSDKernel_i386 : public RegisterContextPOSIX_x86 {
public:
RegisterContextFreeBSDKernel_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_FREEBSDKERNEL_REGISTERCONTEXTFREEBSDKERNEL_I386_H

View File

@ -1,88 +0,0 @@
//===-- RegisterContextFreeBSDKernel_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
//
//===----------------------------------------------------------------------===//
#include "RegisterContextFreeBSDKernel_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;
RegisterContextFreeBSDKernel_x86_64::RegisterContextFreeBSDKernel_x86_64(
Thread &thread, RegisterInfoInterface *register_info, lldb::addr_t pcb_addr)
: RegisterContextPOSIX_x86(thread, 0, register_info), m_pcb_addr(pcb_addr) {
}
bool RegisterContextFreeBSDKernel_x86_64::ReadGPR() { return true; }
bool RegisterContextFreeBSDKernel_x86_64::ReadFPR() { return true; }
bool RegisterContextFreeBSDKernel_x86_64::WriteGPR() {
assert(0);
return false;
}
bool RegisterContextFreeBSDKernel_x86_64::WriteFPR() {
assert(0);
return false;
}
bool RegisterContextFreeBSDKernel_x86_64::ReadRegister(
const RegisterInfo *reg_info, RegisterValue &value) {
if (m_pcb_addr == LLDB_INVALID_ADDRESS)
return false;
struct {
llvm::support::ulittle64_t r15;
llvm::support::ulittle64_t r14;
llvm::support::ulittle64_t r13;
llvm::support::ulittle64_t r12;
llvm::support::ulittle64_t rbp;
llvm::support::ulittle64_t rsp;
llvm::support::ulittle64_t rbx;
llvm::support::ulittle64_t rip;
} pcb;
Status error;
size_t rd =
m_thread.GetProcess()->ReadMemory(m_pcb_addr, &pcb, sizeof(pcb), error);
if (rd != sizeof(pcb))
return false;
uint32_t reg = reg_info->kinds[lldb::eRegisterKindLLDB];
switch (reg) {
#define REG(x) \
case lldb_##x##_x86_64: \
value = pcb.x; \
break;
REG(r15);
REG(r14);
REG(r13);
REG(r12);
REG(rbp);
REG(rsp);
REG(rbx);
REG(rip);
#undef REG
default:
return false;
}
return true;
}
bool RegisterContextFreeBSDKernel_x86_64::WriteRegister(
const RegisterInfo *reg_info, const RegisterValue &value) {
return false;
}

View File

@ -1,41 +0,0 @@
//===-- RegisterContextFreeBSDKernel_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_FREEBSDKERNEL_REGISTERCONTEXTFREEBSDKERNEL_X86_64_H
#define LLDB_SOURCE_PLUGINS_PROCESS_FREEBSDKERNEL_REGISTERCONTEXTFREEBSDKERNEL_X86_64_H
#include "Plugins/Process/Utility/RegisterContextPOSIX_x86.h"
#include "Plugins/Process/elf-core/RegisterUtilities.h"
class RegisterContextFreeBSDKernel_x86_64 : public RegisterContextPOSIX_x86 {
public:
RegisterContextFreeBSDKernel_x86_64(
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_FREEBSDKERNEL_REGISTERCONTEXTFREEBSDKERNEL_X86_64_H

View File

@ -1,85 +0,0 @@
//===-- ThreadFreeBSDKernel.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 "ThreadFreeBSDKernel.h"
#include "lldb/Target/Unwind.h"
#include "lldb/Utility/Log.h"
#include "Plugins/Process/Utility/RegisterContextFreeBSD_i386.h"
#include "Plugins/Process/Utility/RegisterContextFreeBSD_x86_64.h"
#include "Plugins/Process/Utility/RegisterInfoPOSIX_arm64.h"
#include "ProcessFreeBSDKernel.h"
#include "RegisterContextFreeBSDKernel_arm64.h"
#include "RegisterContextFreeBSDKernel_i386.h"
#include "RegisterContextFreeBSDKernel_x86_64.h"
#include "ThreadFreeBSDKernel.h"
using namespace lldb;
using namespace lldb_private;
ThreadFreeBSDKernel::ThreadFreeBSDKernel(Process &process, lldb::tid_t tid,
lldb::addr_t pcb_addr)
: Thread(process, tid), m_pcb_addr(pcb_addr) {}
ThreadFreeBSDKernel::~ThreadFreeBSDKernel() {}
void ThreadFreeBSDKernel::RefreshStateAfterStop() {}
lldb::RegisterContextSP ThreadFreeBSDKernel::GetRegisterContext() {
if (!m_reg_context_sp)
m_reg_context_sp = CreateRegisterContextForFrame(nullptr);
return m_reg_context_sp;
}
lldb::RegisterContextSP
ThreadFreeBSDKernel::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;
ProcessFreeBSDKernel *process =
static_cast<ProcessFreeBSDKernel *>(GetProcess().get());
ArchSpec arch = process->GetTarget().GetArchitecture();
switch (arch.GetMachine()) {
case llvm::Triple::aarch64:
m_thread_reg_ctx_sp =
std::make_shared<RegisterContextFreeBSDKernel_arm64>(
*this, std::make_unique<RegisterInfoPOSIX_arm64>(arch, 0),
m_pcb_addr);
break;
case llvm::Triple::x86:
m_thread_reg_ctx_sp =
std::make_shared<RegisterContextFreeBSDKernel_i386>(
*this, new RegisterContextFreeBSD_i386(arch), m_pcb_addr);
break;
case llvm::Triple::x86_64:
m_thread_reg_ctx_sp =
std::make_shared<RegisterContextFreeBSDKernel_x86_64>(
*this, new RegisterContextFreeBSD_x86_64(arch), m_pcb_addr);
break;
default:
assert(false && "Unsupported architecture passed to ThreadFreeBSDKernel");
break;
}
reg_ctx_sp = m_thread_reg_ctx_sp;
} else {
reg_ctx_sp = GetUnwinder().CreateRegisterContextForFrame(frame);
}
return reg_ctx_sp;
}
bool ThreadFreeBSDKernel::CalculateStopInfo() { return false; }

View File

@ -1,36 +0,0 @@
//===-- ThreadFreeBSDKernel.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_FREEBSDKERNEL_THREADFREEBSDKERNEL_H
#define LLDB_SOURCE_PLUGINS_PROCESS_FREEBSDKERNEL_THREADFREEBSDKERNEL_H
#include "lldb/Target/Thread.h"
class ThreadFreeBSDKernel : public lldb_private::Thread {
public:
ThreadFreeBSDKernel(lldb_private::Process &process, lldb::tid_t tid,
lldb::addr_t pcb_addr);
~ThreadFreeBSDKernel() override;
void RefreshStateAfterStop() override;
lldb::RegisterContextSP GetRegisterContext() override;
lldb::RegisterContextSP
CreateRegisterContextForFrame(lldb_private::StackFrame *frame) override;
protected:
bool CalculateStopInfo() override;
private:
lldb::RegisterContextSP m_thread_reg_ctx_sp;
lldb::addr_t m_pcb_addr;
};
#endif // LLDB_SOURCE_PLUGINS_PROCESS_FREEBSDKERNEL_THREADFREEBSDKERNEL_H

View File

@ -1,153 +0,0 @@
import bz2
import shutil
import struct
import lldb
from lldbsuite.test.decorators import *
from lldbsuite.test.lldbtest import *
from lldbsuite.test import lldbutil
class FreeBSDKernelVMCoreTestCase(TestBase):
NO_DEBUG_INFO_TESTCASE = True
mydir = TestBase.compute_mydir(__file__)
def make_target(self, src_filename):
src = self.getSourcePath(src_filename)
dest = self.getBuildArtifact("kernel")
self.yaml2obj(src, dest, max_size=30*1024*1024)
return self.dbg.CreateTarget(dest)
def make_vmcore(self, src_filename):
src = self.getSourcePath(src_filename)
dest = self.getBuildArtifact("vmcore")
with bz2.open(src, "rb") as inf:
with open(dest, "wb") as outf:
shutil.copyfileobj(inf, outf)
return dest
def do_test(self, kernel_yaml, vmcore_bz2, bt_expected, regs_expected,
hz_value=100):
target = self.make_target(kernel_yaml)
vmcore_file = self.make_vmcore(vmcore_bz2)
process = target.LoadCore(vmcore_file)
self.assertTrue(process, PROCESS_IS_VALID)
self.assertEqual(process.GetNumThreads(), 1)
self.assertEqual(process.GetProcessID(), 0)
# test memory reading
self.expect("expr -- *(int *) &hz",
substrs=["(int) $0 = %d" % hz_value])
main_mod = target.GetModuleAtIndex(0)
hz_addr = (main_mod.FindSymbols("hz")[0].symbol.addr
.GetLoadAddress(target))
error = lldb.SBError()
self.assertEqual(process.ReadMemory(hz_addr, 4, error),
struct.pack("<I", hz_value))
# test backtrace
self.assertEqual(
[process.GetThreadAtIndex(0).GetFrameAtIndex(i).addr
.GetLoadAddress(target) for i in range(len(bt_expected))],
bt_expected)
# test registers
regs = process.GetThreadAtIndex(0).GetFrameAtIndex(0).GetRegisters()
reg_values = {}
for regset in regs:
for reg in regset:
if reg.value is None:
continue
reg_values[reg.name] = reg.value
self.assertEqual(reg_values, regs_expected)
self.dbg.DeleteTarget(target)
def test_amd64_full_vmcore(self):
self.do_test("kernel-amd64.yaml", "vmcore-amd64-full.bz2",
[0xffffffff80c09ade, 0xffffffff80c09916,
0xffffffff80c09d90, 0xffffffff80c09b93,
0xffffffff80c57d91, 0xffffffff80c19e71,
0xffffffff80c192bc, 0xffffffff80c19933,
0xffffffff80c1977f, 0xffffffff8108ba8c,
0xffffffff810620ce],
{"rbx": "0x0000000000000000",
"rbp": "0xfffffe0085cb2760",
"rsp": "0xfffffe0085cb2748",
"r12": "0xfffffe0045a6c300",
"r13": "0xfffff800033693a8",
"r14": "0x0000000000000000",
"r15": "0xfffff80003369380",
"rip": "0xffffffff80c09ade",
})
def test_amd64_minidump(self):
self.do_test("kernel-amd64.yaml", "vmcore-amd64-minidump.bz2",
[0xffffffff80c09ade, 0xffffffff80c09916,
0xffffffff80c09d90, 0xffffffff80c09b93,
0xffffffff80c57d91, 0xffffffff80c19e71,
0xffffffff80c192bc, 0xffffffff80c19933,
0xffffffff80c1977f, 0xffffffff8108ba8c,
0xffffffff810620ce],
{"rbx": "0x0000000000000000",
"rbp": "0xfffffe00798c4760",
"rsp": "0xfffffe00798c4748",
"r12": "0xfffffe0045b11c00",
"r13": "0xfffff800033693a8",
"r14": "0x0000000000000000",
"r15": "0xfffff80003369380",
"rip": "0xffffffff80c09ade",
})
def test_arm64_minidump(self):
self.do_test("kernel-arm64.yaml", "vmcore-arm64-minidump.bz2",
[0xffff0000004b6e78], # TODO: fix unwinding
{"x0": "0x0000000000000000",
"x1": "0x0000000000000000",
"x2": "0x0000000000000000",
"x3": "0x0000000000000000",
"x4": "0x0000000000000000",
"x5": "0x0000000000000000",
"x6": "0x0000000000000000",
"x7": "0x0000000000000000",
"x8": "0xffffa00001548700",
"x9": "0x0000000000000000",
"x10": "0xffffa00000e04580",
"x11": "0x0000000000000000",
"x12": "0x000000000008950a",
"x13": "0x0000000000089500",
"x14": "0x0000000000000039",
"x15": "0x0000000000000000",
"x16": "0x00000000ffffffd8",
"x17": "0x0000000000000000",
"x18": "0xffff000000e6d380",
"x19": "0xffff000000af9000",
"x20": "0xffff000000b82000",
"x21": "0xffffa00000319da8",
"x22": "0xffff000000b84000",
"x23": "0xffff000000b84000",
"x24": "0xffff000000b55000",
"x25": "0x0000000000000000",
"x26": "0x0000000000040800",
"x27": "0x0000000000000000",
"x28": "0x00000000002019ca",
"fp": "0xffff0000d58f23b0",
"sp": "0xffff0000d58f23b0",
"pc": "0xffff0000004b6e78",
},
hz_value=1000)
def test_i386_minidump(self):
self.do_test("kernel-i386.yaml", "vmcore-i386-minidump.bz2",
[0x010025c5, 0x01002410, 0x010027d5, 0x01002644,
0x01049a2f, 0x01011077, 0x01010780, 0x01010c7a,
0x01010ab2, 0x013e9e2d, 0xffc033f9],
{"ebp": "0x151968e4",
"esp": "0x151968d8",
"esi": "0x0c77aa80",
"edi": "0x03f0dc80",
"eip": "0x010025c5",
})

View File

@ -1,38 +0,0 @@
--- !ELF
FileHeader:
Class: ELFCLASS64
Data: ELFDATA2LSB
OSABI: ELFOSABI_FREEBSD
Type: ET_EXEC
Machine: EM_X86_64
Entry: 0xFFFFFFFF8037C000
Sections:
- Name: .bss
Type: SHT_NOBITS
Flags: [ SHF_WRITE, SHF_ALLOC ]
Address: 0xFFFFFFFF819BA380
AddressAlign: 0x80
Offset: 0x17BA348
Size: 0x445C80
Symbols:
- Name: kernbase
Index: SHN_ABS
Binding: STB_GLOBAL
Value: 0xFFFFFFFF80000000
- Name: KPML4phys
Type: STT_OBJECT
Section: .bss
Binding: STB_GLOBAL
Value: 0xFFFFFFFF81D47EB8
Size: 0x8
- Name: dumppcb
Type: STT_OBJECT
Section: .bss
Value: 0xFFFFFFFF81CA6868
Size: 0x140
- Name: hz
Type: STT_OBJECT
Section: .bss
Binding: STB_GLOBAL
Value: 0xFFFFFFFF81CD4C0C
Size: 0x4

View File

@ -1,30 +0,0 @@
--- !ELF
FileHeader:
Class: ELFCLASS64
Data: ELFDATA2LSB
Type: ET_EXEC
Machine: EM_AARCH64
Entry: 0xFFFF000000000800
Sections:
- Name: .bss
Type: SHT_NOBITS
Flags: [ SHF_WRITE, SHF_ALLOC ]
Address: 0xFFFF000000C35000
AddressAlign: 0x1000
Size: 0x37F000
Symbols:
- Name: kernbase
Index: SHN_ABS
Binding: STB_GLOBAL
Value: 0xFFFF000000000000
- Name: dumppcb
Type: STT_OBJECT
Section: .bss
Value: 0xFFFF000000DF3790
Size: 0x560
- Name: hz
Type: STT_OBJECT
Section: .bss
Binding: STB_GLOBAL
Value: 0xFFFF000000E2651C
Size: 0x4

View File

@ -1,38 +0,0 @@
--- !ELF
FileHeader:
Class: ELFCLASS32
Data: ELFDATA2LSB
OSABI: ELFOSABI_FREEBSD
Type: ET_EXEC
Machine: EM_386
Entry: 0x8F9000
Sections:
- Name: .bss
Type: SHT_NOBITS
Flags: [ SHF_WRITE, SHF_ALLOC ]
Address: 0x1AB7B00
AddressAlign: 0x80
Offset: 0x12B7AB0
Size: 0x2D48D8
Symbols:
- Name: kernbase
Index: SHN_ABS
Binding: STB_GLOBAL
Value: 0x800000
- Name: dumppcb
Type: STT_OBJECT
Section: .bss
Value: 0x1D2D9A0
Size: 0xC0
- Name: hz
Type: STT_OBJECT
Section: .bss
Binding: STB_GLOBAL
Value: 0x1D4053C
Size: 0x4
- Name: IdlePDPT
Type: STT_OBJECT
Section: .bss
Binding: STB_GLOBAL
Value: 0x1D8B044
Size: 0x4

View File

@ -1,36 +0,0 @@
How to create vmcores for tests
===============================
1. Boot a FreeBSD VM with as little memory as possible and create a core dump
per `FreeBSD Handbook Kernel Debugging Chapter`_. Note that you may need to
reboot with more memory after the kernel panic as otherwise savecore(8) may
fail.
For instance, I was able to boot FreeBSD and qemu-system-x86_64 with 128 MiB
RAM but had to increase it to 256 MiB for the boot after kernel panic.
2. Transfer the kernel image (``/boot/kernel/kernel``) and vmcore
(``/var/crash/vmcore.latest``) from the VM.
3. Patch libfbsdvmcore using ``libfbsdvmcore-print-offsets.patch`` and build
LLDB against the patched library.
4. Do a test run of ``test.script`` in LLDB against the kernel + vmcore::
lldb -b -s test.script --core /path/to/core /path/to/kernel
If everything works fine, the LLDB output should be interspersed with
``%RD`` lines.
5. Use the ``copy-sparse.py`` tool to create a sparse version of the vmcore::
lldb -b -s test.script --core /path/to/core /path/to/kernel |
grep '^% RD' | python copy-sparse.py /path/to/core vmcore.sparse
6. Compress the sparse vmcore file using ``bzip2``::
bzip2 -9 vmcore.sparse
.. _FreeBSD Handbook Kernel Debugging Chapter:
https://docs.freebsd.org/en/books/developers-handbook/kerneldebug/

View File

@ -1,34 +0,0 @@
#!/usr/bin/env python
import argparse
import re
import sys
def main():
argp = argparse.ArgumentParser()
argp.add_argument('infile', type=argparse.FileType('rb'),
help='Input vmcore file')
argp.add_argument('outfile', type=argparse.FileType('wb'),
help='Output vmcore file')
args = argp.parse_args()
inf = args.infile
outf = args.outfile
line_re = re.compile(r"^% RD: (\d+) (\d+)")
# copy the first chunk that usually includes ELF headers
# (not output by patched libfbsdvmcore since libelf reads this)
outf.write(inf.read(1024))
for l in sys.stdin:
m = line_re.match(l)
offset, size = [int(x) for x in m.groups()]
inf.seek(offset)
outf.seek(offset)
outf.write(inf.read(size))
if __name__ == "__main__":
main()

View File

@ -1,166 +0,0 @@
diff --git a/lib/fvc.c b/lib/fvc.c
index e6b96c1..4033f78 100644
--- a/lib/fvc.c
+++ b/lib/fvc.c
@@ -297,6 +297,7 @@ fvc_read(fvc_t *kd, fvc_addr_t kva, void *buf, size_t len)
_fvc_syserr(kd, kd->program, "fvc_read");
break;
}
+ printf("%% RD: %zu %d\n", pa, cc);
/*
* If ka_kvatop returns a bogus value or our core file is
* truncated, we might wind up seeking beyond the end of the
@@ -331,3 +332,8 @@ fvc_kerndisp(fvc_t *kd)
return (kd->arch->ka_kerndisp(kd));
}
+
+ssize_t xpread(int fd, void *buf, size_t count, off_t offset) {
+ printf("%% RD: %zu %zu\n", offset, count);
+ return pread(fd, buf, count, offset);
+}
diff --git a/lib/fvc.h b/lib/fvc.h
index 8680079..ff1e0f0 100644
--- a/lib/fvc.h
+++ b/lib/fvc.h
@@ -54,6 +54,8 @@ typedef unsigned char fvc_vm_prot_t;
#define FVC_VM_PROT_WRITE ((fvc_vm_prot_t) 0x02)
#define FVC_VM_PROT_EXECUTE ((fvc_vm_prot_t) 0x04)
+ssize_t xpread(int fd, void *buf, size_t count, off_t offset);
+
struct fvc_page {
unsigned int kp_version;
fvc_addr_t kp_paddr;
diff --git a/lib/fvc_amd64.c b/lib/fvc_amd64.c
index 4d27998..69f1807 100644
--- a/lib/fvc_amd64.c
+++ b/lib/fvc_amd64.c
@@ -205,7 +205,7 @@ _amd64_vatop(fvc_t *kd, fvc_addr_t va, off_t *pa)
_fvc_err(kd, kd->program, "_amd64_vatop: pdpe_pa not found");
goto invalid;
}
- if (pread(kd->pmfd, &pdpe, sizeof(pdpe), ofs) != sizeof(pdpe)) {
+ if (xpread(kd->pmfd, &pdpe, sizeof(pdpe), ofs) != sizeof(pdpe)) {
_fvc_syserr(kd, kd->program, "_amd64_vatop: read pdpe");
goto invalid;
}
@@ -237,7 +237,7 @@ _amd64_vatop(fvc_t *kd, fvc_addr_t va, off_t *pa)
_fvc_syserr(kd, kd->program, "_amd64_vatop: pde_pa not found");
goto invalid;
}
- if (pread(kd->pmfd, &pde, sizeof(pde), ofs) != sizeof(pde)) {
+ if (xpread(kd->pmfd, &pde, sizeof(pde), ofs) != sizeof(pde)) {
_fvc_syserr(kd, kd->program, "_amd64_vatop: read pde");
goto invalid;
}
@@ -269,7 +269,7 @@ _amd64_vatop(fvc_t *kd, fvc_addr_t va, off_t *pa)
_fvc_err(kd, kd->program, "_amd64_vatop: pte_pa not found");
goto invalid;
}
- if (pread(kd->pmfd, &pte, sizeof(pte), ofs) != sizeof(pte)) {
+ if (xpread(kd->pmfd, &pte, sizeof(pte), ofs) != sizeof(pte)) {
_fvc_syserr(kd, kd->program, "_amd64_vatop: read");
goto invalid;
}
diff --git a/lib/fvc_minidump_aarch64.c b/lib/fvc_minidump_aarch64.c
index 4b8477a..a1c5b42 100644
--- a/lib/fvc_minidump_aarch64.c
+++ b/lib/fvc_minidump_aarch64.c
@@ -86,7 +86,7 @@ _aarch64_minidump_initvtop(fvc_t *kd)
return (-1);
}
kd->vmst = vmst;
- if (pread(kd->pmfd, &vmst->hdr, sizeof(vmst->hdr), 0) !=
+ if (xpread(kd->pmfd, &vmst->hdr, sizeof(vmst->hdr), 0) !=
sizeof(vmst->hdr)) {
_fvc_err(kd, kd->program, "cannot read dump header");
return (-1);
diff --git a/lib/fvc_minidump_amd64.c b/lib/fvc_minidump_amd64.c
index 93e8238..0d2237f 100644
--- a/lib/fvc_minidump_amd64.c
+++ b/lib/fvc_minidump_amd64.c
@@ -126,7 +126,7 @@ _amd64_minidump_initvtop(fvc_t *kd)
return (-1);
}
kd->vmst = vmst;
- if (pread(kd->pmfd, &vmst->hdr, sizeof(vmst->hdr), 0) !=
+ if (xpread(kd->pmfd, &vmst->hdr, sizeof(vmst->hdr), 0) !=
sizeof(vmst->hdr)) {
_fvc_err(kd, kd->program, "cannot read dump header");
return (-1);
@@ -269,7 +269,7 @@ _amd64_minidump_vatop(fvc_t *kd, fvc_addr_t va, off_t *pa)
(uintmax_t)a);
goto invalid;
}
- if (pread(kd->pmfd, &pt, AMD64_PAGE_SIZE, ofs) !=
+ if (xpread(kd->pmfd, &pt, AMD64_PAGE_SIZE, ofs) !=
AMD64_PAGE_SIZE) {
_fvc_err(kd, kd->program,
"cannot read page table entry for %ju",
diff --git a/lib/fvc_minidump_i386.c b/lib/fvc_minidump_i386.c
index 61cc3db..b3ab955 100644
--- a/lib/fvc_minidump_i386.c
+++ b/lib/fvc_minidump_i386.c
@@ -94,7 +94,7 @@ _i386_minidump_initvtop(fvc_t *kd)
return (-1);
}
kd->vmst = vmst;
- if (pread(kd->pmfd, &vmst->hdr, sizeof(vmst->hdr), 0) !=
+ if (xpread(kd->pmfd, &vmst->hdr, sizeof(vmst->hdr), 0) !=
sizeof(vmst->hdr)) {
_fvc_err(kd, kd->program, "cannot read dump header");
return (-1);
diff --git a/lib/fvc_private.c b/lib/fvc_private.c
index 0069a54..fc798fe 100644
--- a/lib/fvc_private.c
+++ b/lib/fvc_private.c
@@ -130,7 +130,7 @@ _fvc_is_minidump(fvc_t *kd)
{
char minihdr[8];
- if (pread(kd->pmfd, &minihdr, 8, 0) == 8 &&
+ if (xpread(kd->pmfd, &minihdr, 8, 0) == 8 &&
memcmp(&minihdr, "minidump", 8) == 0)
return (1);
return (0);
@@ -256,6 +256,7 @@ _fvc_pmap_get(fvc_t *kd, u_long idx, size_t len)
if ((off_t)off >= kd->pt_sparse_off)
return (NULL);
+ printf("%% RD: %zu %zu\n", kd->page_map_off+off, len);
return (void *)((uintptr_t)kd->page_map + off);
}
@@ -270,8 +271,13 @@ _fvc_map_get(fvc_t *kd, u_long pa, unsigned int page_size)
return NULL;
addr = (uintptr_t)kd->page_map + off;
- if (off >= kd->pt_sparse_off)
+ if (off >= kd->pt_sparse_off) {
+
addr = (uintptr_t)kd->sparse_map + (off - kd->pt_sparse_off);
+ printf("%% RD: %zu %u\n", off, page_size);
+ }
+ else
+ printf("%% RD: %zu %u\n", kd->page_map_off+off, page_size);
return (void *)addr;
}
@@ -289,6 +295,7 @@ _fvc_pt_init(fvc_t *kd, size_t dump_avail_size, off_t dump_avail_off,
if (dump_avail_size > 0) {
kd->dump_avail = mmap(NULL, kd->dump_avail_size, PROT_READ,
MAP_PRIVATE, kd->pmfd, dump_avail_off);
+ printf("%% RD: %zu %zu\n", dump_avail_off, dump_avail_size);
} else {
/*
* Older version minidumps don't provide dump_avail[],
@@ -309,7 +316,7 @@ _fvc_pt_init(fvc_t *kd, size_t dump_avail_size, off_t dump_avail_off,
map_len);
return (-1);
}
- rd = pread(kd->pmfd, kd->pt_map, map_len, map_off);
+ rd = xpread(kd->pmfd, kd->pt_map, map_len, map_off);
if (rd < 0 || rd != (ssize_t)map_len) {
_fvc_err(kd, kd->program, "cannot read %zu bytes for bitmap",
map_len);

View File

@ -1,5 +0,0 @@
thread list
register read pc
bt
p *(int*)&hz
memory read &hz