From aedb328a4dc9cb48ee3cf3198281649ea2c4f532 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20G=C3=B3rny?= Date: Wed, 1 Dec 2021 23:04:59 +0100 Subject: [lldb] Introduce a FreeBSDKernel plugin for vmcores Introduce a FreeBSDKernel plugin that provides the ability to read FreeBSD kernel core dumps. The plugin utilizes libfbsdvmcore to provide support for both "full memory dump" and minidump formats across variety of architectures supported by FreeBSD. It provides the ability to read kernel memory, as well as the crashed thread status with registers on arm64, i386 and x86_64. Differential Revision: https://reviews.llvm.org/D114911 --- lldb/cmake/modules/LLDBConfig.cmake | 1 + lldb/packages/Python/lldbsuite/test/lldbtest.py | 4 +- lldb/source/Plugins/Process/CMakeLists.txt | 1 + .../Plugins/Process/FreeBSDKernel/CMakeLists.txt | 19 +++ .../Process/FreeBSDKernel/ProcessFreeBSDKernel.cpp | 126 ++++++++++++++++ .../Process/FreeBSDKernel/ProcessFreeBSDKernel.h | 60 ++++++++ .../RegisterContextFreeBSDKernel_arm64.cpp | 110 ++++++++++++++ .../RegisterContextFreeBSDKernel_arm64.h | 41 +++++ .../RegisterContextFreeBSDKernel_i386.cpp | 83 +++++++++++ .../RegisterContextFreeBSDKernel_i386.h | 41 +++++ .../RegisterContextFreeBSDKernel_x86_64.cpp | 88 +++++++++++ .../RegisterContextFreeBSDKernel_x86_64.h | 41 +++++ .../Process/FreeBSDKernel/ThreadFreeBSDKernel.cpp | 85 +++++++++++ .../Process/FreeBSDKernel/ThreadFreeBSDKernel.h | 36 +++++ .../FreeBSDKernel/TestFreeBSDKernelVMCore.py | 153 +++++++++++++++++++ .../postmortem/FreeBSDKernel/kernel-amd64.yaml | 38 +++++ .../postmortem/FreeBSDKernel/kernel-arm64.yaml | 30 ++++ .../postmortem/FreeBSDKernel/kernel-i386.yaml | 38 +++++ .../postmortem/FreeBSDKernel/tools/README.rst | 36 +++++ .../postmortem/FreeBSDKernel/tools/copy-sparse.py | 34 +++++ .../tools/libfbsdvmcore-print-offsets.patch | 166 +++++++++++++++++++++ .../postmortem/FreeBSDKernel/tools/test.script | 5 + .../postmortem/FreeBSDKernel/vmcore-amd64-full.bz2 | Bin 0 -> 4651 bytes .../FreeBSDKernel/vmcore-amd64-minidump.bz2 | Bin 0 -> 7028 bytes .../FreeBSDKernel/vmcore-arm64-minidump.bz2 | Bin 0 -> 3505 bytes .../FreeBSDKernel/vmcore-i386-minidump.bz2 | Bin 0 -> 5799 bytes 26 files changed, 1235 insertions(+), 1 deletion(-) create mode 100644 lldb/source/Plugins/Process/FreeBSDKernel/CMakeLists.txt create mode 100644 lldb/source/Plugins/Process/FreeBSDKernel/ProcessFreeBSDKernel.cpp create mode 100644 lldb/source/Plugins/Process/FreeBSDKernel/ProcessFreeBSDKernel.h create mode 100644 lldb/source/Plugins/Process/FreeBSDKernel/RegisterContextFreeBSDKernel_arm64.cpp create mode 100644 lldb/source/Plugins/Process/FreeBSDKernel/RegisterContextFreeBSDKernel_arm64.h create mode 100644 lldb/source/Plugins/Process/FreeBSDKernel/RegisterContextFreeBSDKernel_i386.cpp create mode 100644 lldb/source/Plugins/Process/FreeBSDKernel/RegisterContextFreeBSDKernel_i386.h create mode 100644 lldb/source/Plugins/Process/FreeBSDKernel/RegisterContextFreeBSDKernel_x86_64.cpp create mode 100644 lldb/source/Plugins/Process/FreeBSDKernel/RegisterContextFreeBSDKernel_x86_64.h create mode 100644 lldb/source/Plugins/Process/FreeBSDKernel/ThreadFreeBSDKernel.cpp create mode 100644 lldb/source/Plugins/Process/FreeBSDKernel/ThreadFreeBSDKernel.h create mode 100644 lldb/test/API/functionalities/postmortem/FreeBSDKernel/TestFreeBSDKernelVMCore.py create mode 100644 lldb/test/API/functionalities/postmortem/FreeBSDKernel/kernel-amd64.yaml create mode 100644 lldb/test/API/functionalities/postmortem/FreeBSDKernel/kernel-arm64.yaml create mode 100644 lldb/test/API/functionalities/postmortem/FreeBSDKernel/kernel-i386.yaml create mode 100644 lldb/test/API/functionalities/postmortem/FreeBSDKernel/tools/README.rst create mode 100644 lldb/test/API/functionalities/postmortem/FreeBSDKernel/tools/copy-sparse.py create mode 100644 lldb/test/API/functionalities/postmortem/FreeBSDKernel/tools/libfbsdvmcore-print-offsets.patch create mode 100644 lldb/test/API/functionalities/postmortem/FreeBSDKernel/tools/test.script create mode 100644 lldb/test/API/functionalities/postmortem/FreeBSDKernel/vmcore-amd64-full.bz2 create mode 100644 lldb/test/API/functionalities/postmortem/FreeBSDKernel/vmcore-amd64-minidump.bz2 create mode 100644 lldb/test/API/functionalities/postmortem/FreeBSDKernel/vmcore-arm64-minidump.bz2 create mode 100644 lldb/test/API/functionalities/postmortem/FreeBSDKernel/vmcore-i386-minidump.bz2 diff --git a/lldb/cmake/modules/LLDBConfig.cmake b/lldb/cmake/modules/LLDBConfig.cmake index b62cd7d24438..5ddac2716ee5 100644 --- a/lldb/cmake/modules/LLDBConfig.cmake +++ b/lldb/cmake/modules/LLDBConfig.cmake @@ -58,6 +58,7 @@ 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) diff --git a/lldb/packages/Python/lldbsuite/test/lldbtest.py b/lldb/packages/Python/lldbsuite/test/lldbtest.py index 924e1fed4f38..605ba251e73f 100644 --- a/lldb/packages/Python/lldbsuite/test/lldbtest.py +++ b/lldb/packages/Python/lldbsuite/test/lldbtest.py @@ -1570,7 +1570,7 @@ class Base(unittest2.TestCase): return os.environ["CC"] - def yaml2obj(self, yaml_path, obj_path): + def yaml2obj(self, yaml_path, obj_path, max_size=None): """ Create an object file at the given path from a yaml file. @@ -1580,6 +1580,8 @@ 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( diff --git a/lldb/source/Plugins/Process/CMakeLists.txt b/lldb/source/Plugins/Process/CMakeLists.txt index bea5bac9eb21..a51d0f7afd17 100644 --- a/lldb/source/Plugins/Process/CMakeLists.txt +++ b/lldb/source/Plugins/Process/CMakeLists.txt @@ -18,3 +18,4 @@ add_subdirectory(Utility) add_subdirectory(elf-core) add_subdirectory(mach-core) add_subdirectory(minidump) +add_subdirectory(FreeBSDKernel) diff --git a/lldb/source/Plugins/Process/FreeBSDKernel/CMakeLists.txt b/lldb/source/Plugins/Process/FreeBSDKernel/CMakeLists.txt new file mode 100644 index 000000000000..ad388ee76b07 --- /dev/null +++ b/lldb/source/Plugins/Process/FreeBSDKernel/CMakeLists.txt @@ -0,0 +1,19 @@ +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 + ) diff --git a/lldb/source/Plugins/Process/FreeBSDKernel/ProcessFreeBSDKernel.cpp b/lldb/source/Plugins/Process/FreeBSDKernel/ProcessFreeBSDKernel.cpp new file mode 100644 index 000000000000..327e25acd589 --- /dev/null +++ b/lldb/source/Plugins/Process/FreeBSDKernel/ProcessFreeBSDKernel.cpp @@ -0,0 +1,126 @@ +//===-- 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 + +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(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( + 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(m_fvc), addr, buf, size); + if (rd < 0 || static_cast(rd) != size) { + error.SetErrorStringWithFormat("Reading memory failed: %s", + fvc_geterr(static_cast(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(); +} diff --git a/lldb/source/Plugins/Process/FreeBSDKernel/ProcessFreeBSDKernel.h b/lldb/source/Plugins/Process/FreeBSDKernel/ProcessFreeBSDKernel.h new file mode 100644 index 000000000000..cd10728463b5 --- /dev/null +++ b/lldb/source/Plugins/Process/FreeBSDKernel/ProcessFreeBSDKernel.h @@ -0,0 +1,60 @@ +//===-- 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 diff --git a/lldb/source/Plugins/Process/FreeBSDKernel/RegisterContextFreeBSDKernel_arm64.cpp b/lldb/source/Plugins/Process/FreeBSDKernel/RegisterContextFreeBSDKernel_arm64.cpp new file mode 100644 index 000000000000..11843ddc82d9 --- /dev/null +++ b/lldb/source/Plugins/Process/FreeBSDKernel/RegisterContextFreeBSDKernel_arm64.cpp @@ -0,0 +1,110 @@ +//===-- 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 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; +} diff --git a/lldb/source/Plugins/Process/FreeBSDKernel/RegisterContextFreeBSDKernel_arm64.h b/lldb/source/Plugins/Process/FreeBSDKernel/RegisterContextFreeBSDKernel_arm64.h new file mode 100644 index 000000000000..155dda6e748f --- /dev/null +++ b/lldb/source/Plugins/Process/FreeBSDKernel/RegisterContextFreeBSDKernel_arm64.h @@ -0,0 +1,41 @@ +//===-- 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 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 diff --git a/lldb/source/Plugins/Process/FreeBSDKernel/RegisterContextFreeBSDKernel_i386.cpp b/lldb/source/Plugins/Process/FreeBSDKernel/RegisterContextFreeBSDKernel_i386.cpp new file mode 100644 index 000000000000..fde85c9c9f0d --- /dev/null +++ b/lldb/source/Plugins/Process/FreeBSDKernel/RegisterContextFreeBSDKernel_i386.cpp @@ -0,0 +1,83 @@ +//===-- 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; +} diff --git a/lldb/source/Plugins/Process/FreeBSDKernel/RegisterContextFreeBSDKernel_i386.h b/lldb/source/Plugins/Process/FreeBSDKernel/RegisterContextFreeBSDKernel_i386.h new file mode 100644 index 000000000000..218e3374f8df --- /dev/null +++ b/lldb/source/Plugins/Process/FreeBSDKernel/RegisterContextFreeBSDKernel_i386.h @@ -0,0 +1,41 @@ +//===-- 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 diff --git a/lldb/source/Plugins/Process/FreeBSDKernel/RegisterContextFreeBSDKernel_x86_64.cpp b/lldb/source/Plugins/Process/FreeBSDKernel/RegisterContextFreeBSDKernel_x86_64.cpp new file mode 100644 index 000000000000..ff57842e345c --- /dev/null +++ b/lldb/source/Plugins/Process/FreeBSDKernel/RegisterContextFreeBSDKernel_x86_64.cpp @@ -0,0 +1,88 @@ +//===-- 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; +} diff --git a/lldb/source/Plugins/Process/FreeBSDKernel/RegisterContextFreeBSDKernel_x86_64.h b/lldb/source/Plugins/Process/FreeBSDKernel/RegisterContextFreeBSDKernel_x86_64.h new file mode 100644 index 000000000000..9a2ac638dfea --- /dev/null +++ b/lldb/source/Plugins/Process/FreeBSDKernel/RegisterContextFreeBSDKernel_x86_64.h @@ -0,0 +1,41 @@ +//===-- 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 diff --git a/lldb/source/Plugins/Process/FreeBSDKernel/ThreadFreeBSDKernel.cpp b/lldb/source/Plugins/Process/FreeBSDKernel/ThreadFreeBSDKernel.cpp new file mode 100644 index 000000000000..124c65d587ff --- /dev/null +++ b/lldb/source/Plugins/Process/FreeBSDKernel/ThreadFreeBSDKernel.cpp @@ -0,0 +1,85 @@ +//===-- 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(GetProcess().get()); + ArchSpec arch = process->GetTarget().GetArchitecture(); + + switch (arch.GetMachine()) { + case llvm::Triple::aarch64: + m_thread_reg_ctx_sp = + std::make_shared( + *this, std::make_unique(arch, 0), + m_pcb_addr); + break; + case llvm::Triple::x86: + m_thread_reg_ctx_sp = + std::make_shared( + *this, new RegisterContextFreeBSD_i386(arch), m_pcb_addr); + break; + case llvm::Triple::x86_64: + m_thread_reg_ctx_sp = + std::make_shared( + *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; } diff --git a/lldb/source/Plugins/Process/FreeBSDKernel/ThreadFreeBSDKernel.h b/lldb/source/Plugins/Process/FreeBSDKernel/ThreadFreeBSDKernel.h new file mode 100644 index 000000000000..2842eba64e56 --- /dev/null +++ b/lldb/source/Plugins/Process/FreeBSDKernel/ThreadFreeBSDKernel.h @@ -0,0 +1,36 @@ +//===-- 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 diff --git a/lldb/test/API/functionalities/postmortem/FreeBSDKernel/TestFreeBSDKernelVMCore.py b/lldb/test/API/functionalities/postmortem/FreeBSDKernel/TestFreeBSDKernelVMCore.py new file mode 100644 index 000000000000..6073b508a436 --- /dev/null +++ b/lldb/test/API/functionalities/postmortem/FreeBSDKernel/TestFreeBSDKernelVMCore.py @@ -0,0 +1,153 @@ +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("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); diff --git a/lldb/test/API/functionalities/postmortem/FreeBSDKernel/tools/test.script b/lldb/test/API/functionalities/postmortem/FreeBSDKernel/tools/test.script new file mode 100644 index 000000000000..5580c3757cc5 --- /dev/null +++ b/lldb/test/API/functionalities/postmortem/FreeBSDKernel/tools/test.script @@ -0,0 +1,5 @@ +thread list +register read pc +bt +p *(int*)&hz +memory read &hz diff --git a/lldb/test/API/functionalities/postmortem/FreeBSDKernel/vmcore-amd64-full.bz2 b/lldb/test/API/functionalities/postmortem/FreeBSDKernel/vmcore-amd64-full.bz2 new file mode 100644 index 000000000000..34b368616ff0 Binary files /dev/null and b/lldb/test/API/functionalities/postmortem/FreeBSDKernel/vmcore-amd64-full.bz2 differ diff --git a/lldb/test/API/functionalities/postmortem/FreeBSDKernel/vmcore-amd64-minidump.bz2 b/lldb/test/API/functionalities/postmortem/FreeBSDKernel/vmcore-amd64-minidump.bz2 new file mode 100644 index 000000000000..b99ff797b683 Binary files /dev/null and b/lldb/test/API/functionalities/postmortem/FreeBSDKernel/vmcore-amd64-minidump.bz2 differ diff --git a/lldb/test/API/functionalities/postmortem/FreeBSDKernel/vmcore-arm64-minidump.bz2 b/lldb/test/API/functionalities/postmortem/FreeBSDKernel/vmcore-arm64-minidump.bz2 new file mode 100644 index 000000000000..73770dfb563e Binary files /dev/null and b/lldb/test/API/functionalities/postmortem/FreeBSDKernel/vmcore-arm64-minidump.bz2 differ diff --git a/lldb/test/API/functionalities/postmortem/FreeBSDKernel/vmcore-i386-minidump.bz2 b/lldb/test/API/functionalities/postmortem/FreeBSDKernel/vmcore-i386-minidump.bz2 new file mode 100644 index 000000000000..af373a1bb6aa Binary files /dev/null and b/lldb/test/API/functionalities/postmortem/FreeBSDKernel/vmcore-i386-minidump.bz2 differ -- cgit v1.2.1