DynamicLoaderMacOSXDYLD.cpp revision e6bd142d9fa7ed149bd37efd8a75637375f165b7
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
35using namespace lldb;
36using 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
43DynamicLoaderMacOSXDYLD::DYLDImageInfo *
44DynamicLoaderMacOSXDYLD::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//----------------------------------------------------------------------
85DynamicLoader *
86DynamicLoaderMacOSXDYLD::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//----------------------------------------------------------------------
104DynamicLoaderMacOSXDYLD::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//----------------------------------------------------------------------
120DynamicLoaderMacOSXDYLD::~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//------------------------------------------------------------------
131void
132DynamicLoaderMacOSXDYLD::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//------------------------------------------------------------------
145void
146DynamicLoaderMacOSXDYLD::DidLaunch ()
147{
148    PrivateInitialize(m_process);
149    LocateDYLD ();
150    SetNotificationBreakpoint ();
151}
152
153
154//----------------------------------------------------------------------
155// Clear out the state of this class.
156//----------------------------------------------------------------------
157void
158DynamicLoaderMacOSXDYLD::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//----------------------------------------------------------------------
177bool
178DynamicLoaderMacOSXDYLD::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//----------------------------------------------------------------------
189bool
190DynamicLoaderMacOSXDYLD::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
228ModuleSP
229DynamicLoaderMacOSXDYLD::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//----------------------------------------------------------------------
261bool
262DynamicLoaderMacOSXDYLD::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            InitializeFromAllImageInfos ();
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
307bool
308DynamicLoaderMacOSXDYLD::NeedToLocateDYLD () const
309{
310    return m_dyld_all_image_infos_addr == LLDB_INVALID_ADDRESS;
311}
312
313bool
314DynamicLoaderMacOSXDYLD::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//----------------------------------------------------------------------
351bool
352DynamicLoaderMacOSXDYLD::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                    const addr_t new_section_load_addr = info.segments[i].vmaddr + info.slide;
370                    if (section_sp)
371                    {
372                        const addr_t old_section_load_addr = m_process->GetTarget().GetSectionLoadList().GetSectionLoadAddress (section_sp.get());
373                        if (old_section_load_addr == LLDB_INVALID_ADDRESS ||
374                            old_section_load_addr != new_section_load_addr)
375                        {
376                            if (m_process->GetTarget().GetSectionLoadList().SetSectionLoadAddress (section_sp.get(), new_section_load_addr))
377                                changed = true;
378                        }
379                    }
380                    else
381                    {
382                        fprintf (stderr,
383                                 "warning: unable to find and load segment named '%s' at 0x%llx in '%s/%s' in macosx dynamic loader plug-in.\n",
384                                 info.segments[i].name.AsCString("<invalid>"),
385                                 (uint64_t)new_section_load_addr,
386                                 image_object_file->GetFileSpec().GetDirectory().AsCString(),
387                                 image_object_file->GetFileSpec().GetFilename().AsCString());
388                    }
389                }
390            }
391        }
392    }
393    return changed;
394}
395
396//----------------------------------------------------------------------
397// Update the load addresses for all segments in MODULE using the
398// updated INFO that is passed in.
399//----------------------------------------------------------------------
400bool
401DynamicLoaderMacOSXDYLD::UnloadImageLoadAddress (Module *module, DYLDImageInfo& info)
402{
403    bool changed = false;
404    if (module)
405    {
406        ObjectFile *image_object_file = module->GetObjectFile();
407        if (image_object_file)
408        {
409            SectionList *section_list = image_object_file->GetSectionList ();
410            if (section_list)
411            {
412                uint32_t num_segments = info.segments.size();
413                for (uint32_t i=0; i<num_segments; ++i)
414                {
415                    SectionSP section_sp(section_list->FindSectionByName(info.segments[i].name));
416                    if (section_sp)
417                    {
418                        const addr_t old_section_load_addr = info.segments[i].vmaddr + info.slide;
419                        if (m_process->GetTarget().GetSectionLoadList().SetSectionUnloaded (section_sp.get(), old_section_load_addr))
420                            changed = true;
421                    }
422                    else
423                    {
424                        fprintf (stderr,
425                                 "warning: unable to find and unload segment named '%s' in '%s/%s' in macosx dynamic loader plug-in.\n",
426                                 info.segments[i].name.AsCString("<invalid>"),
427                                 image_object_file->GetFileSpec().GetDirectory().AsCString(),
428                                 image_object_file->GetFileSpec().GetFilename().AsCString());
429                    }
430                }
431            }
432        }
433    }
434    return changed;
435}
436
437
438//----------------------------------------------------------------------
439// Static callback function that gets called when our DYLD notification
440// breakpoint gets hit. We update all of our image infos and then
441// let our super class DynamicLoader class decide if we should stop
442// or not (based on global preference).
443//----------------------------------------------------------------------
444bool
445DynamicLoaderMacOSXDYLD::NotifyBreakpointHit (void *baton,
446                                              StoppointCallbackContext *context,
447                                              lldb::user_id_t break_id,
448                                              lldb::user_id_t break_loc_id)
449{
450    // Let the event know that the images have changed
451    // DYLD passes three arguments to the notification breakpoint.
452    // Arg1: enum dyld_image_mode mode - 0 = adding, 1 = removing
453    // Arg2: uint32_t infoCount        - Number of shared libraries added
454    // Arg3: dyld_image_info info[]    - Array of structs of the form:
455    //                                     const struct mach_header *imageLoadAddress
456    //                                     const char               *imageFilePath
457    //                                     uintptr_t                 imageFileModDate (a time_t)
458
459    DynamicLoaderMacOSXDYLD* dyld_instance = (DynamicLoaderMacOSXDYLD*) baton;
460
461    // First step is to see if we've already initialized the all image infos.  If we haven't then this function
462    // will do so and return true.  In the course of initializing the all_image_infos it will read the complete
463    // current state, so we don't need to figure out what has changed from the data passed in to us.
464
465    if (dyld_instance->InitializeFromAllImageInfos())
466        return dyld_instance->GetStopWhenImagesChange();
467
468    Process *process = context->exe_ctx.process;
469    const lldb::ABISP &abi = process->GetABI();
470    if (abi != NULL)
471    {
472        // Build up the value array to store the three arguments given above, then get the values from the ABI:
473
474        ClangASTContext *clang_ast_context = process->GetTarget().GetScratchClangASTContext();
475        ValueList argument_values;
476        Value input_value;
477
478        void *clang_void_ptr_type = clang_ast_context->GetVoidPtrType(false);
479        void *clang_uint32_type   = clang_ast_context->GetBuiltinTypeForEncodingAndBitSize(lldb::eEncodingUint, 32);
480        input_value.SetValueType (Value::eValueTypeScalar);
481        input_value.SetContext (Value::eContextTypeClangType, clang_uint32_type);
482        argument_values.PushValue(input_value);
483        argument_values.PushValue(input_value);
484        input_value.SetContext (Value::eContextTypeClangType, clang_void_ptr_type);
485        argument_values.PushValue (input_value);
486
487        if (abi->GetArgumentValues (*context->exe_ctx.thread, argument_values))
488        {
489            uint32_t dyld_mode = argument_values.GetValueAtIndex(0)->GetScalar().UInt (-1);
490            if (dyld_mode != -1)
491            {
492                // Okay the mode was right, now get the number of elements, and the array of new elements...
493                uint32_t image_infos_count = argument_values.GetValueAtIndex(1)->GetScalar().UInt (-1);
494                if (image_infos_count != -1)
495                {
496                    // Got the number added, now go through the array of added elements, putting out the mach header
497                    // address, and adding the image.
498                    // Note, I'm not putting in logging here, since the AddModules & RemoveModules functions do
499                    // all the logging internally.
500
501                    lldb::addr_t image_infos_addr = argument_values.GetValueAtIndex(2)->GetScalar().ULongLong();
502                    if (dyld_mode == 0)
503                    {
504                        // This is add:
505                        dyld_instance->AddModulesUsingImageInfosAddress (image_infos_addr, image_infos_count);
506                    }
507                    else
508                    {
509                        // This is remove:
510                        dyld_instance->RemoveModulesUsingImageInfosAddress (image_infos_addr, image_infos_count);
511                    }
512
513                }
514            }
515        }
516    }
517
518    // Return true to stop the target, false to just let the target run
519    return dyld_instance->GetStopWhenImagesChange();
520}
521
522bool
523DynamicLoaderMacOSXDYLD::ReadAllImageInfosStructure ()
524{
525    Mutex::Locker locker(m_mutex);
526
527    // the all image infos is already valid for this process stop ID
528    if (m_process->GetStopID() == m_dyld_all_image_infos_stop_id)
529        return true;
530
531    m_dyld_all_image_infos.Clear();
532    if (m_dyld_all_image_infos_addr != LLDB_INVALID_ADDRESS)
533    {
534        ByteOrder byte_order = m_process->GetTarget().GetArchitecture().GetByteOrder();
535        uint32_t addr_size = 4;
536        if (m_dyld_all_image_infos_addr > UINT32_MAX)
537            addr_size = 8;
538
539        uint8_t buf[256];
540        DataExtractor data (buf, sizeof(buf), byte_order, addr_size);
541        uint32_t offset = 0;
542
543        const size_t count_v2 =  sizeof (uint32_t) + // version
544                                 sizeof (uint32_t) + // infoArrayCount
545                                 addr_size +         // infoArray
546                                 addr_size +         // notification
547                                 addr_size +         // processDetachedFromSharedRegion + libSystemInitialized + pad
548                                 addr_size;          // dyldImageLoadAddress
549        const size_t count_v11 = count_v2 +
550                                 addr_size +         // jitInfo
551                                 addr_size +         // dyldVersion
552                                 addr_size +         // errorMessage
553                                 addr_size +         // terminationFlags
554                                 addr_size +         // coreSymbolicationShmPage
555                                 addr_size +         // systemOrderFlag
556                                 addr_size +         // uuidArrayCount
557                                 addr_size +         // uuidArray
558                                 addr_size +         // dyldAllImageInfosAddress
559                                 addr_size +         // initialImageCount
560                                 addr_size +         // errorKind
561                                 addr_size +         // errorClientOfDylibPath
562                                 addr_size +         // errorTargetDylibPath
563                                 addr_size;          // errorSymbol
564        assert (sizeof (buf) >= count_v11);
565
566        int count;
567        Error error;
568        if (m_process->ReadMemory (m_dyld_all_image_infos_addr, buf, 4, error) == 4)
569        {
570            m_dyld_all_image_infos.version = data.GetU32(&offset);
571            // If anything in the high byte is set, we probably got the byte
572            // order incorrect (the process might not have it set correctly
573            // yet due to attaching to a program without a specified file).
574            if (m_dyld_all_image_infos.version & 0xff000000)
575            {
576                // We have guessed the wrong byte order. Swap it and try
577                // reading the version again.
578                if (byte_order == eByteOrderLittle)
579                    byte_order = eByteOrderBig;
580                else
581                    byte_order = eByteOrderLittle;
582
583                data.SetByteOrder (byte_order);
584                offset = 0;
585                m_dyld_all_image_infos.version = data.GetU32(&offset);
586            }
587        }
588        else
589        {
590            return false;
591        }
592
593        if (m_dyld_all_image_infos.version >= 11)
594            count = count_v11;
595        else
596            count = count_v2;
597
598        const size_t bytes_read = m_process->ReadMemory (m_dyld_all_image_infos_addr, buf, count, error);
599        if (bytes_read == count)
600        {
601            offset = 0;
602            m_dyld_all_image_infos.version = data.GetU32(&offset);
603            m_dyld_all_image_infos.dylib_info_count = data.GetU32(&offset);
604            m_dyld_all_image_infos.dylib_info_addr = data.GetPointer(&offset);
605            m_dyld_all_image_infos.notification = data.GetPointer(&offset);
606            m_dyld_all_image_infos.processDetachedFromSharedRegion = data.GetU8(&offset);
607            m_dyld_all_image_infos.libSystemInitialized = data.GetU8(&offset);
608            // Adjust for padding.
609            offset += addr_size - 2;
610            m_dyld_all_image_infos.dyldImageLoadAddress = data.GetPointer(&offset);
611            if (m_dyld_all_image_infos.version >= 11)
612            {
613                offset += addr_size * 8;
614                uint64_t dyld_all_image_infos_addr = data.GetPointer(&offset);
615
616                // When we started, we were given the actual address of the all_image_infos
617                // struct (probably via TASK_DYLD_INFO) in memory - this address is stored in
618                // m_dyld_all_image_infos_addr and is the most accurate address we have.
619
620                // We read the dyld_all_image_infos struct from memory; it contains its own address.
621                // If the address in the struct does not match the actual address,
622                // the dyld we're looking at has been loaded at a different location (slid) from
623                // where it intended to load.  The addresses in the dyld_all_image_infos struct
624                // are the original, non-slid addresses, and need to be adjusted.  Most importantly
625                // the address of dyld and the notification address need to be adjusted.
626
627                if (dyld_all_image_infos_addr != m_dyld_all_image_infos_addr)
628                {
629                    uint64_t image_infos_offset = dyld_all_image_infos_addr - m_dyld_all_image_infos.dyldImageLoadAddress;
630                    uint64_t notification_offset = m_dyld_all_image_infos.notification - m_dyld_all_image_infos.dyldImageLoadAddress;
631                    m_dyld_all_image_infos.dyldImageLoadAddress = m_dyld_all_image_infos_addr - image_infos_offset;
632                    m_dyld_all_image_infos.notification = m_dyld_all_image_infos.dyldImageLoadAddress + notification_offset;
633                }
634            }
635            m_dyld_all_image_infos_stop_id = m_process->GetStopID();
636            return true;
637        }
638    }
639    return false;
640}
641
642
643bool
644DynamicLoaderMacOSXDYLD::AddModulesUsingImageInfosAddress (lldb::addr_t image_infos_addr, uint32_t image_infos_count)
645{
646    DYLDImageInfo::collection image_infos;
647    LogSP log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_DYNAMIC_LOADER));
648    if (log)
649        log->Printf ("Adding %d modules.\n");
650
651    Mutex::Locker locker(m_mutex);
652    if (m_process->GetStopID() == m_dyld_image_infos_stop_id)
653        return true;
654
655    if (!ReadImageInfos (image_infos_addr, image_infos_count, image_infos))
656        return false;
657
658    UpdateImageInfosHeaderAndLoadCommands (image_infos, image_infos_count, false);
659    bool return_value = AddModulesUsingImageInfos (image_infos);
660    m_dyld_image_infos_stop_id = m_process->GetStopID();
661    return return_value;
662}
663
664// Adds the modules in image_infos to m_dyld_image_infos.
665// NB don't call this passing in m_dyld_image_infos.
666
667bool
668DynamicLoaderMacOSXDYLD::AddModulesUsingImageInfos (DYLDImageInfo::collection &image_infos)
669{
670    // Now add these images to the main list.
671    ModuleList loaded_module_list;
672    LogSP log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_DYNAMIC_LOADER));
673
674    for (uint32_t idx = 0; idx < image_infos.size(); ++idx)
675    {
676        if (log)
677        {
678            log->Printf ("Adding new image at address=0x%16.16llx.", image_infos[idx].address);
679            image_infos[idx].PutToLog (log.get());
680        }
681
682        m_dyld_image_infos.push_back(image_infos[idx]);
683
684        ModuleSP image_module_sp (FindTargetModuleForDYLDImageInfo (image_infos[idx], true, NULL));
685
686        if (image_module_sp)
687        {
688            if (image_infos[idx].header.filetype == llvm::MachO::HeaderFileTypeDynamicLinkEditor)
689                image_module_sp->SetIsDynamicLinkEditor (true);
690
691            ObjectFile *objfile = image_module_sp->GetObjectFile ();
692            if (objfile)
693            {
694                SectionList *sections = objfile->GetSectionList();
695                if (sections)
696                {
697                    ConstString commpage_dbstr("__commpage");
698                    Section *commpage_section = sections->FindSectionByName(commpage_dbstr).get();
699                    if (commpage_section)
700                    {
701                        ModuleList& target_images = m_process->GetTarget().GetImages();
702                        const FileSpec objfile_file_spec = objfile->GetFileSpec();
703                        ArchSpec arch (image_infos[idx].GetArchitecture ());
704                        ModuleSP commpage_image_module_sp(target_images.FindFirstModuleForFileSpec (objfile_file_spec,
705                                                                                                    &arch,
706                                                                                                    &commpage_dbstr));
707                        if (!commpage_image_module_sp)
708                        {
709                            commpage_image_module_sp
710                                    = m_process->GetTarget().GetSharedModule (image_infos[idx].file_spec,
711                                                                              arch,
712                                                                              NULL,
713                                                                              &commpage_dbstr,
714                                                                              objfile->GetOffset() + commpage_section->GetFileOffset());
715                        }
716                        if (commpage_image_module_sp)
717                            UpdateCommPageLoadAddress (commpage_image_module_sp.get());
718                    }
719                }
720            }
721
722            // UpdateImageLoadAddress will return true if any segments
723            // change load address. We need to check this so we don't
724            // mention that all loaded shared libraries are newly loaded
725            // each time we hit out dyld breakpoint since dyld will list all
726            // shared libraries each time.
727            if (UpdateImageLoadAddress (image_module_sp.get(), image_infos[idx]))
728            {
729                loaded_module_list.AppendIfNeeded (image_module_sp);
730            }
731        }
732    }
733
734    if (loaded_module_list.GetSize() > 0)
735    {
736        // FIXME: This should really be in the Runtime handlers class, which should get
737        // called by the target's ModulesDidLoad, but we're doing it all locally for now
738        // to save time.
739        // Also, I'm assuming there can be only one libobjc dylib loaded...
740
741        ObjCLanguageRuntime *objc_runtime = m_process->GetObjCLanguageRuntime();
742        if (objc_runtime != NULL && !objc_runtime->HasReadObjCLibrary())
743        {
744            size_t num_modules = loaded_module_list.GetSize();
745            for (int i = 0; i < num_modules; i++)
746            {
747                if (objc_runtime->IsModuleObjCLibrary (loaded_module_list.GetModuleAtIndex (i)))
748                {
749                    objc_runtime->ReadObjCLibrary (loaded_module_list.GetModuleAtIndex (i));
750                    break;
751                }
752            }
753        }
754        if (log)
755            loaded_module_list.LogUUIDAndPaths (log, "DynamicLoaderMacOSXDYLD::ModulesDidLoad");
756        m_process->GetTarget().ModulesDidLoad (loaded_module_list);
757    }
758    return true;
759}
760
761bool
762DynamicLoaderMacOSXDYLD::RemoveModulesUsingImageInfosAddress (lldb::addr_t image_infos_addr, uint32_t image_infos_count)
763{
764    DYLDImageInfo::collection image_infos;
765    LogSP log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_DYNAMIC_LOADER));
766
767    Mutex::Locker locker(m_mutex);
768    if (m_process->GetStopID() == m_dyld_image_infos_stop_id)
769        return true;
770
771    // First read in the image_infos for the removed modules, and their headers & load commands.
772    if (!ReadImageInfos (image_infos_addr, image_infos_count, image_infos))
773    {
774        if (log)
775            log->PutCString ("Failed reading image infos array.");
776        return false;
777    }
778
779    if (log)
780        log->Printf ("Removing %d modules.", image_infos_count);
781
782    ModuleList unloaded_module_list;
783    for (uint32_t idx = 0; idx < image_infos.size(); ++idx)
784    {
785        if (log)
786        {
787            log->Printf ("Removing module at address=0x%16.16llx.", image_infos[idx].address);
788            image_infos[idx].PutToLog (log.get());
789        }
790
791        // Remove this image_infos from the m_all_image_infos.  We do the comparision by address
792        // rather than by file spec because we can have many modules with the same "file spec" in the
793        // case that they are modules loaded from memory.
794        //
795        // Also copy over the uuid from the old entry to the removed entry so we can
796        // use it to lookup the module in the module list.
797
798        DYLDImageInfo::collection::iterator pos, end = m_dyld_image_infos.end();
799        for (pos = m_dyld_image_infos.begin(); pos != end; pos++)
800        {
801            if (image_infos[idx].address == (*pos).address)
802            {
803                image_infos[idx].uuid = (*pos).uuid;
804
805                // Add the module from this image_info to the "unloaded_module_list".  We'll remove them all at
806                // one go later on.
807
808                ModuleSP unload_image_module_sp (FindTargetModuleForDYLDImageInfo (image_infos[idx], false, NULL));
809                if (unload_image_module_sp.get())
810                {
811                    UnloadImageLoadAddress (unload_image_module_sp.get(), image_infos[idx]);
812                    unloaded_module_list.AppendIfNeeded (unload_image_module_sp);
813                }
814                else
815                {
816                    if (log)
817                    {
818                        log->Printf ("Could not find module for unloading info entry:");
819                        image_infos[idx].PutToLog(log.get());
820                    }
821                }
822
823                // Then remove it from the m_dyld_image_infos:
824
825                m_dyld_image_infos.erase(pos);
826                break;
827            }
828        }
829
830        if (pos == end)
831        {
832            if (log)
833            {
834                log->Printf ("Could not find image_info entry for unloading image:");
835                image_infos[idx].PutToLog(log.get());
836            }
837        }
838    }
839    if (unloaded_module_list.GetSize() > 0)
840    {
841        if (log)
842        {
843            log->PutCString("Unloaded:");
844            unloaded_module_list.LogUUIDAndPaths (log, "DynamicLoaderMacOSXDYLD::ModulesDidUnload");
845        }
846        m_process->GetTarget().ModulesDidUnload (unloaded_module_list);
847    }
848    m_dyld_image_infos_stop_id = m_process->GetStopID();
849    return true;
850}
851
852bool
853DynamicLoaderMacOSXDYLD::ReadImageInfos (lldb::addr_t image_infos_addr,
854                                         uint32_t image_infos_count,
855                                         DYLDImageInfo::collection &image_infos)
856{
857    const ByteOrder endian = m_dyld.GetByteOrder();
858    const uint32_t addr_size = m_dyld.GetAddressByteSize();
859
860    image_infos.resize(image_infos_count);
861    const size_t count = image_infos.size() * 3 * addr_size;
862    DataBufferHeap info_data(count, 0);
863    Error error;
864    const size_t bytes_read = m_process->ReadMemory (image_infos_addr,
865                                                     info_data.GetBytes(),
866                                                     info_data.GetByteSize(),
867                                                     error);
868    if (bytes_read == count)
869    {
870        uint32_t info_data_offset = 0;
871        DataExtractor info_data_ref(info_data.GetBytes(), info_data.GetByteSize(), endian, addr_size);
872        for (int i = 0; i < image_infos.size() && info_data_ref.ValidOffset(info_data_offset); i++)
873        {
874            image_infos[i].address = info_data_ref.GetPointer(&info_data_offset);
875            lldb::addr_t path_addr = info_data_ref.GetPointer(&info_data_offset);
876            image_infos[i].mod_date = info_data_ref.GetPointer(&info_data_offset);
877
878            char raw_path[PATH_MAX];
879            m_process->ReadCStringFromMemory (path_addr, raw_path, sizeof(raw_path));
880            // don't resolve the path
881            const bool resolve_path = false;
882            image_infos[i].file_spec.SetFile(raw_path, resolve_path);
883        }
884        return true;
885    }
886    else
887    {
888        return false;
889    }
890}
891
892//----------------------------------------------------------------------
893// If we have found where the "_dyld_all_image_infos" lives in memory,
894// read the current info from it, and then update all image load
895// addresses (or lack thereof).  Only do this if this is the first time
896// we're reading the dyld infos.  Return true if we actually read anything,
897// and false otherwise.
898//----------------------------------------------------------------------
899bool
900DynamicLoaderMacOSXDYLD::InitializeFromAllImageInfos ()
901{
902    LogSP log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_DYNAMIC_LOADER));
903
904    Mutex::Locker locker(m_mutex);
905    if (m_process->GetStopID() == m_dyld_image_infos_stop_id
906          || m_dyld_image_infos.size() != 0)
907        return false;
908
909    if (ReadAllImageInfosStructure ())
910    {
911        if (m_dyld_all_image_infos.dylib_info_count > 0)
912        {
913            if (m_dyld_all_image_infos.dylib_info_addr == 0)
914            {
915                // DYLD is updating the images now.  So we should say we have no images, and then we'll
916                // figure it out when we hit the added breakpoint.
917                return false;
918            }
919            else
920            {
921                if (!AddModulesUsingImageInfosAddress (m_dyld_all_image_infos.dylib_info_addr,
922                                                       m_dyld_all_image_infos.dylib_info_count))
923                {
924                    DEBUG_PRINTF( "unable to read all data for all_dylib_infos.");
925                    m_dyld_image_infos.clear();
926                }
927            }
928        }
929        return true;
930    }
931    else
932        return false;
933}
934
935//----------------------------------------------------------------------
936// Read a mach_header at ADDR into HEADER, and also fill in the load
937// command data into LOAD_COMMAND_DATA if it is non-NULL.
938//
939// Returns true if we succeed, false if we fail for any reason.
940//----------------------------------------------------------------------
941bool
942DynamicLoaderMacOSXDYLD::ReadMachHeader (lldb::addr_t addr, llvm::MachO::mach_header *header, DataExtractor *load_command_data)
943{
944    DataBufferHeap header_bytes(sizeof(llvm::MachO::mach_header), 0);
945    Error error;
946    size_t bytes_read = m_process->ReadMemory (addr,
947                                               header_bytes.GetBytes(),
948                                               header_bytes.GetByteSize(),
949                                               error);
950    if (bytes_read == sizeof(llvm::MachO::mach_header))
951    {
952        uint32_t offset = 0;
953        ::memset (header, 0, sizeof(header));
954
955        // Get the magic byte unswapped so we can figure out what we are dealing with
956        DataExtractor data(header_bytes.GetBytes(), header_bytes.GetByteSize(), lldb::endian::InlHostByteOrder(), 4);
957        header->magic = data.GetU32(&offset);
958        lldb::addr_t load_cmd_addr = addr;
959        data.SetByteOrder(DynamicLoaderMacOSXDYLD::GetByteOrderFromMagic(header->magic));
960        switch (header->magic)
961        {
962        case llvm::MachO::HeaderMagic32:
963        case llvm::MachO::HeaderMagic32Swapped:
964            data.SetAddressByteSize(4);
965            load_cmd_addr += sizeof(llvm::MachO::mach_header);
966            break;
967
968        case llvm::MachO::HeaderMagic64:
969        case llvm::MachO::HeaderMagic64Swapped:
970            data.SetAddressByteSize(8);
971            load_cmd_addr += sizeof(llvm::MachO::mach_header_64);
972            break;
973
974        default:
975            return false;
976        }
977
978        // Read the rest of dyld's mach header
979        if (data.GetU32(&offset, &header->cputype, (sizeof(llvm::MachO::mach_header)/sizeof(uint32_t)) - 1))
980        {
981            if (load_command_data == NULL)
982                return true; // We were able to read the mach_header and weren't asked to read the load command bytes
983
984            DataBufferSP load_cmd_data_sp(new DataBufferHeap(header->sizeofcmds, 0));
985
986            size_t load_cmd_bytes_read = m_process->ReadMemory (load_cmd_addr,
987                                                                load_cmd_data_sp->GetBytes(),
988                                                                load_cmd_data_sp->GetByteSize(),
989                                                                error);
990
991            if (load_cmd_bytes_read == header->sizeofcmds)
992            {
993                // Set the load command data and also set the correct endian
994                // swap settings and the correct address size
995                load_command_data->SetData(load_cmd_data_sp, 0, header->sizeofcmds);
996                load_command_data->SetByteOrder(data.GetByteOrder());
997                load_command_data->SetAddressByteSize(data.GetAddressByteSize());
998                return true; // We successfully read the mach_header and the load command data
999            }
1000
1001            return false; // We weren't able to read the load command data
1002        }
1003    }
1004    return false; // We failed the read the mach_header
1005}
1006
1007
1008//----------------------------------------------------------------------
1009// Parse the load commands for an image
1010//----------------------------------------------------------------------
1011uint32_t
1012DynamicLoaderMacOSXDYLD::ParseLoadCommands (const DataExtractor& data, DYLDImageInfo& dylib_info, FileSpec *lc_id_dylinker)
1013{
1014    uint32_t offset = 0;
1015    uint32_t cmd_idx;
1016    Segment segment;
1017    dylib_info.Clear (true);
1018
1019    for (cmd_idx = 0; cmd_idx < dylib_info.header.ncmds; cmd_idx++)
1020    {
1021        // Clear out any load command specific data from DYLIB_INFO since
1022        // we are about to read it.
1023
1024        if (data.ValidOffsetForDataOfSize (offset, sizeof(llvm::MachO::load_command)))
1025        {
1026            llvm::MachO::load_command load_cmd;
1027            uint32_t load_cmd_offset = offset;
1028            load_cmd.cmd = data.GetU32 (&offset);
1029            load_cmd.cmdsize = data.GetU32 (&offset);
1030            switch (load_cmd.cmd)
1031            {
1032            case llvm::MachO::LoadCommandSegment32:
1033                {
1034                    segment.name.SetTrimmedCStringWithLength ((const char *)data.GetData(&offset, 16), 16);
1035                    // We are putting 4 uint32_t values 4 uint64_t values so
1036                    // we have to use multiple 32 bit gets below.
1037                    segment.vmaddr = data.GetU32 (&offset);
1038                    segment.vmsize = data.GetU32 (&offset);
1039                    segment.fileoff = data.GetU32 (&offset);
1040                    segment.filesize = data.GetU32 (&offset);
1041                    // Extract maxprot, initprot, nsects and flags all at once
1042                    data.GetU32(&offset, &segment.maxprot, 4);
1043                    dylib_info.segments.push_back (segment);
1044                }
1045                break;
1046
1047            case llvm::MachO::LoadCommandSegment64:
1048                {
1049                    segment.name.SetTrimmedCStringWithLength ((const char *)data.GetData(&offset, 16), 16);
1050                    // Extract vmaddr, vmsize, fileoff, and filesize all at once
1051                    data.GetU64(&offset, &segment.vmaddr, 4);
1052                    // Extract maxprot, initprot, nsects and flags all at once
1053                    data.GetU32(&offset, &segment.maxprot, 4);
1054                    dylib_info.segments.push_back (segment);
1055                }
1056                break;
1057
1058            case llvm::MachO::LoadCommandDynamicLinkerIdent:
1059                if (lc_id_dylinker)
1060                {
1061                    uint32_t name_offset = load_cmd_offset + data.GetU32 (&offset);
1062                    const char *path = data.PeekCStr (name_offset);
1063                    lc_id_dylinker->SetFile (path, true);
1064                }
1065                break;
1066
1067            case llvm::MachO::LoadCommandUUID:
1068                dylib_info.uuid.SetBytes(data.GetData (&offset, 16));
1069                break;
1070
1071            default:
1072                break;
1073            }
1074            // Set offset to be the beginning of the next load command.
1075            offset = load_cmd_offset + load_cmd.cmdsize;
1076        }
1077    }
1078
1079    // All sections listed in the dyld image info structure will all
1080    // either be fixed up already, or they will all be off by a single
1081    // slide amount that is determined by finding the first segment
1082    // that is at file offset zero which also has bytes (a file size
1083    // that is greater than zero) in the object file.
1084
1085    // Determine the slide amount (if any)
1086    const size_t num_sections = dylib_info.segments.size();
1087    for (size_t i = 0; i < num_sections; ++i)
1088    {
1089        // Iterate through the object file sections to find the
1090        // first section that starts of file offset zero and that
1091        // has bytes in the file...
1092        if (dylib_info.segments[i].fileoff == 0 && dylib_info.segments[i].filesize > 0)
1093        {
1094            dylib_info.slide = dylib_info.address - dylib_info.segments[i].vmaddr;
1095            // We have found the slide amount, so we can exit
1096            // this for loop.
1097            break;
1098        }
1099    }
1100    return cmd_idx;
1101}
1102
1103//----------------------------------------------------------------------
1104// Read the mach_header and load commands for each image that the
1105// _dyld_all_image_infos structure points to and cache the results.
1106//----------------------------------------------------------------------
1107
1108void
1109DynamicLoaderMacOSXDYLD::UpdateImageInfosHeaderAndLoadCommands(DYLDImageInfo::collection &image_infos,
1110                                                               uint32_t infos_count,
1111                                                               bool update_executable)
1112{
1113    uint32_t exe_idx = UINT32_MAX;
1114    LogSP log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_DYNAMIC_LOADER));
1115    // Read any UUID values that we can get
1116    for (uint32_t i = 0; i < infos_count; i++)
1117    {
1118        if (!image_infos[i].UUIDValid())
1119        {
1120            DataExtractor data; // Load command data
1121            if (!ReadMachHeader (image_infos[i].address, &image_infos[i].header, &data))
1122                continue;
1123
1124            ParseLoadCommands (data, image_infos[i], NULL);
1125
1126            if (image_infos[i].header.filetype == llvm::MachO::HeaderFileTypeExecutable)
1127                exe_idx = i;
1128
1129        }
1130    }
1131
1132    if (exe_idx < image_infos.size())
1133    {
1134        ModuleSP exe_module_sp (FindTargetModuleForDYLDImageInfo (image_infos[exe_idx], false, NULL));
1135
1136        if (!exe_module_sp)
1137        {
1138            ArchSpec exe_arch_spec (image_infos[exe_idx].GetArchitecture ());
1139            exe_module_sp = m_process->GetTarget().GetSharedModule (image_infos[exe_idx].file_spec,
1140                                                                    exe_arch_spec,
1141                                                                    &image_infos[exe_idx].uuid);
1142        }
1143
1144        if (exe_module_sp)
1145        {
1146            if (exe_module_sp.get() != m_process->GetTarget().GetExecutableModule().get())
1147            {
1148                // Don't load dependent images since we are in dyld where we will know
1149                // and find out about all images that are loaded
1150                bool get_dependent_images = false;
1151                m_process->GetTarget().SetExecutableModule (exe_module_sp,
1152                                                            get_dependent_images);
1153            }
1154        }
1155    }
1156}
1157
1158//----------------------------------------------------------------------
1159// Dump a Segment to the file handle provided.
1160//----------------------------------------------------------------------
1161void
1162DynamicLoaderMacOSXDYLD::Segment::PutToLog (Log *log, lldb::addr_t slide) const
1163{
1164    if (log)
1165    {
1166        if (slide == 0)
1167            log->Printf ("\t\t%16s [0x%16.16llx - 0x%16.16llx)",
1168                         name.AsCString(""),
1169                         vmaddr + slide,
1170                         vmaddr + slide + vmsize);
1171        else
1172            log->Printf ("\t\t%16s [0x%16.16llx - 0x%16.16llx) slide = 0x%llx",
1173                         name.AsCString(""),
1174                         vmaddr + slide,
1175                         vmaddr + slide + vmsize,
1176                         slide);
1177    }
1178}
1179
1180const DynamicLoaderMacOSXDYLD::Segment *
1181DynamicLoaderMacOSXDYLD::DYLDImageInfo::FindSegment (const ConstString &name) const
1182{
1183    const size_t num_segments = segments.size();
1184    for (size_t i=0; i<num_segments; ++i)
1185    {
1186        if (segments[i].name == name)
1187            return &segments[i];
1188    }
1189    return NULL;
1190}
1191
1192
1193//----------------------------------------------------------------------
1194// Dump an image info structure to the file handle provided.
1195//----------------------------------------------------------------------
1196void
1197DynamicLoaderMacOSXDYLD::DYLDImageInfo::PutToLog (Log *log) const
1198{
1199    if (log == NULL)
1200        return;
1201    uint8_t *u = (uint8_t *)uuid.GetBytes();
1202
1203    if (address == LLDB_INVALID_ADDRESS)
1204    {
1205        if (u)
1206        {
1207            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)",
1208                        mod_date,
1209                        u[ 0], u[ 1], u[ 2], u[ 3],
1210                        u[ 4], u[ 5], u[ 6], u[ 7],
1211                        u[ 8], u[ 9], u[10], u[11],
1212                        u[12], u[13], u[14], u[15],
1213                        file_spec.GetDirectory().AsCString(),
1214                        file_spec.GetFilename().AsCString());
1215        }
1216        else
1217            log->Printf("\t                           modtime=0x%8.8llx path='%s/%s' (UNLOADED)",
1218                        mod_date,
1219                        file_spec.GetDirectory().AsCString(),
1220                        file_spec.GetFilename().AsCString());
1221    }
1222    else
1223    {
1224        if (u)
1225        {
1226            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'",
1227                        address,
1228                        mod_date,
1229                        u[ 0], u[ 1], u[ 2], u[ 3],
1230                        u[ 4], u[ 5], u[ 6], u[ 7],
1231                        u[ 8], u[ 9], u[10], u[11],
1232                        u[12], u[13], u[14], u[15],
1233                        file_spec.GetDirectory().AsCString(),
1234                        file_spec.GetFilename().AsCString());
1235        }
1236        else
1237        {
1238            log->Printf("\taddress=0x%16.16llx modtime=0x%8.8llx path='%s/%s'",
1239                        address,
1240                        mod_date,
1241                        file_spec.GetDirectory().AsCString(),
1242                        file_spec.GetFilename().AsCString());
1243
1244        }
1245        for (uint32_t i=0; i<segments.size(); ++i)
1246            segments[i].PutToLog(log, slide);
1247    }
1248}
1249
1250//----------------------------------------------------------------------
1251// Dump the _dyld_all_image_infos members and all current image infos
1252// that we have parsed to the file handle provided.
1253//----------------------------------------------------------------------
1254void
1255DynamicLoaderMacOSXDYLD::PutToLog(Log *log) const
1256{
1257    if (log == NULL)
1258        return;
1259
1260    Mutex::Locker locker(m_mutex);
1261    log->Printf("dyld_all_image_infos = { version=%d, count=%d, addr=0x%8.8llx, notify=0x%8.8llx }",
1262                    m_dyld_all_image_infos.version,
1263                    m_dyld_all_image_infos.dylib_info_count,
1264                    (uint64_t)m_dyld_all_image_infos.dylib_info_addr,
1265                    (uint64_t)m_dyld_all_image_infos.notification);
1266    size_t i;
1267    const size_t count = m_dyld_image_infos.size();
1268    if (count > 0)
1269    {
1270        log->PutCString("Loaded:");
1271        for (i = 0; i<count; i++)
1272            m_dyld_image_infos[i].PutToLog(log);
1273    }
1274}
1275
1276void
1277DynamicLoaderMacOSXDYLD::PrivateInitialize(Process *process)
1278{
1279    DEBUG_PRINTF("DynamicLoaderMacOSXDYLD::%s() process state = %s\n", __FUNCTION__, StateAsCString(m_process->GetState()));
1280    Clear(true);
1281    m_process = process;
1282    m_process->GetTarget().GetSectionLoadList().Clear();
1283}
1284
1285bool
1286DynamicLoaderMacOSXDYLD::SetNotificationBreakpoint ()
1287{
1288    DEBUG_PRINTF("DynamicLoaderMacOSXDYLD::%s() process state = %s\n", __FUNCTION__, StateAsCString(m_process->GetState()));
1289    if (m_break_id == LLDB_INVALID_BREAK_ID)
1290    {
1291        if (m_dyld_all_image_infos.notification != LLDB_INVALID_ADDRESS)
1292        {
1293            Address so_addr;
1294            // Set the notification breakpoint and install a breakpoint
1295            // callback function that will get called each time the
1296            // breakpoint gets hit. We will use this to track when shared
1297            // libraries get loaded/unloaded.
1298
1299            if (m_process->GetTarget().GetSectionLoadList().ResolveLoadAddress(m_dyld_all_image_infos.notification, so_addr))
1300            {
1301                Breakpoint *dyld_break = m_process->GetTarget().CreateBreakpoint (so_addr, true).get();
1302                dyld_break->SetCallback (DynamicLoaderMacOSXDYLD::NotifyBreakpointHit, this, true);
1303                m_break_id = dyld_break->GetID();
1304            }
1305        }
1306    }
1307    return m_break_id != LLDB_INVALID_BREAK_ID;
1308}
1309
1310//----------------------------------------------------------------------
1311// Member function that gets called when the process state changes.
1312//----------------------------------------------------------------------
1313void
1314DynamicLoaderMacOSXDYLD::PrivateProcessStateChanged (Process *process, StateType state)
1315{
1316    DEBUG_PRINTF("DynamicLoaderMacOSXDYLD::%s(%s)\n", __FUNCTION__, StateAsCString(state));
1317    switch (state)
1318    {
1319    case eStateConnected:
1320    case eStateAttaching:
1321    case eStateLaunching:
1322    case eStateInvalid:
1323    case eStateUnloaded:
1324    case eStateExited:
1325    case eStateDetached:
1326        Clear(false);
1327        break;
1328
1329    case eStateStopped:
1330        // Keep trying find dyld and set our notification breakpoint each time
1331        // we stop until we succeed
1332        if (!DidSetNotificationBreakpoint () && m_process->IsAlive())
1333        {
1334            if (NeedToLocateDYLD ())
1335                LocateDYLD ();
1336
1337            SetNotificationBreakpoint ();
1338        }
1339        break;
1340
1341    case eStateRunning:
1342    case eStateStepping:
1343    case eStateCrashed:
1344    case eStateSuspended:
1345        break;
1346
1347    default:
1348        break;
1349    }
1350}
1351
1352ThreadPlanSP
1353DynamicLoaderMacOSXDYLD::GetStepThroughTrampolinePlan (Thread &thread, bool stop_others)
1354{
1355    ThreadPlanSP thread_plan_sp;
1356    StackFrame *current_frame = thread.GetStackFrameAtIndex(0).get();
1357    const SymbolContext &current_context = current_frame->GetSymbolContext(eSymbolContextSymbol);
1358    Symbol *current_symbol = current_context.symbol;
1359    LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP));
1360
1361    if (current_symbol != NULL)
1362    {
1363        if (current_symbol->IsTrampoline())
1364        {
1365            const ConstString &trampoline_name = current_symbol->GetMangled().GetName(Mangled::ePreferMangled);
1366
1367            if (trampoline_name)
1368            {
1369                SymbolContextList target_symbols;
1370                ModuleList &images = thread.GetProcess().GetTarget().GetImages();
1371                images.FindSymbolsWithNameAndType(trampoline_name, eSymbolTypeCode, target_symbols);
1372                // FIXME - Make the Run to Address take multiple addresses, and
1373                // run to any of them.
1374                uint32_t num_symbols = target_symbols.GetSize();
1375                if (num_symbols == 1)
1376                {
1377                    SymbolContext context;
1378                    AddressRange addr_range;
1379                    if (target_symbols.GetContextAtIndex(0, context))
1380                    {
1381                        context.GetAddressRange (eSymbolContextEverything, 0, false, addr_range);
1382                        thread_plan_sp.reset (new ThreadPlanRunToAddress (thread, addr_range.GetBaseAddress(), stop_others));
1383                    }
1384                    else
1385                    {
1386                        if (log)
1387                            log->Printf ("Couldn't resolve the symbol context.");
1388                    }
1389                }
1390                else if (num_symbols > 1)
1391                {
1392                    std::vector<lldb::addr_t>  addresses;
1393                    addresses.resize (num_symbols);
1394                    for (uint32_t i = 0; i < num_symbols; i++)
1395                    {
1396                        SymbolContext context;
1397                        AddressRange addr_range;
1398                        if (target_symbols.GetContextAtIndex(i, context))
1399                        {
1400                            context.GetAddressRange (eSymbolContextEverything, 0, false, addr_range);
1401                            lldb::addr_t load_addr = addr_range.GetBaseAddress().GetLoadAddress(&thread.GetProcess().GetTarget());
1402                            addresses[i] = load_addr;
1403                        }
1404                    }
1405                    if (addresses.size() > 0)
1406                        thread_plan_sp.reset (new ThreadPlanRunToAddress (thread, addresses, stop_others));
1407                    else
1408                    {
1409                        if (log)
1410                            log->Printf ("Couldn't resolve the symbol contexts.");
1411                    }
1412                }
1413                else
1414                {
1415                    if (log)
1416                    {
1417                        log->Printf ("Could not find symbol for trampoline target: \"%s\"", trampoline_name.AsCString());
1418                    }
1419                }
1420            }
1421        }
1422    }
1423    else
1424    {
1425        if (log)
1426            log->Printf ("Could not find symbol for step through.");
1427    }
1428
1429    return thread_plan_sp;
1430}
1431
1432Error
1433DynamicLoaderMacOSXDYLD::CanLoadImage ()
1434{
1435    Error error;
1436    // In order for us to tell if we can load a shared library we verify that
1437    // the dylib_info_addr isn't zero (which means no shared libraries have
1438    // been set yet, or dyld is currently mucking with the shared library list).
1439    if (ReadAllImageInfosStructure ())
1440    {
1441        // TODO: also check the _dyld_global_lock_held variable in libSystem.B.dylib?
1442        // TODO: check the malloc lock?
1443        // TODO: check the objective C lock?
1444        if (m_dyld_all_image_infos.dylib_info_addr != 0)
1445            return error; // Success
1446    }
1447
1448    error.SetErrorString("unsafe to load or unload shared libraries");
1449    return error;
1450}
1451
1452void
1453DynamicLoaderMacOSXDYLD::Initialize()
1454{
1455    PluginManager::RegisterPlugin (GetPluginNameStatic(),
1456                                   GetPluginDescriptionStatic(),
1457                                   CreateInstance);
1458}
1459
1460void
1461DynamicLoaderMacOSXDYLD::Terminate()
1462{
1463    PluginManager::UnregisterPlugin (CreateInstance);
1464}
1465
1466
1467const char *
1468DynamicLoaderMacOSXDYLD::GetPluginNameStatic()
1469{
1470    return "dynamic-loader.macosx-dyld";
1471}
1472
1473const char *
1474DynamicLoaderMacOSXDYLD::GetPluginDescriptionStatic()
1475{
1476    return "Dynamic loader plug-in that watches for shared library loads/unloads in MacOSX user processes.";
1477}
1478
1479
1480//------------------------------------------------------------------
1481// PluginInterface protocol
1482//------------------------------------------------------------------
1483const char *
1484DynamicLoaderMacOSXDYLD::GetPluginName()
1485{
1486    return "DynamicLoaderMacOSXDYLD";
1487}
1488
1489const char *
1490DynamicLoaderMacOSXDYLD::GetShortPluginName()
1491{
1492    return GetPluginNameStatic();
1493}
1494
1495uint32_t
1496DynamicLoaderMacOSXDYLD::GetPluginVersion()
1497{
1498    return 1;
1499}
1500
1501