1b1c73532SDimitry Andric //===-- DynamicLoaderFreeBSDKernel.cpp
2b1c73532SDimitry Andric //------------------------------------------===//
3b1c73532SDimitry Andric //
4b1c73532SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
5b1c73532SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
6b1c73532SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7b1c73532SDimitry Andric //
8b1c73532SDimitry Andric //===----------------------------------------------------------------------===//
9b1c73532SDimitry Andric 
10b1c73532SDimitry Andric #include "lldb/Breakpoint/StoppointCallbackContext.h"
11b1c73532SDimitry Andric #include "lldb/Core/Debugger.h"
12b1c73532SDimitry Andric #include "lldb/Core/Module.h"
13b1c73532SDimitry Andric #include "lldb/Core/ModuleSpec.h"
14b1c73532SDimitry Andric #include "lldb/Core/PluginManager.h"
15b1c73532SDimitry Andric #include "lldb/Core/Section.h"
16b1c73532SDimitry Andric #include "lldb/Host/StreamFile.h"
17b1c73532SDimitry Andric #include "lldb/Interpreter/OptionValueProperties.h"
18b1c73532SDimitry Andric #include "lldb/Symbol/ObjectFile.h"
19b1c73532SDimitry Andric #include "lldb/Target/OperatingSystem.h"
20b1c73532SDimitry Andric #include "lldb/Target/RegisterContext.h"
21b1c73532SDimitry Andric #include "lldb/Target/StackFrame.h"
22b1c73532SDimitry Andric #include "lldb/Target/Target.h"
23b1c73532SDimitry Andric #include "lldb/Target/Thread.h"
24b1c73532SDimitry Andric #include "lldb/Target/ThreadPlanRunToAddress.h"
25b1c73532SDimitry Andric #include "lldb/Utility/DataBuffer.h"
26b1c73532SDimitry Andric #include "lldb/Utility/DataBufferHeap.h"
27b1c73532SDimitry Andric #include "lldb/Utility/LLDBLog.h"
28b1c73532SDimitry Andric #include "lldb/Utility/Log.h"
29b1c73532SDimitry Andric #include "lldb/Utility/State.h"
30b1c73532SDimitry Andric 
31b1c73532SDimitry Andric #include "Plugins/ObjectFile/ELF/ObjectFileELF.h"
32b1c73532SDimitry Andric 
33b1c73532SDimitry Andric #include "DynamicLoaderFreeBSDKernel.h"
34b1c73532SDimitry Andric #include <memory>
35b1c73532SDimitry Andric #include <mutex>
36b1c73532SDimitry Andric 
37b1c73532SDimitry Andric using namespace lldb;
38b1c73532SDimitry Andric using namespace lldb_private;
39b1c73532SDimitry Andric 
LLDB_PLUGIN_DEFINE(DynamicLoaderFreeBSDKernel)40b1c73532SDimitry Andric LLDB_PLUGIN_DEFINE(DynamicLoaderFreeBSDKernel)
41b1c73532SDimitry Andric 
42b1c73532SDimitry Andric void DynamicLoaderFreeBSDKernel::Initialize() {
43b1c73532SDimitry Andric   PluginManager::RegisterPlugin(GetPluginNameStatic(),
44b1c73532SDimitry Andric                                 GetPluginDescriptionStatic(), CreateInstance,
45b1c73532SDimitry Andric                                 DebuggerInit);
46b1c73532SDimitry Andric }
47b1c73532SDimitry Andric 
Terminate()48b1c73532SDimitry Andric void DynamicLoaderFreeBSDKernel::Terminate() {
49b1c73532SDimitry Andric   PluginManager::UnregisterPlugin(CreateInstance);
50b1c73532SDimitry Andric }
51b1c73532SDimitry Andric 
GetPluginDescriptionStatic()52b1c73532SDimitry Andric llvm::StringRef DynamicLoaderFreeBSDKernel::GetPluginDescriptionStatic() {
53b1c73532SDimitry Andric   return "The Dynamic Loader Plugin For FreeBSD Kernel";
54b1c73532SDimitry Andric }
55b1c73532SDimitry Andric 
is_kernel(Module * module)56b1c73532SDimitry Andric static bool is_kernel(Module *module) {
57b1c73532SDimitry Andric   if (!module)
58b1c73532SDimitry Andric     return false;
59b1c73532SDimitry Andric 
60b1c73532SDimitry Andric   ObjectFile *objfile = module->GetObjectFile();
61b1c73532SDimitry Andric   if (!objfile)
62b1c73532SDimitry Andric     return false;
63b1c73532SDimitry Andric   if (objfile->GetType() != ObjectFile::eTypeExecutable)
64b1c73532SDimitry Andric     return false;
65b1c73532SDimitry Andric   if (objfile->GetStrata() != ObjectFile::eStrataUnknown &&
66b1c73532SDimitry Andric       objfile->GetStrata() != ObjectFile::eStrataKernel)
67b1c73532SDimitry Andric     return false;
68b1c73532SDimitry Andric 
69b1c73532SDimitry Andric   return true;
70b1c73532SDimitry Andric }
71b1c73532SDimitry Andric 
is_kmod(Module * module)72b1c73532SDimitry Andric static bool is_kmod(Module *module) {
73b1c73532SDimitry Andric   if (!module)
74b1c73532SDimitry Andric     return false;
75b1c73532SDimitry Andric   if (!module->GetObjectFile())
76b1c73532SDimitry Andric     return false;
77b1c73532SDimitry Andric   ObjectFile *objfile = module->GetObjectFile();
78b1c73532SDimitry Andric   if (objfile->GetType() != ObjectFile::eTypeObjectFile &&
79b1c73532SDimitry Andric       objfile->GetType() != ObjectFile::eTypeSharedLibrary)
80b1c73532SDimitry Andric     return false;
81b1c73532SDimitry Andric 
82b1c73532SDimitry Andric   return true;
83b1c73532SDimitry Andric }
84b1c73532SDimitry Andric 
is_reloc(Module * module)85b1c73532SDimitry Andric static bool is_reloc(Module *module) {
86b1c73532SDimitry Andric   if (!module)
87b1c73532SDimitry Andric     return false;
88b1c73532SDimitry Andric   if (!module->GetObjectFile())
89b1c73532SDimitry Andric     return false;
90b1c73532SDimitry Andric   ObjectFile *objfile = module->GetObjectFile();
91b1c73532SDimitry Andric   if (objfile->GetType() != ObjectFile::eTypeObjectFile)
92b1c73532SDimitry Andric     return false;
93b1c73532SDimitry Andric 
94b1c73532SDimitry Andric   return true;
95b1c73532SDimitry Andric }
96b1c73532SDimitry Andric 
97b1c73532SDimitry Andric // Instantiate Function of the FreeBSD Kernel Dynamic Loader Plugin called when
98b1c73532SDimitry Andric // Register the Plugin
99b1c73532SDimitry Andric DynamicLoader *
CreateInstance(lldb_private::Process * process,bool force)100b1c73532SDimitry Andric DynamicLoaderFreeBSDKernel::CreateInstance(lldb_private::Process *process,
101b1c73532SDimitry Andric                                            bool force) {
102b1c73532SDimitry Andric   // Check the environment when the plugin is not force loaded
103b1c73532SDimitry Andric   Module *exec = process->GetTarget().GetExecutableModulePointer();
104b1c73532SDimitry Andric   if (exec && !is_kernel(exec)) {
105b1c73532SDimitry Andric     return nullptr;
106b1c73532SDimitry Andric   }
107b1c73532SDimitry Andric   if (!force) {
108b1c73532SDimitry Andric     // Check if the target is kernel
109b1c73532SDimitry Andric     const llvm::Triple &triple_ref =
110b1c73532SDimitry Andric         process->GetTarget().GetArchitecture().GetTriple();
111b1c73532SDimitry Andric     if (!triple_ref.isOSFreeBSD()) {
112b1c73532SDimitry Andric       return nullptr;
113b1c73532SDimitry Andric     }
114b1c73532SDimitry Andric   }
115b1c73532SDimitry Andric 
116b1c73532SDimitry Andric   // At this point we have checked the target is a FreeBSD kernel and all we
117b1c73532SDimitry Andric   // have to do is to find the kernel address
118b1c73532SDimitry Andric   const addr_t kernel_address = FindFreeBSDKernel(process);
119b1c73532SDimitry Andric 
120b1c73532SDimitry Andric   if (CheckForKernelImageAtAddress(process, kernel_address).IsValid())
121b1c73532SDimitry Andric     return new DynamicLoaderFreeBSDKernel(process, kernel_address);
122b1c73532SDimitry Andric 
123b1c73532SDimitry Andric   return nullptr;
124b1c73532SDimitry Andric }
125b1c73532SDimitry Andric 
126b1c73532SDimitry Andric addr_t
FindFreeBSDKernel(lldb_private::Process * process)127b1c73532SDimitry Andric DynamicLoaderFreeBSDKernel::FindFreeBSDKernel(lldb_private::Process *process) {
128b1c73532SDimitry Andric   addr_t kernel_addr = process->GetImageInfoAddress();
129b1c73532SDimitry Andric   if (kernel_addr == LLDB_INVALID_ADDRESS)
130b1c73532SDimitry Andric     kernel_addr = FindKernelAtLoadAddress(process);
131b1c73532SDimitry Andric   return kernel_addr;
132b1c73532SDimitry Andric }
133b1c73532SDimitry Andric 
134b1c73532SDimitry Andric // Get the kernel address if the kernel is not loaded with a slide
FindKernelAtLoadAddress(lldb_private::Process * process)135b1c73532SDimitry Andric addr_t DynamicLoaderFreeBSDKernel::FindKernelAtLoadAddress(
136b1c73532SDimitry Andric     lldb_private::Process *process) {
137b1c73532SDimitry Andric   Module *exe_module = process->GetTarget().GetExecutableModulePointer();
138b1c73532SDimitry Andric 
139b1c73532SDimitry Andric   if (!is_kernel(exe_module))
140b1c73532SDimitry Andric     return LLDB_INVALID_ADDRESS;
141b1c73532SDimitry Andric 
142b1c73532SDimitry Andric   ObjectFile *exe_objfile = exe_module->GetObjectFile();
143b1c73532SDimitry Andric 
144b1c73532SDimitry Andric   if (!exe_objfile->GetBaseAddress().IsValid())
145b1c73532SDimitry Andric     return LLDB_INVALID_ADDRESS;
146b1c73532SDimitry Andric 
147b1c73532SDimitry Andric   if (CheckForKernelImageAtAddress(
148b1c73532SDimitry Andric           process, exe_objfile->GetBaseAddress().GetFileAddress())
149b1c73532SDimitry Andric           .IsValid())
150b1c73532SDimitry Andric     return exe_objfile->GetBaseAddress().GetFileAddress();
151b1c73532SDimitry Andric 
152b1c73532SDimitry Andric   return LLDB_INVALID_ADDRESS;
153b1c73532SDimitry Andric }
154b1c73532SDimitry Andric 
155b1c73532SDimitry Andric // Read ELF header from memry and return
ReadELFHeader(Process * process,lldb::addr_t addr,llvm::ELF::Elf32_Ehdr & header,bool * read_error)156b1c73532SDimitry Andric bool DynamicLoaderFreeBSDKernel::ReadELFHeader(Process *process,
157b1c73532SDimitry Andric                                                lldb::addr_t addr,
158b1c73532SDimitry Andric                                                llvm::ELF::Elf32_Ehdr &header,
159b1c73532SDimitry Andric                                                bool *read_error) {
160b1c73532SDimitry Andric   Status error;
161b1c73532SDimitry Andric   if (read_error)
162b1c73532SDimitry Andric     *read_error = false;
163b1c73532SDimitry Andric 
164b1c73532SDimitry Andric   if (process->ReadMemory(addr, &header, sizeof(header), error) !=
165b1c73532SDimitry Andric       sizeof(header)) {
166b1c73532SDimitry Andric     if (read_error)
167b1c73532SDimitry Andric       *read_error = true;
168b1c73532SDimitry Andric     return false;
169b1c73532SDimitry Andric   }
170b1c73532SDimitry Andric 
171b1c73532SDimitry Andric   if (!header.checkMagic())
172b1c73532SDimitry Andric     return false;
173b1c73532SDimitry Andric 
174b1c73532SDimitry Andric   return true;
175b1c73532SDimitry Andric }
176b1c73532SDimitry Andric 
177b1c73532SDimitry Andric // Check the correctness of Kernel and return UUID
CheckForKernelImageAtAddress(Process * process,lldb::addr_t addr,bool * read_error)178b1c73532SDimitry Andric lldb_private::UUID DynamicLoaderFreeBSDKernel::CheckForKernelImageAtAddress(
179b1c73532SDimitry Andric     Process *process, lldb::addr_t addr, bool *read_error) {
180b1c73532SDimitry Andric   Log *log = GetLog(LLDBLog::DynamicLoader);
181b1c73532SDimitry Andric 
182b1c73532SDimitry Andric   if (addr == LLDB_INVALID_ADDRESS) {
183b1c73532SDimitry Andric     if (read_error)
184b1c73532SDimitry Andric       *read_error = true;
185b1c73532SDimitry Andric     return UUID();
186b1c73532SDimitry Andric   }
187b1c73532SDimitry Andric 
188b1c73532SDimitry Andric   LLDB_LOGF(log,
189b1c73532SDimitry Andric             "DynamicLoaderFreeBSDKernel::CheckForKernelImageAtAddress: "
190b1c73532SDimitry Andric             "looking for kernel binary at 0x%" PRIx64,
191b1c73532SDimitry Andric             addr);
192b1c73532SDimitry Andric 
193b1c73532SDimitry Andric   llvm::ELF::Elf32_Ehdr header;
194b1c73532SDimitry Andric   if (!ReadELFHeader(process, addr, header)) {
195b1c73532SDimitry Andric     *read_error = true;
196b1c73532SDimitry Andric     return UUID();
197b1c73532SDimitry Andric   }
198b1c73532SDimitry Andric 
199b1c73532SDimitry Andric   // Check header type
200b1c73532SDimitry Andric   if (header.e_type != llvm::ELF::ET_EXEC)
201b1c73532SDimitry Andric     return UUID();
202b1c73532SDimitry Andric 
203b1c73532SDimitry Andric   ModuleSP memory_module_sp =
204b1c73532SDimitry Andric       process->ReadModuleFromMemory(FileSpec("temp_freebsd_kernel"), addr);
205b1c73532SDimitry Andric 
206b1c73532SDimitry Andric   if (!memory_module_sp.get()) {
207b1c73532SDimitry Andric     *read_error = true;
208b1c73532SDimitry Andric     return UUID();
209b1c73532SDimitry Andric   }
210b1c73532SDimitry Andric 
211b1c73532SDimitry Andric   ObjectFile *exe_objfile = memory_module_sp->GetObjectFile();
212b1c73532SDimitry Andric   if (exe_objfile == nullptr) {
213b1c73532SDimitry Andric     LLDB_LOGF(log,
214b1c73532SDimitry Andric               "DynamicLoaderFreeBSDKernel::CheckForKernelImageAtAddress "
215b1c73532SDimitry Andric               "found a binary at 0x%" PRIx64
216b1c73532SDimitry Andric               " but could not create an object file from memory",
217b1c73532SDimitry Andric               addr);
218b1c73532SDimitry Andric     return UUID();
219b1c73532SDimitry Andric   }
220b1c73532SDimitry Andric 
221b1c73532SDimitry Andric   // In here, I should check is_kernel for memory_module_sp
222b1c73532SDimitry Andric   // However, the ReadModuleFromMemory reads wrong section so that this check
223b1c73532SDimitry Andric   // will failed
224b1c73532SDimitry Andric   ArchSpec kernel_arch(llvm::ELF::convertEMachineToArchName(header.e_machine));
225b1c73532SDimitry Andric 
226b1c73532SDimitry Andric   if (!process->GetTarget().GetArchitecture().IsCompatibleMatch(kernel_arch))
227b1c73532SDimitry Andric     process->GetTarget().SetArchitecture(kernel_arch);
228b1c73532SDimitry Andric 
229b1c73532SDimitry Andric   std::string uuid_str;
230b1c73532SDimitry Andric   if (memory_module_sp->GetUUID().IsValid()) {
231b1c73532SDimitry Andric     uuid_str = "with UUID ";
232b1c73532SDimitry Andric     uuid_str += memory_module_sp->GetUUID().GetAsString();
233b1c73532SDimitry Andric   } else {
234b1c73532SDimitry Andric     uuid_str = "and no LC_UUID found in load commands ";
235b1c73532SDimitry Andric   }
236b1c73532SDimitry Andric   LLDB_LOGF(log,
237b1c73532SDimitry Andric             "DynamicLoaderFreeBSDKernel::CheckForKernelImageAtAddress: "
238b1c73532SDimitry Andric             "kernel binary image found at 0x%" PRIx64 " with arch '%s' %s",
239b1c73532SDimitry Andric             addr, kernel_arch.GetTriple().str().c_str(), uuid_str.c_str());
240b1c73532SDimitry Andric 
241b1c73532SDimitry Andric   return memory_module_sp->GetUUID();
242b1c73532SDimitry Andric }
243b1c73532SDimitry Andric 
DebuggerInit(lldb_private::Debugger & debugger)244b1c73532SDimitry Andric void DynamicLoaderFreeBSDKernel::DebuggerInit(
245b1c73532SDimitry Andric     lldb_private::Debugger &debugger) {}
246b1c73532SDimitry Andric 
DynamicLoaderFreeBSDKernel(Process * process,addr_t kernel_address)247b1c73532SDimitry Andric DynamicLoaderFreeBSDKernel::DynamicLoaderFreeBSDKernel(Process *process,
248b1c73532SDimitry Andric                                                        addr_t kernel_address)
249b1c73532SDimitry Andric     : DynamicLoader(process), m_process(process),
250b1c73532SDimitry Andric       m_linker_file_list_struct_addr(LLDB_INVALID_ADDRESS),
251b1c73532SDimitry Andric       m_linker_file_head_addr(LLDB_INVALID_ADDRESS),
252b1c73532SDimitry Andric       m_kernel_load_address(kernel_address), m_mutex() {
253b1c73532SDimitry Andric   process->SetCanRunCode(false);
254b1c73532SDimitry Andric }
255b1c73532SDimitry Andric 
~DynamicLoaderFreeBSDKernel()256b1c73532SDimitry Andric DynamicLoaderFreeBSDKernel::~DynamicLoaderFreeBSDKernel() { Clear(true); }
257b1c73532SDimitry Andric 
Update()258b1c73532SDimitry Andric void DynamicLoaderFreeBSDKernel::Update() {
259b1c73532SDimitry Andric   LoadKernelModules();
260b1c73532SDimitry Andric   SetNotificationBreakPoint();
261b1c73532SDimitry Andric }
262b1c73532SDimitry Andric 
263b1c73532SDimitry Andric // Create in memory Module at the load address
ReadMemoryModule(lldb_private::Process * process)264b1c73532SDimitry Andric bool DynamicLoaderFreeBSDKernel::KModImageInfo::ReadMemoryModule(
265b1c73532SDimitry Andric     lldb_private::Process *process) {
266b1c73532SDimitry Andric   Log *log = GetLog(LLDBLog::DynamicLoader);
267b1c73532SDimitry Andric   if (m_memory_module_sp)
268b1c73532SDimitry Andric     return true;
269b1c73532SDimitry Andric   if (m_load_address == LLDB_INVALID_ADDRESS)
270b1c73532SDimitry Andric     return false;
271b1c73532SDimitry Andric 
272b1c73532SDimitry Andric   FileSpec file_spec(m_name);
273b1c73532SDimitry Andric 
274b1c73532SDimitry Andric   ModuleSP memory_module_sp;
275b1c73532SDimitry Andric 
276b1c73532SDimitry Andric   llvm::ELF::Elf32_Ehdr elf_eheader;
277b1c73532SDimitry Andric   size_t size_to_read = 512;
278b1c73532SDimitry Andric 
279b1c73532SDimitry Andric   if (ReadELFHeader(process, m_load_address, elf_eheader)) {
280b1c73532SDimitry Andric     if (elf_eheader.e_ident[llvm::ELF::EI_CLASS] == llvm::ELF::ELFCLASS32) {
281b1c73532SDimitry Andric       size_to_read = sizeof(llvm::ELF::Elf32_Ehdr) +
282b1c73532SDimitry Andric                      elf_eheader.e_phnum * elf_eheader.e_phentsize;
283b1c73532SDimitry Andric     } else if (elf_eheader.e_ident[llvm::ELF::EI_CLASS] ==
284b1c73532SDimitry Andric                llvm::ELF::ELFCLASS64) {
285b1c73532SDimitry Andric       llvm::ELF::Elf64_Ehdr elf_eheader;
286b1c73532SDimitry Andric       Status error;
287b1c73532SDimitry Andric       if (process->ReadMemory(m_load_address, &elf_eheader, sizeof(elf_eheader),
288b1c73532SDimitry Andric                               error) == sizeof(elf_eheader))
289b1c73532SDimitry Andric         size_to_read = sizeof(llvm::ELF::Elf64_Ehdr) +
290b1c73532SDimitry Andric                        elf_eheader.e_phnum * elf_eheader.e_phentsize;
291b1c73532SDimitry Andric     }
292b1c73532SDimitry Andric   }
293b1c73532SDimitry Andric 
294b1c73532SDimitry Andric   memory_module_sp =
295b1c73532SDimitry Andric       process->ReadModuleFromMemory(file_spec, m_load_address, size_to_read);
296b1c73532SDimitry Andric 
297b1c73532SDimitry Andric   if (!memory_module_sp)
298b1c73532SDimitry Andric     return false;
299b1c73532SDimitry Andric 
300b1c73532SDimitry Andric   bool this_is_kernel = is_kernel(memory_module_sp.get());
301b1c73532SDimitry Andric 
302b1c73532SDimitry Andric   if (!m_uuid.IsValid() && memory_module_sp->GetUUID().IsValid())
303b1c73532SDimitry Andric     m_uuid = memory_module_sp->GetUUID();
304b1c73532SDimitry Andric 
305b1c73532SDimitry Andric   m_memory_module_sp = memory_module_sp;
306b1c73532SDimitry Andric   m_is_kernel = this_is_kernel;
307b1c73532SDimitry Andric 
308b1c73532SDimitry Andric   // The kernel binary is from memory
309b1c73532SDimitry Andric   if (this_is_kernel) {
310b1c73532SDimitry Andric     LLDB_LOGF(log, "KextImageInfo::ReadMemoryModule read the kernel binary out "
311b1c73532SDimitry Andric                    "of memory");
312b1c73532SDimitry Andric 
313b1c73532SDimitry Andric     if (memory_module_sp->GetArchitecture().IsValid())
314b1c73532SDimitry Andric       process->GetTarget().SetArchitecture(memory_module_sp->GetArchitecture());
315b1c73532SDimitry Andric   }
316b1c73532SDimitry Andric 
317b1c73532SDimitry Andric   return true;
318b1c73532SDimitry Andric }
319b1c73532SDimitry Andric 
LoadImageUsingMemoryModule(lldb_private::Process * process)320b1c73532SDimitry Andric bool DynamicLoaderFreeBSDKernel::KModImageInfo::LoadImageUsingMemoryModule(
321b1c73532SDimitry Andric     lldb_private::Process *process) {
322b1c73532SDimitry Andric   Log *log = GetLog(LLDBLog::DynamicLoader);
323b1c73532SDimitry Andric 
324b1c73532SDimitry Andric   if (IsLoaded())
325b1c73532SDimitry Andric     return true;
326b1c73532SDimitry Andric 
327b1c73532SDimitry Andric   Target &target = process->GetTarget();
328b1c73532SDimitry Andric 
329b1c73532SDimitry Andric   if (IsKernel() && m_uuid.IsValid()) {
330b1c73532SDimitry Andric     Stream &s = target.GetDebugger().GetOutputStream();
331b1c73532SDimitry Andric     s.Printf("Kernel UUID: %s\n", m_uuid.GetAsString().c_str());
332b1c73532SDimitry Andric     s.Printf("Load Address: 0x%" PRIx64 "\n", m_load_address);
333b1c73532SDimitry Andric   }
334b1c73532SDimitry Andric 
335b1c73532SDimitry Andric   // Test if the module is loaded into the taget,
336b1c73532SDimitry Andric   // maybe the module is loaded manually by user by doing target module add
337b1c73532SDimitry Andric   // So that we have to create the module manually
338b1c73532SDimitry Andric   if (!m_module_sp) {
339b1c73532SDimitry Andric     const ModuleList &target_images = target.GetImages();
340b1c73532SDimitry Andric     m_module_sp = target_images.FindModule(m_uuid);
341b1c73532SDimitry Andric 
342b1c73532SDimitry Andric     // Search in the file system
343b1c73532SDimitry Andric     if (!m_module_sp) {
344b1c73532SDimitry Andric       ModuleSpec module_spec(FileSpec(GetPath()), target.GetArchitecture());
345b1c73532SDimitry Andric       if (IsKernel()) {
346b1c73532SDimitry Andric         Status error;
347b1c73532SDimitry Andric         if (PluginManager::DownloadObjectAndSymbolFile(module_spec, error,
348b1c73532SDimitry Andric                                                        true)) {
349b1c73532SDimitry Andric           if (FileSystem::Instance().Exists(module_spec.GetFileSpec()))
350b1c73532SDimitry Andric             m_module_sp = std::make_shared<Module>(module_spec.GetFileSpec(),
351b1c73532SDimitry Andric                                                    target.GetArchitecture());
352b1c73532SDimitry Andric         }
353b1c73532SDimitry Andric       }
354b1c73532SDimitry Andric 
355b1c73532SDimitry Andric       if (!m_module_sp)
356b1c73532SDimitry Andric         m_module_sp = target.GetOrCreateModule(module_spec, true);
357b1c73532SDimitry Andric       if (IsKernel() && !m_module_sp) {
358b1c73532SDimitry Andric         Stream &s = target.GetDebugger().GetOutputStream();
359b1c73532SDimitry Andric         s.Printf("WARNING: Unable to locate kernel binary on the debugger "
360b1c73532SDimitry Andric                  "system.\n");
361b1c73532SDimitry Andric       }
362b1c73532SDimitry Andric     }
363b1c73532SDimitry Andric 
364b1c73532SDimitry Andric     if (m_module_sp) {
365b1c73532SDimitry Andric       // If the file is not kernel or kmod, the target should be loaded once and
366b1c73532SDimitry Andric       // don't reload again
367b1c73532SDimitry Andric       if (!IsKernel() && !is_kmod(m_module_sp.get())) {
368b1c73532SDimitry Andric         ModuleSP existing_module_sp = target.GetImages().FindModule(m_uuid);
369b1c73532SDimitry Andric         if (existing_module_sp &&
370b1c73532SDimitry Andric             existing_module_sp->IsLoadedInTarget(&target)) {
371b1c73532SDimitry Andric           LLDB_LOGF(log,
372b1c73532SDimitry Andric                     "'%s' with UUID %s is not a kmod or kernel, and is "
373b1c73532SDimitry Andric                     "already registered in target, not loading.",
374b1c73532SDimitry Andric                     m_name.c_str(), m_uuid.GetAsString().c_str());
375b1c73532SDimitry Andric           return true;
376b1c73532SDimitry Andric         }
377b1c73532SDimitry Andric       }
378b1c73532SDimitry Andric       m_uuid = m_module_sp->GetUUID();
379b1c73532SDimitry Andric 
380b1c73532SDimitry Andric       // or append to the images
381b1c73532SDimitry Andric       target.GetImages().AppendIfNeeded(m_module_sp, false);
382b1c73532SDimitry Andric     }
383b1c73532SDimitry Andric   }
384b1c73532SDimitry Andric 
385b1c73532SDimitry Andric   // If this file is relocatable kernel module(x86_64), adjust it's
386b1c73532SDimitry Andric   // section(PT_LOAD segment) and return Because the kernel module's load
387b1c73532SDimitry Andric   // address is the text section. lldb cannot create full memory module upon
388b1c73532SDimitry Andric   // relocatable file So what we do is to set the load address only.
389b1c73532SDimitry Andric   if (is_kmod(m_module_sp.get()) && is_reloc(m_module_sp.get())) {
390b1c73532SDimitry Andric     m_stop_id = process->GetStopID();
391b1c73532SDimitry Andric     bool changed = false;
392b1c73532SDimitry Andric     m_module_sp->SetLoadAddress(target, m_load_address, true, changed);
393b1c73532SDimitry Andric     return true;
394b1c73532SDimitry Andric   }
395b1c73532SDimitry Andric 
396b1c73532SDimitry Andric   if (m_module_sp)
397b1c73532SDimitry Andric     ReadMemoryModule(process);
398b1c73532SDimitry Andric 
399b1c73532SDimitry Andric   // Calculate the slides of in memory module
400b1c73532SDimitry Andric   if (!m_memory_module_sp || !m_module_sp) {
401b1c73532SDimitry Andric     m_module_sp.reset();
402b1c73532SDimitry Andric     return false;
403b1c73532SDimitry Andric   }
404b1c73532SDimitry Andric 
405b1c73532SDimitry Andric   ObjectFile *ondisk_object_file = m_module_sp->GetObjectFile();
406b1c73532SDimitry Andric   ObjectFile *memory_object_file = m_memory_module_sp->GetObjectFile();
407b1c73532SDimitry Andric 
408b1c73532SDimitry Andric   if (!ondisk_object_file || !memory_object_file)
409b1c73532SDimitry Andric     m_module_sp.reset();
410b1c73532SDimitry Andric 
411b1c73532SDimitry Andric   // Find the slide address
412b1c73532SDimitry Andric   addr_t fixed_slide = LLDB_INVALID_ADDRESS;
413ac9a064cSDimitry Andric   if (llvm::dyn_cast<ObjectFileELF>(memory_object_file)) {
414b1c73532SDimitry Andric     addr_t load_address = memory_object_file->GetBaseAddress().GetFileAddress();
415b1c73532SDimitry Andric 
416b1c73532SDimitry Andric     if (load_address != LLDB_INVALID_ADDRESS &&
417b1c73532SDimitry Andric         m_load_address != load_address) {
418b1c73532SDimitry Andric       fixed_slide = m_load_address - load_address;
419b1c73532SDimitry Andric       LLDB_LOGF(log,
420b1c73532SDimitry Andric                 "kmod %s in-memory LOAD vmaddr is not correct, using a "
421b1c73532SDimitry Andric                 "fixed slide of 0x%" PRIx64,
422b1c73532SDimitry Andric                 m_name.c_str(), fixed_slide);
423b1c73532SDimitry Andric     }
424b1c73532SDimitry Andric   }
425b1c73532SDimitry Andric 
426b1c73532SDimitry Andric   SectionList *ondisk_section_list = ondisk_object_file->GetSectionList();
427b1c73532SDimitry Andric   SectionList *memory_section_list = memory_object_file->GetSectionList();
428b1c73532SDimitry Andric 
429b1c73532SDimitry Andric   if (memory_section_list && ondisk_object_file) {
430b1c73532SDimitry Andric     const uint32_t num_ondisk_sections = ondisk_section_list->GetSize();
431b1c73532SDimitry Andric     uint32_t num_load_sections = 0;
432b1c73532SDimitry Andric 
433b1c73532SDimitry Andric     for (uint32_t section_idx = 0; section_idx < num_ondisk_sections;
434b1c73532SDimitry Andric          ++section_idx) {
435b1c73532SDimitry Andric       SectionSP on_disk_section_sp =
436b1c73532SDimitry Andric           ondisk_section_list->GetSectionAtIndex(section_idx);
437b1c73532SDimitry Andric 
438b1c73532SDimitry Andric       if (!on_disk_section_sp)
439b1c73532SDimitry Andric         continue;
440b1c73532SDimitry Andric       if (fixed_slide != LLDB_INVALID_ADDRESS) {
441b1c73532SDimitry Andric         target.SetSectionLoadAddress(on_disk_section_sp,
442b1c73532SDimitry Andric                                      on_disk_section_sp->GetFileAddress() +
443b1c73532SDimitry Andric                                          fixed_slide);
444b1c73532SDimitry Andric 
445b1c73532SDimitry Andric       } else {
446b1c73532SDimitry Andric         const Section *memory_section =
447b1c73532SDimitry Andric             memory_section_list
448b1c73532SDimitry Andric                 ->FindSectionByName(on_disk_section_sp->GetName())
449b1c73532SDimitry Andric                 .get();
450b1c73532SDimitry Andric         if (memory_section) {
451b1c73532SDimitry Andric           target.SetSectionLoadAddress(on_disk_section_sp,
452b1c73532SDimitry Andric                                        memory_section->GetFileAddress());
453b1c73532SDimitry Andric           ++num_load_sections;
454b1c73532SDimitry Andric         }
455b1c73532SDimitry Andric       }
456b1c73532SDimitry Andric     }
457b1c73532SDimitry Andric 
458b1c73532SDimitry Andric     if (num_load_sections)
459b1c73532SDimitry Andric       m_stop_id = process->GetStopID();
460b1c73532SDimitry Andric     else
461b1c73532SDimitry Andric       m_module_sp.reset();
462b1c73532SDimitry Andric   } else {
463b1c73532SDimitry Andric     m_module_sp.reset();
464b1c73532SDimitry Andric   }
465b1c73532SDimitry Andric 
466b1c73532SDimitry Andric   if (IsLoaded() && m_module_sp && IsKernel()) {
467b1c73532SDimitry Andric     Stream &s = target.GetDebugger().GetOutputStream();
468b1c73532SDimitry Andric     ObjectFile *kernel_object_file = m_module_sp->GetObjectFile();
469b1c73532SDimitry Andric     if (kernel_object_file) {
470b1c73532SDimitry Andric       addr_t file_address =
471b1c73532SDimitry Andric           kernel_object_file->GetBaseAddress().GetFileAddress();
472b1c73532SDimitry Andric       if (m_load_address != LLDB_INVALID_ADDRESS &&
473b1c73532SDimitry Andric           file_address != LLDB_INVALID_ADDRESS) {
474b1c73532SDimitry Andric         s.Printf("Kernel slide 0x%" PRIx64 " in memory.\n",
475b1c73532SDimitry Andric                  m_load_address - file_address);
476b1c73532SDimitry Andric         s.Printf("Loaded kernel file %s\n",
477b1c73532SDimitry Andric                  m_module_sp->GetFileSpec().GetPath().c_str());
478b1c73532SDimitry Andric       }
479b1c73532SDimitry Andric     }
480b1c73532SDimitry Andric     s.Flush();
481b1c73532SDimitry Andric   }
482b1c73532SDimitry Andric 
483b1c73532SDimitry Andric   return IsLoaded();
484b1c73532SDimitry Andric }
485b1c73532SDimitry Andric 
486b1c73532SDimitry Andric // This function is work for kernel file, others it wil reset load address and
487b1c73532SDimitry Andric // return false
LoadImageUsingFileAddress(lldb_private::Process * process)488b1c73532SDimitry Andric bool DynamicLoaderFreeBSDKernel::KModImageInfo::LoadImageUsingFileAddress(
489b1c73532SDimitry Andric     lldb_private::Process *process) {
490b1c73532SDimitry Andric   if (IsLoaded())
491b1c73532SDimitry Andric     return true;
492b1c73532SDimitry Andric 
493b1c73532SDimitry Andric   if (m_module_sp) {
494b1c73532SDimitry Andric     bool changed = false;
495b1c73532SDimitry Andric     if (m_module_sp->SetLoadAddress(process->GetTarget(), 0, true, changed))
496b1c73532SDimitry Andric       m_stop_id = process->GetStopID();
497b1c73532SDimitry Andric   }
498b1c73532SDimitry Andric 
499b1c73532SDimitry Andric   return false;
500b1c73532SDimitry Andric }
501b1c73532SDimitry Andric 
502b1c73532SDimitry Andric // Get the head of found_list
ReadKmodsListHeader()503b1c73532SDimitry Andric bool DynamicLoaderFreeBSDKernel::ReadKmodsListHeader() {
504b1c73532SDimitry Andric   std::lock_guard<decltype(m_mutex)> guard(m_mutex);
505b1c73532SDimitry Andric 
506b1c73532SDimitry Andric   if (m_linker_file_list_struct_addr.IsValid()) {
507b1c73532SDimitry Andric     // Get tqh_first struct element from linker_files
508b1c73532SDimitry Andric     Status error;
509b1c73532SDimitry Andric     addr_t address = m_process->ReadPointerFromMemory(
510b1c73532SDimitry Andric         m_linker_file_list_struct_addr.GetLoadAddress(&m_process->GetTarget()),
511b1c73532SDimitry Andric         error);
512b1c73532SDimitry Andric     if (address != LLDB_INVALID_ADDRESS && error.Success()) {
513b1c73532SDimitry Andric       m_linker_file_head_addr = Address(address);
514b1c73532SDimitry Andric     } else {
515b1c73532SDimitry Andric       m_linker_file_list_struct_addr.Clear();
516b1c73532SDimitry Andric       return false;
517b1c73532SDimitry Andric     }
518b1c73532SDimitry Andric 
519b1c73532SDimitry Andric     if (!m_linker_file_head_addr.IsValid() ||
520b1c73532SDimitry Andric         m_linker_file_head_addr.GetFileAddress() == 0) {
521b1c73532SDimitry Andric       m_linker_file_list_struct_addr.Clear();
522b1c73532SDimitry Andric       return false;
523b1c73532SDimitry Andric     }
524b1c73532SDimitry Andric   }
525b1c73532SDimitry Andric   return true;
526b1c73532SDimitry Andric }
527b1c73532SDimitry Andric 
528b1c73532SDimitry Andric // Parse Kmod info in found_list
ParseKmods(Address linker_files_head_addr)529b1c73532SDimitry Andric bool DynamicLoaderFreeBSDKernel::ParseKmods(Address linker_files_head_addr) {
530b1c73532SDimitry Andric   std::lock_guard<decltype(m_mutex)> guard(m_mutex);
531b1c73532SDimitry Andric   KModImageInfo::collection_type linker_files_list;
532b1c73532SDimitry Andric   Log *log = GetLog(LLDBLog::DynamicLoader);
533b1c73532SDimitry Andric 
534b1c73532SDimitry Andric   if (!ReadAllKmods(linker_files_head_addr, linker_files_list))
535b1c73532SDimitry Andric     return false;
536b1c73532SDimitry Andric   LLDB_LOGF(
537b1c73532SDimitry Andric       log,
538b1c73532SDimitry Andric       "Kmod-changed breakpoint hit, there are %zu kernel modules currently.\n",
539b1c73532SDimitry Andric       linker_files_list.size());
540b1c73532SDimitry Andric 
541b1c73532SDimitry Andric   ModuleList &modules = m_process->GetTarget().GetImages();
542b1c73532SDimitry Andric   ModuleList remove_modules;
543b1c73532SDimitry Andric   ModuleList add_modules;
544b1c73532SDimitry Andric 
545b1c73532SDimitry Andric   for (ModuleSP module : modules.Modules()) {
546b1c73532SDimitry Andric     if (is_kernel(module.get()))
547b1c73532SDimitry Andric       continue;
548b1c73532SDimitry Andric     if (is_kmod(module.get()))
549b1c73532SDimitry Andric       remove_modules.AppendIfNeeded(module);
550b1c73532SDimitry Andric   }
551b1c73532SDimitry Andric 
552b1c73532SDimitry Andric   m_process->GetTarget().ModulesDidUnload(remove_modules, false);
553b1c73532SDimitry Andric 
554b1c73532SDimitry Andric   for (KModImageInfo &image_info : linker_files_list) {
555b1c73532SDimitry Andric     if (m_kld_name_to_uuid.find(image_info.GetName()) !=
556b1c73532SDimitry Andric         m_kld_name_to_uuid.end())
557b1c73532SDimitry Andric       image_info.SetUUID(m_kld_name_to_uuid[image_info.GetName()]);
558b1c73532SDimitry Andric     bool failed_to_load = false;
559b1c73532SDimitry Andric     if (!image_info.LoadImageUsingMemoryModule(m_process)) {
560b1c73532SDimitry Andric       image_info.LoadImageUsingFileAddress(m_process);
561b1c73532SDimitry Andric       failed_to_load = true;
562b1c73532SDimitry Andric     } else {
563b1c73532SDimitry Andric       m_linker_files_list.push_back(image_info);
564b1c73532SDimitry Andric       m_kld_name_to_uuid[image_info.GetName()] = image_info.GetUUID();
565b1c73532SDimitry Andric     }
566b1c73532SDimitry Andric 
567b1c73532SDimitry Andric     if (!failed_to_load)
568b1c73532SDimitry Andric       add_modules.AppendIfNeeded(image_info.GetModule());
569b1c73532SDimitry Andric   }
570b1c73532SDimitry Andric   m_process->GetTarget().ModulesDidLoad(add_modules);
571b1c73532SDimitry Andric   return true;
572b1c73532SDimitry Andric }
573b1c73532SDimitry Andric 
574b1c73532SDimitry Andric // Read all kmod from a given arrays of list
ReadAllKmods(Address linker_files_head_addr,KModImageInfo::collection_type & kmods_list)575b1c73532SDimitry Andric bool DynamicLoaderFreeBSDKernel::ReadAllKmods(
576b1c73532SDimitry Andric     Address linker_files_head_addr,
577b1c73532SDimitry Andric     KModImageInfo::collection_type &kmods_list) {
578b1c73532SDimitry Andric 
579b1c73532SDimitry Andric   // Get offset of next member and load address symbol
580b1c73532SDimitry Andric   static ConstString kld_off_address_symbol_name("kld_off_address");
581b1c73532SDimitry Andric   static ConstString kld_off_next_symbol_name("kld_off_next");
582b1c73532SDimitry Andric   static ConstString kld_off_filename_symbol_name("kld_off_filename");
583b1c73532SDimitry Andric   static ConstString kld_off_pathname_symbol_name("kld_off_pathname");
584b1c73532SDimitry Andric   const Symbol *kld_off_address_symbol =
585b1c73532SDimitry Andric       m_kernel_image_info.GetModule()->FindFirstSymbolWithNameAndType(
586b1c73532SDimitry Andric           kld_off_address_symbol_name, eSymbolTypeData);
587b1c73532SDimitry Andric   const Symbol *kld_off_next_symbol =
588b1c73532SDimitry Andric       m_kernel_image_info.GetModule()->FindFirstSymbolWithNameAndType(
589b1c73532SDimitry Andric           kld_off_next_symbol_name, eSymbolTypeData);
590b1c73532SDimitry Andric   const Symbol *kld_off_filename_symbol =
591b1c73532SDimitry Andric       m_kernel_image_info.GetModule()->FindFirstSymbolWithNameAndType(
592b1c73532SDimitry Andric           kld_off_filename_symbol_name, eSymbolTypeData);
593b1c73532SDimitry Andric   const Symbol *kld_off_pathname_symbol =
594b1c73532SDimitry Andric       m_kernel_image_info.GetModule()->FindFirstSymbolWithNameAndType(
595b1c73532SDimitry Andric           kld_off_pathname_symbol_name, eSymbolTypeData);
596b1c73532SDimitry Andric 
597b1c73532SDimitry Andric   if (!kld_off_address_symbol || !kld_off_next_symbol ||
598b1c73532SDimitry Andric       !kld_off_filename_symbol || !kld_off_pathname_symbol)
599b1c73532SDimitry Andric     return false;
600b1c73532SDimitry Andric 
601b1c73532SDimitry Andric   Status error;
602b1c73532SDimitry Andric   const int32_t kld_off_address = m_process->ReadSignedIntegerFromMemory(
603b1c73532SDimitry Andric       kld_off_address_symbol->GetAddress().GetLoadAddress(
604b1c73532SDimitry Andric           &m_process->GetTarget()),
605b1c73532SDimitry Andric       4, 0, error);
606b1c73532SDimitry Andric   if (error.Fail())
607b1c73532SDimitry Andric     return false;
608b1c73532SDimitry Andric   const int32_t kld_off_next = m_process->ReadSignedIntegerFromMemory(
609b1c73532SDimitry Andric       kld_off_next_symbol->GetAddress().GetLoadAddress(&m_process->GetTarget()),
610b1c73532SDimitry Andric       4, 0, error);
611b1c73532SDimitry Andric   if (error.Fail())
612b1c73532SDimitry Andric     return false;
613b1c73532SDimitry Andric   const int32_t kld_off_filename = m_process->ReadSignedIntegerFromMemory(
614b1c73532SDimitry Andric       kld_off_filename_symbol->GetAddress().GetLoadAddress(
615b1c73532SDimitry Andric           &m_process->GetTarget()),
616b1c73532SDimitry Andric       4, 0, error);
617b1c73532SDimitry Andric   if (error.Fail())
618b1c73532SDimitry Andric     return false;
619b1c73532SDimitry Andric 
620b1c73532SDimitry Andric   const int32_t kld_off_pathname = m_process->ReadSignedIntegerFromMemory(
621b1c73532SDimitry Andric       kld_off_pathname_symbol->GetAddress().GetLoadAddress(
622b1c73532SDimitry Andric           &m_process->GetTarget()),
623b1c73532SDimitry Andric       4, 0, error);
624b1c73532SDimitry Andric   if (error.Fail())
625b1c73532SDimitry Andric     return false;
626b1c73532SDimitry Andric 
627b1c73532SDimitry Andric   // Parse KMods
628b1c73532SDimitry Andric   addr_t kld_load_addr(LLDB_INVALID_ADDRESS);
629b1c73532SDimitry Andric   char kld_filename[255];
630b1c73532SDimitry Andric   char kld_pathname[255];
631b1c73532SDimitry Andric   addr_t current_kld =
632b1c73532SDimitry Andric       linker_files_head_addr.GetLoadAddress(&m_process->GetTarget());
633b1c73532SDimitry Andric 
634b1c73532SDimitry Andric   while (current_kld != 0) {
635b1c73532SDimitry Andric     addr_t kld_filename_addr =
636b1c73532SDimitry Andric         m_process->ReadPointerFromMemory(current_kld + kld_off_filename, error);
637b1c73532SDimitry Andric     if (error.Fail())
638b1c73532SDimitry Andric       return false;
639b1c73532SDimitry Andric     addr_t kld_pathname_addr =
640b1c73532SDimitry Andric         m_process->ReadPointerFromMemory(current_kld + kld_off_pathname, error);
641b1c73532SDimitry Andric     if (error.Fail())
642b1c73532SDimitry Andric       return false;
643b1c73532SDimitry Andric 
644b1c73532SDimitry Andric     m_process->ReadCStringFromMemory(kld_filename_addr, kld_filename,
645b1c73532SDimitry Andric                                      sizeof(kld_filename), error);
646b1c73532SDimitry Andric     if (error.Fail())
647b1c73532SDimitry Andric       return false;
648b1c73532SDimitry Andric     m_process->ReadCStringFromMemory(kld_pathname_addr, kld_pathname,
649b1c73532SDimitry Andric                                      sizeof(kld_pathname), error);
650b1c73532SDimitry Andric     if (error.Fail())
651b1c73532SDimitry Andric       return false;
652b1c73532SDimitry Andric     kld_load_addr =
653b1c73532SDimitry Andric         m_process->ReadPointerFromMemory(current_kld + kld_off_address, error);
654b1c73532SDimitry Andric     if (error.Fail())
655b1c73532SDimitry Andric       return false;
656b1c73532SDimitry Andric 
657b1c73532SDimitry Andric     kmods_list.emplace_back();
658b1c73532SDimitry Andric     KModImageInfo &kmod_info = kmods_list.back();
659b1c73532SDimitry Andric     kmod_info.SetName(kld_filename);
660b1c73532SDimitry Andric     kmod_info.SetLoadAddress(kld_load_addr);
661b1c73532SDimitry Andric     kmod_info.SetPath(kld_pathname);
662b1c73532SDimitry Andric 
663b1c73532SDimitry Andric     current_kld =
664b1c73532SDimitry Andric         m_process->ReadPointerFromMemory(current_kld + kld_off_next, error);
665b1c73532SDimitry Andric     if (kmod_info.GetName() == "kernel")
666b1c73532SDimitry Andric       kmods_list.pop_back();
667b1c73532SDimitry Andric     if (error.Fail())
668b1c73532SDimitry Andric       return false;
669b1c73532SDimitry Andric   }
670b1c73532SDimitry Andric 
671b1c73532SDimitry Andric   return true;
672b1c73532SDimitry Andric }
673b1c73532SDimitry Andric 
674b1c73532SDimitry Andric // Read all kmods
ReadAllKmods()675b1c73532SDimitry Andric void DynamicLoaderFreeBSDKernel::ReadAllKmods() {
676b1c73532SDimitry Andric   std::lock_guard<decltype(m_mutex)> guard(m_mutex);
677b1c73532SDimitry Andric 
678b1c73532SDimitry Andric   if (ReadKmodsListHeader()) {
679b1c73532SDimitry Andric     if (m_linker_file_head_addr.IsValid()) {
680b1c73532SDimitry Andric       if (!ParseKmods(m_linker_file_head_addr))
681b1c73532SDimitry Andric         m_linker_files_list.clear();
682b1c73532SDimitry Andric     }
683b1c73532SDimitry Andric   }
684b1c73532SDimitry Andric }
685b1c73532SDimitry Andric 
686b1c73532SDimitry Andric // Load all Kernel Modules
LoadKernelModules()687b1c73532SDimitry Andric void DynamicLoaderFreeBSDKernel::LoadKernelModules() {
688b1c73532SDimitry Andric   Log *log = GetLog(LLDBLog::DynamicLoader);
689b1c73532SDimitry Andric   LLDB_LOGF(log, "DynamicLoaderFreeBSDKernel::LoadKernelModules "
690b1c73532SDimitry Andric                  "Start loading Kernel Module");
691b1c73532SDimitry Andric 
692b1c73532SDimitry Andric   // Initialize Kernel Image Information at the first time
693b1c73532SDimitry Andric   if (m_kernel_image_info.GetLoadAddress() == LLDB_INVALID_ADDRESS) {
694b1c73532SDimitry Andric     ModuleSP module_sp = m_process->GetTarget().GetExecutableModule();
695b1c73532SDimitry Andric     if (is_kernel(module_sp.get())) {
696b1c73532SDimitry Andric       m_kernel_image_info.SetModule(module_sp);
697b1c73532SDimitry Andric       m_kernel_image_info.SetIsKernel(true);
698b1c73532SDimitry Andric     }
699b1c73532SDimitry Andric 
700b1c73532SDimitry Andric     // Set name for kernel
701b1c73532SDimitry Andric     llvm::StringRef kernel_name("freebsd_kernel");
702b1c73532SDimitry Andric     module_sp = m_kernel_image_info.GetModule();
703b1c73532SDimitry Andric     if (module_sp.get() && module_sp->GetObjectFile() &&
704b1c73532SDimitry Andric         !module_sp->GetObjectFile()->GetFileSpec().GetFilename().IsEmpty())
705b1c73532SDimitry Andric       kernel_name = module_sp->GetObjectFile()
706b1c73532SDimitry Andric                         ->GetFileSpec()
707b1c73532SDimitry Andric                         .GetFilename()
708b1c73532SDimitry Andric                         .GetStringRef();
709b1c73532SDimitry Andric     m_kernel_image_info.SetName(kernel_name.data());
710b1c73532SDimitry Andric 
711b1c73532SDimitry Andric     if (m_kernel_image_info.GetLoadAddress() == LLDB_INVALID_ADDRESS) {
712b1c73532SDimitry Andric       m_kernel_image_info.SetLoadAddress(m_kernel_load_address);
713b1c73532SDimitry Andric     }
714b1c73532SDimitry Andric 
715b1c73532SDimitry Andric     // Build In memory Module
716b1c73532SDimitry Andric     if (m_kernel_image_info.GetLoadAddress() != LLDB_INVALID_ADDRESS) {
717b1c73532SDimitry Andric       // If the kernel is not loaded in the memory, use file to load
718b1c73532SDimitry Andric       if (!m_kernel_image_info.LoadImageUsingMemoryModule(m_process))
719b1c73532SDimitry Andric         m_kernel_image_info.LoadImageUsingFileAddress(m_process);
720b1c73532SDimitry Andric     }
721b1c73532SDimitry Andric   }
722b1c73532SDimitry Andric 
723b1c73532SDimitry Andric   LoadOperatingSystemPlugin(false);
724b1c73532SDimitry Andric 
725b1c73532SDimitry Andric   if (!m_kernel_image_info.IsLoaded() || !m_kernel_image_info.GetModule()) {
726b1c73532SDimitry Andric     m_kernel_image_info.Clear();
727b1c73532SDimitry Andric     return;
728b1c73532SDimitry Andric   }
729b1c73532SDimitry Andric 
730b1c73532SDimitry Andric   static ConstString modlist_symbol_name("linker_files");
731b1c73532SDimitry Andric 
732b1c73532SDimitry Andric   const Symbol *symbol =
733b1c73532SDimitry Andric       m_kernel_image_info.GetModule()->FindFirstSymbolWithNameAndType(
734b1c73532SDimitry Andric           modlist_symbol_name, lldb::eSymbolTypeData);
735b1c73532SDimitry Andric 
736b1c73532SDimitry Andric   if (symbol) {
737b1c73532SDimitry Andric     m_linker_file_list_struct_addr = symbol->GetAddress();
738b1c73532SDimitry Andric     ReadAllKmods();
739b1c73532SDimitry Andric   } else {
740b1c73532SDimitry Andric     LLDB_LOGF(log, "DynamicLoaderFreeBSDKernel::LoadKernelModules "
741b1c73532SDimitry Andric                    "cannot file modlist symbol");
742b1c73532SDimitry Andric   }
743b1c73532SDimitry Andric }
744b1c73532SDimitry Andric 
745b1c73532SDimitry Andric // Update symbol when use kldload by setting callback function on kldload
SetNotificationBreakPoint()746b1c73532SDimitry Andric void DynamicLoaderFreeBSDKernel::SetNotificationBreakPoint() {}
747b1c73532SDimitry Andric 
748b1c73532SDimitry Andric // Hook called when attach to a process
DidAttach()749b1c73532SDimitry Andric void DynamicLoaderFreeBSDKernel::DidAttach() {
750b1c73532SDimitry Andric   PrivateInitialize(m_process);
751b1c73532SDimitry Andric   Update();
752b1c73532SDimitry Andric }
753b1c73532SDimitry Andric 
754b1c73532SDimitry Andric // Hook called after attach to a process
DidLaunch()755b1c73532SDimitry Andric void DynamicLoaderFreeBSDKernel::DidLaunch() {
756b1c73532SDimitry Andric   PrivateInitialize(m_process);
757b1c73532SDimitry Andric   Update();
758b1c73532SDimitry Andric }
759b1c73532SDimitry Andric 
760b1c73532SDimitry Andric // Clear all member except kernel address
Clear(bool clear_process)761b1c73532SDimitry Andric void DynamicLoaderFreeBSDKernel::Clear(bool clear_process) {
762b1c73532SDimitry Andric   std::lock_guard<decltype(m_mutex)> guard(m_mutex);
763b1c73532SDimitry Andric   if (clear_process)
764b1c73532SDimitry Andric     m_process = nullptr;
765b1c73532SDimitry Andric   m_linker_file_head_addr.Clear();
766b1c73532SDimitry Andric   m_linker_file_list_struct_addr.Clear();
767b1c73532SDimitry Andric   m_kernel_image_info.Clear();
768b1c73532SDimitry Andric   m_linker_files_list.clear();
769b1c73532SDimitry Andric }
770b1c73532SDimitry Andric 
771b1c73532SDimitry Andric // Reinitialize class
PrivateInitialize(Process * process)772b1c73532SDimitry Andric void DynamicLoaderFreeBSDKernel::PrivateInitialize(Process *process) {
773b1c73532SDimitry Andric   Clear(true);
774b1c73532SDimitry Andric   m_process = process;
775b1c73532SDimitry Andric }
776b1c73532SDimitry Andric 
GetStepThroughTrampolinePlan(lldb_private::Thread & thread,bool stop_others)777b1c73532SDimitry Andric ThreadPlanSP DynamicLoaderFreeBSDKernel::GetStepThroughTrampolinePlan(
778b1c73532SDimitry Andric     lldb_private::Thread &thread, bool stop_others) {
779b1c73532SDimitry Andric   Log *log = GetLog(LLDBLog::Step);
780b1c73532SDimitry Andric   LLDB_LOGF(log, "DynamicLoaderFreeBSDKernel::GetStepThroughTrampolinePlan is "
781b1c73532SDimitry Andric                  "not yet implemented.");
782b1c73532SDimitry Andric   return {};
783b1c73532SDimitry Andric }
784b1c73532SDimitry Andric 
CanLoadImage()785b1c73532SDimitry Andric Status DynamicLoaderFreeBSDKernel::CanLoadImage() {
786b1c73532SDimitry Andric   Status error("shared object cannot be loaded into kernel");
787b1c73532SDimitry Andric   return error;
788b1c73532SDimitry Andric }
789