
The implemtation support parsing kernel module for FreeBSD Kernel and has been test on x86-64 and arm64. In summary, this class parse the linked list resides in the kernel memory that record all kernel module and load the debug symbol file to facilitate debug process
172 lines
5.1 KiB
C++
172 lines
5.1 KiB
C++
//===-- DynamicLoaderFreeBSDKernel.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_DYNAMICLOADER_FREEBSD_KERNEL_DYNAMICLOADERFREEBSDKERNEL_H
|
|
#define LLDB_SOURCE_PLUGINS_DYNAMICLOADER_FREEBSD_KERNEL_DYNAMICLOADERFREEBSDKERNEL_H
|
|
|
|
#include <mutex>
|
|
#include <string>
|
|
#include <vector>
|
|
|
|
#include "lldb/Target/DynamicLoader.h"
|
|
#include "lldb/Target/Process.h"
|
|
#include "lldb/Utility/FileSpec.h"
|
|
#include "lldb/Utility/UUID.h"
|
|
#include "llvm/BinaryFormat/ELF.h"
|
|
|
|
class DynamicLoaderFreeBSDKernel : public lldb_private::DynamicLoader {
|
|
public:
|
|
DynamicLoaderFreeBSDKernel(lldb_private::Process *process,
|
|
lldb::addr_t kernel_addr);
|
|
|
|
~DynamicLoaderFreeBSDKernel() override;
|
|
|
|
// Static Functions
|
|
|
|
static void Initialize();
|
|
|
|
static void Terminate();
|
|
|
|
static llvm::StringRef GetPluginNameStatic() { return "freebsd-kernel"; }
|
|
|
|
static llvm::StringRef GetPluginDescriptionStatic();
|
|
|
|
static lldb_private::DynamicLoader *
|
|
CreateInstance(lldb_private::Process *process, bool force);
|
|
|
|
static void DebuggerInit(lldb_private::Debugger &debugger);
|
|
|
|
static lldb::addr_t FindFreeBSDKernel(lldb_private::Process *process);
|
|
|
|
// Hooks for time point that after attach to some proccess
|
|
void DidAttach() override;
|
|
|
|
void DidLaunch() override;
|
|
|
|
lldb::ThreadPlanSP GetStepThroughTrampolinePlan(lldb_private::Thread &thread,
|
|
bool stop_others) override;
|
|
|
|
lldb_private::Status CanLoadImage() override;
|
|
|
|
llvm::StringRef GetPluginName() override { return GetPluginNameStatic(); }
|
|
|
|
protected:
|
|
class KModImageInfo {
|
|
public:
|
|
KModImageInfo()
|
|
: m_module_sp(), m_memory_module_sp(), m_uuid(), m_name(), m_path() {}
|
|
|
|
void Clear() {
|
|
m_load_address = LLDB_INVALID_ADDRESS;
|
|
m_name.clear();
|
|
m_uuid.Clear();
|
|
m_module_sp.reset();
|
|
m_memory_module_sp.reset();
|
|
m_stop_id = UINT32_MAX;
|
|
m_path.clear();
|
|
}
|
|
|
|
void SetLoadAddress(lldb::addr_t load_address) {
|
|
m_load_address = load_address;
|
|
}
|
|
|
|
lldb::addr_t GetLoadAddress() const { return m_load_address; }
|
|
|
|
void SetUUID(const lldb_private::UUID uuid) { m_uuid = uuid; }
|
|
|
|
lldb_private::UUID GetUUID() const { return m_uuid; }
|
|
|
|
void SetName(const char *name) { m_name = name; }
|
|
|
|
std::string GetName() const { return m_name; }
|
|
|
|
void SetPath(const char *path) { m_path = path; }
|
|
|
|
std::string GetPath() const { return m_path; }
|
|
|
|
void SetModule(lldb::ModuleSP module) { m_module_sp = module; }
|
|
|
|
lldb::ModuleSP GetModule() { return m_module_sp; }
|
|
|
|
void SetIsKernel(bool is_kernel) { m_is_kernel = is_kernel; }
|
|
|
|
bool IsKernel() const { return m_is_kernel; };
|
|
|
|
void SetStopID(uint32_t stop_id) { m_stop_id = stop_id; }
|
|
|
|
uint32_t GetStopID() { return m_stop_id; }
|
|
|
|
bool IsLoaded() const { return m_stop_id != UINT32_MAX; };
|
|
|
|
bool ReadMemoryModule(lldb_private::Process *process);
|
|
|
|
bool LoadImageUsingMemoryModule(lldb_private::Process *process);
|
|
|
|
bool LoadImageUsingFileAddress(lldb_private::Process *process);
|
|
|
|
using collection_type = std::vector<KModImageInfo>;
|
|
|
|
private:
|
|
lldb::ModuleSP m_module_sp;
|
|
lldb::ModuleSP m_memory_module_sp;
|
|
lldb::addr_t m_load_address = LLDB_INVALID_ADDRESS;
|
|
lldb_private::UUID m_uuid;
|
|
bool m_is_kernel = false;
|
|
std::string m_name;
|
|
std::string m_path;
|
|
uint32_t m_stop_id = UINT32_MAX;
|
|
};
|
|
|
|
void PrivateInitialize(lldb_private::Process *process);
|
|
|
|
void Clear(bool clear_process);
|
|
|
|
void Update();
|
|
|
|
void LoadKernelModules();
|
|
|
|
void ReadAllKmods();
|
|
|
|
bool ReadAllKmods(lldb_private::Address linker_files_head_address,
|
|
KModImageInfo::collection_type &kmods_list);
|
|
|
|
bool ReadKmodsListHeader();
|
|
|
|
bool ParseKmods(lldb_private::Address linker_files_head_address);
|
|
|
|
void SetNotificationBreakPoint();
|
|
|
|
static lldb_private::UUID
|
|
CheckForKernelImageAtAddress(lldb_private::Process *process,
|
|
lldb::addr_t address,
|
|
bool *read_error = nullptr);
|
|
|
|
static lldb::addr_t FindKernelAtLoadAddress(lldb_private::Process *process);
|
|
|
|
static bool ReadELFHeader(lldb_private::Process *process,
|
|
lldb::addr_t address, llvm::ELF::Elf32_Ehdr &header,
|
|
bool *read_error = nullptr);
|
|
|
|
lldb_private::Process *m_process;
|
|
lldb_private::Address m_linker_file_list_struct_addr;
|
|
lldb_private::Address m_linker_file_head_addr;
|
|
lldb::addr_t m_kernel_load_address;
|
|
KModImageInfo m_kernel_image_info;
|
|
KModImageInfo::collection_type m_linker_files_list;
|
|
std::recursive_mutex m_mutex;
|
|
std::unordered_map<std::string, lldb_private::UUID> m_kld_name_to_uuid;
|
|
|
|
private:
|
|
DynamicLoaderFreeBSDKernel(const DynamicLoaderFreeBSDKernel &) = delete;
|
|
|
|
const DynamicLoaderFreeBSDKernel &
|
|
operator=(const DynamicLoaderFreeBSDKernel &) = delete;
|
|
};
|
|
|
|
#endif
|