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