Exemplo n.º 1
0
bool
FileSpec::Equal (const FileSpec& a, const FileSpec& b, bool full)
{
    if (!full && (a.GetDirectory().IsEmpty() || b.GetDirectory().IsEmpty()))
        return a.m_filename == b.m_filename;
    else
        return a == b;
}
Exemplo n.º 2
0
bool
HostInfoLinux::ComputeSupportExeDirectory(FileSpec &file_spec)
{
    if (HostInfoPosix::ComputeSupportExeDirectory(file_spec) &&
            !file_spec.IsRelativeToCurrentWorkingDirectory() &&
            file_spec.Exists())
        return true;
    file_spec.GetDirectory() = GetProgramFileSpec().GetDirectory();
    return !file_spec.GetDirectory().IsEmpty();
}
Exemplo n.º 3
0
    bool FileSpecMatchesAsBaseOrFull(const FileSpec &left,
                                     const FileSpec &right) const {
        // If the filenames don't match, the paths can't be equal
        if (!left.FileEquals(right))
            return false;
        // If BOTH have a directory, also compare the directories.
        if (left.GetDirectory() && right.GetDirectory())
            return left.DirectoryEquals(right);

        // If one has a directory but not the other, they match.
        return true;
    }
Exemplo n.º 4
0
Error
Platform::ResolveExecutable (const FileSpec &exe_file,
                             const ArchSpec &exe_arch,
                             lldb::ModuleSP &exe_module_sp)
{
    Error error;
    if (exe_file.Exists())
    {
        if (exe_arch.IsValid())
        {
            error = ModuleList::GetSharedModule (exe_file, 
                                                 exe_arch, 
                                                 NULL,
                                                 NULL, 
                                                 0, 
                                                 exe_module_sp, 
                                                 NULL, 
                                                 NULL);
        }
        else
        {
            // No valid architecture was specified, ask the platform for
            // the architectures that we should be using (in the correct order)
            // and see if we can find a match that way
            ArchSpec platform_arch;
            for (uint32_t idx = 0; GetSupportedArchitectureAtIndex (idx, platform_arch); ++idx)
            {
                error = ModuleList::GetSharedModule (exe_file, 
                                                     platform_arch, 
                                                     NULL,
                                                     NULL, 
                                                     0, 
                                                     exe_module_sp, 
                                                     NULL, 
                                                     NULL);
                // Did we find an executable using one of the 
                if (error.Success() && exe_module_sp)
                    break;
            }
        }
    }
    else
    {
        error.SetErrorStringWithFormat ("'%s%s%s' does not exist",
                                        exe_file.GetDirectory().AsCString(""),
                                        exe_file.GetDirectory() ? "/" : "",
                                        exe_file.GetFilename().AsCString(""));
    }
    return error;
}
Exemplo n.º 5
0
TargetSP
TargetList::FindTargetWithExecutableAndArchitecture
(
    const FileSpec &exe_file_spec,
    const ArchSpec *exe_arch_ptr
) const
{
    Mutex::Locker locker (m_target_list_mutex);
    TargetSP target_sp;
    bool full_match = (bool)exe_file_spec.GetDirectory();

    collection::const_iterator pos, end = m_target_list.end();
    for (pos = m_target_list.begin(); pos != end; ++pos)
    {
        Module *exe_module = (*pos)->GetExecutableModulePointer();

        if (exe_module)
        {
            if (FileSpec::Equal (exe_file_spec, exe_module->GetFileSpec(), full_match))
            {
                if (exe_arch_ptr)
                {
                    if (!exe_arch_ptr->IsCompatibleMatch(exe_module->GetArchitecture()))
                        continue;
                }
                target_sp = *pos;
                break;
            }
        }
    }
    return target_sp;
}
Exemplo n.º 6
0
bool
HostInfoPosix::ComputeHeaderDirectory(FileSpec &file_spec)
{
    FileSpec temp_file("/opt/local/include/lldb", false);
    file_spec.GetDirectory().SetCString(temp_file.GetPath().c_str());
    return true;
}
Exemplo n.º 7
0
static Error save_socket_id_to_file(const std::string &socket_id,
                                    const FileSpec &file_spec) {
  FileSpec temp_file_spec(file_spec.GetDirectory().AsCString(), false);
  auto error = FileSystem::MakeDirectory(temp_file_spec,
                                         eFilePermissionsDirectoryDefault);
  if (error.Fail())
    return Error("Failed to create directory %s: %s",
                 temp_file_spec.GetCString(), error.AsCString());

  llvm::SmallString<PATH_MAX> temp_file_path;
  temp_file_spec.AppendPathComponent("port-file.%%%%%%");
  auto err_code = llvm::sys::fs::createUniqueFile(temp_file_spec.GetCString(),
                                                  temp_file_path);
  if (err_code)
    return Error("Failed to create temp file: %s", err_code.message().c_str());

  llvm::FileRemover tmp_file_remover(temp_file_path.c_str());

  {
    std::ofstream temp_file(temp_file_path.c_str(), std::ios::out);
    if (!temp_file.is_open())
      return Error("Failed to open temp file %s", temp_file_path.c_str());
    temp_file << socket_id;
  }

  err_code = llvm::sys::fs::rename(temp_file_path.c_str(), file_spec.GetPath());
  if (err_code)
    return Error("Failed to rename file %s to %s: %s", temp_file_path.c_str(),
                 file_spec.GetPath().c_str(), err_code.message().c_str());

  tmp_file_remover.releaseFile();
  return Error();
}
Exemplo n.º 8
0
//------------------------------------------------------------------
// Find the index of the file in the file spec list that matches
// "file_spec" starting "start_idx" entries into the file spec list.
//
// Returns the valid index of the file that matches "file_spec" if
// it is found, else UINT32_MAX is returned.
//------------------------------------------------------------------
uint32_t
FileSpecList::FindFileIndex (uint32_t start_idx, const FileSpec &file_spec, bool full) const
{
    const uint32_t num_files = m_files.size();
    uint32_t idx;

    // When looking for files, we will compare only the filename if the
    // FILE_SPEC argument is empty
    bool compare_filename_only = file_spec.GetDirectory().IsEmpty();

    for (idx = start_idx; idx < num_files; ++idx)
    {
        if (compare_filename_only)
        {
            if (m_files[idx].GetFilename() == file_spec.GetFilename())
                return idx;
        }
        else
        {
            if (FileSpec::Equal (m_files[idx], file_spec, full))
                return idx;
        }
    }

    // We didn't find the file, return an invalid index
    return UINT32_MAX;
}
Exemplo n.º 9
0
bool
HostInfoLinux::ComputeSystemPluginsDirectory(FileSpec &file_spec)
{
    FileSpec temp_file("/usr/lib/lldb", true);
    file_spec.GetDirectory().SetCString(temp_file.GetPath().c_str());
    return true;
}
Exemplo n.º 10
0
bool
HostInfoLinux::ComputeUserPluginsDirectory(FileSpec &file_spec)
{
    // XDG Base Directory Specification
    // http://standards.freedesktop.org/basedir-spec/basedir-spec-latest.html
    // If XDG_DATA_HOME exists, use that, otherwise use ~/.local/share/lldb.
    const char *xdg_data_home = getenv("XDG_DATA_HOME");
    if (xdg_data_home && xdg_data_home[0])
    {
        std::string user_plugin_dir(xdg_data_home);
        user_plugin_dir += "/lldb";
        file_spec.GetDirectory().SetCString(user_plugin_dir.c_str());
    }
    else
        file_spec.GetDirectory().SetCString("~/.local/share/lldb");
    return true;
}
Exemplo n.º 11
0
Error
ModuleCache::CreateHostSysRootModuleSymLink (const FileSpec &sysroot_module_path_spec, const FileSpec &module_file_path)
{
    const auto error = MakeDirectory (FileSpec (sysroot_module_path_spec.GetDirectory ().AsCString (), false));
    if (error.Fail ())
        return error;

    return FileSystem::Symlink (sysroot_module_path_spec.GetPath ().c_str (),
                                module_file_path.GetPath ().c_str ());
}
Exemplo n.º 12
0
bool
HostInfoBase::ComputeSharedLibraryDirectory(FileSpec &file_spec)
{
    // To get paths related to LLDB we get the path to the executable that
    // contains this function. On MacOSX this will be "LLDB.framework/.../LLDB",
    // on linux this is assumed to be the "lldb" main executable. If LLDB on
    // linux is actually in a shared library (liblldb.so) then this function will
    // need to be modified to "do the right thing".

    FileSpec lldb_file_spec(
        Host::GetModuleFileSpecForHostAddress(reinterpret_cast<void *>(reinterpret_cast<intptr_t>(HostInfoBase::GetLLDBPath))));
    
    // This is necessary because when running the testsuite the shlib might be a symbolic link inside the Python resource dir.
    FileSystem::ResolveSymbolicLink(lldb_file_spec, lldb_file_spec);
    
    // Remove the filename so that this FileSpec only represents the directory.
    file_spec.GetDirectory() = lldb_file_spec.GetDirectory();

    return (bool)file_spec.GetDirectory();
}
Exemplo n.º 13
0
uint32_t
Module::ResolveSymbolContextsForFileSpec (const FileSpec &file_spec, uint32_t line, bool check_inlines, uint32_t resolve_scope, SymbolContextList& sc_list)
{
    Mutex::Locker locker (m_mutex);
    Timer scoped_timer(__PRETTY_FUNCTION__,
                       "Module::ResolveSymbolContextForFilePath (%s%s%s:%u, check_inlines = %s, resolve_scope = 0x%8.8x)",
                       file_spec.GetDirectory().AsCString(""),
                       file_spec.GetDirectory() ? "/" : "",
                       file_spec.GetFilename().AsCString(""),
                       line,
                       check_inlines ? "yes" : "no",
                       resolve_scope);

    const uint32_t initial_count = sc_list.GetSize();

    SymbolVendor *symbols = GetSymbolVendor  ();
    if (symbols)
        symbols->ResolveSymbolContext (file_spec, line, check_inlines, resolve_scope, sc_list);

    return sc_list.GetSize() - initial_count;
}
Exemplo n.º 14
0
ModuleSP
Target::GetSharedModule
(
    const FileSpec& file_spec,
    const ArchSpec& arch,
    const lldb_private::UUID *uuid_ptr,
    const ConstString *object_name,
    off_t object_offset,
    Error *error_ptr
)
{
    // Don't pass in the UUID so we can tell if we have a stale value in our list
    ModuleSP old_module_sp; // This will get filled in if we have a new version of the library
    bool did_create_module = false;
    ModuleSP module_sp;

    // If there are image search path entries, try to use them first to acquire a suitable image.

    Error error;

    if (m_image_search_paths.GetSize())
    {
        FileSpec transformed_spec;
        if (m_image_search_paths.RemapPath (file_spec.GetDirectory(), transformed_spec.GetDirectory()))
        {
            transformed_spec.GetFilename() = file_spec.GetFilename();
            error = ModuleList::GetSharedModule (transformed_spec, arch, uuid_ptr, object_name, object_offset, module_sp, &old_module_sp, &did_create_module);
        }
    }

    // If a module hasn't been found yet, use the unmodified path.

    if (!module_sp)
    {
        error = (ModuleList::GetSharedModule (file_spec, arch, uuid_ptr, object_name, object_offset, module_sp, &old_module_sp, &did_create_module));
    }

    if (module_sp)
    {
        m_images.Append (module_sp);
        if (did_create_module)
        {
            if (old_module_sp && m_images.GetIndexForModule (old_module_sp.get()) != LLDB_INVALID_INDEX32)
                ModuleUpdated(old_module_sp, module_sp);
            else
                ModuleAdded(module_sp);
        }
    }
    if (error_ptr)
        *error_ptr = error;
    return module_sp;
}
Exemplo n.º 15
0
bool
HostInfoWindows::ComputePythonDirectory(FileSpec &file_spec)
{
    FileSpec lldb_file_spec;
    if (!GetLLDBPath(lldb::ePathTypeLLDBShlibDir, lldb_file_spec))
        return false;
    llvm::SmallString<64> path(lldb_file_spec.GetDirectory().AsCString());
    llvm::sys::path::remove_filename(path);
    llvm::sys::path::append(path, "lib", "site-packages");
    std::replace(path.begin(), path.end(), '\\', '/');
    file_spec.GetDirectory().SetString(path.c_str());
    return true;
}
Exemplo n.º 16
0
bool HostInfoPosix::ComputePythonDirectory(FileSpec &file_spec) {
#ifndef LLDB_DISABLE_PYTHON
  FileSpec lldb_file_spec;
  if (!GetLLDBPath(lldb::ePathTypeLLDBShlibDir, lldb_file_spec))
    return false;

  char raw_path[PATH_MAX];
  lldb_file_spec.GetPath(raw_path, sizeof(raw_path));

#if defined(LLDB_PYTHON_RELATIVE_LIBDIR)
  // Build the path by backing out of the lib dir, then building
  // with whatever the real python interpreter uses.  (e.g. lib
  // for most, lib64 on RHEL x86_64).
  char python_path[PATH_MAX];
  ::snprintf(python_path, sizeof(python_path), "%s/../%s", raw_path,
             LLDB_PYTHON_RELATIVE_LIBDIR);

  char final_path[PATH_MAX];
  realpath(python_path, final_path);
  file_spec.GetDirectory().SetCString(final_path);

  return true;
#else
  llvm::SmallString<256> python_version_dir;
  llvm::raw_svector_ostream os(python_version_dir);
  os << "/python" << PY_MAJOR_VERSION << '.' << PY_MINOR_VERSION
     << "/site-packages";

  // We may get our string truncated. Should we protect this with an assert?
  ::strncat(raw_path, python_version_dir.c_str(),
            sizeof(raw_path) - strlen(raw_path) - 1);

  file_spec.GetDirectory().SetCString(raw_path);
  return true;
#endif
#else
  return false;
#endif
}
Exemplo n.º 17
0
bool
HostInfoWindows::ComputePythonDirectory(FileSpec &file_spec)
{
    FileSpec lldb_file_spec;
    if (!GetLLDBPath(lldb::ePathTypeLLDBShlibDir, lldb_file_spec))
        return false;

    char raw_path[PATH_MAX];
    lldb_file_spec.AppendPathComponent("../lib/site-packages");
    lldb_file_spec.GetPath(raw_path, sizeof(raw_path));

    file_spec.GetDirectory().SetCString(raw_path);
    return true;
}
Exemplo n.º 18
0
bool
HostInfoPosix::ComputeSupportExeDirectory(FileSpec &file_spec)
{
    Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST);

    FileSpec lldb_file_spec;
    if (!GetLLDBPath(lldb::ePathTypeLLDBShlibDir, lldb_file_spec))
        return false;

    char raw_path[PATH_MAX];
    lldb_file_spec.GetPath(raw_path, sizeof(raw_path));

    // Most Posix systems (e.g. Linux/*BSD) will attempt to replace a */lib with */bin as the base
    // directory for helper exe programs.  This will fail if the /lib and /bin directories are
    // rooted in entirely different trees.
    if (log)
        log->Printf("HostInfoPosix::ComputeSupportExeDirectory() attempting to derive the bin path (ePathTypeSupportExecutableDir) from "
                    "this path: %s",
                    raw_path);
    char *lib_pos = ::strstr(raw_path, "/lib");
    if (lib_pos != nullptr)
    {
        // Now write in bin in place of lib.
        ::snprintf(lib_pos, PATH_MAX - (lib_pos - raw_path), "/bin");

        if (log)
            log->Printf("Host::%s() derived the bin path as: %s", __FUNCTION__, raw_path);
    }
    else
    {
        if (log)
            log->Printf("Host::%s() failed to find /lib/liblldb within the shared lib path, bailing on bin path construction",
                        __FUNCTION__);
    }
    file_spec.GetDirectory().SetCString(raw_path);
    return (bool)file_spec.GetDirectory();
}
Exemplo n.º 19
0
bool
HostInfoBase::ComputeProcessTempFileDirectory(FileSpec &file_spec)
{
    FileSpec temp_file_spec;
    if (!HostInfo::ComputeGlobalTempFileDirectory(temp_file_spec))
        return false;

    std::string pid_str{std::to_string(Host::GetCurrentProcessID())};
    temp_file_spec.AppendPathComponent(pid_str);
    if (!FileSystem::MakeDirectory(temp_file_spec, eFilePermissionsDirectoryDefault).Success())
        return false;

    file_spec.GetDirectory().SetCString(temp_file_spec.GetCString());
    return true;
}
Exemplo n.º 20
0
bool HostInfoPosix::ComputePathRelativeToLibrary(FileSpec &file_spec,
                                                 llvm::StringRef dir) {
  Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST);

  FileSpec lldb_file_spec;
  if (!GetLLDBPath(lldb::ePathTypeLLDBShlibDir, lldb_file_spec))
    return false;

  std::string raw_path = lldb_file_spec.GetPath();
  // drop library directory
  llvm::StringRef parent_path = llvm::sys::path::parent_path(raw_path);

  // Most Posix systems (e.g. Linux/*BSD) will attempt to replace a */lib with
  // */bin as the base directory for helper exe programs.  This will fail if the
  // /lib and /bin directories are rooted in entirely different trees.
  if (log)
    log->Printf("HostInfoPosix::ComputePathRelativeToLibrary() attempting to "
                "derive the %s path from this path: %s",
                dir.data(), raw_path.c_str());

  if (!parent_path.empty()) {
    // Now write in bin in place of lib.
    raw_path = (parent_path + dir).str();

    if (log)
      log->Printf("Host::%s() derived the bin path as: %s", __FUNCTION__,
                  raw_path.c_str());
  } else {
    if (log)
      log->Printf("Host::%s() failed to find /lib/liblldb within the shared "
                  "lib path, bailing on bin path construction",
                  __FUNCTION__);
  }
  file_spec.GetDirectory().SetString(raw_path);
  return (bool)file_spec.GetDirectory();
}
Exemplo n.º 21
0
bool
HostInfoBase::ComputeGlobalTempFileDirectory(FileSpec &file_spec)
{
    file_spec.Clear();

    FileSpec temp_file_spec;
    if (!HostInfo::ComputeTempFileBaseDirectory(temp_file_spec))
        return false;

    temp_file_spec.AppendPathComponent("lldb");
    if (!FileSystem::MakeDirectory(temp_file_spec, eFilePermissionsDirectoryDefault).Success())
        return false;

    file_spec.GetDirectory().SetCString(temp_file_spec.GetCString());
    return true;
}
Exemplo n.º 22
0
bool
HostInfoBase::ComputeProcessTempFileDirectory(FileSpec &file_spec)
{
    FileSpec temp_file_spec;
    if (!HostInfo::ComputeGlobalTempFileDirectory(temp_file_spec))
        return false;

    std::string pid_str{std::to_string(Host::GetCurrentProcessID())};
    temp_file_spec.AppendPathComponent(pid_str);
    if (!FileSystem::MakeDirectory(temp_file_spec, eFilePermissionsDirectoryDefault).Success())
        return false;

    // Make an atexit handler to clean up the process specify LLDB temp dir
    // and all of its contents.
    ::atexit(CleanupProcessSpecificLLDBTempDir);
    file_spec.GetDirectory().SetCString(temp_file_spec.GetCString());
    return true;
}
Exemplo n.º 23
0
uint32_t
Module::FindCompileUnits (const FileSpec &path,
                          bool append,
                          SymbolContextList &sc_list)
{
    if (!append)
        sc_list.Clear();
    
    const uint32_t start_size = sc_list.GetSize();
    const uint32_t num_compile_units = GetNumCompileUnits();
    SymbolContext sc;
    sc.module_sp = this;
    const bool compare_directory = path.GetDirectory();
    for (uint32_t i=0; i<num_compile_units; ++i)
    {
        sc.comp_unit = GetCompileUnitAtIndex(i).get();
        if (FileSpec::Equal (*sc.comp_unit, path, compare_directory))
            sc_list.Append(sc);
    }
    return sc_list.GetSize() - start_size;
}
Exemplo n.º 24
0
Error
Platform::Install (const FileSpec& src, const FileSpec& dst)
{
    Error error;
    
    Log *log = GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PLATFORM);
    if (log)
        log->Printf ("Platform::Install (src='%s', dst='%s')", src.GetPath().c_str(), dst.GetPath().c_str());
    FileSpec fixed_dst(dst);
    
    if (!fixed_dst.GetFilename())
        fixed_dst.GetFilename() = src.GetFilename();

    ConstString working_dir = GetWorkingDirectory();

    if (dst)
    {
        if (dst.GetDirectory())
        {
            const char first_dst_dir_char = dst.GetDirectory().GetCString()[0];
            if (first_dst_dir_char == '/' || first_dst_dir_char  == '\\')
            {
                fixed_dst.GetDirectory() = dst.GetDirectory();
            }
            // If the fixed destination file doesn't have a directory yet,
            // then we must have a relative path. We will resolve this relative
            // path against the platform's working directory
            if (!fixed_dst.GetDirectory())
            {
                FileSpec relative_spec;
                std::string path;
                if (working_dir)
                {
                    relative_spec.SetFile(working_dir.GetCString(), false);
                    relative_spec.AppendPathComponent(dst.GetPath().c_str());
                    fixed_dst.GetDirectory() = relative_spec.GetDirectory();
                }
                else
                {
                    error.SetErrorStringWithFormat("platform working directory must be valid for relative path '%s'", dst.GetPath().c_str());
                    return error;
                }
            }
        }
        else
        {
            if (working_dir)
            {
                fixed_dst.GetDirectory() = working_dir;
            }
            else
            {
                error.SetErrorStringWithFormat("platform working directory must be valid for relative path '%s'", dst.GetPath().c_str());
                return error;
            }
        }
    }
    else
    {
        if (working_dir)
        {
            fixed_dst.GetDirectory() = working_dir;
        }
        else
        {
            error.SetErrorStringWithFormat("platform working directory must be valid when destination directory is empty");
            return error;
        }
    }
    
    if (log)
        log->Printf ("Platform::Install (src='%s', dst='%s') fixed_dst='%s'", src.GetPath().c_str(), dst.GetPath().c_str(), fixed_dst.GetPath().c_str());

    if (GetSupportsRSync())
    {
        error = PutFile(src, dst);
    }
    else
    {
        switch (src.GetFileType())
        {
            case FileSpec::eFileTypeDirectory:
                {
                    if (GetFileExists (fixed_dst))
                        Unlink (fixed_dst.GetPath().c_str());
                    uint32_t permissions = src.GetPermissions();
                    if (permissions == 0)
                        permissions = eFilePermissionsDirectoryDefault;
                    std::string dst_dir_path(fixed_dst.GetPath());
                    error = MakeDirectory(dst_dir_path.c_str(), permissions);
                    if (error.Success())
                    {
                        // Make a filespec that only fills in the directory of a FileSpec so
                        // when we enumerate we can quickly fill in the filename for dst copies
                        FileSpec recurse_dst;
                        recurse_dst.GetDirectory().SetCString(dst_dir_path.c_str());
                        std::string src_dir_path (src.GetPath());
                        RecurseCopyBaton baton = { recurse_dst, this, Error() };
                        FileSpec::EnumerateDirectory(src_dir_path.c_str(), true, true, true, RecurseCopy_Callback, &baton);
                        return baton.error;
                    }
                }
                break;

            case FileSpec::eFileTypeRegular:
                if (GetFileExists (fixed_dst))
                    Unlink (fixed_dst.GetPath().c_str());
                error = PutFile(src, fixed_dst);
                break;

            case FileSpec::eFileTypeSymbolicLink:
                {
                    if (GetFileExists (fixed_dst))
                        Unlink (fixed_dst.GetPath().c_str());
                    char buf[PATH_MAX];
                    error = Host::Readlink(src.GetPath().c_str(), buf, sizeof(buf));
                    if (error.Success())
                        error = CreateSymlink(dst.GetPath().c_str(), buf);
                }
                break;
            case FileSpec::eFileTypePipe:
                error.SetErrorString("platform install doesn't handle pipes");
                break;
            case FileSpec::eFileTypeSocket:
                error.SetErrorString("platform install doesn't handle sockets");
                break;
            case FileSpec::eFileTypeInvalid:
            case FileSpec::eFileTypeUnknown:
            case FileSpec::eFileTypeOther:
                error.SetErrorString("platform install doesn't handle non file or directory items");
                break;
        }
    }
    return error;
}
Exemplo n.º 25
0
SourceManager::File::File(const FileSpec &file_spec, Target *target) :
    m_file_spec_orig (file_spec),
    m_file_spec(file_spec),
    m_mod_time (file_spec.GetModificationTime()),
    m_data_sp(),
    m_offsets()
{
    if (!m_mod_time.IsValid())
    {
        if (target)
        {
            if (!file_spec.GetDirectory() && file_spec.GetFilename())
            {
                // If this is just a file name, lets see if we can find it in the target:
                bool check_inlines = false;
                SymbolContextList sc_list;
                size_t num_matches = target->GetImages().ResolveSymbolContextForFilePath (file_spec.GetFilename().AsCString(),
                                                                                          0,
                                                                                          check_inlines,
                                                                                          lldb::eSymbolContextModule | lldb::eSymbolContextCompUnit,
                                                                                          sc_list);
                bool got_multiple = false;
                if (num_matches != 0)
                {
                    if (num_matches > 1)
                    {
                        SymbolContext sc;
                        FileSpec *test_cu_spec = NULL;

                        for (unsigned i = 0; i < num_matches; i++)
                        {
                            sc_list.GetContextAtIndex(i, sc);
                            if (sc.comp_unit)
                            {
                                if (test_cu_spec)
                                {
                                    if (test_cu_spec != static_cast<FileSpec *> (sc.comp_unit))
                                        got_multiple = true;
                                        break;
                                }
                                else
                                    test_cu_spec = sc.comp_unit;
                            }
                        }
                    }
                    if (!got_multiple)
                    {
                        SymbolContext sc;
                        sc_list.GetContextAtIndex (0, sc);
                        m_file_spec = sc.comp_unit;
                        m_mod_time = m_file_spec.GetModificationTime();
                    }
                }
            }
            // Try remapping if m_file_spec does not correspond to an existing file.
            if (!m_file_spec.Exists())
            {
                FileSpec new_file_spec;
                // Check target specific source remappings first, then fall back to
                // modules objects can have individual path remappings that were detected
                // when the debug info for a module was found.
                // then
                if (target->GetSourcePathMap().FindFile (m_file_spec, new_file_spec) ||
                    target->GetImages().FindSourceFile (m_file_spec, new_file_spec))
                {
                    m_file_spec = new_file_spec;
                    m_mod_time = m_file_spec.GetModificationTime();
                }
            }
        }
    }
    
    if (m_mod_time.IsValid())
        m_data_sp = m_file_spec.ReadFileContents ();
}
Exemplo n.º 26
0
uint32_t
CompileUnit::ResolveSymbolContext
(
    const FileSpec& file_spec,
    uint32_t line,
    bool check_inlines,
    bool exact,
    uint32_t resolve_scope,
    SymbolContextList &sc_list
)
{
    // First find all of the file indexes that match our "file_spec". If 
    // "file_spec" has an empty directory, then only compare the basenames
    // when finding file indexes
    std::vector<uint32_t> file_indexes;
    bool file_spec_matches_cu_file_spec = FileSpec::Equal(file_spec, *this, !file_spec.GetDirectory().IsEmpty());

    // If we are not looking for inlined functions and our file spec doesn't
    // match then we are done...
    if (file_spec_matches_cu_file_spec == false && check_inlines == false)
        return 0;

    uint32_t file_idx = GetSupportFiles().FindFileIndex (1, file_spec, true);
    while (file_idx != UINT32_MAX)
    {
        file_indexes.push_back (file_idx);
        file_idx = GetSupportFiles().FindFileIndex (file_idx + 1, file_spec, true);
    }
    
    const size_t num_file_indexes = file_indexes.size();
    if (num_file_indexes == 0)
        return 0;

    const uint32_t prev_size = sc_list.GetSize();

    SymbolContext sc(GetModule());
    sc.comp_unit = this;


    if (line != 0)
    {
        LineTable *line_table = sc.comp_unit->GetLineTable();

        if (line_table != NULL)
        {
            uint32_t found_line;
            uint32_t line_idx;
            
            if (num_file_indexes == 1)
            {
                // We only have a single support file that matches, so use
                // the line table function that searches for a line entries
                // that match a single support file index
                LineEntry line_entry;
                line_idx = line_table->FindLineEntryIndexByFileIndex (0, file_indexes.front(), line, exact, &line_entry);

                // If "exact == true", then "found_line" will be the same
                // as "line". If "exact == false", the "found_line" will be the
                // closest line entry with a line number greater than "line" and 
                // we will use this for our subsequent line exact matches below.
                found_line = line_entry.line;

                while (line_idx != UINT32_MAX)
                {
                    // If they only asked for the line entry, then we're done, we can just copy that over.
                    // But if they wanted more than just the line number, fill it in.
                    if (resolve_scope == eSymbolContextLineEntry)
                    {
                        sc.line_entry = line_entry;
                    }
                    else
                    {
                        line_entry.range.GetBaseAddress().CalculateSymbolContext(&sc, resolve_scope);
                    }
                    
                    sc_list.Append(sc);
                    line_idx = line_table->FindLineEntryIndexByFileIndex (line_idx + 1, file_indexes.front(), found_line, true, &line_entry);
                }
            }
            else
            {
                // We found multiple support files that match "file_spec" so use
                // the line table function that searches for a line entries
                // that match a multiple support file indexes.
                LineEntry line_entry;
                line_idx = line_table->FindLineEntryIndexByFileIndex (0, file_indexes, line, exact, &line_entry);

                // If "exact == true", then "found_line" will be the same
                // as "line". If "exact == false", the "found_line" will be the
                // closest line entry with a line number greater than "line" and 
                // we will use this for our subsequent line exact matches below.
                found_line = line_entry.line;

                while (line_idx != UINT32_MAX)
                {
                    if (resolve_scope == eSymbolContextLineEntry)
                    {
                        sc.line_entry = line_entry;
                    }
                    else
                    {
                        line_entry.range.GetBaseAddress().CalculateSymbolContext(&sc, resolve_scope);
                    }
                    
                    sc_list.Append(sc);
                    line_idx = line_table->FindLineEntryIndexByFileIndex (line_idx + 1, file_indexes, found_line, true, &line_entry);
                }
            }
        }
    }
    else if (file_spec_matches_cu_file_spec && !check_inlines)
    {
        // only append the context if we aren't looking for inline call sites
        // by file and line and if the file spec matches that of the compile unit
        sc_list.Append(sc);
    }
    return sc_list.GetSize() - prev_size;
}
Exemplo n.º 27
0
Error
PlatformRemoteiOS::ResolveExecutable (const FileSpec &exe_file,
                                      const ArchSpec &exe_arch,
                                      lldb::ModuleSP &exe_module_sp)
{
    Error error;
    // Nothing special to do here, just use the actual file and architecture

    FileSpec resolved_exe_file (exe_file);
    
    // If we have "ls" as the exe_file, resolve the executable loation based on
    // the current path variables
    // TODO: resolve bare executables in the Platform SDK
//    if (!resolved_exe_file.Exists())
//        resolved_exe_file.ResolveExecutableLocation ();

    // Resolve any executable within a bundle on MacOSX
    // TODO: verify that this handles shallow bundles, if not then implement one ourselves
    Host::ResolveExecutableInBundle (resolved_exe_file);

    if (resolved_exe_file.Exists())
    {
        if (exe_arch.IsValid())
        {
            error = ModuleList::GetSharedModule (resolved_exe_file, 
                                                 exe_arch, 
                                                 NULL,
                                                 NULL, 
                                                 0, 
                                                 exe_module_sp, 
                                                 NULL, 
                                                 NULL);
        
            if (exe_module_sp->GetObjectFile())
                return error;
            exe_module_sp.reset();
        }
        // No valid architecture was specified or the exact ARM slice wasn't
        // found so ask the platform for the architectures that we should be
        // using (in the correct order) and see if we can find a match that way
        StreamString arch_names;
        ArchSpec platform_arch;
        for (uint32_t idx = 0; GetSupportedArchitectureAtIndex (idx, platform_arch); ++idx)
        {
            error = ModuleList::GetSharedModule (resolved_exe_file, 
                                                 platform_arch, 
                                                 NULL,
                                                 NULL, 
                                                 0, 
                                                 exe_module_sp, 
                                                 NULL, 
                                                 NULL);
            // Did we find an executable using one of the 
            if (error.Success())
            {
                if (exe_module_sp && exe_module_sp->GetObjectFile())
                    break;
                else
                    error.SetErrorToGenericError();
            }
            
            if (idx > 0)
                arch_names.PutCString (", ");
            arch_names.PutCString (platform_arch.GetArchitectureName());
        }
        
        if (error.Fail() || !exe_module_sp)
        {
            error.SetErrorStringWithFormat ("'%s%s%s' doesn't contain any '%s' platform architectures: %s",
                                            exe_file.GetDirectory().AsCString(""),
                                            exe_file.GetDirectory() ? "/" : "",
                                            exe_file.GetFilename().AsCString(""),
                                            GetShortPluginName(),
                                            arch_names.GetString().c_str());
        }
    }
    else
    {
        error.SetErrorStringWithFormat ("'%s%s%s' does not exist",
                                        exe_file.GetDirectory().AsCString(""),
                                        exe_file.GetDirectory() ? "/" : "",
                                        exe_file.GetFilename().AsCString(""));
    }

    return error;
}
Exemplo n.º 28
0
Error
PlatformFreeBSD::ResolveExecutable (const FileSpec &exe_file,
                                    const ArchSpec &exe_arch,
                                    lldb::ModuleSP &exe_module_sp,
                                    const FileSpecList *module_search_paths_ptr)
{
    Error error;
    // Nothing special to do here, just use the actual file and architecture

    char exe_path[PATH_MAX];
    FileSpec resolved_exe_file (exe_file);

    if (IsHost())
    {
        // If we have "ls" as the exe_file, resolve the executable loation based on
        // the current path variables
        if (!resolved_exe_file.Exists())
        {
            exe_file.GetPath(exe_path, sizeof(exe_path));
            resolved_exe_file.SetFile(exe_path, true);
        }

        if (!resolved_exe_file.Exists())
            resolved_exe_file.ResolveExecutableLocation ();

        // Resolve any executable within a bundle on MacOSX
        //Host::ResolveExecutableInBundle (resolved_exe_file);

        if (resolved_exe_file.Exists())
            error.Clear();
        else
        {
            exe_file.GetPath(exe_path, sizeof(exe_path));
            error.SetErrorStringWithFormat("unable to find executable for '%s'", exe_path);
        }
    }
    else
    {
        if (m_remote_platform_sp)
        {
            error = m_remote_platform_sp->ResolveExecutable (exe_file,
                                                             exe_arch,
                                                             exe_module_sp,
                                                             module_search_paths_ptr);
        }
        else
        {
            // We may connect to a process and use the provided executable (Don't use local $PATH).
            
            // Resolve any executable within a bundle on MacOSX
            Host::ResolveExecutableInBundle (resolved_exe_file);
            
            if (resolved_exe_file.Exists()) {
                error.Clear();
            }
            else
            {
                exe_file.GetPath(exe_path, sizeof(exe_path));
                error.SetErrorStringWithFormat("the platform is not currently connected, and '%s' doesn't exist in the system root.", exe_path);
            }
        }
    }


    if (error.Success())
    {
        ModuleSpec module_spec (resolved_exe_file, exe_arch);
        if (module_spec.GetArchitecture().IsValid())
        {
            error = ModuleList::GetSharedModule (module_spec,
                                                 exe_module_sp,
                                                 module_search_paths_ptr,
                                                 NULL,
                                                 NULL);

            if (!exe_module_sp || exe_module_sp->GetObjectFile() == NULL)
            {
                exe_module_sp.reset();
                error.SetErrorStringWithFormat ("'%s%s%s' doesn't contain the architecture %s",
                                                exe_file.GetDirectory().AsCString(""),
                                                exe_file.GetDirectory() ? "/" : "",
                                                exe_file.GetFilename().AsCString(""),
                                                exe_arch.GetArchitectureName());
            }
        }
        else
        {
            // No valid architecture was specified, ask the platform for
            // the architectures that we should be using (in the correct order)
            // and see if we can find a match that way
            StreamString arch_names;
            ArchSpec platform_arch;
            for (uint32_t idx = 0; GetSupportedArchitectureAtIndex (idx, platform_arch); ++idx)
            {
                error = ModuleList::GetSharedModule (module_spec,
                                                     exe_module_sp,
                                                     module_search_paths_ptr,
                                                     NULL,
                                                     NULL);
                // Did we find an executable using one of the
                if (error.Success())
                {
                    if (exe_module_sp && exe_module_sp->GetObjectFile())
                        break;
                    else
                        error.SetErrorToGenericError();
                }

                if (idx > 0)
                    arch_names.PutCString (", ");
                arch_names.PutCString (platform_arch.GetArchitectureName());
            }

            if (error.Fail() || !exe_module_sp)
            {
                error.SetErrorStringWithFormat ("'%s%s%s' doesn't contain any '%s' platform architectures: %s",
                                                exe_file.GetDirectory().AsCString(""),
                                                exe_file.GetDirectory() ? "/" : "",
                                                exe_file.GetFilename().AsCString(""),
                                                GetShortPluginName(),
                                                arch_names.GetString().c_str());
            }
        }
    }
    else
    {
        error.SetErrorStringWithFormat ("'%s%s%s' does not exist",
                                        exe_file.GetDirectory().AsCString(""),
                                        exe_file.GetDirectory() ? "/" : "",
                                        exe_file.GetFilename().AsCString(""));
    }

    return error;
}
Exemplo n.º 29
0
bool
Host::GetLLDBPath (PathType path_type, FileSpec &file_spec)
{
    // To get paths related to LLDB we get the path to the executable that
    // contains this function. On MacOSX this will be "LLDB.framework/.../LLDB",
    // on linux this is assumed to be the "lldb" main executable. If LLDB on
    // linux is actually in a shared library (lldb.so??) then this function will
    // need to be modified to "do the right thing".

    switch (path_type)
    {
    case ePathTypeLLDBShlibDir:
        {
            static ConstString g_lldb_so_dir;
            if (!g_lldb_so_dir)
            {
                FileSpec lldb_file_spec (Host::GetModuleFileSpecForHostAddress ((void *)Host::GetLLDBPath));
                g_lldb_so_dir = lldb_file_spec.GetDirectory();
            }
            file_spec.GetDirectory() = g_lldb_so_dir;
            return file_spec.GetDirectory();
        }
        break;

    case ePathTypeSupportExecutableDir:  
        {
            static ConstString g_lldb_support_exe_dir;
            if (!g_lldb_support_exe_dir)
            {
                FileSpec lldb_file_spec;
                if (GetLLDBPath (ePathTypeLLDBShlibDir, lldb_file_spec))
                {
                    char raw_path[PATH_MAX];
                    char resolved_path[PATH_MAX];
                    lldb_file_spec.GetPath(raw_path, sizeof(raw_path));

#if defined (__APPLE__)
                    char *framework_pos = ::strstr (raw_path, "LLDB.framework");
                    if (framework_pos)
                    {
                        framework_pos += strlen("LLDB.framework");
#if !defined (__arm__)
                        ::strncpy (framework_pos, "/Resources", PATH_MAX - (framework_pos - raw_path));
#endif
                    }
#endif
                    FileSpec::Resolve (raw_path, resolved_path, sizeof(resolved_path));
                    g_lldb_support_exe_dir.SetCString(resolved_path);
                }
            }
            file_spec.GetDirectory() = g_lldb_support_exe_dir;
            return file_spec.GetDirectory();
        }
        break;

    case ePathTypeHeaderDir:
        {
            static ConstString g_lldb_headers_dir;
            if (!g_lldb_headers_dir)
            {
#if defined (__APPLE__)
                FileSpec lldb_file_spec;
                if (GetLLDBPath (ePathTypeLLDBShlibDir, lldb_file_spec))
                {
                    char raw_path[PATH_MAX];
                    char resolved_path[PATH_MAX];
                    lldb_file_spec.GetPath(raw_path, sizeof(raw_path));

                    char *framework_pos = ::strstr (raw_path, "LLDB.framework");
                    if (framework_pos)
                    {
                        framework_pos += strlen("LLDB.framework");
                        ::strncpy (framework_pos, "/Headers", PATH_MAX - (framework_pos - raw_path));
                    }
                    FileSpec::Resolve (raw_path, resolved_path, sizeof(resolved_path));
                    g_lldb_headers_dir.SetCString(resolved_path);
                }
#else
                // TODO: Anyone know how we can determine this for linux? Other systems??
                g_lldb_headers_dir.SetCString ("/opt/local/include/lldb");
#endif
            }
            file_spec.GetDirectory() = g_lldb_headers_dir;
            return file_spec.GetDirectory();
        }
        break;

    case ePathTypePythonDir:                
        {
            // TODO: Anyone know how we can determine this for linux? Other systems?
            // For linux we are currently assuming the location of the lldb
            // binary that contains this function is the directory that will 
            // contain lldb.so, lldb.py and embedded_interpreter.py...

            static ConstString g_lldb_python_dir;
            if (!g_lldb_python_dir)
            {
                FileSpec lldb_file_spec;
                if (GetLLDBPath (ePathTypeLLDBShlibDir, lldb_file_spec))
                {
                    char raw_path[PATH_MAX];
                    char resolved_path[PATH_MAX];
                    lldb_file_spec.GetPath(raw_path, sizeof(raw_path));

#if defined (__APPLE__)
                    char *framework_pos = ::strstr (raw_path, "LLDB.framework");
                    if (framework_pos)
                    {
                        framework_pos += strlen("LLDB.framework");
                        ::strncpy (framework_pos, "/Resources/Python", PATH_MAX - (framework_pos - raw_path));
                    }
#endif
                    FileSpec::Resolve (raw_path, resolved_path, sizeof(resolved_path));
                    g_lldb_python_dir.SetCString(resolved_path);
                }
            }
            file_spec.GetDirectory() = g_lldb_python_dir;
            return file_spec.GetDirectory();
        }
        break;
    
    case ePathTypeLLDBSystemPlugins:    // System plug-ins directory
        {
#if defined (__APPLE__)
            static ConstString g_lldb_system_plugin_dir;
            static bool g_lldb_system_plugin_dir_located = false;
            if (!g_lldb_system_plugin_dir_located)
            {
                g_lldb_system_plugin_dir_located = true;
                FileSpec lldb_file_spec;
                if (GetLLDBPath (ePathTypeLLDBShlibDir, lldb_file_spec))
                {
                    char raw_path[PATH_MAX];
                    char resolved_path[PATH_MAX];
                    lldb_file_spec.GetPath(raw_path, sizeof(raw_path));

                    char *framework_pos = ::strstr (raw_path, "LLDB.framework");
                    if (framework_pos)
                    {
                        framework_pos += strlen("LLDB.framework");
                        ::strncpy (framework_pos, "/Resources/PlugIns", PATH_MAX - (framework_pos - raw_path));
                        FileSpec::Resolve (raw_path, resolved_path, sizeof(resolved_path));
                        g_lldb_system_plugin_dir.SetCString(resolved_path);
                    }
                    return false;
                }
            }
            
            if (g_lldb_system_plugin_dir)
            {
                file_spec.GetDirectory() = g_lldb_system_plugin_dir;
                return true;
            }
#endif
            // TODO: where would system LLDB plug-ins be located on linux? Other systems?
            return false;
        }
        break;

    case ePathTypeLLDBUserPlugins:      // User plug-ins directory
        {
#if defined (__APPLE__)
            static ConstString g_lldb_user_plugin_dir;
            if (!g_lldb_user_plugin_dir)
            {
                char user_plugin_path[PATH_MAX];
                if (FileSpec::Resolve ("~/Library/Application Support/LLDB/PlugIns", 
                                       user_plugin_path, 
                                       sizeof(user_plugin_path)))
                {
                    g_lldb_user_plugin_dir.SetCString(user_plugin_path);
                }
            }
            file_spec.GetDirectory() = g_lldb_user_plugin_dir;
            return file_spec.GetDirectory();
#endif
            // TODO: where would user LLDB plug-ins be located on linux? Other systems?
            return false;
        }
    default:
        assert (!"Unhandled PathType");
        break;
    }

    return false;
}
Exemplo n.º 30
0
Error
TargetList::CreateTargetInternal (Debugger &debugger,
                                  const char *user_exe_path,
                                  const ArchSpec& specified_arch,
                                  bool get_dependent_files,
                                  lldb::PlatformSP &platform_sp,
                                  lldb::TargetSP &target_sp,
                                  bool is_dummy_target)
{

    Timer scoped_timer (__PRETTY_FUNCTION__,
                        "TargetList::CreateTarget (file = '%s', arch = '%s')",
                        user_exe_path,
                        specified_arch.GetArchitectureName());
    Error error;

    ArchSpec arch(specified_arch);

    if (arch.IsValid())
    {
        if (!platform_sp || !platform_sp->IsCompatibleArchitecture(arch, false, NULL))
            platform_sp = Platform::GetPlatformForArchitecture(specified_arch, &arch);
    }
    
    if (!platform_sp)
        platform_sp = debugger.GetPlatformList().GetSelectedPlatform();

    if (!arch.IsValid())
        arch = specified_arch;

    FileSpec file (user_exe_path, false);
    if (!file.Exists() && user_exe_path && user_exe_path[0] == '~')
    {
        // we want to expand the tilde but we don't want to resolve any symbolic links
        // so we can't use the FileSpec constructor's resolve flag
        llvm::SmallString<64> unglobbed_path(user_exe_path);
        FileSpec::ResolveUsername(unglobbed_path);

        if (unglobbed_path.empty())
            file = FileSpec(user_exe_path, false);
        else
            file = FileSpec(unglobbed_path.c_str(), false);
    }

    bool user_exe_path_is_bundle = false;
    char resolved_bundle_exe_path[PATH_MAX];
    resolved_bundle_exe_path[0] = '\0';
    if (file)
    {
        if (file.GetFileType() == FileSpec::eFileTypeDirectory)
            user_exe_path_is_bundle = true;

        if (file.IsRelative() && user_exe_path)
        {
            // Ignore paths that start with "./" and "../"
            if (!((user_exe_path[0] == '.' && user_exe_path[1] == '/') ||
                  (user_exe_path[0] == '.' && user_exe_path[1] == '.' && user_exe_path[2] == '/')))
            {
                char cwd[PATH_MAX];
                if (getcwd (cwd, sizeof(cwd)))
                {
                    std::string cwd_user_exe_path (cwd);
                    cwd_user_exe_path += '/';
                    cwd_user_exe_path += user_exe_path;
                    FileSpec cwd_file (cwd_user_exe_path.c_str(), false);
                    if (cwd_file.Exists())
                        file = cwd_file;
                }
            }
        }

        ModuleSP exe_module_sp;
        if (platform_sp)
        {
            FileSpecList executable_search_paths (Target::GetDefaultExecutableSearchPaths());
            ModuleSpec module_spec(file, arch);
            error = platform_sp->ResolveExecutable (module_spec,
                                                    exe_module_sp, 
                                                    executable_search_paths.GetSize() ? &executable_search_paths : NULL);
        }

        if (error.Success() && exe_module_sp)
        {
            if (exe_module_sp->GetObjectFile() == NULL)
            {
                if (arch.IsValid())
                {
                    error.SetErrorStringWithFormat("\"%s\" doesn't contain architecture %s",
                                                   file.GetPath().c_str(),
                                                   arch.GetArchitectureName());
                }
                else
                {
                    error.SetErrorStringWithFormat("unsupported file type \"%s\"",
                                                   file.GetPath().c_str());
                }
                return error;
            }
            target_sp.reset(new Target(debugger, arch, platform_sp, is_dummy_target));
            target_sp->SetExecutableModule (exe_module_sp, get_dependent_files);
            if (user_exe_path_is_bundle)
                exe_module_sp->GetFileSpec().GetPath(resolved_bundle_exe_path, sizeof(resolved_bundle_exe_path));
        }
    }
    else
    {
        // No file was specified, just create an empty target with any arch
        // if a valid arch was specified
        target_sp.reset(new Target(debugger, arch, platform_sp, is_dummy_target));
    }

    if (target_sp)
    {
        // Set argv0 with what the user typed, unless the user specified a
        // directory. If the user specified a directory, then it is probably a
        // bundle that was resolved and we need to use the resolved bundle path
        if (user_exe_path)
        {
            // Use exactly what the user typed as the first argument when we exec or posix_spawn
            if (user_exe_path_is_bundle && resolved_bundle_exe_path[0])
            {
                target_sp->SetArg0 (resolved_bundle_exe_path);
            }
            else
            {
                // Use resolved path
                target_sp->SetArg0 (file.GetPath().c_str());
            }
        }
        if (file.GetDirectory())
        {
            FileSpec file_dir;
            file_dir.GetDirectory() = file.GetDirectory();
            target_sp->GetExecutableSearchPaths ().Append (file_dir);
        }

        // Don't put the dummy target in the target list, it's held separately.
        if (!is_dummy_target)
        {
            Mutex::Locker locker(m_target_list_mutex);
            m_selected_target_idx = m_target_list.size();
            m_target_list.push_back(target_sp);
            // Now prime this from the dummy target:
            target_sp->PrimeFromDummyTarget(debugger.GetDummyTarget());
        }
        else
        {
            m_dummy_target_sp = target_sp;
        }
    }

    return error;
}