Add Utility/ModuleCache class and integrate it with PlatformGDBRemoteServer - in order to allow modules caching from remote targets.

http://reviews.llvm.org/D8037

llvm-svn: 231734
This commit is contained in:
Oleksiy Vyalov 2015-03-10 01:15:28 +00:00
parent 8fb05ac998
commit 63acdfdeb2
27 changed files with 762 additions and 60 deletions

View File

@ -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 @@ public:
m_uuid (),
m_object_name (),
m_object_offset (0),
m_object_size (0),
m_object_mod_time (),
m_source_mappings ()
{
@ -42,6 +44,7 @@ public:
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 @@ public:
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 @@ public:
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 @@ public:
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 @@ public:
{
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 @@ public:
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 @@ public:
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 @@ public:
{
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 @@ protected:
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;
};

View File

@ -115,7 +115,8 @@ class HostInfoBase
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);

View File

@ -13,6 +13,7 @@
// C Includes
// C++ Includes
#include <map>
#include <memory>
#include <string>
#include <vector>
@ -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<PlatformProperties> PlatformPropertiesSP;
//----------------------------------------------------------------------
/// @class Platform Platform.h "lldb/Target/Platform.h"
/// @brief A plug-in interface definition class for debug platform that
@ -49,13 +74,15 @@ namespace lldb_private {
public PluginInterface
{
public:
static void
Initialize ();
static void
Terminate ();
static const PlatformPropertiesSP &
GetGlobalPlatformProperties ();
//------------------------------------------------------------------
/// Get the native host platform plug-in.
///
@ -350,6 +377,11 @@ namespace lldb_private {
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 @@ namespace lldb_private {
std::string m_local_cache_directory;
std::vector<ConstString> m_trap_handlers;
bool m_calculated_trap_handlers;
const std::unique_ptr<ModuleCache> m_module_cache;
//------------------------------------------------------------------
/// Ask the Platform subclass to fill in the list of trap handler names
@ -1090,6 +1123,22 @@ namespace lldb_private {
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);
};

View File

@ -860,14 +860,15 @@ namespace lldb {
//----------------------------------------------------------------------
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;
//----------------------------------------------------------------------

View File

@ -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 = "<group>"; };
254FBBA41A91670E00BD6378 /* SBAttachInfo.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SBAttachInfo.cpp; path = source/API/SBAttachInfo.cpp; sourceTree = "<group>"; };
254FBBA61A91672800BD6378 /* SBAttachInfo.i */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c.preprocessed; path = SBAttachInfo.i; sourceTree = "<group>"; };
257E47151AA56C2000A62F81 /* ModuleCache.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ModuleCache.cpp; path = source/Utility/ModuleCache.cpp; sourceTree = "<group>"; };
257E47161AA56C2000A62F81 /* ModuleCache.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ModuleCache.h; path = source/Utility/ModuleCache.h; sourceTree = "<group>"; };
260157C41885F4FF00F875CF /* libpanel.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libpanel.dylib; path = /usr/lib/libpanel.dylib; sourceTree = "<absolute>"; };
260223E7115F06D500A601A2 /* SBCommunication.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SBCommunication.h; path = include/lldb/API/SBCommunication.h; sourceTree = "<group>"; };
260223E8115F06E500A601A2 /* SBCommunication.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SBCommunication.cpp; path = source/API/SBCommunication.cpp; sourceTree = "<group>"; };
@ -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 */,

View File

@ -697,6 +697,10 @@ Debugger::Debugger(lldb::LogOutputCallback log_callback, void *baton) :
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"),

View File

@ -234,7 +234,10 @@ UUID::SetFromCString (const char *cstr, uint32_t num_uuid_bytes)
// 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;

View File

@ -68,7 +68,8 @@ namespace
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 @@ HostInfoBase::GetLLDBPath(lldb::PathType type, FileSpec &file_spec)
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 @@ HostInfoBase::ComputeSupportExeDirectory(FileSpec &file_spec)
}
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 @@ HostInfoBase::ComputeTempFileDirectory(FileSpec &file_spec)
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;
}

View File

@ -851,6 +851,7 @@ DynamicLoaderMacOSXDYLD::AddModulesUsingImageInfos (DYLDImageInfo::collection &i
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)
{

View File

@ -595,7 +595,8 @@ ObjectContainerBSDArchive::GetModuleSpecifications (const lldb_private::FileSpec
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;
}
}

View File

@ -604,8 +604,7 @@ ObjectFileELF::GetModuleSpecifications (const lldb_private::FileSpec& file,
{
if (data_sp)
{
ModuleSpec spec;
spec.GetFileSpec() = file;
ModuleSpec spec (file);
const uint32_t sub_type = subTypeFromElfHeader(header);
spec.GetArchitecture().SetArchitecture(eArchTypeELF,

View File

@ -995,7 +995,8 @@ ObjectFileMachO::GetModuleSpecifications (const lldb_private::FileSpec& file,
ModuleSpec spec;
spec.GetFileSpec() = file;
spec.SetObjectOffset(file_offset);
spec.SetObjectSize(length);
if (GetArchitecture (header, data, data_offset, spec.GetArchitecture()))
{
if (spec.GetArchitecture().IsValid())

View File

@ -165,6 +165,18 @@ PlatformFreeBSD::~PlatformFreeBSD()
}
//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,

View File

@ -71,6 +71,11 @@ public:
//------------------------------------------------------------
// 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,

View File

@ -50,6 +50,17 @@ PlatformPOSIX::~PlatformPOSIX()
{
}
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)
{

View File

@ -31,6 +31,12 @@ public:
//------------------------------------------------------------
// 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 @@ public:
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;

View File

@ -201,6 +201,17 @@ PlatformWindows::~PlatformWindows()
{
}
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,

View File

@ -59,6 +59,11 @@ public:
//------------------------------------------------------------
// 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,

View File

@ -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 @@ PlatformRemoteGDBServer::ResolveExecutable (const ModuleSpec &module_spec,
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 @@ PlatformRemoteGDBServer::ConnectRemote (Args& args)
{
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 @@ PlatformRemoteGDBServer::ConnectRemote (Args& args)
error.SetErrorString ("\"platform connect\" takes a single argument: <connect-url>");
}
}
return error;
}
@ -840,4 +907,4 @@ void
PlatformRemoteGDBServer::CalculateTrapHandlerSymbolNames ()
{
m_trap_handlers.push_back (ConstString ("_sigtramp"));
}
}

View File

@ -68,6 +68,11 @@ public:
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 @@ public:
virtual bool
SetRemoteWorkingDirectory(const lldb_private::ConstString &path);
// Remote subclasses should override this and return a valid instance
// name if connected.

View File

@ -3720,5 +3720,6 @@ GDBRemoteCommunicationClient::GetModuleInfo (const char* module_path,
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 ();
}

View File

@ -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 @@ GDBRemoteCommunicationServerCommon::Handle_qModuleInfo (StringExtractorGDBRemote
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());

View File

@ -10,13 +10,19 @@
#include "lldb/Target/Platform.h"
// C Includes
// C++ Includes
#include <algorithm>
#include <fstream>
#include <vector>
// 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 @@ Platform::GetHostPlatformName ()
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 @@ Platform::Terminate ()
}
}
const PlatformPropertiesSP &
Platform::GetGlobalPlatformProperties ()
{
static const auto g_settings_sp (std::make_shared<PlatformProperties> ());
return g_settings_sp;
}
void
Platform::SetHostPlatform (const lldb::PlatformSP &platform_sp)
{
@ -165,20 +252,37 @@ Platform::GetSharedModule (const ModuleSpec &module_spec,
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 @@ Platform::Platform (bool is_host) :
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<ModuleCache> ())
{
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_OBJECT));
if (log)
@ -1647,3 +1752,154 @@ Platform::GetTrapHandlerSymbolNames ()
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<PATH_MAX> 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<char> 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<uint64_t>(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;
}

View File

@ -6,6 +6,7 @@ add_lldb_library(lldbUtility
JSON.cpp
KQueue.cpp
LLDBAssert.cpp
ModuleCache.cpp
PseudoTerminal.cpp
Range.cpp
RegisterNumber.cpp

View File

@ -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 <assert.h>
#include <cstdio>
#
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 ());
}

View File

@ -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 <string>
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_

View File

@ -46,7 +46,6 @@ class HelloWorldTestCase(TestBase):
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 @@ class HelloWorldTestCase(TestBase):
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 @@ class HelloWorldTestCase(TestBase):
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