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