Example #1
0
Error PlatformRemoteAppleWatch::GetSharedModule(
    const ModuleSpec &module_spec, lldb_private::Process *process,
    ModuleSP &module_sp, const FileSpecList *module_search_paths_ptr,
    ModuleSP *old_module_sp_ptr, bool *did_create_ptr) {
    // For Apple Watch, the SDK files are all cached locally on the host
    // system. So first we ask for the file in the cached SDK,
    // then we attempt to get a shared module for the right architecture
    // with the right UUID.
    const FileSpec &platform_file = module_spec.GetFileSpec();
    Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST |
               LIBLLDB_LOG_VERBOSE);

    Error error;
    char platform_file_path[PATH_MAX];

    if (platform_file.GetPath(platform_file_path, sizeof(platform_file_path))) {
        ModuleSpec platform_module_spec(module_spec);

        UpdateSDKDirectoryInfosIfNeeded();

        const uint32_t num_sdk_infos = m_sdk_directory_infos.size();

        // If we are connected we migth be able to correctly deduce the SDK
        // directory
        // using the OS build.
        const uint32_t connected_sdk_idx = GetConnectedSDKIndex();
        if (connected_sdk_idx < num_sdk_infos) {
            if (log) {
                log->Printf("Searching for %s in sdk path %s", platform_file_path,
                            m_sdk_directory_infos[connected_sdk_idx]
                            .directory.GetPath()
                            .c_str());
            }
            if (GetFileInSDK(platform_file_path, connected_sdk_idx,
                             platform_module_spec.GetFileSpec())) {
                module_sp.reset();
                error = ResolveExecutable(platform_module_spec, module_sp, nullptr);
                if (module_sp) {
                    m_last_module_sdk_idx = connected_sdk_idx;
                    error.Clear();
                    return error;
                }
            }
        }

        // Try the last SDK index if it is set as most files from an SDK
        // will tend to be valid in that same SDK.
        if (m_last_module_sdk_idx < num_sdk_infos) {
            if (log) {
                log->Printf("Searching for %s in sdk path %s", platform_file_path,
                            m_sdk_directory_infos[m_last_module_sdk_idx]
                            .directory.GetPath()
                            .c_str());
            }
            if (GetFileInSDK(platform_file_path, m_last_module_sdk_idx,
                             platform_module_spec.GetFileSpec())) {
                module_sp.reset();
                error = ResolveExecutable(platform_module_spec, module_sp, nullptr);
                if (module_sp) {
                    error.Clear();
                    return error;
                }
            }
        }

        // First try for an exact match of major, minor and update
        for (uint32_t sdk_idx = 0; sdk_idx < num_sdk_infos; ++sdk_idx) {
            if (m_last_module_sdk_idx == sdk_idx) {
                // Skip the last module SDK index if we already searched
                // it above
                continue;
            }
            if (log) {
                log->Printf("Searching for %s in sdk path %s", platform_file_path,
                            m_sdk_directory_infos[sdk_idx].directory.GetPath().c_str());
            }
            if (GetFileInSDK(platform_file_path, sdk_idx,
                             platform_module_spec.GetFileSpec())) {
                // printf ("sdk[%u]: '%s'\n", sdk_idx, local_file.GetPath().c_str());

                error = ResolveExecutable(platform_module_spec, module_sp, nullptr);
                if (module_sp) {
                    // Remember the index of the last SDK that we found a file
                    // in in case the wrong SDK was selected.
                    m_last_module_sdk_idx = sdk_idx;
                    error.Clear();
                    return error;
                }
            }
        }
    }
    // Not the module we are looking for... Nothing to see here...
    module_sp.reset();

    // This may not be an SDK-related module.  Try whether we can bring in the
    // thing to our local cache.
    error = GetSharedModuleWithLocalCache(module_spec, module_sp,
                                          module_search_paths_ptr,
                                          old_module_sp_ptr, did_create_ptr);
    if (error.Success())
        return error;

    // See if the file is present in any of the module_search_paths_ptr
    // directories.
    if (!module_sp && module_search_paths_ptr && platform_file) {
        // create a vector of all the file / directory names in platform_file
        // e.g. this might be
        // /System/Library/PrivateFrameworks/UIFoundation.framework/UIFoundation
        //
        // We'll need to look in the module_search_paths_ptr directories for
        // both "UIFoundation" and "UIFoundation.framework" -- most likely the
        // latter will be the one we find there.

        FileSpec platform_pull_apart(platform_file);
        std::vector<std::string> path_parts;
        ConstString unix_root_dir("/");
        while (true) {
            ConstString part = platform_pull_apart.GetLastPathComponent();
            platform_pull_apart.RemoveLastPathComponent();
            if (part.IsEmpty() || part == unix_root_dir)
                break;
            path_parts.push_back(part.AsCString());
        }
        const size_t path_parts_size = path_parts.size();

        size_t num_module_search_paths = module_search_paths_ptr->GetSize();
        for (size_t i = 0; i < num_module_search_paths; ++i) {
            // Create a new FileSpec with this module_search_paths_ptr
            // plus just the filename ("UIFoundation"), then the parent
            // dir plus filename ("UIFoundation.framework/UIFoundation")
            // etc - up to four names (to handle "Foo.framework/Contents/MacOS/Foo")

            for (size_t j = 0; j < 4 && j < path_parts_size - 1; ++j) {
                FileSpec path_to_try(module_search_paths_ptr->GetFileSpecAtIndex(i));

                // Add the components backwards.  For
                // .../PrivateFrameworks/UIFoundation.framework/UIFoundation
                // path_parts is
                //   [0] UIFoundation
                //   [1] UIFoundation.framework
                //   [2] PrivateFrameworks
                //
                // and if 'j' is 2, we want to append path_parts[1] and then
                // path_parts[0], aka
                // 'UIFoundation.framework/UIFoundation', to the module_search_paths_ptr
                // path.

                for (int k = j; k >= 0; --k) {
                    path_to_try.AppendPathComponent(path_parts[k]);
                }

                if (path_to_try.Exists()) {
                    ModuleSpec new_module_spec(module_spec);
                    new_module_spec.GetFileSpec() = path_to_try;
                    Error new_error(Platform::GetSharedModule(
                                        new_module_spec, process, module_sp, NULL, old_module_sp_ptr,
                                        did_create_ptr));

                    if (module_sp) {
                        module_sp->SetPlatformFileSpec(path_to_try);
                        return new_error;
                    }
                }
            }
        }
    }

    const bool always_create = false;
    error = ModuleList::GetSharedModule(
                module_spec, module_sp, module_search_paths_ptr, old_module_sp_ptr,
                did_create_ptr, always_create);

    if (module_sp)
        module_sp->SetPlatformFileSpec(platform_file);

    return error;
}
/// Checks to see if the target module has changed, updates the target
/// accordingly and returns the target executable module.
ModuleSP
DynamicLoaderHexagonDYLD::GetTargetExecutable()
{
    Target &target = m_process->GetTarget();
    ModuleSP executable = target.GetExecutableModule();

    // There is no executable
    if (! executable.get())
        return executable;

    // The target executable file does not exits
    if (! executable->GetFileSpec().Exists())
        return executable;
    
    // Prep module for loading
    ModuleSpec module_spec(executable->GetFileSpec(), executable->GetArchitecture());
    ModuleSP   module_sp  (new Module (module_spec));

    // Check if the executable has changed and set it to the target executable if they differ.
    if (module_sp.get() && module_sp->GetUUID().IsValid() && executable->GetUUID().IsValid())
    {
        // if the executable has changed ??
        if (module_sp->GetUUID() != executable->GetUUID())
            executable.reset();
    }
    else if (executable->FileHasChanged())
        executable.reset();

    if ( executable.get( ) )
        return executable;

    // TODO: What case is this code used?
    executable = target.GetSharedModule(module_spec);
    if (executable.get() != target.GetExecutableModulePointer())
    {
        // Don't load dependent images since we are in dyld where we will know
        // and find out about all images that are loaded
        const bool get_dependent_images = false;
        target.SetExecutableModule(executable, get_dependent_images);
    }
    
    return executable;
}
Example #3
0
Error
ModuleList::GetSharedModule(const ModuleSpec &module_spec,
                            ModuleSP &module_sp,
                            const FileSpecList *module_search_paths_ptr,
                            ModuleSP *old_module_sp_ptr,
                            bool *did_create_ptr,
                            bool always_create)
{
    ModuleList &shared_module_list = GetSharedModuleList ();
    Mutex::Locker locker(shared_module_list.m_modules_mutex);
    char path[PATH_MAX];

    Error error;

    module_sp.reset();

    if (did_create_ptr)
        *did_create_ptr = false;
    if (old_module_sp_ptr)
        old_module_sp_ptr->reset();

    const UUID *uuid_ptr = module_spec.GetUUIDPtr();
    const FileSpec &module_file_spec = module_spec.GetFileSpec();
    const ArchSpec &arch = module_spec.GetArchitecture();

    // Make sure no one else can try and get or create a module while this
    // function is actively working on it by doing an extra lock on the
    // global mutex list.
    if (!always_create)
    {
        ModuleList matching_module_list;
        const size_t num_matching_modules = shared_module_list.FindModules (module_spec, matching_module_list);
        if (num_matching_modules > 0)
        {
            for (size_t module_idx = 0; module_idx < num_matching_modules; ++module_idx)
            {
                module_sp = matching_module_list.GetModuleAtIndex(module_idx);

                // Make sure the file for the module hasn't been modified
                if (module_sp->FileHasChanged())
                {
                    if (old_module_sp_ptr && !*old_module_sp_ptr)
                        *old_module_sp_ptr = module_sp;

                    Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_MODULES));
                    if (log != nullptr)
                        log->Printf("module changed: %p, removing from global module list",
                                    static_cast<void*>(module_sp.get()));

                    shared_module_list.Remove (module_sp);
                    module_sp.reset();
                }
                else
                {
                    // The module matches and the module was not modified from
                    // when it was last loaded.
                    return error;
                }
            }
        }
    }

    if (module_sp)
        return error;

    module_sp.reset (new Module (module_spec));
    // Make sure there are a module and an object file since we can specify
    // a valid file path with an architecture that might not be in that file.
    // By getting the object file we can guarantee that the architecture matches
    if (module_sp->GetObjectFile())
    {
        // If we get in here we got the correct arch, now we just need
        // to verify the UUID if one was given
        if (uuid_ptr && *uuid_ptr != module_sp->GetUUID())
        {
            module_sp.reset();
        }
        else
        {
            if (module_sp->GetObjectFile() && module_sp->GetObjectFile()->GetType() == ObjectFile::eTypeStubLibrary)
            {
                module_sp.reset();
            }
            else
            {
                if (did_create_ptr)
                {
                    *did_create_ptr = true;
                }

                shared_module_list.ReplaceEquivalent(module_sp);
                return error;
            }
        }
    }
    else
    {
        module_sp.reset();
    }

    if (module_search_paths_ptr)
    {
        const auto num_directories = module_search_paths_ptr->GetSize();
        for (size_t idx = 0; idx < num_directories; ++idx)
        {
            auto search_path_spec = module_search_paths_ptr->GetFileSpecAtIndex(idx);
            if (!search_path_spec.ResolvePath())
                continue;
            if (!search_path_spec.Exists() || !search_path_spec.IsDirectory())
                continue;
            search_path_spec.AppendPathComponent(module_spec.GetFileSpec().GetFilename().AsCString());
            if (!search_path_spec.Exists())
                continue;

            auto resolved_module_spec(module_spec);
            resolved_module_spec.GetFileSpec() = search_path_spec;
            module_sp.reset (new Module (resolved_module_spec));
            if (module_sp->GetObjectFile())
            {
                // If we get in here we got the correct arch, now we just need
                // to verify the UUID if one was given
                if (uuid_ptr && *uuid_ptr != module_sp->GetUUID())
                {
                    module_sp.reset();
                }
                else
                {
                    if (module_sp->GetObjectFile()->GetType() == ObjectFile::eTypeStubLibrary)
                    {
                        module_sp.reset();
                    }
                    else
                    {
                        if (did_create_ptr)
                            *did_create_ptr = true;
    
                        shared_module_list.ReplaceEquivalent(module_sp);
                        return Error();
                    }
                }
            }
            else
            {
                module_sp.reset();
            }
        }
    }

    // Either the file didn't exist where at the path, or no path was given, so
    // we now have to use more extreme measures to try and find the appropriate
    // module.

    // Fixup the incoming path in case the path points to a valid file, yet
    // the arch or UUID (if one was passed in) don't match.
    ModuleSpec located_binary_modulespec = Symbols::LocateExecutableObjectFile (module_spec);

    // Don't look for the file if it appears to be the same one we already
    // checked for above...
    if (located_binary_modulespec.GetFileSpec() != module_file_spec)
    {
        if (!located_binary_modulespec.GetFileSpec().Exists())
        {
            located_binary_modulespec.GetFileSpec().GetPath(path, sizeof(path));
            if (path[0] == '\0')
                module_file_spec.GetPath(path, sizeof(path));
            // How can this check ever be true? This branch it is false, and we haven't modified file_spec.
            if (located_binary_modulespec.GetFileSpec().Exists())
            {
                std::string uuid_str;
                if (uuid_ptr && uuid_ptr->IsValid())
                    uuid_str = uuid_ptr->GetAsString();

                if (arch.IsValid())
                {
                    if (!uuid_str.empty())
                        error.SetErrorStringWithFormat("'%s' does not contain the %s architecture and UUID %s", path, arch.GetArchitectureName(), uuid_str.c_str());
                    else
                        error.SetErrorStringWithFormat("'%s' does not contain the %s architecture.", path, arch.GetArchitectureName());
                }
            }
            else
            {
                error.SetErrorStringWithFormat("'%s' does not exist", path);
            }
            if (error.Fail())
                module_sp.reset();
            return error;
        }

        // Make sure no one else can try and get or create a module while this
        // function is actively working on it by doing an extra lock on the
        // global mutex list.
        ModuleSpec platform_module_spec(module_spec);
        platform_module_spec.GetFileSpec() = located_binary_modulespec.GetFileSpec();
        platform_module_spec.GetPlatformFileSpec() = located_binary_modulespec.GetFileSpec();
        platform_module_spec.GetSymbolFileSpec() = located_binary_modulespec.GetSymbolFileSpec();
        ModuleList matching_module_list;
        if (shared_module_list.FindModules (platform_module_spec, matching_module_list) > 0)
        {
            module_sp = matching_module_list.GetModuleAtIndex(0);

            // If we didn't have a UUID in mind when looking for the object file,
            // then we should make sure the modification time hasn't changed!
            if (platform_module_spec.GetUUIDPtr() == nullptr)
            {
                TimeValue file_spec_mod_time(located_binary_modulespec.GetFileSpec().GetModificationTime());
                if (file_spec_mod_time.IsValid())
                {
                    if (file_spec_mod_time != module_sp->GetModificationTime())
                    {
                        if (old_module_sp_ptr)
                            *old_module_sp_ptr = module_sp;
                        shared_module_list.Remove (module_sp);
                        module_sp.reset();
                    }
                }
            }
        }

        if (!module_sp)
        {
            module_sp.reset (new Module (platform_module_spec));
            // Make sure there are a module and an object file since we can specify
            // a valid file path with an architecture that might not be in that file.
            // By getting the object file we can guarantee that the architecture matches
            if (module_sp && module_sp->GetObjectFile())
            {
                if (module_sp->GetObjectFile()->GetType() == ObjectFile::eTypeStubLibrary)
                {
                    module_sp.reset();
                }
                else
                {
                    if (did_create_ptr)
                        *did_create_ptr = true;

                    shared_module_list.ReplaceEquivalent(module_sp);
                }
            }
            else
            {
                located_binary_modulespec.GetFileSpec().GetPath(path, sizeof(path));

                if (located_binary_modulespec.GetFileSpec())
                {
                    if (arch.IsValid())
                        error.SetErrorStringWithFormat("unable to open %s architecture in '%s'", arch.GetArchitectureName(), path);
                    else
                        error.SetErrorStringWithFormat("unable to open '%s'", path);
                }
                else
                {
                    std::string uuid_str;
                    if (uuid_ptr && uuid_ptr->IsValid())
                        uuid_str = uuid_ptr->GetAsString();

                    if (!uuid_str.empty())
                        error.SetErrorStringWithFormat("cannot locate a module for UUID '%s'", uuid_str.c_str());
                    else
                        error.SetErrorStringWithFormat("cannot locate a module");
                }
            }
        }
    }

    return error;
}
Example #4
0
Error
PlatformRemoteiOS::GetSharedModule (const ModuleSpec &module_spec,
                                    Process* process,
                                    ModuleSP &module_sp,
                                    const FileSpecList *module_search_paths_ptr,
                                    ModuleSP *old_module_sp_ptr,
                                    bool *did_create_ptr)
{
    // For iOS, the SDK files are all cached locally on the host
    // system. So first we ask for the file in the cached SDK,
    // then we attempt to get a shared module for the right architecture
    // with the right UUID.
    const FileSpec &platform_file = module_spec.GetFileSpec();

    Error error;
    char platform_file_path[PATH_MAX];
    
    if (platform_file.GetPath(platform_file_path, sizeof(platform_file_path)))
    {
        ModuleSpec platform_module_spec(module_spec);

        UpdateSDKDirectoryInfosIfNeeded();

        const uint32_t num_sdk_infos = m_sdk_directory_infos.size();

        // If we are connected we migth be able to correctly deduce the SDK directory
        // using the OS build.
        const uint32_t connected_sdk_idx = GetConnectedSDKIndex ();
        if (connected_sdk_idx < num_sdk_infos)
        {
            if (GetFileInSDK (platform_file_path, connected_sdk_idx, platform_module_spec.GetFileSpec()))
            {
                module_sp.reset();
                error = ResolveExecutable (platform_module_spec,
                                           module_sp,
                                           NULL);
                if (module_sp)
                {
                    m_last_module_sdk_idx = connected_sdk_idx;
                    error.Clear();
                    return error;
                }
            }
        }

        // Try the last SDK index if it is set as most files from an SDK
        // will tend to be valid in that same SDK.
        if (m_last_module_sdk_idx < num_sdk_infos)
        {
            if (GetFileInSDK (platform_file_path, m_last_module_sdk_idx, platform_module_spec.GetFileSpec()))
            {
                module_sp.reset();
                error = ResolveExecutable (platform_module_spec,
                                           module_sp,
                                           NULL);
                if (module_sp)
                {
                    error.Clear();
                    return error;
                }
            }
        }
        
        // First try for an exact match of major, minor and update:
        // If a particalar SDK version was specified via --version or --build, look for a match on disk.
        const SDKDirectoryInfo *current_sdk_info = GetSDKDirectoryForCurrentOSVersion();
        const uint32_t current_sdk_idx = GetSDKIndexBySDKDirectoryInfo(current_sdk_info);
        if (current_sdk_idx < num_sdk_infos && current_sdk_idx != m_last_module_sdk_idx)
        {
            if (GetFileInSDK (platform_file_path, current_sdk_idx, platform_module_spec.GetFileSpec()))
            {
                module_sp.reset();
                error = ResolveExecutable (platform_module_spec,
                                           module_sp,
                                           NULL);
                if (module_sp)
                {
                    m_last_module_sdk_idx = current_sdk_idx;
                    error.Clear();
                    return error;
                }
            }
        }

        // Second try all SDKs that were found.
        for (uint32_t sdk_idx=0; sdk_idx<num_sdk_infos; ++sdk_idx)
        {
            if (m_last_module_sdk_idx == sdk_idx)
            {
                // Skip the last module SDK index if we already searched
                // it above
                continue;
            }
            if (GetFileInSDK (platform_file_path, sdk_idx, platform_module_spec.GetFileSpec()))
            {
                //printf ("sdk[%u]: '%s'\n", sdk_idx, local_file.GetPath().c_str());
                
                error = ResolveExecutable (platform_module_spec, module_sp, NULL);
                if (module_sp)
                {
                    // Remember the index of the last SDK that we found a file
                    // in in case the wrong SDK was selected.
                    m_last_module_sdk_idx = sdk_idx;
                    error.Clear();
                    return error;
                }
            }
        }
    }
    // Not the module we are looking for... Nothing to see here...
    module_sp.reset();

    // This may not be an SDK-related module.  Try whether we can bring in the thing to our local cache.
    error = GetSharedModuleWithLocalCache(module_spec, module_sp, module_search_paths_ptr, old_module_sp_ptr, did_create_ptr);
    if (error.Success())
        return error;

    const bool always_create = false;
    error = ModuleList::GetSharedModule (module_spec,
                                         module_sp,
                                         module_search_paths_ptr,
                                         old_module_sp_ptr,
                                         did_create_ptr,
                                         always_create);

    if (module_sp)
        module_sp->SetPlatformFileSpec(platform_file);

    return error;
}
Example #5
0
bool SearchFilterByModule::ModulePasses(const ModuleSP &module_sp) {
  return (module_sp &&
          FileSpec::Equal(module_sp->GetFileSpec(), m_module_spec, false));
}
Example #6
0
Error
PlatformDarwin::GetSharedModule (const ModuleSpec &module_spec,
                                 ModuleSP &module_sp,
                                 const FileSpecList *module_search_paths_ptr,
                                 ModuleSP *old_module_sp_ptr,
                                 bool *did_create_ptr)
{
    Error error;
    module_sp.reset();
    
    if (IsRemote())
    {
        // If we have a remote platform always, let it try and locate
        // the shared module first.
        if (m_remote_platform_sp)
        {
            error = m_remote_platform_sp->GetSharedModule (module_spec,
                                                           module_sp,
                                                           module_search_paths_ptr,
                                                           old_module_sp_ptr,
                                                           did_create_ptr);
        }
    }
    
    if (!module_sp)
    {
        // Fall back to the local platform and find the file locally
        error = Platform::GetSharedModule (module_spec,
                                           module_sp,
                                           module_search_paths_ptr,
                                           old_module_sp_ptr,
                                           did_create_ptr);
        
        const FileSpec &platform_file = module_spec.GetFileSpec();
        if (!module_sp && module_search_paths_ptr && platform_file)
        {
            // We can try to pull off part of the file path up to the bundle
            // directory level and try any module search paths...
            FileSpec bundle_directory;
            if (Host::GetBundleDirectory (platform_file, bundle_directory))
            {
                char platform_path[PATH_MAX];
                char bundle_dir[PATH_MAX];
                platform_file.GetPath (platform_path, sizeof(platform_path));
                const size_t bundle_directory_len = bundle_directory.GetPath (bundle_dir, sizeof(bundle_dir));
                char new_path[PATH_MAX];
                size_t num_module_search_paths = module_search_paths_ptr->GetSize();
                for (size_t i=0; i<num_module_search_paths; ++i)
                {
                    const size_t search_path_len = module_search_paths_ptr->GetFileSpecAtIndex(i).GetPath(new_path, sizeof(new_path));
                    if (search_path_len < sizeof(new_path))
                    {
                        snprintf (new_path + search_path_len, sizeof(new_path) - search_path_len, "/%s", platform_path + bundle_directory_len);
                        FileSpec new_file_spec (new_path, false);
                        if (new_file_spec.Exists())
                        {
                            ModuleSpec new_module_spec (module_spec);
                            new_module_spec.GetFileSpec() = new_file_spec;
                            Error new_error (Platform::GetSharedModule (new_module_spec,
                                                                        module_sp,
                                                                        NULL,
                                                                        old_module_sp_ptr,
                                                                        did_create_ptr));
                            
                            if (module_sp)
                            {
                                module_sp->SetPlatformFileSpec(new_file_spec);
                                return new_error;
                            }
                        }
                    }
                }
            }
        }
    }
    if (module_sp)
        module_sp->SetPlatformFileSpec(module_spec.GetFileSpec());
    return error;
}
Example #7
0
void
Target::SetExecutableModule (ModuleSP& executable_sp, bool get_dependent_files)
{
    m_images.Clear();
    m_scratch_ast_context_ap.reset();

    if (executable_sp.get())
    {
        Timer scoped_timer (__PRETTY_FUNCTION__,
                            "Target::SetExecutableModule (executable = '%s/%s')",
                            executable_sp->GetFileSpec().GetDirectory().AsCString(),
                            executable_sp->GetFileSpec().GetFilename().AsCString());

        m_images.Append(executable_sp); // The first image is our exectuable file

        ArchSpec exe_arch = executable_sp->GetArchitecture();
        // If we haven't set an architecture yet, reset our architecture based on what we found in the executable module.
        if (!m_arch_spec.IsValid())
            m_arch_spec = exe_arch;

        FileSpecList dependent_files;
        ObjectFile * executable_objfile = executable_sp->GetObjectFile();
        if (executable_objfile == NULL)
        {

            FileSpec bundle_executable(executable_sp->GetFileSpec());
            if (Host::ResolveExecutableInBundle (bundle_executable))
            {
                ModuleSP bundle_exe_module_sp(GetSharedModule(bundle_executable,
                                              exe_arch));
                SetExecutableModule (bundle_exe_module_sp, get_dependent_files);
                if (bundle_exe_module_sp->GetObjectFile() != NULL)
                    executable_sp = bundle_exe_module_sp;
                return;
            }
        }

        if (executable_objfile)
        {
            executable_objfile->GetDependentModules(dependent_files);
            for (uint32_t i=0; i<dependent_files.GetSize(); i++)
            {
                ModuleSP image_module_sp(GetSharedModule(dependent_files.GetFileSpecPointerAtIndex(i),
                                         exe_arch));
                if (image_module_sp.get())
                {
                    //image_module_sp->Dump(&s);// REMOVE THIS, DEBUG ONLY
                    ObjectFile *objfile = image_module_sp->GetObjectFile();
                    if (objfile)
                        objfile->GetDependentModules(dependent_files);
                }
            }
        }

        // Now see if we know the target triple, and if so, create our scratch AST context:
        if (m_arch_spec.IsValid())
        {
            m_scratch_ast_context_ap.reset (new ClangASTContext(m_arch_spec.GetTriple().str().c_str()));
        }
    }

    UpdateInstanceName();
}
Example #8
0
Error
ModuleList::GetSharedModule
(
    const FileSpec& in_file_spec,
    const ArchSpec& arch,
    const lldb_private::UUID *uuid_ptr,
    const ConstString *object_name_ptr,
    off_t object_offset,
    ModuleSP &module_sp,
    ModuleSP *old_module_sp_ptr,
    bool *did_create_ptr,
    bool always_create
)
{
    ModuleList &shared_module_list = GetSharedModuleList ();
    Mutex::Locker locker(shared_module_list.m_modules_mutex);
    char path[PATH_MAX];
    char uuid_cstr[64];

    Error error;

    module_sp.reset();

    if (did_create_ptr)
        *did_create_ptr = false;
    if (old_module_sp_ptr)
        old_module_sp_ptr->reset();


    // First just try and get the file where it purports to be (path in
    // in_file_spec), then check and uuid.

    if (in_file_spec)
    {
        // Make sure no one else can try and get or create a module while this
        // function is actively working on it by doing an extra lock on the
        // global mutex list.
        if (always_create == false)
        {
            ModuleList matching_module_list;
            const size_t num_matching_modules = shared_module_list.FindModules (&in_file_spec, &arch, NULL, object_name_ptr, matching_module_list);
            if (num_matching_modules > 0)
            {
                for (uint32_t module_idx = 0; module_idx < num_matching_modules; ++module_idx)
                {
                    module_sp = matching_module_list.GetModuleAtIndex(module_idx);
                    if (uuid_ptr && uuid_ptr->IsValid())
                    {
                        // We found the module we were looking for.
                        if (module_sp->GetUUID() == *uuid_ptr)
                            return error;
                    }
                    else
                    {
                        // If we didn't have a UUID in mind when looking for the object file,
                        // then we should make sure the modification time hasn't changed!
                        TimeValue file_spec_mod_time(in_file_spec.GetModificationTime());
                        if (file_spec_mod_time.IsValid())
                        {
                            if (file_spec_mod_time == module_sp->GetModificationTime())
                                return error;
                        }
                    }
                    if (old_module_sp_ptr && !old_module_sp_ptr->get())
                        *old_module_sp_ptr = module_sp;
                    shared_module_list.Remove (module_sp);
                    module_sp.reset();
                }
            }
        }

        if (module_sp)
            return error;
        else
        {
#if defined ENABLE_MODULE_SP_LOGGING
            ModuleSP logging_module_sp (new Module (in_file_spec, arch, object_name_ptr, object_offset), ModuleSharedPtrLogger, (void *)ConstString("a.out").GetCString());
            module_sp = logging_module_sp;
#else
            module_sp.reset (new Module (in_file_spec, arch, object_name_ptr, object_offset));
#endif
            // Make sure there are a module and an object file since we can specify
            // a valid file path with an architecture that might not be in that file.
            // By getting the object file we can guarantee that the architecture matches
            if (module_sp && module_sp->GetObjectFile())
            {
                // If we get in here we got the correct arch, now we just need
                // to verify the UUID if one was given
                if (uuid_ptr && *uuid_ptr != module_sp->GetUUID())
                    module_sp.reset();
                else
                {
                    if (did_create_ptr)
                        *did_create_ptr = true;
                    
                    shared_module_list.Append(module_sp);
                    return error;
                }
            }
        }
    }

    // Either the file didn't exist where at the path, or no path was given, so
    // we now have to use more extreme measures to try and find the appropriate
    // module.

    // Fixup the incoming path in case the path points to a valid file, yet
    // the arch or UUID (if one was passed in) don't match.
    FileSpec file_spec = Symbols::LocateExecutableObjectFile (in_file_spec ? &in_file_spec : NULL, 
                                                              arch.IsValid() ? &arch : NULL, 
                                                              uuid_ptr);

    // Don't look for the file if it appears to be the same one we already
    // checked for above...
    if (file_spec != in_file_spec)
    {
        if (!file_spec.Exists())
        {
            file_spec.GetPath(path, sizeof(path));
            if (file_spec.Exists())
            {
                if (uuid_ptr && uuid_ptr->IsValid())
                    uuid_ptr->GetAsCString(uuid_cstr, sizeof (uuid_cstr));
                else
                    uuid_cstr[0] = '\0';


                if (arch.IsValid())
                {
                    if (uuid_cstr[0])
                        error.SetErrorStringWithFormat("'%s' does not contain the %s architecture and UUID %s", path, arch.GetArchitectureName(), uuid_cstr);
                    else
                        error.SetErrorStringWithFormat("'%s' does not contain the %s architecture.", path, arch.GetArchitectureName());
                }
            }
            else
            {
                error.SetErrorStringWithFormat("'%s' does not exist", path);
            }
            return error;
        }


        // Make sure no one else can try and get or create a module while this
        // function is actively working on it by doing an extra lock on the
        // global mutex list.
        ModuleList matching_module_list;
        if (shared_module_list.FindModules (&file_spec, &arch, uuid_ptr, object_name_ptr, matching_module_list) > 0)
        {
            module_sp = matching_module_list.GetModuleAtIndex(0);

            // If we didn't have a UUID in mind when looking for the object file,
            // then we should make sure the modification time hasn't changed!
            if (uuid_ptr == NULL)
            {
                TimeValue file_spec_mod_time(file_spec.GetModificationTime());
                if (file_spec_mod_time.IsValid())
                {
                    if (file_spec_mod_time != module_sp->GetModificationTime())
                    {
                        if (old_module_sp_ptr)
                            *old_module_sp_ptr = module_sp;
                        shared_module_list.Remove (module_sp);
                        module_sp.reset();
                    }
                }
            }
        }

        if (module_sp.get() == NULL)
        {
#if defined ENABLE_MODULE_SP_LOGGING
            ModuleSP logging_module_sp (new Module (file_spec, arch, object_name_ptr, object_offset), ModuleSharedPtrLogger, 0);
            module_sp = logging_module_sp;
#else
            module_sp.reset (new Module (file_spec, arch, object_name_ptr, object_offset));
#endif
            // Make sure there are a module and an object file since we can specify
            // a valid file path with an architecture that might not be in that file.
            // By getting the object file we can guarantee that the architecture matches
            if (module_sp && module_sp->GetObjectFile())
            {
                if (did_create_ptr)
                    *did_create_ptr = true;

                shared_module_list.Append(module_sp);
            }
            else
            {
                file_spec.GetPath(path, sizeof(path));

                if (file_spec)
                {
                    if (arch.IsValid())
                        error.SetErrorStringWithFormat("unable to open %s architecture in '%s'", arch.GetArchitectureName(), path);
                    else
                        error.SetErrorStringWithFormat("unable to open '%s'", path);
                }
                else
                {
                    if (uuid_ptr && uuid_ptr->IsValid())
                        uuid_ptr->GetAsCString(uuid_cstr, sizeof (uuid_cstr));
                    else
                        uuid_cstr[0] = '\0';

                    if (uuid_cstr[0])
                        error.SetErrorStringWithFormat("cannot locate a module for UUID '%s'", uuid_cstr);
                    else
                        error.SetErrorStringWithFormat("cannot locate a module");
                }
            }
        }
    }

    return error;
}
Example #9
0
void Breakpoint::ModuleReplaced(ModuleSP old_module_sp,
                                ModuleSP new_module_sp) {
  Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_BREAKPOINTS));
  if (log)
    log->Printf("Breakpoint::ModulesReplaced for %s\n",
                old_module_sp->GetSpecificationDescription().c_str());
  // First find all the locations that are in the old module

  BreakpointLocationCollection old_break_locs;
  for (BreakpointLocationSP break_loc_sp : m_locations.BreakpointLocations()) {
    SectionSP section_sp = break_loc_sp->GetAddress().GetSection();
    if (section_sp && section_sp->GetModule() == old_module_sp) {
      old_break_locs.Add(break_loc_sp);
    }
  }

  size_t num_old_locations = old_break_locs.GetSize();

  if (num_old_locations == 0) {
    // There were no locations in the old module, so we just need to check if
    // there were any in the new module.
    ModuleList temp_list;
    temp_list.Append(new_module_sp);
    ResolveBreakpointInModules(temp_list);
  } else {
    // First search the new module for locations.
    // Then compare this with the old list, copy over locations that "look the
    // same"
    // Then delete the old locations.
    // Finally remember to post the creation event.
    //
    // Two locations are the same if they have the same comp unit & function (by
    // name) and there are the same number
    // of locations in the old function as in the new one.

    ModuleList temp_list;
    temp_list.Append(new_module_sp);
    BreakpointLocationCollection new_break_locs;
    ResolveBreakpointInModules(temp_list, new_break_locs);
    BreakpointLocationCollection locations_to_remove;
    BreakpointLocationCollection locations_to_announce;

    size_t num_new_locations = new_break_locs.GetSize();

    if (num_new_locations > 0) {
      // Break out the case of one location -> one location since that's the
      // most common one, and there's no need
      // to build up the structures needed for the merge in that case.
      if (num_new_locations == 1 && num_old_locations == 1) {
        bool equivalent_locations = false;
        SymbolContext old_sc, new_sc;
        // The only way the old and new location can be equivalent is if they
        // have the same amount of information:
        BreakpointLocationSP old_loc_sp = old_break_locs.GetByIndex(0);
        BreakpointLocationSP new_loc_sp = new_break_locs.GetByIndex(0);

        if (old_loc_sp->GetAddress().CalculateSymbolContext(&old_sc) ==
            new_loc_sp->GetAddress().CalculateSymbolContext(&new_sc)) {
          equivalent_locations =
              SymbolContextsMightBeEquivalent(old_sc, new_sc);
        }

        if (equivalent_locations) {
          m_locations.SwapLocation(old_loc_sp, new_loc_sp);
        } else {
          locations_to_remove.Add(old_loc_sp);
          locations_to_announce.Add(new_loc_sp);
        }
      } else {
        // We don't want to have to keep computing the SymbolContexts for these
        // addresses over and over,
        // so lets get them up front:

        typedef std::map<lldb::break_id_t, SymbolContext> IDToSCMap;
        IDToSCMap old_sc_map;
        for (size_t idx = 0; idx < num_old_locations; idx++) {
          SymbolContext sc;
          BreakpointLocationSP bp_loc_sp = old_break_locs.GetByIndex(idx);
          lldb::break_id_t loc_id = bp_loc_sp->GetID();
          bp_loc_sp->GetAddress().CalculateSymbolContext(&old_sc_map[loc_id]);
        }

        std::map<lldb::break_id_t, SymbolContext> new_sc_map;
        for (size_t idx = 0; idx < num_new_locations; idx++) {
          SymbolContext sc;
          BreakpointLocationSP bp_loc_sp = new_break_locs.GetByIndex(idx);
          lldb::break_id_t loc_id = bp_loc_sp->GetID();
          bp_loc_sp->GetAddress().CalculateSymbolContext(&new_sc_map[loc_id]);
        }
        // Take an element from the old Symbol Contexts
        while (old_sc_map.size() > 0) {
          lldb::break_id_t old_id = old_sc_map.begin()->first;
          SymbolContext &old_sc = old_sc_map.begin()->second;

          // Count the number of entries equivalent to this SC for the old list:
          std::vector<lldb::break_id_t> old_id_vec;
          old_id_vec.push_back(old_id);

          IDToSCMap::iterator tmp_iter;
          for (tmp_iter = ++old_sc_map.begin(); tmp_iter != old_sc_map.end();
               tmp_iter++) {
            if (SymbolContextsMightBeEquivalent(old_sc, tmp_iter->second))
              old_id_vec.push_back(tmp_iter->first);
          }

          // Now find all the equivalent locations in the new list.
          std::vector<lldb::break_id_t> new_id_vec;
          for (tmp_iter = new_sc_map.begin(); tmp_iter != new_sc_map.end();
               tmp_iter++) {
            if (SymbolContextsMightBeEquivalent(old_sc, tmp_iter->second))
              new_id_vec.push_back(tmp_iter->first);
          }

          // Alright, if we have the same number of potentially equivalent
          // locations in the old
          // and new modules, we'll just map them one to one in ascending ID
          // order (assuming the
          // resolver's order would match the equivalent ones.
          // Otherwise, we'll dump all the old ones, and just take the new ones,
          // erasing the elements
          // from both maps as we go.

          if (old_id_vec.size() == new_id_vec.size()) {
            sort(old_id_vec.begin(), old_id_vec.end());
            sort(new_id_vec.begin(), new_id_vec.end());
            size_t num_elements = old_id_vec.size();
            for (size_t idx = 0; idx < num_elements; idx++) {
              BreakpointLocationSP old_loc_sp =
                  old_break_locs.FindByIDPair(GetID(), old_id_vec[idx]);
              BreakpointLocationSP new_loc_sp =
                  new_break_locs.FindByIDPair(GetID(), new_id_vec[idx]);
              m_locations.SwapLocation(old_loc_sp, new_loc_sp);
              old_sc_map.erase(old_id_vec[idx]);
              new_sc_map.erase(new_id_vec[idx]);
            }
          } else {
            for (lldb::break_id_t old_id : old_id_vec) {
              locations_to_remove.Add(
                  old_break_locs.FindByIDPair(GetID(), old_id));
              old_sc_map.erase(old_id);
            }
            for (lldb::break_id_t new_id : new_id_vec) {
              locations_to_announce.Add(
                  new_break_locs.FindByIDPair(GetID(), new_id));
              new_sc_map.erase(new_id);
            }
          }
        }
      }
    }

    // Now remove the remaining old locations, and cons up a removed locations
    // event.
    // Note, we don't put the new locations that were swapped with an old
    // location on the locations_to_remove
    // list, so we don't need to worry about telling the world about removing a
    // location we didn't tell them
    // about adding.

    BreakpointEventData *locations_event;
    if (!IsInternal())
      locations_event = new BreakpointEventData(
          eBreakpointEventTypeLocationsRemoved, shared_from_this());
    else
      locations_event = nullptr;

    for (BreakpointLocationSP loc_sp :
         locations_to_remove.BreakpointLocations()) {
      m_locations.RemoveLocation(loc_sp);
      if (locations_event)
        locations_event->GetBreakpointLocationCollection().Add(loc_sp);
    }
    SendBreakpointChangedEvent(locations_event);

    // And announce the new ones.

    if (!IsInternal()) {
      locations_event = new BreakpointEventData(
          eBreakpointEventTypeLocationsAdded, shared_from_this());
      for (BreakpointLocationSP loc_sp :
           locations_to_announce.BreakpointLocations())
        locations_event->GetBreakpointLocationCollection().Add(loc_sp);

      SendBreakpointChangedEvent(locations_event);
    }
    m_locations.Compact();
  }
}
Example #10
0
Error
PlatformRemoteiOS::GetSharedModule (const ModuleSpec &module_spec,
                                    ModuleSP &module_sp,
                                    const FileSpecList *module_search_paths_ptr,
                                    ModuleSP *old_module_sp_ptr,
                                    bool *did_create_ptr)
{
    // For iOS, the SDK files are all cached locally on the host
    // system. So first we ask for the file in the cached SDK,
    // then we attempt to get a shared module for the right architecture
    // with the right UUID.
    const FileSpec &platform_file = module_spec.GetFileSpec();

    FileSpec local_file;
    const UUID *module_uuid_ptr = module_spec.GetUUIDPtr();
    Error error (GetSymbolFile (platform_file, module_uuid_ptr, local_file));
    if (error.Success())
    {
        error = ResolveExecutable (local_file, module_spec.GetArchitecture(), module_sp, NULL);
        if (module_sp && ((module_uuid_ptr == NULL) || (module_sp->GetUUID() == *module_uuid_ptr)))
        {
            //printf ("found in user specified SDK\n");
            error.Clear();
            return error;
        }

        char platform_file_path[PATH_MAX];
        if (platform_file.GetPath(platform_file_path, sizeof(platform_file_path)))
        {
            FileSpec local_file;
            const uint32_t num_sdk_infos = m_sdk_directory_infos.size();
            // Try the last SDK index if it is set as most files from an SDK
            // will tend to be valid in that same SDK.
            if (m_last_module_sdk_idx < num_sdk_infos)
            {
                if (GetFileInSDK (platform_file_path, m_last_module_sdk_idx, local_file))
                {
                    //printf ("sdk[%u] last: '%s'\n", m_last_module_sdk_idx, local_file.GetPath().c_str());
                    module_sp.reset();
                    error = ResolveExecutable (local_file,
                                               module_spec.GetArchitecture(),
                                               module_sp,
                                               NULL);
                    if (module_sp && ((module_uuid_ptr == NULL) || (module_sp->GetUUID() == *module_uuid_ptr)))
                    {
                        //printf ("sdk[%u] last found\n", m_last_module_sdk_idx);
                        error.Clear();
                        return error;
                    }
                }
            }
            
            // First try for an exact match of major, minor and update
            for (uint32_t sdk_idx=0; sdk_idx<num_sdk_infos; ++sdk_idx)
            {
                if (m_last_module_sdk_idx == sdk_idx)
                {
                    // Skip the last module SDK index if we already searched
                    // it above
                    continue;
                }
                if (GetFileInSDK (platform_file_path, sdk_idx, local_file))
                {
                    //printf ("sdk[%u]: '%s'\n", sdk_idx, local_file.GetPath().c_str());
                    
                    error = ResolveExecutable (local_file,
                                               module_spec.GetArchitecture(),
                                               module_sp,
                                               NULL);
                    if (module_sp && ((module_uuid_ptr == NULL) || (module_sp->GetUUID() == *module_uuid_ptr)))
                    {
                        // Remember the index of the last SDK that we found a file
                        // in in case the wrong SDK was selected.
                        m_last_module_sdk_idx = sdk_idx;
                        //printf ("sdk[%u]: found (setting last to %u)\n", sdk_idx, m_last_module_sdk_idx);
                        error.Clear();
                        return error;
                    }
                }
            }
        }
        // Not the module we are looking for... Nothing to see here...
        module_sp.reset();
    }
    else
    {
        // This may not be an SDK-related module.  Try whether we can bring in the thing to our local cache.
        error = GetSharedModuleWithLocalCache(module_spec, module_sp, module_search_paths_ptr, old_module_sp_ptr, did_create_ptr);
        if (error.Success())
            return error;
        else
            error.Clear(); // Clear the error and fall-through.
    }

    const bool always_create = false;
    error = ModuleList::GetSharedModule (module_spec, 
                                         module_sp,
                                         module_search_paths_ptr,
                                         old_module_sp_ptr,
                                         did_create_ptr,
                                         always_create);

    if (module_sp)
        module_sp->SetPlatformFileSpec(platform_file);

    return error;
}
Error
PlatformDarwinKernel::GetSharedModule (const ModuleSpec &module_spec,
                                       Process *process,
                                       ModuleSP &module_sp,
                                       const FileSpecList *module_search_paths_ptr,
                                       ModuleSP *old_module_sp_ptr,
                                       bool *did_create_ptr)
{
    Error error;
    module_sp.reset();
    const FileSpec &platform_file = module_spec.GetFileSpec();

    // Treat the file's path as a kext bundle ID (e.g. "com.apple.driver.AppleIRController") and search our kext index.
    std::string kext_bundle_id = platform_file.GetPath();
    if (!kext_bundle_id.empty())
    {
        ConstString kext_bundle_cs(kext_bundle_id.c_str());
        if (m_name_to_kext_path_map.count(kext_bundle_cs) > 0)
        {
            for (BundleIDToKextIterator it = m_name_to_kext_path_map.begin (); it != m_name_to_kext_path_map.end (); ++it)
            {
                if (it->first == kext_bundle_cs)
                {
                    error = ExamineKextForMatchingUUID (it->second, module_spec.GetUUID(), module_spec.GetArchitecture(), module_sp);
                    if (module_sp.get())
                    {
                        return error;
                    }
                }
            }
        }
    }

    if (kext_bundle_id.compare("mach_kernel") == 0 && module_spec.GetUUID().IsValid())
    {
        for (auto possible_kernel : m_kernel_binaries)
        {
            if (possible_kernel.Exists())
            {
                ModuleSpec kern_spec (possible_kernel);
                kern_spec.GetUUID() = module_spec.GetUUID();
                ModuleSP module_sp (new Module (kern_spec));
                if (module_sp && module_sp->GetObjectFile() && module_sp->MatchesModuleSpec (kern_spec))
                {
                    // module_sp is an actual kernel binary we want to add.
                    if (process)
                    {
                        process->GetTarget().GetImages().AppendIfNeeded (module_sp);
                        error.Clear();
                        return error;
                    }
                    else
                    {
                        error = ModuleList::GetSharedModule (kern_spec, module_sp, NULL, NULL, NULL);
                        if (module_sp 
                            && module_sp->GetObjectFile() 
                            && module_sp->GetObjectFile()->GetType() != ObjectFile::Type::eTypeCoreFile)
                        {
                            return error;
                        }
                        module_sp.reset();
                    }
                }
            }
        }
    }

    // Else fall back to treating the file's path as an actual file path - defer to PlatformDarwin's GetSharedModule.
    return PlatformDarwin::GetSharedModule (module_spec, process, module_sp, module_search_paths_ptr, old_module_sp_ptr, did_create_ptr);
}
Error
PlatformRemoteAppleWatch::GetSharedModule (const ModuleSpec &module_spec,
                                           lldb_private::Process* process,
                                           ModuleSP &module_sp,
                                           const FileSpecList *module_search_paths_ptr,
                                           ModuleSP *old_module_sp_ptr,
                                           bool *did_create_ptr)
{
    // For Apple Watch, the SDK files are all cached locally on the host
    // system. So first we ask for the file in the cached SDK,
    // then we attempt to get a shared module for the right architecture
    // with the right UUID.
    const FileSpec &platform_file = module_spec.GetFileSpec();
    Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST | LIBLLDB_LOG_VERBOSE);

    Error error;
    char platform_file_path[PATH_MAX];
    
    if (platform_file.GetPath(platform_file_path, sizeof(platform_file_path)))
    {
        ModuleSpec platform_module_spec(module_spec);

        UpdateSDKDirectoryInfosIfNeeded();

        const uint32_t num_sdk_infos = m_sdk_directory_infos.size();

        // If we are connected we migth be able to correctly deduce the SDK directory
        // using the OS build.
        const uint32_t connected_sdk_idx = GetConnectedSDKIndex ();
        if (connected_sdk_idx < num_sdk_infos)
        {
            if (log)
            {
                log->Printf ("Searching for %s in sdk path %s", platform_file_path, m_sdk_directory_infos[connected_sdk_idx].directory.GetPath().c_str());
            }
            if (GetFileInSDK (platform_file_path, connected_sdk_idx, platform_module_spec.GetFileSpec()))
            {
                module_sp.reset();
                error = ResolveExecutable(platform_module_spec,
                                          module_sp,
                                          nullptr);
                if (module_sp)
                {
                    m_last_module_sdk_idx = connected_sdk_idx;
                    error.Clear();
                    return error;
                }
            }
        }

        // Try the last SDK index if it is set as most files from an SDK
        // will tend to be valid in that same SDK.
        if (m_last_module_sdk_idx < num_sdk_infos)
        {
            if (log)
            {
                log->Printf ("Searching for %s in sdk path %s", platform_file_path, m_sdk_directory_infos[m_last_module_sdk_idx].directory.GetPath().c_str());
            }
            if (GetFileInSDK (platform_file_path, m_last_module_sdk_idx, platform_module_spec.GetFileSpec()))
            {
                module_sp.reset();
                error = ResolveExecutable(platform_module_spec,
                                          module_sp,
                                          nullptr);
                if (module_sp)
                {
                    error.Clear();
                    return error;
                }
            }
        }
        
        // First try for an exact match of major, minor and update
        for (uint32_t sdk_idx=0; sdk_idx<num_sdk_infos; ++sdk_idx)
        {
            if (m_last_module_sdk_idx == sdk_idx)
            {
                // Skip the last module SDK index if we already searched
                // it above
                continue;
            }
            if (log)
            {
                log->Printf ("Searching for %s in sdk path %s", platform_file_path, m_sdk_directory_infos[sdk_idx].directory.GetPath().c_str());
            }
            if (GetFileInSDK (platform_file_path, sdk_idx, platform_module_spec.GetFileSpec()))
            {
                //printf ("sdk[%u]: '%s'\n", sdk_idx, local_file.GetPath().c_str());
                
                error = ResolveExecutable(platform_module_spec, module_sp, nullptr);
                if (module_sp)
                {
                    // Remember the index of the last SDK that we found a file
                    // in in case the wrong SDK was selected.
                    m_last_module_sdk_idx = sdk_idx;
                    error.Clear();
                    return error;
                }
            }
        }
    }
    // Not the module we are looking for... Nothing to see here...
    module_sp.reset();

    // This may not be an SDK-related module.  Try whether we can bring in the thing to our local cache.
    error = GetSharedModuleWithLocalCache(module_spec, module_sp, module_search_paths_ptr, old_module_sp_ptr, did_create_ptr);
    if (error.Success())
        return error;

    const bool always_create = false;
    error = ModuleList::GetSharedModule (module_spec,
                                         module_sp,
                                         module_search_paths_ptr,
                                         old_module_sp_ptr,
                                         did_create_ptr,
                                         always_create);

    if (module_sp)
        module_sp->SetPlatformFileSpec(platform_file);

    return error;
}