1 //===-- DynamicLoaderMacOSXDYLD.cpp -----------------------------*- C++ -*-===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 
10 #include "lldb/Breakpoint/StoppointCallbackContext.h"
11 #include "lldb/Core/DataBuffer.h"
12 #include "lldb/Core/DataBufferHeap.h"
13 #include "lldb/Core/Log.h"
14 #include "lldb/Core/Module.h"
15 #include "lldb/Core/PluginManager.h"
16 #include "lldb/Core/State.h"
17 #include "lldb/Symbol/ObjectFile.h"
18 #include "lldb/Target/ObjCLanguageRuntime.h"
19 #include "lldb/Target/RegisterContext.h"
20 #include "lldb/Target/Target.h"
21 #include "lldb/Target/Thread.h"
22 #include "lldb/Target/ThreadPlanRunToAddress.h"
23 #include "lldb/Target/StackFrame.h"
24 
25 #include "DynamicLoaderMacOSXDYLD.h"
26 
27 //#define ENABLE_DEBUG_PRINTF // COMMENT THIS LINE OUT PRIOR TO CHECKIN
28 #ifdef ENABLE_DEBUG_PRINTF
29 #include <stdio.h>
30 #define DEBUG_PRINTF(fmt, ...) printf(fmt, ## __VA_ARGS__)
31 #else
32 #define DEBUG_PRINTF(fmt, ...)
33 #endif
34 
35 using namespace lldb;
36 using namespace lldb_private;
37 
38 /// FIXME - The ObjC Runtime trampoline handler doesn't really belong here.
39 /// I am putting it here so I can invoke it in the Trampoline code here, but
40 /// it should be moved to the ObjC Runtime support when it is set up.
41 
42 
43 DynamicLoaderMacOSXDYLD::DYLDImageInfo *
44 DynamicLoaderMacOSXDYLD::GetImageInfo (Module *module)
45 {
46     const UUID &module_uuid = module->GetUUID();
47     DYLDImageInfo::collection::iterator pos, end = m_dyld_image_infos.end();
48 
49     // First try just by UUID as it is the safest.
50     if (module_uuid.IsValid())
51     {
52         for (pos = m_dyld_image_infos.begin(); pos != end; ++pos)
53         {
54             if (pos->uuid == module_uuid)
55                 return &(*pos);
56         }
57 
58         if (m_dyld.uuid == module_uuid)
59             return &m_dyld;
60     }
61 
62     // Next try by platform path only for things that don't have a valid UUID
63     // since if a file has a valid UUID in real life it should also in the
64     // dyld info. This is the next safest because the paths in the dyld info
65     // are platform paths, not local paths. For local debugging platform == local
66     // paths.
67     const FileSpec &platform_file_spec = module->GetPlatformFileSpec();
68     for (pos = m_dyld_image_infos.begin(); pos != end; ++pos)
69     {
70         if (pos->file_spec == platform_file_spec && pos->uuid.IsValid() == false)
71             return &(*pos);
72     }
73 
74     if (m_dyld.file_spec == platform_file_spec && m_dyld.uuid.IsValid() == false)
75         return &m_dyld;
76 
77     return NULL;
78 }
79 
80 //----------------------------------------------------------------------
81 // Create an instance of this class. This function is filled into
82 // the plugin info class that gets handed out by the plugin factory and
83 // allows the lldb to instantiate an instance of this class.
84 //----------------------------------------------------------------------
85 DynamicLoader *
86 DynamicLoaderMacOSXDYLD::CreateInstance (Process* process, bool force)
87 {
88     bool create = force;
89     if (!create)
90     {
91         const llvm::Triple &triple_ref = process->GetTarget().GetArchitecture().GetTriple();
92         if (triple_ref.getOS() == llvm::Triple::Darwin && triple_ref.getVendor() == llvm::Triple::Apple)
93             create = true;
94     }
95 
96     if (create)
97         return new DynamicLoaderMacOSXDYLD (process);
98     return NULL;
99 }
100 
101 //----------------------------------------------------------------------
102 // Constructor
103 //----------------------------------------------------------------------
104 DynamicLoaderMacOSXDYLD::DynamicLoaderMacOSXDYLD (Process* process) :
105     DynamicLoader(process),
106     m_dyld(),
107     m_dyld_all_image_infos_addr(LLDB_INVALID_ADDRESS),
108     m_dyld_all_image_infos(),
109     m_dyld_all_image_infos_stop_id (UINT32_MAX),
110     m_break_id(LLDB_INVALID_BREAK_ID),
111     m_dyld_image_infos(),
112     m_dyld_image_infos_stop_id (UINT32_MAX),
113     m_mutex(Mutex::eMutexTypeRecursive)
114 {
115 }
116 
117 //----------------------------------------------------------------------
118 // Destructor
119 //----------------------------------------------------------------------
120 DynamicLoaderMacOSXDYLD::~DynamicLoaderMacOSXDYLD()
121 {
122     Clear(true);
123 }
124 
125 //------------------------------------------------------------------
126 /// Called after attaching a process.
127 ///
128 /// Allow DynamicLoader plug-ins to execute some code after
129 /// attaching to a process.
130 //------------------------------------------------------------------
131 void
132 DynamicLoaderMacOSXDYLD::DidAttach ()
133 {
134     PrivateInitialize(m_process);
135     LocateDYLD ();
136     SetNotificationBreakpoint ();
137 }
138 
139 //------------------------------------------------------------------
140 /// Called after attaching a process.
141 ///
142 /// Allow DynamicLoader plug-ins to execute some code after
143 /// attaching to a process.
144 //------------------------------------------------------------------
145 void
146 DynamicLoaderMacOSXDYLD::DidLaunch ()
147 {
148     PrivateInitialize(m_process);
149     LocateDYLD ();
150     SetNotificationBreakpoint ();
151 }
152 
153 
154 //----------------------------------------------------------------------
155 // Clear out the state of this class.
156 //----------------------------------------------------------------------
157 void
158 DynamicLoaderMacOSXDYLD::Clear (bool clear_process)
159 {
160     Mutex::Locker locker(m_mutex);
161 
162     if (m_process->IsAlive() && LLDB_BREAK_ID_IS_VALID(m_break_id))
163         m_process->ClearBreakpointSiteByID(m_break_id);
164 
165     if (clear_process)
166         m_process = NULL;
167     m_dyld.Clear(false);
168     m_dyld_all_image_infos_addr = LLDB_INVALID_ADDRESS;
169     m_dyld_all_image_infos.Clear();
170     m_break_id = LLDB_INVALID_BREAK_ID;
171     m_dyld_image_infos.clear();
172 }
173 
174 //----------------------------------------------------------------------
175 // Check if we have found DYLD yet
176 //----------------------------------------------------------------------
177 bool
178 DynamicLoaderMacOSXDYLD::DidSetNotificationBreakpoint() const
179 {
180     return LLDB_BREAK_ID_IS_VALID (m_break_id);
181 }
182 
183 //----------------------------------------------------------------------
184 // Try and figure out where dyld is by first asking the Process
185 // if it knows (which currently calls down in the the lldb::Process
186 // to get the DYLD info (available on SnowLeopard only). If that fails,
187 // then check in the default addresses.
188 //----------------------------------------------------------------------
189 bool
190 DynamicLoaderMacOSXDYLD::LocateDYLD()
191 {
192     if (m_dyld_all_image_infos_addr == LLDB_INVALID_ADDRESS)
193         m_dyld_all_image_infos_addr = m_process->GetImageInfoAddress ();
194 
195     if (m_dyld_all_image_infos_addr != LLDB_INVALID_ADDRESS)
196     {
197         if (ReadAllImageInfosStructure ())
198         {
199             if (m_dyld_all_image_infos.dyldImageLoadAddress != LLDB_INVALID_ADDRESS)
200                 return ReadDYLDInfoFromMemoryAndSetNotificationCallback (m_dyld_all_image_infos.dyldImageLoadAddress);
201             else
202                 return ReadDYLDInfoFromMemoryAndSetNotificationCallback (m_dyld_all_image_infos_addr & 0xfffffffffff00000ull);
203         }
204     }
205 
206     // Check some default values
207     Module *executable = m_process->GetTarget().GetExecutableModule().get();
208 
209     if (executable)
210     {
211         if (executable->GetArchitecture().GetAddressByteSize() == 8)
212         {
213             return ReadDYLDInfoFromMemoryAndSetNotificationCallback(0x7fff5fc00000ull);
214         }
215 #if defined (__arm__)
216         else
217         {
218             ArchSpec arm_arch("arm");
219             if (arm_arch == executable->Arch())
220                 return ReadDYLDInfoFromMemoryAndSetNotificationCallback(0x2fe00000);
221         }
222 #endif
223         return ReadDYLDInfoFromMemoryAndSetNotificationCallback(0x8fe00000);
224     }
225     return false;
226 }
227 
228 ModuleSP
229 DynamicLoaderMacOSXDYLD::FindTargetModuleForDYLDImageInfo (const DYLDImageInfo &image_info, bool can_create, bool *did_create_ptr)
230 {
231     if (did_create_ptr)
232         *did_create_ptr = false;
233     ModuleSP module_sp;
234     ModuleList &target_images = m_process->GetTarget().GetImages();
235     const bool image_info_uuid_is_valid = image_info.uuid.IsValid();
236     if (image_info_uuid_is_valid)
237         module_sp = target_images.FindModule(image_info.uuid);
238 
239     if (!module_sp)
240     {
241         ArchSpec arch(image_info.GetArchitecture ());
242 
243         module_sp = target_images.FindFirstModuleForFileSpec (image_info.file_spec, &arch, NULL);
244 
245         if (can_create && !module_sp)
246         {
247             module_sp = m_process->GetTarget().GetSharedModule (image_info.file_spec,
248                                                                 arch,
249                                                                 image_info_uuid_is_valid ? &image_info.uuid : NULL);
250             if (did_create_ptr)
251                 *did_create_ptr = module_sp;
252         }
253     }
254     return module_sp;
255 }
256 
257 //----------------------------------------------------------------------
258 // Assume that dyld is in memory at ADDR and try to parse it's load
259 // commands
260 //----------------------------------------------------------------------
261 bool
262 DynamicLoaderMacOSXDYLD::ReadDYLDInfoFromMemoryAndSetNotificationCallback(lldb::addr_t addr)
263 {
264     DataExtractor data; // Load command data
265     if (ReadMachHeader (addr, &m_dyld.header, &data))
266     {
267         if (m_dyld.header.filetype == llvm::MachO::HeaderFileTypeDynamicLinkEditor)
268         {
269             m_dyld.address = addr;
270             ModuleSP dyld_module_sp;
271             if (ParseLoadCommands (data, m_dyld, &m_dyld.file_spec))
272             {
273                 if (m_dyld.file_spec)
274                 {
275                     dyld_module_sp = FindTargetModuleForDYLDImageInfo (m_dyld, true, NULL);
276 
277                     if (dyld_module_sp)
278                         UpdateImageLoadAddress (dyld_module_sp.get(), m_dyld);
279                 }
280             }
281 
282             if (m_dyld_all_image_infos_addr == LLDB_INVALID_ADDRESS && dyld_module_sp.get())
283             {
284                 static ConstString g_dyld_all_image_infos ("dyld_all_image_infos");
285                 const Symbol *symbol = dyld_module_sp->FindFirstSymbolWithNameAndType (g_dyld_all_image_infos, eSymbolTypeData);
286                 if (symbol)
287                     m_dyld_all_image_infos_addr = symbol->GetValue().GetLoadAddress(&m_process->GetTarget());
288             }
289 
290             // Update all image infos
291             UpdateAllImageInfos();
292 
293             // If we didn't have an executable before, but now we do, then the
294             // dyld module shared pointer might be unique and we may need to add
295             // it again (since Target::SetExecutableModule() will clear the
296             // images). So append the dyld module back to the list if it is
297             /// unique!
298             if (dyld_module_sp && m_process->GetTarget().GetImages().AppendIfNeeded (dyld_module_sp))
299                 UpdateImageLoadAddress(dyld_module_sp.get(), m_dyld);
300 
301             return true;
302         }
303     }
304     return false;
305 }
306 
307 bool
308 DynamicLoaderMacOSXDYLD::NeedToLocateDYLD () const
309 {
310     return m_dyld_all_image_infos_addr == LLDB_INVALID_ADDRESS;
311 }
312 
313 bool
314 DynamicLoaderMacOSXDYLD::UpdateCommPageLoadAddress(Module *module)
315 {
316     bool changed = false;
317     if (module)
318     {
319         ObjectFile *image_object_file = module->GetObjectFile();
320         if (image_object_file)
321         {
322             SectionList *section_list = image_object_file->GetSectionList ();
323             if (section_list)
324             {
325                 uint32_t num_sections = section_list->GetSize();
326                 for (uint32_t i=0; i<num_sections; ++i)
327                 {
328                     Section* section = section_list->GetSectionAtIndex (i).get();
329                     if (section)
330                     {
331                         const addr_t new_section_load_addr = section->GetFileAddress ();
332                         const addr_t old_section_load_addr = m_process->GetTarget().GetSectionLoadList().GetSectionLoadAddress (section);
333                         if (old_section_load_addr == LLDB_INVALID_ADDRESS ||
334                             old_section_load_addr != new_section_load_addr)
335                         {
336                             if (m_process->GetTarget().GetSectionLoadList().SetSectionLoadAddress (section, section->GetFileAddress ()))
337                                 changed = true;
338                         }
339                     }
340                 }
341             }
342         }
343     }
344     return changed;
345 }
346 
347 //----------------------------------------------------------------------
348 // Update the load addresses for all segments in MODULE using the
349 // updated INFO that is passed in.
350 //----------------------------------------------------------------------
351 bool
352 DynamicLoaderMacOSXDYLD::UpdateImageLoadAddress (Module *module, DYLDImageInfo& info)
353 {
354     bool changed = false;
355     if (module)
356     {
357         ObjectFile *image_object_file = module->GetObjectFile();
358         if (image_object_file)
359         {
360             SectionList *section_list = image_object_file->GetSectionList ();
361             if (section_list)
362             {
363                 // We now know the slide amount, so go through all sections
364                 // and update the load addresses with the correct values.
365                 uint32_t num_segments = info.segments.size();
366                 for (uint32_t i=0; i<num_segments; ++i)
367                 {
368                     SectionSP section_sp(section_list->FindSectionByName(info.segments[i].name));
369                     assert (section_sp.get() != NULL);
370                     const addr_t new_section_load_addr = info.segments[i].vmaddr + info.slide;
371                     const addr_t old_section_load_addr = m_process->GetTarget().GetSectionLoadList().GetSectionLoadAddress (section_sp.get());
372                     if (old_section_load_addr == LLDB_INVALID_ADDRESS ||
373                         old_section_load_addr != new_section_load_addr)
374                     {
375                         if (m_process->GetTarget().GetSectionLoadList().SetSectionLoadAddress (section_sp.get(), new_section_load_addr))
376                             changed = true;
377                     }
378                 }
379             }
380         }
381     }
382     return changed;
383 }
384 
385 //----------------------------------------------------------------------
386 // Update the load addresses for all segments in MODULE using the
387 // updated INFO that is passed in.
388 //----------------------------------------------------------------------
389 bool
390 DynamicLoaderMacOSXDYLD::UnloadImageLoadAddress (Module *module, DYLDImageInfo& info)
391 {
392     bool changed = false;
393     if (module)
394     {
395         ObjectFile *image_object_file = module->GetObjectFile();
396         if (image_object_file)
397         {
398             SectionList *section_list = image_object_file->GetSectionList ();
399             if (section_list)
400             {
401                 uint32_t num_segments = info.segments.size();
402                 for (uint32_t i=0; i<num_segments; ++i)
403                 {
404                     SectionSP section_sp(section_list->FindSectionByName(info.segments[i].name));
405                     assert (section_sp.get() != NULL);
406                     const addr_t old_section_load_addr = info.segments[i].vmaddr + info.slide;
407                     if (m_process->GetTarget().GetSectionLoadList().SetSectionUnloaded (section_sp.get(), old_section_load_addr))
408                         changed = true;
409                 }
410             }
411         }
412     }
413     return changed;
414 }
415 
416 
417 //----------------------------------------------------------------------
418 // Static callback function that gets called when our DYLD notification
419 // breakpoint gets hit. We update all of our image infos and then
420 // let our super class DynamicLoader class decide if we should stop
421 // or not (based on global preference).
422 //----------------------------------------------------------------------
423 bool
424 DynamicLoaderMacOSXDYLD::NotifyBreakpointHit (void *baton, StoppointCallbackContext *context, lldb::user_id_t break_id, lldb::user_id_t break_loc_id)
425 {
426     // Let the event know that the images have changed
427     DynamicLoaderMacOSXDYLD* dyld_instance = (DynamicLoaderMacOSXDYLD*) baton;
428     dyld_instance->UpdateAllImageInfos();
429     // Return true to stop the target, false to just let the target run
430     return dyld_instance->GetStopWhenImagesChange();
431 }
432 
433 bool
434 DynamicLoaderMacOSXDYLD::ReadAllImageInfosStructure ()
435 {
436     Mutex::Locker locker(m_mutex);
437 
438     // the all image infos is already valid for this process stop ID
439     if (m_process->GetStopID() == m_dyld_all_image_infos_stop_id)
440         return true;
441 
442     m_dyld_all_image_infos.Clear();
443     if (m_dyld_all_image_infos_addr != LLDB_INVALID_ADDRESS)
444     {
445         ByteOrder byte_order = m_process->GetTarget().GetArchitecture().GetByteOrder();
446         uint32_t addr_size = 4;
447         if (m_dyld_all_image_infos_addr > UINT32_MAX)
448             addr_size = 8;
449 
450         uint8_t buf[256];
451         DataExtractor data (buf, sizeof(buf), byte_order, addr_size);
452         uint32_t offset = 0;
453 
454         const size_t count_v2 =  sizeof (uint32_t) + // version
455                                  sizeof (uint32_t) + // infoArrayCount
456                                  addr_size +         // infoArray
457                                  addr_size +         // notification
458                                  addr_size +         // processDetachedFromSharedRegion + libSystemInitialized + pad
459                                  addr_size;          // dyldImageLoadAddress
460         const size_t count_v11 = count_v2 +
461                                  addr_size +         // jitInfo
462                                  addr_size +         // dyldVersion
463                                  addr_size +         // errorMessage
464                                  addr_size +         // terminationFlags
465                                  addr_size +         // coreSymbolicationShmPage
466                                  addr_size +         // systemOrderFlag
467                                  addr_size +         // uuidArrayCount
468                                  addr_size +         // uuidArray
469                                  addr_size +         // dyldAllImageInfosAddress
470                                  addr_size +         // initialImageCount
471                                  addr_size +         // errorKind
472                                  addr_size +         // errorClientOfDylibPath
473                                  addr_size +         // errorTargetDylibPath
474                                  addr_size;          // errorSymbol
475         assert (sizeof (buf) > count_v11);
476 
477         int count;
478         Error error;
479         if (m_process->ReadMemory (m_dyld_all_image_infos_addr, buf, 4, error) == 4)
480         {
481             m_dyld_all_image_infos.version = data.GetU32(&offset);
482             // If anything in the high byte is set, we probably got the byte
483             // order incorrect (the process might not have it set correctly
484             // yet due to attaching to a program without a specified file).
485             if (m_dyld_all_image_infos.version & 0xff000000)
486             {
487                 // We have guessed the wrong byte order. Swap it and try
488                 // reading the version again.
489                 if (byte_order == eByteOrderLittle)
490                     byte_order = eByteOrderBig;
491                 else
492                     byte_order = eByteOrderLittle;
493 
494                 data.SetByteOrder (byte_order);
495                 offset = 0;
496                 m_dyld_all_image_infos.version = data.GetU32(&offset);
497             }
498         }
499         else
500         {
501             return false;
502         }
503 
504         if (m_dyld_all_image_infos.version >= 11)
505             count = count_v11;
506         else
507             count = count_v2;
508 
509         const size_t bytes_read = m_process->ReadMemory (m_dyld_all_image_infos_addr, buf, count, error);
510         if (bytes_read == count)
511         {
512             offset = 0;
513             m_dyld_all_image_infos.version = data.GetU32(&offset);
514             m_dyld_all_image_infos.dylib_info_count = data.GetU32(&offset);
515             m_dyld_all_image_infos.dylib_info_addr = data.GetPointer(&offset);
516             m_dyld_all_image_infos.notification = data.GetPointer(&offset);
517             m_dyld_all_image_infos.processDetachedFromSharedRegion = data.GetU8(&offset);
518             m_dyld_all_image_infos.libSystemInitialized = data.GetU8(&offset);
519             // Adjust for padding.
520             offset += addr_size - 2;
521             m_dyld_all_image_infos.dyldImageLoadAddress = data.GetPointer(&offset);
522             if (m_dyld_all_image_infos.version >= 11)
523             {
524                 offset += addr_size * 8;
525                 uint64_t dyld_all_image_infos_addr = data.GetPointer(&offset);
526 
527                 // When we started, we were given the actual address of the all_image_infos
528                 // struct (probably via TASK_DYLD_INFO) in memory - this address is stored in
529                 // m_dyld_all_image_infos_addr and is the most accurate address we have.
530 
531                 // We read the dyld_all_image_infos struct from memory; it contains its own address.
532                 // If the address in the struct does not match the actual address,
533                 // the dyld we're looking at has been loaded at a different location (slid) from
534                 // where it intended to load.  The addresses in the dyld_all_image_infos struct
535                 // are the original, non-slid addresses, and need to be adjusted.  Most importantly
536                 // the address of dyld and the notification address need to be adjusted.
537 
538                 if (dyld_all_image_infos_addr != m_dyld_all_image_infos_addr)
539                 {
540                     uint64_t image_infos_offset = dyld_all_image_infos_addr - m_dyld_all_image_infos.dyldImageLoadAddress;
541                     uint64_t notification_offset = m_dyld_all_image_infos.notification - m_dyld_all_image_infos.dyldImageLoadAddress;
542                     m_dyld_all_image_infos.dyldImageLoadAddress = m_dyld_all_image_infos_addr - image_infos_offset;
543                     m_dyld_all_image_infos.notification = m_dyld_all_image_infos.dyldImageLoadAddress + notification_offset;
544                 }
545             }
546             m_dyld_all_image_infos_stop_id = m_process->GetStopID();
547             return true;
548         }
549     }
550     return false;
551 }
552 
553 //----------------------------------------------------------------------
554 // If we have found where the "_dyld_all_image_infos" lives in memory,
555 // read the current info from it, and then update all image load
556 // addresses (or lack thereof).
557 //----------------------------------------------------------------------
558 uint32_t
559 DynamicLoaderMacOSXDYLD::UpdateAllImageInfos()
560 {
561     LogSP log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_DYNAMIC_LOADER));
562     ModuleList& target_images = m_process->GetTarget().GetImages();
563 
564     if (ReadAllImageInfosStructure ())
565     {
566         Mutex::Locker locker(m_mutex);
567         if (m_process->GetStopID() == m_dyld_image_infos_stop_id)
568             m_dyld_image_infos.size();
569 
570         uint32_t idx;
571         uint32_t i = 0;
572         // Since we can't downsize a vector, we must do this using the swap method
573         DYLDImageInfo::collection old_dyld_all_image_infos;
574         old_dyld_all_image_infos.swap(m_dyld_image_infos);
575 
576         // If we made it here, we are assuming that the all dylib info data should
577         // be valid, lets read the info array.
578         const ByteOrder endian = m_dyld.GetByteOrder();
579         const uint32_t addr_size = m_dyld.GetAddressByteSize();
580 
581         if (m_dyld_all_image_infos.dylib_info_count > 0)
582         {
583             if (m_dyld_all_image_infos.dylib_info_addr == 0)
584             {
585                 // DYLD is updating the images right now...
586             }
587             else
588             {
589                 m_dyld_image_infos.resize(m_dyld_all_image_infos.dylib_info_count);
590                 const size_t count = m_dyld_image_infos.size() * 3 * addr_size;
591                 DataBufferHeap info_data(count, 0);
592                 Error error;
593                 const size_t bytes_read = m_process->ReadMemory (m_dyld_all_image_infos.dylib_info_addr,
594                                                                  info_data.GetBytes(),
595                                                                  info_data.GetByteSize(),
596                                                                  error);
597                 if (bytes_read == count)
598                 {
599                     uint32_t info_data_offset = 0;
600                     DataExtractor info_data_ref(info_data.GetBytes(), info_data.GetByteSize(), endian, addr_size);
601                     for (i = 0; info_data_ref.ValidOffset(info_data_offset); i++)
602                     {
603                         assert (i < m_dyld_image_infos.size());
604                         m_dyld_image_infos[i].address = info_data_ref.GetPointer(&info_data_offset);
605                         lldb::addr_t path_addr = info_data_ref.GetPointer(&info_data_offset);
606                         m_dyld_image_infos[i].mod_date = info_data_ref.GetPointer(&info_data_offset);
607 
608                         char raw_path[PATH_MAX];
609                         m_process->ReadCStringFromMemory (path_addr, raw_path, sizeof(raw_path));
610                         // don't resolve the path
611                         const bool resolve_path = false;
612                         m_dyld_image_infos[i].file_spec.SetFile(raw_path, resolve_path);
613                     }
614                     assert(i == m_dyld_all_image_infos.dylib_info_count);
615 
616                     UpdateAllImageInfosHeaderAndLoadCommands();
617                 }
618                 else
619                 {
620                     DEBUG_PRINTF( "unable to read all data for all_dylib_infos.");
621                     m_dyld_image_infos.clear();
622                 }
623             }
624         }
625 
626         // If our new list is smaller than our old list, we have unloaded
627         // some shared libraries
628         if (m_dyld_image_infos.size() != old_dyld_all_image_infos.size())
629         {
630             ModuleList unloaded_module_list;
631             if (old_dyld_all_image_infos.size() == 0)
632             {
633                 // This is the first time we are loading shared libraries,
634                 // we need to make sure to trim anything that isn't in the
635                 // m_dyld_image_infos out of the target module list since
636                 // we might have shared libraries that got loaded from
637                 // elsewhere due to DYLD_FRAMEWORK_PATH, or DYLD_LIBRARY_PATH
638                 // environment variables...
639                 const size_t num_images = target_images.GetSize();
640                 for (idx = 0; idx < num_images; ++idx)
641                 {
642                     ModuleSP module_sp (target_images.GetModuleAtIndex (idx));
643 
644                     if (GetImageInfo (module_sp.get()) == NULL)
645                         unloaded_module_list.AppendIfNeeded (module_sp);
646                 }
647             }
648             else
649             {
650                 uint32_t old_idx;
651                 for (idx = 0; idx < old_dyld_all_image_infos.size(); ++idx)
652                 {
653                     for (old_idx = idx; old_idx < old_dyld_all_image_infos.size(); ++old_idx)
654                     {
655                         if (m_dyld_image_infos[idx].file_spec == old_dyld_all_image_infos[old_idx].file_spec)
656                         {
657                             old_dyld_all_image_infos[old_idx].address = LLDB_INVALID_ADDRESS;
658                             break;
659                         }
660                     }
661                 }
662 
663                 for (old_idx = 0; old_idx < old_dyld_all_image_infos.size(); ++old_idx)
664                 {
665                     if (old_dyld_all_image_infos[old_idx].address != LLDB_INVALID_ADDRESS)
666                     {
667                         if (log)
668                             old_dyld_all_image_infos[old_idx].PutToLog (log.get());
669                         ModuleSP unload_image_module_sp (FindTargetModuleForDYLDImageInfo (old_dyld_all_image_infos[old_idx], false, NULL));
670                         if (unload_image_module_sp.get())
671                         {
672                             if (UnloadImageLoadAddress (unload_image_module_sp.get(), old_dyld_all_image_infos[old_idx]))
673                                 unloaded_module_list.AppendIfNeeded (unload_image_module_sp);
674                         }
675                     }
676                 }
677             }
678 
679             if (unloaded_module_list.GetSize() > 0)
680             {
681                 if (log)
682                 {
683                     log->PutCString("Unloaded:");
684                     unloaded_module_list.LogUUIDAndPaths (log, "DynamicLoaderMacOSXDYLD::ModulesDidUnload");
685                 }
686                 m_process->GetTarget().ModulesDidUnload (unloaded_module_list);
687             }
688         }
689         else
690         {
691             if (log)
692                 PutToLog(log.get());
693         }
694         m_dyld_image_infos_stop_id = m_process->GetStopID();
695     }
696     else
697     {
698         m_dyld_image_infos.clear();
699     }
700 
701     const uint32_t num_dylibs = m_dyld_image_infos.size();
702     if (num_dylibs > 0)
703     {
704         ModuleList loaded_module_list;
705         for (uint32_t idx = 0; idx<num_dylibs; ++idx)
706         {
707             ModuleSP image_module_sp (FindTargetModuleForDYLDImageInfo (m_dyld_image_infos[idx], true, NULL));
708 
709             if (image_module_sp)
710             {
711                 if (m_dyld_image_infos[idx].header.filetype == llvm::MachO::HeaderFileTypeDynamicLinkEditor)
712                     image_module_sp->SetIsDynamicLinkEditor (true);
713 
714                 ObjectFile *objfile = image_module_sp->GetObjectFile ();
715                 if (objfile)
716                 {
717                     SectionList *sections = objfile->GetSectionList();
718                     if (sections)
719                     {
720                         ConstString commpage_dbstr("__commpage");
721                         Section *commpage_section = sections->FindSectionByName(commpage_dbstr).get();
722                         if (commpage_section)
723                         {
724                             const FileSpec objfile_file_spec = objfile->GetFileSpec();
725                             ArchSpec arch (m_dyld_image_infos[idx].GetArchitecture ());
726                             ModuleSP commpage_image_module_sp(target_images.FindFirstModuleForFileSpec (objfile_file_spec, &arch, &commpage_dbstr));
727                             if (!commpage_image_module_sp)
728                             {
729                                 commpage_image_module_sp = m_process->GetTarget().GetSharedModule (m_dyld_image_infos[idx].file_spec,
730                                                                                                    arch,
731                                                                                                    NULL,
732                                                                                                    &commpage_dbstr,
733                                                                                                    objfile->GetOffset() + commpage_section->GetFileOffset());
734                             }
735                             if (commpage_image_module_sp)
736                                 UpdateCommPageLoadAddress (commpage_image_module_sp.get());
737                         }
738                     }
739                 }
740 
741                 // UpdateImageLoadAddress will return true if any segments
742                 // change load address. We need to check this so we don't
743                 // mention that all loaded shared libraries are newly loaded
744                 // each time we hit out dyld breakpoint since dyld will list all
745                 // shared libraries each time.
746                 if (UpdateImageLoadAddress (image_module_sp.get(), m_dyld_image_infos[idx]))
747                 {
748                     loaded_module_list.AppendIfNeeded (image_module_sp);
749                 }
750             }
751         }
752         if (loaded_module_list.GetSize() > 0)
753         {
754             // FIXME: This should really be in the Runtime handlers class, which should get
755             // called by the target's ModulesDidLoad, but we're doing it all locally for now
756             // to save time.
757             // Also, I'm assuming there can be only one libobjc dylib loaded...
758 
759             ObjCLanguageRuntime *objc_runtime = m_process->GetObjCLanguageRuntime();
760             if (objc_runtime != NULL && !objc_runtime->HasReadObjCLibrary())
761             {
762                 size_t num_modules = loaded_module_list.GetSize();
763                 for (int i = 0; i < num_modules; i++)
764                 {
765                     if (objc_runtime->IsModuleObjCLibrary (loaded_module_list.GetModuleAtIndex (i)))
766                     {
767                         objc_runtime->ReadObjCLibrary (loaded_module_list.GetModuleAtIndex (i));
768                         break;
769                     }
770                 }
771             }
772             if (log)
773                 loaded_module_list.LogUUIDAndPaths (log, "DynamicLoaderMacOSXDYLD::ModulesDidLoad");
774             m_process->GetTarget().ModulesDidLoad (loaded_module_list);
775         }
776     }
777     return m_dyld_image_infos.size();
778 }
779 
780 //----------------------------------------------------------------------
781 // Read a mach_header at ADDR into HEADER, and also fill in the load
782 // command data into LOAD_COMMAND_DATA if it is non-NULL.
783 //
784 // Returns true if we succeed, false if we fail for any reason.
785 //----------------------------------------------------------------------
786 bool
787 DynamicLoaderMacOSXDYLD::ReadMachHeader (lldb::addr_t addr, llvm::MachO::mach_header *header, DataExtractor *load_command_data)
788 {
789     DataBufferHeap header_bytes(sizeof(llvm::MachO::mach_header), 0);
790     Error error;
791     size_t bytes_read = m_process->ReadMemory (addr,
792                                                header_bytes.GetBytes(),
793                                                header_bytes.GetByteSize(),
794                                                error);
795     if (bytes_read == sizeof(llvm::MachO::mach_header))
796     {
797         uint32_t offset = 0;
798         ::memset (header, 0, sizeof(header));
799 
800         // Get the magic byte unswapped so we can figure out what we are dealing with
801         DataExtractor data(header_bytes.GetBytes(), header_bytes.GetByteSize(), lldb::endian::InlHostByteOrder(), 4);
802         header->magic = data.GetU32(&offset);
803         lldb::addr_t load_cmd_addr = addr;
804         data.SetByteOrder(DynamicLoaderMacOSXDYLD::GetByteOrderFromMagic(header->magic));
805         switch (header->magic)
806         {
807         case llvm::MachO::HeaderMagic32:
808         case llvm::MachO::HeaderMagic32Swapped:
809             data.SetAddressByteSize(4);
810             load_cmd_addr += sizeof(llvm::MachO::mach_header);
811             break;
812 
813         case llvm::MachO::HeaderMagic64:
814         case llvm::MachO::HeaderMagic64Swapped:
815             data.SetAddressByteSize(8);
816             load_cmd_addr += sizeof(llvm::MachO::mach_header_64);
817             break;
818 
819         default:
820             return false;
821         }
822 
823         // Read the rest of dyld's mach header
824         if (data.GetU32(&offset, &header->cputype, (sizeof(llvm::MachO::mach_header)/sizeof(uint32_t)) - 1))
825         {
826             if (load_command_data == NULL)
827                 return true; // We were able to read the mach_header and weren't asked to read the load command bytes
828 
829             DataBufferSP load_cmd_data_sp(new DataBufferHeap(header->sizeofcmds, 0));
830 
831             size_t load_cmd_bytes_read = m_process->ReadMemory (load_cmd_addr,
832                                                                 load_cmd_data_sp->GetBytes(),
833                                                                 load_cmd_data_sp->GetByteSize(),
834                                                                 error);
835 
836             if (load_cmd_bytes_read == header->sizeofcmds)
837             {
838                 // Set the load command data and also set the correct endian
839                 // swap settings and the correct address size
840                 load_command_data->SetData(load_cmd_data_sp, 0, header->sizeofcmds);
841                 load_command_data->SetByteOrder(data.GetByteOrder());
842                 load_command_data->SetAddressByteSize(data.GetAddressByteSize());
843                 return true; // We successfully read the mach_header and the load command data
844             }
845 
846             return false; // We weren't able to read the load command data
847         }
848     }
849     return false; // We failed the read the mach_header
850 }
851 
852 
853 //----------------------------------------------------------------------
854 // Parse the load commands for an image
855 //----------------------------------------------------------------------
856 uint32_t
857 DynamicLoaderMacOSXDYLD::ParseLoadCommands (const DataExtractor& data, DYLDImageInfo& dylib_info, FileSpec *lc_id_dylinker)
858 {
859     uint32_t offset = 0;
860     uint32_t cmd_idx;
861     Segment segment;
862     dylib_info.Clear (true);
863 
864     for (cmd_idx = 0; cmd_idx < dylib_info.header.ncmds; cmd_idx++)
865     {
866         // Clear out any load command specific data from DYLIB_INFO since
867         // we are about to read it.
868 
869         if (data.ValidOffsetForDataOfSize (offset, sizeof(llvm::MachO::load_command)))
870         {
871             llvm::MachO::load_command load_cmd;
872             uint32_t load_cmd_offset = offset;
873             load_cmd.cmd = data.GetU32 (&offset);
874             load_cmd.cmdsize = data.GetU32 (&offset);
875             switch (load_cmd.cmd)
876             {
877             case llvm::MachO::LoadCommandSegment32:
878                 {
879                     segment.name.SetTrimmedCStringWithLength ((const char *)data.GetData(&offset, 16), 16);
880                     // We are putting 4 uint32_t values 4 uint64_t values so
881                     // we have to use multiple 32 bit gets below.
882                     segment.vmaddr = data.GetU32 (&offset);
883                     segment.vmsize = data.GetU32 (&offset);
884                     segment.fileoff = data.GetU32 (&offset);
885                     segment.filesize = data.GetU32 (&offset);
886                     // Extract maxprot, initprot, nsects and flags all at once
887                     data.GetU32(&offset, &segment.maxprot, 4);
888                     dylib_info.segments.push_back (segment);
889                 }
890                 break;
891 
892             case llvm::MachO::LoadCommandSegment64:
893                 {
894                     segment.name.SetTrimmedCStringWithLength ((const char *)data.GetData(&offset, 16), 16);
895                     // Extract vmaddr, vmsize, fileoff, and filesize all at once
896                     data.GetU64(&offset, &segment.vmaddr, 4);
897                     // Extract maxprot, initprot, nsects and flags all at once
898                     data.GetU32(&offset, &segment.maxprot, 4);
899                     dylib_info.segments.push_back (segment);
900                 }
901                 break;
902 
903             case llvm::MachO::LoadCommandDynamicLinkerIdent:
904                 if (lc_id_dylinker)
905                 {
906                     uint32_t name_offset = load_cmd_offset + data.GetU32 (&offset);
907                     const char *path = data.PeekCStr (name_offset);
908                     lc_id_dylinker->SetFile (path, true);
909                 }
910                 break;
911 
912             case llvm::MachO::LoadCommandUUID:
913                 dylib_info.uuid.SetBytes(data.GetData (&offset, 16));
914                 break;
915 
916             default:
917                 break;
918             }
919             // Set offset to be the beginning of the next load command.
920             offset = load_cmd_offset + load_cmd.cmdsize;
921         }
922     }
923 
924     // All sections listed in the dyld image info structure will all
925     // either be fixed up already, or they will all be off by a single
926     // slide amount that is determined by finding the first segment
927     // that is at file offset zero which also has bytes (a file size
928     // that is greater than zero) in the object file.
929 
930     // Determine the slide amount (if any)
931     const size_t num_sections = dylib_info.segments.size();
932     for (size_t i = 0; i < num_sections; ++i)
933     {
934         // Iterate through the object file sections to find the
935         // first section that starts of file offset zero and that
936         // has bytes in the file...
937         if (dylib_info.segments[i].fileoff == 0 && dylib_info.segments[i].filesize > 0)
938         {
939             dylib_info.slide = dylib_info.address - dylib_info.segments[i].vmaddr;
940             // We have found the slide amount, so we can exit
941             // this for loop.
942             break;
943         }
944     }
945     return cmd_idx;
946 }
947 
948 //----------------------------------------------------------------------
949 // Read the mach_header and load commands for each image that the
950 // _dyld_all_image_infos structure points to and cache the results.
951 //----------------------------------------------------------------------
952 void
953 DynamicLoaderMacOSXDYLD::UpdateAllImageInfosHeaderAndLoadCommands()
954 {
955     uint32_t exe_idx = UINT32_MAX;
956     LogSP log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_DYNAMIC_LOADER));
957     // Read any UUID values that we can get
958     for (uint32_t i = 0; i < m_dyld_all_image_infos.dylib_info_count; i++)
959     {
960         if (!m_dyld_image_infos[i].UUIDValid())
961         {
962             DataExtractor data; // Load command data
963             if (!ReadMachHeader (m_dyld_image_infos[i].address, &m_dyld_image_infos[i].header, &data))
964                 continue;
965 
966             ParseLoadCommands (data, m_dyld_image_infos[i], NULL);
967 
968             if (m_dyld_image_infos[i].header.filetype == llvm::MachO::HeaderFileTypeExecutable)
969                 exe_idx = i;
970 
971             if (log)
972                 m_dyld_image_infos[i].PutToLog (log.get());
973         }
974     }
975 
976     if (exe_idx < m_dyld_image_infos.size())
977     {
978         ModuleSP exe_module_sp (FindTargetModuleForDYLDImageInfo (m_dyld_image_infos[exe_idx], false, NULL));
979 
980         if (!exe_module_sp)
981         {
982             ArchSpec exe_arch_spec (m_dyld_image_infos[exe_idx].GetArchitecture ());
983             exe_module_sp = m_process->GetTarget().GetSharedModule (m_dyld_image_infos[exe_idx].file_spec,
984                                                                     exe_arch_spec,
985                                                                     &m_dyld_image_infos[exe_idx].uuid);
986         }
987 
988         if (exe_module_sp)
989         {
990             if (exe_module_sp.get() != m_process->GetTarget().GetExecutableModule().get())
991             {
992                 // Don't load dependent images since we are in dyld where we will know
993                 // and find out about all images that are loaded
994                 bool get_dependent_images = false;
995                 m_process->GetTarget().SetExecutableModule (exe_module_sp,
996                                                             get_dependent_images);
997             }
998         }
999     }
1000 }
1001 
1002 //----------------------------------------------------------------------
1003 // Dump a Segment to the file handle provided.
1004 //----------------------------------------------------------------------
1005 void
1006 DynamicLoaderMacOSXDYLD::Segment::PutToLog (Log *log, lldb::addr_t slide) const
1007 {
1008     if (log)
1009     {
1010         if (slide == 0)
1011             log->Printf ("\t\t%16s [0x%16.16llx - 0x%16.16llx)",
1012                          name.AsCString(""),
1013                          vmaddr + slide,
1014                          vmaddr + slide + vmsize);
1015         else
1016             log->Printf ("\t\t%16s [0x%16.16llx - 0x%16.16llx) slide = 0x%llx",
1017                          name.AsCString(""),
1018                          vmaddr + slide,
1019                          vmaddr + slide + vmsize,
1020                          slide);
1021     }
1022 }
1023 
1024 const DynamicLoaderMacOSXDYLD::Segment *
1025 DynamicLoaderMacOSXDYLD::DYLDImageInfo::FindSegment (const ConstString &name) const
1026 {
1027     const size_t num_segments = segments.size();
1028     for (size_t i=0; i<num_segments; ++i)
1029     {
1030         if (segments[i].name == name)
1031             return &segments[i];
1032     }
1033     return NULL;
1034 }
1035 
1036 
1037 //----------------------------------------------------------------------
1038 // Dump an image info structure to the file handle provided.
1039 //----------------------------------------------------------------------
1040 void
1041 DynamicLoaderMacOSXDYLD::DYLDImageInfo::PutToLog (Log *log) const
1042 {
1043     if (log == NULL)
1044         return;
1045     uint8_t *u = (uint8_t *)uuid.GetBytes();
1046 
1047     if (address == LLDB_INVALID_ADDRESS)
1048     {
1049         if (u)
1050         {
1051             log->Printf("\t                           modtime=0x%8.8llx 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/%s' (UNLOADED)",
1052                         mod_date,
1053                         u[ 0], u[ 1], u[ 2], u[ 3],
1054                         u[ 4], u[ 5], u[ 6], u[ 7],
1055                         u[ 8], u[ 9], u[10], u[11],
1056                         u[12], u[13], u[14], u[15],
1057                         file_spec.GetDirectory().AsCString(),
1058                         file_spec.GetFilename().AsCString());
1059         }
1060         else
1061             log->Printf("\t                           modtime=0x%8.8llx path='%s/%s' (UNLOADED)",
1062                         mod_date,
1063                         file_spec.GetDirectory().AsCString(),
1064                         file_spec.GetFilename().AsCString());
1065     }
1066     else
1067     {
1068         if (u)
1069         {
1070             log->Printf("\taddress=0x%16.16llx modtime=0x%8.8llx 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/%s'",
1071                         address,
1072                         mod_date,
1073                         u[ 0], u[ 1], u[ 2], u[ 3],
1074                         u[ 4], u[ 5], u[ 6], u[ 7],
1075                         u[ 8], u[ 9], u[10], u[11],
1076                         u[12], u[13], u[14], u[15],
1077                         file_spec.GetDirectory().AsCString(),
1078                         file_spec.GetFilename().AsCString());
1079         }
1080         else
1081         {
1082             log->Printf("\taddress=0x%16.16llx modtime=0x%8.8llx path='%s/%s'",
1083                         address,
1084                         mod_date,
1085                         file_spec.GetDirectory().AsCString(),
1086                         file_spec.GetFilename().AsCString());
1087 
1088         }
1089         for (uint32_t i=0; i<segments.size(); ++i)
1090             segments[i].PutToLog(log, slide);
1091     }
1092 }
1093 
1094 //----------------------------------------------------------------------
1095 // Dump the _dyld_all_image_infos members and all current image infos
1096 // that we have parsed to the file handle provided.
1097 //----------------------------------------------------------------------
1098 void
1099 DynamicLoaderMacOSXDYLD::PutToLog(Log *log) const
1100 {
1101     if (log == NULL)
1102         return;
1103 
1104     Mutex::Locker locker(m_mutex);
1105     log->Printf("dyld_all_image_infos = { version=%d, count=%d, addr=0x%8.8llx, notify=0x%8.8llx }",
1106                     m_dyld_all_image_infos.version,
1107                     m_dyld_all_image_infos.dylib_info_count,
1108                     (uint64_t)m_dyld_all_image_infos.dylib_info_addr,
1109                     (uint64_t)m_dyld_all_image_infos.notification);
1110     size_t i;
1111     const size_t count = m_dyld_image_infos.size();
1112     if (count > 0)
1113     {
1114         log->PutCString("Loaded:");
1115         for (i = 0; i<count; i++)
1116             m_dyld_image_infos[i].PutToLog(log);
1117     }
1118 }
1119 
1120 void
1121 DynamicLoaderMacOSXDYLD::PrivateInitialize(Process *process)
1122 {
1123     DEBUG_PRINTF("DynamicLoaderMacOSXDYLD::%s() process state = %s\n", __FUNCTION__, StateAsCString(m_process->GetState()));
1124     Clear(true);
1125     m_process = process;
1126     m_process->GetTarget().GetSectionLoadList().Clear();
1127 }
1128 
1129 bool
1130 DynamicLoaderMacOSXDYLD::SetNotificationBreakpoint ()
1131 {
1132     DEBUG_PRINTF("DynamicLoaderMacOSXDYLD::%s() process state = %s\n", __FUNCTION__, StateAsCString(m_process->GetState()));
1133     if (m_break_id == LLDB_INVALID_BREAK_ID)
1134     {
1135         if (m_dyld_all_image_infos.notification != LLDB_INVALID_ADDRESS)
1136         {
1137             Address so_addr;
1138             // Set the notification breakpoint and install a breakpoint
1139             // callback function that will get called each time the
1140             // breakpoint gets hit. We will use this to track when shared
1141             // libraries get loaded/unloaded.
1142 
1143             if (m_process->GetTarget().GetSectionLoadList().ResolveLoadAddress(m_dyld_all_image_infos.notification, so_addr))
1144             {
1145                 Breakpoint *dyld_break = m_process->GetTarget().CreateBreakpoint (so_addr, true).get();
1146                 dyld_break->SetCallback (DynamicLoaderMacOSXDYLD::NotifyBreakpointHit, this, true);
1147                 m_break_id = dyld_break->GetID();
1148             }
1149         }
1150     }
1151     return m_break_id != LLDB_INVALID_BREAK_ID;
1152 }
1153 
1154 //----------------------------------------------------------------------
1155 // Member function that gets called when the process state changes.
1156 //----------------------------------------------------------------------
1157 void
1158 DynamicLoaderMacOSXDYLD::PrivateProcessStateChanged (Process *process, StateType state)
1159 {
1160     DEBUG_PRINTF("DynamicLoaderMacOSXDYLD::%s(%s)\n", __FUNCTION__, StateAsCString(state));
1161     switch (state)
1162     {
1163     case eStateConnected:
1164     case eStateAttaching:
1165     case eStateLaunching:
1166     case eStateInvalid:
1167     case eStateUnloaded:
1168     case eStateExited:
1169     case eStateDetached:
1170         Clear(false);
1171         break;
1172 
1173     case eStateStopped:
1174         // Keep trying find dyld and set our notification breakpoint each time
1175         // we stop until we succeed
1176         if (!DidSetNotificationBreakpoint () && m_process->IsAlive())
1177         {
1178             if (NeedToLocateDYLD ())
1179                 LocateDYLD ();
1180 
1181             SetNotificationBreakpoint ();
1182         }
1183         break;
1184 
1185     case eStateRunning:
1186     case eStateStepping:
1187     case eStateCrashed:
1188     case eStateSuspended:
1189         break;
1190 
1191     default:
1192         break;
1193     }
1194 }
1195 
1196 ThreadPlanSP
1197 DynamicLoaderMacOSXDYLD::GetStepThroughTrampolinePlan (Thread &thread, bool stop_others)
1198 {
1199     ThreadPlanSP thread_plan_sp;
1200     StackFrame *current_frame = thread.GetStackFrameAtIndex(0).get();
1201     const SymbolContext &current_context = current_frame->GetSymbolContext(eSymbolContextSymbol);
1202     Symbol *current_symbol = current_context.symbol;
1203     LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP));
1204 
1205     if (current_symbol != NULL)
1206     {
1207         if (current_symbol->IsTrampoline())
1208         {
1209             const ConstString &trampoline_name = current_symbol->GetMangled().GetName(Mangled::ePreferMangled);
1210 
1211             if (trampoline_name)
1212             {
1213                 SymbolContextList target_symbols;
1214                 ModuleList &images = thread.GetProcess().GetTarget().GetImages();
1215                 images.FindSymbolsWithNameAndType(trampoline_name, eSymbolTypeCode, target_symbols);
1216                 // FIXME - Make the Run to Address take multiple addresses, and
1217                 // run to any of them.
1218                 uint32_t num_symbols = target_symbols.GetSize();
1219                 if (num_symbols == 1)
1220                 {
1221                     SymbolContext context;
1222                     AddressRange addr_range;
1223                     if (target_symbols.GetContextAtIndex(0, context))
1224                     {
1225                         context.GetAddressRange (eSymbolContextEverything, 0, false, addr_range);
1226                         thread_plan_sp.reset (new ThreadPlanRunToAddress (thread, addr_range.GetBaseAddress(), stop_others));
1227                     }
1228                     else
1229                     {
1230                         if (log)
1231                             log->Printf ("Couldn't resolve the symbol context.");
1232                     }
1233                 }
1234                 else if (num_symbols > 1)
1235                 {
1236                     std::vector<lldb::addr_t>  addresses;
1237                     addresses.resize (num_symbols);
1238                     for (uint32_t i = 0; i < num_symbols; i++)
1239                     {
1240                         SymbolContext context;
1241                         AddressRange addr_range;
1242                         if (target_symbols.GetContextAtIndex(i, context))
1243                         {
1244                             context.GetAddressRange (eSymbolContextEverything, 0, false, addr_range);
1245                             lldb::addr_t load_addr = addr_range.GetBaseAddress().GetLoadAddress(&thread.GetProcess().GetTarget());
1246                             addresses[i] = load_addr;
1247                         }
1248                     }
1249                     if (addresses.size() > 0)
1250                         thread_plan_sp.reset (new ThreadPlanRunToAddress (thread, addresses, stop_others));
1251                     else
1252                     {
1253                         if (log)
1254                             log->Printf ("Couldn't resolve the symbol contexts.");
1255                     }
1256                 }
1257                 else
1258                 {
1259                     if (log)
1260                     {
1261                         log->Printf ("Could not find symbol for trampoline target: \"%s\"", trampoline_name.AsCString());
1262                     }
1263                 }
1264             }
1265         }
1266     }
1267     else
1268     {
1269         if (log)
1270             log->Printf ("Could not find symbol for step through.");
1271     }
1272 
1273     return thread_plan_sp;
1274 }
1275 
1276 Error
1277 DynamicLoaderMacOSXDYLD::CanLoadImage ()
1278 {
1279     Error error;
1280     // In order for us to tell if we can load a shared library we verify that
1281     // the dylib_info_addr isn't zero (which means no shared libraries have
1282     // been set yet, or dyld is currently mucking with the shared library list).
1283     if (ReadAllImageInfosStructure ())
1284     {
1285         // TODO: also check the _dyld_global_lock_held variable in libSystem.B.dylib?
1286         // TODO: check the malloc lock?
1287         // TODO: check the objective C lock?
1288         if (m_dyld_all_image_infos.dylib_info_addr != 0)
1289             return error; // Success
1290     }
1291 
1292     error.SetErrorString("unsafe to load or unload shared libraries");
1293     return error;
1294 }
1295 
1296 void
1297 DynamicLoaderMacOSXDYLD::Initialize()
1298 {
1299     PluginManager::RegisterPlugin (GetPluginNameStatic(),
1300                                    GetPluginDescriptionStatic(),
1301                                    CreateInstance);
1302 }
1303 
1304 void
1305 DynamicLoaderMacOSXDYLD::Terminate()
1306 {
1307     PluginManager::UnregisterPlugin (CreateInstance);
1308 }
1309 
1310 
1311 const char *
1312 DynamicLoaderMacOSXDYLD::GetPluginNameStatic()
1313 {
1314     return "dynamic-loader.macosx-dyld";
1315 }
1316 
1317 const char *
1318 DynamicLoaderMacOSXDYLD::GetPluginDescriptionStatic()
1319 {
1320     return "Dynamic loader plug-in that watches for shared library loads/unloads in MacOSX user processes.";
1321 }
1322 
1323 
1324 //------------------------------------------------------------------
1325 // PluginInterface protocol
1326 //------------------------------------------------------------------
1327 const char *
1328 DynamicLoaderMacOSXDYLD::GetPluginName()
1329 {
1330     return "DynamicLoaderMacOSXDYLD";
1331 }
1332 
1333 const char *
1334 DynamicLoaderMacOSXDYLD::GetShortPluginName()
1335 {
1336     return GetPluginNameStatic();
1337 }
1338 
1339 uint32_t
1340 DynamicLoaderMacOSXDYLD::GetPluginVersion()
1341 {
1342     return 1;
1343 }
1344 
1345