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