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