aboutsummaryrefslogtreecommitdiff
path: root/lldb/source/Target/Platform.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lldb/source/Target/Platform.cpp')
-rw-r--r--lldb/source/Target/Platform.cpp399
1 files changed, 233 insertions, 166 deletions
diff --git a/lldb/source/Target/Platform.cpp b/lldb/source/Target/Platform.cpp
index 3c331c8760df..559f7664c72e 100644
--- a/lldb/source/Target/Platform.cpp
+++ b/lldb/source/Target/Platform.cpp
@@ -19,6 +19,7 @@
#include "lldb/Core/ModuleSpec.h"
#include "lldb/Core/PluginManager.h"
#include "lldb/Core/StreamFile.h"
+#include "lldb/Host/FileCache.h"
#include "lldb/Host/FileSystem.h"
#include "lldb/Host/Host.h"
#include "lldb/Host/HostInfo.h"
@@ -34,9 +35,11 @@
#include "lldb/Target/UnixSignals.h"
#include "lldb/Utility/DataBufferHeap.h"
#include "lldb/Utility/FileSpec.h"
+#include "lldb/Utility/LLDBLog.h"
#include "lldb/Utility/Log.h"
#include "lldb/Utility/Status.h"
#include "lldb/Utility/StructuredData.h"
+#include "llvm/ADT/STLExtras.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/Path.h"
@@ -48,8 +51,6 @@
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 &GetHostPlatformSP() {
@@ -134,26 +135,9 @@ void PlatformProperties::SetDefaultModuleCacheDirectory(
/// or attaching to processes unless another platform is specified.
PlatformSP Platform::GetHostPlatform() { return GetHostPlatformSP(); }
-static std::vector<PlatformSP> &GetPlatformList() {
- static std::vector<PlatformSP> g_platform_list;
- return g_platform_list;
-}
-
-static std::recursive_mutex &GetPlatformListMutex() {
- static std::recursive_mutex g_mutex;
- return g_mutex;
-}
-
-void Platform::Initialize() { g_initialize_count++; }
+void Platform::Initialize() {}
-void Platform::Terminate() {
- if (g_initialize_count > 0) {
- if (--g_initialize_count == 0) {
- std::lock_guard<std::recursive_mutex> guard(GetPlatformListMutex());
- GetPlatformList().clear();
- }
- }
-}
+void Platform::Terminate() {}
PlatformProperties &Platform::GetGlobalPlatformProperties() {
static PlatformProperties g_settings;
@@ -164,11 +148,6 @@ void Platform::SetHostPlatform(const lldb::PlatformSP &platform_sp) {
// The native platform should use its static void Platform::Initialize()
// function to register itself as the native platform.
GetHostPlatformSP() = platform_sp;
-
- if (platform_sp) {
- std::lock_guard<std::recursive_mutex> guard(GetPlatformListMutex());
- GetPlatformList().push_back(platform_sp);
- }
}
Status Platform::GetFileWithUUID(const FileSpec &platform_file,
@@ -271,108 +250,15 @@ bool Platform::GetModuleSpec(const FileSpec &module_file_spec,
module_spec);
}
-PlatformSP Platform::Find(ConstString name) {
- if (name) {
- static ConstString g_host_platform_name("host");
- if (name == g_host_platform_name)
- return GetHostPlatform();
-
- std::lock_guard<std::recursive_mutex> guard(GetPlatformListMutex());
- for (const auto &platform_sp : GetPlatformList()) {
- if (platform_sp->GetName() == name)
- return platform_sp;
- }
- }
- return PlatformSP();
-}
-
-PlatformSP Platform::Create(ConstString name, Status &error) {
- PlatformCreateInstance create_callback = nullptr;
+PlatformSP Platform::Create(llvm::StringRef name) {
lldb::PlatformSP platform_sp;
- if (name) {
- static ConstString g_host_platform_name("host");
- if (name == g_host_platform_name)
- return GetHostPlatform();
-
- create_callback = PluginManager::GetPlatformCreateCallbackForPluginName(
- name.GetStringRef());
- if (create_callback)
- platform_sp = create_callback(true, nullptr);
- else
- error.SetErrorStringWithFormat(
- "unable to find a plug-in for the platform named \"%s\"",
- name.GetCString());
- } else
- error.SetErrorString("invalid platform name");
-
- if (platform_sp) {
- std::lock_guard<std::recursive_mutex> guard(GetPlatformListMutex());
- GetPlatformList().push_back(platform_sp);
- }
-
- return platform_sp;
-}
-
-PlatformSP Platform::Create(const ArchSpec &arch, ArchSpec *platform_arch_ptr,
- Status &error) {
- lldb::PlatformSP platform_sp;
- if (arch.IsValid()) {
- // Scope for locker
- {
- // First try exact arch matches across all platforms already created
- std::lock_guard<std::recursive_mutex> guard(GetPlatformListMutex());
- for (const auto &platform_sp : GetPlatformList()) {
- if (platform_sp->IsCompatibleArchitecture(arch, true,
- platform_arch_ptr))
- return platform_sp;
- }
-
- // Next try compatible arch matches across all platforms already created
- for (const auto &platform_sp : GetPlatformList()) {
- if (platform_sp->IsCompatibleArchitecture(arch, false,
- platform_arch_ptr))
- return platform_sp;
- }
- }
+ if (name == GetHostPlatformName())
+ return GetHostPlatform();
- PlatformCreateInstance create_callback;
- // First try exact arch matches across all platform plug-ins
- uint32_t idx;
- for (idx = 0; (create_callback =
- PluginManager::GetPlatformCreateCallbackAtIndex(idx));
- ++idx) {
- if (create_callback) {
- platform_sp = create_callback(false, &arch);
- if (platform_sp &&
- platform_sp->IsCompatibleArchitecture(arch, true,
- platform_arch_ptr)) {
- std::lock_guard<std::recursive_mutex> guard(GetPlatformListMutex());
- GetPlatformList().push_back(platform_sp);
- return platform_sp;
- }
- }
- }
- // Next try compatible arch matches across all platform plug-ins
- for (idx = 0; (create_callback =
- PluginManager::GetPlatformCreateCallbackAtIndex(idx));
- ++idx) {
- if (create_callback) {
- platform_sp = create_callback(false, &arch);
- if (platform_sp &&
- platform_sp->IsCompatibleArchitecture(arch, false,
- platform_arch_ptr)) {
- std::lock_guard<std::recursive_mutex> guard(GetPlatformListMutex());
- GetPlatformList().push_back(platform_sp);
- return platform_sp;
- }
- }
- }
- } else
- error.SetErrorString("invalid platform name");
- if (platform_arch_ptr)
- platform_arch_ptr->Clear();
- platform_sp.reset();
- return platform_sp;
+ if (PlatformCreateInstance create_callback =
+ PluginManager::GetPlatformCreateCallbackForPluginName(name))
+ return create_callback(true, nullptr);
+ return nullptr;
}
ArchSpec Platform::GetAugmentedArchSpec(Platform *platform, llvm::StringRef triple) {
@@ -384,14 +270,13 @@ ArchSpec Platform::GetAugmentedArchSpec(Platform *platform, llvm::StringRef trip
/// Default Constructor
Platform::Platform(bool is_host)
: m_is_host(is_host), m_os_version_set_while_connected(false),
- m_system_arch_set_while_connected(false), m_sdk_sysroot(), m_sdk_build(),
- m_working_dir(), m_remote_url(), m_name(), m_system_arch(), m_mutex(),
- m_max_uid_name_len(0), m_max_gid_name_len(0), m_supports_rsync(false),
- m_rsync_opts(), m_rsync_prefix(), m_supports_ssh(false), m_ssh_opts(),
+ m_system_arch_set_while_connected(false), m_max_uid_name_len(0),
+ m_max_gid_name_len(0), m_supports_rsync(false), m_rsync_opts(),
+ m_rsync_prefix(), m_supports_ssh(false), m_ssh_opts(),
m_ignores_remote_hostname(false), m_trap_handlers(),
m_calculated_trap_handlers(false),
m_module_cache(std::make_unique<ModuleCache>()) {
- Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_OBJECT));
+ Log *log = GetLog(LLDBLog::Object);
LLDB_LOGF(log, "%p Platform::Platform()", static_cast<void *>(this));
}
@@ -623,7 +508,7 @@ RecurseCopy_Callback(void *baton, llvm::sys::fs::file_type ft,
Status Platform::Install(const FileSpec &src, const FileSpec &dst) {
Status error;
- Log *log = GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PLATFORM);
+ Log *log = GetLog(LLDBLog::Platform);
LLDB_LOGF(log, "Platform::Install (src='%s', dst='%s')",
src.GetPath().c_str(), dst.GetPath().c_str());
FileSpec fixed_dst(dst);
@@ -733,7 +618,7 @@ Status Platform::Install(const FileSpec &src, const FileSpec &dst) {
bool Platform::SetWorkingDirectory(const FileSpec &file_spec) {
if (IsHost()) {
- Log *log = GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PLATFORM);
+ Log *log = GetLog(LLDBLog::Platform);
LLDB_LOG(log, "{0}", file_spec);
if (std::error_code ec = llvm::sys::fs::set_current_path(file_spec.GetPath())) {
LLDB_LOG(log, "error: {0}", ec.message());
@@ -786,15 +671,63 @@ Status Platform::SetFilePermissions(const FileSpec &file_spec,
}
}
-ConstString Platform::GetName() { return ConstString(GetPluginName()); }
+user_id_t Platform::OpenFile(const FileSpec &file_spec,
+ File::OpenOptions flags, uint32_t mode,
+ Status &error) {
+ if (IsHost())
+ return FileCache::GetInstance().OpenFile(file_spec, flags, mode, error);
+ return UINT64_MAX;
+}
+
+bool Platform::CloseFile(user_id_t fd, Status &error) {
+ if (IsHost())
+ return FileCache::GetInstance().CloseFile(fd, error);
+ return false;
+}
+
+user_id_t Platform::GetFileSize(const FileSpec &file_spec) {
+ if (!IsHost())
+ return UINT64_MAX;
+
+ uint64_t Size;
+ if (llvm::sys::fs::file_size(file_spec.GetPath(), Size))
+ return 0;
+ return Size;
+}
+
+uint64_t Platform::ReadFile(lldb::user_id_t fd, uint64_t offset, void *dst,
+ uint64_t dst_len, Status &error) {
+ if (IsHost())
+ return FileCache::GetInstance().ReadFile(fd, offset, dst, dst_len, error);
+ error.SetErrorStringWithFormatv(
+ "Platform::ReadFile() is not supported in the {0} platform",
+ GetPluginName());
+ return -1;
+}
+
+uint64_t Platform::WriteFile(lldb::user_id_t fd, uint64_t offset,
+ const void *src, uint64_t src_len, Status &error) {
+ if (IsHost())
+ return FileCache::GetInstance().WriteFile(fd, offset, src, src_len, error);
+ error.SetErrorStringWithFormatv(
+ "Platform::WriteFile() is not supported in the {0} platform",
+ GetPluginName());
+ return -1;
+}
+
+UserIDResolver &Platform::GetUserIDResolver() {
+ if (IsHost())
+ return HostInfo::GetUserIDResolver();
+ return UserIDResolver::GetNoopResolver();
+}
const char *Platform::GetHostname() {
if (IsHost())
return "127.0.0.1";
- if (m_name.empty())
+ if (m_hostname.empty())
return nullptr;
- return m_name.c_str();
+ return m_hostname.c_str();
}
ConstString Platform::GetFullNameForDylib(ConstString basename) {
@@ -802,7 +735,7 @@ ConstString Platform::GetFullNameForDylib(ConstString basename) {
}
bool Platform::SetRemoteWorkingDirectory(const FileSpec &working_dir) {
- Log *log = GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PLATFORM);
+ Log *log = GetLog(LLDBLog::Platform);
LLDB_LOGF(log, "Platform::SetRemoteWorkingDirectory('%s')",
working_dir.GetCString());
m_working_dir = working_dir;
@@ -847,7 +780,9 @@ Platform::ResolveExecutable(const ModuleSpec &module_spec,
// architectures that we should be using (in the correct order) and see
// if we can find a match that way
ModuleSpec arch_module_spec(module_spec);
- for (const ArchSpec &arch : GetSupportedArchitectures()) {
+ ArchSpec process_host_arch;
+ for (const ArchSpec &arch :
+ GetSupportedArchitectures(process_host_arch)) {
arch_module_spec.GetArchitecture() = arch;
error = ModuleList::GetSharedModule(arch_module_spec, exe_module_sp,
module_search_paths_ptr, nullptr,
@@ -894,7 +829,8 @@ Platform::ResolveRemoteExecutable(const ModuleSpec &module_spec,
// correct order) and see if we can find a match that way
StreamString arch_names;
llvm::ListSeparator LS;
- for (const ArchSpec &arch : GetSupportedArchitectures()) {
+ ArchSpec process_host_arch;
+ for (const ArchSpec &arch : GetSupportedArchitectures(process_host_arch)) {
resolved_module_spec.GetArchitecture() = arch;
error = ModuleList::GetSharedModule(resolved_module_spec, exe_module_sp,
module_search_paths_ptr, nullptr,
@@ -992,7 +928,7 @@ ArchSpec Platform::GetAugmentedArchSpec(llvm::StringRef triple) {
ArchSpec compatible_arch;
ArchSpec raw_arch(triple);
- if (!IsCompatibleArchitecture(raw_arch, false, &compatible_arch))
+ if (!IsCompatibleArchitecture(raw_arch, {}, false, &compatible_arch))
return raw_arch;
if (!compatible_arch.IsValid())
@@ -1056,7 +992,7 @@ uint32_t Platform::FindProcesses(const ProcessInstanceInfoMatch &match_info,
Status Platform::LaunchProcess(ProcessLaunchInfo &launch_info) {
Status error;
- Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_PLATFORM));
+ Log *log = GetLog(LLDBLog::Platform);
LLDB_LOGF(log, "Platform::%s()", __FUNCTION__);
// Take care of the host case so that each subclass can just call this
@@ -1109,7 +1045,7 @@ Status Platform::ShellExpandArguments(ProcessLaunchInfo &launch_info) {
}
Status Platform::KillProcess(const lldb::pid_t pid) {
- Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_PLATFORM));
+ Log *log = GetLog(LLDBLog::Platform);
LLDB_LOGF(log, "Platform::%s, pid %" PRIu64, __FUNCTION__, pid);
if (!IsHost()) {
@@ -1123,7 +1059,7 @@ Status Platform::KillProcess(const lldb::pid_t pid) {
lldb::ProcessSP Platform::DebugProcess(ProcessLaunchInfo &launch_info,
Debugger &debugger, Target &target,
Status &error) {
- Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_PLATFORM));
+ Log *log = GetLog(LLDBLog::Platform);
LLDB_LOG(log, "target = {0})", &target);
ProcessSP process_sp;
@@ -1202,16 +1138,6 @@ lldb::ProcessSP Platform::DebugProcess(ProcessLaunchInfo &launch_info,
return process_sp;
}
-lldb::PlatformSP
-Platform::GetPlatformForArchitecture(const ArchSpec &arch,
- ArchSpec *platform_arch_ptr) {
- lldb::PlatformSP platform_sp;
- Status error;
- if (arch.IsValid())
- platform_sp = Platform::Create(arch, platform_arch_ptr, error);
- return platform_sp;
-}
-
std::vector<ArchSpec>
Platform::CreateArchList(llvm::ArrayRef<llvm::Triple::ArchType> archs,
llvm::Triple::OSType os) {
@@ -1228,6 +1154,7 @@ Platform::CreateArchList(llvm::ArrayRef<llvm::Triple::ArchType> archs,
/// Lets a platform answer if it is compatible with a given
/// architecture and the target triple contained within.
bool Platform::IsCompatibleArchitecture(const ArchSpec &arch,
+ const ArchSpec &process_host_arch,
bool exact_arch_match,
ArchSpec *compatible_arch_ptr) {
// If the architecture is invalid, we must answer true...
@@ -1235,7 +1162,8 @@ bool Platform::IsCompatibleArchitecture(const ArchSpec &arch,
ArchSpec platform_arch;
auto match = exact_arch_match ? &ArchSpec::IsExactMatch
: &ArchSpec::IsCompatibleMatch;
- for (const ArchSpec &platform_arch : GetSupportedArchitectures()) {
+ for (const ArchSpec &platform_arch :
+ GetSupportedArchitectures(process_host_arch)) {
if ((arch.*match)(platform_arch)) {
if (compatible_arch_ptr)
*compatible_arch_ptr = platform_arch;
@@ -1250,7 +1178,7 @@ bool Platform::IsCompatibleArchitecture(const ArchSpec &arch,
Status Platform::PutFile(const FileSpec &source, const FileSpec &destination,
uint32_t uid, uint32_t gid) {
- Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_PLATFORM));
+ Log *log = GetLog(LLDBLog::Platform);
LLDB_LOGF(log, "[PutFile] Using block by block transfer....\n");
auto source_open_options =
@@ -1278,7 +1206,7 @@ Status Platform::PutFile(const FileSpec &source, const FileSpec &destination,
return error;
if (dest_file == UINT64_MAX)
return Status("unable to open target file");
- lldb::DataBufferSP buffer_sp(new DataBufferHeap(1024 * 16, 0));
+ lldb::WritableDataBufferSP buffer_sp(new DataBufferHeap(1024 * 16, 0));
uint64_t offset = 0;
for (;;) {
size_t bytes_read = buffer_sp->GetByteSize();
@@ -1317,17 +1245,21 @@ Status
Platform::CreateSymlink(const FileSpec &src, // The name of the link is in src
const FileSpec &dst) // The symlink points to dst
{
- Status error("unimplemented");
- return error;
+ if (IsHost())
+ return FileSystem::Instance().Symlink(src, dst);
+ return Status("unimplemented");
}
bool Platform::GetFileExists(const lldb_private::FileSpec &file_spec) {
+ if (IsHost())
+ return FileSystem::Instance().Exists(file_spec);
return false;
}
Status Platform::Unlink(const FileSpec &path) {
- Status error("unimplemented");
- return error;
+ if (IsHost())
+ return llvm::sys::fs::remove(path.GetPath());
+ return Status("unimplemented");
}
MmapArgList Platform::GetMmapArgumentList(const ArchSpec &arch, addr_t addr,
@@ -1373,8 +1305,7 @@ lldb_private::Status Platform::RunShellCommand(
if (IsHost())
return Host::RunShellCommand(shell, command, working_dir, status_ptr,
signo_ptr, command_output, timeout);
- else
- return Status("unimplemented");
+ return Status("unable to run a remote command without a platform");
}
bool Platform::CalculateMD5(const FileSpec &file_spec, uint64_t &low,
@@ -1533,7 +1464,11 @@ lldb_private::Status OptionGroupPlatformCaching::SetOptionValue(
return error;
}
-Environment Platform::GetEnvironment() { return Environment(); }
+Environment Platform::GetEnvironment() {
+ if (IsHost())
+ return Host::GetEnvironment();
+ return Environment();
+}
const std::vector<ConstString> &Platform::GetTrapHandlerSymbolNames() {
if (!m_calculated_trap_handlers) {
@@ -1573,8 +1508,10 @@ Status Platform::GetRemoteSharedModule(const ModuleSpec &module_spec,
bool *did_create_ptr) {
// Get module information from a target.
ModuleSpec resolved_module_spec;
+ ArchSpec process_host_arch;
bool got_module_spec = false;
if (process) {
+ process_host_arch = process->GetSystemArchitecture();
// Try to get module information from the process
if (process->GetModuleSpec(module_spec.GetFileSpec(),
module_spec.GetArchitecture(),
@@ -1592,7 +1529,7 @@ Status Platform::GetRemoteSharedModule(const ModuleSpec &module_spec,
// architectures that we should be using (in the correct order) and see if
// we can find a match that way
ModuleSpec arch_module_spec(module_spec);
- for (const ArchSpec &arch : GetSupportedArchitectures()) {
+ for (const ArchSpec &arch : GetSupportedArchitectures(process_host_arch)) {
arch_module_spec.GetArchitecture() = arch;
error = ModuleList::GetSharedModule(arch_module_spec, module_sp, nullptr,
nullptr, nullptr);
@@ -1646,7 +1583,7 @@ bool Platform::GetCachedSharedModule(const ModuleSpec &module_spec,
!GetGlobalPlatformProperties().GetModuleCacheDirectory())
return false;
- Log *log = GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PLATFORM);
+ Log *log = GetLog(LLDBLog::Platform);
// Check local cache for a module.
auto error = m_module_cache->GetAndPut(
@@ -1728,7 +1665,7 @@ Status Platform::DownloadSymbolFile(const lldb::ModuleSP &module_sp,
FileSpec Platform::GetModuleCacheRoot() {
auto dir_spec = GetGlobalPlatformProperties().GetModuleCacheDirectory();
- dir_spec.AppendPathComponent(GetName().AsCString());
+ dir_spec.AppendPathComponent(GetPluginName());
return dir_spec;
}
@@ -2007,3 +1944,133 @@ size_t Platform::GetSoftwareBreakpointTrapOpcode(Target &target,
CompilerType Platform::GetSiginfoType(const llvm::Triple& triple) {
return CompilerType();
}
+
+Args Platform::GetExtraStartupCommands() {
+ return {};
+}
+
+PlatformSP PlatformList::GetOrCreate(llvm::StringRef name) {
+ std::lock_guard<std::recursive_mutex> guard(m_mutex);
+ for (const PlatformSP &platform_sp : m_platforms) {
+ if (platform_sp->GetName() == name)
+ return platform_sp;
+ }
+ return Create(name);
+}
+
+PlatformSP PlatformList::GetOrCreate(const ArchSpec &arch,
+ const ArchSpec &process_host_arch,
+ ArchSpec *platform_arch_ptr,
+ Status &error) {
+ std::lock_guard<std::recursive_mutex> guard(m_mutex);
+ // First try exact arch matches across all platforms already created
+ for (const auto &platform_sp : m_platforms) {
+ if (platform_sp->IsCompatibleArchitecture(arch, process_host_arch, true,
+ platform_arch_ptr))
+ return platform_sp;
+ }
+
+ // Next try compatible arch matches across all platforms already created
+ for (const auto &platform_sp : m_platforms) {
+ if (platform_sp->IsCompatibleArchitecture(arch, process_host_arch, false,
+ platform_arch_ptr))
+ return platform_sp;
+ }
+
+ PlatformCreateInstance create_callback;
+ // First try exact arch matches across all platform plug-ins
+ uint32_t idx;
+ for (idx = 0;
+ (create_callback = PluginManager::GetPlatformCreateCallbackAtIndex(idx));
+ ++idx) {
+ PlatformSP platform_sp = create_callback(false, &arch);
+ if (platform_sp && platform_sp->IsCompatibleArchitecture(
+ arch, process_host_arch, true, platform_arch_ptr)) {
+ m_platforms.push_back(platform_sp);
+ return platform_sp;
+ }
+ }
+ // Next try compatible arch matches across all platform plug-ins
+ for (idx = 0;
+ (create_callback = PluginManager::GetPlatformCreateCallbackAtIndex(idx));
+ ++idx) {
+ PlatformSP platform_sp = create_callback(false, &arch);
+ if (platform_sp && platform_sp->IsCompatibleArchitecture(
+ arch, process_host_arch, false, platform_arch_ptr)) {
+ m_platforms.push_back(platform_sp);
+ return platform_sp;
+ }
+ }
+ if (platform_arch_ptr)
+ platform_arch_ptr->Clear();
+ return nullptr;
+}
+
+PlatformSP PlatformList::GetOrCreate(const ArchSpec &arch,
+ const ArchSpec &process_host_arch,
+ ArchSpec *platform_arch_ptr) {
+ Status error;
+ if (arch.IsValid())
+ return GetOrCreate(arch, process_host_arch, platform_arch_ptr, error);
+ return nullptr;
+}
+
+PlatformSP PlatformList::GetOrCreate(llvm::ArrayRef<ArchSpec> archs,
+ const ArchSpec &process_host_arch,
+ std::vector<PlatformSP> &candidates) {
+ candidates.clear();
+ candidates.reserve(archs.size());
+
+ if (archs.empty())
+ return nullptr;
+
+ PlatformSP host_platform_sp = Platform::GetHostPlatform();
+
+ // Prefer the selected platform if it matches at least one architecture.
+ if (m_selected_platform_sp) {
+ for (const ArchSpec &arch : archs) {
+ if (m_selected_platform_sp->IsCompatibleArchitecture(
+ arch, process_host_arch, false, nullptr))
+ return m_selected_platform_sp;
+ }
+ }
+
+ // Prefer the host platform if it matches at least one architecture.
+ if (host_platform_sp) {
+ for (const ArchSpec &arch : archs) {
+ if (host_platform_sp->IsCompatibleArchitecture(arch, process_host_arch,
+ false, nullptr))
+ return host_platform_sp;
+ }
+ }
+
+ // Collect a list of candidate platforms for the architectures.
+ for (const ArchSpec &arch : archs) {
+ if (PlatformSP platform = GetOrCreate(arch, process_host_arch, nullptr))
+ candidates.push_back(platform);
+ }
+
+ // The selected or host platform didn't match any of the architectures. If
+ // the same platform supports all architectures then that's the obvious next
+ // best thing.
+ if (candidates.size() == archs.size()) {
+ if (std::all_of(candidates.begin(), candidates.end(),
+ [&](const PlatformSP &p) -> bool {
+ return p->GetName() == candidates.front()->GetName();
+ })) {
+ return candidates.front();
+ }
+ }
+
+ // At this point we either have no platforms that match the given
+ // architectures or multiple platforms with no good way to disambiguate
+ // between them.
+ return nullptr;
+}
+
+PlatformSP PlatformList::Create(llvm::StringRef name) {
+ std::lock_guard<std::recursive_mutex> guard(m_mutex);
+ PlatformSP platform_sp = Platform::Create(name);
+ m_platforms.push_back(platform_sp);
+ return platform_sp;
+}