uint32_t SymbolFilePDB::ResolveSymbolContext( const lldb_private::FileSpec &file_spec, uint32_t line, bool check_inlines, uint32_t resolve_scope, lldb_private::SymbolContextList &sc_list) { if (resolve_scope & lldb::eSymbolContextCompUnit) { // Locate all compilation units with line numbers referencing the specified // file. For example, if // `file_spec` is <vector>, then this should return all source files and // header files that reference // <vector>, either directly or indirectly. auto compilands = m_session_up->findCompilandsForSourceFile( file_spec.GetPath(), PDB_NameSearchFlags::NS_CaseInsensitive); // For each one, either find get its previously parsed data, or parse it // afresh and add it to // the symbol context list. while (auto compiland = compilands->getNext()) { // If we're not checking inlines, then don't add line information for this // file unless the FileSpec // matches. if (!check_inlines) { // `getSourceFileName` returns the basename of the original source file // used to generate this compiland. // It does not return the full path. Currently the only way to get that // is to do a basename lookup to // get the IPDBSourceFile, but this is ambiguous in the case of two // source files with the same name // contributing to the same compiland. This is a moderately extreme // edge case, so we consider this ok // for now, although we need to find a long term solution. std::string source_file = compiland->getSourceFileName(); auto pdb_file = m_session_up->findOneSourceFile( compiland.get(), source_file, PDB_NameSearchFlags::NS_CaseInsensitive); source_file = pdb_file->getFileName(); FileSpec this_spec(source_file, false, FileSpec::ePathSyntaxWindows); if (!file_spec.FileEquals(this_spec)) continue; } SymbolContext sc; auto cu = ParseCompileUnitForSymIndex(compiland->getSymIndexId()); sc.comp_unit = cu.get(); sc.module_sp = cu->GetModule(); sc_list.Append(sc); // If we were asked to resolve line entries, add all entries to the line // table that match the requested // line (or all lines if `line` == 0) if (resolve_scope & lldb::eSymbolContextLineEntry) ParseCompileUnitLineTable(sc, line); } } return sc_list.GetSize(); }
lldb_private::Error PlatformMacOSX::GetFileWithUUID (const lldb_private::FileSpec &platform_file, const lldb_private::UUID *uuid_ptr, lldb_private::FileSpec &local_file) { if (IsRemote() && m_remote_platform_sp) { std::string local_os_build; #if !defined(__linux__) HostInfo::GetOSBuildString(local_os_build); #endif std::string remote_os_build; m_remote_platform_sp->GetOSBuildString(remote_os_build); if (local_os_build.compare(remote_os_build) == 0) { // same OS version: the local file is good enough local_file = platform_file; return Error(); } else { // try to find the file in the cache std::string cache_path(GetLocalCacheDirectory()); std::string module_path (platform_file.GetPath()); cache_path.append(module_path); FileSpec module_cache_spec(cache_path.c_str(),false); if (module_cache_spec.Exists()) { local_file = module_cache_spec; return Error(); } // bring in the remote module file FileSpec module_cache_folder = module_cache_spec.CopyByRemovingLastPathComponent(); // try to make the local directory first Error err = FileSystem::MakeDirectory(module_cache_folder, eFilePermissionsDirectoryDefault); if (err.Fail()) return err; err = GetFile(platform_file, module_cache_spec); if (err.Fail()) return err; if (module_cache_spec.Exists()) { local_file = module_cache_spec; return Error(); } else return Error("unable to obtain valid module file"); } } local_file = platform_file; return Error(); }
lldb_private::Error PlatformPOSIX::GetFile(const lldb_private::FileSpec &source, // remote file path const lldb_private::FileSpec &destination) // local file path { Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PLATFORM)); // Check the args, first. std::string src_path (source.GetPath()); if (src_path.empty()) return Error("unable to get file path for source"); std::string dst_path (destination.GetPath()); if (dst_path.empty()) return Error("unable to get file path for destination"); if (IsHost()) { if (FileSpec::Equal(source, destination, true)) return Error("local scenario->source and destination are the same file path: no operation performed"); // cp src dst StreamString cp_command; cp_command.Printf("cp %s %s", src_path.c_str(), dst_path.c_str()); int status; RunShellCommand(cp_command.GetData(), NULL, &status, NULL, NULL, 10); if (status != 0) return Error("unable to perform copy"); return Error(); } else if (m_remote_platform_sp) { if (GetSupportsRSync()) { StreamString command; if (GetIgnoresRemoteHostname()) { if (!GetRSyncPrefix()) command.Printf("rsync %s %s %s", GetRSyncOpts(), src_path.c_str(), dst_path.c_str()); else command.Printf("rsync %s %s%s %s", GetRSyncOpts(), GetRSyncPrefix(), src_path.c_str(), dst_path.c_str()); } else command.Printf("rsync %s %s:%s %s", GetRSyncOpts(), m_remote_platform_sp->GetHostname(), src_path.c_str(), dst_path.c_str()); if (log) log->Printf("[GetFile] Running command: %s\n", command.GetData()); int retcode; Host::RunShellCommand(command.GetData(), NULL, &retcode, NULL, NULL, 60); if (retcode == 0) return Error(); // If we are here, rsync has failed - let's try the slow way before giving up } // open src and dst // read/write, read/write, read/write, ... // close src // close dst if (log) log->Printf("[GetFile] Using block by block transfer....\n"); Error error; user_id_t fd_src = OpenFile (source, File::eOpenOptionRead, lldb::eFilePermissionsFileDefault, error); if (fd_src == UINT64_MAX) return Error("unable to open source file"); uint32_t permissions = 0; error = GetFilePermissions(source, permissions); if (permissions == 0) permissions = lldb::eFilePermissionsFileDefault; user_id_t fd_dst = FileCache::GetInstance().OpenFile( destination, File::eOpenOptionCanCreate | File::eOpenOptionWrite | File::eOpenOptionTruncate, permissions, error); if (fd_dst == UINT64_MAX) { if (error.Success()) error.SetErrorString("unable to open destination file"); } if (error.Success()) { lldb::DataBufferSP buffer_sp(new DataBufferHeap(1024, 0)); uint64_t offset = 0; error.Clear(); while (error.Success()) { const uint64_t n_read = ReadFile (fd_src, offset, buffer_sp->GetBytes(), buffer_sp->GetByteSize(), error); if (error.Fail()) break; if (n_read == 0) break; if (FileCache::GetInstance().WriteFile(fd_dst, offset, buffer_sp->GetBytes(), n_read, error) != n_read) { if (!error.Fail()) error.SetErrorString("unable to write to destination file"); break; } offset += n_read; } } // Ignore the close error of src. if (fd_src != UINT64_MAX) CloseFile(fd_src, error); // And close the dst file descriptot. if (fd_dst != UINT64_MAX && !FileCache::GetInstance().CloseFile(fd_dst, error)) { if (!error.Fail()) error.SetErrorString("unable to close destination file"); } return error; } return Platform::GetFile(source,destination); }
lldb_private::Error PlatformPOSIX::PutFile (const lldb_private::FileSpec& source, const lldb_private::FileSpec& destination, uint32_t uid, uint32_t gid) { Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PLATFORM)); if (IsHost()) { if (FileSpec::Equal(source, destination, true)) return Error(); // cp src dst // chown uid:gid dst std::string src_path (source.GetPath()); if (src_path.empty()) return Error("unable to get file path for source"); std::string dst_path (destination.GetPath()); if (dst_path.empty()) return Error("unable to get file path for destination"); StreamString command; command.Printf("cp %s %s", src_path.c_str(), dst_path.c_str()); int status; RunShellCommand(command.GetData(), NULL, &status, NULL, NULL, 10); if (status != 0) return Error("unable to perform copy"); if (uid == UINT32_MAX && gid == UINT32_MAX) return Error(); if (chown_file(this,dst_path.c_str(),uid,gid) != 0) return Error("unable to perform chown"); return Error(); } else if (m_remote_platform_sp) { if (GetSupportsRSync()) { std::string src_path (source.GetPath()); if (src_path.empty()) return Error("unable to get file path for source"); std::string dst_path (destination.GetPath()); if (dst_path.empty()) return Error("unable to get file path for destination"); StreamString command; if (GetIgnoresRemoteHostname()) { if (!GetRSyncPrefix()) command.Printf("rsync %s %s %s", GetRSyncOpts(), src_path.c_str(), dst_path.c_str()); else command.Printf("rsync %s %s %s%s", GetRSyncOpts(), src_path.c_str(), GetRSyncPrefix(), dst_path.c_str()); } else command.Printf("rsync %s %s %s:%s", GetRSyncOpts(), src_path.c_str(), GetHostname(), dst_path.c_str()); if (log) log->Printf("[PutFile] Running command: %s\n", command.GetData()); int retcode; Host::RunShellCommand(command.GetData(), NULL, &retcode, NULL, NULL, 60); if (retcode == 0) { // Don't chown a local file for a remote system // if (chown_file(this,dst_path.c_str(),uid,gid) != 0) // return Error("unable to perform chown"); return Error(); } // if we are still here rsync has failed - let's try the slow way before giving up } } return Platform::PutFile(source,destination,uid,gid); }