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