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