1//===-- DynamicLoaderDarwinKernel.cpp -------------------------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
9#include "Plugins/ObjectFile/Mach-O/ObjectFileMachO.h"
10#include "Plugins/Platform/MacOSX/PlatformDarwinKernel.h"
11#include "lldb/Breakpoint/StoppointCallbackContext.h"
12#include "lldb/Core/Debugger.h"
13#include "lldb/Core/Module.h"
14#include "lldb/Core/ModuleSpec.h"
15#include "lldb/Core/PluginManager.h"
16#include "lldb/Core/Progress.h"
17#include "lldb/Core/Section.h"
18#include "lldb/Interpreter/OptionValueProperties.h"
19#include "lldb/Symbol/ObjectFile.h"
20#include "lldb/Target/OperatingSystem.h"
21#include "lldb/Target/RegisterContext.h"
22#include "lldb/Target/StackFrame.h"
23#include "lldb/Target/Target.h"
24#include "lldb/Target/Thread.h"
25#include "lldb/Target/ThreadPlanRunToAddress.h"
26#include "lldb/Utility/AddressableBits.h"
27#include "lldb/Utility/DataBuffer.h"
28#include "lldb/Utility/DataBufferHeap.h"
29#include "lldb/Utility/LLDBLog.h"
30#include "lldb/Utility/Log.h"
31#include "lldb/Utility/State.h"
32
33#include "DynamicLoaderDarwinKernel.h"
34
35#include <algorithm>
36#include <memory>
37
38//#define ENABLE_DEBUG_PRINTF // COMMENT THIS LINE OUT PRIOR TO CHECKIN
39#ifdef ENABLE_DEBUG_PRINTF
40#include <cstdio>
41#define DEBUG_PRINTF(fmt, ...) printf(fmt, ##__VA_ARGS__)
42#else
43#define DEBUG_PRINTF(fmt, ...)
44#endif
45
46using namespace lldb;
47using namespace lldb_private;
48
49LLDB_PLUGIN_DEFINE(DynamicLoaderDarwinKernel)
50
51// Progressively greater amounts of scanning we will allow For some targets
52// very early in startup, we can't do any random reads of memory or we can
53// crash the device so a setting is needed that can completely disable the
54// KASLR scans.
55
56enum KASLRScanType {
57 eKASLRScanNone = 0, // No reading into the inferior at all
58 eKASLRScanLowgloAddresses, // Check one word of memory for a possible kernel
59 // addr, then see if a kernel is there
60 eKASLRScanNearPC, // Scan backwards from the current $pc looking for kernel;
61 // checking at 96 locations total
62 eKASLRScanExhaustiveScan // Scan through the entire possible kernel address
63 // range looking for a kernel
64};
65
66static constexpr OptionEnumValueElement g_kaslr_kernel_scan_enum_values[] = {
67 {
68 .value: eKASLRScanNone,
69 .string_value: "none",
70 .usage: "Do not read memory looking for a Darwin kernel when attaching.",
71 },
72 {
73 .value: eKASLRScanLowgloAddresses,
74 .string_value: "basic",
75 .usage: "Check for the Darwin kernel's load addr in the lowglo page "
76 "(boot-args=debug) only.",
77 },
78 {
79 .value: eKASLRScanNearPC,
80 .string_value: "fast-scan",
81 .usage: "Scan near the pc value on attach to find the Darwin kernel's load "
82 "address.",
83 },
84 {
85 .value: eKASLRScanExhaustiveScan,
86 .string_value: "exhaustive-scan",
87 .usage: "Scan through the entire potential address range of Darwin kernel "
88 "(only on 32-bit targets).",
89 },
90};
91
92#define LLDB_PROPERTIES_dynamicloaderdarwinkernel
93#include "DynamicLoaderDarwinKernelProperties.inc"
94
95enum {
96#define LLDB_PROPERTIES_dynamicloaderdarwinkernel
97#include "DynamicLoaderDarwinKernelPropertiesEnum.inc"
98};
99
100class DynamicLoaderDarwinKernelProperties : public Properties {
101public:
102 static llvm::StringRef GetSettingName() {
103 static constexpr llvm::StringLiteral g_setting_name("darwin-kernel");
104 return g_setting_name;
105 }
106
107 DynamicLoaderDarwinKernelProperties() : Properties() {
108 m_collection_sp = std::make_shared<OptionValueProperties>(args: GetSettingName());
109 m_collection_sp->Initialize(setting_definitions: g_dynamicloaderdarwinkernel_properties);
110 }
111
112 ~DynamicLoaderDarwinKernelProperties() override = default;
113
114 bool GetLoadKexts() const {
115 const uint32_t idx = ePropertyLoadKexts;
116 return GetPropertyAtIndexAs<bool>(
117 idx,
118 g_dynamicloaderdarwinkernel_properties[idx].default_uint_value != 0);
119 }
120
121 KASLRScanType GetScanType() const {
122 const uint32_t idx = ePropertyScanType;
123 return GetPropertyAtIndexAs<KASLRScanType>(
124 idx,
125 static_cast<KASLRScanType>(
126 g_dynamicloaderdarwinkernel_properties[idx].default_uint_value));
127 }
128};
129
130static DynamicLoaderDarwinKernelProperties &GetGlobalProperties() {
131 static DynamicLoaderDarwinKernelProperties g_settings;
132 return g_settings;
133}
134
135static bool is_kernel(Module *module) {
136 if (!module)
137 return false;
138 ObjectFile *objfile = module->GetObjectFile();
139 if (!objfile)
140 return false;
141 if (objfile->GetType() != ObjectFile::eTypeExecutable)
142 return false;
143 if (objfile->GetStrata() != ObjectFile::eStrataKernel)
144 return false;
145
146 return true;
147}
148
149// Create an instance of this class. This function is filled into the plugin
150// info class that gets handed out by the plugin factory and allows the lldb to
151// instantiate an instance of this class.
152DynamicLoader *DynamicLoaderDarwinKernel::CreateInstance(Process *process,
153 bool force) {
154 if (!force) {
155 // If the user provided an executable binary and it is not a kernel, this
156 // plugin should not create an instance.
157 Module *exec = process->GetTarget().GetExecutableModulePointer();
158 if (exec && !is_kernel(module: exec))
159 return nullptr;
160
161 // If the target's architecture does not look like an Apple environment,
162 // this plugin should not create an instance.
163 const llvm::Triple &triple_ref =
164 process->GetTarget().GetArchitecture().GetTriple();
165 switch (triple_ref.getOS()) {
166 case llvm::Triple::Darwin:
167 case llvm::Triple::MacOSX:
168 case llvm::Triple::IOS:
169 case llvm::Triple::TvOS:
170 case llvm::Triple::WatchOS:
171 case llvm::Triple::BridgeOS:
172 case llvm::Triple::DriverKit:
173 case llvm::Triple::XROS:
174 if (triple_ref.getVendor() != llvm::Triple::Apple) {
175 return nullptr;
176 }
177 break;
178 // If we have triple like armv7-unknown-unknown, we should try looking for
179 // a Darwin kernel.
180 case llvm::Triple::UnknownOS:
181 break;
182 default:
183 return nullptr;
184 break;
185 }
186 }
187
188 // At this point if there is an ExecutableModule, it is a kernel and the
189 // Target is some variant of an Apple system. If the Process hasn't provided
190 // the kernel load address, we need to look around in memory to find it.
191 const addr_t kernel_load_address = SearchForDarwinKernel(process);
192 if (CheckForKernelImageAtAddress(addr: kernel_load_address, process).IsValid()) {
193 return new DynamicLoaderDarwinKernel(process, kernel_load_address);
194 }
195 return nullptr;
196}
197
198lldb::addr_t
199DynamicLoaderDarwinKernel::SearchForDarwinKernel(Process *process) {
200 addr_t kernel_load_address = process->GetImageInfoAddress();
201 if (kernel_load_address == LLDB_INVALID_ADDRESS)
202 kernel_load_address = SearchForKernelAtSameLoadAddr(process);
203 if (kernel_load_address == LLDB_INVALID_ADDRESS)
204 kernel_load_address = SearchForKernelWithDebugHints(process);
205 if (kernel_load_address == LLDB_INVALID_ADDRESS)
206 kernel_load_address = SearchForKernelNearPC(process);
207 if (kernel_load_address == LLDB_INVALID_ADDRESS)
208 kernel_load_address = SearchForKernelViaExhaustiveSearch(process);
209
210 return kernel_load_address;
211}
212
213// Check if the kernel binary is loaded in memory without a slide. First verify
214// that the ExecutableModule is a kernel before we proceed. Returns the address
215// of the kernel if one was found, else LLDB_INVALID_ADDRESS.
216lldb::addr_t
217DynamicLoaderDarwinKernel::SearchForKernelAtSameLoadAddr(Process *process) {
218 Module *exe_module = process->GetTarget().GetExecutableModulePointer();
219
220 if (!is_kernel(module: process->GetTarget().GetExecutableModulePointer()))
221 return LLDB_INVALID_ADDRESS;
222
223 ObjectFile *exe_objfile = exe_module->GetObjectFile();
224
225 if (!exe_objfile->GetBaseAddress().IsValid())
226 return LLDB_INVALID_ADDRESS;
227
228 if (CheckForKernelImageAtAddress(
229 addr: exe_objfile->GetBaseAddress().GetFileAddress(), process) ==
230 exe_module->GetUUID())
231 return exe_objfile->GetBaseAddress().GetFileAddress();
232
233 return LLDB_INVALID_ADDRESS;
234}
235
236// If the debug flag is included in the boot-args nvram setting, the kernel's
237// load address will be noted in the lowglo page at a fixed address Returns the
238// address of the kernel if one was found, else LLDB_INVALID_ADDRESS.
239lldb::addr_t
240DynamicLoaderDarwinKernel::SearchForKernelWithDebugHints(Process *process) {
241 if (GetGlobalProperties().GetScanType() == eKASLRScanNone)
242 return LLDB_INVALID_ADDRESS;
243
244 Status read_err;
245 addr_t kernel_addresses_64[] = {
246 0xfffffff000002010ULL,
247 0xfffffe0000004010ULL, // newest arm64 devices, large memory support
248 0xfffffff000004010ULL, // newest arm64 devices
249 0xffffff8000004010ULL, // 2014-2015-ish arm64 devices
250 0xffffff8000002010ULL, // oldest arm64 devices
251 LLDB_INVALID_ADDRESS};
252 addr_t kernel_addresses_32[] = {0xffff0110, // 2016 and earlier armv7 devices
253 0xffff1010, LLDB_INVALID_ADDRESS};
254
255 uint8_t uval[8];
256 if (process->GetAddressByteSize() == 8) {
257 for (size_t i = 0; kernel_addresses_64[i] != LLDB_INVALID_ADDRESS; i++) {
258 if (process->ReadMemoryFromInferior(vm_addr: kernel_addresses_64[i], buf: uval, size: 8,
259 error&: read_err) == 8) {
260 DataExtractor data(&uval, 8, process->GetByteOrder(),
261 process->GetAddressByteSize());
262 lldb::offset_t offset = 0;
263 uint64_t addr = data.GetU64(offset_ptr: &offset);
264 if (CheckForKernelImageAtAddress(addr, process).IsValid()) {
265 return addr;
266 }
267 }
268 }
269 }
270
271 if (process->GetAddressByteSize() == 4) {
272 for (size_t i = 0; kernel_addresses_32[i] != LLDB_INVALID_ADDRESS; i++) {
273 if (process->ReadMemoryFromInferior(vm_addr: kernel_addresses_32[i], buf: uval, size: 4,
274 error&: read_err) == 4) {
275 DataExtractor data(&uval, 4, process->GetByteOrder(),
276 process->GetAddressByteSize());
277 lldb::offset_t offset = 0;
278 uint32_t addr = data.GetU32(offset_ptr: &offset);
279 if (CheckForKernelImageAtAddress(addr, process).IsValid()) {
280 return addr;
281 }
282 }
283 }
284 }
285
286 return LLDB_INVALID_ADDRESS;
287}
288
289// If the kernel is currently executing when lldb attaches, and we don't have a
290// better way of finding the kernel's load address, try searching backwards
291// from the current pc value looking for the kernel's Mach header in memory.
292// Returns the address of the kernel if one was found, else
293// LLDB_INVALID_ADDRESS.
294lldb::addr_t
295DynamicLoaderDarwinKernel::SearchForKernelNearPC(Process *process) {
296 if (GetGlobalProperties().GetScanType() == eKASLRScanNone ||
297 GetGlobalProperties().GetScanType() == eKASLRScanLowgloAddresses) {
298 return LLDB_INVALID_ADDRESS;
299 }
300
301 ThreadSP thread = process->GetThreadList().GetSelectedThread();
302 if (thread.get() == nullptr)
303 return LLDB_INVALID_ADDRESS;
304 addr_t pc = thread->GetRegisterContext()->GetPC(LLDB_INVALID_ADDRESS);
305
306 int ptrsize = process->GetTarget().GetArchitecture().GetAddressByteSize();
307
308 // The kernel is always loaded in high memory, if the top bit is zero,
309 // this isn't a kernel.
310 if (ptrsize == 8) {
311 if ((pc & (1ULL << 63)) == 0) {
312 return LLDB_INVALID_ADDRESS;
313 }
314 } else {
315 if ((pc & (1ULL << 31)) == 0) {
316 return LLDB_INVALID_ADDRESS;
317 }
318 }
319
320 if (pc == LLDB_INVALID_ADDRESS)
321 return LLDB_INVALID_ADDRESS;
322
323 int pagesize = 0x4000; // 16k pages on 64-bit targets
324 if (ptrsize == 4)
325 pagesize = 0x1000; // 4k pages on 32-bit targets
326
327 // The kernel will be loaded on a page boundary.
328 // Round the current pc down to the nearest page boundary.
329 addr_t addr = pc & ~(pagesize - 1ULL);
330
331 // Search backwards for 128 megabytes, or first memory read error.
332 while (pc - addr < 128 * 0x100000) {
333 bool read_error;
334 if (CheckForKernelImageAtAddress(addr, process, read_error: &read_error).IsValid())
335 return addr;
336
337 // Stop scanning on the first read error we encounter; we've walked
338 // past this executable block of memory.
339 if (read_error == true)
340 break;
341
342 addr -= pagesize;
343 }
344
345 return LLDB_INVALID_ADDRESS;
346}
347
348// Scan through the valid address range for a kernel binary. This is uselessly
349// slow in 64-bit environments so we don't even try it. This scan is not
350// enabled by default even for 32-bit targets. Returns the address of the
351// kernel if one was found, else LLDB_INVALID_ADDRESS.
352lldb::addr_t DynamicLoaderDarwinKernel::SearchForKernelViaExhaustiveSearch(
353 Process *process) {
354 if (GetGlobalProperties().GetScanType() != eKASLRScanExhaustiveScan) {
355 return LLDB_INVALID_ADDRESS;
356 }
357
358 addr_t kernel_range_low, kernel_range_high;
359 if (process->GetTarget().GetArchitecture().GetAddressByteSize() == 8) {
360 kernel_range_low = 1ULL << 63;
361 kernel_range_high = UINT64_MAX;
362 } else {
363 kernel_range_low = 1ULL << 31;
364 kernel_range_high = UINT32_MAX;
365 }
366
367 // Stepping through memory at one-megabyte resolution looking for a kernel
368 // rarely works (fast enough) with a 64-bit address space -- for now, let's
369 // not even bother. We may be attaching to something which *isn't* a kernel
370 // and we don't want to spin for minutes on-end looking for a kernel.
371 if (process->GetTarget().GetArchitecture().GetAddressByteSize() == 8)
372 return LLDB_INVALID_ADDRESS;
373
374 addr_t addr = kernel_range_low;
375
376 while (addr >= kernel_range_low && addr < kernel_range_high) {
377 // x86_64 kernels are at offset 0
378 if (CheckForKernelImageAtAddress(addr, process).IsValid())
379 return addr;
380 // 32-bit arm kernels are at offset 0x1000 (one 4k page)
381 if (CheckForKernelImageAtAddress(addr: addr + 0x1000, process).IsValid())
382 return addr + 0x1000;
383 // 64-bit arm kernels are at offset 0x4000 (one 16k page)
384 if (CheckForKernelImageAtAddress(addr: addr + 0x4000, process).IsValid())
385 return addr + 0x4000;
386 addr += 0x100000;
387 }
388 return LLDB_INVALID_ADDRESS;
389}
390
391// Read the mach_header struct out of memory and return it.
392// Returns true if the mach_header was successfully read,
393// Returns false if there was a problem reading the header, or it was not
394// a Mach-O header.
395
396bool
397DynamicLoaderDarwinKernel::ReadMachHeader(addr_t addr, Process *process, llvm::MachO::mach_header &header,
398 bool *read_error) {
399 Status error;
400 if (read_error)
401 *read_error = false;
402
403 // Read the mach header and see whether it looks like a kernel
404 if (process->ReadMemory(vm_addr: addr, buf: &header, size: sizeof(header), error) !=
405 sizeof(header)) {
406 if (read_error)
407 *read_error = true;
408 return false;
409 }
410
411 const uint32_t magicks[] = { llvm::MachO::MH_MAGIC_64, llvm::MachO::MH_MAGIC, llvm::MachO::MH_CIGAM, llvm::MachO::MH_CIGAM_64};
412
413 bool found_matching_pattern = false;
414 for (size_t i = 0; i < std::size(magicks); i++)
415 if (::memcmp (s1: &header.magic, s2: &magicks[i], n: sizeof (uint32_t)) == 0)
416 found_matching_pattern = true;
417
418 if (!found_matching_pattern)
419 return false;
420
421 if (header.magic == llvm::MachO::MH_CIGAM ||
422 header.magic == llvm::MachO::MH_CIGAM_64) {
423 header.magic = llvm::byteswap<uint32_t>(V: header.magic);
424 header.cputype = llvm::byteswap<uint32_t>(V: header.cputype);
425 header.cpusubtype = llvm::byteswap<uint32_t>(V: header.cpusubtype);
426 header.filetype = llvm::byteswap<uint32_t>(V: header.filetype);
427 header.ncmds = llvm::byteswap<uint32_t>(V: header.ncmds);
428 header.sizeofcmds = llvm::byteswap<uint32_t>(V: header.sizeofcmds);
429 header.flags = llvm::byteswap<uint32_t>(V: header.flags);
430 }
431
432 return true;
433}
434
435// Given an address in memory, look to see if there is a kernel image at that
436// address.
437// Returns a UUID; if a kernel was not found at that address, UUID.IsValid()
438// will be false.
439lldb_private::UUID
440DynamicLoaderDarwinKernel::CheckForKernelImageAtAddress(lldb::addr_t addr,
441 Process *process,
442 bool *read_error) {
443 Log *log = GetLog(mask: LLDBLog::DynamicLoader);
444 if (addr == LLDB_INVALID_ADDRESS) {
445 if (read_error)
446 *read_error = true;
447 return UUID();
448 }
449
450 LLDB_LOGF(log,
451 "DynamicLoaderDarwinKernel::CheckForKernelImageAtAddress: "
452 "looking for kernel binary at 0x%" PRIx64,
453 addr);
454
455 llvm::MachO::mach_header header;
456
457 if (!ReadMachHeader(addr, process, header, read_error))
458 return UUID();
459
460 // First try a quick test -- read the first 4 bytes and see if there is a
461 // valid Mach-O magic field there
462 // (the first field of the mach_header/mach_header_64 struct).
463 // A kernel is an executable which does not have the dynamic link object flag
464 // set.
465 if (header.filetype == llvm::MachO::MH_EXECUTE &&
466 (header.flags & llvm::MachO::MH_DYLDLINK) == 0) {
467 // Create a full module to get the UUID
468 ModuleSP memory_module_sp =
469 process->ReadModuleFromMemory(file_spec: FileSpec("temp_mach_kernel"), header_addr: addr);
470 if (!memory_module_sp.get())
471 return UUID();
472
473 ObjectFile *exe_objfile = memory_module_sp->GetObjectFile();
474 if (exe_objfile == nullptr) {
475 LLDB_LOGF(log,
476 "DynamicLoaderDarwinKernel::CheckForKernelImageAtAddress "
477 "found a binary at 0x%" PRIx64
478 " but could not create an object file from memory",
479 addr);
480 return UUID();
481 }
482
483 if (is_kernel(module: memory_module_sp.get())) {
484 ArchSpec kernel_arch(eArchTypeMachO, header.cputype, header.cpusubtype);
485 if (!process->GetTarget().GetArchitecture().IsCompatibleMatch(
486 rhs: kernel_arch)) {
487 process->GetTarget().SetArchitecture(arch_spec: kernel_arch);
488 }
489 if (log) {
490 std::string uuid_str;
491 if (memory_module_sp->GetUUID().IsValid()) {
492 uuid_str = "with UUID ";
493 uuid_str += memory_module_sp->GetUUID().GetAsString();
494 } else {
495 uuid_str = "and no LC_UUID found in load commands ";
496 }
497 LLDB_LOGF(
498 log,
499 "DynamicLoaderDarwinKernel::CheckForKernelImageAtAddress: "
500 "kernel binary image found at 0x%" PRIx64 " with arch '%s' %s",
501 addr, kernel_arch.GetTriple().str().c_str(), uuid_str.c_str());
502 }
503 return memory_module_sp->GetUUID();
504 }
505 }
506
507 return UUID();
508}
509
510// Constructor
511DynamicLoaderDarwinKernel::DynamicLoaderDarwinKernel(Process *process,
512 lldb::addr_t kernel_addr)
513 : DynamicLoader(process), m_kernel_load_address(kernel_addr), m_kernel(),
514 m_kext_summary_header_ptr_addr(), m_kext_summary_header_addr(),
515 m_kext_summary_header(), m_known_kexts(), m_mutex(),
516 m_break_id(LLDB_INVALID_BREAK_ID) {
517 Status error;
518 process->SetCanRunCode(false);
519 PlatformSP platform_sp =
520 process->GetTarget().GetDebugger().GetPlatformList().Create(
521 name: PlatformDarwinKernel::GetPluginNameStatic());
522 if (platform_sp.get())
523 process->GetTarget().SetPlatform(platform_sp);
524}
525
526// Destructor
527DynamicLoaderDarwinKernel::~DynamicLoaderDarwinKernel() { Clear(clear_process: true); }
528
529void DynamicLoaderDarwinKernel::UpdateIfNeeded() {
530 LoadKernelModuleIfNeeded();
531 SetNotificationBreakpointIfNeeded();
532}
533
534/// We've attached to a remote connection, or read a corefile.
535/// Now load the kernel binary and potentially the kexts, add
536/// them to the Target.
537void DynamicLoaderDarwinKernel::DidAttach() {
538 PrivateInitialize(process: m_process);
539 UpdateIfNeeded();
540}
541
542/// Called after attaching a process.
543///
544/// Allow DynamicLoader plug-ins to execute some code after
545/// attaching to a process.
546void DynamicLoaderDarwinKernel::DidLaunch() {
547 PrivateInitialize(process: m_process);
548 UpdateIfNeeded();
549}
550
551// Clear out the state of this class.
552void DynamicLoaderDarwinKernel::Clear(bool clear_process) {
553 std::lock_guard<std::recursive_mutex> guard(m_mutex);
554
555 if (m_process->IsAlive() && LLDB_BREAK_ID_IS_VALID(m_break_id))
556 m_process->ClearBreakpointSiteByID(break_id: m_break_id);
557
558 if (clear_process)
559 m_process = nullptr;
560 m_kernel.Clear();
561 m_known_kexts.clear();
562 m_kext_summary_header_ptr_addr.Clear();
563 m_kext_summary_header_addr.Clear();
564 m_break_id = LLDB_INVALID_BREAK_ID;
565}
566
567bool DynamicLoaderDarwinKernel::KextImageInfo::LoadImageAtFileAddress(
568 Process *process) {
569 if (IsLoaded())
570 return true;
571
572 if (m_module_sp) {
573 bool changed = false;
574 if (m_module_sp->SetLoadAddress(target&: process->GetTarget(), value: 0, value_is_offset: true, changed))
575 m_load_process_stop_id = process->GetStopID();
576 }
577 return false;
578}
579
580void DynamicLoaderDarwinKernel::KextImageInfo::SetModule(ModuleSP module_sp) {
581 m_module_sp = module_sp;
582 m_kernel_image = is_kernel(module: module_sp.get());
583}
584
585ModuleSP DynamicLoaderDarwinKernel::KextImageInfo::GetModule() {
586 return m_module_sp;
587}
588
589void DynamicLoaderDarwinKernel::KextImageInfo::SetLoadAddress(
590 addr_t load_addr) {
591 m_load_address = load_addr;
592}
593
594addr_t DynamicLoaderDarwinKernel::KextImageInfo::GetLoadAddress() const {
595 return m_load_address;
596}
597
598uint64_t DynamicLoaderDarwinKernel::KextImageInfo::GetSize() const {
599 return m_size;
600}
601
602void DynamicLoaderDarwinKernel::KextImageInfo::SetSize(uint64_t size) {
603 m_size = size;
604}
605
606uint32_t DynamicLoaderDarwinKernel::KextImageInfo::GetProcessStopId() const {
607 return m_load_process_stop_id;
608}
609
610void DynamicLoaderDarwinKernel::KextImageInfo::SetProcessStopId(
611 uint32_t stop_id) {
612 m_load_process_stop_id = stop_id;
613}
614
615bool DynamicLoaderDarwinKernel::KextImageInfo::operator==(
616 const KextImageInfo &rhs) const {
617 if (m_uuid.IsValid() || rhs.GetUUID().IsValid()) {
618 return m_uuid == rhs.GetUUID();
619 }
620
621 return m_name == rhs.GetName() && m_load_address == rhs.GetLoadAddress();
622}
623
624void DynamicLoaderDarwinKernel::KextImageInfo::SetName(const char *name) {
625 m_name = name;
626}
627
628std::string DynamicLoaderDarwinKernel::KextImageInfo::GetName() const {
629 return m_name;
630}
631
632void DynamicLoaderDarwinKernel::KextImageInfo::SetUUID(const UUID &uuid) {
633 m_uuid = uuid;
634}
635
636UUID DynamicLoaderDarwinKernel::KextImageInfo::GetUUID() const {
637 return m_uuid;
638}
639
640// Given the m_load_address from the kext summaries, and a UUID, try to create
641// an in-memory Module at that address. Require that the MemoryModule have a
642// matching UUID and detect if this MemoryModule is a kernel or a kext.
643//
644// Returns true if m_memory_module_sp is now set to a valid Module.
645
646bool DynamicLoaderDarwinKernel::KextImageInfo::ReadMemoryModule(
647 Process *process) {
648 Log *log = GetLog(mask: LLDBLog::Host);
649 if (m_memory_module_sp.get() != nullptr)
650 return true;
651 if (m_load_address == LLDB_INVALID_ADDRESS)
652 return false;
653
654 FileSpec file_spec(m_name.c_str());
655
656 llvm::MachO::mach_header mh;
657 size_t size_to_read = 512;
658 if (ReadMachHeader(addr: m_load_address, process, header&: mh)) {
659 if (mh.magic == llvm::MachO::MH_CIGAM || mh.magic == llvm::MachO::MH_MAGIC)
660 size_to_read = sizeof(llvm::MachO::mach_header) + mh.sizeofcmds;
661 if (mh.magic == llvm::MachO::MH_CIGAM_64 ||
662 mh.magic == llvm::MachO::MH_MAGIC_64)
663 size_to_read = sizeof(llvm::MachO::mach_header_64) + mh.sizeofcmds;
664 }
665
666 ModuleSP memory_module_sp =
667 process->ReadModuleFromMemory(file_spec, header_addr: m_load_address, size_to_read);
668
669 if (memory_module_sp.get() == nullptr)
670 return false;
671
672 bool this_is_kernel = is_kernel(module: memory_module_sp.get());
673
674 // If this is a kext, and the kernel specified what UUID we should find at
675 // this load address, require that the memory module have a matching UUID or
676 // something has gone wrong and we should discard it.
677 if (m_uuid.IsValid()) {
678 if (m_uuid != memory_module_sp->GetUUID()) {
679 if (log) {
680 LLDB_LOGF(log,
681 "KextImageInfo::ReadMemoryModule the kernel said to find "
682 "uuid %s at 0x%" PRIx64
683 " but instead we found uuid %s, throwing it away",
684 m_uuid.GetAsString().c_str(), m_load_address,
685 memory_module_sp->GetUUID().GetAsString().c_str());
686 }
687 return false;
688 }
689 }
690
691 // If the in-memory Module has a UUID, let's use that.
692 if (!m_uuid.IsValid() && memory_module_sp->GetUUID().IsValid()) {
693 m_uuid = memory_module_sp->GetUUID();
694 }
695
696 m_memory_module_sp = memory_module_sp;
697 m_kernel_image = this_is_kernel;
698 if (this_is_kernel) {
699 if (log) {
700 // This is unusual and probably not intended
701 LLDB_LOGF(log,
702 "KextImageInfo::ReadMemoryModule read the kernel binary out "
703 "of memory");
704 }
705 if (memory_module_sp->GetArchitecture().IsValid()) {
706 process->GetTarget().SetArchitecture(arch_spec: memory_module_sp->GetArchitecture());
707 }
708 }
709
710 return true;
711}
712
713bool DynamicLoaderDarwinKernel::KextImageInfo::IsKernel() const {
714 return m_kernel_image;
715}
716
717void DynamicLoaderDarwinKernel::KextImageInfo::SetIsKernel(bool is_kernel) {
718 m_kernel_image = is_kernel;
719}
720
721bool DynamicLoaderDarwinKernel::KextImageInfo::LoadImageUsingMemoryModule(
722 Process *process, Progress *progress) {
723 Log *log = GetLog(mask: LLDBLog::DynamicLoader);
724 if (IsLoaded())
725 return true;
726
727 Target &target = process->GetTarget();
728
729 // kexts will have a uuid from the table.
730 // for the kernel, we'll need to read the load commands out of memory to get it.
731 if (m_uuid.IsValid() == false) {
732 if (ReadMemoryModule(process) == false) {
733 Log *log = GetLog(mask: LLDBLog::DynamicLoader);
734 LLDB_LOGF(log,
735 "Unable to read '%s' from memory at address 0x%" PRIx64
736 " to get the segment load addresses.",
737 m_name.c_str(), m_load_address);
738 return false;
739 }
740 }
741
742 if (IsKernel() && m_uuid.IsValid()) {
743 lldb::StreamUP s = target.GetDebugger().GetAsyncOutputStream();
744 s->Printf(format: "Kernel UUID: %s\n", m_uuid.GetAsString().c_str());
745 s->Printf(format: "Load Address: 0x%" PRIx64 "\n", m_load_address);
746
747 // Start of a kernel debug session, we have the UUID of the kernel.
748 // Go through the target's list of modules and if there are any kernel
749 // modules with non-matching UUIDs, remove them. The user may have added
750 // the wrong kernel binary manually and it will only confuse things.
751 ModuleList incorrect_kernels;
752 for (ModuleSP module_sp : target.GetImages().Modules()) {
753 if (is_kernel(module: module_sp.get()) && module_sp->GetUUID() != m_uuid)
754 incorrect_kernels.Append(module_sp);
755 }
756 target.GetImages().Remove(module_list&: incorrect_kernels);
757 }
758
759 if (!m_module_sp) {
760 // See if the kext has already been loaded into the target, probably by the
761 // user doing target modules add.
762 const ModuleList &target_images = target.GetImages();
763 m_module_sp = target_images.FindModule(uuid: m_uuid);
764
765 StreamString prog_str;
766 // 'mach_kernel' is a fake name we make up to find kernels
767 // that were located by the local filesystem scan.
768 if (GetName() != "mach_kernel")
769 prog_str << GetName() << " ";
770 if (GetUUID().IsValid())
771 prog_str << GetUUID().GetAsString() << " ";
772 if (GetLoadAddress() != LLDB_INVALID_ADDRESS) {
773 prog_str << "at 0x";
774 prog_str.PutHex64(uvalue: GetLoadAddress());
775 }
776
777 std::unique_ptr<Progress> progress_up;
778 if (progress)
779 progress->Increment(amount: 1, updated_detail: prog_str.GetString().str());
780 else {
781 if (IsKernel())
782 progress_up = std::make_unique<Progress>(args: "Loading kernel",
783 args: prog_str.GetString().str());
784 else
785 progress_up = std::make_unique<Progress>(args: "Loading kext",
786 args: prog_str.GetString().str());
787 }
788
789 // Search for the kext on the local filesystem via the UUID
790 if (!m_module_sp && m_uuid.IsValid()) {
791 ModuleSpec module_spec;
792 module_spec.GetUUID() = m_uuid;
793 if (!m_uuid.IsValid())
794 module_spec.GetArchitecture() = target.GetArchitecture();
795 module_spec.GetFileSpec() = FileSpec(m_name);
796
797 // If the current platform is PlatformDarwinKernel, create a ModuleSpec
798 // with the filename set to be the bundle ID for this kext, e.g.
799 // "com.apple.filesystems.msdosfs", and ask the platform to find it.
800 // PlatformDarwinKernel does a special scan for kexts on the local
801 // system.
802 PlatformSP platform_sp(target.GetPlatform());
803 if (platform_sp) {
804 FileSpecList search_paths = target.GetExecutableSearchPaths();
805 platform_sp->GetSharedModule(module_spec, process, module_sp&: m_module_sp,
806 module_search_paths_ptr: &search_paths, old_modules: nullptr, did_create_ptr: nullptr);
807 }
808
809 // Ask the Target to find this file on the local system, if possible.
810 // This will search in the list of currently-loaded files, look in the
811 // standard search paths on the system, and on a Mac it will try calling
812 // the DebugSymbols framework with the UUID to find the binary via its
813 // search methods.
814 if (!m_module_sp) {
815 m_module_sp = target.GetOrCreateModule(module_spec, notify: true /* notify */);
816 }
817
818 // For the kernel, we really do need an on-disk file copy of the binary
819 // to do anything useful. This will force a call to dsymForUUID if it
820 // exists, instead of depending on the DebugSymbols preferences being
821 // set.
822 Status kernel_search_error;
823 if (IsKernel() &&
824 (!m_module_sp || !m_module_sp->GetSymbolFileFileSpec())) {
825 if (PluginManager::DownloadObjectAndSymbolFile(
826 module_spec, error&: kernel_search_error, force_lookup: true)) {
827 if (FileSystem::Instance().Exists(file_spec: module_spec.GetFileSpec())) {
828 m_module_sp = std::make_shared<Module>(args&: module_spec.GetFileSpec(),
829 args: target.GetArchitecture());
830 }
831 }
832 }
833
834 if (IsKernel() && !m_module_sp) {
835 lldb::StreamUP s = target.GetDebugger().GetAsyncErrorStream();
836 s->Printf(format: "WARNING: Unable to locate kernel binary on the debugger "
837 "system.\n");
838 if (kernel_search_error.Fail() && kernel_search_error.AsCString(default_error_str: "") &&
839 kernel_search_error.AsCString(default_error_str: "")[0] != '\0') {
840 *s << kernel_search_error.AsCString();
841 }
842 }
843 }
844
845 if (m_module_sp && m_uuid.IsValid() && m_module_sp->GetUUID() == m_uuid &&
846 m_module_sp->GetObjectFile()) {
847 if (ObjectFileMachO *ondisk_objfile_macho =
848 llvm::dyn_cast<ObjectFileMachO>(Val: m_module_sp->GetObjectFile())) {
849 if (!IsKernel() && !ondisk_objfile_macho->IsKext()) {
850 // We have a non-kext, non-kernel binary. If we already have this
851 // loaded in the Target with load addresses, don't re-load it again.
852 ModuleSP existing_module_sp = target.GetImages().FindModule(uuid: m_uuid);
853 if (existing_module_sp &&
854 existing_module_sp->IsLoadedInTarget(target: &target)) {
855 LLDB_LOGF(log,
856 "'%s' with UUID %s is not a kext or kernel, and is "
857 "already registered in target, not loading.",
858 m_name.c_str(), m_uuid.GetAsString().c_str());
859 // It's already loaded, return true.
860 return true;
861 }
862 }
863 }
864 }
865
866 // If we managed to find a module, append it to the target's list of
867 // images. If we also have a memory module, require that they have matching
868 // UUIDs
869 if (m_module_sp) {
870 if (m_uuid.IsValid() && m_module_sp->GetUUID() == m_uuid) {
871 target.GetImages().AppendIfNeeded(new_module: m_module_sp, notify: false);
872 }
873 }
874 }
875
876 // If we've found a binary, read the load commands out of memory so we
877 // can set the segment load addresses.
878 if (m_module_sp)
879 ReadMemoryModule (process);
880
881 static ConstString g_section_name_LINKEDIT("__LINKEDIT");
882
883 if (m_memory_module_sp && m_module_sp) {
884 if (m_module_sp->GetUUID() == m_memory_module_sp->GetUUID()) {
885 ObjectFile *ondisk_object_file = m_module_sp->GetObjectFile();
886 ObjectFile *memory_object_file = m_memory_module_sp->GetObjectFile();
887
888 if (memory_object_file && ondisk_object_file) {
889 // The memory_module for kexts may have an invalid __LINKEDIT seg; skip
890 // it.
891 const bool ignore_linkedit = !IsKernel();
892
893 // Normally a kext will have its segment load commands
894 // (LC_SEGMENT vmaddrs) corrected in memory to have their
895 // actual segment addresses.
896 // Userland proceses have their libraries updated the same way
897 // by dyld. The Mach-O load commands in memory are the canonical
898 // addresses.
899 //
900 // If the kernel gives us a binary where the in-memory segment
901 // vmaddr is incorrect, then this binary was put in memory without
902 // updating its Mach-O load commands. We should assume a static
903 // slide value will be applied to every segment; we don't have the
904 // correct addresses for each individual segment.
905 addr_t fixed_slide = LLDB_INVALID_ADDRESS;
906 if (ObjectFileMachO *memory_objfile_macho =
907 llvm::dyn_cast<ObjectFileMachO>(Val: memory_object_file)) {
908 if (Section *header_sect =
909 memory_objfile_macho->GetMachHeaderSection()) {
910 if (header_sect->GetFileAddress() != m_load_address) {
911 fixed_slide = m_load_address - header_sect->GetFileAddress();
912 LLDB_LOGF(
913 log,
914 "kext %s in-memory LC_SEGMENT vmaddr is not correct, using a "
915 "fixed slide of 0x%" PRIx64,
916 m_name.c_str(), fixed_slide);
917 }
918 }
919 }
920
921 SectionList *ondisk_section_list = ondisk_object_file->GetSectionList();
922 SectionList *memory_section_list = memory_object_file->GetSectionList();
923 if (memory_section_list && ondisk_section_list) {
924 const uint32_t num_ondisk_sections = ondisk_section_list->GetSize();
925 // There may be CTF sections in the memory image so we can't always
926 // just compare the number of sections (which are actually segments
927 // in mach-o parlance)
928 uint32_t sect_idx = 0;
929
930 // Use the memory_module's addresses for each section to set the file
931 // module's load address as appropriate. We don't want to use a
932 // single slide value for the entire kext - different segments may be
933 // slid different amounts by the kext loader.
934
935 uint32_t num_sections_loaded = 0;
936 for (sect_idx = 0; sect_idx < num_ondisk_sections; ++sect_idx) {
937 SectionSP ondisk_section_sp(
938 ondisk_section_list->GetSectionAtIndex(idx: sect_idx));
939 if (ondisk_section_sp) {
940 // Don't ever load __LINKEDIT as it may or may not be actually
941 // mapped into memory and there is no current way to tell. Until
942 // such an ability exists, do not load the __LINKEDIT.
943 if (ignore_linkedit &&
944 ondisk_section_sp->GetName() == g_section_name_LINKEDIT)
945 continue;
946
947 if (fixed_slide != LLDB_INVALID_ADDRESS) {
948 target.SetSectionLoadAddress(
949 section: ondisk_section_sp,
950 load_addr: ondisk_section_sp->GetFileAddress() + fixed_slide);
951 } else {
952 const Section *memory_section =
953 memory_section_list
954 ->FindSectionByName(section_dstr: ondisk_section_sp->GetName())
955 .get();
956 if (memory_section) {
957 target.SetSectionLoadAddress(
958 section: ondisk_section_sp, load_addr: memory_section->GetFileAddress());
959 ++num_sections_loaded;
960 }
961 }
962 }
963 }
964 if (num_sections_loaded > 0)
965 m_load_process_stop_id = process->GetStopID();
966 else
967 m_module_sp.reset(); // No sections were loaded
968 } else
969 m_module_sp.reset(); // One or both section lists
970 } else
971 m_module_sp.reset(); // One or both object files missing
972 } else
973 m_module_sp.reset(); // UUID mismatch
974 }
975
976 bool is_loaded = IsLoaded();
977
978 if (is_loaded && m_module_sp && IsKernel()) {
979 lldb::StreamUP s = target.GetDebugger().GetAsyncOutputStream();
980 ObjectFile *kernel_object_file = m_module_sp->GetObjectFile();
981 if (kernel_object_file) {
982 addr_t file_address =
983 kernel_object_file->GetBaseAddress().GetFileAddress();
984 if (m_load_address != LLDB_INVALID_ADDRESS &&
985 file_address != LLDB_INVALID_ADDRESS) {
986 s->Printf(format: "Kernel slid 0x%" PRIx64 " in memory.\n",
987 m_load_address - file_address);
988 }
989 }
990 s->Printf(format: "Loaded kernel file %s\n",
991 m_module_sp->GetFileSpec().GetPath().c_str());
992 }
993
994 // Notify the target about the module being added;
995 // set breakpoints, load dSYM scripts, etc. as needed.
996 if (is_loaded && m_module_sp) {
997 ModuleList loaded_module_list;
998 loaded_module_list.Append(module_sp: m_module_sp);
999 target.ModulesDidLoad(module_list&: loaded_module_list);
1000 }
1001
1002 return is_loaded;
1003}
1004
1005uint32_t DynamicLoaderDarwinKernel::KextImageInfo::GetAddressByteSize() {
1006 if (m_memory_module_sp)
1007 return m_memory_module_sp->GetArchitecture().GetAddressByteSize();
1008 if (m_module_sp)
1009 return m_module_sp->GetArchitecture().GetAddressByteSize();
1010 return 0;
1011}
1012
1013lldb::ByteOrder DynamicLoaderDarwinKernel::KextImageInfo::GetByteOrder() {
1014 if (m_memory_module_sp)
1015 return m_memory_module_sp->GetArchitecture().GetByteOrder();
1016 if (m_module_sp)
1017 return m_module_sp->GetArchitecture().GetByteOrder();
1018 return endian::InlHostByteOrder();
1019}
1020
1021lldb_private::ArchSpec
1022DynamicLoaderDarwinKernel::KextImageInfo::GetArchitecture() const {
1023 if (m_memory_module_sp)
1024 return m_memory_module_sp->GetArchitecture();
1025 if (m_module_sp)
1026 return m_module_sp->GetArchitecture();
1027 return lldb_private::ArchSpec();
1028}
1029
1030// Load the kernel module and initialize the "m_kernel" member. Return true
1031// _only_ if the kernel is loaded the first time through (subsequent calls to
1032// this function should return false after the kernel has been already loaded).
1033void DynamicLoaderDarwinKernel::LoadKernelModuleIfNeeded() {
1034 if (!m_kext_summary_header_ptr_addr.IsValid()) {
1035 m_kernel.Clear();
1036 ModuleSP module_sp = m_process->GetTarget().GetExecutableModule();
1037 if (is_kernel(module: module_sp.get())) {
1038 m_kernel.SetModule(module_sp);
1039 m_kernel.SetIsKernel(true);
1040 }
1041
1042 ConstString kernel_name("mach_kernel");
1043 if (m_kernel.GetModule().get() && m_kernel.GetModule()->GetObjectFile() &&
1044 !m_kernel.GetModule()
1045 ->GetObjectFile()
1046 ->GetFileSpec()
1047 .GetFilename()
1048 .IsEmpty()) {
1049 kernel_name =
1050 m_kernel.GetModule()->GetObjectFile()->GetFileSpec().GetFilename();
1051 }
1052 m_kernel.SetName(kernel_name.AsCString());
1053
1054 if (m_kernel.GetLoadAddress() == LLDB_INVALID_ADDRESS) {
1055 m_kernel.SetLoadAddress(m_kernel_load_address);
1056 if (m_kernel.GetLoadAddress() == LLDB_INVALID_ADDRESS &&
1057 m_kernel.GetModule()) {
1058 // We didn't get a hint from the process, so we will try the kernel at
1059 // the address that it exists at in the file if we have one
1060 ObjectFile *kernel_object_file = m_kernel.GetModule()->GetObjectFile();
1061 if (kernel_object_file) {
1062 addr_t load_address =
1063 kernel_object_file->GetBaseAddress().GetLoadAddress(
1064 target: &m_process->GetTarget());
1065 addr_t file_address =
1066 kernel_object_file->GetBaseAddress().GetFileAddress();
1067 if (load_address != LLDB_INVALID_ADDRESS && load_address != 0) {
1068 m_kernel.SetLoadAddress(load_address);
1069 if (load_address != file_address) {
1070 // Don't accidentally relocate the kernel to the File address --
1071 // the Load address has already been set to its actual in-memory
1072 // address. Mark it as IsLoaded.
1073 m_kernel.SetProcessStopId(m_process->GetStopID());
1074 }
1075 } else {
1076 m_kernel.SetLoadAddress(file_address);
1077 }
1078 }
1079 }
1080 }
1081 if (m_kernel.GetLoadAddress() != LLDB_INVALID_ADDRESS)
1082 if (!m_kernel.LoadImageUsingMemoryModule(process: m_process))
1083 m_kernel.LoadImageAtFileAddress(process: m_process);
1084
1085 // The operating system plugin gets loaded and initialized in
1086 // LoadImageUsingMemoryModule when we discover the kernel dSYM. For a core
1087 // file in particular, that's the wrong place to do this, since we haven't
1088 // fixed up the section addresses yet. So let's redo it here.
1089 LoadOperatingSystemPlugin(flush: false);
1090
1091 if (m_kernel.IsLoaded() && m_kernel.GetModule()) {
1092 static ConstString kext_summary_symbol("gLoadedKextSummaries");
1093 static ConstString arm64_T1Sz_value("gT1Sz");
1094 const Symbol *symbol =
1095 m_kernel.GetModule()->FindFirstSymbolWithNameAndType(
1096 name: kext_summary_symbol, symbol_type: eSymbolTypeAny);
1097 if (symbol) {
1098 m_kext_summary_header_ptr_addr = symbol->GetAddress();
1099 // Update all image infos
1100 ReadAllKextSummaries();
1101 }
1102 // If the kernel global with the T1Sz setting is available,
1103 // update the target.process.virtual-addressable-bits to be correct.
1104 // NB the xnu kernel always has T0Sz and T1Sz the same value. If
1105 // it wasn't the same, we would need to set
1106 // target.process.virtual-addressable-bits = T0Sz
1107 // target.process.highmem-virtual-addressable-bits = T1Sz
1108 symbol = m_kernel.GetModule()->FindFirstSymbolWithNameAndType(
1109 name: arm64_T1Sz_value, symbol_type: eSymbolTypeData);
1110 if (symbol) {
1111 const addr_t orig_code_mask = m_process->GetCodeAddressMask();
1112 const addr_t orig_data_mask = m_process->GetDataAddressMask();
1113
1114 m_process->SetCodeAddressMask(0);
1115 m_process->SetDataAddressMask(0);
1116 Status error;
1117 // gT1Sz is 8 bytes. We may run on a stripped kernel binary
1118 // where we can't get the size accurately. Hardcode it.
1119 const size_t sym_bytesize = 8; // size of gT1Sz value
1120 uint64_t sym_value =
1121 m_process->GetTarget().ReadUnsignedIntegerFromMemory(
1122 addr: symbol->GetAddress(), integer_byte_size: sym_bytesize, fail_value: 0, error);
1123 if (error.Success()) {
1124 // 64 - T1Sz is the highest bit used for auth.
1125 // The value we pass in to SetVirtualAddressableBits is
1126 // the number of bits used for addressing, so if
1127 // T1Sz is 25, then 64-25 == 39, bits 0..38 are used for
1128 // addressing, bits 39..63 are used for PAC/TBI or whatever.
1129 uint32_t virt_addr_bits = 64 - sym_value;
1130 addr_t mask = AddressableBits::AddressableBitToMask(addressable_bits: virt_addr_bits);
1131 m_process->SetCodeAddressMask(mask);
1132 m_process->SetDataAddressMask(mask);
1133 } else {
1134 m_process->SetCodeAddressMask(orig_code_mask);
1135 m_process->SetDataAddressMask(orig_data_mask);
1136 }
1137 }
1138 } else {
1139 m_kernel.Clear();
1140 }
1141 }
1142}
1143
1144// Static callback function that gets called when our DYLD notification
1145// breakpoint gets hit. We update all of our image infos and then let our super
1146// class DynamicLoader class decide if we should stop or not (based on global
1147// preference).
1148bool DynamicLoaderDarwinKernel::BreakpointHitCallback(
1149 void *baton, StoppointCallbackContext *context, user_id_t break_id,
1150 user_id_t break_loc_id) {
1151 return static_cast<DynamicLoaderDarwinKernel *>(baton)->BreakpointHit(
1152 context, break_id, break_loc_id);
1153}
1154
1155bool DynamicLoaderDarwinKernel::BreakpointHit(StoppointCallbackContext *context,
1156 user_id_t break_id,
1157 user_id_t break_loc_id) {
1158 Log *log = GetLog(mask: LLDBLog::DynamicLoader);
1159 LLDB_LOGF(log, "DynamicLoaderDarwinKernel::BreakpointHit (...)\n");
1160
1161 ReadAllKextSummaries();
1162
1163 if (log)
1164 PutToLog(log);
1165
1166 return GetStopWhenImagesChange();
1167}
1168
1169bool DynamicLoaderDarwinKernel::ReadKextSummaryHeader() {
1170 std::lock_guard<std::recursive_mutex> guard(m_mutex);
1171
1172 // the all image infos is already valid for this process stop ID
1173
1174 if (m_kext_summary_header_ptr_addr.IsValid()) {
1175 const uint32_t addr_size = m_kernel.GetAddressByteSize();
1176 const ByteOrder byte_order = m_kernel.GetByteOrder();
1177 Status error;
1178 // Read enough bytes for a "OSKextLoadedKextSummaryHeader" structure which
1179 // is currently 4 uint32_t and a pointer.
1180 uint8_t buf[24];
1181 DataExtractor data(buf, sizeof(buf), byte_order, addr_size);
1182 const size_t count = 4 * sizeof(uint32_t) + addr_size;
1183 const bool force_live_memory = true;
1184 if (m_process->GetTarget().ReadPointerFromMemory(
1185 addr: m_kext_summary_header_ptr_addr, error,
1186 pointer_addr&: m_kext_summary_header_addr, force_live_memory)) {
1187 // We got a valid address for our kext summary header and make sure it
1188 // isn't NULL
1189 if (m_kext_summary_header_addr.IsValid() &&
1190 m_kext_summary_header_addr.GetFileAddress() != 0) {
1191 const size_t bytes_read = m_process->GetTarget().ReadMemory(
1192 addr: m_kext_summary_header_addr, dst: buf, dst_len: count, error, force_live_memory);
1193 if (bytes_read == count) {
1194 lldb::offset_t offset = 0;
1195 m_kext_summary_header.version = data.GetU32(offset_ptr: &offset);
1196 if (m_kext_summary_header.version > 128) {
1197 lldb::StreamSP s =
1198 m_process->GetTarget().GetDebugger().GetAsyncOutputStream();
1199 s->Printf(format: "WARNING: Unable to read kext summary header, got "
1200 "improbable version number %u\n",
1201 m_kext_summary_header.version);
1202 // If we get an improbably large version number, we're probably
1203 // getting bad memory.
1204 m_kext_summary_header_addr.Clear();
1205 return false;
1206 }
1207 if (m_kext_summary_header.version >= 2) {
1208 m_kext_summary_header.entry_size = data.GetU32(offset_ptr: &offset);
1209 if (m_kext_summary_header.entry_size > 4096) {
1210 // If we get an improbably large entry_size, we're probably
1211 // getting bad memory.
1212 lldb::StreamSP s =
1213 m_process->GetTarget().GetDebugger().GetAsyncOutputStream();
1214 s->Printf(format: "WARNING: Unable to read kext summary header, got "
1215 "improbable entry_size %u\n",
1216 m_kext_summary_header.entry_size);
1217 m_kext_summary_header_addr.Clear();
1218 return false;
1219 }
1220 } else {
1221 // Versions less than 2 didn't have an entry size, it was hard
1222 // coded
1223 m_kext_summary_header.entry_size =
1224 KERNEL_MODULE_ENTRY_SIZE_VERSION_1;
1225 }
1226 m_kext_summary_header.entry_count = data.GetU32(offset_ptr: &offset);
1227 if (m_kext_summary_header.entry_count > 10000) {
1228 // If we get an improbably large number of kexts, we're probably
1229 // getting bad memory.
1230 lldb::StreamSP s =
1231 m_process->GetTarget().GetDebugger().GetAsyncOutputStream();
1232 s->Printf(format: "WARNING: Unable to read kext summary header, got "
1233 "improbable number of kexts %u\n",
1234 m_kext_summary_header.entry_count);
1235 m_kext_summary_header_addr.Clear();
1236 return false;
1237 }
1238 return true;
1239 }
1240 }
1241 }
1242 }
1243 m_kext_summary_header_addr.Clear();
1244 return false;
1245}
1246
1247// We've either (a) just attached to a new kernel, or (b) the kexts-changed
1248// breakpoint was hit and we need to figure out what kexts have been added or
1249// removed. Read the kext summaries from the inferior kernel memory, compare
1250// them against the m_known_kexts vector and update the m_known_kexts vector as
1251// needed to keep in sync with the inferior.
1252
1253bool DynamicLoaderDarwinKernel::ParseKextSummaries(
1254 const Address &kext_summary_addr, uint32_t count) {
1255 KextImageInfo::collection kext_summaries;
1256 Log *log = GetLog(mask: LLDBLog::DynamicLoader);
1257 LLDB_LOGF(log,
1258 "Kexts-changed breakpoint hit, there are %d kexts currently.\n",
1259 count);
1260
1261 std::lock_guard<std::recursive_mutex> guard(m_mutex);
1262
1263 if (!ReadKextSummaries(kext_summary_addr, image_infos_count: count, image_infos&: kext_summaries))
1264 return false;
1265
1266 // read the plugin.dynamic-loader.darwin-kernel.load-kexts setting -- if the
1267 // user requested no kext loading, don't print any messages about kexts &
1268 // don't try to read them.
1269 const bool load_kexts = GetGlobalProperties().GetLoadKexts();
1270
1271 // By default, all kexts we've loaded in the past are marked as "remove" and
1272 // all of the kexts we just found out about from ReadKextSummaries are marked
1273 // as "add".
1274 std::vector<bool> to_be_removed(m_known_kexts.size(), true);
1275 std::vector<bool> to_be_added(count, true);
1276
1277 int number_of_new_kexts_being_added = 0;
1278 int number_of_old_kexts_being_removed = m_known_kexts.size();
1279
1280 const uint32_t new_kexts_size = kext_summaries.size();
1281 const uint32_t old_kexts_size = m_known_kexts.size();
1282
1283 // The m_known_kexts vector may have entries that have been Cleared, or are a
1284 // kernel.
1285 for (uint32_t old_kext = 0; old_kext < old_kexts_size; old_kext++) {
1286 bool ignore = false;
1287 KextImageInfo &image_info = m_known_kexts[old_kext];
1288 if (image_info.IsKernel()) {
1289 ignore = true;
1290 } else if (image_info.GetLoadAddress() == LLDB_INVALID_ADDRESS &&
1291 !image_info.GetModule()) {
1292 ignore = true;
1293 }
1294
1295 if (ignore) {
1296 number_of_old_kexts_being_removed--;
1297 to_be_removed[old_kext] = false;
1298 }
1299 }
1300
1301 // Scan over the list of kexts we just read from the kernel, note those that
1302 // need to be added and those already loaded.
1303 for (uint32_t new_kext = 0; new_kext < new_kexts_size; new_kext++) {
1304 bool add_this_one = true;
1305 for (uint32_t old_kext = 0; old_kext < old_kexts_size; old_kext++) {
1306 if (m_known_kexts[old_kext] == kext_summaries[new_kext]) {
1307 // We already have this kext, don't re-load it.
1308 to_be_added[new_kext] = false;
1309 // This kext is still present, do not remove it.
1310 to_be_removed[old_kext] = false;
1311
1312 number_of_old_kexts_being_removed--;
1313 add_this_one = false;
1314 break;
1315 }
1316 }
1317 // If this "kext" entry is actually an alias for the kernel -- the kext was
1318 // compiled into the kernel or something -- then we don't want to load the
1319 // kernel's text section at a different address. Ignore this kext entry.
1320 if (kext_summaries[new_kext].GetUUID().IsValid() &&
1321 m_kernel.GetUUID().IsValid() &&
1322 kext_summaries[new_kext].GetUUID() == m_kernel.GetUUID()) {
1323 to_be_added[new_kext] = false;
1324 break;
1325 }
1326 if (add_this_one) {
1327 number_of_new_kexts_being_added++;
1328 }
1329 }
1330
1331 if (number_of_new_kexts_being_added == 0 &&
1332 number_of_old_kexts_being_removed == 0)
1333 return true;
1334
1335 lldb::StreamSP s =
1336 m_process->GetTarget().GetDebugger().GetAsyncOutputStream();
1337 if (load_kexts) {
1338 if (number_of_new_kexts_being_added > 0 &&
1339 number_of_old_kexts_being_removed > 0) {
1340 s->Printf(format: "Loading %d kext modules and unloading %d kext modules ",
1341 number_of_new_kexts_being_added,
1342 number_of_old_kexts_being_removed);
1343 } else if (number_of_new_kexts_being_added > 0) {
1344 s->Printf(format: "Loading %d kext modules ", number_of_new_kexts_being_added);
1345 } else if (number_of_old_kexts_being_removed > 0) {
1346 s->Printf(format: "Unloading %d kext modules ",
1347 number_of_old_kexts_being_removed);
1348 }
1349 }
1350
1351 if (log) {
1352 if (load_kexts) {
1353 LLDB_LOGF(log,
1354 "DynamicLoaderDarwinKernel::ParseKextSummaries: %d kexts "
1355 "added, %d kexts removed",
1356 number_of_new_kexts_being_added,
1357 number_of_old_kexts_being_removed);
1358 } else {
1359 LLDB_LOGF(log,
1360 "DynamicLoaderDarwinKernel::ParseKextSummaries kext loading is "
1361 "disabled, else would have %d kexts added, %d kexts removed",
1362 number_of_new_kexts_being_added,
1363 number_of_old_kexts_being_removed);
1364 }
1365 }
1366
1367 // Build up a list of <kext-name, uuid> for any kexts that fail to load
1368 std::vector<std::pair<std::string, UUID>> kexts_failed_to_load;
1369 if (number_of_new_kexts_being_added > 0) {
1370 ModuleList loaded_module_list;
1371 Progress progress("Loading kext", "", number_of_new_kexts_being_added);
1372
1373 const uint32_t num_of_new_kexts = kext_summaries.size();
1374 for (uint32_t new_kext = 0; new_kext < num_of_new_kexts; new_kext++) {
1375 if (to_be_added[new_kext]) {
1376 KextImageInfo &image_info = kext_summaries[new_kext];
1377 if (load_kexts) {
1378 if (!image_info.LoadImageUsingMemoryModule(process: m_process, progress: &progress)) {
1379 kexts_failed_to_load.push_back(x: std::pair<std::string, UUID>(
1380 kext_summaries[new_kext].GetName(),
1381 kext_summaries[new_kext].GetUUID()));
1382 image_info.LoadImageAtFileAddress(process: m_process);
1383 }
1384 }
1385
1386 m_known_kexts.push_back(x: image_info);
1387
1388 if (image_info.GetModule() &&
1389 m_process->GetStopID() == image_info.GetProcessStopId())
1390 loaded_module_list.AppendIfNeeded(new_module: image_info.GetModule());
1391
1392 if (log)
1393 kext_summaries[new_kext].PutToLog(log);
1394 }
1395 }
1396 m_process->GetTarget().ModulesDidLoad(module_list&: loaded_module_list);
1397 }
1398
1399 if (number_of_old_kexts_being_removed > 0) {
1400 ModuleList loaded_module_list;
1401 const uint32_t num_of_old_kexts = m_known_kexts.size();
1402 for (uint32_t old_kext = 0; old_kext < num_of_old_kexts; old_kext++) {
1403 ModuleList unloaded_module_list;
1404 if (to_be_removed[old_kext]) {
1405 KextImageInfo &image_info = m_known_kexts[old_kext];
1406 // You can't unload the kernel.
1407 if (!image_info.IsKernel()) {
1408 if (image_info.GetModule()) {
1409 unloaded_module_list.AppendIfNeeded(new_module: image_info.GetModule());
1410 }
1411 s->Printf(format: ".");
1412 image_info.Clear();
1413 // should pull it out of the KextImageInfos vector but that would
1414 // mutate the list and invalidate the to_be_removed bool vector;
1415 // leaving it in place once Cleared() is relatively harmless.
1416 }
1417 }
1418 m_process->GetTarget().ModulesDidUnload(module_list&: unloaded_module_list, delete_locations: false);
1419 }
1420 }
1421
1422 if (load_kexts) {
1423 s->Printf(format: " done.\n");
1424 if (kexts_failed_to_load.size() > 0 && number_of_new_kexts_being_added > 0) {
1425 s->Printf(format: "Failed to load %d of %d kexts:\n",
1426 (int)kexts_failed_to_load.size(),
1427 number_of_new_kexts_being_added);
1428 // print a sorted list of <kext-name, uuid> kexts which failed to load
1429 unsigned longest_name = 0;
1430 std::sort(first: kexts_failed_to_load.begin(), last: kexts_failed_to_load.end());
1431 for (const auto &ku : kexts_failed_to_load) {
1432 if (ku.first.size() > longest_name)
1433 longest_name = ku.first.size();
1434 }
1435 for (const auto &ku : kexts_failed_to_load) {
1436 std::string uuid;
1437 if (ku.second.IsValid())
1438 uuid = ku.second.GetAsString();
1439 s->Printf(format: " %-*s %s\n", longest_name, ku.first.c_str(), uuid.c_str());
1440 }
1441 }
1442 }
1443
1444 return true;
1445}
1446
1447uint32_t DynamicLoaderDarwinKernel::ReadKextSummaries(
1448 const Address &kext_summary_addr, uint32_t image_infos_count,
1449 KextImageInfo::collection &image_infos) {
1450 const ByteOrder endian = m_kernel.GetByteOrder();
1451 const uint32_t addr_size = m_kernel.GetAddressByteSize();
1452
1453 image_infos.resize(new_size: image_infos_count);
1454 const size_t count = image_infos.size() * m_kext_summary_header.entry_size;
1455 DataBufferHeap data(count, 0);
1456 Status error;
1457
1458 const bool force_live_memory = true;
1459 const size_t bytes_read = m_process->GetTarget().ReadMemory(
1460 addr: kext_summary_addr, dst: data.GetBytes(), dst_len: data.GetByteSize(), error, force_live_memory);
1461 if (bytes_read == count) {
1462
1463 DataExtractor extractor(data.GetBytes(), data.GetByteSize(), endian,
1464 addr_size);
1465 uint32_t i = 0;
1466 for (uint32_t kext_summary_offset = 0;
1467 i < image_infos.size() &&
1468 extractor.ValidOffsetForDataOfSize(offset: kext_summary_offset,
1469 length: m_kext_summary_header.entry_size);
1470 ++i, kext_summary_offset += m_kext_summary_header.entry_size) {
1471 lldb::offset_t offset = kext_summary_offset;
1472 const void *name_data =
1473 extractor.GetData(offset_ptr: &offset, length: KERNEL_MODULE_MAX_NAME);
1474 if (name_data == nullptr)
1475 break;
1476 image_infos[i].SetName((const char *)name_data);
1477 UUID uuid(extractor.GetData(offset_ptr: &offset, length: 16), 16);
1478 image_infos[i].SetUUID(uuid);
1479 image_infos[i].SetLoadAddress(extractor.GetU64(offset_ptr: &offset));
1480 image_infos[i].SetSize(extractor.GetU64(offset_ptr: &offset));
1481 }
1482 if (i < image_infos.size())
1483 image_infos.resize(new_size: i);
1484 } else {
1485 image_infos.clear();
1486 }
1487 return image_infos.size();
1488}
1489
1490bool DynamicLoaderDarwinKernel::ReadAllKextSummaries() {
1491 std::lock_guard<std::recursive_mutex> guard(m_mutex);
1492
1493 if (ReadKextSummaryHeader()) {
1494 if (m_kext_summary_header.entry_count > 0 &&
1495 m_kext_summary_header_addr.IsValid()) {
1496 Address summary_addr(m_kext_summary_header_addr);
1497 summary_addr.Slide(offset: m_kext_summary_header.GetSize());
1498 if (!ParseKextSummaries(kext_summary_addr: summary_addr,
1499 count: m_kext_summary_header.entry_count)) {
1500 m_known_kexts.clear();
1501 }
1502 return true;
1503 }
1504 }
1505 return false;
1506}
1507
1508// Dump an image info structure to the file handle provided.
1509void DynamicLoaderDarwinKernel::KextImageInfo::PutToLog(Log *log) const {
1510 if (m_load_address == LLDB_INVALID_ADDRESS) {
1511 LLDB_LOG(log, "uuid={0} name=\"{1}\" (UNLOADED)", m_uuid.GetAsString(),
1512 m_name);
1513 } else {
1514 LLDB_LOG(log, "addr={0:x+16} size={1:x+16} uuid={2} name=\"{3}\"",
1515 m_load_address, m_size, m_uuid.GetAsString(), m_name);
1516 }
1517}
1518
1519// Dump the _dyld_all_image_infos members and all current image infos that we
1520// have parsed to the file handle provided.
1521void DynamicLoaderDarwinKernel::PutToLog(Log *log) const {
1522 if (log == nullptr)
1523 return;
1524
1525 std::lock_guard<std::recursive_mutex> guard(m_mutex);
1526 LLDB_LOGF(log,
1527 "gLoadedKextSummaries = 0x%16.16" PRIx64
1528 " { version=%u, entry_size=%u, entry_count=%u }",
1529 m_kext_summary_header_addr.GetFileAddress(),
1530 m_kext_summary_header.version, m_kext_summary_header.entry_size,
1531 m_kext_summary_header.entry_count);
1532
1533 size_t i;
1534 const size_t count = m_known_kexts.size();
1535 if (count > 0) {
1536 log->PutCString(cstr: "Loaded:");
1537 for (i = 0; i < count; i++)
1538 m_known_kexts[i].PutToLog(log);
1539 }
1540}
1541
1542void DynamicLoaderDarwinKernel::PrivateInitialize(Process *process) {
1543 DEBUG_PRINTF("DynamicLoaderDarwinKernel::%s() process state = %s\n",
1544 __FUNCTION__, StateAsCString(m_process->GetState()));
1545 Clear(clear_process: true);
1546 m_process = process;
1547}
1548
1549void DynamicLoaderDarwinKernel::SetNotificationBreakpointIfNeeded() {
1550 if (m_break_id == LLDB_INVALID_BREAK_ID && m_kernel.GetModule()) {
1551 DEBUG_PRINTF("DynamicLoaderDarwinKernel::%s() process state = %s\n",
1552 __FUNCTION__, StateAsCString(m_process->GetState()));
1553
1554 const bool internal_bp = true;
1555 const bool hardware = false;
1556 const LazyBool skip_prologue = eLazyBoolNo;
1557 FileSpecList module_spec_list;
1558 module_spec_list.Append(file: m_kernel.GetModule()->GetFileSpec());
1559 Breakpoint *bp =
1560 m_process->GetTarget()
1561 .CreateBreakpoint(containingModules: &module_spec_list, containingSourceFiles: nullptr,
1562 func_name: "OSKextLoadedKextSummariesUpdated",
1563 func_name_type_mask: eFunctionNameTypeFull, language: eLanguageTypeUnknown, offset: 0,
1564 skip_prologue, internal: internal_bp, request_hardware: hardware)
1565 .get();
1566
1567 bp->SetCallback(callback: DynamicLoaderDarwinKernel::BreakpointHitCallback, baton: this,
1568 is_synchronous: true);
1569 m_break_id = bp->GetID();
1570 }
1571}
1572
1573// Member function that gets called when the process state changes.
1574void DynamicLoaderDarwinKernel::PrivateProcessStateChanged(Process *process,
1575 StateType state) {
1576 DEBUG_PRINTF("DynamicLoaderDarwinKernel::%s(%s)\n", __FUNCTION__,
1577 StateAsCString(state));
1578 switch (state) {
1579 case eStateConnected:
1580 case eStateAttaching:
1581 case eStateLaunching:
1582 case eStateInvalid:
1583 case eStateUnloaded:
1584 case eStateExited:
1585 case eStateDetached:
1586 Clear(clear_process: false);
1587 break;
1588
1589 case eStateStopped:
1590 UpdateIfNeeded();
1591 break;
1592
1593 case eStateRunning:
1594 case eStateStepping:
1595 case eStateCrashed:
1596 case eStateSuspended:
1597 break;
1598 }
1599}
1600
1601ThreadPlanSP
1602DynamicLoaderDarwinKernel::GetStepThroughTrampolinePlan(Thread &thread,
1603 bool stop_others) {
1604 ThreadPlanSP thread_plan_sp;
1605 Log *log = GetLog(mask: LLDBLog::Step);
1606 LLDB_LOGF(log, "Could not find symbol for step through.");
1607 return thread_plan_sp;
1608}
1609
1610Status DynamicLoaderDarwinKernel::CanLoadImage() {
1611 Status error;
1612 error = Status::FromErrorString(
1613 str: "always unsafe to load or unload shared libraries in the darwin kernel");
1614 return error;
1615}
1616
1617void DynamicLoaderDarwinKernel::Initialize() {
1618 PluginManager::RegisterPlugin(name: GetPluginNameStatic(),
1619 description: GetPluginDescriptionStatic(), create_callback: CreateInstance,
1620 debugger_init_callback: DebuggerInitialize);
1621}
1622
1623void DynamicLoaderDarwinKernel::Terminate() {
1624 PluginManager::UnregisterPlugin(create_callback: CreateInstance);
1625}
1626
1627void DynamicLoaderDarwinKernel::DebuggerInitialize(
1628 lldb_private::Debugger &debugger) {
1629 if (!PluginManager::GetSettingForDynamicLoaderPlugin(
1630 debugger, setting_name: DynamicLoaderDarwinKernelProperties::GetSettingName())) {
1631 const bool is_global_setting = true;
1632 PluginManager::CreateSettingForDynamicLoaderPlugin(
1633 debugger, properties_sp: GetGlobalProperties().GetValueProperties(),
1634 description: "Properties for the DynamicLoaderDarwinKernel plug-in.",
1635 is_global_property: is_global_setting);
1636 }
1637}
1638
1639llvm::StringRef DynamicLoaderDarwinKernel::GetPluginDescriptionStatic() {
1640 return "Dynamic loader plug-in that watches for shared library loads/unloads "
1641 "in the MacOSX kernel.";
1642}
1643
1644lldb::ByteOrder
1645DynamicLoaderDarwinKernel::GetByteOrderFromMagic(uint32_t magic) {
1646 switch (magic) {
1647 case llvm::MachO::MH_MAGIC:
1648 case llvm::MachO::MH_MAGIC_64:
1649 return endian::InlHostByteOrder();
1650
1651 case llvm::MachO::MH_CIGAM:
1652 case llvm::MachO::MH_CIGAM_64:
1653 if (endian::InlHostByteOrder() == lldb::eByteOrderBig)
1654 return lldb::eByteOrderLittle;
1655 else
1656 return lldb::eByteOrderBig;
1657
1658 default:
1659 break;
1660 }
1661 return lldb::eByteOrderInvalid;
1662}
1663

Provided by KDAB

Privacy Policy
Improve your Profiling and Debugging skills
Find out more

source code of lldb/source/Plugins/DynamicLoader/Darwin-Kernel/DynamicLoaderDarwinKernel.cpp