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; }
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(); }
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; }
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; }
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; }
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; }
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(); }
//------------------------------------------------------------------ // 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; }
bool HostInfoLinux::ComputeSystemPluginsDirectory(FileSpec &file_spec) { FileSpec temp_file("/usr/lib/lldb", true); file_spec.GetDirectory().SetCString(temp_file.GetPath().c_str()); return true; }
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; }
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 ()); }
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(); }
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; }
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; }
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; }
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 }
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; }
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(); }
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; }
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(); }
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; }
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; }
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; }
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; }
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 (); }
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; }
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; }
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; }
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; }
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; }