DynamicLoaderMacOSXDYLD.cpp revision d2a1143a67661c65c6df4f4f1321ba4acdfe84c1
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        create = true;
92        Module* exe_module = process->GetTarget().GetExecutableModulePointer();
93        if (exe_module)
94        {
95            ObjectFile *object_file = exe_module->GetObjectFile();
96            if (object_file)
97            {
98                SectionList *section_list = object_file->GetSectionList();
99                if (section_list)
100                {
101                    static ConstString g_kld_section_name ("__KLD");
102                    if (section_list->FindSectionByName (g_kld_section_name))
103                    {
104                        create = false;
105                    }
106                }
107            }
108        }
109
110        if (create)
111        {
112            const llvm::Triple &triple_ref = process->GetTarget().GetArchitecture().GetTriple();
113            create = triple_ref.getOS() == llvm::Triple::Darwin && triple_ref.getVendor() == llvm::Triple::Apple;
114        }
115    }
116
117    if (create)
118        return new DynamicLoaderMacOSXDYLD (process);
119    return NULL;
120}
121
122//----------------------------------------------------------------------
123// Constructor
124//----------------------------------------------------------------------
125DynamicLoaderMacOSXDYLD::DynamicLoaderMacOSXDYLD (Process* process) :
126    DynamicLoader(process),
127    m_dyld(),
128    m_dyld_all_image_infos_addr(LLDB_INVALID_ADDRESS),
129    m_dyld_all_image_infos(),
130    m_dyld_all_image_infos_stop_id (UINT32_MAX),
131    m_break_id(LLDB_INVALID_BREAK_ID),
132    m_dyld_image_infos(),
133    m_dyld_image_infos_stop_id (UINT32_MAX),
134    m_mutex(Mutex::eMutexTypeRecursive)
135{
136}
137
138//----------------------------------------------------------------------
139// Destructor
140//----------------------------------------------------------------------
141DynamicLoaderMacOSXDYLD::~DynamicLoaderMacOSXDYLD()
142{
143    Clear(true);
144}
145
146//------------------------------------------------------------------
147/// Called after attaching a process.
148///
149/// Allow DynamicLoader plug-ins to execute some code after
150/// attaching to a process.
151//------------------------------------------------------------------
152void
153DynamicLoaderMacOSXDYLD::DidAttach ()
154{
155    PrivateInitialize(m_process);
156    LocateDYLD ();
157    SetNotificationBreakpoint ();
158}
159
160//------------------------------------------------------------------
161/// Called after attaching a process.
162///
163/// Allow DynamicLoader plug-ins to execute some code after
164/// attaching to a process.
165//------------------------------------------------------------------
166void
167DynamicLoaderMacOSXDYLD::DidLaunch ()
168{
169    PrivateInitialize(m_process);
170    LocateDYLD ();
171    SetNotificationBreakpoint ();
172}
173
174
175//----------------------------------------------------------------------
176// Clear out the state of this class.
177//----------------------------------------------------------------------
178void
179DynamicLoaderMacOSXDYLD::Clear (bool clear_process)
180{
181    Mutex::Locker locker(m_mutex);
182
183    if (m_process->IsAlive() && LLDB_BREAK_ID_IS_VALID(m_break_id))
184        m_process->ClearBreakpointSiteByID(m_break_id);
185
186    if (clear_process)
187        m_process = NULL;
188    m_dyld.Clear(false);
189    m_dyld_all_image_infos_addr = LLDB_INVALID_ADDRESS;
190    m_dyld_all_image_infos.Clear();
191    m_break_id = LLDB_INVALID_BREAK_ID;
192    m_dyld_image_infos.clear();
193}
194
195//----------------------------------------------------------------------
196// Check if we have found DYLD yet
197//----------------------------------------------------------------------
198bool
199DynamicLoaderMacOSXDYLD::DidSetNotificationBreakpoint() const
200{
201    return LLDB_BREAK_ID_IS_VALID (m_break_id);
202}
203
204//----------------------------------------------------------------------
205// Try and figure out where dyld is by first asking the Process
206// if it knows (which currently calls down in the the lldb::Process
207// to get the DYLD info (available on SnowLeopard only). If that fails,
208// then check in the default addresses.
209//----------------------------------------------------------------------
210bool
211DynamicLoaderMacOSXDYLD::LocateDYLD()
212{
213    if (m_dyld_all_image_infos_addr == LLDB_INVALID_ADDRESS)
214        m_dyld_all_image_infos_addr = m_process->GetImageInfoAddress ();
215
216    if (m_dyld_all_image_infos_addr != LLDB_INVALID_ADDRESS)
217    {
218        if (ReadAllImageInfosStructure ())
219        {
220            if (m_dyld_all_image_infos.dyldImageLoadAddress != LLDB_INVALID_ADDRESS)
221                return ReadDYLDInfoFromMemoryAndSetNotificationCallback (m_dyld_all_image_infos.dyldImageLoadAddress);
222            else
223                return ReadDYLDInfoFromMemoryAndSetNotificationCallback (m_dyld_all_image_infos_addr & 0xfffffffffff00000ull);
224        }
225    }
226
227    // Check some default values
228    Module *executable = m_process->GetTarget().GetExecutableModulePointer();
229
230    if (executable)
231    {
232        const ArchSpec &exe_arch = executable->GetArchitecture();
233        if (exe_arch.GetAddressByteSize() == 8)
234        {
235            return ReadDYLDInfoFromMemoryAndSetNotificationCallback(0x7fff5fc00000ull);
236        }
237        else if (exe_arch.GetMachine() == llvm::Triple::arm || exe_arch.GetMachine() == llvm::Triple::thumb)
238        {
239            return ReadDYLDInfoFromMemoryAndSetNotificationCallback(0x2fe00000);
240        }
241        else
242        {
243            return ReadDYLDInfoFromMemoryAndSetNotificationCallback(0x8fe00000);
244        }
245    }
246    return false;
247}
248
249ModuleSP
250DynamicLoaderMacOSXDYLD::FindTargetModuleForDYLDImageInfo (const DYLDImageInfo &image_info, bool can_create, bool *did_create_ptr)
251{
252    if (did_create_ptr)
253        *did_create_ptr = false;
254    ModuleSP module_sp;
255    ModuleList &target_images = m_process->GetTarget().GetImages();
256    const bool image_info_uuid_is_valid = image_info.uuid.IsValid();
257    if (image_info_uuid_is_valid)
258        module_sp = target_images.FindModule(image_info.uuid);
259
260    if (!module_sp)
261    {
262        ArchSpec arch(image_info.GetArchitecture ());
263
264        module_sp = target_images.FindFirstModuleForFileSpec (image_info.file_spec, &arch, NULL);
265
266        if (can_create)
267        {
268            if (module_sp)
269            {
270                if (image_info_uuid_is_valid)
271                {
272                    if (module_sp->GetUUID() != image_info.uuid)
273                        module_sp.reset();
274                }
275                else
276                {
277                    // No UUID, we must rely upon the cached module modification
278                    // time and the modification time of the file on disk
279                    if (module_sp->GetModificationTime() != module_sp->GetFileSpec().GetModificationTime())
280                        module_sp.reset();
281                }
282            }
283
284            if (!module_sp)
285            {
286                module_sp = m_process->GetTarget().GetSharedModule (image_info.file_spec,
287                                                                    arch,
288                                                                    image_info_uuid_is_valid ? &image_info.uuid : NULL);
289                if (did_create_ptr)
290                    *did_create_ptr = module_sp;
291            }
292        }
293    }
294    return module_sp;
295}
296
297//----------------------------------------------------------------------
298// Assume that dyld is in memory at ADDR and try to parse it's load
299// commands
300//----------------------------------------------------------------------
301bool
302DynamicLoaderMacOSXDYLD::ReadDYLDInfoFromMemoryAndSetNotificationCallback(lldb::addr_t addr)
303{
304    DataExtractor data; // Load command data
305    if (ReadMachHeader (addr, &m_dyld.header, &data))
306    {
307        if (m_dyld.header.filetype == llvm::MachO::HeaderFileTypeDynamicLinkEditor)
308        {
309            m_dyld.address = addr;
310            ModuleSP dyld_module_sp;
311            if (ParseLoadCommands (data, m_dyld, &m_dyld.file_spec))
312            {
313                if (m_dyld.file_spec)
314                {
315                    dyld_module_sp = FindTargetModuleForDYLDImageInfo (m_dyld, true, NULL);
316
317                    if (dyld_module_sp)
318                        UpdateImageLoadAddress (dyld_module_sp.get(), m_dyld);
319                }
320            }
321
322            if (m_dyld_all_image_infos_addr == LLDB_INVALID_ADDRESS && dyld_module_sp.get())
323            {
324                static ConstString g_dyld_all_image_infos ("dyld_all_image_infos");
325                const Symbol *symbol = dyld_module_sp->FindFirstSymbolWithNameAndType (g_dyld_all_image_infos, eSymbolTypeData);
326                if (symbol)
327                    m_dyld_all_image_infos_addr = symbol->GetValue().GetLoadAddress(&m_process->GetTarget());
328            }
329
330            // Update all image infos
331            InitializeFromAllImageInfos ();
332
333            // If we didn't have an executable before, but now we do, then the
334            // dyld module shared pointer might be unique and we may need to add
335            // it again (since Target::SetExecutableModule() will clear the
336            // images). So append the dyld module back to the list if it is
337            /// unique!
338            if (dyld_module_sp && m_process->GetTarget().GetImages().AppendIfNeeded (dyld_module_sp))
339                UpdateImageLoadAddress(dyld_module_sp.get(), m_dyld);
340
341            return true;
342        }
343    }
344    return false;
345}
346
347bool
348DynamicLoaderMacOSXDYLD::NeedToLocateDYLD () const
349{
350    return m_dyld_all_image_infos_addr == LLDB_INVALID_ADDRESS;
351}
352
353bool
354DynamicLoaderMacOSXDYLD::UpdateCommPageLoadAddress(Module *module)
355{
356    bool changed = false;
357    if (module)
358    {
359        ObjectFile *image_object_file = module->GetObjectFile();
360        if (image_object_file)
361        {
362            SectionList *section_list = image_object_file->GetSectionList ();
363            if (section_list)
364            {
365                uint32_t num_sections = section_list->GetSize();
366                for (uint32_t i=0; i<num_sections; ++i)
367                {
368                    Section* section = section_list->GetSectionAtIndex (i).get();
369                    if (section)
370                    {
371                        const addr_t new_section_load_addr = section->GetFileAddress ();
372                        const addr_t old_section_load_addr = m_process->GetTarget().GetSectionLoadList().GetSectionLoadAddress (section);
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, section->GetFileAddress ()))
377                                changed = true;
378                        }
379                    }
380                }
381            }
382        }
383    }
384    return changed;
385}
386
387//----------------------------------------------------------------------
388// Update the load addresses for all segments in MODULE using the
389// updated INFO that is passed in.
390//----------------------------------------------------------------------
391bool
392DynamicLoaderMacOSXDYLD::UpdateImageLoadAddress (Module *module, DYLDImageInfo& info)
393{
394    bool changed = false;
395    if (module)
396    {
397        ObjectFile *image_object_file = module->GetObjectFile();
398        if (image_object_file)
399        {
400            SectionList *section_list = image_object_file->GetSectionList ();
401            if (section_list)
402            {
403                // We now know the slide amount, so go through all sections
404                // and update the load addresses with the correct values.
405                uint32_t num_segments = info.segments.size();
406                for (uint32_t i=0; i<num_segments; ++i)
407                {
408                    SectionSP section_sp(section_list->FindSectionByName(info.segments[i].name));
409                    const addr_t new_section_load_addr = info.segments[i].vmaddr + info.slide;
410                    if (section_sp)
411                    {
412                        const addr_t old_section_load_addr = m_process->GetTarget().GetSectionLoadList().GetSectionLoadAddress (section_sp.get());
413                        if (old_section_load_addr == LLDB_INVALID_ADDRESS ||
414                            old_section_load_addr != new_section_load_addr)
415                        {
416                            if (m_process->GetTarget().GetSectionLoadList().SetSectionLoadAddress (section_sp.get(), new_section_load_addr))
417                                changed = true;
418                        }
419                    }
420                    else
421                    {
422                        fprintf (stderr,
423                                 "warning: unable to find and load segment named '%s' at 0x%llx in '%s/%s' in macosx dynamic loader plug-in.\n",
424                                 info.segments[i].name.AsCString("<invalid>"),
425                                 (uint64_t)new_section_load_addr,
426                                 image_object_file->GetFileSpec().GetDirectory().AsCString(),
427                                 image_object_file->GetFileSpec().GetFilename().AsCString());
428                    }
429                }
430            }
431        }
432    }
433    return changed;
434}
435
436//----------------------------------------------------------------------
437// Update the load addresses for all segments in MODULE using the
438// updated INFO that is passed in.
439//----------------------------------------------------------------------
440bool
441DynamicLoaderMacOSXDYLD::UnloadImageLoadAddress (Module *module, DYLDImageInfo& info)
442{
443    bool changed = false;
444    if (module)
445    {
446        ObjectFile *image_object_file = module->GetObjectFile();
447        if (image_object_file)
448        {
449            SectionList *section_list = image_object_file->GetSectionList ();
450            if (section_list)
451            {
452                uint32_t num_segments = info.segments.size();
453                for (uint32_t i=0; i<num_segments; ++i)
454                {
455                    SectionSP section_sp(section_list->FindSectionByName(info.segments[i].name));
456                    if (section_sp)
457                    {
458                        const addr_t old_section_load_addr = info.segments[i].vmaddr + info.slide;
459                        if (m_process->GetTarget().GetSectionLoadList().SetSectionUnloaded (section_sp.get(), old_section_load_addr))
460                            changed = true;
461                    }
462                    else
463                    {
464                        fprintf (stderr,
465                                 "warning: unable to find and unload segment named '%s' in '%s/%s' in macosx dynamic loader plug-in.\n",
466                                 info.segments[i].name.AsCString("<invalid>"),
467                                 image_object_file->GetFileSpec().GetDirectory().AsCString(),
468                                 image_object_file->GetFileSpec().GetFilename().AsCString());
469                    }
470                }
471            }
472        }
473    }
474    return changed;
475}
476
477
478//----------------------------------------------------------------------
479// Static callback function that gets called when our DYLD notification
480// breakpoint gets hit. We update all of our image infos and then
481// let our super class DynamicLoader class decide if we should stop
482// or not (based on global preference).
483//----------------------------------------------------------------------
484bool
485DynamicLoaderMacOSXDYLD::NotifyBreakpointHit (void *baton,
486                                              StoppointCallbackContext *context,
487                                              lldb::user_id_t break_id,
488                                              lldb::user_id_t break_loc_id)
489{
490    // Let the event know that the images have changed
491    // DYLD passes three arguments to the notification breakpoint.
492    // Arg1: enum dyld_image_mode mode - 0 = adding, 1 = removing
493    // Arg2: uint32_t infoCount        - Number of shared libraries added
494    // Arg3: dyld_image_info info[]    - Array of structs of the form:
495    //                                     const struct mach_header *imageLoadAddress
496    //                                     const char               *imageFilePath
497    //                                     uintptr_t                 imageFileModDate (a time_t)
498
499    DynamicLoaderMacOSXDYLD* dyld_instance = (DynamicLoaderMacOSXDYLD*) baton;
500
501    // First step is to see if we've already initialized the all image infos.  If we haven't then this function
502    // will do so and return true.  In the course of initializing the all_image_infos it will read the complete
503    // current state, so we don't need to figure out what has changed from the data passed in to us.
504
505    if (dyld_instance->InitializeFromAllImageInfos())
506        return dyld_instance->GetStopWhenImagesChange();
507
508    Process *process = context->exe_ctx.GetProcessPtr();
509    const lldb::ABISP &abi = process->GetABI();
510    if (abi != NULL)
511    {
512        // Build up the value array to store the three arguments given above, then get the values from the ABI:
513
514        ClangASTContext *clang_ast_context = process->GetTarget().GetScratchClangASTContext();
515        ValueList argument_values;
516        Value input_value;
517
518        void *clang_void_ptr_type = clang_ast_context->GetVoidPtrType(false);
519        void *clang_uint32_type   = clang_ast_context->GetBuiltinTypeForEncodingAndBitSize(lldb::eEncodingUint, 32);
520        input_value.SetValueType (Value::eValueTypeScalar);
521        input_value.SetContext (Value::eContextTypeClangType, clang_uint32_type);
522        argument_values.PushValue(input_value);
523        argument_values.PushValue(input_value);
524        input_value.SetContext (Value::eContextTypeClangType, clang_void_ptr_type);
525        argument_values.PushValue (input_value);
526
527        if (abi->GetArgumentValues (context->exe_ctx.GetThreadRef(), argument_values))
528        {
529            uint32_t dyld_mode = argument_values.GetValueAtIndex(0)->GetScalar().UInt (-1);
530            if (dyld_mode != -1)
531            {
532                // Okay the mode was right, now get the number of elements, and the array of new elements...
533                uint32_t image_infos_count = argument_values.GetValueAtIndex(1)->GetScalar().UInt (-1);
534                if (image_infos_count != -1)
535                {
536                    // Got the number added, now go through the array of added elements, putting out the mach header
537                    // address, and adding the image.
538                    // Note, I'm not putting in logging here, since the AddModules & RemoveModules functions do
539                    // all the logging internally.
540
541                    lldb::addr_t image_infos_addr = argument_values.GetValueAtIndex(2)->GetScalar().ULongLong();
542                    if (dyld_mode == 0)
543                    {
544                        // This is add:
545                        dyld_instance->AddModulesUsingImageInfosAddress (image_infos_addr, image_infos_count);
546                    }
547                    else
548                    {
549                        // This is remove:
550                        dyld_instance->RemoveModulesUsingImageInfosAddress (image_infos_addr, image_infos_count);
551                    }
552
553                }
554            }
555        }
556    }
557
558    // Return true to stop the target, false to just let the target run
559    return dyld_instance->GetStopWhenImagesChange();
560}
561
562bool
563DynamicLoaderMacOSXDYLD::ReadAllImageInfosStructure ()
564{
565    Mutex::Locker locker(m_mutex);
566
567    // the all image infos is already valid for this process stop ID
568    if (m_process->GetStopID() == m_dyld_all_image_infos_stop_id)
569        return true;
570
571    m_dyld_all_image_infos.Clear();
572    if (m_dyld_all_image_infos_addr != LLDB_INVALID_ADDRESS)
573    {
574        ByteOrder byte_order = m_process->GetTarget().GetArchitecture().GetByteOrder();
575        uint32_t addr_size = 4;
576        if (m_dyld_all_image_infos_addr > UINT32_MAX)
577            addr_size = 8;
578
579        uint8_t buf[256];
580        DataExtractor data (buf, sizeof(buf), byte_order, addr_size);
581        uint32_t offset = 0;
582
583        const size_t count_v2 =  sizeof (uint32_t) + // version
584                                 sizeof (uint32_t) + // infoArrayCount
585                                 addr_size +         // infoArray
586                                 addr_size +         // notification
587                                 addr_size +         // processDetachedFromSharedRegion + libSystemInitialized + pad
588                                 addr_size;          // dyldImageLoadAddress
589        const size_t count_v11 = count_v2 +
590                                 addr_size +         // jitInfo
591                                 addr_size +         // dyldVersion
592                                 addr_size +         // errorMessage
593                                 addr_size +         // terminationFlags
594                                 addr_size +         // coreSymbolicationShmPage
595                                 addr_size +         // systemOrderFlag
596                                 addr_size +         // uuidArrayCount
597                                 addr_size +         // uuidArray
598                                 addr_size +         // dyldAllImageInfosAddress
599                                 addr_size +         // initialImageCount
600                                 addr_size +         // errorKind
601                                 addr_size +         // errorClientOfDylibPath
602                                 addr_size +         // errorTargetDylibPath
603                                 addr_size;          // errorSymbol
604        assert (sizeof (buf) >= count_v11);
605
606        int count;
607        Error error;
608        if (m_process->ReadMemory (m_dyld_all_image_infos_addr, buf, 4, error) == 4)
609        {
610            m_dyld_all_image_infos.version = data.GetU32(&offset);
611            // If anything in the high byte is set, we probably got the byte
612            // order incorrect (the process might not have it set correctly
613            // yet due to attaching to a program without a specified file).
614            if (m_dyld_all_image_infos.version & 0xff000000)
615            {
616                // We have guessed the wrong byte order. Swap it and try
617                // reading the version again.
618                if (byte_order == eByteOrderLittle)
619                    byte_order = eByteOrderBig;
620                else
621                    byte_order = eByteOrderLittle;
622
623                data.SetByteOrder (byte_order);
624                offset = 0;
625                m_dyld_all_image_infos.version = data.GetU32(&offset);
626            }
627        }
628        else
629        {
630            return false;
631        }
632
633        if (m_dyld_all_image_infos.version >= 11)
634            count = count_v11;
635        else
636            count = count_v2;
637
638        const size_t bytes_read = m_process->ReadMemory (m_dyld_all_image_infos_addr, buf, count, error);
639        if (bytes_read == count)
640        {
641            offset = 0;
642            m_dyld_all_image_infos.version = data.GetU32(&offset);
643            m_dyld_all_image_infos.dylib_info_count = data.GetU32(&offset);
644            m_dyld_all_image_infos.dylib_info_addr = data.GetPointer(&offset);
645            m_dyld_all_image_infos.notification = data.GetPointer(&offset);
646            m_dyld_all_image_infos.processDetachedFromSharedRegion = data.GetU8(&offset);
647            m_dyld_all_image_infos.libSystemInitialized = data.GetU8(&offset);
648            // Adjust for padding.
649            offset += addr_size - 2;
650            m_dyld_all_image_infos.dyldImageLoadAddress = data.GetPointer(&offset);
651            if (m_dyld_all_image_infos.version >= 11)
652            {
653                offset += addr_size * 8;
654                uint64_t dyld_all_image_infos_addr = data.GetPointer(&offset);
655
656                // When we started, we were given the actual address of the all_image_infos
657                // struct (probably via TASK_DYLD_INFO) in memory - this address is stored in
658                // m_dyld_all_image_infos_addr and is the most accurate address we have.
659
660                // We read the dyld_all_image_infos struct from memory; it contains its own address.
661                // If the address in the struct does not match the actual address,
662                // the dyld we're looking at has been loaded at a different location (slid) from
663                // where it intended to load.  The addresses in the dyld_all_image_infos struct
664                // are the original, non-slid addresses, and need to be adjusted.  Most importantly
665                // the address of dyld and the notification address need to be adjusted.
666
667                if (dyld_all_image_infos_addr != m_dyld_all_image_infos_addr)
668                {
669                    uint64_t image_infos_offset = dyld_all_image_infos_addr - m_dyld_all_image_infos.dyldImageLoadAddress;
670                    uint64_t notification_offset = m_dyld_all_image_infos.notification - m_dyld_all_image_infos.dyldImageLoadAddress;
671                    m_dyld_all_image_infos.dyldImageLoadAddress = m_dyld_all_image_infos_addr - image_infos_offset;
672                    m_dyld_all_image_infos.notification = m_dyld_all_image_infos.dyldImageLoadAddress + notification_offset;
673                }
674            }
675            m_dyld_all_image_infos_stop_id = m_process->GetStopID();
676            return true;
677        }
678    }
679    return false;
680}
681
682
683bool
684DynamicLoaderMacOSXDYLD::AddModulesUsingImageInfosAddress (lldb::addr_t image_infos_addr, uint32_t image_infos_count)
685{
686    DYLDImageInfo::collection image_infos;
687    LogSP log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_DYNAMIC_LOADER));
688    if (log)
689        log->Printf ("Adding %d modules.\n", image_infos_count);
690
691    Mutex::Locker locker(m_mutex);
692    if (m_process->GetStopID() == m_dyld_image_infos_stop_id)
693        return true;
694
695    if (!ReadImageInfos (image_infos_addr, image_infos_count, image_infos))
696        return false;
697
698    UpdateImageInfosHeaderAndLoadCommands (image_infos, image_infos_count, false);
699    bool return_value = AddModulesUsingImageInfos (image_infos);
700    m_dyld_image_infos_stop_id = m_process->GetStopID();
701    return return_value;
702}
703
704// Adds the modules in image_infos to m_dyld_image_infos.
705// NB don't call this passing in m_dyld_image_infos.
706
707bool
708DynamicLoaderMacOSXDYLD::AddModulesUsingImageInfos (DYLDImageInfo::collection &image_infos)
709{
710    // Now add these images to the main list.
711    ModuleList loaded_module_list;
712    LogSP log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_DYNAMIC_LOADER));
713
714    for (uint32_t idx = 0; idx < image_infos.size(); ++idx)
715    {
716        if (log)
717        {
718            log->Printf ("Adding new image at address=0x%16.16llx.", image_infos[idx].address);
719            image_infos[idx].PutToLog (log.get());
720        }
721
722        m_dyld_image_infos.push_back(image_infos[idx]);
723
724        ModuleSP image_module_sp (FindTargetModuleForDYLDImageInfo (image_infos[idx], true, NULL));
725
726        if (image_module_sp)
727        {
728            if (image_infos[idx].header.filetype == llvm::MachO::HeaderFileTypeDynamicLinkEditor)
729                image_module_sp->SetIsDynamicLinkEditor (true);
730
731            ObjectFile *objfile = image_module_sp->GetObjectFile ();
732            if (objfile)
733            {
734                SectionList *sections = objfile->GetSectionList();
735                if (sections)
736                {
737                    ConstString commpage_dbstr("__commpage");
738                    Section *commpage_section = sections->FindSectionByName(commpage_dbstr).get();
739                    if (commpage_section)
740                    {
741                        ModuleList& target_images = m_process->GetTarget().GetImages();
742                        const FileSpec objfile_file_spec = objfile->GetFileSpec();
743                        ArchSpec arch (image_infos[idx].GetArchitecture ());
744                        ModuleSP commpage_image_module_sp(target_images.FindFirstModuleForFileSpec (objfile_file_spec,
745                                                                                                    &arch,
746                                                                                                    &commpage_dbstr));
747                        if (!commpage_image_module_sp)
748                        {
749                            commpage_image_module_sp
750                                    = m_process->GetTarget().GetSharedModule (image_infos[idx].file_spec,
751                                                                              arch,
752                                                                              NULL,
753                                                                              &commpage_dbstr,
754                                                                              objfile->GetOffset() + commpage_section->GetFileOffset());
755                        }
756                        if (commpage_image_module_sp)
757                            UpdateCommPageLoadAddress (commpage_image_module_sp.get());
758                    }
759                }
760            }
761
762            // UpdateImageLoadAddress will return true if any segments
763            // change load address. We need to check this so we don't
764            // mention that all loaded shared libraries are newly loaded
765            // each time we hit out dyld breakpoint since dyld will list all
766            // shared libraries each time.
767            if (UpdateImageLoadAddress (image_module_sp.get(), image_infos[idx]))
768            {
769                loaded_module_list.AppendIfNeeded (image_module_sp);
770            }
771        }
772    }
773
774    if (loaded_module_list.GetSize() > 0)
775    {
776        // FIXME: This should really be in the Runtime handlers class, which should get
777        // called by the target's ModulesDidLoad, but we're doing it all locally for now
778        // to save time.
779        // Also, I'm assuming there can be only one libobjc dylib loaded...
780
781        ObjCLanguageRuntime *objc_runtime = m_process->GetObjCLanguageRuntime();
782        if (objc_runtime != NULL && !objc_runtime->HasReadObjCLibrary())
783        {
784            size_t num_modules = loaded_module_list.GetSize();
785            for (int i = 0; i < num_modules; i++)
786            {
787                if (objc_runtime->IsModuleObjCLibrary (loaded_module_list.GetModuleAtIndex (i)))
788                {
789                    objc_runtime->ReadObjCLibrary (loaded_module_list.GetModuleAtIndex (i));
790                    break;
791                }
792            }
793        }
794        if (log)
795            loaded_module_list.LogUUIDAndPaths (log, "DynamicLoaderMacOSXDYLD::ModulesDidLoad");
796        m_process->GetTarget().ModulesDidLoad (loaded_module_list);
797    }
798    return true;
799}
800
801bool
802DynamicLoaderMacOSXDYLD::RemoveModulesUsingImageInfosAddress (lldb::addr_t image_infos_addr, uint32_t image_infos_count)
803{
804    DYLDImageInfo::collection image_infos;
805    LogSP log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_DYNAMIC_LOADER));
806
807    Mutex::Locker locker(m_mutex);
808    if (m_process->GetStopID() == m_dyld_image_infos_stop_id)
809        return true;
810
811    // First read in the image_infos for the removed modules, and their headers & load commands.
812    if (!ReadImageInfos (image_infos_addr, image_infos_count, image_infos))
813    {
814        if (log)
815            log->PutCString ("Failed reading image infos array.");
816        return false;
817    }
818
819    if (log)
820        log->Printf ("Removing %d modules.", image_infos_count);
821
822    ModuleList unloaded_module_list;
823    for (uint32_t idx = 0; idx < image_infos.size(); ++idx)
824    {
825        if (log)
826        {
827            log->Printf ("Removing module at address=0x%16.16llx.", image_infos[idx].address);
828            image_infos[idx].PutToLog (log.get());
829        }
830
831        // Remove this image_infos from the m_all_image_infos.  We do the comparision by address
832        // rather than by file spec because we can have many modules with the same "file spec" in the
833        // case that they are modules loaded from memory.
834        //
835        // Also copy over the uuid from the old entry to the removed entry so we can
836        // use it to lookup the module in the module list.
837
838        DYLDImageInfo::collection::iterator pos, end = m_dyld_image_infos.end();
839        for (pos = m_dyld_image_infos.begin(); pos != end; pos++)
840        {
841            if (image_infos[idx].address == (*pos).address)
842            {
843                image_infos[idx].uuid = (*pos).uuid;
844
845                // Add the module from this image_info to the "unloaded_module_list".  We'll remove them all at
846                // one go later on.
847
848                ModuleSP unload_image_module_sp (FindTargetModuleForDYLDImageInfo (image_infos[idx], false, NULL));
849                if (unload_image_module_sp.get())
850                {
851                    // When we unload, be sure to use the image info from the old list,
852                    // since that has sections correctly filled in.
853                    UnloadImageLoadAddress (unload_image_module_sp.get(), *pos);
854                    unloaded_module_list.AppendIfNeeded (unload_image_module_sp);
855                }
856                else
857                {
858                    if (log)
859                    {
860                        log->Printf ("Could not find module for unloading info entry:");
861                        image_infos[idx].PutToLog(log.get());
862                    }
863                }
864
865                // Then remove it from the m_dyld_image_infos:
866
867                m_dyld_image_infos.erase(pos);
868                break;
869            }
870        }
871
872        if (pos == end)
873        {
874            if (log)
875            {
876                log->Printf ("Could not find image_info entry for unloading image:");
877                image_infos[idx].PutToLog(log.get());
878            }
879        }
880    }
881    if (unloaded_module_list.GetSize() > 0)
882    {
883        if (log)
884        {
885            log->PutCString("Unloaded:");
886            unloaded_module_list.LogUUIDAndPaths (log, "DynamicLoaderMacOSXDYLD::ModulesDidUnload");
887        }
888        m_process->GetTarget().ModulesDidUnload (unloaded_module_list);
889    }
890    m_dyld_image_infos_stop_id = m_process->GetStopID();
891    return true;
892}
893
894bool
895DynamicLoaderMacOSXDYLD::ReadImageInfos (lldb::addr_t image_infos_addr,
896                                         uint32_t image_infos_count,
897                                         DYLDImageInfo::collection &image_infos)
898{
899    const ByteOrder endian = m_dyld.GetByteOrder();
900    const uint32_t addr_size = m_dyld.GetAddressByteSize();
901
902    image_infos.resize(image_infos_count);
903    const size_t count = image_infos.size() * 3 * addr_size;
904    DataBufferHeap info_data(count, 0);
905    Error error;
906    const size_t bytes_read = m_process->ReadMemory (image_infos_addr,
907                                                     info_data.GetBytes(),
908                                                     info_data.GetByteSize(),
909                                                     error);
910    if (bytes_read == count)
911    {
912        uint32_t info_data_offset = 0;
913        DataExtractor info_data_ref(info_data.GetBytes(), info_data.GetByteSize(), endian, addr_size);
914        for (int i = 0; i < image_infos.size() && info_data_ref.ValidOffset(info_data_offset); i++)
915        {
916            image_infos[i].address = info_data_ref.GetPointer(&info_data_offset);
917            lldb::addr_t path_addr = info_data_ref.GetPointer(&info_data_offset);
918            image_infos[i].mod_date = info_data_ref.GetPointer(&info_data_offset);
919
920            char raw_path[PATH_MAX];
921            m_process->ReadCStringFromMemory (path_addr, raw_path, sizeof(raw_path));
922            // don't resolve the path
923            const bool resolve_path = false;
924            image_infos[i].file_spec.SetFile(raw_path, resolve_path);
925        }
926        return true;
927    }
928    else
929    {
930        return false;
931    }
932}
933
934//----------------------------------------------------------------------
935// If we have found where the "_dyld_all_image_infos" lives in memory,
936// read the current info from it, and then update all image load
937// addresses (or lack thereof).  Only do this if this is the first time
938// we're reading the dyld infos.  Return true if we actually read anything,
939// and false otherwise.
940//----------------------------------------------------------------------
941bool
942DynamicLoaderMacOSXDYLD::InitializeFromAllImageInfos ()
943{
944    LogSP log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_DYNAMIC_LOADER));
945
946    Mutex::Locker locker(m_mutex);
947    if (m_process->GetStopID() == m_dyld_image_infos_stop_id
948          || m_dyld_image_infos.size() != 0)
949        return false;
950
951    if (ReadAllImageInfosStructure ())
952    {
953        // Nothing to load or unload?
954        if (m_dyld_all_image_infos.dylib_info_count == 0)
955            return true;
956
957        if (m_dyld_all_image_infos.dylib_info_addr == 0)
958        {
959            // DYLD is updating the images now.  So we should say we have no images, and then we'll
960            // figure it out when we hit the added breakpoint.
961            return false;
962        }
963        else
964        {
965            if (!AddModulesUsingImageInfosAddress (m_dyld_all_image_infos.dylib_info_addr,
966                                                   m_dyld_all_image_infos.dylib_info_count))
967            {
968                DEBUG_PRINTF( "unable to read all data for all_dylib_infos.");
969                m_dyld_image_infos.clear();
970            }
971        }
972
973        // Now we have one more bit of business.  If there is a library left in the images for our target that
974        // doesn't have a load address, then it must be something that we were expecting to load (for instance we
975        // read a load command for it) but it didn't in fact load - probably because DYLD_*_PATH pointed
976        // to an equivalent version.  We don't want it to stay in the target's module list or it will confuse
977        // us, so unload it here.
978        Target &target = m_process->GetTarget();
979        ModuleList &modules = target.GetImages();
980        ModuleList not_loaded_modules;
981        size_t num_modules = modules.GetSize();
982        for (size_t i = 0; i < num_modules; i++)
983        {
984            ModuleSP module_sp = modules.GetModuleAtIndex(i);
985            if (!module_sp->IsLoadedInTarget (&target))
986            {
987                if (log)
988                {
989                    StreamString s;
990                    module_sp->GetDescription (&s);
991                    log->Printf ("Unloading pre-run module: %s.", s.GetData ());
992                }
993                not_loaded_modules.Append (module_sp);
994            }
995        }
996
997        if (not_loaded_modules.GetSize() != 0)
998        {
999            target.ModulesDidUnload(not_loaded_modules);
1000        }
1001
1002        return true;
1003    }
1004    else
1005        return false;
1006}
1007
1008//----------------------------------------------------------------------
1009// Read a mach_header at ADDR into HEADER, and also fill in the load
1010// command data into LOAD_COMMAND_DATA if it is non-NULL.
1011//
1012// Returns true if we succeed, false if we fail for any reason.
1013//----------------------------------------------------------------------
1014bool
1015DynamicLoaderMacOSXDYLD::ReadMachHeader (lldb::addr_t addr, llvm::MachO::mach_header *header, DataExtractor *load_command_data)
1016{
1017    DataBufferHeap header_bytes(sizeof(llvm::MachO::mach_header), 0);
1018    Error error;
1019    size_t bytes_read = m_process->ReadMemory (addr,
1020                                               header_bytes.GetBytes(),
1021                                               header_bytes.GetByteSize(),
1022                                               error);
1023    if (bytes_read == sizeof(llvm::MachO::mach_header))
1024    {
1025        uint32_t offset = 0;
1026        ::memset (header, 0, sizeof(llvm::MachO::mach_header));
1027
1028        // Get the magic byte unswapped so we can figure out what we are dealing with
1029        DataExtractor data(header_bytes.GetBytes(), header_bytes.GetByteSize(), lldb::endian::InlHostByteOrder(), 4);
1030        header->magic = data.GetU32(&offset);
1031        lldb::addr_t load_cmd_addr = addr;
1032        data.SetByteOrder(DynamicLoaderMacOSXDYLD::GetByteOrderFromMagic(header->magic));
1033        switch (header->magic)
1034        {
1035        case llvm::MachO::HeaderMagic32:
1036        case llvm::MachO::HeaderMagic32Swapped:
1037            data.SetAddressByteSize(4);
1038            load_cmd_addr += sizeof(llvm::MachO::mach_header);
1039            break;
1040
1041        case llvm::MachO::HeaderMagic64:
1042        case llvm::MachO::HeaderMagic64Swapped:
1043            data.SetAddressByteSize(8);
1044            load_cmd_addr += sizeof(llvm::MachO::mach_header_64);
1045            break;
1046
1047        default:
1048            return false;
1049        }
1050
1051        // Read the rest of dyld's mach header
1052        if (data.GetU32(&offset, &header->cputype, (sizeof(llvm::MachO::mach_header)/sizeof(uint32_t)) - 1))
1053        {
1054            if (load_command_data == NULL)
1055                return true; // We were able to read the mach_header and weren't asked to read the load command bytes
1056
1057            DataBufferSP load_cmd_data_sp(new DataBufferHeap(header->sizeofcmds, 0));
1058
1059            size_t load_cmd_bytes_read = m_process->ReadMemory (load_cmd_addr,
1060                                                                load_cmd_data_sp->GetBytes(),
1061                                                                load_cmd_data_sp->GetByteSize(),
1062                                                                error);
1063
1064            if (load_cmd_bytes_read == header->sizeofcmds)
1065            {
1066                // Set the load command data and also set the correct endian
1067                // swap settings and the correct address size
1068                load_command_data->SetData(load_cmd_data_sp, 0, header->sizeofcmds);
1069                load_command_data->SetByteOrder(data.GetByteOrder());
1070                load_command_data->SetAddressByteSize(data.GetAddressByteSize());
1071                return true; // We successfully read the mach_header and the load command data
1072            }
1073
1074            return false; // We weren't able to read the load command data
1075        }
1076    }
1077    return false; // We failed the read the mach_header
1078}
1079
1080
1081//----------------------------------------------------------------------
1082// Parse the load commands for an image
1083//----------------------------------------------------------------------
1084uint32_t
1085DynamicLoaderMacOSXDYLD::ParseLoadCommands (const DataExtractor& data, DYLDImageInfo& dylib_info, FileSpec *lc_id_dylinker)
1086{
1087    uint32_t offset = 0;
1088    uint32_t cmd_idx;
1089    Segment segment;
1090    dylib_info.Clear (true);
1091
1092    for (cmd_idx = 0; cmd_idx < dylib_info.header.ncmds; cmd_idx++)
1093    {
1094        // Clear out any load command specific data from DYLIB_INFO since
1095        // we are about to read it.
1096
1097        if (data.ValidOffsetForDataOfSize (offset, sizeof(llvm::MachO::load_command)))
1098        {
1099            llvm::MachO::load_command load_cmd;
1100            uint32_t load_cmd_offset = offset;
1101            load_cmd.cmd = data.GetU32 (&offset);
1102            load_cmd.cmdsize = data.GetU32 (&offset);
1103            switch (load_cmd.cmd)
1104            {
1105            case llvm::MachO::LoadCommandSegment32:
1106                {
1107                    segment.name.SetTrimmedCStringWithLength ((const char *)data.GetData(&offset, 16), 16);
1108                    // We are putting 4 uint32_t values 4 uint64_t values so
1109                    // we have to use multiple 32 bit gets below.
1110                    segment.vmaddr = data.GetU32 (&offset);
1111                    segment.vmsize = data.GetU32 (&offset);
1112                    segment.fileoff = data.GetU32 (&offset);
1113                    segment.filesize = data.GetU32 (&offset);
1114                    // Extract maxprot, initprot, nsects and flags all at once
1115                    data.GetU32(&offset, &segment.maxprot, 4);
1116                    dylib_info.segments.push_back (segment);
1117                }
1118                break;
1119
1120            case llvm::MachO::LoadCommandSegment64:
1121                {
1122                    segment.name.SetTrimmedCStringWithLength ((const char *)data.GetData(&offset, 16), 16);
1123                    // Extract vmaddr, vmsize, fileoff, and filesize all at once
1124                    data.GetU64(&offset, &segment.vmaddr, 4);
1125                    // Extract maxprot, initprot, nsects and flags all at once
1126                    data.GetU32(&offset, &segment.maxprot, 4);
1127                    dylib_info.segments.push_back (segment);
1128                }
1129                break;
1130
1131            case llvm::MachO::LoadCommandDynamicLinkerIdent:
1132                if (lc_id_dylinker)
1133                {
1134                    uint32_t name_offset = load_cmd_offset + data.GetU32 (&offset);
1135                    const char *path = data.PeekCStr (name_offset);
1136                    lc_id_dylinker->SetFile (path, true);
1137                }
1138                break;
1139
1140            case llvm::MachO::LoadCommandUUID:
1141                dylib_info.uuid.SetBytes(data.GetData (&offset, 16));
1142                break;
1143
1144            default:
1145                break;
1146            }
1147            // Set offset to be the beginning of the next load command.
1148            offset = load_cmd_offset + load_cmd.cmdsize;
1149        }
1150    }
1151
1152    // All sections listed in the dyld image info structure will all
1153    // either be fixed up already, or they will all be off by a single
1154    // slide amount that is determined by finding the first segment
1155    // that is at file offset zero which also has bytes (a file size
1156    // that is greater than zero) in the object file.
1157
1158    // Determine the slide amount (if any)
1159    const size_t num_sections = dylib_info.segments.size();
1160    for (size_t i = 0; i < num_sections; ++i)
1161    {
1162        // Iterate through the object file sections to find the
1163        // first section that starts of file offset zero and that
1164        // has bytes in the file...
1165        if (dylib_info.segments[i].fileoff == 0 && dylib_info.segments[i].filesize > 0)
1166        {
1167            dylib_info.slide = dylib_info.address - dylib_info.segments[i].vmaddr;
1168            // We have found the slide amount, so we can exit
1169            // this for loop.
1170            break;
1171        }
1172    }
1173    return cmd_idx;
1174}
1175
1176//----------------------------------------------------------------------
1177// Read the mach_header and load commands for each image that the
1178// _dyld_all_image_infos structure points to and cache the results.
1179//----------------------------------------------------------------------
1180
1181void
1182DynamicLoaderMacOSXDYLD::UpdateImageInfosHeaderAndLoadCommands(DYLDImageInfo::collection &image_infos,
1183                                                               uint32_t infos_count,
1184                                                               bool update_executable)
1185{
1186    uint32_t exe_idx = UINT32_MAX;
1187    LogSP log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_DYNAMIC_LOADER));
1188    // Read any UUID values that we can get
1189    for (uint32_t i = 0; i < infos_count; i++)
1190    {
1191        if (!image_infos[i].UUIDValid())
1192        {
1193            DataExtractor data; // Load command data
1194            if (!ReadMachHeader (image_infos[i].address, &image_infos[i].header, &data))
1195                continue;
1196
1197            ParseLoadCommands (data, image_infos[i], NULL);
1198
1199            if (image_infos[i].header.filetype == llvm::MachO::HeaderFileTypeExecutable)
1200                exe_idx = i;
1201
1202        }
1203    }
1204
1205    if (exe_idx < image_infos.size())
1206    {
1207        const bool can_create = true;
1208        ModuleSP exe_module_sp (FindTargetModuleForDYLDImageInfo (image_infos[exe_idx], can_create, NULL));
1209
1210        if (!exe_module_sp)
1211        {
1212            ArchSpec exe_arch_spec (image_infos[exe_idx].GetArchitecture ());
1213            exe_module_sp = m_process->GetTarget().GetSharedModule (image_infos[exe_idx].file_spec,
1214                                                                    exe_arch_spec,
1215                                                                    &image_infos[exe_idx].uuid);
1216        }
1217
1218        if (exe_module_sp)
1219        {
1220            if (exe_module_sp.get() != m_process->GetTarget().GetExecutableModulePointer())
1221            {
1222                // Don't load dependent images since we are in dyld where we will know
1223                // and find out about all images that are loaded
1224                const bool get_dependent_images = false;
1225                m_process->GetTarget().SetExecutableModule (exe_module_sp,
1226                                                            get_dependent_images);
1227            }
1228        }
1229    }
1230}
1231
1232//----------------------------------------------------------------------
1233// Dump a Segment to the file handle provided.
1234//----------------------------------------------------------------------
1235void
1236DynamicLoaderMacOSXDYLD::Segment::PutToLog (Log *log, lldb::addr_t slide) const
1237{
1238    if (log)
1239    {
1240        if (slide == 0)
1241            log->Printf ("\t\t%16s [0x%16.16llx - 0x%16.16llx)",
1242                         name.AsCString(""),
1243                         vmaddr + slide,
1244                         vmaddr + slide + vmsize);
1245        else
1246            log->Printf ("\t\t%16s [0x%16.16llx - 0x%16.16llx) slide = 0x%llx",
1247                         name.AsCString(""),
1248                         vmaddr + slide,
1249                         vmaddr + slide + vmsize,
1250                         slide);
1251    }
1252}
1253
1254const DynamicLoaderMacOSXDYLD::Segment *
1255DynamicLoaderMacOSXDYLD::DYLDImageInfo::FindSegment (const ConstString &name) const
1256{
1257    const size_t num_segments = segments.size();
1258    for (size_t i=0; i<num_segments; ++i)
1259    {
1260        if (segments[i].name == name)
1261            return &segments[i];
1262    }
1263    return NULL;
1264}
1265
1266
1267//----------------------------------------------------------------------
1268// Dump an image info structure to the file handle provided.
1269//----------------------------------------------------------------------
1270void
1271DynamicLoaderMacOSXDYLD::DYLDImageInfo::PutToLog (Log *log) const
1272{
1273    if (log == NULL)
1274        return;
1275    uint8_t *u = (uint8_t *)uuid.GetBytes();
1276
1277    if (address == LLDB_INVALID_ADDRESS)
1278    {
1279        if (u)
1280        {
1281            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)",
1282                        mod_date,
1283                        u[ 0], u[ 1], u[ 2], u[ 3],
1284                        u[ 4], u[ 5], u[ 6], u[ 7],
1285                        u[ 8], u[ 9], u[10], u[11],
1286                        u[12], u[13], u[14], u[15],
1287                        file_spec.GetDirectory().AsCString(),
1288                        file_spec.GetFilename().AsCString());
1289        }
1290        else
1291            log->Printf("\t                           modtime=0x%8.8llx path='%s/%s' (UNLOADED)",
1292                        mod_date,
1293                        file_spec.GetDirectory().AsCString(),
1294                        file_spec.GetFilename().AsCString());
1295    }
1296    else
1297    {
1298        if (u)
1299        {
1300            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'",
1301                        address,
1302                        mod_date,
1303                        u[ 0], u[ 1], u[ 2], u[ 3],
1304                        u[ 4], u[ 5], u[ 6], u[ 7],
1305                        u[ 8], u[ 9], u[10], u[11],
1306                        u[12], u[13], u[14], u[15],
1307                        file_spec.GetDirectory().AsCString(),
1308                        file_spec.GetFilename().AsCString());
1309        }
1310        else
1311        {
1312            log->Printf("\taddress=0x%16.16llx modtime=0x%8.8llx path='%s/%s'",
1313                        address,
1314                        mod_date,
1315                        file_spec.GetDirectory().AsCString(),
1316                        file_spec.GetFilename().AsCString());
1317
1318        }
1319        for (uint32_t i=0; i<segments.size(); ++i)
1320            segments[i].PutToLog(log, slide);
1321    }
1322}
1323
1324//----------------------------------------------------------------------
1325// Dump the _dyld_all_image_infos members and all current image infos
1326// that we have parsed to the file handle provided.
1327//----------------------------------------------------------------------
1328void
1329DynamicLoaderMacOSXDYLD::PutToLog(Log *log) const
1330{
1331    if (log == NULL)
1332        return;
1333
1334    Mutex::Locker locker(m_mutex);
1335    log->Printf("dyld_all_image_infos = { version=%d, count=%d, addr=0x%8.8llx, notify=0x%8.8llx }",
1336                    m_dyld_all_image_infos.version,
1337                    m_dyld_all_image_infos.dylib_info_count,
1338                    (uint64_t)m_dyld_all_image_infos.dylib_info_addr,
1339                    (uint64_t)m_dyld_all_image_infos.notification);
1340    size_t i;
1341    const size_t count = m_dyld_image_infos.size();
1342    if (count > 0)
1343    {
1344        log->PutCString("Loaded:");
1345        for (i = 0; i<count; i++)
1346            m_dyld_image_infos[i].PutToLog(log);
1347    }
1348}
1349
1350void
1351DynamicLoaderMacOSXDYLD::PrivateInitialize(Process *process)
1352{
1353    DEBUG_PRINTF("DynamicLoaderMacOSXDYLD::%s() process state = %s\n", __FUNCTION__, StateAsCString(m_process->GetState()));
1354    Clear(true);
1355    m_process = process;
1356    m_process->GetTarget().GetSectionLoadList().Clear();
1357}
1358
1359bool
1360DynamicLoaderMacOSXDYLD::SetNotificationBreakpoint ()
1361{
1362    DEBUG_PRINTF("DynamicLoaderMacOSXDYLD::%s() process state = %s\n", __FUNCTION__, StateAsCString(m_process->GetState()));
1363    if (m_break_id == LLDB_INVALID_BREAK_ID)
1364    {
1365        if (m_dyld_all_image_infos.notification != LLDB_INVALID_ADDRESS)
1366        {
1367            Address so_addr;
1368            // Set the notification breakpoint and install a breakpoint
1369            // callback function that will get called each time the
1370            // breakpoint gets hit. We will use this to track when shared
1371            // libraries get loaded/unloaded.
1372
1373            if (m_process->GetTarget().GetSectionLoadList().ResolveLoadAddress(m_dyld_all_image_infos.notification, so_addr))
1374            {
1375                Breakpoint *dyld_break = m_process->GetTarget().CreateBreakpoint (so_addr, true).get();
1376                dyld_break->SetCallback (DynamicLoaderMacOSXDYLD::NotifyBreakpointHit, this, true);
1377                m_break_id = dyld_break->GetID();
1378            }
1379        }
1380    }
1381    return m_break_id != LLDB_INVALID_BREAK_ID;
1382}
1383
1384//----------------------------------------------------------------------
1385// Member function that gets called when the process state changes.
1386//----------------------------------------------------------------------
1387void
1388DynamicLoaderMacOSXDYLD::PrivateProcessStateChanged (Process *process, StateType state)
1389{
1390    DEBUG_PRINTF("DynamicLoaderMacOSXDYLD::%s(%s)\n", __FUNCTION__, StateAsCString(state));
1391    switch (state)
1392    {
1393    case eStateConnected:
1394    case eStateAttaching:
1395    case eStateLaunching:
1396    case eStateInvalid:
1397    case eStateUnloaded:
1398    case eStateExited:
1399    case eStateDetached:
1400        Clear(false);
1401        break;
1402
1403    case eStateStopped:
1404        // Keep trying find dyld and set our notification breakpoint each time
1405        // we stop until we succeed
1406        if (!DidSetNotificationBreakpoint () && m_process->IsAlive())
1407        {
1408            if (NeedToLocateDYLD ())
1409                LocateDYLD ();
1410
1411            SetNotificationBreakpoint ();
1412        }
1413        break;
1414
1415    case eStateRunning:
1416    case eStateStepping:
1417    case eStateCrashed:
1418    case eStateSuspended:
1419        break;
1420
1421    default:
1422        break;
1423    }
1424}
1425
1426// This bit in the n_desc field of the mach file means that this is a
1427// stub that runs arbitrary code to determine the trampoline target.
1428// We've established a naming convention with the CoreOS folks for the
1429// equivalent symbols they will use for this (which the objc guys didn't follow...)
1430// For now we'll just look for all symbols matching that naming convention...
1431
1432#define MACH_O_N_SYMBOL_RESOLVER 0x100
1433
1434ThreadPlanSP
1435DynamicLoaderMacOSXDYLD::GetStepThroughTrampolinePlan (Thread &thread, bool stop_others)
1436{
1437    ThreadPlanSP thread_plan_sp;
1438    StackFrame *current_frame = thread.GetStackFrameAtIndex(0).get();
1439    const SymbolContext &current_context = current_frame->GetSymbolContext(eSymbolContextSymbol);
1440    Symbol *current_symbol = current_context.symbol;
1441    LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP));
1442
1443    if (current_symbol != NULL)
1444    {
1445        if (current_symbol->IsTrampoline())
1446        {
1447            const ConstString &trampoline_name = current_symbol->GetMangled().GetName(Mangled::ePreferMangled);
1448
1449            if (trampoline_name)
1450            {
1451                SymbolContextList target_symbols;
1452                ModuleList &images = thread.GetProcess().GetTarget().GetImages();
1453
1454                images.FindSymbolsWithNameAndType(trampoline_name, eSymbolTypeCode, target_symbols);
1455
1456                size_t num_original_symbols = target_symbols.GetSize();
1457                // FIXME: The resolver symbol is only valid in object files.  In binaries it is reused for the
1458                // shared library slot number.  So we'll have to look this up in the dyld info.
1459                // For now, just turn this off.
1460
1461                // bool orig_is_resolver = (current_symbol->GetFlags() & MACH_O_N_SYMBOL_RESOLVER) == MACH_O_N_SYMBOL_RESOLVER;
1462                bool orig_is_resolver = false;
1463
1464                if (num_original_symbols > 0)
1465                {
1466                    // We found symbols that look like they are the targets to our symbol.  Now look through the
1467                    // modules containing our symbols to see if there are any for our symbol.
1468
1469                    ModuleList modules_to_search;
1470
1471                    for (size_t i = 0; i < num_original_symbols; i++)
1472                    {
1473                        SymbolContext sc;
1474                        target_symbols.GetContextAtIndex(i, sc);
1475
1476                        Module* module_to_add = sc.symbol->CalculateSymbolContextModule();
1477                        if (module_to_add)
1478                             modules_to_search.AppendIfNeeded(static_cast<ModuleSP>(module_to_add));
1479                    }
1480
1481                    // If the original stub symbol is a resolver, then we don't want to break on the symbol with the
1482                    // original name, but instead on all the symbols it could resolve to since otherwise we would stop
1483                    // in the middle of the resolution...
1484                    // Note that the stub is not of the resolver type it will point to the equivalent symbol,
1485                    // not the original name, so in that case we don't need to do anything.
1486
1487                    if (orig_is_resolver)
1488                    {
1489                        target_symbols.Clear();
1490
1491                        FindEquivalentSymbols (current_symbol, modules_to_search, target_symbols);
1492                    }
1493
1494                    // FIXME - Make the Run to Address take multiple addresses, and
1495                    // run to any of them.
1496                    uint32_t num_symbols = target_symbols.GetSize();
1497                    if (num_symbols > 0)
1498                    {
1499                        std::vector<lldb::addr_t>  addresses;
1500                        addresses.resize (num_symbols);
1501                        for (uint32_t i = 0; i < num_symbols; i++)
1502                        {
1503                            SymbolContext context;
1504                            AddressRange addr_range;
1505                            if (target_symbols.GetContextAtIndex(i, context))
1506                            {
1507                                context.GetAddressRange (eSymbolContextEverything, 0, false, addr_range);
1508                                lldb::addr_t load_addr = addr_range.GetBaseAddress().GetLoadAddress(&thread.GetProcess().GetTarget());
1509                                addresses[i] = load_addr;
1510                            }
1511                        }
1512                        if (addresses.size() > 0)
1513                            thread_plan_sp.reset (new ThreadPlanRunToAddress (thread, addresses, stop_others));
1514                        else
1515                        {
1516                            if (log)
1517                                log->Printf ("Couldn't resolve the symbol contexts.");
1518                        }
1519                    }
1520                    else
1521                    {
1522                        if (log)
1523                        {
1524                            log->Printf ("Found a resolver stub for: \"%s\" but could not find any symbols it resolves to.",
1525                                         trampoline_name.AsCString());
1526                        }
1527                    }
1528                }
1529                else
1530                {
1531                    if (log)
1532                    {
1533                        log->Printf ("Could not find symbol for trampoline target: \"%s\"", trampoline_name.AsCString());
1534                    }
1535                }
1536            }
1537        }
1538    }
1539    else
1540    {
1541        if (log)
1542            log->Printf ("Could not find symbol for step through.");
1543    }
1544
1545    return thread_plan_sp;
1546}
1547
1548size_t
1549DynamicLoaderMacOSXDYLD::FindEquivalentSymbols (lldb_private::Symbol *original_symbol,
1550                                               lldb_private::ModuleList &images,
1551                                               lldb_private::SymbolContextList &equivalent_symbols)
1552{
1553    const ConstString &trampoline_name = original_symbol->GetMangled().GetName(Mangled::ePreferMangled);
1554    if (!trampoline_name)
1555        return 0;
1556
1557    size_t initial_size = equivalent_symbols.GetSize();
1558
1559    static const char *resolver_name_regex = "(_gc|_non_gc|\\$[A-Z0-9]+)$";
1560    std::string equivalent_regex_buf("^");
1561    equivalent_regex_buf.append (trampoline_name.GetCString());
1562    equivalent_regex_buf.append (resolver_name_regex);
1563
1564    RegularExpression equivalent_name_regex (equivalent_regex_buf.c_str());
1565    const bool append = true;
1566    images.FindSymbolsMatchingRegExAndType (equivalent_name_regex, eSymbolTypeCode, equivalent_symbols, append);
1567
1568    return equivalent_symbols.GetSize() - initial_size;
1569}
1570
1571Error
1572DynamicLoaderMacOSXDYLD::CanLoadImage ()
1573{
1574    Error error;
1575    // In order for us to tell if we can load a shared library we verify that
1576    // the dylib_info_addr isn't zero (which means no shared libraries have
1577    // been set yet, or dyld is currently mucking with the shared library list).
1578    if (ReadAllImageInfosStructure ())
1579    {
1580        // TODO: also check the _dyld_global_lock_held variable in libSystem.B.dylib?
1581        // TODO: check the malloc lock?
1582        // TODO: check the objective C lock?
1583        if (m_dyld_all_image_infos.dylib_info_addr != 0)
1584            return error; // Success
1585    }
1586
1587    error.SetErrorString("unsafe to load or unload shared libraries");
1588    return error;
1589}
1590
1591void
1592DynamicLoaderMacOSXDYLD::Initialize()
1593{
1594    PluginManager::RegisterPlugin (GetPluginNameStatic(),
1595                                   GetPluginDescriptionStatic(),
1596                                   CreateInstance);
1597}
1598
1599void
1600DynamicLoaderMacOSXDYLD::Terminate()
1601{
1602    PluginManager::UnregisterPlugin (CreateInstance);
1603}
1604
1605
1606const char *
1607DynamicLoaderMacOSXDYLD::GetPluginNameStatic()
1608{
1609    return "dynamic-loader.macosx-dyld";
1610}
1611
1612const char *
1613DynamicLoaderMacOSXDYLD::GetPluginDescriptionStatic()
1614{
1615    return "Dynamic loader plug-in that watches for shared library loads/unloads in MacOSX user processes.";
1616}
1617
1618
1619//------------------------------------------------------------------
1620// PluginInterface protocol
1621//------------------------------------------------------------------
1622const char *
1623DynamicLoaderMacOSXDYLD::GetPluginName()
1624{
1625    return "DynamicLoaderMacOSXDYLD";
1626}
1627
1628const char *
1629DynamicLoaderMacOSXDYLD::GetShortPluginName()
1630{
1631    return GetPluginNameStatic();
1632}
1633
1634uint32_t
1635DynamicLoaderMacOSXDYLD::GetPluginVersion()
1636{
1637    return 1;
1638}
1639
1640