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 
11 #include "lldb/Breakpoint/StoppointCallbackContext.h"
12 #include "lldb/Core/DataBuffer.h"
13 #include "lldb/Core/DataBufferHeap.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 
33 //#define ENABLE_DEBUG_PRINTF // COMMENT THIS LINE OUT PRIOR TO CHECKIN
34 #ifdef ENABLE_DEBUG_PRINTF
35 #include <stdio.h>
36 #define DEBUG_PRINTF(fmt, ...) printf(fmt, ## __VA_ARGS__)
37 #else
38 #define DEBUG_PRINTF(fmt, ...)
39 #endif
40 
41 #ifndef __APPLE__
42 #include "Utility/UuidCompatibility.h"
43 #endif
44 
45 using namespace lldb;
46 using namespace lldb_private;
47 
48 /// FIXME - The ObjC Runtime trampoline handler doesn't really belong here.
49 /// I am putting it here so I can invoke it in the Trampoline code here, but
50 /// it should be moved to the ObjC Runtime support when it is set up.
51 
52 
53 DynamicLoaderMacOSXDYLD::DYLDImageInfo *
54 DynamicLoaderMacOSXDYLD::GetImageInfo (Module *module)
55 {
56     const UUID &module_uuid = module->GetUUID();
57     DYLDImageInfo::collection::iterator pos, end = m_dyld_image_infos.end();
58 
59     // First try just by UUID as it is the safest.
60     if (module_uuid.IsValid())
61     {
62         for (pos = m_dyld_image_infos.begin(); pos != end; ++pos)
63         {
64             if (pos->uuid == module_uuid)
65                 return &(*pos);
66         }
67 
68         if (m_dyld.uuid == module_uuid)
69             return &m_dyld;
70     }
71 
72     // Next try by platform path only for things that don't have a valid UUID
73     // since if a file has a valid UUID in real life it should also in the
74     // dyld info. This is the next safest because the paths in the dyld info
75     // are platform paths, not local paths. For local debugging platform == local
76     // paths.
77     const FileSpec &platform_file_spec = module->GetPlatformFileSpec();
78     for (pos = m_dyld_image_infos.begin(); pos != end; ++pos)
79     {
80         if (pos->file_spec == platform_file_spec && pos->uuid.IsValid() == false)
81             return &(*pos);
82     }
83 
84     if (m_dyld.file_spec == platform_file_spec && m_dyld.uuid.IsValid() == false)
85         return &m_dyld;
86 
87     return NULL;
88 }
89 
90 //----------------------------------------------------------------------
91 // Create an instance of this class. This function is filled into
92 // the plugin info class that gets handed out by the plugin factory and
93 // allows the lldb to instantiate an instance of this class.
94 //----------------------------------------------------------------------
95 DynamicLoader *
96 DynamicLoaderMacOSXDYLD::CreateInstance (Process* process, bool force)
97 {
98     bool create = force;
99     if (!create)
100     {
101         create = true;
102         Module* exe_module = process->GetTarget().GetExecutableModulePointer();
103         if (exe_module)
104         {
105             ObjectFile *object_file = exe_module->GetObjectFile();
106             if (object_file)
107             {
108                 create = (object_file->GetStrata() == ObjectFile::eStrataUser);
109             }
110         }
111 
112         if (create)
113         {
114             const llvm::Triple &triple_ref = process->GetTarget().GetArchitecture().GetTriple();
115             switch (triple_ref.getOS())
116             {
117                 case llvm::Triple::Darwin:
118                 case llvm::Triple::MacOSX:
119                 case llvm::Triple::IOS:
120                     create = triple_ref.getVendor() == llvm::Triple::Apple;
121                     break;
122                 default:
123                     create = false;
124                     break;
125             }
126         }
127     }
128 
129     if (create)
130         return new DynamicLoaderMacOSXDYLD (process);
131     return NULL;
132 }
133 
134 //----------------------------------------------------------------------
135 // Constructor
136 //----------------------------------------------------------------------
137 DynamicLoaderMacOSXDYLD::DynamicLoaderMacOSXDYLD (Process* process) :
138     DynamicLoader(process),
139     m_dyld(),
140     m_dyld_module_wp(),
141     m_dyld_all_image_infos_addr(LLDB_INVALID_ADDRESS),
142     m_dyld_all_image_infos(),
143     m_dyld_all_image_infos_stop_id (UINT32_MAX),
144     m_break_id(LLDB_INVALID_BREAK_ID),
145     m_dyld_image_infos(),
146     m_dyld_image_infos_stop_id (UINT32_MAX),
147     m_mutex(Mutex::eMutexTypeRecursive),
148     m_process_image_addr_is_all_images_infos (false)
149 {
150 }
151 
152 //----------------------------------------------------------------------
153 // Destructor
154 //----------------------------------------------------------------------
155 DynamicLoaderMacOSXDYLD::~DynamicLoaderMacOSXDYLD()
156 {
157     Clear(true);
158 }
159 
160 //------------------------------------------------------------------
161 /// Called after attaching a process.
162 ///
163 /// Allow DynamicLoader plug-ins to execute some code after
164 /// attaching to a process.
165 //------------------------------------------------------------------
166 void
167 DynamicLoaderMacOSXDYLD::DidAttach ()
168 {
169     PrivateInitialize(m_process);
170     LocateDYLD ();
171     SetNotificationBreakpoint ();
172 }
173 
174 //------------------------------------------------------------------
175 /// Called after attaching a process.
176 ///
177 /// Allow DynamicLoader plug-ins to execute some code after
178 /// attaching to a process.
179 //------------------------------------------------------------------
180 void
181 DynamicLoaderMacOSXDYLD::DidLaunch ()
182 {
183     PrivateInitialize(m_process);
184     LocateDYLD ();
185     SetNotificationBreakpoint ();
186 }
187 
188 bool
189 DynamicLoaderMacOSXDYLD::ProcessDidExec ()
190 {
191     if (m_process)
192     {
193         // If we are stopped after an exec, we will have only one thread...
194         if (m_process->GetThreadList().GetSize() == 1)
195         {
196             // We know if a process has exec'ed if our "m_dyld_all_image_infos_addr"
197             // value differs from the Process' image info address. When a process
198             // execs itself it might cause a change if ASLR is enabled.
199             const addr_t shlib_addr = m_process->GetImageInfoAddress ();
200             if (m_process_image_addr_is_all_images_infos == true && shlib_addr != m_dyld_all_image_infos_addr)
201             {
202                 // The image info address from the process is the 'dyld_all_image_infos'
203                 // address and it has changed.
204                 return true;
205             }
206 
207             if (m_process_image_addr_is_all_images_infos == false && shlib_addr == m_dyld.address)
208             {
209                 // The image info address from the process is the mach_header
210                 // address for dyld and it has changed.
211                 return true;
212             }
213 
214             // ASLR might be disabled and dyld could have ended up in the same
215             // location. We should try and detect if we are stopped at '_dyld_start'
216             ThreadSP thread_sp (m_process->GetThreadList().GetThreadAtIndex(0));
217             if (thread_sp)
218             {
219                 lldb::StackFrameSP frame_sp (thread_sp->GetStackFrameAtIndex(0));
220                 if (frame_sp)
221                 {
222                     const Symbol *symbol = frame_sp->GetSymbolContext(eSymbolContextSymbol).symbol;
223                     if (symbol)
224                     {
225                         if (symbol->GetName() == ConstString("_dyld_start"))
226                             return true;
227                     }
228                 }
229             }
230         }
231     }
232     return false;
233 }
234 
235 
236 
237 //----------------------------------------------------------------------
238 // Clear out the state of this class.
239 //----------------------------------------------------------------------
240 void
241 DynamicLoaderMacOSXDYLD::Clear (bool clear_process)
242 {
243     Mutex::Locker locker(m_mutex);
244 
245     if (m_process->IsAlive() && LLDB_BREAK_ID_IS_VALID(m_break_id))
246         m_process->GetTarget().RemoveBreakpointByID (m_break_id);
247 
248     if (clear_process)
249         m_process = NULL;
250     m_dyld.Clear(false);
251     m_dyld_all_image_infos_addr = LLDB_INVALID_ADDRESS;
252     m_dyld_all_image_infos.Clear();
253     m_break_id = LLDB_INVALID_BREAK_ID;
254     m_dyld_image_infos.clear();
255 }
256 
257 //----------------------------------------------------------------------
258 // Check if we have found DYLD yet
259 //----------------------------------------------------------------------
260 bool
261 DynamicLoaderMacOSXDYLD::DidSetNotificationBreakpoint() const
262 {
263     return LLDB_BREAK_ID_IS_VALID (m_break_id);
264 }
265 
266 //----------------------------------------------------------------------
267 // Try and figure out where dyld is by first asking the Process
268 // if it knows (which currently calls down in the lldb::Process
269 // to get the DYLD info (available on SnowLeopard only). If that fails,
270 // then check in the default addresses.
271 //----------------------------------------------------------------------
272 bool
273 DynamicLoaderMacOSXDYLD::LocateDYLD()
274 {
275     if (m_dyld_all_image_infos_addr == LLDB_INVALID_ADDRESS)
276     {
277         // Check the image info addr as it might point to the
278         // mach header for dyld, or it might point to the
279         // dyld_all_image_infos struct
280         const addr_t shlib_addr = m_process->GetImageInfoAddress ();
281         if (shlib_addr != LLDB_INVALID_ADDRESS)
282         {
283             ByteOrder byte_order = m_process->GetTarget().GetArchitecture().GetByteOrder();
284             uint8_t buf[4];
285             DataExtractor data (buf, sizeof(buf), byte_order, 4);
286             Error error;
287             if (m_process->ReadMemory (shlib_addr, buf, 4, error) == 4)
288             {
289                 lldb::offset_t offset = 0;
290                 uint32_t magic = data.GetU32 (&offset);
291                 switch (magic)
292                 {
293                 case llvm::MachO::MH_MAGIC:
294                 case llvm::MachO::MH_MAGIC_64:
295                 case llvm::MachO::MH_CIGAM:
296                 case llvm::MachO::MH_CIGAM_64:
297                     m_process_image_addr_is_all_images_infos = false;
298                     return ReadDYLDInfoFromMemoryAndSetNotificationCallback(shlib_addr);
299 
300                 default:
301                     break;
302                 }
303             }
304             // Maybe it points to the all image infos?
305             m_dyld_all_image_infos_addr = shlib_addr;
306             m_process_image_addr_is_all_images_infos = true;
307         }
308     }
309 
310     if (m_dyld_all_image_infos_addr != LLDB_INVALID_ADDRESS)
311     {
312         if (ReadAllImageInfosStructure ())
313         {
314             if (m_dyld_all_image_infos.dyldImageLoadAddress != LLDB_INVALID_ADDRESS)
315                 return ReadDYLDInfoFromMemoryAndSetNotificationCallback (m_dyld_all_image_infos.dyldImageLoadAddress);
316             else
317                 return ReadDYLDInfoFromMemoryAndSetNotificationCallback (m_dyld_all_image_infos_addr & 0xfffffffffff00000ull);
318         }
319     }
320 
321     // Check some default values
322     Module *executable = m_process->GetTarget().GetExecutableModulePointer();
323 
324     if (executable)
325     {
326         const ArchSpec &exe_arch = executable->GetArchitecture();
327         if (exe_arch.GetAddressByteSize() == 8)
328         {
329             return ReadDYLDInfoFromMemoryAndSetNotificationCallback(0x7fff5fc00000ull);
330         }
331         else if (exe_arch.GetMachine() == llvm::Triple::arm || exe_arch.GetMachine() == llvm::Triple::thumb || exe_arch.GetMachine() == llvm::Triple::aarch64)
332         {
333             return ReadDYLDInfoFromMemoryAndSetNotificationCallback(0x2fe00000);
334         }
335         else
336         {
337             return ReadDYLDInfoFromMemoryAndSetNotificationCallback(0x8fe00000);
338         }
339     }
340     return false;
341 }
342 
343 ModuleSP
344 DynamicLoaderMacOSXDYLD::FindTargetModuleForDYLDImageInfo (DYLDImageInfo &image_info, bool can_create, bool *did_create_ptr)
345 {
346     if (did_create_ptr)
347         *did_create_ptr = false;
348 
349     Target &target = m_process->GetTarget();
350     const ModuleList &target_images = target.GetImages();
351     ModuleSpec module_spec (image_info.file_spec);
352     module_spec.GetUUID() = image_info.uuid;
353     ModuleSP module_sp (target_images.FindFirstModule (module_spec));
354 
355     if (module_sp && !module_spec.GetUUID().IsValid() && !module_sp->GetUUID().IsValid())
356     {
357         // No UUID, we must rely upon the cached module modification
358         // time and the modification time of the file on disk
359         if (module_sp->GetModificationTime() != module_sp->GetFileSpec().GetModificationTime())
360             module_sp.reset();
361     }
362 
363     if (!module_sp)
364     {
365         if (can_create)
366         {
367             module_sp = target.GetSharedModule (module_spec);
368             if (!module_sp || module_sp->GetObjectFile() == NULL)
369                 module_sp = m_process->ReadModuleFromMemory (image_info.file_spec, image_info.address);
370 
371             if (did_create_ptr)
372                 *did_create_ptr = (bool) module_sp;
373         }
374     }
375     return module_sp;
376 }
377 
378 //----------------------------------------------------------------------
379 // Assume that dyld is in memory at ADDR and try to parse it's load
380 // commands
381 //----------------------------------------------------------------------
382 bool
383 DynamicLoaderMacOSXDYLD::ReadDYLDInfoFromMemoryAndSetNotificationCallback(lldb::addr_t addr)
384 {
385     DataExtractor data; // Load command data
386     if (ReadMachHeader (addr, &m_dyld.header, &data))
387     {
388         if (m_dyld.header.filetype == llvm::MachO::MH_DYLINKER)
389         {
390             m_dyld.address = addr;
391             ModuleSP dyld_module_sp;
392             if (ParseLoadCommands (data, m_dyld, &m_dyld.file_spec))
393             {
394                 if (m_dyld.file_spec)
395                 {
396                     dyld_module_sp = FindTargetModuleForDYLDImageInfo (m_dyld, true, NULL);
397 
398                     if (dyld_module_sp)
399                         UpdateImageLoadAddress (dyld_module_sp.get(), m_dyld);
400                 }
401             }
402 
403             Target &target = m_process->GetTarget();
404 
405             if (m_dyld_all_image_infos_addr == LLDB_INVALID_ADDRESS && dyld_module_sp.get())
406             {
407                 static ConstString g_dyld_all_image_infos ("dyld_all_image_infos");
408                 const Symbol *symbol = dyld_module_sp->FindFirstSymbolWithNameAndType (g_dyld_all_image_infos, eSymbolTypeData);
409                 if (symbol)
410                     m_dyld_all_image_infos_addr = symbol->GetAddress().GetLoadAddress(&target);
411             }
412 
413             // Update all image infos
414             InitializeFromAllImageInfos ();
415 
416             // If we didn't have an executable before, but now we do, then the
417             // dyld module shared pointer might be unique and we may need to add
418             // it again (since Target::SetExecutableModule() will clear the
419             // images). So append the dyld module back to the list if it is
420             /// unique!
421             if (dyld_module_sp)
422             {
423                 target.GetImages().AppendIfNeeded (dyld_module_sp);
424 
425                 // At this point we should have read in dyld's module, and so we should set breakpoints in it:
426                 ModuleList modules;
427                 modules.Append(dyld_module_sp);
428                 target.ModulesDidLoad(modules);
429                 m_dyld_module_wp = dyld_module_sp;
430             }
431             return true;
432         }
433     }
434     return false;
435 }
436 
437 bool
438 DynamicLoaderMacOSXDYLD::NeedToLocateDYLD () const
439 {
440     return m_dyld_all_image_infos_addr == LLDB_INVALID_ADDRESS;
441 }
442 
443 //----------------------------------------------------------------------
444 // Update the load addresses for all segments in MODULE using the
445 // updated INFO that is passed in.
446 //----------------------------------------------------------------------
447 bool
448 DynamicLoaderMacOSXDYLD::UpdateImageLoadAddress (Module *module, DYLDImageInfo& info)
449 {
450     bool changed = false;
451     if (module)
452     {
453         ObjectFile *image_object_file = module->GetObjectFile();
454         if (image_object_file)
455         {
456             SectionList *section_list = image_object_file->GetSectionList ();
457             if (section_list)
458             {
459                 std::vector<uint32_t> inaccessible_segment_indexes;
460                 // We now know the slide amount, so go through all sections
461                 // and update the load addresses with the correct values.
462                 const size_t num_segments = info.segments.size();
463                 for (size_t i=0; i<num_segments; ++i)
464                 {
465                     // Only load a segment if it has protections. Things like
466                     // __PAGEZERO don't have any protections, and they shouldn't
467                     // be slid
468                     SectionSP section_sp(section_list->FindSectionByName(info.segments[i].name));
469 
470                     if (info.segments[i].maxprot == 0)
471                     {
472                         inaccessible_segment_indexes.push_back(i);
473                     }
474                     else
475                     {
476                         const addr_t new_section_load_addr = info.segments[i].vmaddr + info.slide;
477                         static ConstString g_section_name_LINKEDIT ("__LINKEDIT");
478 
479                         if (section_sp)
480                         {
481                             // __LINKEDIT sections from files in the shared cache
482                             // can overlap so check to see what the segment name is
483                             // and pass "false" so we don't warn of overlapping
484                             // "Section" objects, and "true" for all other sections.
485                             const bool warn_multiple = section_sp->GetName() != g_section_name_LINKEDIT;
486 
487                             changed = m_process->GetTarget().SetSectionLoadAddress (section_sp, new_section_load_addr, warn_multiple);
488                         }
489                         else
490                         {
491                             Host::SystemLog (Host::eSystemLogWarning,
492                                              "warning: unable to find and load segment named '%s' at 0x%" PRIx64 " in '%s' in macosx dynamic loader plug-in.\n",
493                                              info.segments[i].name.AsCString("<invalid>"),
494                                              (uint64_t)new_section_load_addr,
495                                              image_object_file->GetFileSpec().GetPath().c_str());
496                         }
497                     }
498                 }
499 
500                 // If the loaded the file (it changed) and we have segments that
501                 // are not readable or writeable, add them to the invalid memory
502                 // region cache for the process. This will typically only be
503                 // the __PAGEZERO segment in the main executable. We might be able
504                 // to apply this more generally to more sections that have no
505                 // protections in the future, but for now we are going to just
506                 // do __PAGEZERO.
507                 if (changed && !inaccessible_segment_indexes.empty())
508                 {
509                     for (uint32_t i=0; i<inaccessible_segment_indexes.size(); ++i)
510                     {
511                         const uint32_t seg_idx = inaccessible_segment_indexes[i];
512                         SectionSP section_sp(section_list->FindSectionByName(info.segments[seg_idx].name));
513 
514                         if (section_sp)
515                         {
516                             static ConstString g_pagezero_section_name("__PAGEZERO");
517                             if (g_pagezero_section_name == section_sp->GetName())
518                             {
519                                 // __PAGEZERO never slides...
520                                 const lldb::addr_t vmaddr = info.segments[seg_idx].vmaddr;
521                                 const lldb::addr_t vmsize = info.segments[seg_idx].vmsize;
522                                 Process::LoadRange pagezero_range (vmaddr, vmsize);
523                                 m_process->AddInvalidMemoryRegion(pagezero_range);
524                             }
525                         }
526                     }
527                 }
528             }
529         }
530     }
531     // We might have an in memory image that was loaded as soon as it was created
532     if (info.load_stop_id == m_process->GetStopID())
533         changed = true;
534     else if (changed)
535     {
536         // Update the stop ID when this library was updated
537         info.load_stop_id = m_process->GetStopID();
538     }
539     return changed;
540 }
541 
542 //----------------------------------------------------------------------
543 // Update the load addresses for all segments in MODULE using the
544 // updated INFO that is passed in.
545 //----------------------------------------------------------------------
546 bool
547 DynamicLoaderMacOSXDYLD::UnloadImageLoadAddress (Module *module, DYLDImageInfo& info)
548 {
549     bool changed = false;
550     if (module)
551     {
552         ObjectFile *image_object_file = module->GetObjectFile();
553         if (image_object_file)
554         {
555             SectionList *section_list = image_object_file->GetSectionList ();
556             if (section_list)
557             {
558                 const size_t num_segments = info.segments.size();
559                 for (size_t i=0; i<num_segments; ++i)
560                 {
561                     SectionSP section_sp(section_list->FindSectionByName(info.segments[i].name));
562                     if (section_sp)
563                     {
564                         const addr_t old_section_load_addr = info.segments[i].vmaddr + info.slide;
565                         if (m_process->GetTarget().SetSectionUnloaded (section_sp, old_section_load_addr))
566                             changed = true;
567                     }
568                     else
569                     {
570                         Host::SystemLog (Host::eSystemLogWarning,
571                                          "warning: unable to find and unload segment named '%s' in '%s' in macosx dynamic loader plug-in.\n",
572                                          info.segments[i].name.AsCString("<invalid>"),
573                                          image_object_file->GetFileSpec().GetPath().c_str());
574                     }
575                 }
576             }
577         }
578     }
579     return changed;
580 }
581 
582 
583 //----------------------------------------------------------------------
584 // Static callback function that gets called when our DYLD notification
585 // breakpoint gets hit. We update all of our image infos and then
586 // let our super class DynamicLoader class decide if we should stop
587 // or not (based on global preference).
588 //----------------------------------------------------------------------
589 bool
590 DynamicLoaderMacOSXDYLD::NotifyBreakpointHit (void *baton,
591                                               StoppointCallbackContext *context,
592                                               lldb::user_id_t break_id,
593                                               lldb::user_id_t break_loc_id)
594 {
595     // Let the event know that the images have changed
596     // DYLD passes three arguments to the notification breakpoint.
597     // Arg1: enum dyld_image_mode mode - 0 = adding, 1 = removing
598     // Arg2: uint32_t infoCount        - Number of shared libraries added
599     // Arg3: dyld_image_info info[]    - Array of structs of the form:
600     //                                     const struct mach_header *imageLoadAddress
601     //                                     const char               *imageFilePath
602     //                                     uintptr_t                 imageFileModDate (a time_t)
603 
604     DynamicLoaderMacOSXDYLD* dyld_instance = (DynamicLoaderMacOSXDYLD*) baton;
605 
606     // First step is to see if we've already initialized the all image infos.  If we haven't then this function
607     // will do so and return true.  In the course of initializing the all_image_infos it will read the complete
608     // current state, so we don't need to figure out what has changed from the data passed in to us.
609 
610     if (dyld_instance->InitializeFromAllImageInfos())
611         return dyld_instance->GetStopWhenImagesChange();
612 
613     ExecutionContext exe_ctx (context->exe_ctx_ref);
614     Process *process = exe_ctx.GetProcessPtr();
615     const lldb::ABISP &abi = process->GetABI();
616     if (abi)
617     {
618         // Build up the value array to store the three arguments given above, then get the values from the ABI:
619 
620         ClangASTContext *clang_ast_context = process->GetTarget().GetScratchClangASTContext();
621         ValueList argument_values;
622         Value input_value;
623 
624         ClangASTType clang_void_ptr_type = clang_ast_context->GetBasicType(eBasicTypeVoid).GetPointerType();
625         ClangASTType clang_uint32_type = clang_ast_context->GetBuiltinTypeForEncodingAndBitSize(lldb::eEncodingUint, 32);
626         input_value.SetValueType (Value::eValueTypeScalar);
627         input_value.SetClangType (clang_uint32_type);
628 //        input_value.SetContext (Value::eContextTypeClangType, clang_uint32_type);
629         argument_values.PushValue (input_value);
630         argument_values.PushValue (input_value);
631         input_value.SetClangType (clang_void_ptr_type);
632         //        input_value.SetContext (Value::eContextTypeClangType, clang_void_ptr_type);
633         argument_values.PushValue (input_value);
634 
635         if (abi->GetArgumentValues (exe_ctx.GetThreadRef(), argument_values))
636         {
637             uint32_t dyld_mode = argument_values.GetValueAtIndex(0)->GetScalar().UInt (-1);
638             if (dyld_mode != static_cast<uint32_t>(-1))
639             {
640                 // Okay the mode was right, now get the number of elements, and the array of new elements...
641                 uint32_t image_infos_count = argument_values.GetValueAtIndex(1)->GetScalar().UInt (-1);
642                 if (image_infos_count != static_cast<uint32_t>(-1))
643                 {
644                     // Got the number added, now go through the array of added elements, putting out the mach header
645                     // address, and adding the image.
646                     // Note, I'm not putting in logging here, since the AddModules & RemoveModules functions do
647                     // all the logging internally.
648 
649                     lldb::addr_t image_infos_addr = argument_values.GetValueAtIndex(2)->GetScalar().ULongLong();
650                     if (dyld_mode == 0)
651                     {
652                         // This is add:
653                         dyld_instance->AddModulesUsingImageInfosAddress (image_infos_addr, image_infos_count);
654                     }
655                     else
656                     {
657                         // This is remove:
658                         dyld_instance->RemoveModulesUsingImageInfosAddress (image_infos_addr, image_infos_count);
659                     }
660 
661                 }
662             }
663         }
664     }
665 
666     // Return true to stop the target, false to just let the target run
667     return dyld_instance->GetStopWhenImagesChange();
668 }
669 
670 bool
671 DynamicLoaderMacOSXDYLD::ReadAllImageInfosStructure ()
672 {
673     Mutex::Locker locker(m_mutex);
674 
675     // the all image infos is already valid for this process stop ID
676     if (m_process->GetStopID() == m_dyld_all_image_infos_stop_id)
677         return true;
678 
679     m_dyld_all_image_infos.Clear();
680     if (m_dyld_all_image_infos_addr != LLDB_INVALID_ADDRESS)
681     {
682         ByteOrder byte_order = m_process->GetTarget().GetArchitecture().GetByteOrder();
683         uint32_t addr_size = 4;
684         if (m_dyld_all_image_infos_addr > UINT32_MAX)
685             addr_size = 8;
686 
687         uint8_t buf[256];
688         DataExtractor data (buf, sizeof(buf), byte_order, addr_size);
689         lldb::offset_t offset = 0;
690 
691         const size_t count_v2 =  sizeof (uint32_t) + // version
692                                  sizeof (uint32_t) + // infoArrayCount
693                                  addr_size +         // infoArray
694                                  addr_size +         // notification
695                                  addr_size +         // processDetachedFromSharedRegion + libSystemInitialized + pad
696                                  addr_size;          // dyldImageLoadAddress
697         const size_t count_v11 = count_v2 +
698                                  addr_size +         // jitInfo
699                                  addr_size +         // dyldVersion
700                                  addr_size +         // errorMessage
701                                  addr_size +         // terminationFlags
702                                  addr_size +         // coreSymbolicationShmPage
703                                  addr_size +         // systemOrderFlag
704                                  addr_size +         // uuidArrayCount
705                                  addr_size +         // uuidArray
706                                  addr_size +         // dyldAllImageInfosAddress
707                                  addr_size +         // initialImageCount
708                                  addr_size +         // errorKind
709                                  addr_size +         // errorClientOfDylibPath
710                                  addr_size +         // errorTargetDylibPath
711                                  addr_size;          // errorSymbol
712         const size_t count_v13 = count_v11 +
713                                  addr_size +         // sharedCacheSlide
714                                  sizeof (uuid_t);    // sharedCacheUUID
715         (void) count_v13; // Avoid warnings when assertions are off.
716         assert (sizeof (buf) >= count_v13);
717 
718         Error error;
719         if (m_process->ReadMemory (m_dyld_all_image_infos_addr, buf, 4, error) == 4)
720         {
721             m_dyld_all_image_infos.version = data.GetU32(&offset);
722             // If anything in the high byte is set, we probably got the byte
723             // order incorrect (the process might not have it set correctly
724             // yet due to attaching to a program without a specified file).
725             if (m_dyld_all_image_infos.version & 0xff000000)
726             {
727                 // We have guessed the wrong byte order. Swap it and try
728                 // reading the version again.
729                 if (byte_order == eByteOrderLittle)
730                     byte_order = eByteOrderBig;
731                 else
732                     byte_order = eByteOrderLittle;
733 
734                 data.SetByteOrder (byte_order);
735                 offset = 0;
736                 m_dyld_all_image_infos.version = data.GetU32(&offset);
737             }
738         }
739         else
740         {
741             return false;
742         }
743 
744         const size_t count = (m_dyld_all_image_infos.version >= 11) ? count_v11 : count_v2;
745 
746         const size_t bytes_read = m_process->ReadMemory (m_dyld_all_image_infos_addr, buf, count, error);
747         if (bytes_read == count)
748         {
749             offset = 0;
750             m_dyld_all_image_infos.version = data.GetU32(&offset);
751             m_dyld_all_image_infos.dylib_info_count = data.GetU32(&offset);
752             m_dyld_all_image_infos.dylib_info_addr = data.GetPointer(&offset);
753             m_dyld_all_image_infos.notification = data.GetPointer(&offset);
754             m_dyld_all_image_infos.processDetachedFromSharedRegion = data.GetU8(&offset);
755             m_dyld_all_image_infos.libSystemInitialized = data.GetU8(&offset);
756             // Adjust for padding.
757             offset += addr_size - 2;
758             m_dyld_all_image_infos.dyldImageLoadAddress = data.GetPointer(&offset);
759             if (m_dyld_all_image_infos.version >= 11)
760             {
761                 offset += addr_size * 8;
762                 uint64_t dyld_all_image_infos_addr = data.GetPointer(&offset);
763 
764                 // When we started, we were given the actual address of the all_image_infos
765                 // struct (probably via TASK_DYLD_INFO) in memory - this address is stored in
766                 // m_dyld_all_image_infos_addr and is the most accurate address we have.
767 
768                 // We read the dyld_all_image_infos struct from memory; it contains its own address.
769                 // If the address in the struct does not match the actual address,
770                 // the dyld we're looking at has been loaded at a different location (slid) from
771                 // where it intended to load.  The addresses in the dyld_all_image_infos struct
772                 // are the original, non-slid addresses, and need to be adjusted.  Most importantly
773                 // the address of dyld and the notification address need to be adjusted.
774 
775                 if (dyld_all_image_infos_addr != m_dyld_all_image_infos_addr)
776                 {
777                     uint64_t image_infos_offset = dyld_all_image_infos_addr - m_dyld_all_image_infos.dyldImageLoadAddress;
778                     uint64_t notification_offset = m_dyld_all_image_infos.notification - m_dyld_all_image_infos.dyldImageLoadAddress;
779                     m_dyld_all_image_infos.dyldImageLoadAddress = m_dyld_all_image_infos_addr - image_infos_offset;
780                     m_dyld_all_image_infos.notification = m_dyld_all_image_infos.dyldImageLoadAddress + notification_offset;
781                 }
782             }
783             m_dyld_all_image_infos_stop_id = m_process->GetStopID();
784             return true;
785         }
786     }
787     return false;
788 }
789 
790 
791 bool
792 DynamicLoaderMacOSXDYLD::AddModulesUsingImageInfosAddress (lldb::addr_t image_infos_addr, uint32_t image_infos_count)
793 {
794     DYLDImageInfo::collection image_infos;
795     Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_DYNAMIC_LOADER));
796     if (log)
797         log->Printf ("Adding %d modules.\n", image_infos_count);
798 
799     Mutex::Locker locker(m_mutex);
800     if (m_process->GetStopID() == m_dyld_image_infos_stop_id)
801         return true;
802 
803     if (!ReadImageInfos (image_infos_addr, image_infos_count, image_infos))
804         return false;
805 
806     UpdateImageInfosHeaderAndLoadCommands (image_infos, image_infos_count, false);
807     bool return_value = AddModulesUsingImageInfos (image_infos);
808     m_dyld_image_infos_stop_id = m_process->GetStopID();
809     return return_value;
810 }
811 
812 // Adds the modules in image_infos to m_dyld_image_infos.
813 // NB don't call this passing in m_dyld_image_infos.
814 
815 bool
816 DynamicLoaderMacOSXDYLD::AddModulesUsingImageInfos (DYLDImageInfo::collection &image_infos)
817 {
818     // Now add these images to the main list.
819     ModuleList loaded_module_list;
820     Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_DYNAMIC_LOADER));
821     Target &target = m_process->GetTarget();
822     ModuleList& target_images = target.GetImages();
823 
824     for (uint32_t idx = 0; idx < image_infos.size(); ++idx)
825     {
826         if (log)
827         {
828             log->Printf ("Adding new image at address=0x%16.16" PRIx64 ".", image_infos[idx].address);
829             image_infos[idx].PutToLog (log);
830         }
831 
832         m_dyld_image_infos.push_back(image_infos[idx]);
833 
834         ModuleSP image_module_sp (FindTargetModuleForDYLDImageInfo (image_infos[idx], true, NULL));
835 
836         if (image_module_sp)
837         {
838             ObjectFile *objfile = image_module_sp->GetObjectFile ();
839             if (objfile)
840             {
841                 SectionList *sections = objfile->GetSectionList();
842                 if (sections)
843                 {
844                     ConstString commpage_dbstr("__commpage");
845                     Section *commpage_section = sections->FindSectionByName(commpage_dbstr).get();
846                     if (commpage_section)
847                     {
848                         ModuleSpec module_spec (objfile->GetFileSpec(), image_infos[idx].GetArchitecture ());
849                         module_spec.GetObjectName() = commpage_dbstr;
850                         ModuleSP commpage_image_module_sp(target_images.FindFirstModule (module_spec));
851                         if (!commpage_image_module_sp)
852                         {
853                             module_spec.SetObjectOffset (objfile->GetFileOffset() + commpage_section->GetFileOffset());
854                             commpage_image_module_sp  = target.GetSharedModule (module_spec);
855                             if (!commpage_image_module_sp || commpage_image_module_sp->GetObjectFile() == NULL)
856                             {
857                                 commpage_image_module_sp = m_process->ReadModuleFromMemory (image_infos[idx].file_spec,
858                                                                                             image_infos[idx].address);
859                                 // Always load a memory image right away in the target in case
860                                 // we end up trying to read the symbol table from memory... The
861                                 // __LINKEDIT will need to be mapped so we can figure out where
862                                 // the symbol table bits are...
863                                 bool changed = false;
864                                 UpdateImageLoadAddress (commpage_image_module_sp.get(), image_infos[idx]);
865                                 target.GetImages().Append(commpage_image_module_sp);
866                                 if (changed)
867                                 {
868                                     image_infos[idx].load_stop_id = m_process->GetStopID();
869                                     loaded_module_list.AppendIfNeeded (commpage_image_module_sp);
870                                 }
871                             }
872                         }
873                     }
874                 }
875             }
876 
877             // UpdateImageLoadAddress will return true if any segments
878             // change load address. We need to check this so we don't
879             // mention that all loaded shared libraries are newly loaded
880             // each time we hit out dyld breakpoint since dyld will list all
881             // shared libraries each time.
882             if (UpdateImageLoadAddress (image_module_sp.get(), image_infos[idx]))
883             {
884                 target_images.AppendIfNeeded(image_module_sp);
885                 loaded_module_list.AppendIfNeeded (image_module_sp);
886             }
887         }
888     }
889 
890     if (loaded_module_list.GetSize() > 0)
891     {
892         // FIXME: This should really be in the Runtime handlers class, which should get
893         // called by the target's ModulesDidLoad, but we're doing it all locally for now
894         // to save time.
895         // Also, I'm assuming there can be only one libobjc dylib loaded...
896 
897         ObjCLanguageRuntime *objc_runtime = m_process->GetObjCLanguageRuntime(true);
898         if (objc_runtime != NULL && !objc_runtime->HasReadObjCLibrary())
899         {
900             size_t num_modules = loaded_module_list.GetSize();
901             for (size_t i = 0; i < num_modules; i++)
902             {
903                 if (objc_runtime->IsModuleObjCLibrary (loaded_module_list.GetModuleAtIndex (i)))
904                 {
905                     objc_runtime->ReadObjCLibrary (loaded_module_list.GetModuleAtIndex (i));
906                     break;
907                 }
908             }
909         }
910         if (log)
911             loaded_module_list.LogUUIDAndPaths (log, "DynamicLoaderMacOSXDYLD::ModulesDidLoad");
912         m_process->GetTarget().ModulesDidLoad (loaded_module_list);
913     }
914     return true;
915 }
916 
917 bool
918 DynamicLoaderMacOSXDYLD::RemoveModulesUsingImageInfosAddress (lldb::addr_t image_infos_addr, uint32_t image_infos_count)
919 {
920     DYLDImageInfo::collection image_infos;
921     Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_DYNAMIC_LOADER));
922 
923     Mutex::Locker locker(m_mutex);
924     if (m_process->GetStopID() == m_dyld_image_infos_stop_id)
925         return true;
926 
927     // First read in the image_infos for the removed modules, and their headers & load commands.
928     if (!ReadImageInfos (image_infos_addr, image_infos_count, image_infos))
929     {
930         if (log)
931             log->PutCString ("Failed reading image infos array.");
932         return false;
933     }
934 
935     if (log)
936         log->Printf ("Removing %d modules.", image_infos_count);
937 
938     ModuleList unloaded_module_list;
939     for (uint32_t idx = 0; idx < image_infos.size(); ++idx)
940     {
941         if (log)
942         {
943             log->Printf ("Removing module at address=0x%16.16" PRIx64 ".", image_infos[idx].address);
944             image_infos[idx].PutToLog (log);
945         }
946 
947         // Remove this image_infos from the m_all_image_infos.  We do the comparison by address
948         // rather than by file spec because we can have many modules with the same "file spec" in the
949         // case that they are modules loaded from memory.
950         //
951         // Also copy over the uuid from the old entry to the removed entry so we can
952         // use it to lookup the module in the module list.
953 
954         DYLDImageInfo::collection::iterator pos, end = m_dyld_image_infos.end();
955         for (pos = m_dyld_image_infos.begin(); pos != end; pos++)
956         {
957             if (image_infos[idx].address == (*pos).address)
958             {
959                 image_infos[idx].uuid = (*pos).uuid;
960 
961                 // Add the module from this image_info to the "unloaded_module_list".  We'll remove them all at
962                 // one go later on.
963 
964                 ModuleSP unload_image_module_sp (FindTargetModuleForDYLDImageInfo (image_infos[idx], false, NULL));
965                 if (unload_image_module_sp.get())
966                 {
967                     // When we unload, be sure to use the image info from the old list,
968                     // since that has sections correctly filled in.
969                     UnloadImageLoadAddress (unload_image_module_sp.get(), *pos);
970                     unloaded_module_list.AppendIfNeeded (unload_image_module_sp);
971                 }
972                 else
973                 {
974                     if (log)
975                     {
976                         log->Printf ("Could not find module for unloading info entry:");
977                         image_infos[idx].PutToLog(log);
978                     }
979                 }
980 
981                 // Then remove it from the m_dyld_image_infos:
982 
983                 m_dyld_image_infos.erase(pos);
984                 break;
985             }
986         }
987 
988         if (pos == end)
989         {
990             if (log)
991             {
992                 log->Printf ("Could not find image_info entry for unloading image:");
993                 image_infos[idx].PutToLog(log);
994             }
995         }
996     }
997     if (unloaded_module_list.GetSize() > 0)
998     {
999         if (log)
1000         {
1001             log->PutCString("Unloaded:");
1002             unloaded_module_list.LogUUIDAndPaths (log, "DynamicLoaderMacOSXDYLD::ModulesDidUnload");
1003         }
1004         m_process->GetTarget().GetImages().Remove (unloaded_module_list);
1005     }
1006     m_dyld_image_infos_stop_id = m_process->GetStopID();
1007     return true;
1008 }
1009 
1010 bool
1011 DynamicLoaderMacOSXDYLD::ReadImageInfos (lldb::addr_t image_infos_addr,
1012                                          uint32_t image_infos_count,
1013                                          DYLDImageInfo::collection &image_infos)
1014 {
1015     const ByteOrder endian = m_dyld.GetByteOrder();
1016     const uint32_t addr_size = m_dyld.GetAddressByteSize();
1017 
1018     image_infos.resize(image_infos_count);
1019     const size_t count = image_infos.size() * 3 * addr_size;
1020     DataBufferHeap info_data(count, 0);
1021     Error error;
1022     const size_t bytes_read = m_process->ReadMemory (image_infos_addr,
1023                                                      info_data.GetBytes(),
1024                                                      info_data.GetByteSize(),
1025                                                      error);
1026     if (bytes_read == count)
1027     {
1028         lldb::offset_t info_data_offset = 0;
1029         DataExtractor info_data_ref(info_data.GetBytes(), info_data.GetByteSize(), endian, addr_size);
1030         for (size_t i = 0; i < image_infos.size() && info_data_ref.ValidOffset(info_data_offset); i++)
1031         {
1032             image_infos[i].address = info_data_ref.GetPointer(&info_data_offset);
1033             lldb::addr_t path_addr = info_data_ref.GetPointer(&info_data_offset);
1034             image_infos[i].mod_date = info_data_ref.GetPointer(&info_data_offset);
1035 
1036             char raw_path[PATH_MAX];
1037             m_process->ReadCStringFromMemory (path_addr, raw_path, sizeof(raw_path), error);
1038             // don't resolve the path
1039             if (error.Success())
1040             {
1041                 const bool resolve_path = false;
1042                 image_infos[i].file_spec.SetFile(raw_path, resolve_path);
1043             }
1044         }
1045         return true;
1046     }
1047     else
1048     {
1049         return false;
1050     }
1051 }
1052 
1053 //----------------------------------------------------------------------
1054 // If we have found where the "_dyld_all_image_infos" lives in memory,
1055 // read the current info from it, and then update all image load
1056 // addresses (or lack thereof).  Only do this if this is the first time
1057 // we're reading the dyld infos.  Return true if we actually read anything,
1058 // and false otherwise.
1059 //----------------------------------------------------------------------
1060 bool
1061 DynamicLoaderMacOSXDYLD::InitializeFromAllImageInfos ()
1062 {
1063     Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_DYNAMIC_LOADER));
1064 
1065     Mutex::Locker locker(m_mutex);
1066     if (m_process->GetStopID() == m_dyld_image_infos_stop_id
1067           || m_dyld_image_infos.size() != 0)
1068         return false;
1069 
1070     if (ReadAllImageInfosStructure ())
1071     {
1072         // Nothing to load or unload?
1073         if (m_dyld_all_image_infos.dylib_info_count == 0)
1074             return true;
1075 
1076         if (m_dyld_all_image_infos.dylib_info_addr == 0)
1077         {
1078             // DYLD is updating the images now.  So we should say we have no images, and then we'll
1079             // figure it out when we hit the added breakpoint.
1080             return false;
1081         }
1082         else
1083         {
1084             if (!AddModulesUsingImageInfosAddress (m_dyld_all_image_infos.dylib_info_addr,
1085                                                    m_dyld_all_image_infos.dylib_info_count))
1086             {
1087                 DEBUG_PRINTF("%s", "unable to read all data for all_dylib_infos.");
1088                 m_dyld_image_infos.clear();
1089             }
1090         }
1091 
1092         // Now we have one more bit of business.  If there is a library left in the images for our target that
1093         // doesn't have a load address, then it must be something that we were expecting to load (for instance we
1094         // read a load command for it) but it didn't in fact load - probably because DYLD_*_PATH pointed
1095         // to an equivalent version.  We don't want it to stay in the target's module list or it will confuse
1096         // us, so unload it here.
1097         Target &target = m_process->GetTarget();
1098         const ModuleList &target_modules = target.GetImages();
1099         ModuleList not_loaded_modules;
1100         Mutex::Locker modules_locker(target_modules.GetMutex());
1101 
1102         size_t num_modules = target_modules.GetSize();
1103         for (size_t i = 0; i < num_modules; i++)
1104         {
1105             ModuleSP module_sp = target_modules.GetModuleAtIndexUnlocked (i);
1106             if (!module_sp->IsLoadedInTarget (&target))
1107             {
1108                 if (log)
1109                 {
1110                     StreamString s;
1111                     module_sp->GetDescription (&s);
1112                     log->Printf ("Unloading pre-run module: %s.", s.GetData ());
1113                 }
1114                 not_loaded_modules.Append (module_sp);
1115             }
1116         }
1117 
1118         if (not_loaded_modules.GetSize() != 0)
1119         {
1120             target.GetImages().Remove(not_loaded_modules);
1121         }
1122 
1123         return true;
1124     }
1125     else
1126         return false;
1127 }
1128 
1129 //----------------------------------------------------------------------
1130 // Read a mach_header at ADDR into HEADER, and also fill in the load
1131 // command data into LOAD_COMMAND_DATA if it is non-NULL.
1132 //
1133 // Returns true if we succeed, false if we fail for any reason.
1134 //----------------------------------------------------------------------
1135 bool
1136 DynamicLoaderMacOSXDYLD::ReadMachHeader (lldb::addr_t addr, llvm::MachO::mach_header *header, DataExtractor *load_command_data)
1137 {
1138     DataBufferHeap header_bytes(sizeof(llvm::MachO::mach_header), 0);
1139     Error error;
1140     size_t bytes_read = m_process->ReadMemory (addr,
1141                                                header_bytes.GetBytes(),
1142                                                header_bytes.GetByteSize(),
1143                                                error);
1144     if (bytes_read == sizeof(llvm::MachO::mach_header))
1145     {
1146         lldb::offset_t offset = 0;
1147         ::memset (header, 0, sizeof(llvm::MachO::mach_header));
1148 
1149         // Get the magic byte unswapped so we can figure out what we are dealing with
1150         DataExtractor data(header_bytes.GetBytes(), header_bytes.GetByteSize(), lldb::endian::InlHostByteOrder(), 4);
1151         header->magic = data.GetU32(&offset);
1152         lldb::addr_t load_cmd_addr = addr;
1153         data.SetByteOrder(DynamicLoaderMacOSXDYLD::GetByteOrderFromMagic(header->magic));
1154         switch (header->magic)
1155         {
1156         case llvm::MachO::MH_MAGIC:
1157         case llvm::MachO::MH_CIGAM:
1158             data.SetAddressByteSize(4);
1159             load_cmd_addr += sizeof(llvm::MachO::mach_header);
1160             break;
1161 
1162         case llvm::MachO::MH_MAGIC_64:
1163         case llvm::MachO::MH_CIGAM_64:
1164             data.SetAddressByteSize(8);
1165             load_cmd_addr += sizeof(llvm::MachO::mach_header_64);
1166             break;
1167 
1168         default:
1169             return false;
1170         }
1171 
1172         // Read the rest of dyld's mach header
1173         if (data.GetU32(&offset, &header->cputype, (sizeof(llvm::MachO::mach_header)/sizeof(uint32_t)) - 1))
1174         {
1175             if (load_command_data == NULL)
1176                 return true; // We were able to read the mach_header and weren't asked to read the load command bytes
1177 
1178             DataBufferSP load_cmd_data_sp(new DataBufferHeap(header->sizeofcmds, 0));
1179 
1180             size_t load_cmd_bytes_read = m_process->ReadMemory (load_cmd_addr,
1181                                                                 load_cmd_data_sp->GetBytes(),
1182                                                                 load_cmd_data_sp->GetByteSize(),
1183                                                                 error);
1184 
1185             if (load_cmd_bytes_read == header->sizeofcmds)
1186             {
1187                 // Set the load command data and also set the correct endian
1188                 // swap settings and the correct address size
1189                 load_command_data->SetData(load_cmd_data_sp, 0, header->sizeofcmds);
1190                 load_command_data->SetByteOrder(data.GetByteOrder());
1191                 load_command_data->SetAddressByteSize(data.GetAddressByteSize());
1192                 return true; // We successfully read the mach_header and the load command data
1193             }
1194 
1195             return false; // We weren't able to read the load command data
1196         }
1197     }
1198     return false; // We failed the read the mach_header
1199 }
1200 
1201 
1202 //----------------------------------------------------------------------
1203 // Parse the load commands for an image
1204 //----------------------------------------------------------------------
1205 uint32_t
1206 DynamicLoaderMacOSXDYLD::ParseLoadCommands (const DataExtractor& data, DYLDImageInfo& dylib_info, FileSpec *lc_id_dylinker)
1207 {
1208     lldb::offset_t offset = 0;
1209     uint32_t cmd_idx;
1210     Segment segment;
1211     dylib_info.Clear (true);
1212 
1213     for (cmd_idx = 0; cmd_idx < dylib_info.header.ncmds; cmd_idx++)
1214     {
1215         // Clear out any load command specific data from DYLIB_INFO since
1216         // we are about to read it.
1217 
1218         if (data.ValidOffsetForDataOfSize (offset, sizeof(llvm::MachO::load_command)))
1219         {
1220             llvm::MachO::load_command load_cmd;
1221             lldb::offset_t load_cmd_offset = offset;
1222             load_cmd.cmd = data.GetU32 (&offset);
1223             load_cmd.cmdsize = data.GetU32 (&offset);
1224             switch (load_cmd.cmd)
1225             {
1226             case llvm::MachO::LC_SEGMENT:
1227                 {
1228                     segment.name.SetTrimmedCStringWithLength ((const char *)data.GetData(&offset, 16), 16);
1229                     // We are putting 4 uint32_t values 4 uint64_t values so
1230                     // we have to use multiple 32 bit gets below.
1231                     segment.vmaddr = data.GetU32 (&offset);
1232                     segment.vmsize = data.GetU32 (&offset);
1233                     segment.fileoff = data.GetU32 (&offset);
1234                     segment.filesize = data.GetU32 (&offset);
1235                     // Extract maxprot, initprot, nsects and flags all at once
1236                     data.GetU32(&offset, &segment.maxprot, 4);
1237                     dylib_info.segments.push_back (segment);
1238                 }
1239                 break;
1240 
1241             case llvm::MachO::LC_SEGMENT_64:
1242                 {
1243                     segment.name.SetTrimmedCStringWithLength ((const char *)data.GetData(&offset, 16), 16);
1244                     // Extract vmaddr, vmsize, fileoff, and filesize all at once
1245                     data.GetU64(&offset, &segment.vmaddr, 4);
1246                     // Extract maxprot, initprot, nsects and flags all at once
1247                     data.GetU32(&offset, &segment.maxprot, 4);
1248                     dylib_info.segments.push_back (segment);
1249                 }
1250                 break;
1251 
1252             case llvm::MachO::LC_ID_DYLINKER:
1253                 if (lc_id_dylinker)
1254                 {
1255                     const lldb::offset_t name_offset = load_cmd_offset + data.GetU32 (&offset);
1256                     const char *path = data.PeekCStr (name_offset);
1257                     lc_id_dylinker->SetFile (path, true);
1258                 }
1259                 break;
1260 
1261             case llvm::MachO::LC_UUID:
1262                 dylib_info.uuid.SetBytes(data.GetData (&offset, 16));
1263                 break;
1264 
1265             default:
1266                 break;
1267             }
1268             // Set offset to be the beginning of the next load command.
1269             offset = load_cmd_offset + load_cmd.cmdsize;
1270         }
1271     }
1272 
1273     // All sections listed in the dyld image info structure will all
1274     // either be fixed up already, or they will all be off by a single
1275     // slide amount that is determined by finding the first segment
1276     // that is at file offset zero which also has bytes (a file size
1277     // that is greater than zero) in the object file.
1278 
1279     // Determine the slide amount (if any)
1280     const size_t num_sections = dylib_info.segments.size();
1281     for (size_t i = 0; i < num_sections; ++i)
1282     {
1283         // Iterate through the object file sections to find the
1284         // first section that starts of file offset zero and that
1285         // has bytes in the file...
1286         if (dylib_info.segments[i].fileoff == 0 && dylib_info.segments[i].filesize > 0)
1287         {
1288             dylib_info.slide = dylib_info.address - dylib_info.segments[i].vmaddr;
1289             // We have found the slide amount, so we can exit
1290             // this for loop.
1291             break;
1292         }
1293     }
1294     return cmd_idx;
1295 }
1296 
1297 //----------------------------------------------------------------------
1298 // Read the mach_header and load commands for each image that the
1299 // _dyld_all_image_infos structure points to and cache the results.
1300 //----------------------------------------------------------------------
1301 
1302 void
1303 DynamicLoaderMacOSXDYLD::UpdateImageInfosHeaderAndLoadCommands(DYLDImageInfo::collection &image_infos,
1304                                                                uint32_t infos_count,
1305                                                                bool update_executable)
1306 {
1307     uint32_t exe_idx = UINT32_MAX;
1308     // Read any UUID values that we can get
1309     for (uint32_t i = 0; i < infos_count; i++)
1310     {
1311         if (!image_infos[i].UUIDValid())
1312         {
1313             DataExtractor data; // Load command data
1314             if (!ReadMachHeader (image_infos[i].address, &image_infos[i].header, &data))
1315                 continue;
1316 
1317             ParseLoadCommands (data, image_infos[i], NULL);
1318 
1319             if (image_infos[i].header.filetype == llvm::MachO::MH_EXECUTE)
1320                 exe_idx = i;
1321 
1322         }
1323     }
1324 
1325     Target &target = m_process->GetTarget();
1326 
1327     if (exe_idx < image_infos.size())
1328     {
1329         const bool can_create = true;
1330         ModuleSP exe_module_sp (FindTargetModuleForDYLDImageInfo (image_infos[exe_idx], can_create, NULL));
1331 
1332         if (exe_module_sp)
1333         {
1334             UpdateImageLoadAddress (exe_module_sp.get(), image_infos[exe_idx]);
1335 
1336             if (exe_module_sp.get() != target.GetExecutableModulePointer())
1337             {
1338                 // Don't load dependent images since we are in dyld where we will know
1339                 // and find out about all images that are loaded. Also when setting the
1340                 // executable module, it will clear the targets module list, and if we
1341                 // have an in memory dyld module, it will get removed from the list
1342                 // so we will need to add it back after setting the executable module,
1343                 // so we first try and see if we already have a weak pointer to the
1344                 // dyld module, make it into a shared pointer, then add the executable,
1345                 // then re-add it back to make sure it is always in the list.
1346                 ModuleSP dyld_module_sp(m_dyld_module_wp.lock());
1347 
1348                 const bool get_dependent_images = false;
1349                 m_process->GetTarget().SetExecutableModule (exe_module_sp,
1350                                                             get_dependent_images);
1351 
1352                 if (dyld_module_sp)
1353                 {
1354                    if(target.GetImages().AppendIfNeeded (dyld_module_sp))
1355                    {
1356                         // Also add it to the section list.
1357                         UpdateImageLoadAddress(dyld_module_sp.get(), m_dyld);
1358                    }
1359                 }
1360             }
1361         }
1362     }
1363 }
1364 
1365 //----------------------------------------------------------------------
1366 // On Mac OS X libobjc (the Objective-C runtime) has several critical dispatch
1367 // functions written in hand-written assembly, and also have hand-written unwind
1368 // information in the eh_frame section.  Normally we prefer analyzing the
1369 // assembly instructions of a currently executing frame to unwind from that frame --
1370 // but on hand-written functions this profiling can fail.  We should use the
1371 // eh_frame instructions for these functions all the time.
1372 //
1373 // As an aside, it would be better if the eh_frame entries had a flag (or were
1374 // extensible so they could have an Apple-specific flag) which indicates that
1375 // the instructions are asynchronous -- accurate at every instruction, instead
1376 // of our normal default assumption that they are not.
1377 //----------------------------------------------------------------------
1378 
1379 bool
1380 DynamicLoaderMacOSXDYLD::AlwaysRelyOnEHUnwindInfo (SymbolContext &sym_ctx)
1381 {
1382     ModuleSP module_sp;
1383     if (sym_ctx.symbol)
1384     {
1385         module_sp = sym_ctx.symbol->GetAddress().GetModule();
1386     }
1387     if (module_sp.get() == NULL && sym_ctx.function)
1388     {
1389         module_sp = sym_ctx.function->GetAddressRange().GetBaseAddress().GetModule();
1390     }
1391     if (module_sp.get() == NULL)
1392         return false;
1393 
1394     ObjCLanguageRuntime *objc_runtime = m_process->GetObjCLanguageRuntime();
1395     if (objc_runtime != NULL && objc_runtime->IsModuleObjCLibrary (module_sp))
1396     {
1397         return true;
1398     }
1399 
1400     return false;
1401 }
1402 
1403 
1404 
1405 //----------------------------------------------------------------------
1406 // Dump a Segment to the file handle provided.
1407 //----------------------------------------------------------------------
1408 void
1409 DynamicLoaderMacOSXDYLD::Segment::PutToLog (Log *log, lldb::addr_t slide) const
1410 {
1411     if (log)
1412     {
1413         if (slide == 0)
1414             log->Printf ("\t\t%16s [0x%16.16" PRIx64 " - 0x%16.16" PRIx64 ")",
1415                          name.AsCString(""),
1416                          vmaddr + slide,
1417                          vmaddr + slide + vmsize);
1418         else
1419             log->Printf ("\t\t%16s [0x%16.16" PRIx64 " - 0x%16.16" PRIx64 ") slide = 0x%" PRIx64,
1420                          name.AsCString(""),
1421                          vmaddr + slide,
1422                          vmaddr + slide + vmsize,
1423                          slide);
1424     }
1425 }
1426 
1427 const DynamicLoaderMacOSXDYLD::Segment *
1428 DynamicLoaderMacOSXDYLD::DYLDImageInfo::FindSegment (const ConstString &name) const
1429 {
1430     const size_t num_segments = segments.size();
1431     for (size_t i=0; i<num_segments; ++i)
1432     {
1433         if (segments[i].name == name)
1434             return &segments[i];
1435     }
1436     return NULL;
1437 }
1438 
1439 
1440 //----------------------------------------------------------------------
1441 // Dump an image info structure to the file handle provided.
1442 //----------------------------------------------------------------------
1443 void
1444 DynamicLoaderMacOSXDYLD::DYLDImageInfo::PutToLog (Log *log) const
1445 {
1446     if (log == NULL)
1447         return;
1448     uint8_t *u = (uint8_t *)uuid.GetBytes();
1449 
1450     if (address == LLDB_INVALID_ADDRESS)
1451     {
1452         if (u)
1453         {
1454             log->Printf("\t                           modtime=0x%8.8" PRIx64 " uuid=%2.2X%2.2X%2.2X%2.2X-%2.2X%2.2X-%2.2X%2.2X-%2.2X%2.2X-%2.2X%2.2X%2.2X%2.2X%2.2X%2.2X path='%s' (UNLOADED)",
1455                         mod_date,
1456                         u[ 0], u[ 1], u[ 2], u[ 3],
1457                         u[ 4], u[ 5], u[ 6], u[ 7],
1458                         u[ 8], u[ 9], u[10], u[11],
1459                         u[12], u[13], u[14], u[15],
1460                         file_spec.GetPath().c_str());
1461         }
1462         else
1463             log->Printf("\t                           modtime=0x%8.8" PRIx64 " path='%s' (UNLOADED)",
1464                         mod_date,
1465                         file_spec.GetPath().c_str());
1466     }
1467     else
1468     {
1469         if (u)
1470         {
1471             log->Printf("\taddress=0x%16.16" PRIx64 " modtime=0x%8.8" PRIx64 " uuid=%2.2X%2.2X%2.2X%2.2X-%2.2X%2.2X-%2.2X%2.2X-%2.2X%2.2X-%2.2X%2.2X%2.2X%2.2X%2.2X%2.2X path='%s'",
1472                         address,
1473                         mod_date,
1474                         u[ 0], u[ 1], u[ 2], u[ 3],
1475                         u[ 4], u[ 5], u[ 6], u[ 7],
1476                         u[ 8], u[ 9], u[10], u[11],
1477                         u[12], u[13], u[14], u[15],
1478                         file_spec.GetPath().c_str());
1479         }
1480         else
1481         {
1482             log->Printf("\taddress=0x%16.16" PRIx64 " modtime=0x%8.8" PRIx64 " path='%s'",
1483                         address,
1484                         mod_date,
1485                         file_spec.GetPath().c_str());
1486 
1487         }
1488         for (uint32_t i=0; i<segments.size(); ++i)
1489             segments[i].PutToLog(log, slide);
1490     }
1491 }
1492 
1493 //----------------------------------------------------------------------
1494 // Dump the _dyld_all_image_infos members and all current image infos
1495 // that we have parsed to the file handle provided.
1496 //----------------------------------------------------------------------
1497 void
1498 DynamicLoaderMacOSXDYLD::PutToLog(Log *log) const
1499 {
1500     if (log == NULL)
1501         return;
1502 
1503     Mutex::Locker locker(m_mutex);
1504     log->Printf("dyld_all_image_infos = { version=%d, count=%d, addr=0x%8.8" PRIx64 ", notify=0x%8.8" PRIx64 " }",
1505                     m_dyld_all_image_infos.version,
1506                     m_dyld_all_image_infos.dylib_info_count,
1507                     (uint64_t)m_dyld_all_image_infos.dylib_info_addr,
1508                     (uint64_t)m_dyld_all_image_infos.notification);
1509     size_t i;
1510     const size_t count = m_dyld_image_infos.size();
1511     if (count > 0)
1512     {
1513         log->PutCString("Loaded:");
1514         for (i = 0; i<count; i++)
1515             m_dyld_image_infos[i].PutToLog(log);
1516     }
1517 }
1518 
1519 void
1520 DynamicLoaderMacOSXDYLD::PrivateInitialize(Process *process)
1521 {
1522     DEBUG_PRINTF("DynamicLoaderMacOSXDYLD::%s() process state = %s\n", __FUNCTION__, StateAsCString(m_process->GetState()));
1523     Clear(true);
1524     m_process = process;
1525     m_process->GetTarget().ClearAllLoadedSections();
1526 }
1527 
1528 bool
1529 DynamicLoaderMacOSXDYLD::SetNotificationBreakpoint ()
1530 {
1531     DEBUG_PRINTF("DynamicLoaderMacOSXDYLD::%s() process state = %s\n", __FUNCTION__, StateAsCString(m_process->GetState()));
1532     if (m_break_id == LLDB_INVALID_BREAK_ID)
1533     {
1534         if (m_dyld_all_image_infos.notification != LLDB_INVALID_ADDRESS)
1535         {
1536             Address so_addr;
1537             // Set the notification breakpoint and install a breakpoint
1538             // callback function that will get called each time the
1539             // breakpoint gets hit. We will use this to track when shared
1540             // libraries get loaded/unloaded.
1541             bool resolved = m_process->GetTarget().ResolveLoadAddress(m_dyld_all_image_infos.notification, so_addr);
1542             if (!resolved)
1543             {
1544                 ModuleSP dyld_module_sp = m_dyld_module_wp.lock();
1545                 if (dyld_module_sp)
1546                 {
1547                     UpdateImageLoadAddress (dyld_module_sp.get(), m_dyld);
1548                     resolved = m_process->GetTarget().ResolveLoadAddress(m_dyld_all_image_infos.notification, so_addr);
1549                 }
1550             }
1551 
1552             if (resolved)
1553             {
1554                 Breakpoint *dyld_break = m_process->GetTarget().CreateBreakpoint (so_addr, true, false).get();
1555                 dyld_break->SetCallback (DynamicLoaderMacOSXDYLD::NotifyBreakpointHit, this, true);
1556                 dyld_break->SetBreakpointKind ("shared-library-event");
1557                 m_break_id = dyld_break->GetID();
1558             }
1559         }
1560     }
1561     return m_break_id != LLDB_INVALID_BREAK_ID;
1562 }
1563 
1564 //----------------------------------------------------------------------
1565 // Member function that gets called when the process state changes.
1566 //----------------------------------------------------------------------
1567 void
1568 DynamicLoaderMacOSXDYLD::PrivateProcessStateChanged (Process *process, StateType state)
1569 {
1570     DEBUG_PRINTF("DynamicLoaderMacOSXDYLD::%s(%s)\n", __FUNCTION__, StateAsCString(state));
1571     switch (state)
1572     {
1573     case eStateConnected:
1574     case eStateAttaching:
1575     case eStateLaunching:
1576     case eStateInvalid:
1577     case eStateUnloaded:
1578     case eStateExited:
1579     case eStateDetached:
1580         Clear(false);
1581         break;
1582 
1583     case eStateStopped:
1584         // Keep trying find dyld and set our notification breakpoint each time
1585         // we stop until we succeed
1586         if (!DidSetNotificationBreakpoint () && m_process->IsAlive())
1587         {
1588             if (NeedToLocateDYLD ())
1589                 LocateDYLD ();
1590 
1591             SetNotificationBreakpoint ();
1592         }
1593         break;
1594 
1595     case eStateRunning:
1596     case eStateStepping:
1597     case eStateCrashed:
1598     case eStateSuspended:
1599         break;
1600     }
1601 }
1602 
1603 ThreadPlanSP
1604 DynamicLoaderMacOSXDYLD::GetStepThroughTrampolinePlan (Thread &thread, bool stop_others)
1605 {
1606     ThreadPlanSP thread_plan_sp;
1607     StackFrame *current_frame = thread.GetStackFrameAtIndex(0).get();
1608     const SymbolContext &current_context = current_frame->GetSymbolContext(eSymbolContextSymbol);
1609     Symbol *current_symbol = current_context.symbol;
1610     Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP));
1611     TargetSP target_sp (thread.CalculateTarget());
1612 
1613     if (current_symbol != NULL)
1614     {
1615         std::vector<Address>  addresses;
1616 
1617         if (current_symbol->IsTrampoline())
1618         {
1619             const ConstString &trampoline_name = current_symbol->GetMangled().GetName(Mangled::ePreferMangled);
1620 
1621             if (trampoline_name)
1622             {
1623                 const ModuleList &images = target_sp->GetImages();
1624 
1625                 SymbolContextList code_symbols;
1626                 images.FindSymbolsWithNameAndType(trampoline_name, eSymbolTypeCode, code_symbols);
1627                 size_t num_code_symbols = code_symbols.GetSize();
1628 
1629                 if (num_code_symbols > 0)
1630                 {
1631                     for (uint32_t i = 0; i < num_code_symbols; i++)
1632                     {
1633                         SymbolContext context;
1634                         AddressRange addr_range;
1635                         if (code_symbols.GetContextAtIndex(i, context))
1636                         {
1637                             context.GetAddressRange (eSymbolContextEverything, 0, false, addr_range);
1638                             addresses.push_back(addr_range.GetBaseAddress());
1639                             if (log)
1640                             {
1641                                 addr_t load_addr = addr_range.GetBaseAddress().GetLoadAddress(target_sp.get());
1642 
1643                                 log->Printf ("Found a trampoline target symbol at 0x%" PRIx64 ".", load_addr);
1644                             }
1645                         }
1646                     }
1647                 }
1648 
1649                 SymbolContextList reexported_symbols;
1650                 images.FindSymbolsWithNameAndType(trampoline_name, eSymbolTypeReExported, reexported_symbols);
1651                 size_t num_reexported_symbols = reexported_symbols.GetSize();
1652                 if (num_reexported_symbols > 0)
1653                 {
1654                     for (uint32_t i = 0; i < num_reexported_symbols; i++)
1655                     {
1656                         SymbolContext context;
1657                         if (reexported_symbols.GetContextAtIndex(i, context))
1658                         {
1659                             if (context.symbol)
1660                             {
1661                                 Symbol *actual_symbol = context.symbol->ResolveReExportedSymbol(*target_sp.get());
1662                                 if (actual_symbol)
1663                                 {
1664                                     if (actual_symbol->GetAddress().IsValid())
1665                                     {
1666                                         addresses.push_back(actual_symbol->GetAddress());
1667                                         if (log)
1668                                         {
1669                                             lldb::addr_t load_addr = actual_symbol->GetAddress().GetLoadAddress(target_sp.get());
1670                                             log->Printf ("Found a re-exported symbol: %s at 0x%" PRIx64 ".",
1671                                                          actual_symbol->GetName().GetCString(), load_addr);
1672                                         }
1673                                     }
1674                                 }
1675                             }
1676                         }
1677                     }
1678                 }
1679 
1680                 SymbolContextList indirect_symbols;
1681                 images.FindSymbolsWithNameAndType(trampoline_name, eSymbolTypeResolver, indirect_symbols);
1682                 size_t num_indirect_symbols = indirect_symbols.GetSize();
1683                 if (num_indirect_symbols > 0)
1684                 {
1685                     for (uint32_t i = 0; i < num_indirect_symbols; i++)
1686                     {
1687                         SymbolContext context;
1688                         AddressRange addr_range;
1689                         if (indirect_symbols.GetContextAtIndex(i, context))
1690                         {
1691                             context.GetAddressRange (eSymbolContextEverything, 0, false, addr_range);
1692                             addresses.push_back(addr_range.GetBaseAddress());
1693                             if (log)
1694                             {
1695                                 addr_t load_addr = addr_range.GetBaseAddress().GetLoadAddress(target_sp.get());
1696 
1697                                 log->Printf ("Found an indirect target symbol at 0x%" PRIx64 ".", load_addr);
1698                             }
1699                         }
1700                     }
1701                 }
1702             }
1703         }
1704         else if (current_symbol->GetType() == eSymbolTypeReExported)
1705         {
1706             // I am not sure we could ever end up stopped AT a re-exported symbol.  But just in case:
1707 
1708             const Symbol *actual_symbol = current_symbol->ResolveReExportedSymbol(*(target_sp.get()));
1709             if (actual_symbol)
1710             {
1711                 Address target_addr(actual_symbol->GetAddress());
1712                 if (target_addr.IsValid())
1713                 {
1714                     if (log)
1715                         log->Printf ("Found a re-exported symbol: %s pointing to: %s at 0x%" PRIx64 ".",
1716                                      current_symbol->GetName().GetCString(),
1717                                      actual_symbol->GetName().GetCString(),
1718                                      target_addr.GetLoadAddress(target_sp.get()));
1719                     addresses.push_back (target_addr.GetLoadAddress(target_sp.get()));
1720 
1721                 }
1722             }
1723         }
1724 
1725         if (addresses.size() > 0)
1726         {
1727             // First check whether any of the addresses point to Indirect symbols, and if they do, resolve them:
1728             std::vector<lldb::addr_t> load_addrs;
1729             for (Address address : addresses)
1730             {
1731                 Symbol *symbol = address.CalculateSymbolContextSymbol();
1732                 if (symbol && symbol->IsIndirect())
1733                 {
1734                     Error error;
1735                     addr_t resolved_addr = thread.GetProcess()->ResolveIndirectFunction(&symbol->GetAddress(), error);
1736                     if (error.Success())
1737                     {
1738                         load_addrs.push_back(resolved_addr);
1739                         if (log)
1740                             log->Printf("ResolveIndirectFunction found resolved target for %s at 0x%" PRIx64 ".",
1741                                         symbol->GetName().GetCString(), resolved_addr);
1742                     }
1743                 }
1744                 else
1745                 {
1746                     load_addrs.push_back(address.GetLoadAddress(target_sp.get()));
1747                 }
1748 
1749             }
1750             thread_plan_sp.reset (new ThreadPlanRunToAddress (thread, load_addrs, stop_others));
1751         }
1752     }
1753     else
1754     {
1755         if (log)
1756             log->Printf ("Could not find symbol for step through.");
1757     }
1758 
1759     return thread_plan_sp;
1760 }
1761 
1762 size_t
1763 DynamicLoaderMacOSXDYLD::FindEquivalentSymbols (lldb_private::Symbol *original_symbol,
1764                                                lldb_private::ModuleList &images,
1765                                                lldb_private::SymbolContextList &equivalent_symbols)
1766 {
1767     const ConstString &trampoline_name = original_symbol->GetMangled().GetName(Mangled::ePreferMangled);
1768     if (!trampoline_name)
1769         return 0;
1770 
1771     size_t initial_size = equivalent_symbols.GetSize();
1772 
1773     static const char *resolver_name_regex = "(_gc|_non_gc|\\$[A-Za-z0-9\\$]+)$";
1774     std::string equivalent_regex_buf("^");
1775     equivalent_regex_buf.append (trampoline_name.GetCString());
1776     equivalent_regex_buf.append (resolver_name_regex);
1777 
1778     RegularExpression equivalent_name_regex (equivalent_regex_buf.c_str());
1779     const bool append = true;
1780     images.FindSymbolsMatchingRegExAndType (equivalent_name_regex, eSymbolTypeCode, equivalent_symbols, append);
1781 
1782     return equivalent_symbols.GetSize() - initial_size;
1783 }
1784 
1785 Error
1786 DynamicLoaderMacOSXDYLD::CanLoadImage ()
1787 {
1788     Error error;
1789     // In order for us to tell if we can load a shared library we verify that
1790     // the dylib_info_addr isn't zero (which means no shared libraries have
1791     // been set yet, or dyld is currently mucking with the shared library list).
1792     if (ReadAllImageInfosStructure ())
1793     {
1794         // TODO: also check the _dyld_global_lock_held variable in libSystem.B.dylib?
1795         // TODO: check the malloc lock?
1796         // TODO: check the objective C lock?
1797         if (m_dyld_all_image_infos.dylib_info_addr != 0)
1798             return error; // Success
1799     }
1800 
1801     error.SetErrorString("unsafe to load or unload shared libraries");
1802     return error;
1803 }
1804 
1805 void
1806 DynamicLoaderMacOSXDYLD::Initialize()
1807 {
1808     PluginManager::RegisterPlugin (GetPluginNameStatic(),
1809                                    GetPluginDescriptionStatic(),
1810                                    CreateInstance);
1811 }
1812 
1813 void
1814 DynamicLoaderMacOSXDYLD::Terminate()
1815 {
1816     PluginManager::UnregisterPlugin (CreateInstance);
1817 }
1818 
1819 
1820 lldb_private::ConstString
1821 DynamicLoaderMacOSXDYLD::GetPluginNameStatic()
1822 {
1823     static ConstString g_name("macosx-dyld");
1824     return g_name;
1825 }
1826 
1827 const char *
1828 DynamicLoaderMacOSXDYLD::GetPluginDescriptionStatic()
1829 {
1830     return "Dynamic loader plug-in that watches for shared library loads/unloads in MacOSX user processes.";
1831 }
1832 
1833 
1834 //------------------------------------------------------------------
1835 // PluginInterface protocol
1836 //------------------------------------------------------------------
1837 lldb_private::ConstString
1838 DynamicLoaderMacOSXDYLD::GetPluginName()
1839 {
1840     return GetPluginNameStatic();
1841 }
1842 
1843 uint32_t
1844 DynamicLoaderMacOSXDYLD::GetPluginVersion()
1845 {
1846     return 1;
1847 }
1848 
1849 uint32_t
1850 DynamicLoaderMacOSXDYLD::AddrByteSize()
1851 {
1852     switch (m_dyld.header.magic)
1853     {
1854         case llvm::MachO::MH_MAGIC:
1855         case llvm::MachO::MH_CIGAM:
1856             return 4;
1857 
1858         case llvm::MachO::MH_MAGIC_64:
1859         case llvm::MachO::MH_CIGAM_64:
1860             return 8;
1861 
1862         default:
1863             break;
1864     }
1865     return 0;
1866 }
1867 
1868 lldb::ByteOrder
1869 DynamicLoaderMacOSXDYLD::GetByteOrderFromMagic (uint32_t magic)
1870 {
1871     switch (magic)
1872     {
1873         case llvm::MachO::MH_MAGIC:
1874         case llvm::MachO::MH_MAGIC_64:
1875             return lldb::endian::InlHostByteOrder();
1876 
1877         case llvm::MachO::MH_CIGAM:
1878         case llvm::MachO::MH_CIGAM_64:
1879             if (lldb::endian::InlHostByteOrder() == lldb::eByteOrderBig)
1880                 return lldb::eByteOrderLittle;
1881             else
1882                 return lldb::eByteOrderBig;
1883 
1884         default:
1885             break;
1886     }
1887     return lldb::eByteOrderInvalid;
1888 }
1889 
1890 lldb::ByteOrder
1891 DynamicLoaderMacOSXDYLD::DYLDImageInfo::GetByteOrder()
1892 {
1893     return DynamicLoaderMacOSXDYLD::GetByteOrderFromMagic(header.magic);
1894 }
1895 
1896