15f757f3fSDimitry Andric //===-- DynamicLoaderFreeBSDKernel.cpp
25f757f3fSDimitry Andric //------------------------------------------===//
35f757f3fSDimitry Andric //
45f757f3fSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
55f757f3fSDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
65f757f3fSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
75f757f3fSDimitry Andric //
85f757f3fSDimitry Andric //===----------------------------------------------------------------------===//
95f757f3fSDimitry Andric 
105f757f3fSDimitry Andric #include "lldb/Breakpoint/StoppointCallbackContext.h"
115f757f3fSDimitry Andric #include "lldb/Core/Debugger.h"
125f757f3fSDimitry Andric #include "lldb/Core/Module.h"
135f757f3fSDimitry Andric #include "lldb/Core/ModuleSpec.h"
145f757f3fSDimitry Andric #include "lldb/Core/PluginManager.h"
155f757f3fSDimitry Andric #include "lldb/Core/Section.h"
165f757f3fSDimitry Andric #include "lldb/Host/StreamFile.h"
175f757f3fSDimitry Andric #include "lldb/Interpreter/OptionValueProperties.h"
185f757f3fSDimitry Andric #include "lldb/Symbol/ObjectFile.h"
195f757f3fSDimitry Andric #include "lldb/Target/OperatingSystem.h"
205f757f3fSDimitry Andric #include "lldb/Target/RegisterContext.h"
215f757f3fSDimitry Andric #include "lldb/Target/StackFrame.h"
225f757f3fSDimitry Andric #include "lldb/Target/Target.h"
235f757f3fSDimitry Andric #include "lldb/Target/Thread.h"
245f757f3fSDimitry Andric #include "lldb/Target/ThreadPlanRunToAddress.h"
255f757f3fSDimitry Andric #include "lldb/Utility/DataBuffer.h"
265f757f3fSDimitry Andric #include "lldb/Utility/DataBufferHeap.h"
275f757f3fSDimitry Andric #include "lldb/Utility/LLDBLog.h"
285f757f3fSDimitry Andric #include "lldb/Utility/Log.h"
295f757f3fSDimitry Andric #include "lldb/Utility/State.h"
305f757f3fSDimitry Andric 
315f757f3fSDimitry Andric #include "Plugins/ObjectFile/ELF/ObjectFileELF.h"
325f757f3fSDimitry Andric 
335f757f3fSDimitry Andric #include "DynamicLoaderFreeBSDKernel.h"
345f757f3fSDimitry Andric #include <memory>
355f757f3fSDimitry Andric #include <mutex>
365f757f3fSDimitry Andric 
375f757f3fSDimitry Andric using namespace lldb;
385f757f3fSDimitry Andric using namespace lldb_private;
395f757f3fSDimitry Andric 
405f757f3fSDimitry Andric LLDB_PLUGIN_DEFINE(DynamicLoaderFreeBSDKernel)
415f757f3fSDimitry Andric 
425f757f3fSDimitry Andric void DynamicLoaderFreeBSDKernel::Initialize() {
435f757f3fSDimitry Andric   PluginManager::RegisterPlugin(GetPluginNameStatic(),
445f757f3fSDimitry Andric                                 GetPluginDescriptionStatic(), CreateInstance,
455f757f3fSDimitry Andric                                 DebuggerInit);
465f757f3fSDimitry Andric }
475f757f3fSDimitry Andric 
485f757f3fSDimitry Andric void DynamicLoaderFreeBSDKernel::Terminate() {
495f757f3fSDimitry Andric   PluginManager::UnregisterPlugin(CreateInstance);
505f757f3fSDimitry Andric }
515f757f3fSDimitry Andric 
525f757f3fSDimitry Andric llvm::StringRef DynamicLoaderFreeBSDKernel::GetPluginDescriptionStatic() {
535f757f3fSDimitry Andric   return "The Dynamic Loader Plugin For FreeBSD Kernel";
545f757f3fSDimitry Andric }
555f757f3fSDimitry Andric 
565f757f3fSDimitry Andric static bool is_kernel(Module *module) {
575f757f3fSDimitry Andric   if (!module)
585f757f3fSDimitry Andric     return false;
595f757f3fSDimitry Andric 
605f757f3fSDimitry Andric   ObjectFile *objfile = module->GetObjectFile();
615f757f3fSDimitry Andric   if (!objfile)
625f757f3fSDimitry Andric     return false;
635f757f3fSDimitry Andric   if (objfile->GetType() != ObjectFile::eTypeExecutable)
645f757f3fSDimitry Andric     return false;
655f757f3fSDimitry Andric   if (objfile->GetStrata() != ObjectFile::eStrataUnknown &&
665f757f3fSDimitry Andric       objfile->GetStrata() != ObjectFile::eStrataKernel)
675f757f3fSDimitry Andric     return false;
685f757f3fSDimitry Andric 
695f757f3fSDimitry Andric   return true;
705f757f3fSDimitry Andric }
715f757f3fSDimitry Andric 
725f757f3fSDimitry Andric static bool is_kmod(Module *module) {
735f757f3fSDimitry Andric   if (!module)
745f757f3fSDimitry Andric     return false;
755f757f3fSDimitry Andric   if (!module->GetObjectFile())
765f757f3fSDimitry Andric     return false;
775f757f3fSDimitry Andric   ObjectFile *objfile = module->GetObjectFile();
785f757f3fSDimitry Andric   if (objfile->GetType() != ObjectFile::eTypeObjectFile &&
795f757f3fSDimitry Andric       objfile->GetType() != ObjectFile::eTypeSharedLibrary)
805f757f3fSDimitry Andric     return false;
815f757f3fSDimitry Andric 
825f757f3fSDimitry Andric   return true;
835f757f3fSDimitry Andric }
845f757f3fSDimitry Andric 
855f757f3fSDimitry Andric static bool is_reloc(Module *module) {
865f757f3fSDimitry Andric   if (!module)
875f757f3fSDimitry Andric     return false;
885f757f3fSDimitry Andric   if (!module->GetObjectFile())
895f757f3fSDimitry Andric     return false;
905f757f3fSDimitry Andric   ObjectFile *objfile = module->GetObjectFile();
915f757f3fSDimitry Andric   if (objfile->GetType() != ObjectFile::eTypeObjectFile)
925f757f3fSDimitry Andric     return false;
935f757f3fSDimitry Andric 
945f757f3fSDimitry Andric   return true;
955f757f3fSDimitry Andric }
965f757f3fSDimitry Andric 
975f757f3fSDimitry Andric // Instantiate Function of the FreeBSD Kernel Dynamic Loader Plugin called when
985f757f3fSDimitry Andric // Register the Plugin
995f757f3fSDimitry Andric DynamicLoader *
1005f757f3fSDimitry Andric DynamicLoaderFreeBSDKernel::CreateInstance(lldb_private::Process *process,
1015f757f3fSDimitry Andric                                            bool force) {
1025f757f3fSDimitry Andric   // Check the environment when the plugin is not force loaded
1035f757f3fSDimitry Andric   Module *exec = process->GetTarget().GetExecutableModulePointer();
1045f757f3fSDimitry Andric   if (exec && !is_kernel(exec)) {
1055f757f3fSDimitry Andric     return nullptr;
1065f757f3fSDimitry Andric   }
1075f757f3fSDimitry Andric   if (!force) {
1085f757f3fSDimitry Andric     // Check if the target is kernel
1095f757f3fSDimitry Andric     const llvm::Triple &triple_ref =
1105f757f3fSDimitry Andric         process->GetTarget().GetArchitecture().GetTriple();
1115f757f3fSDimitry Andric     if (!triple_ref.isOSFreeBSD()) {
1125f757f3fSDimitry Andric       return nullptr;
1135f757f3fSDimitry Andric     }
1145f757f3fSDimitry Andric   }
1155f757f3fSDimitry Andric 
1165f757f3fSDimitry Andric   // At this point we have checked the target is a FreeBSD kernel and all we
1175f757f3fSDimitry Andric   // have to do is to find the kernel address
1185f757f3fSDimitry Andric   const addr_t kernel_address = FindFreeBSDKernel(process);
1195f757f3fSDimitry Andric 
1205f757f3fSDimitry Andric   if (CheckForKernelImageAtAddress(process, kernel_address).IsValid())
1215f757f3fSDimitry Andric     return new DynamicLoaderFreeBSDKernel(process, kernel_address);
1225f757f3fSDimitry Andric 
1235f757f3fSDimitry Andric   return nullptr;
1245f757f3fSDimitry Andric }
1255f757f3fSDimitry Andric 
1265f757f3fSDimitry Andric addr_t
1275f757f3fSDimitry Andric DynamicLoaderFreeBSDKernel::FindFreeBSDKernel(lldb_private::Process *process) {
1285f757f3fSDimitry Andric   addr_t kernel_addr = process->GetImageInfoAddress();
1295f757f3fSDimitry Andric   if (kernel_addr == LLDB_INVALID_ADDRESS)
1305f757f3fSDimitry Andric     kernel_addr = FindKernelAtLoadAddress(process);
1315f757f3fSDimitry Andric   return kernel_addr;
1325f757f3fSDimitry Andric }
1335f757f3fSDimitry Andric 
1345f757f3fSDimitry Andric // Get the kernel address if the kernel is not loaded with a slide
1355f757f3fSDimitry Andric addr_t DynamicLoaderFreeBSDKernel::FindKernelAtLoadAddress(
1365f757f3fSDimitry Andric     lldb_private::Process *process) {
1375f757f3fSDimitry Andric   Module *exe_module = process->GetTarget().GetExecutableModulePointer();
1385f757f3fSDimitry Andric 
1395f757f3fSDimitry Andric   if (!is_kernel(exe_module))
1405f757f3fSDimitry Andric     return LLDB_INVALID_ADDRESS;
1415f757f3fSDimitry Andric 
1425f757f3fSDimitry Andric   ObjectFile *exe_objfile = exe_module->GetObjectFile();
1435f757f3fSDimitry Andric 
1445f757f3fSDimitry Andric   if (!exe_objfile->GetBaseAddress().IsValid())
1455f757f3fSDimitry Andric     return LLDB_INVALID_ADDRESS;
1465f757f3fSDimitry Andric 
1475f757f3fSDimitry Andric   if (CheckForKernelImageAtAddress(
1485f757f3fSDimitry Andric           process, exe_objfile->GetBaseAddress().GetFileAddress())
1495f757f3fSDimitry Andric           .IsValid())
1505f757f3fSDimitry Andric     return exe_objfile->GetBaseAddress().GetFileAddress();
1515f757f3fSDimitry Andric 
1525f757f3fSDimitry Andric   return LLDB_INVALID_ADDRESS;
1535f757f3fSDimitry Andric }
1545f757f3fSDimitry Andric 
1555f757f3fSDimitry Andric // Read ELF header from memry and return
1565f757f3fSDimitry Andric bool DynamicLoaderFreeBSDKernel::ReadELFHeader(Process *process,
1575f757f3fSDimitry Andric                                                lldb::addr_t addr,
1585f757f3fSDimitry Andric                                                llvm::ELF::Elf32_Ehdr &header,
1595f757f3fSDimitry Andric                                                bool *read_error) {
1605f757f3fSDimitry Andric   Status error;
1615f757f3fSDimitry Andric   if (read_error)
1625f757f3fSDimitry Andric     *read_error = false;
1635f757f3fSDimitry Andric 
1645f757f3fSDimitry Andric   if (process->ReadMemory(addr, &header, sizeof(header), error) !=
1655f757f3fSDimitry Andric       sizeof(header)) {
1665f757f3fSDimitry Andric     if (read_error)
1675f757f3fSDimitry Andric       *read_error = true;
1685f757f3fSDimitry Andric     return false;
1695f757f3fSDimitry Andric   }
1705f757f3fSDimitry Andric 
1715f757f3fSDimitry Andric   if (!header.checkMagic())
1725f757f3fSDimitry Andric     return false;
1735f757f3fSDimitry Andric 
1745f757f3fSDimitry Andric   return true;
1755f757f3fSDimitry Andric }
1765f757f3fSDimitry Andric 
1775f757f3fSDimitry Andric // Check the correctness of Kernel and return UUID
1785f757f3fSDimitry Andric lldb_private::UUID DynamicLoaderFreeBSDKernel::CheckForKernelImageAtAddress(
1795f757f3fSDimitry Andric     Process *process, lldb::addr_t addr, bool *read_error) {
1805f757f3fSDimitry Andric   Log *log = GetLog(LLDBLog::DynamicLoader);
1815f757f3fSDimitry Andric 
1825f757f3fSDimitry Andric   if (addr == LLDB_INVALID_ADDRESS) {
1835f757f3fSDimitry Andric     if (read_error)
1845f757f3fSDimitry Andric       *read_error = true;
1855f757f3fSDimitry Andric     return UUID();
1865f757f3fSDimitry Andric   }
1875f757f3fSDimitry Andric 
1885f757f3fSDimitry Andric   LLDB_LOGF(log,
1895f757f3fSDimitry Andric             "DynamicLoaderFreeBSDKernel::CheckForKernelImageAtAddress: "
1905f757f3fSDimitry Andric             "looking for kernel binary at 0x%" PRIx64,
1915f757f3fSDimitry Andric             addr);
1925f757f3fSDimitry Andric 
1935f757f3fSDimitry Andric   llvm::ELF::Elf32_Ehdr header;
1945f757f3fSDimitry Andric   if (!ReadELFHeader(process, addr, header)) {
1955f757f3fSDimitry Andric     *read_error = true;
1965f757f3fSDimitry Andric     return UUID();
1975f757f3fSDimitry Andric   }
1985f757f3fSDimitry Andric 
1995f757f3fSDimitry Andric   // Check header type
2005f757f3fSDimitry Andric   if (header.e_type != llvm::ELF::ET_EXEC)
2015f757f3fSDimitry Andric     return UUID();
2025f757f3fSDimitry Andric 
2035f757f3fSDimitry Andric   ModuleSP memory_module_sp =
2045f757f3fSDimitry Andric       process->ReadModuleFromMemory(FileSpec("temp_freebsd_kernel"), addr);
2055f757f3fSDimitry Andric 
2065f757f3fSDimitry Andric   if (!memory_module_sp.get()) {
2075f757f3fSDimitry Andric     *read_error = true;
2085f757f3fSDimitry Andric     return UUID();
2095f757f3fSDimitry Andric   }
2105f757f3fSDimitry Andric 
2115f757f3fSDimitry Andric   ObjectFile *exe_objfile = memory_module_sp->GetObjectFile();
2125f757f3fSDimitry Andric   if (exe_objfile == nullptr) {
2135f757f3fSDimitry Andric     LLDB_LOGF(log,
2145f757f3fSDimitry Andric               "DynamicLoaderFreeBSDKernel::CheckForKernelImageAtAddress "
2155f757f3fSDimitry Andric               "found a binary at 0x%" PRIx64
2165f757f3fSDimitry Andric               " but could not create an object file from memory",
2175f757f3fSDimitry Andric               addr);
2185f757f3fSDimitry Andric     return UUID();
2195f757f3fSDimitry Andric   }
2205f757f3fSDimitry Andric 
2215f757f3fSDimitry Andric   // In here, I should check is_kernel for memory_module_sp
2225f757f3fSDimitry Andric   // However, the ReadModuleFromMemory reads wrong section so that this check
2235f757f3fSDimitry Andric   // will failed
2245f757f3fSDimitry Andric   ArchSpec kernel_arch(llvm::ELF::convertEMachineToArchName(header.e_machine));
2255f757f3fSDimitry Andric 
2265f757f3fSDimitry Andric   if (!process->GetTarget().GetArchitecture().IsCompatibleMatch(kernel_arch))
2275f757f3fSDimitry Andric     process->GetTarget().SetArchitecture(kernel_arch);
2285f757f3fSDimitry Andric 
2295f757f3fSDimitry Andric   std::string uuid_str;
2305f757f3fSDimitry Andric   if (memory_module_sp->GetUUID().IsValid()) {
2315f757f3fSDimitry Andric     uuid_str = "with UUID ";
2325f757f3fSDimitry Andric     uuid_str += memory_module_sp->GetUUID().GetAsString();
2335f757f3fSDimitry Andric   } else {
2345f757f3fSDimitry Andric     uuid_str = "and no LC_UUID found in load commands ";
2355f757f3fSDimitry Andric   }
2365f757f3fSDimitry Andric   LLDB_LOGF(log,
2375f757f3fSDimitry Andric             "DynamicLoaderFreeBSDKernel::CheckForKernelImageAtAddress: "
2385f757f3fSDimitry Andric             "kernel binary image found at 0x%" PRIx64 " with arch '%s' %s",
2395f757f3fSDimitry Andric             addr, kernel_arch.GetTriple().str().c_str(), uuid_str.c_str());
2405f757f3fSDimitry Andric 
2415f757f3fSDimitry Andric   return memory_module_sp->GetUUID();
2425f757f3fSDimitry Andric }
2435f757f3fSDimitry Andric 
2445f757f3fSDimitry Andric void DynamicLoaderFreeBSDKernel::DebuggerInit(
2455f757f3fSDimitry Andric     lldb_private::Debugger &debugger) {}
2465f757f3fSDimitry Andric 
2475f757f3fSDimitry Andric DynamicLoaderFreeBSDKernel::DynamicLoaderFreeBSDKernel(Process *process,
2485f757f3fSDimitry Andric                                                        addr_t kernel_address)
2495f757f3fSDimitry Andric     : DynamicLoader(process), m_process(process),
2505f757f3fSDimitry Andric       m_linker_file_list_struct_addr(LLDB_INVALID_ADDRESS),
2515f757f3fSDimitry Andric       m_linker_file_head_addr(LLDB_INVALID_ADDRESS),
2525f757f3fSDimitry Andric       m_kernel_load_address(kernel_address), m_mutex() {
2535f757f3fSDimitry Andric   process->SetCanRunCode(false);
2545f757f3fSDimitry Andric }
2555f757f3fSDimitry Andric 
2565f757f3fSDimitry Andric DynamicLoaderFreeBSDKernel::~DynamicLoaderFreeBSDKernel() { Clear(true); }
2575f757f3fSDimitry Andric 
2585f757f3fSDimitry Andric void DynamicLoaderFreeBSDKernel::Update() {
2595f757f3fSDimitry Andric   LoadKernelModules();
2605f757f3fSDimitry Andric   SetNotificationBreakPoint();
2615f757f3fSDimitry Andric }
2625f757f3fSDimitry Andric 
2635f757f3fSDimitry Andric // Create in memory Module at the load address
2645f757f3fSDimitry Andric bool DynamicLoaderFreeBSDKernel::KModImageInfo::ReadMemoryModule(
2655f757f3fSDimitry Andric     lldb_private::Process *process) {
2665f757f3fSDimitry Andric   Log *log = GetLog(LLDBLog::DynamicLoader);
2675f757f3fSDimitry Andric   if (m_memory_module_sp)
2685f757f3fSDimitry Andric     return true;
2695f757f3fSDimitry Andric   if (m_load_address == LLDB_INVALID_ADDRESS)
2705f757f3fSDimitry Andric     return false;
2715f757f3fSDimitry Andric 
2725f757f3fSDimitry Andric   FileSpec file_spec(m_name);
2735f757f3fSDimitry Andric 
2745f757f3fSDimitry Andric   ModuleSP memory_module_sp;
2755f757f3fSDimitry Andric 
2765f757f3fSDimitry Andric   llvm::ELF::Elf32_Ehdr elf_eheader;
2775f757f3fSDimitry Andric   size_t size_to_read = 512;
2785f757f3fSDimitry Andric 
2795f757f3fSDimitry Andric   if (ReadELFHeader(process, m_load_address, elf_eheader)) {
2805f757f3fSDimitry Andric     if (elf_eheader.e_ident[llvm::ELF::EI_CLASS] == llvm::ELF::ELFCLASS32) {
2815f757f3fSDimitry Andric       size_to_read = sizeof(llvm::ELF::Elf32_Ehdr) +
2825f757f3fSDimitry Andric                      elf_eheader.e_phnum * elf_eheader.e_phentsize;
2835f757f3fSDimitry Andric     } else if (elf_eheader.e_ident[llvm::ELF::EI_CLASS] ==
2845f757f3fSDimitry Andric                llvm::ELF::ELFCLASS64) {
2855f757f3fSDimitry Andric       llvm::ELF::Elf64_Ehdr elf_eheader;
2865f757f3fSDimitry Andric       Status error;
2875f757f3fSDimitry Andric       if (process->ReadMemory(m_load_address, &elf_eheader, sizeof(elf_eheader),
2885f757f3fSDimitry Andric                               error) == sizeof(elf_eheader))
2895f757f3fSDimitry Andric         size_to_read = sizeof(llvm::ELF::Elf64_Ehdr) +
2905f757f3fSDimitry Andric                        elf_eheader.e_phnum * elf_eheader.e_phentsize;
2915f757f3fSDimitry Andric     }
2925f757f3fSDimitry Andric   }
2935f757f3fSDimitry Andric 
2945f757f3fSDimitry Andric   memory_module_sp =
2955f757f3fSDimitry Andric       process->ReadModuleFromMemory(file_spec, m_load_address, size_to_read);
2965f757f3fSDimitry Andric 
2975f757f3fSDimitry Andric   if (!memory_module_sp)
2985f757f3fSDimitry Andric     return false;
2995f757f3fSDimitry Andric 
3005f757f3fSDimitry Andric   bool this_is_kernel = is_kernel(memory_module_sp.get());
3015f757f3fSDimitry Andric 
3025f757f3fSDimitry Andric   if (!m_uuid.IsValid() && memory_module_sp->GetUUID().IsValid())
3035f757f3fSDimitry Andric     m_uuid = memory_module_sp->GetUUID();
3045f757f3fSDimitry Andric 
3055f757f3fSDimitry Andric   m_memory_module_sp = memory_module_sp;
3065f757f3fSDimitry Andric   m_is_kernel = this_is_kernel;
3075f757f3fSDimitry Andric 
3085f757f3fSDimitry Andric   // The kernel binary is from memory
3095f757f3fSDimitry Andric   if (this_is_kernel) {
3105f757f3fSDimitry Andric     LLDB_LOGF(log, "KextImageInfo::ReadMemoryModule read the kernel binary out "
3115f757f3fSDimitry Andric                    "of memory");
3125f757f3fSDimitry Andric 
3135f757f3fSDimitry Andric     if (memory_module_sp->GetArchitecture().IsValid())
3145f757f3fSDimitry Andric       process->GetTarget().SetArchitecture(memory_module_sp->GetArchitecture());
3155f757f3fSDimitry Andric   }
3165f757f3fSDimitry Andric 
3175f757f3fSDimitry Andric   return true;
3185f757f3fSDimitry Andric }
3195f757f3fSDimitry Andric 
3205f757f3fSDimitry Andric bool DynamicLoaderFreeBSDKernel::KModImageInfo::LoadImageUsingMemoryModule(
3215f757f3fSDimitry Andric     lldb_private::Process *process) {
3225f757f3fSDimitry Andric   Log *log = GetLog(LLDBLog::DynamicLoader);
3235f757f3fSDimitry Andric 
3245f757f3fSDimitry Andric   if (IsLoaded())
3255f757f3fSDimitry Andric     return true;
3265f757f3fSDimitry Andric 
3275f757f3fSDimitry Andric   Target &target = process->GetTarget();
3285f757f3fSDimitry Andric 
3295f757f3fSDimitry Andric   if (IsKernel() && m_uuid.IsValid()) {
3305f757f3fSDimitry Andric     Stream &s = target.GetDebugger().GetOutputStream();
3315f757f3fSDimitry Andric     s.Printf("Kernel UUID: %s\n", m_uuid.GetAsString().c_str());
3325f757f3fSDimitry Andric     s.Printf("Load Address: 0x%" PRIx64 "\n", m_load_address);
3335f757f3fSDimitry Andric   }
3345f757f3fSDimitry Andric 
3355f757f3fSDimitry Andric   // Test if the module is loaded into the taget,
3365f757f3fSDimitry Andric   // maybe the module is loaded manually by user by doing target module add
3375f757f3fSDimitry Andric   // So that we have to create the module manually
3385f757f3fSDimitry Andric   if (!m_module_sp) {
3395f757f3fSDimitry Andric     const ModuleList &target_images = target.GetImages();
3405f757f3fSDimitry Andric     m_module_sp = target_images.FindModule(m_uuid);
3415f757f3fSDimitry Andric 
3425f757f3fSDimitry Andric     // Search in the file system
3435f757f3fSDimitry Andric     if (!m_module_sp) {
3445f757f3fSDimitry Andric       ModuleSpec module_spec(FileSpec(GetPath()), target.GetArchitecture());
3455f757f3fSDimitry Andric       if (IsKernel()) {
3465f757f3fSDimitry Andric         Status error;
3475f757f3fSDimitry Andric         if (PluginManager::DownloadObjectAndSymbolFile(module_spec, error,
3485f757f3fSDimitry Andric                                                        true)) {
3495f757f3fSDimitry Andric           if (FileSystem::Instance().Exists(module_spec.GetFileSpec()))
3505f757f3fSDimitry Andric             m_module_sp = std::make_shared<Module>(module_spec.GetFileSpec(),
3515f757f3fSDimitry Andric                                                    target.GetArchitecture());
3525f757f3fSDimitry Andric         }
3535f757f3fSDimitry Andric       }
3545f757f3fSDimitry Andric 
3555f757f3fSDimitry Andric       if (!m_module_sp)
3565f757f3fSDimitry Andric         m_module_sp = target.GetOrCreateModule(module_spec, true);
3575f757f3fSDimitry Andric       if (IsKernel() && !m_module_sp) {
3585f757f3fSDimitry Andric         Stream &s = target.GetDebugger().GetOutputStream();
3595f757f3fSDimitry Andric         s.Printf("WARNING: Unable to locate kernel binary on the debugger "
3605f757f3fSDimitry Andric                  "system.\n");
3615f757f3fSDimitry Andric       }
3625f757f3fSDimitry Andric     }
3635f757f3fSDimitry Andric 
3645f757f3fSDimitry Andric     if (m_module_sp) {
3655f757f3fSDimitry Andric       // If the file is not kernel or kmod, the target should be loaded once and
3665f757f3fSDimitry Andric       // don't reload again
3675f757f3fSDimitry Andric       if (!IsKernel() && !is_kmod(m_module_sp.get())) {
3685f757f3fSDimitry Andric         ModuleSP existing_module_sp = target.GetImages().FindModule(m_uuid);
3695f757f3fSDimitry Andric         if (existing_module_sp &&
3705f757f3fSDimitry Andric             existing_module_sp->IsLoadedInTarget(&target)) {
3715f757f3fSDimitry Andric           LLDB_LOGF(log,
3725f757f3fSDimitry Andric                     "'%s' with UUID %s is not a kmod or kernel, and is "
3735f757f3fSDimitry Andric                     "already registered in target, not loading.",
3745f757f3fSDimitry Andric                     m_name.c_str(), m_uuid.GetAsString().c_str());
3755f757f3fSDimitry Andric           return true;
3765f757f3fSDimitry Andric         }
3775f757f3fSDimitry Andric       }
3785f757f3fSDimitry Andric       m_uuid = m_module_sp->GetUUID();
3795f757f3fSDimitry Andric 
3805f757f3fSDimitry Andric       // or append to the images
3815f757f3fSDimitry Andric       target.GetImages().AppendIfNeeded(m_module_sp, false);
3825f757f3fSDimitry Andric     }
3835f757f3fSDimitry Andric   }
3845f757f3fSDimitry Andric 
3855f757f3fSDimitry Andric   // If this file is relocatable kernel module(x86_64), adjust it's
3865f757f3fSDimitry Andric   // section(PT_LOAD segment) and return Because the kernel module's load
3875f757f3fSDimitry Andric   // address is the text section. lldb cannot create full memory module upon
3885f757f3fSDimitry Andric   // relocatable file So what we do is to set the load address only.
3895f757f3fSDimitry Andric   if (is_kmod(m_module_sp.get()) && is_reloc(m_module_sp.get())) {
3905f757f3fSDimitry Andric     m_stop_id = process->GetStopID();
3915f757f3fSDimitry Andric     bool changed = false;
3925f757f3fSDimitry Andric     m_module_sp->SetLoadAddress(target, m_load_address, true, changed);
3935f757f3fSDimitry Andric     return true;
3945f757f3fSDimitry Andric   }
3955f757f3fSDimitry Andric 
3965f757f3fSDimitry Andric   if (m_module_sp)
3975f757f3fSDimitry Andric     ReadMemoryModule(process);
3985f757f3fSDimitry Andric 
3995f757f3fSDimitry Andric   // Calculate the slides of in memory module
4005f757f3fSDimitry Andric   if (!m_memory_module_sp || !m_module_sp) {
4015f757f3fSDimitry Andric     m_module_sp.reset();
4025f757f3fSDimitry Andric     return false;
4035f757f3fSDimitry Andric   }
4045f757f3fSDimitry Andric 
4055f757f3fSDimitry Andric   ObjectFile *ondisk_object_file = m_module_sp->GetObjectFile();
4065f757f3fSDimitry Andric   ObjectFile *memory_object_file = m_memory_module_sp->GetObjectFile();
4075f757f3fSDimitry Andric 
4085f757f3fSDimitry Andric   if (!ondisk_object_file || !memory_object_file)
4095f757f3fSDimitry Andric     m_module_sp.reset();
4105f757f3fSDimitry Andric 
4115f757f3fSDimitry Andric   // Find the slide address
4125f757f3fSDimitry Andric   addr_t fixed_slide = LLDB_INVALID_ADDRESS;
413*0fca6ea1SDimitry Andric   if (llvm::dyn_cast<ObjectFileELF>(memory_object_file)) {
4145f757f3fSDimitry Andric     addr_t load_address = memory_object_file->GetBaseAddress().GetFileAddress();
4155f757f3fSDimitry Andric 
4165f757f3fSDimitry Andric     if (load_address != LLDB_INVALID_ADDRESS &&
4175f757f3fSDimitry Andric         m_load_address != load_address) {
4185f757f3fSDimitry Andric       fixed_slide = m_load_address - load_address;
4195f757f3fSDimitry Andric       LLDB_LOGF(log,
4205f757f3fSDimitry Andric                 "kmod %s in-memory LOAD vmaddr is not correct, using a "
4215f757f3fSDimitry Andric                 "fixed slide of 0x%" PRIx64,
4225f757f3fSDimitry Andric                 m_name.c_str(), fixed_slide);
4235f757f3fSDimitry Andric     }
4245f757f3fSDimitry Andric   }
4255f757f3fSDimitry Andric 
4265f757f3fSDimitry Andric   SectionList *ondisk_section_list = ondisk_object_file->GetSectionList();
4275f757f3fSDimitry Andric   SectionList *memory_section_list = memory_object_file->GetSectionList();
4285f757f3fSDimitry Andric 
4295f757f3fSDimitry Andric   if (memory_section_list && ondisk_object_file) {
4305f757f3fSDimitry Andric     const uint32_t num_ondisk_sections = ondisk_section_list->GetSize();
4315f757f3fSDimitry Andric     uint32_t num_load_sections = 0;
4325f757f3fSDimitry Andric 
4335f757f3fSDimitry Andric     for (uint32_t section_idx = 0; section_idx < num_ondisk_sections;
4345f757f3fSDimitry Andric          ++section_idx) {
4355f757f3fSDimitry Andric       SectionSP on_disk_section_sp =
4365f757f3fSDimitry Andric           ondisk_section_list->GetSectionAtIndex(section_idx);
4375f757f3fSDimitry Andric 
4385f757f3fSDimitry Andric       if (!on_disk_section_sp)
4395f757f3fSDimitry Andric         continue;
4405f757f3fSDimitry Andric       if (fixed_slide != LLDB_INVALID_ADDRESS) {
4415f757f3fSDimitry Andric         target.SetSectionLoadAddress(on_disk_section_sp,
4425f757f3fSDimitry Andric                                      on_disk_section_sp->GetFileAddress() +
4435f757f3fSDimitry Andric                                          fixed_slide);
4445f757f3fSDimitry Andric 
4455f757f3fSDimitry Andric       } else {
4465f757f3fSDimitry Andric         const Section *memory_section =
4475f757f3fSDimitry Andric             memory_section_list
4485f757f3fSDimitry Andric                 ->FindSectionByName(on_disk_section_sp->GetName())
4495f757f3fSDimitry Andric                 .get();
4505f757f3fSDimitry Andric         if (memory_section) {
4515f757f3fSDimitry Andric           target.SetSectionLoadAddress(on_disk_section_sp,
4525f757f3fSDimitry Andric                                        memory_section->GetFileAddress());
4535f757f3fSDimitry Andric           ++num_load_sections;
4545f757f3fSDimitry Andric         }
4555f757f3fSDimitry Andric       }
4565f757f3fSDimitry Andric     }
4575f757f3fSDimitry Andric 
4585f757f3fSDimitry Andric     if (num_load_sections)
4595f757f3fSDimitry Andric       m_stop_id = process->GetStopID();
4605f757f3fSDimitry Andric     else
4615f757f3fSDimitry Andric       m_module_sp.reset();
4625f757f3fSDimitry Andric   } else {
4635f757f3fSDimitry Andric     m_module_sp.reset();
4645f757f3fSDimitry Andric   }
4655f757f3fSDimitry Andric 
4665f757f3fSDimitry Andric   if (IsLoaded() && m_module_sp && IsKernel()) {
4675f757f3fSDimitry Andric     Stream &s = target.GetDebugger().GetOutputStream();
4685f757f3fSDimitry Andric     ObjectFile *kernel_object_file = m_module_sp->GetObjectFile();
4695f757f3fSDimitry Andric     if (kernel_object_file) {
4705f757f3fSDimitry Andric       addr_t file_address =
4715f757f3fSDimitry Andric           kernel_object_file->GetBaseAddress().GetFileAddress();
4725f757f3fSDimitry Andric       if (m_load_address != LLDB_INVALID_ADDRESS &&
4735f757f3fSDimitry Andric           file_address != LLDB_INVALID_ADDRESS) {
4745f757f3fSDimitry Andric         s.Printf("Kernel slide 0x%" PRIx64 " in memory.\n",
4755f757f3fSDimitry Andric                  m_load_address - file_address);
4765f757f3fSDimitry Andric         s.Printf("Loaded kernel file %s\n",
4775f757f3fSDimitry Andric                  m_module_sp->GetFileSpec().GetPath().c_str());
4785f757f3fSDimitry Andric       }
4795f757f3fSDimitry Andric     }
4805f757f3fSDimitry Andric     s.Flush();
4815f757f3fSDimitry Andric   }
4825f757f3fSDimitry Andric 
4835f757f3fSDimitry Andric   return IsLoaded();
4845f757f3fSDimitry Andric }
4855f757f3fSDimitry Andric 
4865f757f3fSDimitry Andric // This function is work for kernel file, others it wil reset load address and
4875f757f3fSDimitry Andric // return false
4885f757f3fSDimitry Andric bool DynamicLoaderFreeBSDKernel::KModImageInfo::LoadImageUsingFileAddress(
4895f757f3fSDimitry Andric     lldb_private::Process *process) {
4905f757f3fSDimitry Andric   if (IsLoaded())
4915f757f3fSDimitry Andric     return true;
4925f757f3fSDimitry Andric 
4935f757f3fSDimitry Andric   if (m_module_sp) {
4945f757f3fSDimitry Andric     bool changed = false;
4955f757f3fSDimitry Andric     if (m_module_sp->SetLoadAddress(process->GetTarget(), 0, true, changed))
4965f757f3fSDimitry Andric       m_stop_id = process->GetStopID();
4975f757f3fSDimitry Andric   }
4985f757f3fSDimitry Andric 
4995f757f3fSDimitry Andric   return false;
5005f757f3fSDimitry Andric }
5015f757f3fSDimitry Andric 
5025f757f3fSDimitry Andric // Get the head of found_list
5035f757f3fSDimitry Andric bool DynamicLoaderFreeBSDKernel::ReadKmodsListHeader() {
5045f757f3fSDimitry Andric   std::lock_guard<decltype(m_mutex)> guard(m_mutex);
5055f757f3fSDimitry Andric 
5065f757f3fSDimitry Andric   if (m_linker_file_list_struct_addr.IsValid()) {
5075f757f3fSDimitry Andric     // Get tqh_first struct element from linker_files
5085f757f3fSDimitry Andric     Status error;
5095f757f3fSDimitry Andric     addr_t address = m_process->ReadPointerFromMemory(
5105f757f3fSDimitry Andric         m_linker_file_list_struct_addr.GetLoadAddress(&m_process->GetTarget()),
5115f757f3fSDimitry Andric         error);
5125f757f3fSDimitry Andric     if (address != LLDB_INVALID_ADDRESS && error.Success()) {
5135f757f3fSDimitry Andric       m_linker_file_head_addr = Address(address);
5145f757f3fSDimitry Andric     } else {
5155f757f3fSDimitry Andric       m_linker_file_list_struct_addr.Clear();
5165f757f3fSDimitry Andric       return false;
5175f757f3fSDimitry Andric     }
5185f757f3fSDimitry Andric 
5195f757f3fSDimitry Andric     if (!m_linker_file_head_addr.IsValid() ||
5205f757f3fSDimitry Andric         m_linker_file_head_addr.GetFileAddress() == 0) {
5215f757f3fSDimitry Andric       m_linker_file_list_struct_addr.Clear();
5225f757f3fSDimitry Andric       return false;
5235f757f3fSDimitry Andric     }
5245f757f3fSDimitry Andric   }
5255f757f3fSDimitry Andric   return true;
5265f757f3fSDimitry Andric }
5275f757f3fSDimitry Andric 
5285f757f3fSDimitry Andric // Parse Kmod info in found_list
5295f757f3fSDimitry Andric bool DynamicLoaderFreeBSDKernel::ParseKmods(Address linker_files_head_addr) {
5305f757f3fSDimitry Andric   std::lock_guard<decltype(m_mutex)> guard(m_mutex);
5315f757f3fSDimitry Andric   KModImageInfo::collection_type linker_files_list;
5325f757f3fSDimitry Andric   Log *log = GetLog(LLDBLog::DynamicLoader);
5335f757f3fSDimitry Andric 
5345f757f3fSDimitry Andric   if (!ReadAllKmods(linker_files_head_addr, linker_files_list))
5355f757f3fSDimitry Andric     return false;
5365f757f3fSDimitry Andric   LLDB_LOGF(
5375f757f3fSDimitry Andric       log,
5385f757f3fSDimitry Andric       "Kmod-changed breakpoint hit, there are %zu kernel modules currently.\n",
5395f757f3fSDimitry Andric       linker_files_list.size());
5405f757f3fSDimitry Andric 
5415f757f3fSDimitry Andric   ModuleList &modules = m_process->GetTarget().GetImages();
5425f757f3fSDimitry Andric   ModuleList remove_modules;
5435f757f3fSDimitry Andric   ModuleList add_modules;
5445f757f3fSDimitry Andric 
5455f757f3fSDimitry Andric   for (ModuleSP module : modules.Modules()) {
5465f757f3fSDimitry Andric     if (is_kernel(module.get()))
5475f757f3fSDimitry Andric       continue;
5485f757f3fSDimitry Andric     if (is_kmod(module.get()))
5495f757f3fSDimitry Andric       remove_modules.AppendIfNeeded(module);
5505f757f3fSDimitry Andric   }
5515f757f3fSDimitry Andric 
5525f757f3fSDimitry Andric   m_process->GetTarget().ModulesDidUnload(remove_modules, false);
5535f757f3fSDimitry Andric 
5545f757f3fSDimitry Andric   for (KModImageInfo &image_info : linker_files_list) {
5555f757f3fSDimitry Andric     if (m_kld_name_to_uuid.find(image_info.GetName()) !=
5565f757f3fSDimitry Andric         m_kld_name_to_uuid.end())
5575f757f3fSDimitry Andric       image_info.SetUUID(m_kld_name_to_uuid[image_info.GetName()]);
5585f757f3fSDimitry Andric     bool failed_to_load = false;
5595f757f3fSDimitry Andric     if (!image_info.LoadImageUsingMemoryModule(m_process)) {
5605f757f3fSDimitry Andric       image_info.LoadImageUsingFileAddress(m_process);
5615f757f3fSDimitry Andric       failed_to_load = true;
5625f757f3fSDimitry Andric     } else {
5635f757f3fSDimitry Andric       m_linker_files_list.push_back(image_info);
5645f757f3fSDimitry Andric       m_kld_name_to_uuid[image_info.GetName()] = image_info.GetUUID();
5655f757f3fSDimitry Andric     }
5665f757f3fSDimitry Andric 
5675f757f3fSDimitry Andric     if (!failed_to_load)
5685f757f3fSDimitry Andric       add_modules.AppendIfNeeded(image_info.GetModule());
5695f757f3fSDimitry Andric   }
5705f757f3fSDimitry Andric   m_process->GetTarget().ModulesDidLoad(add_modules);
5715f757f3fSDimitry Andric   return true;
5725f757f3fSDimitry Andric }
5735f757f3fSDimitry Andric 
5745f757f3fSDimitry Andric // Read all kmod from a given arrays of list
5755f757f3fSDimitry Andric bool DynamicLoaderFreeBSDKernel::ReadAllKmods(
5765f757f3fSDimitry Andric     Address linker_files_head_addr,
5775f757f3fSDimitry Andric     KModImageInfo::collection_type &kmods_list) {
5785f757f3fSDimitry Andric 
5795f757f3fSDimitry Andric   // Get offset of next member and load address symbol
5805f757f3fSDimitry Andric   static ConstString kld_off_address_symbol_name("kld_off_address");
5815f757f3fSDimitry Andric   static ConstString kld_off_next_symbol_name("kld_off_next");
5825f757f3fSDimitry Andric   static ConstString kld_off_filename_symbol_name("kld_off_filename");
5835f757f3fSDimitry Andric   static ConstString kld_off_pathname_symbol_name("kld_off_pathname");
5845f757f3fSDimitry Andric   const Symbol *kld_off_address_symbol =
5855f757f3fSDimitry Andric       m_kernel_image_info.GetModule()->FindFirstSymbolWithNameAndType(
5865f757f3fSDimitry Andric           kld_off_address_symbol_name, eSymbolTypeData);
5875f757f3fSDimitry Andric   const Symbol *kld_off_next_symbol =
5885f757f3fSDimitry Andric       m_kernel_image_info.GetModule()->FindFirstSymbolWithNameAndType(
5895f757f3fSDimitry Andric           kld_off_next_symbol_name, eSymbolTypeData);
5905f757f3fSDimitry Andric   const Symbol *kld_off_filename_symbol =
5915f757f3fSDimitry Andric       m_kernel_image_info.GetModule()->FindFirstSymbolWithNameAndType(
5925f757f3fSDimitry Andric           kld_off_filename_symbol_name, eSymbolTypeData);
5935f757f3fSDimitry Andric   const Symbol *kld_off_pathname_symbol =
5945f757f3fSDimitry Andric       m_kernel_image_info.GetModule()->FindFirstSymbolWithNameAndType(
5955f757f3fSDimitry Andric           kld_off_pathname_symbol_name, eSymbolTypeData);
5965f757f3fSDimitry Andric 
5975f757f3fSDimitry Andric   if (!kld_off_address_symbol || !kld_off_next_symbol ||
5985f757f3fSDimitry Andric       !kld_off_filename_symbol || !kld_off_pathname_symbol)
5995f757f3fSDimitry Andric     return false;
6005f757f3fSDimitry Andric 
6015f757f3fSDimitry Andric   Status error;
6025f757f3fSDimitry Andric   const int32_t kld_off_address = m_process->ReadSignedIntegerFromMemory(
6035f757f3fSDimitry Andric       kld_off_address_symbol->GetAddress().GetLoadAddress(
6045f757f3fSDimitry Andric           &m_process->GetTarget()),
6055f757f3fSDimitry Andric       4, 0, error);
6065f757f3fSDimitry Andric   if (error.Fail())
6075f757f3fSDimitry Andric     return false;
6085f757f3fSDimitry Andric   const int32_t kld_off_next = m_process->ReadSignedIntegerFromMemory(
6095f757f3fSDimitry Andric       kld_off_next_symbol->GetAddress().GetLoadAddress(&m_process->GetTarget()),
6105f757f3fSDimitry Andric       4, 0, error);
6115f757f3fSDimitry Andric   if (error.Fail())
6125f757f3fSDimitry Andric     return false;
6135f757f3fSDimitry Andric   const int32_t kld_off_filename = m_process->ReadSignedIntegerFromMemory(
6145f757f3fSDimitry Andric       kld_off_filename_symbol->GetAddress().GetLoadAddress(
6155f757f3fSDimitry Andric           &m_process->GetTarget()),
6165f757f3fSDimitry Andric       4, 0, error);
6175f757f3fSDimitry Andric   if (error.Fail())
6185f757f3fSDimitry Andric     return false;
6195f757f3fSDimitry Andric 
6205f757f3fSDimitry Andric   const int32_t kld_off_pathname = m_process->ReadSignedIntegerFromMemory(
6215f757f3fSDimitry Andric       kld_off_pathname_symbol->GetAddress().GetLoadAddress(
6225f757f3fSDimitry Andric           &m_process->GetTarget()),
6235f757f3fSDimitry Andric       4, 0, error);
6245f757f3fSDimitry Andric   if (error.Fail())
6255f757f3fSDimitry Andric     return false;
6265f757f3fSDimitry Andric 
6275f757f3fSDimitry Andric   // Parse KMods
6285f757f3fSDimitry Andric   addr_t kld_load_addr(LLDB_INVALID_ADDRESS);
6295f757f3fSDimitry Andric   char kld_filename[255];
6305f757f3fSDimitry Andric   char kld_pathname[255];
6315f757f3fSDimitry Andric   addr_t current_kld =
6325f757f3fSDimitry Andric       linker_files_head_addr.GetLoadAddress(&m_process->GetTarget());
6335f757f3fSDimitry Andric 
6345f757f3fSDimitry Andric   while (current_kld != 0) {
6355f757f3fSDimitry Andric     addr_t kld_filename_addr =
6365f757f3fSDimitry Andric         m_process->ReadPointerFromMemory(current_kld + kld_off_filename, error);
6375f757f3fSDimitry Andric     if (error.Fail())
6385f757f3fSDimitry Andric       return false;
6395f757f3fSDimitry Andric     addr_t kld_pathname_addr =
6405f757f3fSDimitry Andric         m_process->ReadPointerFromMemory(current_kld + kld_off_pathname, error);
6415f757f3fSDimitry Andric     if (error.Fail())
6425f757f3fSDimitry Andric       return false;
6435f757f3fSDimitry Andric 
6445f757f3fSDimitry Andric     m_process->ReadCStringFromMemory(kld_filename_addr, kld_filename,
6455f757f3fSDimitry Andric                                      sizeof(kld_filename), error);
6465f757f3fSDimitry Andric     if (error.Fail())
6475f757f3fSDimitry Andric       return false;
6485f757f3fSDimitry Andric     m_process->ReadCStringFromMemory(kld_pathname_addr, kld_pathname,
6495f757f3fSDimitry Andric                                      sizeof(kld_pathname), error);
6505f757f3fSDimitry Andric     if (error.Fail())
6515f757f3fSDimitry Andric       return false;
6525f757f3fSDimitry Andric     kld_load_addr =
6535f757f3fSDimitry Andric         m_process->ReadPointerFromMemory(current_kld + kld_off_address, error);
6545f757f3fSDimitry Andric     if (error.Fail())
6555f757f3fSDimitry Andric       return false;
6565f757f3fSDimitry Andric 
6575f757f3fSDimitry Andric     kmods_list.emplace_back();
6585f757f3fSDimitry Andric     KModImageInfo &kmod_info = kmods_list.back();
6595f757f3fSDimitry Andric     kmod_info.SetName(kld_filename);
6605f757f3fSDimitry Andric     kmod_info.SetLoadAddress(kld_load_addr);
6615f757f3fSDimitry Andric     kmod_info.SetPath(kld_pathname);
6625f757f3fSDimitry Andric 
6635f757f3fSDimitry Andric     current_kld =
6645f757f3fSDimitry Andric         m_process->ReadPointerFromMemory(current_kld + kld_off_next, error);
6655f757f3fSDimitry Andric     if (kmod_info.GetName() == "kernel")
6665f757f3fSDimitry Andric       kmods_list.pop_back();
6675f757f3fSDimitry Andric     if (error.Fail())
6685f757f3fSDimitry Andric       return false;
6695f757f3fSDimitry Andric   }
6705f757f3fSDimitry Andric 
6715f757f3fSDimitry Andric   return true;
6725f757f3fSDimitry Andric }
6735f757f3fSDimitry Andric 
6745f757f3fSDimitry Andric // Read all kmods
6755f757f3fSDimitry Andric void DynamicLoaderFreeBSDKernel::ReadAllKmods() {
6765f757f3fSDimitry Andric   std::lock_guard<decltype(m_mutex)> guard(m_mutex);
6775f757f3fSDimitry Andric 
6785f757f3fSDimitry Andric   if (ReadKmodsListHeader()) {
6795f757f3fSDimitry Andric     if (m_linker_file_head_addr.IsValid()) {
6805f757f3fSDimitry Andric       if (!ParseKmods(m_linker_file_head_addr))
6815f757f3fSDimitry Andric         m_linker_files_list.clear();
6825f757f3fSDimitry Andric     }
6835f757f3fSDimitry Andric   }
6845f757f3fSDimitry Andric }
6855f757f3fSDimitry Andric 
6865f757f3fSDimitry Andric // Load all Kernel Modules
6875f757f3fSDimitry Andric void DynamicLoaderFreeBSDKernel::LoadKernelModules() {
6885f757f3fSDimitry Andric   Log *log = GetLog(LLDBLog::DynamicLoader);
6895f757f3fSDimitry Andric   LLDB_LOGF(log, "DynamicLoaderFreeBSDKernel::LoadKernelModules "
6905f757f3fSDimitry Andric                  "Start loading Kernel Module");
6915f757f3fSDimitry Andric 
6925f757f3fSDimitry Andric   // Initialize Kernel Image Information at the first time
6935f757f3fSDimitry Andric   if (m_kernel_image_info.GetLoadAddress() == LLDB_INVALID_ADDRESS) {
6945f757f3fSDimitry Andric     ModuleSP module_sp = m_process->GetTarget().GetExecutableModule();
6955f757f3fSDimitry Andric     if (is_kernel(module_sp.get())) {
6965f757f3fSDimitry Andric       m_kernel_image_info.SetModule(module_sp);
6975f757f3fSDimitry Andric       m_kernel_image_info.SetIsKernel(true);
6985f757f3fSDimitry Andric     }
6995f757f3fSDimitry Andric 
7005f757f3fSDimitry Andric     // Set name for kernel
7015f757f3fSDimitry Andric     llvm::StringRef kernel_name("freebsd_kernel");
7025f757f3fSDimitry Andric     module_sp = m_kernel_image_info.GetModule();
7035f757f3fSDimitry Andric     if (module_sp.get() && module_sp->GetObjectFile() &&
7045f757f3fSDimitry Andric         !module_sp->GetObjectFile()->GetFileSpec().GetFilename().IsEmpty())
7055f757f3fSDimitry Andric       kernel_name = module_sp->GetObjectFile()
7065f757f3fSDimitry Andric                         ->GetFileSpec()
7075f757f3fSDimitry Andric                         .GetFilename()
7085f757f3fSDimitry Andric                         .GetStringRef();
7095f757f3fSDimitry Andric     m_kernel_image_info.SetName(kernel_name.data());
7105f757f3fSDimitry Andric 
7115f757f3fSDimitry Andric     if (m_kernel_image_info.GetLoadAddress() == LLDB_INVALID_ADDRESS) {
7125f757f3fSDimitry Andric       m_kernel_image_info.SetLoadAddress(m_kernel_load_address);
7135f757f3fSDimitry Andric     }
7145f757f3fSDimitry Andric 
7155f757f3fSDimitry Andric     // Build In memory Module
7165f757f3fSDimitry Andric     if (m_kernel_image_info.GetLoadAddress() != LLDB_INVALID_ADDRESS) {
7175f757f3fSDimitry Andric       // If the kernel is not loaded in the memory, use file to load
7185f757f3fSDimitry Andric       if (!m_kernel_image_info.LoadImageUsingMemoryModule(m_process))
7195f757f3fSDimitry Andric         m_kernel_image_info.LoadImageUsingFileAddress(m_process);
7205f757f3fSDimitry Andric     }
7215f757f3fSDimitry Andric   }
7225f757f3fSDimitry Andric 
7235f757f3fSDimitry Andric   LoadOperatingSystemPlugin(false);
7245f757f3fSDimitry Andric 
7255f757f3fSDimitry Andric   if (!m_kernel_image_info.IsLoaded() || !m_kernel_image_info.GetModule()) {
7265f757f3fSDimitry Andric     m_kernel_image_info.Clear();
7275f757f3fSDimitry Andric     return;
7285f757f3fSDimitry Andric   }
7295f757f3fSDimitry Andric 
7305f757f3fSDimitry Andric   static ConstString modlist_symbol_name("linker_files");
7315f757f3fSDimitry Andric 
7325f757f3fSDimitry Andric   const Symbol *symbol =
7335f757f3fSDimitry Andric       m_kernel_image_info.GetModule()->FindFirstSymbolWithNameAndType(
7345f757f3fSDimitry Andric           modlist_symbol_name, lldb::eSymbolTypeData);
7355f757f3fSDimitry Andric 
7365f757f3fSDimitry Andric   if (symbol) {
7375f757f3fSDimitry Andric     m_linker_file_list_struct_addr = symbol->GetAddress();
7385f757f3fSDimitry Andric     ReadAllKmods();
7395f757f3fSDimitry Andric   } else {
7405f757f3fSDimitry Andric     LLDB_LOGF(log, "DynamicLoaderFreeBSDKernel::LoadKernelModules "
7415f757f3fSDimitry Andric                    "cannot file modlist symbol");
7425f757f3fSDimitry Andric   }
7435f757f3fSDimitry Andric }
7445f757f3fSDimitry Andric 
7455f757f3fSDimitry Andric // Update symbol when use kldload by setting callback function on kldload
7465f757f3fSDimitry Andric void DynamicLoaderFreeBSDKernel::SetNotificationBreakPoint() {}
7475f757f3fSDimitry Andric 
7485f757f3fSDimitry Andric // Hook called when attach to a process
7495f757f3fSDimitry Andric void DynamicLoaderFreeBSDKernel::DidAttach() {
7505f757f3fSDimitry Andric   PrivateInitialize(m_process);
7515f757f3fSDimitry Andric   Update();
7525f757f3fSDimitry Andric }
7535f757f3fSDimitry Andric 
7545f757f3fSDimitry Andric // Hook called after attach to a process
7555f757f3fSDimitry Andric void DynamicLoaderFreeBSDKernel::DidLaunch() {
7565f757f3fSDimitry Andric   PrivateInitialize(m_process);
7575f757f3fSDimitry Andric   Update();
7585f757f3fSDimitry Andric }
7595f757f3fSDimitry Andric 
7605f757f3fSDimitry Andric // Clear all member except kernel address
7615f757f3fSDimitry Andric void DynamicLoaderFreeBSDKernel::Clear(bool clear_process) {
7625f757f3fSDimitry Andric   std::lock_guard<decltype(m_mutex)> guard(m_mutex);
7635f757f3fSDimitry Andric   if (clear_process)
7645f757f3fSDimitry Andric     m_process = nullptr;
7655f757f3fSDimitry Andric   m_linker_file_head_addr.Clear();
7665f757f3fSDimitry Andric   m_linker_file_list_struct_addr.Clear();
7675f757f3fSDimitry Andric   m_kernel_image_info.Clear();
7685f757f3fSDimitry Andric   m_linker_files_list.clear();
7695f757f3fSDimitry Andric }
7705f757f3fSDimitry Andric 
7715f757f3fSDimitry Andric // Reinitialize class
7725f757f3fSDimitry Andric void DynamicLoaderFreeBSDKernel::PrivateInitialize(Process *process) {
7735f757f3fSDimitry Andric   Clear(true);
7745f757f3fSDimitry Andric   m_process = process;
7755f757f3fSDimitry Andric }
7765f757f3fSDimitry Andric 
7775f757f3fSDimitry Andric ThreadPlanSP DynamicLoaderFreeBSDKernel::GetStepThroughTrampolinePlan(
7785f757f3fSDimitry Andric     lldb_private::Thread &thread, bool stop_others) {
7795f757f3fSDimitry Andric   Log *log = GetLog(LLDBLog::Step);
7805f757f3fSDimitry Andric   LLDB_LOGF(log, "DynamicLoaderFreeBSDKernel::GetStepThroughTrampolinePlan is "
7815f757f3fSDimitry Andric                  "not yet implemented.");
7825f757f3fSDimitry Andric   return {};
7835f757f3fSDimitry Andric }
7845f757f3fSDimitry Andric 
7855f757f3fSDimitry Andric Status DynamicLoaderFreeBSDKernel::CanLoadImage() {
7865f757f3fSDimitry Andric   Status error("shared object cannot be loaded into kernel");
7875f757f3fSDimitry Andric   return error;
7885f757f3fSDimitry Andric }
789