Index: include/lldb/Core/ModuleSpec.h =================================================================== --- include/lldb/Core/ModuleSpec.h +++ include/lldb/Core/ModuleSpec.h @@ -14,6 +14,7 @@ #include "lldb/Core/Stream.h" #include "lldb/Core/UUID.h" #include "lldb/Host/FileSpec.h" +#include "lldb/Host/Mutex.h" #include "lldb/Target/PathMappingList.h" namespace lldb_private { @@ -29,6 +30,7 @@ m_uuid (), m_object_name (), m_object_offset (0), + m_object_size (0), m_object_mod_time (), m_source_mappings () { @@ -42,6 +44,7 @@ m_uuid (), m_object_name (), m_object_offset (0), + m_object_size (file_spec.GetByteSize ()), m_object_mod_time (), m_source_mappings () { @@ -55,6 +58,7 @@ m_uuid (), m_object_name (), m_object_offset (0), + m_object_size (file_spec.GetByteSize ()), m_object_mod_time (), m_source_mappings () { @@ -68,6 +72,7 @@ m_uuid (rhs.m_uuid), m_object_name (rhs.m_object_name), m_object_offset (rhs.m_object_offset), + m_object_size (rhs.m_object_size), m_object_mod_time (rhs.m_object_mod_time), m_source_mappings (rhs.m_source_mappings) { @@ -85,6 +90,7 @@ m_uuid = rhs.m_uuid; m_object_name = rhs.m_object_name; m_object_offset = rhs.m_object_offset; + m_object_size = rhs.m_object_size; m_object_mod_time = rhs.m_object_mod_time; m_source_mappings = rhs.m_source_mappings; } @@ -254,7 +260,19 @@ { m_object_offset = object_offset; } - + + uint64_t + GetObjectSize () const + { + return m_object_size; + } + + void + SetObjectSize (uint64_t object_size) + { + m_object_size = object_size; + } + TimeValue & GetObjectModificationTime () { @@ -283,6 +301,7 @@ m_uuid.Clear(); m_object_name.Clear(); m_object_offset = 0; + m_object_size = 0; m_source_mappings.Clear(false); m_object_mod_time.Clear(); } @@ -302,6 +321,8 @@ return true; if (m_object_name) return true; + if (m_object_size) + return true; if (m_object_mod_time.IsValid()) return true; return false; @@ -362,7 +383,14 @@ { if (dumped_something) strm.PutCString(", "); - strm.Printf("object_offset = 0x%" PRIx64, m_object_offset); + strm.Printf("object_offset = %" PRIu64, m_object_offset); + dumped_something = true; + } + if (m_object_size > 0) + { + if (dumped_something) + strm.PutCString(", "); + strm.Printf("object size = %" PRIu64, m_object_size); dumped_something = true; } if (m_object_mod_time.IsValid()) @@ -425,6 +453,7 @@ UUID m_uuid; ConstString m_object_name; uint64_t m_object_offset; + uint64_t m_object_size; TimeValue m_object_mod_time; mutable PathMappingList m_source_mappings; }; Index: include/lldb/Host/HostInfoBase.h =================================================================== --- include/lldb/Host/HostInfoBase.h +++ include/lldb/Host/HostInfoBase.h @@ -115,7 +115,8 @@ protected: static bool ComputeSharedLibraryDirectory(FileSpec &file_spec); static bool ComputeSupportExeDirectory(FileSpec &file_spec); - static bool ComputeTempFileDirectory(FileSpec &file_spec); + static bool ComputeProcessTempFileDirectory(FileSpec &file_spec); + static bool ComputeGlobalTempFileDirectory(FileSpec &file_spec); static bool ComputeHeaderDirectory(FileSpec &file_spec); static bool ComputeSystemPluginsDirectory(FileSpec &file_spec); static bool ComputeClangDirectory(FileSpec &file_spec); Index: include/lldb/Target/Platform.h =================================================================== --- include/lldb/Target/Platform.h +++ include/lldb/Target/Platform.h @@ -13,6 +13,7 @@ // C Includes // C++ Includes #include +#include #include #include @@ -23,6 +24,7 @@ #include "lldb/Core/ArchSpec.h" #include "lldb/Core/ConstString.h" #include "lldb/Core/PluginInterface.h" +#include "lldb/Core/UserSettingsController.h" #include "lldb/Interpreter/Options.h" #include "lldb/Host/Mutex.h" @@ -32,6 +34,29 @@ namespace lldb_private { +class ModuleCache; + + class PlatformProperties : public Properties + { + public: + static ConstString + GetSettingName (); + + PlatformProperties(); + + bool + GetUseModuleCache () const; + bool + SetUseModuleCache (bool use_module_cache); + + FileSpec + GetModuleCacheDirectory () const; + bool + SetModuleCacheDirectory (const FileSpec& dir_spec); + }; + + typedef std::shared_ptr PlatformPropertiesSP; + //---------------------------------------------------------------------- /// @class Platform Platform.h "lldb/Target/Platform.h" /// @brief A plug-in interface definition class for debug platform that @@ -49,13 +74,15 @@ public PluginInterface { public: - static void Initialize (); static void Terminate (); + static const PlatformPropertiesSP & + GetGlobalPlatformProperties (); + //------------------------------------------------------------------ /// Get the native host platform plug-in. /// @@ -350,6 +377,11 @@ lldb::ModuleSP *old_module_sp_ptr, bool *did_create_ptr); + virtual bool + GetModuleSpec (const FileSpec& module_file_spec, + const ArchSpec& arch, + ModuleSpec &module_spec); + virtual Error ConnectRemote (Args& args); @@ -988,6 +1020,7 @@ std::string m_local_cache_directory; std::vector m_trap_handlers; bool m_calculated_trap_handlers; + const std::unique_ptr m_module_cache; //------------------------------------------------------------------ /// Ask the Platform subclass to fill in the list of trap handler names @@ -1090,6 +1123,22 @@ m_gid_map.clear(); } + bool + GetCachedSharedModule (const ModuleSpec &module_spec, + lldb::ModuleSP &module_sp); + + Error + DownloadModuleSlice (const FileSpec& src_file_spec, + const uint64_t src_offset, + const uint64_t src_size, + const FileSpec& dst_file_spec); + + bool + GetFileFromLocalCache (const ModuleSpec& module_spec, + FileSpec &cached_file_spec); + + FileSpec GetModuleCacheRoot (); + private: DISALLOW_COPY_AND_ASSIGN (Platform); }; Index: include/lldb/lldb-enumerations.h =================================================================== --- include/lldb/lldb-enumerations.h +++ include/lldb/lldb-enumerations.h @@ -860,14 +860,15 @@ //---------------------------------------------------------------------- typedef enum PathType { - ePathTypeLLDBShlibDir, // The directory where the lldb.so (unix) or LLDB mach-o file in LLDB.framework (MacOSX) exists - ePathTypeSupportExecutableDir, // Find LLDB support executable directory (debugserver, etc) - ePathTypeHeaderDir, // Find LLDB header file directory - ePathTypePythonDir, // Find Python modules (PYTHONPATH) directory - ePathTypeLLDBSystemPlugins, // System plug-ins directory - ePathTypeLLDBUserPlugins, // User plug-ins directory - ePathTypeLLDBTempSystemDir, // The LLDB temp directory for this system that will be cleaned up on exit - ePathTypeClangDir // Find path to Clang builtin headers + ePathTypeLLDBShlibDir, // The directory where the lldb.so (unix) or LLDB mach-o file in LLDB.framework (MacOSX) exists + ePathTypeSupportExecutableDir, // Find LLDB support executable directory (debugserver, etc) + ePathTypeHeaderDir, // Find LLDB header file directory + ePathTypePythonDir, // Find Python modules (PYTHONPATH) directory + ePathTypeLLDBSystemPlugins, // System plug-ins directory + ePathTypeLLDBUserPlugins, // User plug-ins directory + ePathTypeLLDBTempSystemDir, // The LLDB temp directory for this system that will be cleaned up on exit + ePathTypeGlobalLLDBTempSystemDir, // The LLDB temp directory for this system, NOT cleaned up on a process exit. + ePathTypeClangDir // Find path to Clang builtin headers } PathType; //---------------------------------------------------------------------- Index: lldb.xcodeproj/project.pbxproj =================================================================== --- lldb.xcodeproj/project.pbxproj +++ lldb.xcodeproj/project.pbxproj @@ -98,6 +98,8 @@ 254FBB971A81B03100BD6378 /* SBLaunchInfo.h in Headers */ = {isa = PBXBuildFile; fileRef = 254FBB961A81B03100BD6378 /* SBLaunchInfo.h */; settings = {ATTRIBUTES = (Public, ); }; }; 254FBBA31A9166F100BD6378 /* SBAttachInfo.h in Headers */ = {isa = PBXBuildFile; fileRef = 254FBBA21A9166F100BD6378 /* SBAttachInfo.h */; settings = {ATTRIBUTES = (Public, ); }; }; 254FBBA51A91670E00BD6378 /* SBAttachInfo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 254FBBA41A91670E00BD6378 /* SBAttachInfo.cpp */; }; + 257E47171AA56C2000A62F81 /* ModuleCache.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 257E47151AA56C2000A62F81 /* ModuleCache.cpp */; }; + 257E47181AA56C2000A62F81 /* ModuleCache.h in Headers */ = {isa = PBXBuildFile; fileRef = 257E47161AA56C2000A62F81 /* ModuleCache.h */; }; 260157C61885F51C00F875CF /* libpanel.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 260157C41885F4FF00F875CF /* libpanel.dylib */; }; 260157C81885F53100F875CF /* libpanel.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 260157C41885F4FF00F875CF /* libpanel.dylib */; }; 2606EDDF184E68A10034641B /* liblldb-core.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 2689FFCA13353D7A00698AC0 /* liblldb-core.a */; }; @@ -1213,6 +1215,8 @@ 254FBBA21A9166F100BD6378 /* SBAttachInfo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SBAttachInfo.h; path = include/lldb/API/SBAttachInfo.h; sourceTree = ""; }; 254FBBA41A91670E00BD6378 /* SBAttachInfo.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SBAttachInfo.cpp; path = source/API/SBAttachInfo.cpp; sourceTree = ""; }; 254FBBA61A91672800BD6378 /* SBAttachInfo.i */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c.preprocessed; path = SBAttachInfo.i; sourceTree = ""; }; + 257E47151AA56C2000A62F81 /* ModuleCache.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ModuleCache.cpp; path = source/Utility/ModuleCache.cpp; sourceTree = ""; }; + 257E47161AA56C2000A62F81 /* ModuleCache.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ModuleCache.h; path = source/Utility/ModuleCache.h; sourceTree = ""; }; 260157C41885F4FF00F875CF /* libpanel.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libpanel.dylib; path = /usr/lib/libpanel.dylib; sourceTree = ""; }; 260223E7115F06D500A601A2 /* SBCommunication.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SBCommunication.h; path = include/lldb/API/SBCommunication.h; sourceTree = ""; }; 260223E8115F06E500A601A2 /* SBCommunication.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SBCommunication.cpp; path = source/API/SBCommunication.cpp; sourceTree = ""; }; @@ -3448,6 +3452,8 @@ 2682F168115ED9C800CCFF99 /* Utility */ = { isa = PBXGroup; children = ( + 257E47151AA56C2000A62F81 /* ModuleCache.cpp */, + 257E47161AA56C2000A62F81 /* ModuleCache.h */, 33064C9B1A5C7A490033D415 /* UriParser.h */, 33064C991A5C7A330033D415 /* UriParser.cpp */, AF9107E91685709A00DBCD3C /* ARM64_GCC_Registers.h */, @@ -5212,6 +5218,7 @@ buildActionMask = 2147483647; files = ( 26A527C214E24F5F00F3A14A /* ProcessMachCore.h in Headers */, + 257E47181AA56C2000A62F81 /* ModuleCache.h in Headers */, 26BC17AC18C7F4CB00D2196D /* ProcessElfCore.h in Headers */, 26A527C414E24F5F00F3A14A /* ThreadMachCore.h in Headers */, 26474CD318D0CB710073DEBA /* RegisterInfos_i386.h in Headers */, @@ -5976,6 +5983,7 @@ 25420ED21A649D88009ADBCB /* PipeBase.cpp in Sources */, 2689007313353E1A00698AC0 /* Symbols.cpp in Sources */, 26474CBC18D0CB2D0073DEBA /* RegisterContextMach_arm.cpp in Sources */, + 257E47171AA56C2000A62F81 /* ModuleCache.cpp in Sources */, 2689007413353E1A00698AC0 /* Terminal.cpp in Sources */, 2689007513353E1A00698AC0 /* TimeValue.cpp in Sources */, 2689007613353E1A00698AC0 /* CFCBundle.cpp in Sources */, Index: source/Core/Debugger.cpp =================================================================== --- source/Core/Debugger.cpp +++ source/Core/Debugger.cpp @@ -697,6 +697,10 @@ ConstString("Settings specify to debugging targets."), true, Target::GetGlobalProperties()->GetValueProperties()); + m_collection_sp->AppendProperty (ConstString("platform"), + ConstString("Platform settings."), + true, + Platform::GetGlobalPlatformProperties()->GetValueProperties()); if (m_command_interpreter_ap.get()) { m_collection_sp->AppendProperty (ConstString("interpreter"), Index: source/Core/UUID.cpp =================================================================== --- source/Core/UUID.cpp +++ source/Core/UUID.cpp @@ -234,7 +234,10 @@ // If we successfully decoded a UUID, return the amount of characters that // were consumed if (uuid_byte_idx == num_uuid_bytes) + { + m_num_uuid_bytes = num_uuid_bytes; return p - cstr; + } // Else return zero to indicate we were not able to parse a UUID value return 0; Index: source/Host/common/HostInfoBase.cpp =================================================================== --- source/Host/common/HostInfoBase.cpp +++ source/Host/common/HostInfoBase.cpp @@ -68,7 +68,8 @@ FileSpec m_lldb_clang_resource_dir; FileSpec m_lldb_system_plugin_dir; FileSpec m_lldb_user_plugin_dir; - FileSpec m_lldb_tmp_dir; + FileSpec m_lldb_process_tmp_dir; + FileSpec m_lldb_global_tmp_dir; }; HostInfoBaseFields *g_fields = nullptr; @@ -263,13 +264,27 @@ static std::once_flag g_once_flag; static bool success = false; std::call_once(g_once_flag, []() { - success = HostInfo::ComputeTempFileDirectory (g_fields->m_lldb_tmp_dir); + success = HostInfo::ComputeProcessTempFileDirectory (g_fields->m_lldb_process_tmp_dir); Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST); if (log) - log->Printf("HostInfoBase::GetLLDBPath(ePathTypeLLDBTempSystemDir) => '%s'", g_fields->m_lldb_tmp_dir.GetPath().c_str()); + log->Printf("HostInfoBase::GetLLDBPath(ePathTypeLLDBTempSystemDir) => '%s'", g_fields->m_lldb_process_tmp_dir.GetPath().c_str()); }); if (success) - result = &g_fields->m_lldb_tmp_dir; + result = &g_fields->m_lldb_process_tmp_dir; + } + break; + case lldb::ePathTypeGlobalLLDBTempSystemDir: + { + static std::once_flag g_once_flag; + static bool success = false; + std::call_once(g_once_flag, []() { + success = HostInfo::ComputeGlobalTempFileDirectory (g_fields->m_lldb_global_tmp_dir); + Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST); + if (log) + log->Printf("HostInfoBase::GetLLDBPath(ePathTypeGlobalLLDBTempSystemDir) => '%s'", g_fields->m_lldb_global_tmp_dir.GetPath().c_str()); + }); + if (success) + result = &g_fields->m_lldb_global_tmp_dir; } break; } @@ -305,8 +320,32 @@ } bool -HostInfoBase::ComputeTempFileDirectory(FileSpec &file_spec) +HostInfoBase::ComputeProcessTempFileDirectory(FileSpec &file_spec) { + FileSpec temp_file_spec; + if (!ComputeGlobalTempFileDirectory(temp_file_spec)) + return false; + + std::string pid_str; + llvm::raw_string_ostream pid_stream(pid_str); + pid_stream << Host::GetCurrentProcessID(); + temp_file_spec.AppendPathComponent(pid_stream.str().c_str()); + std::string final_path = temp_file_spec.GetPath(); + if (!FileSystem::MakeDirectory(final_path.c_str(), 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().SetCStringWithLength(final_path.c_str(), final_path.size()); + return true; +} + +bool +HostInfoBase::ComputeGlobalTempFileDirectory(FileSpec &file_spec) +{ + file_spec.Clear(); + const char *tmpdir_cstr = getenv("TMPDIR"); if (tmpdir_cstr == NULL) { @@ -322,18 +361,7 @@ if (!FileSystem::MakeDirectory(temp_file_spec.GetPath().c_str(), eFilePermissionsDirectoryDefault).Success()) return false; - std::string pid_str; - llvm::raw_string_ostream pid_stream(pid_str); - pid_stream << Host::GetCurrentProcessID(); - temp_file_spec.AppendPathComponent(pid_stream.str().c_str()); - std::string final_path = temp_file_spec.GetPath(); - if (!FileSystem::MakeDirectory(final_path.c_str(), 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().SetCStringWithLength(final_path.c_str(), final_path.size()); + file_spec = temp_file_spec; return true; } Index: source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOSXDYLD.cpp =================================================================== --- source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOSXDYLD.cpp +++ source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOSXDYLD.cpp @@ -851,6 +851,7 @@ if (!commpage_image_module_sp) { module_spec.SetObjectOffset (objfile->GetFileOffset() + commpage_section->GetFileOffset()); + module_spec.SetObjectSize (objfile->GetByteSize()); commpage_image_module_sp = target.GetSharedModule (module_spec); if (!commpage_image_module_sp || commpage_image_module_sp->GetObjectFile() == NULL) { Index: source/Plugins/ObjectContainer/BSD-Archive/ObjectContainerBSDArchive.cpp =================================================================== --- source/Plugins/ObjectContainer/BSD-Archive/ObjectContainerBSDArchive.cpp +++ source/Plugins/ObjectContainer/BSD-Archive/ObjectContainerBSDArchive.cpp @@ -595,7 +595,8 @@ TimeValue object_mod_time; object_mod_time.OffsetWithSeconds(object->ar_date); spec.GetObjectName () = object->ar_name; - spec.SetObjectOffset(object_file_offset); + spec.SetObjectOffset (object_file_offset); + spec.SetObjectSize (file_size - object_file_offset); spec.GetObjectModificationTime () = object_mod_time; } } Index: source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp =================================================================== --- source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp +++ source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp @@ -604,8 +604,7 @@ { if (data_sp) { - ModuleSpec spec; - spec.GetFileSpec() = file; + ModuleSpec spec (file); const uint32_t sub_type = subTypeFromElfHeader(header); spec.GetArchitecture().SetArchitecture(eArchTypeELF, Index: source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp =================================================================== --- source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp +++ source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp @@ -995,7 +995,8 @@ ModuleSpec spec; spec.GetFileSpec() = file; spec.SetObjectOffset(file_offset); - + spec.SetObjectSize(length); + if (GetArchitecture (header, data, data_offset, spec.GetArchitecture())) { if (spec.GetArchitecture().IsValid()) Index: source/Plugins/Platform/FreeBSD/PlatformFreeBSD.h =================================================================== --- source/Plugins/Platform/FreeBSD/PlatformFreeBSD.h +++ source/Plugins/Platform/FreeBSD/PlatformFreeBSD.h @@ -71,6 +71,11 @@ //------------------------------------------------------------ // lldb_private::Platform functions //------------------------------------------------------------ + virtual bool + GetModuleSpec (const lldb_private::FileSpec& module_file_spec, + const lldb_private::ArchSpec& arch, + lldb_private::ModuleSpec &module_spec); + virtual lldb_private::Error RunShellCommand (const char *command, const char *working_dir, Index: source/Plugins/Platform/FreeBSD/PlatformFreeBSD.cpp =================================================================== --- source/Plugins/Platform/FreeBSD/PlatformFreeBSD.cpp +++ source/Plugins/Platform/FreeBSD/PlatformFreeBSD.cpp @@ -165,6 +165,18 @@ } //TODO:VK: inherit PlatformPOSIX + +bool +PlatformFreeBSD::GetModuleSpec (const FileSpec& module_file_spec, + const ArchSpec& arch, + ModuleSpec &module_spec) +{ + if (m_remote_platform_sp) + return m_remote_platform_sp->GetModuleSpec (module_file_spec, arch, module_spec); + + return Platform::GetModuleSpec (module_file_spec, arch, module_spec); +} + lldb_private::Error PlatformFreeBSD::RunShellCommand (const char *command, const char *working_dir, Index: source/Plugins/Platform/POSIX/PlatformPOSIX.h =================================================================== --- source/Plugins/Platform/POSIX/PlatformPOSIX.h +++ source/Plugins/Platform/POSIX/PlatformPOSIX.h @@ -31,6 +31,12 @@ //------------------------------------------------------------ // lldb_private::Platform functions //------------------------------------------------------------ + + virtual bool + GetModuleSpec (const lldb_private::FileSpec& module_file_spec, + const lldb_private::ArchSpec& arch, + lldb_private::ModuleSpec &module_spec); + virtual lldb_private::OptionGroupOptions *GetConnectionOptions( lldb_private::CommandInterpreter &interpreter) override; @@ -115,7 +121,7 @@ int *signo_ptr, // Pass NULL if you don't want the signal that caused the process to exit std::string *command_output, // Pass NULL if you don't want the command output uint32_t timeout_sec) override;// Timeout in seconds to wait for shell program to finish - + virtual lldb_private::Error MakeDirectory (const char *path, uint32_t mode) override; Index: source/Plugins/Platform/POSIX/PlatformPOSIX.cpp =================================================================== --- source/Plugins/Platform/POSIX/PlatformPOSIX.cpp +++ source/Plugins/Platform/POSIX/PlatformPOSIX.cpp @@ -50,6 +50,17 @@ { } +bool +PlatformPOSIX::GetModuleSpec (const FileSpec& module_file_spec, + const ArchSpec& arch, + ModuleSpec &module_spec) +{ + if (m_remote_platform_sp) + return m_remote_platform_sp->GetModuleSpec (module_file_spec, arch, module_spec); + + return Platform::GetModuleSpec (module_file_spec, arch, module_spec); +} + lldb_private::OptionGroupOptions* PlatformPOSIX::GetConnectionOptions (lldb_private::CommandInterpreter& interpreter) { Index: source/Plugins/Platform/Windows/PlatformWindows.h =================================================================== --- source/Plugins/Platform/Windows/PlatformWindows.h +++ source/Plugins/Platform/Windows/PlatformWindows.h @@ -59,6 +59,11 @@ //------------------------------------------------------------ // lldb_private::Platform functions //------------------------------------------------------------ + virtual bool + GetModuleSpec (const lldb_private::FileSpec& module_file_spec, + const lldb_private::ArchSpec& arch, + lldb_private::ModuleSpec &module_spec); + virtual Error ResolveExecutable(const lldb_private::ModuleSpec &module_spec, lldb::ModuleSP &module_sp, Index: source/Plugins/Platform/Windows/PlatformWindows.cpp =================================================================== --- source/Plugins/Platform/Windows/PlatformWindows.cpp +++ source/Plugins/Platform/Windows/PlatformWindows.cpp @@ -201,6 +201,17 @@ { } +bool +PlatformWindows::GetModuleSpec (const FileSpec& module_file_spec, + const ArchSpec& arch, + ModuleSpec &module_spec) +{ + if (m_remote_platform_sp) + return m_remote_platform_sp->GetModuleSpec (module_file_spec, arch, module_spec); + + return Platform::GetModuleSpec (module_file_spec, arch, module_spec); +} + Error PlatformWindows::ResolveExecutable (const ModuleSpec &ms, lldb::ModuleSP &exe_module_sp, Index: source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.h =================================================================== --- source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.h +++ source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.h @@ -68,6 +68,11 @@ lldb::ModuleSP &module_sp, const lldb_private::FileSpecList *module_search_paths_ptr); + virtual bool + GetModuleSpec (const lldb_private::FileSpec& module_file_spec, + const lldb_private::ArchSpec& arch, + lldb_private::ModuleSpec &module_spec); + virtual const char * GetDescription (); @@ -127,7 +132,6 @@ virtual bool SetRemoteWorkingDirectory(const lldb_private::ConstString &path); - // Remote subclasses should override this and return a valid instance // name if connected. Index: source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.cpp =================================================================== --- source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.cpp +++ source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.cpp @@ -27,6 +27,8 @@ #include "lldb/Host/ConnectionFileDescriptor.h" #include "lldb/Host/FileSpec.h" #include "lldb/Host/Host.h" +#include "lldb/Host/HostInfo.h" +#include "lldb/Host/StringConvert.h" #include "lldb/Target/Process.h" #include "lldb/Target/Target.h" @@ -196,6 +198,73 @@ return error; } +bool +PlatformRemoteGDBServer::GetModuleSpec (const FileSpec& module_file_spec, + const ArchSpec& arch, + ModuleSpec &module_spec) +{ + Log *log = GetLogIfAnyCategoriesSet (LIBLLDB_LOG_PLATFORM); + + const auto module_path = module_file_spec.GetPath (); + + StringExtractorGDBRemote response; + if (!m_gdb_client.GetModuleInfo (module_path.c_str (), arch, response)) + { + if (log) + log->Printf ("PlatformRemoteGDBServer::%s - failed to get module info for %s:%s", + __FUNCTION__, module_path.c_str (), arch.GetTriple ().getTriple ().c_str ()); + return false; + } + + std::string name; + std::string value; + bool success; + StringExtractor extractor; + + module_spec.Clear (); + module_spec.GetFileSpec () = module_file_spec; + + while (response.GetNameColonValue (name, value)) + { + if (name == "uuid" || name == "md5") + { + extractor.GetStringRef ().swap (value); + extractor.SetFilePos (0); + extractor.GetHexByteString (value); + module_spec.GetUUID().SetFromCString (value.c_str(), value.size() / 2); + } + else if (name == "triple") + { + extractor.GetStringRef ().swap (value); + extractor.SetFilePos (0); + extractor.GetHexByteString (value); + module_spec.GetArchitecture().SetTriple (value.c_str ()); + } + else if (name == "file_offset") + { + const auto ival = StringConvert::ToUInt64 (value.c_str (), 0, 16, &success); + if (success) + module_spec.SetObjectOffset (ival); + } + else if (name == "file_size") + { + const auto ival = StringConvert::ToUInt64 (value.c_str (), 0, 16, &success); + if (success) + module_spec.SetObjectSize (ival); + } + } + + if (log) + { + StreamString stream; + module_spec.Dump (stream); + log->Printf ("PlatformRemoteGDBServer::%s - got module info for (%s:%s) : %s", + __FUNCTION__, module_path.c_str (), arch.GetTriple ().getTriple ().c_str (), stream.GetString ().c_str ()); + } + + return true; +} + Error PlatformRemoteGDBServer::GetFileWithUUID (const FileSpec &platform_file, const UUID *uuid_ptr, @@ -346,7 +415,6 @@ { const char *url = args.GetArgumentAtIndex(0); m_gdb_client.SetConnection (new ConnectionFileDescriptor()); - // we're going to reuse the hostname when we connect to the debugserver std::string scheme; int port; @@ -380,7 +448,6 @@ error.SetErrorString ("\"platform connect\" takes a single argument: "); } } - return error; } @@ -840,4 +907,4 @@ PlatformRemoteGDBServer::CalculateTrapHandlerSymbolNames () { m_trap_handlers.push_back (ConstString ("_sigtramp")); -} +} Index: source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp =================================================================== --- source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp +++ source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp @@ -3720,5 +3720,6 @@ const auto& tripple = arch_spec.GetTriple().getTriple(); packet.PutBytesAsRawHex8(tripple.c_str(), tripple.size()); - return SendPacketAndWaitForResponse (packet.GetData(), packet.GetSize(), response, false) == PacketResult::Success; + return SendPacketAndWaitForResponse (packet.GetData(), packet.GetSize(), response, false) == PacketResult::Success && + !response.IsErrorResponse (); } Index: source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerCommon.cpp =================================================================== --- source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerCommon.cpp +++ source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerCommon.cpp @@ -19,7 +19,6 @@ // Other libraries and framework includes #include "llvm/ADT/Triple.h" #include "lldb/Core/Log.h" -#include "lldb/Core/Module.h" #include "lldb/Core/ModuleSpec.h" #include "lldb/Core/StreamGDBRemote.h" #include "lldb/Core/StreamString.h" @@ -1149,19 +1148,16 @@ if (!module_specs.FindMatchingModuleSpec(module_spec, matched_module_spec)) return SendErrorResponse (4); - const ModuleSP module(new Module(matched_module_spec)); - - const auto obj_file(module->GetObjectFile()); - const auto file_offset = obj_file->GetFileOffset(); - const auto file_size = obj_file->GetByteSize(); + const auto file_offset = matched_module_spec.GetObjectOffset(); + const auto file_size = matched_module_spec.GetObjectSize(); + const auto uuid_str = matched_module_spec.GetUUID().GetAsString(""); StreamGDBRemote response; - const auto uuid_str = module->GetUUID().GetAsString(); if (uuid_str.empty()) { std::string md5_hash; - if (!FileSystem::CalculateMD5AsString(module_path_spec, file_offset, file_size, md5_hash)) + if (!FileSystem::CalculateMD5AsString(matched_module_spec.GetFileSpec(), file_offset, file_size, md5_hash)) return SendErrorResponse (5); response.PutCString ("md5:"); response.PutCStringAsRawHex8(md5_hash.c_str()); Index: source/Target/Platform.cpp =================================================================== --- source/Target/Platform.cpp +++ source/Target/Platform.cpp @@ -10,13 +10,19 @@ #include "lldb/Target/Platform.h" // C Includes + // C++ Includes +#include +#include +#include + // Other libraries and framework includes // Project includes #include "lldb/Breakpoint/BreakpointIDList.h" #include "lldb/Core/DataBufferHeap.h" #include "lldb/Core/Error.h" #include "lldb/Core/Log.h" +#include "lldb/Core/Module.h" #include "lldb/Core/ModuleSpec.h" #include "lldb/Core/PluginManager.h" #include "lldb/Core/StructuredData.h" @@ -24,9 +30,16 @@ #include "lldb/Host/FileSystem.h" #include "lldb/Host/Host.h" #include "lldb/Host/HostInfo.h" +#include "lldb/Interpreter/OptionValueProperties.h" +#include "lldb/Interpreter/Property.h" +#include "lldb/Symbol/ObjectFile.h" #include "lldb/Target/Process.h" #include "lldb/Target/Target.h" #include "lldb/Utility/Utils.h" +#include "llvm/Support/FileSystem.h" +#include "llvm/Support/FileUtilities.h" + +#include "Utility/ModuleCache.h" using namespace lldb; using namespace lldb_private; @@ -48,6 +61,73 @@ return "host"; } +namespace { + + PropertyDefinition + g_properties[] = + { + { "use-module-cache" , OptionValue::eTypeBoolean , true, true, nullptr, nullptr, "Use module cache." }, + { "module-cache-directory", OptionValue::eTypeFileSpec, true, 0 , nullptr, nullptr, "Root directory for cached modules." }, + { nullptr , OptionValue::eTypeInvalid , false, 0, nullptr, nullptr, nullptr } + }; + + enum + { + ePropertyUseModuleCache, + ePropertyModuleCacheDirectory + }; + +} // namespace + + +ConstString +PlatformProperties::GetSettingName () +{ + static ConstString g_setting_name("platform"); + return g_setting_name; +} + +PlatformProperties::PlatformProperties () +{ + m_collection_sp.reset (new OptionValueProperties (GetSettingName ())); + m_collection_sp->Initialize (g_properties); + + auto module_cache_dir = GetModuleCacheDirectory (); + if (!module_cache_dir) + { + if (!HostInfo::GetLLDBPath (ePathTypeGlobalLLDBTempSystemDir, module_cache_dir)) + module_cache_dir = FileSpec ("/tmp/lldb", false); + module_cache_dir.AppendPathComponent ("module_cache"); + SetModuleCacheDirectory (module_cache_dir); + } +} + +bool +PlatformProperties::GetUseModuleCache () const +{ + const auto idx = ePropertyUseModuleCache; + return m_collection_sp->GetPropertyAtIndexAsBoolean ( + nullptr, idx, g_properties[idx].default_uint_value != 0); +} + +bool +PlatformProperties::SetUseModuleCache (bool use_module_cache) +{ + return m_collection_sp->SetPropertyAtIndexAsBoolean (nullptr, ePropertyUseModuleCache, use_module_cache); +} + +FileSpec +PlatformProperties::GetModuleCacheDirectory () const +{ + return m_collection_sp->GetPropertyAtIndexAsFileSpec (nullptr, ePropertyModuleCacheDirectory); +} + +bool +PlatformProperties::SetModuleCacheDirectory (const FileSpec& dir_spec) +{ + return m_collection_sp->SetPropertyAtIndexAsFileSpec (nullptr, ePropertyModuleCacheDirectory, dir_spec); +} + //------------------------------------------------------------------ /// Get the native host platform plug-in. /// @@ -97,6 +177,13 @@ } } +const PlatformPropertiesSP & +Platform::GetGlobalPlatformProperties () +{ + static const auto g_settings_sp (std::make_shared ()); + return g_settings_sp; +} + void Platform::SetHostPlatform (const lldb::PlatformSP &platform_sp) { @@ -165,20 +252,37 @@ ModuleSP *old_module_sp_ptr, bool *did_create_ptr) { - // Don't do any path remapping for the default implementation - // of the platform GetSharedModule function, just call through - // to our static ModuleList function. Platform subclasses that - // implement remote debugging, might have a developer kits - // installed that have cached versions of the files for the - // remote target, or might implement a download and cache - // locally implementation. - const bool always_create = false; + if (!IsHost () && GetGlobalPlatformProperties ()->GetUseModuleCache ()) + { + // Use caching only when talking to a remote platform. + if (GetCachedSharedModule (module_spec, module_sp)) + { + if (did_create_ptr) + *did_create_ptr = true; + + return Error (); + } + } return ModuleList::GetSharedModule (module_spec, module_sp, module_search_paths_ptr, old_module_sp_ptr, did_create_ptr, - always_create); + false); +} + +bool +Platform::GetModuleSpec (const FileSpec& module_file_spec, + const ArchSpec& arch, + ModuleSpec &module_spec) +{ + ModuleSpecList module_specs; + if (ObjectFile::GetModuleSpecifications (module_file_spec, 0, 0, module_specs) == 0) + return false; + + ModuleSpec matched_module_spec; + return module_specs.FindMatchingModuleSpec (ModuleSpec (module_file_spec, arch), + module_spec); } PlatformSP @@ -321,7 +425,8 @@ m_ssh_opts (), m_ignores_remote_hostname (false), m_trap_handlers(), - m_calculated_trap_handlers (false) + m_calculated_trap_handlers (false), + m_module_cache (llvm::make_unique ()) { Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_OBJECT)); if (log) @@ -1647,3 +1752,154 @@ return m_trap_handlers; } +bool +Platform::GetCachedSharedModule (const ModuleSpec &module_spec, + lldb::ModuleSP &module_sp) +{ + FileSpec cached_file_spec; + if (m_module_cache && GetFileFromLocalCache (module_spec, cached_file_spec)) + { + auto cached_module_spec (module_spec); + cached_module_spec.GetFileSpec () = cached_file_spec; + cached_module_spec.GetPlatformFileSpec () = module_spec.GetFileSpec (); + module_sp.reset (new Module (cached_module_spec)); + + return true; + } + return false; +} + +bool +Platform::GetFileFromLocalCache (const ModuleSpec& module_spec, + FileSpec &cached_file_spec) +{ + Log *log = GetLogIfAnyCategoriesSet (LIBLLDB_LOG_PLATFORM); + + // Get module information from a target. + ModuleSpec resolved_module_spec; + if (!GetModuleSpec (module_spec.GetFileSpec (), module_spec.GetArchitecture (), resolved_module_spec)) + return false; + + // Check local cache for a module. + auto error = m_module_cache->Get (GetModuleCacheRoot (), + GetHostname (), + resolved_module_spec.GetUUID (), + resolved_module_spec.GetFileSpec (), + cached_file_spec); + if (error.Success ()) + return true; + + if (log) + log->Printf("Platform::%s - module %s not found in local cache: %s", + __FUNCTION__, resolved_module_spec.GetUUID ().GetAsString ().c_str (), error.AsCString ()); + + // Get temporary file name for a downloaded module. + llvm::SmallString tmp_download_file_path; + const auto err_code = llvm::sys::fs::createTemporaryFile ( + "lldb", resolved_module_spec.GetUUID ().GetAsString ().c_str (), tmp_download_file_path); + if (err_code) + { + if (log) + log->Printf ("Platform::%s - failed to create unique file: %s", + __FUNCTION__, err_code.message ().c_str ()); + return false; + } + + llvm::FileRemover tmp_file_remover (tmp_download_file_path.c_str ()); + + const FileSpec tmp_download_file_spec (tmp_download_file_path.c_str (), true); + // Download a module file. + error = DownloadModuleSlice (resolved_module_spec.GetFileSpec (), + resolved_module_spec.GetObjectOffset (), + resolved_module_spec.GetObjectSize (), + tmp_download_file_spec); + if (error.Fail ()) + { + if (log) + log->Printf("Platform::%s - failed to download %s to %s: %s", + __FUNCTION__, module_spec.GetFileSpec ().GetPath ().c_str (), + tmp_download_file_path.c_str (), error.AsCString ()); + return false; + } + + // Put downloaded file into local module cache. + error = m_module_cache->Put (GetModuleCacheRoot (), + GetHostname (), + resolved_module_spec.GetUUID (), + resolved_module_spec.GetFileSpec (), + tmp_download_file_spec); + if (error.Fail ()) + { + if (log) + log->Printf("Platform::%s - failed to put module %s into cache: %s", + __FUNCTION__, resolved_module_spec.GetUUID ().GetAsString ().c_str (), + error.AsCString ()); + return false; + } + + error = m_module_cache->Get (GetModuleCacheRoot (), + GetHostname (), + resolved_module_spec.GetUUID (), + resolved_module_spec.GetFileSpec (), + cached_file_spec); + return error.Success (); +} + +Error +Platform::DownloadModuleSlice (const FileSpec& src_file_spec, + const uint64_t src_offset, + const uint64_t src_size, + const FileSpec& dst_file_spec) +{ + Error error; + + std::ofstream dst (dst_file_spec.GetPath(), std::ios::out | std::ios::binary); + if (!dst.is_open()) + { + error.SetErrorStringWithFormat ("unable to open destination file: %s", dst_file_spec.GetPath ().c_str ()); + return error; + } + + auto src_fd = OpenFile (src_file_spec, + File::eOpenOptionRead, + lldb::eFilePermissionsFileDefault, + error); + + if (error.Fail ()) + { + error.SetErrorStringWithFormat ("unable to open source file: %s", error.AsCString ()); + return error; + } + + std::vector buffer (1024); + auto offset = src_offset; + uint64_t total_bytes_read = 0; + while (total_bytes_read < src_size) + { + const auto to_read = std::min (static_cast(buffer.size ()), src_size - total_bytes_read); + const uint64_t n_read = ReadFile (src_fd, offset, &buffer[0], to_read, error); + if (error.Fail ()) + break; + if (n_read == 0) + { + error.SetErrorString ("read 0 bytes"); + break; + } + offset += n_read; + total_bytes_read += n_read; + dst.write (&buffer[0], n_read); + } + + Error close_error; + CloseFile (src_fd, close_error); // Ignoring close error. + + return error; +} + +FileSpec +Platform::GetModuleCacheRoot () +{ + auto dir_spec = GetGlobalPlatformProperties ()->GetModuleCacheDirectory (); + dir_spec.AppendPathComponent (GetName ().AsCString ()); + return dir_spec; +} Index: source/Utility/CMakeLists.txt =================================================================== --- source/Utility/CMakeLists.txt +++ source/Utility/CMakeLists.txt @@ -6,6 +6,7 @@ JSON.cpp KQueue.cpp LLDBAssert.cpp + ModuleCache.cpp PseudoTerminal.cpp Range.cpp RegisterNumber.cpp Index: source/Utility/ModuleCache.h =================================================================== --- /dev/null +++ source/Utility/ModuleCache.h @@ -0,0 +1,72 @@ +//===-- ModuleCache.h -------------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef utility_ModuleCache_h_ +#define utility_ModuleCache_h_ + +#include "lldb/lldb-types.h" +#include "lldb/lldb-forward.h" + +#include "lldb/Core/Error.h" +#include "lldb/Host/FileSpec.h" + +#include + +namespace lldb_private { + +class UUID; + +//---------------------------------------------------------------------- +/// @class ModuleCache ModuleCache.h "Utility/ModuleCache.h" +/// @brief A module cache class. +/// +/// Caches locally modules that are downloaded from remote targets. +/// Each cached module maintains 2 views: +/// - UUID view: /${CACHE_ROOT}/${PLATFORM_NAME}/.cache/${UUID}/${MODULE_FILENAME} +/// - Sysroot view: /${CACHE_ROOT}/${PLATFORM_NAME}/${HOSTNAME}/${MODULE_FULL_FILEPATH} +/// +/// UUID views stores a real module file, whereas Sysroot view holds a symbolic +/// link to UUID-view file. +/// +/// Example: +/// UUID view : /tmp/lldb/remote-linux/.cache/30C94DC6-6A1F-E951-80C3-D68D2B89E576-D5AE213C/libc.so.6 +/// Sysroot view: /tmp/lldb/remote-linux/ubuntu/lib/x86_64-linux-gnu/libc.so.6 +//---------------------------------------------------------------------- + +class ModuleCache +{ +public: + Error + Put (const FileSpec &root_dir_spec, + const char *hostname, + const UUID &uuid, + const FileSpec &platform_module_spec, + const FileSpec &tmp_file); + + Error + Get (const FileSpec &root_dir_spec, + const char *hostname, + const UUID &uuid, + const FileSpec &platform_module_spec, + FileSpec &cached_module_spec); + +private: + static FileSpec + GetModuleDirectory (const FileSpec &root_dir_spec, const UUID &uuid); + + static FileSpec + GetHostSysRootModulePath (const FileSpec &root_dir_spec, const char *hostname, const FileSpec &platform_module_spec); + + static Error + CreateHostSysRootModuleSymLink (const FileSpec &sysroot_module_path_spec, const FileSpec &module_file_path); +}; + +} // namespace lldb_private + +#endif // utility_ModuleCache_h_ Index: source/Utility/ModuleCache.cpp =================================================================== --- /dev/null +++ source/Utility/ModuleCache.cpp @@ -0,0 +1,132 @@ +//===--------------------- ModuleCache.cpp ----------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "ModuleCache.h" + +#include "lldb/Core/Module.h" +#include "lldb/Host/FileSystem.h" +#include "llvm/Support/FileSystem.h" + +#include + +#include +# +using namespace lldb; +using namespace lldb_private; + +namespace { + +const char* kModulesSubdir = ".cache"; + +FileSpec +JoinPath (const FileSpec &path1, const char* path2) +{ + FileSpec result_spec (path1); + result_spec.AppendPathComponent (path2); + return result_spec; +} + +Error +MakeDirectory (const FileSpec &dir_path) +{ + if (dir_path.Exists ()) + { + if (!dir_path.IsDirectory ()) + return Error ("Invalid existing path"); + + return Error (); + } + + return FileSystem::MakeDirectory (dir_path.GetPath ().c_str (), + eFilePermissionsDirectoryDefault); +} + +} // namespace + +Error +ModuleCache::Put (const FileSpec &root_dir_spec, + const char *hostname, + const UUID &uuid, + const FileSpec &platform_module_spec, + const FileSpec &tmp_file) +{ + const auto module_spec_dir = GetModuleDirectory (root_dir_spec, uuid); + auto error = MakeDirectory (module_spec_dir); + if (error.Fail ()) + return error; + + const auto module_file_path = JoinPath (module_spec_dir, platform_module_spec.GetFilename ().AsCString ()); + + const auto tmp_file_path = tmp_file.GetPath (); + const auto err_code = llvm::sys::fs::copy_file (tmp_file_path.c_str (), module_file_path.GetPath ().c_str ()); + if (err_code) + { + error.SetErrorStringWithFormat ("failed to copy file %s to %s: %s", + tmp_file_path.c_str (), + module_file_path.GetPath ().c_str (), + err_code.message ().c_str ()); + } + + // Create sysroot link to a module. + const auto sysroot_module_path_spec = GetHostSysRootModulePath (root_dir_spec, hostname, platform_module_spec); + return CreateHostSysRootModuleSymLink (sysroot_module_path_spec, module_file_path); +} + +Error +ModuleCache::Get (const FileSpec &root_dir_spec, + const char *hostname, + const UUID &uuid, + const FileSpec &platform_module_spec, + FileSpec &cached_module_spec) +{ + cached_module_spec.Clear (); + + const auto module_spec_dir = GetModuleDirectory (root_dir_spec, uuid); + const auto module_file_path = JoinPath (module_spec_dir, platform_module_spec.GetFilename ().AsCString ()); + + Error error; + if (!module_file_path.Exists ()) + { + error.SetErrorStringWithFormat ("module %s not found", module_file_path.GetPath ().c_str ()); + return error; + } + cached_module_spec = module_file_path; + + // We may have already cached module but downloaded from an another host - in this case let's create a symlink to it. + const auto sysroot_module_path_spec = GetHostSysRootModulePath (root_dir_spec, hostname, platform_module_spec); + if (!sysroot_module_path_spec.Exists ()) + CreateHostSysRootModuleSymLink (sysroot_module_path_spec, cached_module_spec); + + return error; +} + +FileSpec +ModuleCache::GetModuleDirectory (const FileSpec &root_dir_spec, const UUID &uuid) +{ + const auto modules_dir_spec = JoinPath (root_dir_spec, kModulesSubdir); + return JoinPath (modules_dir_spec, uuid.GetAsString ().c_str ()); +} + +FileSpec +ModuleCache::GetHostSysRootModulePath (const FileSpec &root_dir_spec, const char *hostname, const FileSpec &platform_module_spec) +{ + const auto sysroot_dir = JoinPath (root_dir_spec, hostname); + return JoinPath (sysroot_dir, platform_module_spec.GetPath ().c_str ()); +} + +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 ()); +} Index: test/python_api/hello_world/TestHelloWorld.py =================================================================== --- test/python_api/hello_world/TestHelloWorld.py +++ test/python_api/hello_world/TestHelloWorld.py @@ -46,7 +46,6 @@ self.setTearDownCleanup(dictionary=self.d) self.hello_world_attach_with_id_api() - @not_remote_testsuite_ready @python_api_test @dwarf_test @expectedFailurei386 # llvm.org/pr17384: lldb needs to be aware of linux-vdso.so to unwind stacks properly @@ -56,7 +55,7 @@ Use dwarf map (no dsym) and attach to process with id API. """ self.buildDwarf(dictionary=self.d) - self.setTearDownCleanup(dictionary=self.d) + #self.setTearDownCleanup(dictionary=self.d) self.hello_world_attach_with_id_api() @not_remote_testsuite_ready @@ -72,7 +71,6 @@ self.setTearDownCleanup(dictionary=self.d) self.hello_world_attach_with_name_api() - @not_remote_testsuite_ready @python_api_test @dwarf_test @expectedFailurei386 # llvm.org/pr17384: lldb needs to be aware of linux-vdso.so to unwind stacks properly