1 //===-- DynamicLoaderMacOSXDYLD.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 "DynamicLoaderMacOSXDYLD.h"
10 #include "DynamicLoaderDarwin.h"
11 #include "DynamicLoaderMacOS.h"
12 #include "Plugins/LanguageRuntime/ObjC/ObjCLanguageRuntime.h"
13 #include "Plugins/TypeSystem/Clang/TypeSystemClang.h"
14 #include "lldb/Breakpoint/StoppointCallbackContext.h"
15 #include "lldb/Core/Debugger.h"
16 #include "lldb/Core/Module.h"
17 #include "lldb/Core/ModuleSpec.h"
18 #include "lldb/Core/PluginManager.h"
19 #include "lldb/Core/Section.h"
20 #include "lldb/Symbol/Function.h"
21 #include "lldb/Symbol/ObjectFile.h"
22 #include "lldb/Target/ABI.h"
23 #include "lldb/Target/RegisterContext.h"
24 #include "lldb/Target/StackFrame.h"
25 #include "lldb/Target/Target.h"
26 #include "lldb/Target/Thread.h"
27 #include "lldb/Target/ThreadPlanRunToAddress.h"
28 #include "lldb/Utility/DataBuffer.h"
29 #include "lldb/Utility/DataBufferHeap.h"
30 #include "lldb/Utility/LLDBLog.h"
31 #include "lldb/Utility/Log.h"
32 #include "lldb/Utility/State.h"
33
34 //#define ENABLE_DEBUG_PRINTF // COMMENT THIS LINE OUT PRIOR TO CHECKIN
35 #ifdef ENABLE_DEBUG_PRINTF
36 #include <cstdio>
37 #define DEBUG_PRINTF(fmt, ...) printf(fmt, ##__VA_ARGS__)
38 #else
39 #define DEBUG_PRINTF(fmt, ...)
40 #endif
41
42 #ifndef __APPLE__
43 #include "Utility/UuidCompatibility.h"
44 #else
45 #include <uuid/uuid.h>
46 #endif
47
48 using namespace lldb;
49 using namespace lldb_private;
50
LLDB_PLUGIN_DEFINE(DynamicLoaderMacOSXDYLD)51 LLDB_PLUGIN_DEFINE(DynamicLoaderMacOSXDYLD)
52
53 // Create an instance of this class. This function is filled into the plugin
54 // info class that gets handed out by the plugin factory and allows the lldb to
55 // instantiate an instance of this class.
56 DynamicLoader *DynamicLoaderMacOSXDYLD::CreateInstance(Process *process,
57 bool force) {
58 bool create = force;
59 if (!create) {
60 create = true;
61 Module *exe_module = process->GetTarget().GetExecutableModulePointer();
62 if (exe_module) {
63 ObjectFile *object_file = exe_module->GetObjectFile();
64 if (object_file) {
65 create = (object_file->GetStrata() == ObjectFile::eStrataUser);
66 }
67 }
68
69 if (create) {
70 const llvm::Triple &triple_ref =
71 process->GetTarget().GetArchitecture().GetTriple();
72 switch (triple_ref.getOS()) {
73 case llvm::Triple::Darwin:
74 case llvm::Triple::MacOSX:
75 case llvm::Triple::IOS:
76 case llvm::Triple::TvOS:
77 case llvm::Triple::WatchOS:
78 // NEED_BRIDGEOS_TRIPLE case llvm::Triple::BridgeOS:
79 create = triple_ref.getVendor() == llvm::Triple::Apple;
80 break;
81 default:
82 create = false;
83 break;
84 }
85 }
86 }
87
88 if (UseDYLDSPI(process)) {
89 create = false;
90 }
91
92 if (create)
93 return new DynamicLoaderMacOSXDYLD(process);
94 return nullptr;
95 }
96
97 // Constructor
DynamicLoaderMacOSXDYLD(Process * process)98 DynamicLoaderMacOSXDYLD::DynamicLoaderMacOSXDYLD(Process *process)
99 : DynamicLoaderDarwin(process),
100 m_dyld_all_image_infos_addr(LLDB_INVALID_ADDRESS),
101 m_dyld_all_image_infos(), m_dyld_all_image_infos_stop_id(UINT32_MAX),
102 m_break_id(LLDB_INVALID_BREAK_ID), m_mutex(),
103 m_process_image_addr_is_all_images_infos(false) {}
104
105 // Destructor
~DynamicLoaderMacOSXDYLD()106 DynamicLoaderMacOSXDYLD::~DynamicLoaderMacOSXDYLD() {
107 if (LLDB_BREAK_ID_IS_VALID(m_break_id))
108 m_process->GetTarget().RemoveBreakpointByID(m_break_id);
109 }
110
ProcessDidExec()111 bool DynamicLoaderMacOSXDYLD::ProcessDidExec() {
112 std::lock_guard<std::recursive_mutex> baseclass_guard(GetMutex());
113 bool did_exec = false;
114 if (m_process) {
115 // If we are stopped after an exec, we will have only one thread...
116 if (m_process->GetThreadList().GetSize() == 1) {
117 // We know if a process has exec'ed if our "m_dyld_all_image_infos_addr"
118 // value differs from the Process' image info address. When a process
119 // execs itself it might cause a change if ASLR is enabled.
120 const addr_t shlib_addr = m_process->GetImageInfoAddress();
121 if (m_process_image_addr_is_all_images_infos &&
122 shlib_addr != m_dyld_all_image_infos_addr) {
123 // The image info address from the process is the
124 // 'dyld_all_image_infos' address and it has changed.
125 did_exec = true;
126 } else if (!m_process_image_addr_is_all_images_infos &&
127 shlib_addr == m_dyld.address) {
128 // The image info address from the process is the mach_header address
129 // for dyld and it has changed.
130 did_exec = true;
131 } else {
132 // ASLR might be disabled and dyld could have ended up in the same
133 // location. We should try and detect if we are stopped at
134 // '_dyld_start'
135 ThreadSP thread_sp(m_process->GetThreadList().GetThreadAtIndex(0));
136 if (thread_sp) {
137 lldb::StackFrameSP frame_sp(thread_sp->GetStackFrameAtIndex(0));
138 if (frame_sp) {
139 const Symbol *symbol =
140 frame_sp->GetSymbolContext(eSymbolContextSymbol).symbol;
141 if (symbol) {
142 if (symbol->GetName() == "_dyld_start")
143 did_exec = true;
144 }
145 }
146 }
147 }
148
149 if (did_exec) {
150 m_libpthread_module_wp.reset();
151 m_pthread_getspecific_addr.Clear();
152 }
153 }
154 }
155 return did_exec;
156 }
157
158 // Clear out the state of this class.
DoClear()159 void DynamicLoaderMacOSXDYLD::DoClear() {
160 std::lock_guard<std::recursive_mutex> guard(m_mutex);
161
162 if (LLDB_BREAK_ID_IS_VALID(m_break_id))
163 m_process->GetTarget().RemoveBreakpointByID(m_break_id);
164
165 m_dyld_all_image_infos_addr = LLDB_INVALID_ADDRESS;
166 m_dyld_all_image_infos.Clear();
167 m_break_id = LLDB_INVALID_BREAK_ID;
168 }
169
170 // Check if we have found DYLD yet
DidSetNotificationBreakpoint()171 bool DynamicLoaderMacOSXDYLD::DidSetNotificationBreakpoint() {
172 return LLDB_BREAK_ID_IS_VALID(m_break_id);
173 }
174
ClearNotificationBreakpoint()175 void DynamicLoaderMacOSXDYLD::ClearNotificationBreakpoint() {
176 if (LLDB_BREAK_ID_IS_VALID(m_break_id)) {
177 m_process->GetTarget().RemoveBreakpointByID(m_break_id);
178 }
179 }
180
181 // Try and figure out where dyld is by first asking the Process if it knows
182 // (which currently calls down in the lldb::Process to get the DYLD info
183 // (available on SnowLeopard only). If that fails, then check in the default
184 // addresses.
DoInitialImageFetch()185 void DynamicLoaderMacOSXDYLD::DoInitialImageFetch() {
186 if (m_dyld_all_image_infos_addr == LLDB_INVALID_ADDRESS) {
187 // Check the image info addr as it might point to the mach header for dyld,
188 // or it might point to the dyld_all_image_infos struct
189 const addr_t shlib_addr = m_process->GetImageInfoAddress();
190 if (shlib_addr != LLDB_INVALID_ADDRESS) {
191 ByteOrder byte_order =
192 m_process->GetTarget().GetArchitecture().GetByteOrder();
193 uint8_t buf[4];
194 DataExtractor data(buf, sizeof(buf), byte_order, 4);
195 Status error;
196 if (m_process->ReadMemory(shlib_addr, buf, 4, error) == 4) {
197 lldb::offset_t offset = 0;
198 uint32_t magic = data.GetU32(&offset);
199 switch (magic) {
200 case llvm::MachO::MH_MAGIC:
201 case llvm::MachO::MH_MAGIC_64:
202 case llvm::MachO::MH_CIGAM:
203 case llvm::MachO::MH_CIGAM_64:
204 m_process_image_addr_is_all_images_infos = false;
205 ReadDYLDInfoFromMemoryAndSetNotificationCallback(shlib_addr);
206 return;
207
208 default:
209 break;
210 }
211 }
212 // Maybe it points to the all image infos?
213 m_dyld_all_image_infos_addr = shlib_addr;
214 m_process_image_addr_is_all_images_infos = true;
215 }
216 }
217
218 if (m_dyld_all_image_infos_addr != LLDB_INVALID_ADDRESS) {
219 if (ReadAllImageInfosStructure()) {
220 if (m_dyld_all_image_infos.dyldImageLoadAddress != LLDB_INVALID_ADDRESS)
221 ReadDYLDInfoFromMemoryAndSetNotificationCallback(
222 m_dyld_all_image_infos.dyldImageLoadAddress);
223 else
224 ReadDYLDInfoFromMemoryAndSetNotificationCallback(
225 m_dyld_all_image_infos_addr & 0xfffffffffff00000ull);
226 return;
227 }
228 }
229
230 // Check some default values
231 Module *executable = m_process->GetTarget().GetExecutableModulePointer();
232
233 if (executable) {
234 const ArchSpec &exe_arch = executable->GetArchitecture();
235 if (exe_arch.GetAddressByteSize() == 8) {
236 ReadDYLDInfoFromMemoryAndSetNotificationCallback(0x7fff5fc00000ull);
237 } else if (exe_arch.GetMachine() == llvm::Triple::arm ||
238 exe_arch.GetMachine() == llvm::Triple::thumb ||
239 exe_arch.GetMachine() == llvm::Triple::aarch64 ||
240 exe_arch.GetMachine() == llvm::Triple::aarch64_32) {
241 ReadDYLDInfoFromMemoryAndSetNotificationCallback(0x2fe00000);
242 } else {
243 ReadDYLDInfoFromMemoryAndSetNotificationCallback(0x8fe00000);
244 }
245 }
246 }
247
248 // Assume that dyld is in memory at ADDR and try to parse it's load commands
ReadDYLDInfoFromMemoryAndSetNotificationCallback(lldb::addr_t addr)249 bool DynamicLoaderMacOSXDYLD::ReadDYLDInfoFromMemoryAndSetNotificationCallback(
250 lldb::addr_t addr) {
251 std::lock_guard<std::recursive_mutex> baseclass_guard(GetMutex());
252 DataExtractor data; // Load command data
253 static ConstString g_dyld_all_image_infos("dyld_all_image_infos");
254 static ConstString g_new_dyld_all_image_infos("dyld4::dyld_all_image_infos");
255 if (ReadMachHeader(addr, &m_dyld.header, &data)) {
256 if (m_dyld.header.filetype == llvm::MachO::MH_DYLINKER) {
257 m_dyld.address = addr;
258 ModuleSP dyld_module_sp;
259 if (ParseLoadCommands(data, m_dyld, &m_dyld.file_spec)) {
260 if (m_dyld.file_spec) {
261 UpdateDYLDImageInfoFromNewImageInfo(m_dyld);
262 }
263 }
264 dyld_module_sp = GetDYLDModule();
265
266 Target &target = m_process->GetTarget();
267
268 if (m_dyld_all_image_infos_addr == LLDB_INVALID_ADDRESS &&
269 dyld_module_sp.get()) {
270 const Symbol *symbol = dyld_module_sp->FindFirstSymbolWithNameAndType(
271 g_dyld_all_image_infos, eSymbolTypeData);
272 if (!symbol) {
273 symbol = dyld_module_sp->FindFirstSymbolWithNameAndType(
274 g_new_dyld_all_image_infos, eSymbolTypeData);
275 }
276 if (symbol)
277 m_dyld_all_image_infos_addr = symbol->GetLoadAddress(&target);
278 }
279
280 // Update all image infos
281 InitializeFromAllImageInfos();
282
283 // If we didn't have an executable before, but now we do, then the dyld
284 // module shared pointer might be unique and we may need to add it again
285 // (since Target::SetExecutableModule() will clear the images). So append
286 // the dyld module back to the list if it is
287 /// unique!
288 if (dyld_module_sp) {
289 target.GetImages().AppendIfNeeded(dyld_module_sp);
290
291 // At this point we should have read in dyld's module, and so we should
292 // set breakpoints in it:
293 ModuleList modules;
294 modules.Append(dyld_module_sp);
295 target.ModulesDidLoad(modules);
296 SetDYLDModule(dyld_module_sp);
297 }
298
299 return true;
300 }
301 }
302 return false;
303 }
304
NeedToDoInitialImageFetch()305 bool DynamicLoaderMacOSXDYLD::NeedToDoInitialImageFetch() {
306 return m_dyld_all_image_infos_addr == LLDB_INVALID_ADDRESS;
307 }
308
309 // Static callback function that gets called when our DYLD notification
310 // breakpoint gets hit. We update all of our image infos and then let our super
311 // class DynamicLoader class decide if we should stop or not (based on global
312 // preference).
NotifyBreakpointHit(void * baton,StoppointCallbackContext * context,lldb::user_id_t break_id,lldb::user_id_t break_loc_id)313 bool DynamicLoaderMacOSXDYLD::NotifyBreakpointHit(
314 void *baton, StoppointCallbackContext *context, lldb::user_id_t break_id,
315 lldb::user_id_t break_loc_id) {
316 // Let the event know that the images have changed
317 // DYLD passes three arguments to the notification breakpoint.
318 // Arg1: enum dyld_image_mode mode - 0 = adding, 1 = removing Arg2: uint32_t
319 // infoCount - Number of shared libraries added Arg3: dyld_image_info
320 // info[] - Array of structs of the form:
321 // const struct mach_header
322 // *imageLoadAddress
323 // const char *imageFilePath
324 // uintptr_t imageFileModDate (a time_t)
325
326 DynamicLoaderMacOSXDYLD *dyld_instance = (DynamicLoaderMacOSXDYLD *)baton;
327
328 // First step is to see if we've already initialized the all image infos. If
329 // we haven't then this function will do so and return true. In the course
330 // of initializing the all_image_infos it will read the complete current
331 // state, so we don't need to figure out what has changed from the data
332 // passed in to us.
333
334 ExecutionContext exe_ctx(context->exe_ctx_ref);
335 Process *process = exe_ctx.GetProcessPtr();
336
337 // This is a sanity check just in case this dyld_instance is an old dyld
338 // plugin's breakpoint still lying around.
339 if (process != dyld_instance->m_process)
340 return false;
341
342 if (dyld_instance->InitializeFromAllImageInfos())
343 return dyld_instance->GetStopWhenImagesChange();
344
345 const lldb::ABISP &abi = process->GetABI();
346 if (abi) {
347 // Build up the value array to store the three arguments given above, then
348 // get the values from the ABI:
349
350 TypeSystemClang *clang_ast_context =
351 ScratchTypeSystemClang::GetForTarget(process->GetTarget());
352 if (!clang_ast_context)
353 return false;
354
355 ValueList argument_values;
356 Value input_value;
357
358 CompilerType clang_void_ptr_type =
359 clang_ast_context->GetBasicType(eBasicTypeVoid).GetPointerType();
360 CompilerType clang_uint32_type =
361 clang_ast_context->GetBuiltinTypeForEncodingAndBitSize(
362 lldb::eEncodingUint, 32);
363 input_value.SetValueType(Value::ValueType::Scalar);
364 input_value.SetCompilerType(clang_uint32_type);
365 // input_value.SetContext (Value::eContextTypeClangType,
366 // clang_uint32_type);
367 argument_values.PushValue(input_value);
368 argument_values.PushValue(input_value);
369 input_value.SetCompilerType(clang_void_ptr_type);
370 // input_value.SetContext (Value::eContextTypeClangType,
371 // clang_void_ptr_type);
372 argument_values.PushValue(input_value);
373
374 if (abi->GetArgumentValues(exe_ctx.GetThreadRef(), argument_values)) {
375 uint32_t dyld_mode =
376 argument_values.GetValueAtIndex(0)->GetScalar().UInt(-1);
377 if (dyld_mode != static_cast<uint32_t>(-1)) {
378 // Okay the mode was right, now get the number of elements, and the
379 // array of new elements...
380 uint32_t image_infos_count =
381 argument_values.GetValueAtIndex(1)->GetScalar().UInt(-1);
382 if (image_infos_count != static_cast<uint32_t>(-1)) {
383 // Got the number added, now go through the array of added elements,
384 // putting out the mach header address, and adding the image. Note,
385 // I'm not putting in logging here, since the AddModules &
386 // RemoveModules functions do all the logging internally.
387
388 lldb::addr_t image_infos_addr =
389 argument_values.GetValueAtIndex(2)->GetScalar().ULongLong();
390 if (dyld_mode == 0) {
391 // This is add:
392 dyld_instance->AddModulesUsingImageInfosAddress(image_infos_addr,
393 image_infos_count);
394 } else {
395 // This is remove:
396 dyld_instance->RemoveModulesUsingImageInfosAddress(
397 image_infos_addr, image_infos_count);
398 }
399 }
400 }
401 }
402 } else {
403 Target &target = process->GetTarget();
404 Debugger::ReportWarning(
405 "no ABI plugin located for triple " +
406 target.GetArchitecture().GetTriple().getTriple() +
407 ": shared libraries will not be registered",
408 target.GetDebugger().GetID());
409 }
410
411 // Return true to stop the target, false to just let the target run
412 return dyld_instance->GetStopWhenImagesChange();
413 }
414
ReadAllImageInfosStructure()415 bool DynamicLoaderMacOSXDYLD::ReadAllImageInfosStructure() {
416 std::lock_guard<std::recursive_mutex> guard(m_mutex);
417
418 // the all image infos is already valid for this process stop ID
419 if (m_process->GetStopID() == m_dyld_all_image_infos_stop_id)
420 return true;
421
422 m_dyld_all_image_infos.Clear();
423 if (m_dyld_all_image_infos_addr != LLDB_INVALID_ADDRESS) {
424 ByteOrder byte_order =
425 m_process->GetTarget().GetArchitecture().GetByteOrder();
426 uint32_t addr_size =
427 m_process->GetTarget().GetArchitecture().GetAddressByteSize();
428
429 uint8_t buf[256];
430 DataExtractor data(buf, sizeof(buf), byte_order, addr_size);
431 lldb::offset_t offset = 0;
432
433 const size_t count_v2 = sizeof(uint32_t) + // version
434 sizeof(uint32_t) + // infoArrayCount
435 addr_size + // infoArray
436 addr_size + // notification
437 addr_size + // processDetachedFromSharedRegion +
438 // libSystemInitialized + pad
439 addr_size; // dyldImageLoadAddress
440 const size_t count_v11 = count_v2 + addr_size + // jitInfo
441 addr_size + // dyldVersion
442 addr_size + // errorMessage
443 addr_size + // terminationFlags
444 addr_size + // coreSymbolicationShmPage
445 addr_size + // systemOrderFlag
446 addr_size + // uuidArrayCount
447 addr_size + // uuidArray
448 addr_size + // dyldAllImageInfosAddress
449 addr_size + // initialImageCount
450 addr_size + // errorKind
451 addr_size + // errorClientOfDylibPath
452 addr_size + // errorTargetDylibPath
453 addr_size; // errorSymbol
454 const size_t count_v13 = count_v11 + addr_size + // sharedCacheSlide
455 sizeof(uuid_t); // sharedCacheUUID
456 UNUSED_IF_ASSERT_DISABLED(count_v13);
457 assert(sizeof(buf) >= count_v13);
458
459 Status error;
460 if (m_process->ReadMemory(m_dyld_all_image_infos_addr, buf, 4, error) ==
461 4) {
462 m_dyld_all_image_infos.version = data.GetU32(&offset);
463 // If anything in the high byte is set, we probably got the byte order
464 // incorrect (the process might not have it set correctly yet due to
465 // attaching to a program without a specified file).
466 if (m_dyld_all_image_infos.version & 0xff000000) {
467 // We have guessed the wrong byte order. Swap it and try reading the
468 // version again.
469 if (byte_order == eByteOrderLittle)
470 byte_order = eByteOrderBig;
471 else
472 byte_order = eByteOrderLittle;
473
474 data.SetByteOrder(byte_order);
475 offset = 0;
476 m_dyld_all_image_infos.version = data.GetU32(&offset);
477 }
478 } else {
479 return false;
480 }
481
482 const size_t count =
483 (m_dyld_all_image_infos.version >= 11) ? count_v11 : count_v2;
484
485 const size_t bytes_read =
486 m_process->ReadMemory(m_dyld_all_image_infos_addr, buf, count, error);
487 if (bytes_read == count) {
488 offset = 0;
489 m_dyld_all_image_infos.version = data.GetU32(&offset);
490 m_dyld_all_image_infos.dylib_info_count = data.GetU32(&offset);
491 m_dyld_all_image_infos.dylib_info_addr = data.GetAddress(&offset);
492 m_dyld_all_image_infos.notification = data.GetAddress(&offset);
493 m_dyld_all_image_infos.processDetachedFromSharedRegion =
494 data.GetU8(&offset);
495 m_dyld_all_image_infos.libSystemInitialized = data.GetU8(&offset);
496 // Adjust for padding.
497 offset += addr_size - 2;
498 m_dyld_all_image_infos.dyldImageLoadAddress = data.GetAddress(&offset);
499 if (m_dyld_all_image_infos.version >= 11) {
500 offset += addr_size * 8;
501 uint64_t dyld_all_image_infos_addr = data.GetAddress(&offset);
502
503 // When we started, we were given the actual address of the
504 // all_image_infos struct (probably via TASK_DYLD_INFO) in memory -
505 // this address is stored in m_dyld_all_image_infos_addr and is the
506 // most accurate address we have.
507
508 // We read the dyld_all_image_infos struct from memory; it contains its
509 // own address. If the address in the struct does not match the actual
510 // address, the dyld we're looking at has been loaded at a different
511 // location (slid) from where it intended to load. The addresses in
512 // the dyld_all_image_infos struct are the original, non-slid
513 // addresses, and need to be adjusted. Most importantly the address of
514 // dyld and the notification address need to be adjusted.
515
516 if (dyld_all_image_infos_addr != m_dyld_all_image_infos_addr) {
517 uint64_t image_infos_offset =
518 dyld_all_image_infos_addr -
519 m_dyld_all_image_infos.dyldImageLoadAddress;
520 uint64_t notification_offset =
521 m_dyld_all_image_infos.notification -
522 m_dyld_all_image_infos.dyldImageLoadAddress;
523 m_dyld_all_image_infos.dyldImageLoadAddress =
524 m_dyld_all_image_infos_addr - image_infos_offset;
525 m_dyld_all_image_infos.notification =
526 m_dyld_all_image_infos.dyldImageLoadAddress + notification_offset;
527 }
528 }
529 m_dyld_all_image_infos_stop_id = m_process->GetStopID();
530 return true;
531 }
532 }
533 return false;
534 }
535
AddModulesUsingImageInfosAddress(lldb::addr_t image_infos_addr,uint32_t image_infos_count)536 bool DynamicLoaderMacOSXDYLD::AddModulesUsingImageInfosAddress(
537 lldb::addr_t image_infos_addr, uint32_t image_infos_count) {
538 ImageInfo::collection image_infos;
539 Log *log = GetLog(LLDBLog::DynamicLoader);
540 LLDB_LOGF(log, "Adding %d modules.\n", image_infos_count);
541
542 std::lock_guard<std::recursive_mutex> guard(m_mutex);
543 std::lock_guard<std::recursive_mutex> baseclass_guard(GetMutex());
544 if (m_process->GetStopID() == m_dyld_image_infos_stop_id)
545 return true;
546
547 StructuredData::ObjectSP image_infos_json_sp =
548 m_process->GetLoadedDynamicLibrariesInfos(image_infos_addr,
549 image_infos_count);
550 if (image_infos_json_sp.get() && image_infos_json_sp->GetAsDictionary() &&
551 image_infos_json_sp->GetAsDictionary()->HasKey("images") &&
552 image_infos_json_sp->GetAsDictionary()
553 ->GetValueForKey("images")
554 ->GetAsArray() &&
555 image_infos_json_sp->GetAsDictionary()
556 ->GetValueForKey("images")
557 ->GetAsArray()
558 ->GetSize() == image_infos_count) {
559 bool return_value = false;
560 if (JSONImageInformationIntoImageInfo(image_infos_json_sp, image_infos)) {
561 UpdateSpecialBinariesFromNewImageInfos(image_infos);
562 return_value = AddModulesUsingImageInfos(image_infos);
563 }
564 m_dyld_image_infos_stop_id = m_process->GetStopID();
565 return return_value;
566 }
567
568 if (!ReadImageInfos(image_infos_addr, image_infos_count, image_infos))
569 return false;
570
571 UpdateImageInfosHeaderAndLoadCommands(image_infos, image_infos_count, false);
572 bool return_value = AddModulesUsingImageInfos(image_infos);
573 m_dyld_image_infos_stop_id = m_process->GetStopID();
574 return return_value;
575 }
576
RemoveModulesUsingImageInfosAddress(lldb::addr_t image_infos_addr,uint32_t image_infos_count)577 bool DynamicLoaderMacOSXDYLD::RemoveModulesUsingImageInfosAddress(
578 lldb::addr_t image_infos_addr, uint32_t image_infos_count) {
579 ImageInfo::collection image_infos;
580 Log *log = GetLog(LLDBLog::DynamicLoader);
581
582 std::lock_guard<std::recursive_mutex> guard(m_mutex);
583 std::lock_guard<std::recursive_mutex> baseclass_guard(GetMutex());
584 if (m_process->GetStopID() == m_dyld_image_infos_stop_id)
585 return true;
586
587 // First read in the image_infos for the removed modules, and their headers &
588 // load commands.
589 if (!ReadImageInfos(image_infos_addr, image_infos_count, image_infos)) {
590 if (log)
591 log->PutCString("Failed reading image infos array.");
592 return false;
593 }
594
595 LLDB_LOGF(log, "Removing %d modules.", image_infos_count);
596
597 ModuleList unloaded_module_list;
598 for (uint32_t idx = 0; idx < image_infos.size(); ++idx) {
599 if (log) {
600 LLDB_LOGF(log, "Removing module at address=0x%16.16" PRIx64 ".",
601 image_infos[idx].address);
602 image_infos[idx].PutToLog(log);
603 }
604
605 // Remove this image_infos from the m_all_image_infos. We do the
606 // comparison by address rather than by file spec because we can have many
607 // modules with the same "file spec" in the case that they are modules
608 // loaded from memory.
609 //
610 // Also copy over the uuid from the old entry to the removed entry so we
611 // can use it to lookup the module in the module list.
612
613 bool found = false;
614
615 for (ImageInfo::collection::iterator pos = m_dyld_image_infos.begin();
616 pos != m_dyld_image_infos.end(); pos++) {
617 if (image_infos[idx].address == (*pos).address) {
618 image_infos[idx].uuid = (*pos).uuid;
619
620 // Add the module from this image_info to the "unloaded_module_list".
621 // We'll remove them all at one go later on.
622
623 ModuleSP unload_image_module_sp(
624 FindTargetModuleForImageInfo(image_infos[idx], false, nullptr));
625 if (unload_image_module_sp.get()) {
626 // When we unload, be sure to use the image info from the old list,
627 // since that has sections correctly filled in.
628 UnloadModuleSections(unload_image_module_sp.get(), *pos);
629 unloaded_module_list.AppendIfNeeded(unload_image_module_sp);
630 } else {
631 if (log) {
632 LLDB_LOGF(log, "Could not find module for unloading info entry:");
633 image_infos[idx].PutToLog(log);
634 }
635 }
636
637 // Then remove it from the m_dyld_image_infos:
638
639 m_dyld_image_infos.erase(pos);
640 found = true;
641 break;
642 }
643 }
644
645 if (!found) {
646 if (log) {
647 LLDB_LOGF(log, "Could not find image_info entry for unloading image:");
648 image_infos[idx].PutToLog(log);
649 }
650 }
651 }
652 if (unloaded_module_list.GetSize() > 0) {
653 if (log) {
654 log->PutCString("Unloaded:");
655 unloaded_module_list.LogUUIDAndPaths(
656 log, "DynamicLoaderMacOSXDYLD::ModulesDidUnload");
657 }
658 m_process->GetTarget().GetImages().Remove(unloaded_module_list);
659 }
660 m_dyld_image_infos_stop_id = m_process->GetStopID();
661 return true;
662 }
663
ReadImageInfos(lldb::addr_t image_infos_addr,uint32_t image_infos_count,ImageInfo::collection & image_infos)664 bool DynamicLoaderMacOSXDYLD::ReadImageInfos(
665 lldb::addr_t image_infos_addr, uint32_t image_infos_count,
666 ImageInfo::collection &image_infos) {
667 std::lock_guard<std::recursive_mutex> baseclass_guard(GetMutex());
668 const ByteOrder endian = GetByteOrderFromMagic(m_dyld.header.magic);
669 const uint32_t addr_size = m_dyld.GetAddressByteSize();
670
671 image_infos.resize(image_infos_count);
672 const size_t count = image_infos.size() * 3 * addr_size;
673 DataBufferHeap info_data(count, 0);
674 Status error;
675 const size_t bytes_read = m_process->ReadMemory(
676 image_infos_addr, info_data.GetBytes(), info_data.GetByteSize(), error);
677 if (bytes_read == count) {
678 lldb::offset_t info_data_offset = 0;
679 DataExtractor info_data_ref(info_data.GetBytes(), info_data.GetByteSize(),
680 endian, addr_size);
681 for (size_t i = 0;
682 i < image_infos.size() && info_data_ref.ValidOffset(info_data_offset);
683 i++) {
684 image_infos[i].address = info_data_ref.GetAddress(&info_data_offset);
685 lldb::addr_t path_addr = info_data_ref.GetAddress(&info_data_offset);
686 image_infos[i].mod_date = info_data_ref.GetAddress(&info_data_offset);
687
688 char raw_path[PATH_MAX];
689 m_process->ReadCStringFromMemory(path_addr, raw_path, sizeof(raw_path),
690 error);
691 // don't resolve the path
692 if (error.Success()) {
693 image_infos[i].file_spec.SetFile(raw_path, FileSpec::Style::native);
694 }
695 }
696 return true;
697 } else {
698 return false;
699 }
700 }
701
702 // If we have found where the "_dyld_all_image_infos" lives in memory, read the
703 // current info from it, and then update all image load addresses (or lack
704 // thereof). Only do this if this is the first time we're reading the dyld
705 // infos. Return true if we actually read anything, and false otherwise.
InitializeFromAllImageInfos()706 bool DynamicLoaderMacOSXDYLD::InitializeFromAllImageInfos() {
707 Log *log = GetLog(LLDBLog::DynamicLoader);
708
709 std::lock_guard<std::recursive_mutex> guard(m_mutex);
710 std::lock_guard<std::recursive_mutex> baseclass_guard(GetMutex());
711 if (m_process->GetStopID() == m_dyld_image_infos_stop_id ||
712 m_dyld_image_infos.size() != 0)
713 return false;
714
715 if (ReadAllImageInfosStructure()) {
716 // Nothing to load or unload?
717 if (m_dyld_all_image_infos.dylib_info_count == 0)
718 return true;
719
720 if (m_dyld_all_image_infos.dylib_info_addr == 0) {
721 // DYLD is updating the images now. So we should say we have no images,
722 // and then we'll
723 // figure it out when we hit the added breakpoint.
724 return false;
725 } else {
726 if (!AddModulesUsingImageInfosAddress(
727 m_dyld_all_image_infos.dylib_info_addr,
728 m_dyld_all_image_infos.dylib_info_count)) {
729 DEBUG_PRINTF("%s", "unable to read all data for all_dylib_infos.");
730 m_dyld_image_infos.clear();
731 }
732 }
733
734 // Now we have one more bit of business. If there is a library left in the
735 // images for our target that doesn't have a load address, then it must be
736 // something that we were expecting to load (for instance we read a load
737 // command for it) but it didn't in fact load - probably because
738 // DYLD_*_PATH pointed to an equivalent version. We don't want it to stay
739 // in the target's module list or it will confuse us, so unload it here.
740 Target &target = m_process->GetTarget();
741 ModuleList not_loaded_modules;
742 for (ModuleSP module_sp : target.GetImages().Modules()) {
743 if (!module_sp->IsLoadedInTarget(&target)) {
744 if (log) {
745 StreamString s;
746 module_sp->GetDescription(s.AsRawOstream());
747 LLDB_LOGF(log, "Unloading pre-run module: %s.", s.GetData());
748 }
749 not_loaded_modules.Append(module_sp);
750 }
751 }
752
753 if (not_loaded_modules.GetSize() != 0) {
754 target.GetImages().Remove(not_loaded_modules);
755 }
756
757 return true;
758 } else
759 return false;
760 }
761
762 // Read a mach_header at ADDR into HEADER, and also fill in the load command
763 // data into LOAD_COMMAND_DATA if it is non-NULL.
764 //
765 // Returns true if we succeed, false if we fail for any reason.
ReadMachHeader(lldb::addr_t addr,llvm::MachO::mach_header * header,DataExtractor * load_command_data)766 bool DynamicLoaderMacOSXDYLD::ReadMachHeader(lldb::addr_t addr,
767 llvm::MachO::mach_header *header,
768 DataExtractor *load_command_data) {
769 DataBufferHeap header_bytes(sizeof(llvm::MachO::mach_header), 0);
770 Status error;
771 size_t bytes_read = m_process->ReadMemory(addr, header_bytes.GetBytes(),
772 header_bytes.GetByteSize(), error);
773 if (bytes_read == sizeof(llvm::MachO::mach_header)) {
774 lldb::offset_t offset = 0;
775 ::memset(header, 0, sizeof(llvm::MachO::mach_header));
776
777 // Get the magic byte unswapped so we can figure out what we are dealing
778 // with
779 DataExtractor data(header_bytes.GetBytes(), header_bytes.GetByteSize(),
780 endian::InlHostByteOrder(), 4);
781 header->magic = data.GetU32(&offset);
782 lldb::addr_t load_cmd_addr = addr;
783 data.SetByteOrder(
784 DynamicLoaderMacOSXDYLD::GetByteOrderFromMagic(header->magic));
785 switch (header->magic) {
786 case llvm::MachO::MH_MAGIC:
787 case llvm::MachO::MH_CIGAM:
788 data.SetAddressByteSize(4);
789 load_cmd_addr += sizeof(llvm::MachO::mach_header);
790 break;
791
792 case llvm::MachO::MH_MAGIC_64:
793 case llvm::MachO::MH_CIGAM_64:
794 data.SetAddressByteSize(8);
795 load_cmd_addr += sizeof(llvm::MachO::mach_header_64);
796 break;
797
798 default:
799 return false;
800 }
801
802 // Read the rest of dyld's mach header
803 if (data.GetU32(&offset, &header->cputype,
804 (sizeof(llvm::MachO::mach_header) / sizeof(uint32_t)) -
805 1)) {
806 if (load_command_data == nullptr)
807 return true; // We were able to read the mach_header and weren't asked
808 // to read the load command bytes
809
810 WritableDataBufferSP load_cmd_data_sp(
811 new DataBufferHeap(header->sizeofcmds, 0));
812
813 size_t load_cmd_bytes_read =
814 m_process->ReadMemory(load_cmd_addr, load_cmd_data_sp->GetBytes(),
815 load_cmd_data_sp->GetByteSize(), error);
816
817 if (load_cmd_bytes_read == header->sizeofcmds) {
818 // Set the load command data and also set the correct endian swap
819 // settings and the correct address size
820 load_command_data->SetData(load_cmd_data_sp, 0, header->sizeofcmds);
821 load_command_data->SetByteOrder(data.GetByteOrder());
822 load_command_data->SetAddressByteSize(data.GetAddressByteSize());
823 return true; // We successfully read the mach_header and the load
824 // command data
825 }
826
827 return false; // We weren't able to read the load command data
828 }
829 }
830 return false; // We failed the read the mach_header
831 }
832
833 // Parse the load commands for an image
ParseLoadCommands(const DataExtractor & data,ImageInfo & dylib_info,FileSpec * lc_id_dylinker)834 uint32_t DynamicLoaderMacOSXDYLD::ParseLoadCommands(const DataExtractor &data,
835 ImageInfo &dylib_info,
836 FileSpec *lc_id_dylinker) {
837 lldb::offset_t offset = 0;
838 uint32_t cmd_idx;
839 Segment segment;
840 dylib_info.Clear(true);
841
842 for (cmd_idx = 0; cmd_idx < dylib_info.header.ncmds; cmd_idx++) {
843 // Clear out any load command specific data from DYLIB_INFO since we are
844 // about to read it.
845
846 if (data.ValidOffsetForDataOfSize(offset,
847 sizeof(llvm::MachO::load_command))) {
848 llvm::MachO::load_command load_cmd;
849 lldb::offset_t load_cmd_offset = offset;
850 load_cmd.cmd = data.GetU32(&offset);
851 load_cmd.cmdsize = data.GetU32(&offset);
852 switch (load_cmd.cmd) {
853 case llvm::MachO::LC_SEGMENT: {
854 segment.name.SetTrimmedCStringWithLength(
855 (const char *)data.GetData(&offset, 16), 16);
856 // We are putting 4 uint32_t values 4 uint64_t values so we have to use
857 // multiple 32 bit gets below.
858 segment.vmaddr = data.GetU32(&offset);
859 segment.vmsize = data.GetU32(&offset);
860 segment.fileoff = data.GetU32(&offset);
861 segment.filesize = data.GetU32(&offset);
862 // Extract maxprot, initprot, nsects and flags all at once
863 data.GetU32(&offset, &segment.maxprot, 4);
864 dylib_info.segments.push_back(segment);
865 } break;
866
867 case llvm::MachO::LC_SEGMENT_64: {
868 segment.name.SetTrimmedCStringWithLength(
869 (const char *)data.GetData(&offset, 16), 16);
870 // Extract vmaddr, vmsize, fileoff, and filesize all at once
871 data.GetU64(&offset, &segment.vmaddr, 4);
872 // Extract maxprot, initprot, nsects and flags all at once
873 data.GetU32(&offset, &segment.maxprot, 4);
874 dylib_info.segments.push_back(segment);
875 } break;
876
877 case llvm::MachO::LC_ID_DYLINKER:
878 if (lc_id_dylinker) {
879 const lldb::offset_t name_offset =
880 load_cmd_offset + data.GetU32(&offset);
881 const char *path = data.PeekCStr(name_offset);
882 lc_id_dylinker->SetFile(path, FileSpec::Style::native);
883 FileSystem::Instance().Resolve(*lc_id_dylinker);
884 }
885 break;
886
887 case llvm::MachO::LC_UUID:
888 dylib_info.uuid = UUID::fromOptionalData(data.GetData(&offset, 16), 16);
889 break;
890
891 default:
892 break;
893 }
894 // Set offset to be the beginning of the next load command.
895 offset = load_cmd_offset + load_cmd.cmdsize;
896 }
897 }
898
899 // All sections listed in the dyld image info structure will all either be
900 // fixed up already, or they will all be off by a single slide amount that is
901 // determined by finding the first segment that is at file offset zero which
902 // also has bytes (a file size that is greater than zero) in the object file.
903
904 // Determine the slide amount (if any)
905 const size_t num_sections = dylib_info.segments.size();
906 for (size_t i = 0; i < num_sections; ++i) {
907 // Iterate through the object file sections to find the first section that
908 // starts of file offset zero and that has bytes in the file...
909 if ((dylib_info.segments[i].fileoff == 0 &&
910 dylib_info.segments[i].filesize > 0) ||
911 (dylib_info.segments[i].name == "__TEXT")) {
912 dylib_info.slide = dylib_info.address - dylib_info.segments[i].vmaddr;
913 // We have found the slide amount, so we can exit this for loop.
914 break;
915 }
916 }
917 return cmd_idx;
918 }
919
920 // Read the mach_header and load commands for each image that the
921 // _dyld_all_image_infos structure points to and cache the results.
922
UpdateImageInfosHeaderAndLoadCommands(ImageInfo::collection & image_infos,uint32_t infos_count,bool update_executable)923 void DynamicLoaderMacOSXDYLD::UpdateImageInfosHeaderAndLoadCommands(
924 ImageInfo::collection &image_infos, uint32_t infos_count,
925 bool update_executable) {
926 uint32_t exe_idx = UINT32_MAX;
927 // Read any UUID values that we can get
928 for (uint32_t i = 0; i < infos_count; i++) {
929 if (!image_infos[i].UUIDValid()) {
930 DataExtractor data; // Load command data
931 if (!ReadMachHeader(image_infos[i].address, &image_infos[i].header,
932 &data))
933 continue;
934
935 ParseLoadCommands(data, image_infos[i], nullptr);
936
937 if (image_infos[i].header.filetype == llvm::MachO::MH_EXECUTE)
938 exe_idx = i;
939 }
940 }
941
942 Target &target = m_process->GetTarget();
943
944 if (exe_idx < image_infos.size()) {
945 const bool can_create = true;
946 ModuleSP exe_module_sp(FindTargetModuleForImageInfo(image_infos[exe_idx],
947 can_create, nullptr));
948
949 if (exe_module_sp) {
950 UpdateImageLoadAddress(exe_module_sp.get(), image_infos[exe_idx]);
951
952 if (exe_module_sp.get() != target.GetExecutableModulePointer()) {
953 // Don't load dependent images since we are in dyld where we will know
954 // and find out about all images that are loaded. Also when setting the
955 // executable module, it will clear the targets module list, and if we
956 // have an in memory dyld module, it will get removed from the list so
957 // we will need to add it back after setting the executable module, so
958 // we first try and see if we already have a weak pointer to the dyld
959 // module, make it into a shared pointer, then add the executable, then
960 // re-add it back to make sure it is always in the list.
961 ModuleSP dyld_module_sp(GetDYLDModule());
962
963 m_process->GetTarget().SetExecutableModule(exe_module_sp,
964 eLoadDependentsNo);
965
966 if (dyld_module_sp) {
967 if (target.GetImages().AppendIfNeeded(dyld_module_sp)) {
968 std::lock_guard<std::recursive_mutex> baseclass_guard(GetMutex());
969
970 // Also add it to the section list.
971 UpdateImageLoadAddress(dyld_module_sp.get(), m_dyld);
972 }
973 }
974 }
975 }
976 }
977 }
978
979 // Dump the _dyld_all_image_infos members and all current image infos that we
980 // have parsed to the file handle provided.
PutToLog(Log * log) const981 void DynamicLoaderMacOSXDYLD::PutToLog(Log *log) const {
982 if (log == nullptr)
983 return;
984
985 std::lock_guard<std::recursive_mutex> guard(m_mutex);
986 std::lock_guard<std::recursive_mutex> baseclass_guard(GetMutex());
987 LLDB_LOGF(log,
988 "dyld_all_image_infos = { version=%d, count=%d, addr=0x%8.8" PRIx64
989 ", notify=0x%8.8" PRIx64 " }",
990 m_dyld_all_image_infos.version,
991 m_dyld_all_image_infos.dylib_info_count,
992 (uint64_t)m_dyld_all_image_infos.dylib_info_addr,
993 (uint64_t)m_dyld_all_image_infos.notification);
994 size_t i;
995 const size_t count = m_dyld_image_infos.size();
996 if (count > 0) {
997 log->PutCString("Loaded:");
998 for (i = 0; i < count; i++)
999 m_dyld_image_infos[i].PutToLog(log);
1000 }
1001 }
1002
SetNotificationBreakpoint()1003 bool DynamicLoaderMacOSXDYLD::SetNotificationBreakpoint() {
1004 DEBUG_PRINTF("DynamicLoaderMacOSXDYLD::%s() process state = %s\n",
1005 __FUNCTION__, StateAsCString(m_process->GetState()));
1006 if (m_break_id == LLDB_INVALID_BREAK_ID) {
1007 if (m_dyld_all_image_infos.notification != LLDB_INVALID_ADDRESS) {
1008 Address so_addr;
1009 // Set the notification breakpoint and install a breakpoint callback
1010 // function that will get called each time the breakpoint gets hit. We
1011 // will use this to track when shared libraries get loaded/unloaded.
1012 bool resolved = m_process->GetTarget().ResolveLoadAddress(
1013 m_dyld_all_image_infos.notification, so_addr);
1014 if (!resolved) {
1015 ModuleSP dyld_module_sp = GetDYLDModule();
1016 if (dyld_module_sp) {
1017 std::lock_guard<std::recursive_mutex> baseclass_guard(GetMutex());
1018
1019 UpdateImageLoadAddress(dyld_module_sp.get(), m_dyld);
1020 resolved = m_process->GetTarget().ResolveLoadAddress(
1021 m_dyld_all_image_infos.notification, so_addr);
1022 }
1023 }
1024
1025 if (resolved) {
1026 Breakpoint *dyld_break =
1027 m_process->GetTarget().CreateBreakpoint(so_addr, true, false).get();
1028 dyld_break->SetCallback(DynamicLoaderMacOSXDYLD::NotifyBreakpointHit,
1029 this, true);
1030 dyld_break->SetBreakpointKind("shared-library-event");
1031 m_break_id = dyld_break->GetID();
1032 }
1033 }
1034 }
1035 return m_break_id != LLDB_INVALID_BREAK_ID;
1036 }
1037
CanLoadImage()1038 Status DynamicLoaderMacOSXDYLD::CanLoadImage() {
1039 Status error;
1040 // In order for us to tell if we can load a shared library we verify that the
1041 // dylib_info_addr isn't zero (which means no shared libraries have been set
1042 // yet, or dyld is currently mucking with the shared library list).
1043 if (ReadAllImageInfosStructure()) {
1044 // TODO: also check the _dyld_global_lock_held variable in
1045 // libSystem.B.dylib?
1046 // TODO: check the malloc lock?
1047 // TODO: check the objective C lock?
1048 if (m_dyld_all_image_infos.dylib_info_addr != 0)
1049 return error; // Success
1050 }
1051
1052 error.SetErrorString("unsafe to load or unload shared libraries");
1053 return error;
1054 }
1055
GetSharedCacheInformation(lldb::addr_t & base_address,UUID & uuid,LazyBool & using_shared_cache,LazyBool & private_shared_cache)1056 bool DynamicLoaderMacOSXDYLD::GetSharedCacheInformation(
1057 lldb::addr_t &base_address, UUID &uuid, LazyBool &using_shared_cache,
1058 LazyBool &private_shared_cache) {
1059 base_address = LLDB_INVALID_ADDRESS;
1060 uuid.Clear();
1061 using_shared_cache = eLazyBoolCalculate;
1062 private_shared_cache = eLazyBoolCalculate;
1063
1064 if (m_process) {
1065 addr_t all_image_infos = m_process->GetImageInfoAddress();
1066
1067 // The address returned by GetImageInfoAddress may be the address of dyld
1068 // (don't want) or it may be the address of the dyld_all_image_infos
1069 // structure (want). The first four bytes will be either the version field
1070 // (all_image_infos) or a Mach-O file magic constant. Version 13 and higher
1071 // of dyld_all_image_infos is required to get the sharedCacheUUID field.
1072
1073 Status err;
1074 uint32_t version_or_magic =
1075 m_process->ReadUnsignedIntegerFromMemory(all_image_infos, 4, -1, err);
1076 if (version_or_magic != static_cast<uint32_t>(-1) &&
1077 version_or_magic != llvm::MachO::MH_MAGIC &&
1078 version_or_magic != llvm::MachO::MH_CIGAM &&
1079 version_or_magic != llvm::MachO::MH_MAGIC_64 &&
1080 version_or_magic != llvm::MachO::MH_CIGAM_64 &&
1081 version_or_magic >= 13) {
1082 addr_t sharedCacheUUID_address = LLDB_INVALID_ADDRESS;
1083 int wordsize = m_process->GetAddressByteSize();
1084 if (wordsize == 8) {
1085 sharedCacheUUID_address =
1086 all_image_infos + 160; // sharedCacheUUID <mach-o/dyld_images.h>
1087 }
1088 if (wordsize == 4) {
1089 sharedCacheUUID_address =
1090 all_image_infos + 84; // sharedCacheUUID <mach-o/dyld_images.h>
1091 }
1092 if (sharedCacheUUID_address != LLDB_INVALID_ADDRESS) {
1093 uuid_t shared_cache_uuid;
1094 if (m_process->ReadMemory(sharedCacheUUID_address, shared_cache_uuid,
1095 sizeof(uuid_t), err) == sizeof(uuid_t)) {
1096 uuid = UUID::fromOptionalData(shared_cache_uuid, 16);
1097 if (uuid.IsValid()) {
1098 using_shared_cache = eLazyBoolYes;
1099 }
1100 }
1101
1102 if (version_or_magic >= 15) {
1103 // The sharedCacheBaseAddress field is the next one in the
1104 // dyld_all_image_infos struct.
1105 addr_t sharedCacheBaseAddr_address = sharedCacheUUID_address + 16;
1106 Status error;
1107 base_address = m_process->ReadUnsignedIntegerFromMemory(
1108 sharedCacheBaseAddr_address, wordsize, LLDB_INVALID_ADDRESS,
1109 error);
1110 if (error.Fail())
1111 base_address = LLDB_INVALID_ADDRESS;
1112 }
1113
1114 return true;
1115 }
1116
1117 //
1118 // add
1119 // NB: sharedCacheBaseAddress is the next field in dyld_all_image_infos
1120 // after
1121 // sharedCacheUUID -- that is, 16 bytes after it, if we wanted to fetch
1122 // it.
1123 }
1124 }
1125 return false;
1126 }
1127
IsFullyInitialized()1128 bool DynamicLoaderMacOSXDYLD::IsFullyInitialized() {
1129 if (ReadAllImageInfosStructure())
1130 return m_dyld_all_image_infos.libSystemInitialized;
1131 return false;
1132 }
1133
Initialize()1134 void DynamicLoaderMacOSXDYLD::Initialize() {
1135 PluginManager::RegisterPlugin(GetPluginNameStatic(),
1136 GetPluginDescriptionStatic(), CreateInstance);
1137 DynamicLoaderMacOS::Initialize();
1138 }
1139
Terminate()1140 void DynamicLoaderMacOSXDYLD::Terminate() {
1141 DynamicLoaderMacOS::Terminate();
1142 PluginManager::UnregisterPlugin(CreateInstance);
1143 }
1144
GetPluginDescriptionStatic()1145 llvm::StringRef DynamicLoaderMacOSXDYLD::GetPluginDescriptionStatic() {
1146 return "Dynamic loader plug-in that watches for shared library loads/unloads "
1147 "in MacOSX user processes.";
1148 }
1149
AddrByteSize()1150 uint32_t DynamicLoaderMacOSXDYLD::AddrByteSize() {
1151 std::lock_guard<std::recursive_mutex> baseclass_guard(GetMutex());
1152
1153 switch (m_dyld.header.magic) {
1154 case llvm::MachO::MH_MAGIC:
1155 case llvm::MachO::MH_CIGAM:
1156 return 4;
1157
1158 case llvm::MachO::MH_MAGIC_64:
1159 case llvm::MachO::MH_CIGAM_64:
1160 return 8;
1161
1162 default:
1163 break;
1164 }
1165 return 0;
1166 }
1167
GetByteOrderFromMagic(uint32_t magic)1168 lldb::ByteOrder DynamicLoaderMacOSXDYLD::GetByteOrderFromMagic(uint32_t magic) {
1169 switch (magic) {
1170 case llvm::MachO::MH_MAGIC:
1171 case llvm::MachO::MH_MAGIC_64:
1172 return endian::InlHostByteOrder();
1173
1174 case llvm::MachO::MH_CIGAM:
1175 case llvm::MachO::MH_CIGAM_64:
1176 if (endian::InlHostByteOrder() == lldb::eByteOrderBig)
1177 return lldb::eByteOrderLittle;
1178 else
1179 return lldb::eByteOrderBig;
1180
1181 default:
1182 break;
1183 }
1184 return lldb::eByteOrderInvalid;
1185 }
1186