summaryrefslogtreecommitdiffstats
path: root/source/Target/Platform.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'source/Target/Platform.cpp')
-rw-r--r--source/Target/Platform.cpp498
1 files changed, 420 insertions, 78 deletions
diff --git a/source/Target/Platform.cpp b/source/Target/Platform.cpp
index 09c9efc..6758ecf 100644
--- a/source/Target/Platform.cpp
+++ b/source/Target/Platform.cpp
@@ -10,25 +10,47 @@
#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/Debugger.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"
#include "lldb/Host/FileSpec.h"
#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 "Utility/ModuleCache.h"
+
+// Define these constants from POSIX mman.h rather than include the file
+// so that they will be correct even when compiled on Linux.
+#define MAP_PRIVATE 2
+#define MAP_ANON 0x1000
using namespace lldb;
using namespace lldb_private;
-
+
+static uint32_t g_initialize_count = 0;
+
// Use a singleton function for g_local_platform_sp to avoid init
// constructors since LLDB is often part of a shared library
static PlatformSP&
@@ -44,6 +66,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.
///
@@ -75,6 +164,32 @@ GetPlatformListMutex ()
}
void
+Platform::Initialize ()
+{
+ g_initialize_count++;
+}
+
+void
+Platform::Terminate ()
+{
+ if (g_initialize_count > 0)
+ {
+ if (--g_initialize_count == 0)
+ {
+ Mutex::Locker locker(GetPlatformListMutex ());
+ GetPlatformList().clear();
+ }
+ }
+}
+
+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)
{
// The native platform should use its static void Platform::Initialize()
@@ -137,25 +252,43 @@ Platform::LocateExecutableScriptingResources (Target *target, Module &module, St
Error
Platform::GetSharedModule (const ModuleSpec &module_spec,
+ Process* process,
ModuleSP &module_sp,
const FileSpecList *module_search_paths_ptr,
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;
- return ModuleList::GetSharedModule (module_spec,
- module_sp,
- module_search_paths_ptr,
- old_module_sp_ptr,
- did_create_ptr,
- always_create);
+ if (IsHost ())
+ return ModuleList::GetSharedModule (module_spec,
+ module_sp,
+ module_search_paths_ptr,
+ old_module_sp_ptr,
+ did_create_ptr,
+ false);
+
+ return GetRemoteSharedModule (module_spec,
+ process,
+ module_sp,
+ [&](const ModuleSpec &spec)
+ {
+ return ModuleList::GetSharedModule (
+ spec, module_sp, module_search_paths_ptr, old_module_sp_ptr, did_create_ptr, false);
+ },
+ did_create_ptr);
+}
+
+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
@@ -298,7 +431,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)
@@ -476,16 +610,16 @@ Platform::AddClangModuleCompilationOptions (Target *target, std::vector<std::str
}
-ConstString
+FileSpec
Platform::GetWorkingDirectory ()
{
if (IsHost())
{
char cwd[PATH_MAX];
if (getcwd(cwd, sizeof(cwd)))
- return ConstString(cwd);
+ return FileSpec{cwd, true};
else
- return ConstString();
+ return FileSpec{};
}
else
{
@@ -524,11 +658,11 @@ RecurseCopy_Callback (void *baton,
FileSpec dst_dir = rc_baton->dst;
if (!dst_dir.GetFilename())
dst_dir.GetFilename() = src.GetLastPathComponent();
- std::string dst_dir_path (dst_dir.GetPath());
- Error error = rc_baton->platform_ptr->MakeDirectory(dst_dir_path.c_str(), lldb::eFilePermissionsDirectoryDefault);
+ Error error = rc_baton->platform_ptr->MakeDirectory(dst_dir, lldb::eFilePermissionsDirectoryDefault);
if (error.Fail())
{
- rc_baton->error.SetErrorStringWithFormat("unable to setup directory %s on remote end", dst_dir_path.c_str());
+ rc_baton->error.SetErrorStringWithFormat("unable to setup directory %s on remote end",
+ dst_dir.GetCString());
return FileSpec::eEnumerateDirectoryResultQuit; // got an error, bail out
}
@@ -556,15 +690,15 @@ RecurseCopy_Callback (void *baton,
FileSpec dst_file = rc_baton->dst;
if (!dst_file.GetFilename())
dst_file.GetFilename() = src.GetFilename();
-
- char buf[PATH_MAX];
- rc_baton->error = FileSystem::Readlink(src.GetPath().c_str(), buf, sizeof(buf));
+ FileSpec src_resolved;
+
+ rc_baton->error = FileSystem::Readlink(src, src_resolved);
if (rc_baton->error.Fail())
return FileSpec::eEnumerateDirectoryResultQuit; // got an error, bail out
-
- rc_baton->error = rc_baton->platform_ptr->CreateSymlink(dst_file.GetPath().c_str(), buf);
+
+ rc_baton->error = rc_baton->platform_ptr->CreateSymlink(dst_file, src_resolved);
if (rc_baton->error.Fail())
return FileSpec::eEnumerateDirectoryResultQuit; // got an error, bail out
@@ -611,7 +745,7 @@ Platform::Install (const FileSpec& src, const FileSpec& dst)
if (!fixed_dst.GetFilename())
fixed_dst.GetFilename() = src.GetFilename();
- ConstString working_dir = GetWorkingDirectory();
+ FileSpec working_dir = GetWorkingDirectory();
if (dst)
{
@@ -631,8 +765,8 @@ Platform::Install (const FileSpec& src, const FileSpec& dst)
std::string path;
if (working_dir)
{
- relative_spec.SetFile(working_dir.GetCString(), false);
- relative_spec.AppendPathComponent(dst.GetPath().c_str());
+ relative_spec = working_dir;
+ relative_spec.AppendPathComponent(dst.GetPath());
fixed_dst.GetDirectory() = relative_spec.GetDirectory();
}
else
@@ -646,7 +780,7 @@ Platform::Install (const FileSpec& src, const FileSpec& dst)
{
if (working_dir)
{
- fixed_dst.GetDirectory() = working_dir;
+ fixed_dst.GetDirectory().SetCString(working_dir.GetCString());
}
else
{
@@ -659,7 +793,7 @@ Platform::Install (const FileSpec& src, const FileSpec& dst)
{
if (working_dir)
{
- fixed_dst.GetDirectory() = working_dir;
+ fixed_dst.GetDirectory().SetCString(working_dir.GetCString());
}
else
{
@@ -682,18 +816,17 @@ Platform::Install (const FileSpec& src, const FileSpec& dst)
case FileSpec::eFileTypeDirectory:
{
if (GetFileExists (fixed_dst))
- Unlink (fixed_dst.GetPath().c_str());
+ Unlink(fixed_dst);
uint32_t permissions = src.GetPermissions();
if (permissions == 0)
permissions = eFilePermissionsDirectoryDefault;
- std::string dst_dir_path(fixed_dst.GetPath());
- error = MakeDirectory(dst_dir_path.c_str(), permissions);
+ error = MakeDirectory(fixed_dst, permissions);
if (error.Success())
{
// Make a filespec that only fills in the directory of a FileSpec so
// when we enumerate we can quickly fill in the filename for dst copies
FileSpec recurse_dst;
- recurse_dst.GetDirectory().SetCString(dst_dir_path.c_str());
+ recurse_dst.GetDirectory().SetCString(fixed_dst.GetCString());
std::string src_dir_path (src.GetPath());
RecurseCopyBaton baton = { recurse_dst, this, Error() };
FileSpec::EnumerateDirectory(src_dir_path.c_str(), true, true, true, RecurseCopy_Callback, &baton);
@@ -704,18 +837,18 @@ Platform::Install (const FileSpec& src, const FileSpec& dst)
case FileSpec::eFileTypeRegular:
if (GetFileExists (fixed_dst))
- Unlink (fixed_dst.GetPath().c_str());
+ Unlink(fixed_dst);
error = PutFile(src, fixed_dst);
break;
case FileSpec::eFileTypeSymbolicLink:
{
if (GetFileExists (fixed_dst))
- Unlink (fixed_dst.GetPath().c_str());
- char buf[PATH_MAX];
- error = FileSystem::Readlink(src.GetPath().c_str(), buf, sizeof(buf));
+ Unlink(fixed_dst);
+ FileSpec src_resolved;
+ error = FileSystem::Readlink(src, src_resolved);
if (error.Success())
- error = CreateSymlink(dst.GetPath().c_str(), buf);
+ error = CreateSymlink(dst, src_resolved);
}
break;
case FileSpec::eFileTypePipe:
@@ -735,37 +868,33 @@ Platform::Install (const FileSpec& src, const FileSpec& dst)
}
bool
-Platform::SetWorkingDirectory (const ConstString &path)
+Platform::SetWorkingDirectory(const FileSpec &file_spec)
{
if (IsHost())
{
Log *log = GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PLATFORM);
if (log)
- log->Printf("Platform::SetWorkingDirectory('%s')", path.GetCString());
-#ifdef _WIN32
- // Not implemented on Windows
- return false;
-#else
- if (path)
+ log->Printf("Platform::SetWorkingDirectory('%s')",
+ file_spec.GetCString());
+ if (file_spec)
{
- if (chdir(path.GetCString()) == 0)
+ if (::chdir(file_spec.GetCString()) == 0)
return true;
}
return false;
-#endif
}
else
{
m_working_dir.Clear();
- return SetRemoteWorkingDirectory(path);
+ return SetRemoteWorkingDirectory(file_spec);
}
}
Error
-Platform::MakeDirectory (const char *path, uint32_t permissions)
+Platform::MakeDirectory(const FileSpec &file_spec, uint32_t permissions)
{
if (IsHost())
- return FileSystem::MakeDirectory(path, permissions);
+ return FileSystem::MakeDirectory(file_spec, permissions);
else
{
Error error;
@@ -775,10 +904,10 @@ Platform::MakeDirectory (const char *path, uint32_t permissions)
}
Error
-Platform::GetFilePermissions (const char *path, uint32_t &file_permissions)
+Platform::GetFilePermissions(const FileSpec &file_spec, uint32_t &file_permissions)
{
if (IsHost())
- return FileSystem::GetFilePermissions(path, file_permissions);
+ return FileSystem::GetFilePermissions(file_spec, file_permissions);
else
{
Error error;
@@ -788,10 +917,10 @@ Platform::GetFilePermissions (const char *path, uint32_t &file_permissions)
}
Error
-Platform::SetFilePermissions (const char *path, uint32_t file_permissions)
+Platform::SetFilePermissions(const FileSpec &file_spec, uint32_t file_permissions)
{
if (IsHost())
- return FileSystem::SetFilePermissions(path, file_permissions);
+ return FileSystem::SetFilePermissions(file_spec, file_permissions);
else
{
Error error;
@@ -818,12 +947,13 @@ Platform::GetHostname ()
}
bool
-Platform::SetRemoteWorkingDirectory(const ConstString &path)
+Platform::SetRemoteWorkingDirectory(const FileSpec &working_dir)
{
Log *log = GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PLATFORM);
if (log)
- log->Printf("Platform::SetRemoteWorkingDirectory('%s')", path.GetCString());
- m_working_dir = path;
+ log->Printf("Platform::SetRemoteWorkingDirectory('%s')",
+ working_dir.GetCString());
+ m_working_dir = working_dir;
return true;
}
@@ -1092,6 +1222,12 @@ Platform::LaunchProcess (ProcessLaunchInfo &launch_info)
num_resumes))
return error;
}
+ else if (launch_info.GetFlags().Test(eLaunchFlagShellExpandArguments))
+ {
+ error = ShellExpandArguments(launch_info);
+ if (error.Fail())
+ return error;
+ }
if (log)
log->Printf ("Platform::%s final launch_info resume count: %" PRIu32, __FUNCTION__, launch_info.GetResumeCount ());
@@ -1104,16 +1240,41 @@ Platform::LaunchProcess (ProcessLaunchInfo &launch_info)
}
Error
+Platform::ShellExpandArguments (ProcessLaunchInfo &launch_info)
+{
+ if (IsHost())
+ return Host::ShellExpandArguments(launch_info);
+ return Error("base lldb_private::Platform class can't expand arguments");
+}
+
+Error
Platform::KillProcess (const lldb::pid_t pid)
{
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_PLATFORM));
if (log)
log->Printf ("Platform::%s, pid %" PRIu64, __FUNCTION__, pid);
- if (!IsHost ())
- return Error ("base lldb_private::Platform class can't launch remote processes");
+ // Try to find a process plugin to handle this Kill request. If we can't, fall back to
+ // the default OS implementation.
+ size_t num_debuggers = Debugger::GetNumDebuggers();
+ for (size_t didx = 0; didx < num_debuggers; ++didx)
+ {
+ DebuggerSP debugger = Debugger::GetDebuggerAtIndex(didx);
+ lldb_private::TargetList &targets = debugger->GetTargetList();
+ for (int tidx = 0; tidx < targets.GetNumTargets(); ++tidx)
+ {
+ ProcessSP process = targets.GetTargetAtIndex(tidx)->GetProcessSP();
+ if (process->GetID() == pid)
+ return process->Destroy(true);
+ }
+ }
- Host::Kill (pid, SIGTERM);
+ if (!IsHost())
+ {
+ return Error("base lldb_private::Platform class can't kill remote processes unless "
+ "they are controlled by a process plugin");
+ }
+ Host::Kill(pid, SIGTERM);
return Error();
}
@@ -1251,7 +1412,7 @@ Platform::PutFile (const FileSpec& source,
if (log)
log->Printf("[PutFile] Using block by block transfer....\n");
- uint32_t source_open_options = File::eOpenOptionRead;
+ uint32_t source_open_options = File::eOpenOptionRead | File::eOpenOptionCloseOnExec;
if (source.GetFileType() == FileSpec::eFileTypeSymbolicLink)
source_open_options |= File::eOpenoptionDontFollowSymlinks;
@@ -1266,7 +1427,8 @@ Platform::PutFile (const FileSpec& source,
lldb::user_id_t dest_file = OpenFile (destination,
File::eOpenOptionCanCreate |
File::eOpenOptionWrite |
- File::eOpenOptionTruncate,
+ File::eOpenOptionTruncate |
+ File::eOpenOptionCloseOnExec,
permissions,
error);
if (log)
@@ -1309,43 +1471,52 @@ Platform::PutFile (const FileSpec& source,
}
Error
-Platform::GetFile (const FileSpec& source,
- const FileSpec& destination)
+Platform::GetFile(const FileSpec &source,
+ const FileSpec &destination)
{
Error error("unimplemented");
return error;
}
Error
-Platform::CreateSymlink (const char *src, // The name of the link is in src
- const char *dst)// The symlink points to dst
+Platform::CreateSymlink(const FileSpec &src, // The name of the link is in src
+ const FileSpec &dst) // The symlink points to dst
{
Error error("unimplemented");
return error;
}
bool
-Platform::GetFileExists (const lldb_private::FileSpec& file_spec)
+Platform::GetFileExists(const lldb_private::FileSpec &file_spec)
{
return false;
}
Error
-Platform::Unlink (const char *path)
+Platform::Unlink(const FileSpec &path)
{
Error error("unimplemented");
return error;
}
-
+uint64_t
+Platform::ConvertMmapFlagsToPlatform(const ArchSpec &arch, unsigned flags)
+{
+ uint64_t flags_platform = 0;
+ if (flags & eMmapFlagsPrivate)
+ flags_platform |= MAP_PRIVATE;
+ if (flags & eMmapFlagsAnon)
+ flags_platform |= MAP_ANON;
+ return flags_platform;
+}
lldb_private::Error
-Platform::RunShellCommand (const char *command, // Shouldn't be NULL
- const char *working_dir, // Pass NULL to use the current working directory
- int *status_ptr, // Pass NULL if you don't want the process exit status
- 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) // Timeout in seconds to wait for shell program to finish
+Platform::RunShellCommand(const char *command, // Shouldn't be NULL
+ const FileSpec &working_dir, // Pass empty FileSpec to use the current working directory
+ int *status_ptr, // Pass NULL if you don't want the process exit status
+ 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) // Timeout in seconds to wait for shell program to finish
{
if (IsHost())
return Host::RunShellCommand (command, working_dir, status_ptr, signo_ptr, command_output, timeout_sec);
@@ -1609,3 +1780,174 @@ Platform::GetTrapHandlerSymbolNames ()
return m_trap_handlers;
}
+Error
+Platform::GetCachedExecutable (ModuleSpec &module_spec,
+ lldb::ModuleSP &module_sp,
+ const FileSpecList *module_search_paths_ptr,
+ Platform &remote_platform)
+{
+ const auto platform_spec = module_spec.GetFileSpec ();
+ const auto error = LoadCachedExecutable (module_spec,
+ module_sp,
+ module_search_paths_ptr,
+ remote_platform);
+ if (error.Success ())
+ {
+ module_spec.GetFileSpec () = module_sp->GetFileSpec ();
+ module_spec.GetPlatformFileSpec () = platform_spec;
+ }
+
+ return error;
+}
+
+Error
+Platform::LoadCachedExecutable (const ModuleSpec &module_spec,
+ lldb::ModuleSP &module_sp,
+ const FileSpecList *module_search_paths_ptr,
+ Platform &remote_platform)
+{
+ return GetRemoteSharedModule (module_spec,
+ nullptr,
+ module_sp,
+ [&](const ModuleSpec &spec)
+ {
+ return remote_platform.ResolveExecutable (
+ spec, module_sp, module_search_paths_ptr);
+ },
+ nullptr);
+}
+
+Error
+Platform::GetRemoteSharedModule (const ModuleSpec &module_spec,
+ Process* process,
+ lldb::ModuleSP &module_sp,
+ const ModuleResolver &module_resolver,
+ bool *did_create_ptr)
+{
+ // Get module information from a target.
+ ModuleSpec resolved_module_spec;
+ bool got_module_spec = false;
+ if (process)
+ {
+ // Try to get module information from the process
+ if (process->GetModuleSpec (module_spec.GetFileSpec (), module_spec.GetArchitecture (), resolved_module_spec))
+ got_module_spec = true;
+ }
+
+ if (!got_module_spec)
+ {
+ // Get module information from a target.
+ if (!GetModuleSpec (module_spec.GetFileSpec (), module_spec.GetArchitecture (), resolved_module_spec))
+ return module_resolver (module_spec);
+ }
+
+ // Trying to find a module by UUID on local file system.
+ const auto error = module_resolver (resolved_module_spec);
+ if (error.Fail ())
+ {
+ if (GetCachedSharedModule (resolved_module_spec, module_sp, did_create_ptr))
+ return Error ();
+ }
+
+ return error;
+}
+
+bool
+Platform::GetCachedSharedModule (const ModuleSpec &module_spec,
+ lldb::ModuleSP &module_sp,
+ bool *did_create_ptr)
+{
+ if (IsHost() ||
+ !GetGlobalPlatformProperties ()->GetUseModuleCache ())
+ return false;
+
+ Log *log = GetLogIfAnyCategoriesSet (LIBLLDB_LOG_PLATFORM);
+
+ // Check local cache for a module.
+ auto error = m_module_cache->GetAndPut (
+ GetModuleCacheRoot (),
+ GetCacheHostname (),
+ module_spec,
+ [=](const ModuleSpec &module_spec, const FileSpec &tmp_download_file_spec)
+ {
+ return DownloadModuleSlice (module_spec.GetFileSpec (),
+ module_spec.GetObjectOffset (),
+ module_spec.GetObjectSize (),
+ tmp_download_file_spec);
+
+ },
+ module_sp,
+ did_create_ptr);
+ if (error.Success ())
+ return true;
+
+ if (log)
+ log->Printf("Platform::%s - module %s not found in local cache: %s",
+ __FUNCTION__, module_spec.GetUUID ().GetAsString ().c_str (), error.AsCString ());
+ return false;
+}
+
+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;
+}
+
+const char *
+Platform::GetCacheHostname ()
+{
+ return GetHostname ();
+}
OpenPOWER on IntegriCloud