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