[lldb] Remove the global platform list
This patch moves the platform creation and selection logic into the per-debugger platform lists. I've tried to keep functional changes to a minimum -- the main (only) observable difference in this change is that APIs, which select a platform by name (e.g., Debugger::SetCurrentPlatform) will not automatically pick up a platform associated with another debugger (or no debugger at all). I've also added several tests for this functionality -- one of the pleasant consequences of the debugger isolation is that it is now possible to test the platform selection and creation logic. This is a product of the discussion at <https://discourse.llvm.org/t/multiple-platforms-with-the-same-name/59594>. Differential Revision: https://reviews.llvm.org/D120810
This commit is contained in:
@@ -94,79 +94,11 @@ public:
|
||||
/// attaching to processes unless another platform is specified.
|
||||
static lldb::PlatformSP GetHostPlatform();
|
||||
|
||||
/// Get the platform for the given architecture. See Platform::Create for how
|
||||
/// a platform is chosen for a given architecture.
|
||||
///
|
||||
/// \param[in] arch
|
||||
/// The architecture for which we are getting a platform.
|
||||
///
|
||||
/// \param[in] process_host_arch
|
||||
/// The process host architecture if it's known. An invalid ArchSpec
|
||||
/// represents that the process host architecture is unknown.
|
||||
///
|
||||
/// \param[out] platform_arch_ptr
|
||||
/// The architecture which was used to pick the returned platform. This
|
||||
/// can be different from the input architecture if we're looking for a
|
||||
/// compatible match instead of an exact match.
|
||||
///
|
||||
/// \return
|
||||
/// Return the platform that matches the input architecture or the
|
||||
/// default (invalid) platform if none could be found.
|
||||
static lldb::PlatformSP
|
||||
GetPlatformForArchitecture(const ArchSpec &arch,
|
||||
const ArchSpec &process_host_arch = {},
|
||||
ArchSpec *platform_arch_ptr = nullptr);
|
||||
|
||||
/// Get the platform for the given list of architectures.
|
||||
///
|
||||
/// The algorithm works a follows:
|
||||
///
|
||||
/// 1. Returns the selected platform if it matches any of the architectures.
|
||||
/// 2. Returns the host platform if it matches any of the architectures.
|
||||
/// 3. Returns the platform that matches all the architectures.
|
||||
///
|
||||
/// If none of the above apply, this function returns a default platform. The
|
||||
/// candidates output argument differentiates between either no platforms
|
||||
/// supporting the given architecture or multiple platforms supporting the
|
||||
/// given architecture.
|
||||
///
|
||||
/// \param[in] arch
|
||||
/// The architecture for which we are getting a platform.
|
||||
///
|
||||
/// \param[in] process_host_arch
|
||||
/// The process host architecture if it's known. An invalid ArchSpec
|
||||
/// represents that the process host architecture is unknown.
|
||||
///
|
||||
/// \param[in] selected_platform_sp
|
||||
/// The currently selected platform.
|
||||
///
|
||||
/// \param[out] candidates
|
||||
/// A list of candidate platforms in case multiple platforms could
|
||||
/// support the given list of architectures. If no platforms match the
|
||||
/// given architecture the list will be empty.
|
||||
///
|
||||
/// \return
|
||||
/// Return the platform that matches the input architectures or the
|
||||
/// default (invalid) platform if no platforms support the given
|
||||
/// architectures or multiple platforms support the given architecture.
|
||||
static lldb::PlatformSP
|
||||
GetPlatformForArchitectures(std::vector<ArchSpec> archs,
|
||||
const ArchSpec &process_host_arch,
|
||||
lldb::PlatformSP selected_platform_sp,
|
||||
std::vector<lldb::PlatformSP> &candidates);
|
||||
|
||||
static const char *GetHostPlatformName();
|
||||
|
||||
static void SetHostPlatform(const lldb::PlatformSP &platform_sp);
|
||||
|
||||
// Find an existing platform plug-in by name
|
||||
static lldb::PlatformSP Find(ConstString name);
|
||||
|
||||
static lldb::PlatformSP Create(ConstString name, Status &error);
|
||||
|
||||
static lldb::PlatformSP Create(const ArchSpec &arch,
|
||||
const ArchSpec &process_host_arch,
|
||||
ArchSpec *platform_arch_ptr, Status &error);
|
||||
static lldb::PlatformSP Create(llvm::StringRef name);
|
||||
|
||||
/// Augments the triple either with information from platform or the host
|
||||
/// system (if platform is null).
|
||||
@@ -917,9 +849,6 @@ public:
|
||||
virtual CompilerType GetSiginfoType(const llvm::Triple &triple);
|
||||
|
||||
protected:
|
||||
/// For unit testing purposes only.
|
||||
static void Clear();
|
||||
|
||||
/// Create a list of ArchSpecs with the given OS and a architectures. The
|
||||
/// vendor field is left as an "unspecified unknown".
|
||||
static std::vector<ArchSpec>
|
||||
@@ -1069,6 +998,32 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
lldb::PlatformSP GetOrCreate(llvm::StringRef name);
|
||||
lldb::PlatformSP GetOrCreate(const ArchSpec &arch,
|
||||
const ArchSpec &process_host_arch,
|
||||
ArchSpec *platform_arch_ptr, Status &error);
|
||||
lldb::PlatformSP GetOrCreate(const ArchSpec &arch,
|
||||
const ArchSpec &process_host_arch,
|
||||
ArchSpec *platform_arch_ptr);
|
||||
|
||||
/// Get the platform for the given list of architectures.
|
||||
///
|
||||
/// The algorithm works a follows:
|
||||
///
|
||||
/// 1. Returns the selected platform if it matches any of the architectures.
|
||||
/// 2. Returns the host platform if it matches any of the architectures.
|
||||
/// 3. Returns the platform that matches all the architectures.
|
||||
///
|
||||
/// If none of the above apply, this function returns a default platform. The
|
||||
/// candidates output argument differentiates between either no platforms
|
||||
/// supporting the given architecture or multiple platforms supporting the
|
||||
/// given architecture.
|
||||
lldb::PlatformSP GetOrCreate(llvm::ArrayRef<ArchSpec> archs,
|
||||
const ArchSpec &process_host_arch,
|
||||
std::vector<lldb::PlatformSP> &candidates);
|
||||
|
||||
lldb::PlatformSP Create(llvm::StringRef name);
|
||||
|
||||
protected:
|
||||
typedef std::vector<lldb::PlatformSP> collection;
|
||||
mutable std::recursive_mutex m_mutex;
|
||||
|
||||
@@ -902,6 +902,7 @@ def run_suite():
|
||||
(configuration.lldb_platform_name))
|
||||
lldb.remote_platform = lldb.SBPlatform(
|
||||
configuration.lldb_platform_name)
|
||||
lldb.selected_platform = lldb.remote_platform
|
||||
if not lldb.remote_platform.IsValid():
|
||||
print(
|
||||
"error: unable to create the LLDB platform named '%s'." %
|
||||
@@ -918,7 +919,6 @@ def run_suite():
|
||||
err = lldb.remote_platform.ConnectRemote(platform_connect_options)
|
||||
if err.Success():
|
||||
print("Connected.")
|
||||
lldb.selected_platform = lldb.remote_platform
|
||||
else:
|
||||
print("error: failed to connect to remote platform using URL '%s': %s" % (
|
||||
configuration.lldb_platform_url, err))
|
||||
|
||||
@@ -1460,21 +1460,11 @@ SBError SBDebugger::SetCurrentPlatform(const char *platform_name_cstr) {
|
||||
SBError sb_error;
|
||||
if (m_opaque_sp) {
|
||||
if (platform_name_cstr && platform_name_cstr[0]) {
|
||||
ConstString platform_name(platform_name_cstr);
|
||||
PlatformSP platform_sp(Platform::Find(platform_name));
|
||||
|
||||
if (platform_sp) {
|
||||
// Already have a platform with this name, just select it
|
||||
m_opaque_sp->GetPlatformList().SetSelectedPlatform(platform_sp);
|
||||
} else {
|
||||
// We don't have a platform by this name yet, create one
|
||||
platform_sp = Platform::Create(platform_name, sb_error.ref());
|
||||
if (platform_sp) {
|
||||
// We created the platform, now append and select it
|
||||
bool make_selected = true;
|
||||
m_opaque_sp->GetPlatformList().Append(platform_sp, make_selected);
|
||||
}
|
||||
}
|
||||
PlatformList &platforms = m_opaque_sp->GetPlatformList();
|
||||
if (PlatformSP platform_sp = platforms.GetOrCreate(platform_name_cstr))
|
||||
platforms.SetSelectedPlatform(platform_sp);
|
||||
else
|
||||
sb_error.ref().SetErrorString("platform not found");
|
||||
} else {
|
||||
sb_error.ref().SetErrorString("invalid platform name");
|
||||
}
|
||||
|
||||
@@ -292,9 +292,7 @@ SBPlatform::SBPlatform() { LLDB_INSTRUMENT_VA(this); }
|
||||
SBPlatform::SBPlatform(const char *platform_name) {
|
||||
LLDB_INSTRUMENT_VA(this, platform_name);
|
||||
|
||||
Status error;
|
||||
if (platform_name && platform_name[0])
|
||||
m_opaque_sp = Platform::Create(ConstString(platform_name), error);
|
||||
m_opaque_sp = Platform::Create(platform_name);
|
||||
}
|
||||
|
||||
SBPlatform::SBPlatform(const SBPlatform &rhs) {
|
||||
|
||||
@@ -18,10 +18,17 @@ using namespace lldb_private;
|
||||
PlatformSP OptionGroupPlatform::CreatePlatformWithOptions(
|
||||
CommandInterpreter &interpreter, const ArchSpec &arch, bool make_selected,
|
||||
Status &error, ArchSpec &platform_arch) const {
|
||||
PlatformList &platforms = interpreter.GetDebugger().GetPlatformList();
|
||||
|
||||
PlatformSP platform_sp;
|
||||
|
||||
if (!m_platform_name.empty()) {
|
||||
platform_sp = Platform::Create(ConstString(m_platform_name.c_str()), error);
|
||||
platform_sp = platforms.Create(m_platform_name);
|
||||
if (!platform_sp) {
|
||||
error.SetErrorStringWithFormatv(
|
||||
"unable to find a plug-in for the platform named \"{0}\"",
|
||||
m_platform_name);
|
||||
}
|
||||
if (platform_sp) {
|
||||
if (platform_arch.IsValid() && !platform_sp->IsCompatibleArchitecture(
|
||||
arch, {}, false, &platform_arch)) {
|
||||
@@ -33,12 +40,12 @@ PlatformSP OptionGroupPlatform::CreatePlatformWithOptions(
|
||||
}
|
||||
}
|
||||
} else if (arch.IsValid()) {
|
||||
platform_sp = Platform::Create(arch, {}, &platform_arch, error);
|
||||
platform_sp = platforms.GetOrCreate(arch, {}, &platform_arch, error);
|
||||
}
|
||||
|
||||
if (platform_sp) {
|
||||
interpreter.GetDebugger().GetPlatformList().Append(platform_sp,
|
||||
make_selected);
|
||||
if (make_selected)
|
||||
platforms.SetSelectedPlatform(platform_sp);
|
||||
if (!m_os_version.empty())
|
||||
platform_sp->SetOSVersion(m_os_version);
|
||||
|
||||
|
||||
@@ -511,8 +511,9 @@ DynamicLoaderDarwinKernel::DynamicLoaderDarwinKernel(Process *process,
|
||||
m_kext_summary_header(), m_known_kexts(), m_mutex(),
|
||||
m_break_id(LLDB_INVALID_BREAK_ID) {
|
||||
Status error;
|
||||
PlatformSP platform_sp(Platform::Create(
|
||||
ConstString(PlatformDarwinKernel::GetPluginNameStatic()), error));
|
||||
PlatformSP platform_sp =
|
||||
process->GetTarget().GetDebugger().GetPlatformList().Create(
|
||||
PlatformDarwinKernel::GetPluginNameStatic());
|
||||
if (platform_sp.get())
|
||||
process->GetTarget().SetPlatform(platform_sp);
|
||||
}
|
||||
|
||||
@@ -7,5 +7,6 @@ add_lldb_library(lldbPluginPlatformPOSIX
|
||||
lldbHost
|
||||
lldbInterpreter
|
||||
lldbTarget
|
||||
lldbPluginPlatformGDB
|
||||
lldbPluginTypeSystemClang
|
||||
)
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
|
||||
#include "PlatformPOSIX.h"
|
||||
|
||||
#include "Plugins/Platform/gdb-server/PlatformRemoteGDBServer.h"
|
||||
#include "Plugins/TypeSystem/Clang/TypeSystemClang.h"
|
||||
#include "lldb/Core/Debugger.h"
|
||||
#include "lldb/Core/Module.h"
|
||||
@@ -307,7 +308,8 @@ Status PlatformPOSIX::ConnectRemote(Args &args) {
|
||||
} else {
|
||||
if (!m_remote_platform_sp)
|
||||
m_remote_platform_sp =
|
||||
Platform::Create(ConstString("remote-gdb-server"), error);
|
||||
platform_gdb_server::PlatformRemoteGDBServer::CreateInstance(
|
||||
/*force=*/true, nullptr);
|
||||
|
||||
if (m_remote_platform_sp && error.Success())
|
||||
error = m_remote_platform_sp->ConnectRemote(args);
|
||||
|
||||
@@ -6,6 +6,7 @@ add_lldb_library(lldbPluginPlatformWindows PLUGIN
|
||||
lldbCore
|
||||
lldbHost
|
||||
lldbTarget
|
||||
lldbPluginPlatformGDB
|
||||
|
||||
LINK_COMPONENTS
|
||||
Support
|
||||
|
||||
@@ -14,6 +14,8 @@
|
||||
#include <winsock2.h>
|
||||
#endif
|
||||
|
||||
#include "Plugins/Platform/gdb-server/PlatformRemoteGDBServer.h"
|
||||
#include "Plugins/TypeSystem/Clang/TypeSystemClang.h"
|
||||
#include "lldb/Breakpoint/BreakpointLocation.h"
|
||||
#include "lldb/Breakpoint/BreakpointSite.h"
|
||||
#include "lldb/Core/Debugger.h"
|
||||
@@ -28,8 +30,6 @@
|
||||
#include "lldb/Target/Process.h"
|
||||
#include "lldb/Utility/Status.h"
|
||||
|
||||
#include "Plugins/TypeSystem/Clang/TypeSystemClang.h"
|
||||
|
||||
#include "llvm/ADT/ScopeExit.h"
|
||||
#include "llvm/Support/ConvertUTF.h"
|
||||
|
||||
@@ -140,7 +140,8 @@ Status PlatformWindows::ConnectRemote(Args &args) {
|
||||
} else {
|
||||
if (!m_remote_platform_sp)
|
||||
m_remote_platform_sp =
|
||||
Platform::Create(ConstString("remote-gdb-server"), error);
|
||||
platform_gdb_server::PlatformRemoteGDBServer::CreateInstance(
|
||||
/*force=*/true, nullptr);
|
||||
|
||||
if (m_remote_platform_sp) {
|
||||
if (error.Success()) {
|
||||
|
||||
@@ -7,4 +7,5 @@ add_lldb_library(lldbPluginPlatformGDB PLUGIN
|
||||
lldbHost
|
||||
lldbTarget
|
||||
lldbPluginProcessUtility
|
||||
lldbPluginProcessGDBRemote
|
||||
)
|
||||
|
||||
@@ -51,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() {
|
||||
@@ -137,28 +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;
|
||||
}
|
||||
void Platform::Initialize() {}
|
||||
|
||||
static std::recursive_mutex &GetPlatformListMutex() {
|
||||
static std::recursive_mutex g_mutex;
|
||||
return g_mutex;
|
||||
}
|
||||
|
||||
void Platform::Initialize() { g_initialize_count++; }
|
||||
|
||||
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::Clear() { GetPlatformList().clear(); }
|
||||
void Platform::Terminate() {}
|
||||
|
||||
PlatformProperties &Platform::GetGlobalPlatformProperties() {
|
||||
static PlatformProperties g_settings;
|
||||
@@ -169,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,
|
||||
@@ -276,109 +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.GetStringRef())
|
||||
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();
|
||||
if (name == GetHostPlatformName())
|
||||
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,
|
||||
const ArchSpec &process_host_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, 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 : GetPlatformList()) {
|
||||
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) {
|
||||
if (create_callback) {
|
||||
platform_sp = create_callback(false, &arch);
|
||||
if (platform_sp &&
|
||||
platform_sp->IsCompatibleArchitecture(arch, process_host_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, process_host_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) {
|
||||
@@ -1258,73 +1138,6 @@ lldb::ProcessSP Platform::DebugProcess(ProcessLaunchInfo &launch_info,
|
||||
return process_sp;
|
||||
}
|
||||
|
||||
lldb::PlatformSP
|
||||
Platform::GetPlatformForArchitecture(const ArchSpec &arch,
|
||||
const ArchSpec &process_host_arch,
|
||||
ArchSpec *platform_arch_ptr) {
|
||||
lldb::PlatformSP platform_sp;
|
||||
Status error;
|
||||
if (arch.IsValid())
|
||||
platform_sp =
|
||||
Platform::Create(arch, process_host_arch, platform_arch_ptr, error);
|
||||
return platform_sp;
|
||||
}
|
||||
|
||||
lldb::PlatformSP Platform::GetPlatformForArchitectures(
|
||||
std::vector<ArchSpec> archs, const ArchSpec &process_host_arch,
|
||||
lldb::PlatformSP selected_platform_sp,
|
||||
std::vector<lldb::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 (selected_platform_sp) {
|
||||
for (const ArchSpec &arch : archs) {
|
||||
if (selected_platform_sp->IsCompatibleArchitecture(
|
||||
arch, process_host_arch, false, nullptr))
|
||||
return 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 =
|
||||
Platform::GetPlatformForArchitecture(arch, process_host_arch))
|
||||
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;
|
||||
}
|
||||
|
||||
std::vector<ArchSpec>
|
||||
Platform::CreateArchList(llvm::ArrayRef<llvm::Triple::ArchType> archs,
|
||||
llvm::Triple::OSType os) {
|
||||
@@ -2131,3 +1944,129 @@ size_t Platform::GetSoftwareBreakpointTrapOpcode(Target &target,
|
||||
CompilerType Platform::GetSiginfoType(const llvm::Triple& triple) {
|
||||
return CompilerType();
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -2892,7 +2892,7 @@ void Process::CompleteAttach() {
|
||||
!platform_sp->IsCompatibleArchitecture(target_arch, process_host_arch,
|
||||
false, nullptr)) {
|
||||
ArchSpec platform_arch;
|
||||
platform_sp = platform_sp->GetPlatformForArchitecture(
|
||||
platform_sp = GetTarget().GetDebugger().GetPlatformList().GetOrCreate(
|
||||
target_arch, process_host_arch, &platform_arch);
|
||||
if (platform_sp) {
|
||||
GetTarget().SetPlatform(platform_sp);
|
||||
|
||||
@@ -1485,9 +1485,9 @@ bool Target::SetArchitecture(const ArchSpec &arch_spec, bool set_platform) {
|
||||
if (!platform_sp ||
|
||||
!platform_sp->IsCompatibleArchitecture(other, {}, false, nullptr)) {
|
||||
ArchSpec platform_arch;
|
||||
auto arch_platform_sp =
|
||||
Platform::GetPlatformForArchitecture(other, {}, &platform_arch);
|
||||
if (arch_platform_sp) {
|
||||
if (PlatformSP arch_platform_sp =
|
||||
GetDebugger().GetPlatformList().GetOrCreate(other, {},
|
||||
&platform_arch)) {
|
||||
SetPlatform(arch_platform_sp);
|
||||
if (platform_arch.IsValid())
|
||||
other = platform_arch;
|
||||
|
||||
@@ -79,8 +79,9 @@ Status TargetList::CreateTargetInternal(
|
||||
const OptionGroupPlatform *platform_options, TargetSP &target_sp) {
|
||||
Status error;
|
||||
|
||||
PlatformList &platform_list = debugger.GetPlatformList();
|
||||
// Let's start by looking at the selected platform.
|
||||
PlatformSP platform_sp = debugger.GetPlatformList().GetSelectedPlatform();
|
||||
PlatformSP platform_sp = platform_list.GetSelectedPlatform();
|
||||
|
||||
// This variable corresponds to the architecture specified by the triple
|
||||
// string. If that string was empty the currently selected platform will
|
||||
@@ -176,8 +177,7 @@ Status TargetList::CreateTargetInternal(
|
||||
for (const ModuleSpec &spec : module_specs.ModuleSpecs())
|
||||
archs.push_back(spec.GetArchitecture());
|
||||
if (PlatformSP platform_for_archs_sp =
|
||||
Platform::GetPlatformForArchitectures(archs, {}, platform_sp,
|
||||
candidates)) {
|
||||
platform_list.GetOrCreate(archs, {}, candidates)) {
|
||||
platform_sp = platform_for_archs_sp;
|
||||
} else if (candidates.empty()) {
|
||||
error.SetErrorString("no matching platforms found for this file");
|
||||
@@ -209,21 +209,19 @@ Status TargetList::CreateTargetInternal(
|
||||
// compatible with that architecture.
|
||||
if (!prefer_platform_arch && arch.IsValid()) {
|
||||
if (!platform_sp->IsCompatibleArchitecture(arch, {}, false, nullptr)) {
|
||||
platform_sp =
|
||||
Platform::GetPlatformForArchitecture(arch, {}, &platform_arch);
|
||||
platform_sp = platform_list.GetOrCreate(arch, {}, &platform_arch);
|
||||
if (platform_sp)
|
||||
debugger.GetPlatformList().SetSelectedPlatform(platform_sp);
|
||||
platform_list.SetSelectedPlatform(platform_sp);
|
||||
}
|
||||
} else if (platform_arch.IsValid()) {
|
||||
// If "arch" isn't valid, yet "platform_arch" is, it means we have an
|
||||
// executable file with a single architecture which should be used.
|
||||
ArchSpec fixed_platform_arch;
|
||||
if (!platform_sp->IsCompatibleArchitecture(platform_arch, {}, false,
|
||||
nullptr)) {
|
||||
platform_sp = Platform::GetPlatformForArchitecture(platform_arch, {},
|
||||
&fixed_platform_arch);
|
||||
if (!platform_sp->IsCompatibleArchitecture(platform_arch, {}, false, nullptr)) {
|
||||
platform_sp =
|
||||
platform_list.GetOrCreate(platform_arch, {}, &fixed_platform_arch);
|
||||
if (platform_sp)
|
||||
debugger.GetPlatformList().SetSelectedPlatform(platform_sp);
|
||||
platform_list.SetSelectedPlatform(platform_sp);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -253,7 +251,7 @@ Status TargetList::CreateTargetInternal(Debugger &debugger,
|
||||
if (!platform_sp ||
|
||||
!platform_sp->IsCompatibleArchitecture(arch, {}, false, nullptr))
|
||||
platform_sp =
|
||||
Platform::GetPlatformForArchitecture(specified_arch, {}, &arch);
|
||||
debugger.GetPlatformList().GetOrCreate(specified_arch, {}, &arch);
|
||||
}
|
||||
|
||||
if (!platform_sp)
|
||||
|
||||
@@ -92,3 +92,55 @@ class DebuggerAPITestCase(TestBase):
|
||||
|
||||
# Test the local property again, is it set to new_cache_line_size?
|
||||
self.assertEqual(get_cache_line_size(), new_cache_line_size)
|
||||
|
||||
def test_CreateTarget_platform(self):
|
||||
exe = self.getBuildArtifact("a.out")
|
||||
self.yaml2obj("elf.yaml", exe)
|
||||
error = lldb.SBError()
|
||||
target1 = self.dbg.CreateTarget(exe, None, "remote-linux",
|
||||
False, error)
|
||||
self.assertSuccess(error)
|
||||
platform1 = target1.GetPlatform()
|
||||
platform1.SetWorkingDirectory("/foo/bar")
|
||||
|
||||
# Reuse a platform if it matches the currently selected one...
|
||||
target2 = self.dbg.CreateTarget(exe, None, "remote-linux",
|
||||
False, error)
|
||||
self.assertSuccess(error)
|
||||
platform2 = target2.GetPlatform()
|
||||
self.assertEqual(platform2.GetWorkingDirectory(), "/foo/bar")
|
||||
|
||||
# ... but create a new one if it doesn't.
|
||||
self.dbg.SetSelectedPlatform(lldb.SBPlatform("remote-windows"))
|
||||
target3 = self.dbg.CreateTarget(exe, None, "remote-linux",
|
||||
False, error)
|
||||
self.assertSuccess(error)
|
||||
platform3 = target3.GetPlatform()
|
||||
self.assertIsNone(platform3.GetWorkingDirectory())
|
||||
|
||||
def test_CreateTarget_arch(self):
|
||||
exe = self.getBuildArtifact("a.out")
|
||||
if lldbplatformutil.getHostPlatform() == 'linux':
|
||||
self.yaml2obj("macho.yaml", exe)
|
||||
arch = "x86_64-apple-macosx"
|
||||
else:
|
||||
self.yaml2obj("elf.yaml", exe)
|
||||
arch = "x86_64-pc-linux"
|
||||
|
||||
fbsd = lldb.SBPlatform("remote-freebsd")
|
||||
self.dbg.SetSelectedPlatform(fbsd)
|
||||
|
||||
error = lldb.SBError()
|
||||
target1 = self.dbg.CreateTarget(exe, arch, None, False, error)
|
||||
self.assertSuccess(error)
|
||||
platform1 = target1.GetPlatform()
|
||||
self.assertEqual(platform1.GetName(), "remote-macosx")
|
||||
platform1.SetWorkingDirectory("/foo/bar")
|
||||
|
||||
# Reuse a platform even if it is not currently selected.
|
||||
self.dbg.SetSelectedPlatform(fbsd)
|
||||
target2 = self.dbg.CreateTarget(exe, arch, None, False, error)
|
||||
self.assertSuccess(error)
|
||||
platform2 = target2.GetPlatform()
|
||||
self.assertEqual(platform2.GetName(), "remote-macosx")
|
||||
self.assertEqual(platform2.GetWorkingDirectory(), "/foo/bar")
|
||||
|
||||
35
lldb/test/API/python_api/debugger/elf.yaml
Normal file
35
lldb/test/API/python_api/debugger/elf.yaml
Normal file
@@ -0,0 +1,35 @@
|
||||
--- !ELF
|
||||
FileHeader:
|
||||
Class: ELFCLASS64
|
||||
Data: ELFDATA2LSB
|
||||
Type: ET_EXEC
|
||||
Machine: EM_X86_64
|
||||
Sections:
|
||||
- Name: .text
|
||||
Type: SHT_PROGBITS
|
||||
Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
|
||||
Address: 0x1000
|
||||
AddressAlign: 0x4
|
||||
Content: "c3c3c3c3"
|
||||
- Name: .data
|
||||
Type: SHT_PROGBITS
|
||||
Flags: [ SHF_ALLOC ]
|
||||
Address: 0x2000
|
||||
AddressAlign: 0x4
|
||||
Content: "3232"
|
||||
ProgramHeaders:
|
||||
- Type: PT_LOAD
|
||||
Flags: [ PF_X, PF_R ]
|
||||
VAddr: 0x1000
|
||||
PAddr: 0x1000
|
||||
Align: 0x4
|
||||
FirstSec: .text
|
||||
LastSec: .text
|
||||
- Type: PT_LOAD
|
||||
Flags: [ PF_R, PF_W ]
|
||||
VAddr: 0x2000
|
||||
PAddr: 0x1004
|
||||
Align: 0x4
|
||||
FirstSec: .data
|
||||
LastSec: .data
|
||||
|
||||
42
lldb/test/API/python_api/debugger/macho.yaml
Normal file
42
lldb/test/API/python_api/debugger/macho.yaml
Normal file
@@ -0,0 +1,42 @@
|
||||
--- !mach-o
|
||||
FileHeader:
|
||||
magic: 0xFEEDFACF
|
||||
cputype: 0x01000007
|
||||
cpusubtype: 0x00000003
|
||||
filetype: 0x00000001
|
||||
ncmds: 4
|
||||
sizeofcmds: 1160
|
||||
flags: 0x00002000
|
||||
reserved: 0x00000000
|
||||
LoadCommands:
|
||||
- cmd: LC_SEGMENT_64
|
||||
cmdsize: 1032
|
||||
segname: ''
|
||||
vmaddr: 0
|
||||
vmsize: 744
|
||||
fileoff: 1192
|
||||
filesize: 744
|
||||
maxprot: 7
|
||||
initprot: 7
|
||||
nsects: 12
|
||||
flags: 0
|
||||
Sections:
|
||||
- sectname: __text
|
||||
segname: __TEXT
|
||||
addr: 0x0000000000000000
|
||||
size: 22
|
||||
offset: 0x000004A8
|
||||
align: 4
|
||||
reloff: 0x00000000
|
||||
nreloc: 0
|
||||
flags: 0x80000400
|
||||
reserved1: 0x00000000
|
||||
reserved2: 0x00000000
|
||||
reserved3: 0x00000000
|
||||
- cmd: LC_BUILD_VERSION
|
||||
cmdsize: 24
|
||||
platform: 1
|
||||
minos: 658944
|
||||
sdk: 658944
|
||||
ntools: 0
|
||||
...
|
||||
@@ -25,6 +25,29 @@ class SBPlatformAPICase(TestBase):
|
||||
plat = lldb.SBPlatform("remote-linux") # arbitrary choice
|
||||
self.assertTrue(plat)
|
||||
plat.SetSDKRoot(self.getBuildDir())
|
||||
self.dbg.SetCurrentPlatform("remote-linux")
|
||||
self.dbg.SetSelectedPlatform(plat)
|
||||
self.expect("platform status",
|
||||
substrs=["Sysroot:", self.getBuildDir()])
|
||||
|
||||
def test_SetCurrentPlatform_floating(self):
|
||||
# floating platforms cannot be referenced by name until they are
|
||||
# associated with a debugger
|
||||
floating_platform = lldb.SBPlatform("remote-netbsd")
|
||||
floating_platform.SetWorkingDirectory(self.getBuildDir())
|
||||
self.assertSuccess(self.dbg.SetCurrentPlatform("remote-netbsd"))
|
||||
dbg_platform = self.dbg.GetSelectedPlatform()
|
||||
self.assertEqual(dbg_platform.GetName(), "remote-netbsd")
|
||||
self.assertIsNone(dbg_platform.GetWorkingDirectory())
|
||||
|
||||
def test_SetCurrentPlatform_associated(self):
|
||||
# associated platforms are found by name-based lookup
|
||||
floating_platform = lldb.SBPlatform("remote-netbsd")
|
||||
floating_platform.SetWorkingDirectory(self.getBuildDir())
|
||||
orig_platform = self.dbg.GetSelectedPlatform()
|
||||
|
||||
self.dbg.SetSelectedPlatform(floating_platform)
|
||||
self.dbg.SetSelectedPlatform(orig_platform)
|
||||
self.assertSuccess(self.dbg.SetCurrentPlatform("remote-netbsd"))
|
||||
dbg_platform = self.dbg.GetSelectedPlatform()
|
||||
self.assertEqual(dbg_platform.GetName(), "remote-netbsd")
|
||||
self.assertEqual(dbg_platform.GetWorkingDirectory(), self.getBuildDir())
|
||||
|
||||
@@ -21,7 +21,6 @@ using namespace lldb_private;
|
||||
class TestPlatform : public PlatformPOSIX {
|
||||
public:
|
||||
TestPlatform() : PlatformPOSIX(false) {}
|
||||
using Platform::Clear;
|
||||
};
|
||||
|
||||
class PlatformArm : public TestPlatform {
|
||||
@@ -75,67 +74,66 @@ public:
|
||||
|
||||
class PlatformTest : public ::testing::Test {
|
||||
SubsystemRAII<FileSystem, HostInfo> subsystems;
|
||||
void SetUp() override { TestPlatform::Clear(); }
|
||||
|
||||
protected:
|
||||
PlatformList list;
|
||||
|
||||
void SetHostPlatform(const PlatformSP &platform_sp) {
|
||||
Platform::SetHostPlatform(platform_sp);
|
||||
ASSERT_EQ(Platform::GetHostPlatform(), platform_sp);
|
||||
list.Append(platform_sp, /*set_selected=*/true);
|
||||
}
|
||||
};
|
||||
|
||||
TEST_F(PlatformTest, GetPlatformForArchitecturesHost) {
|
||||
const PlatformSP host_platform_sp = std::make_shared<PlatformArm>();
|
||||
Platform::SetHostPlatform(host_platform_sp);
|
||||
ASSERT_EQ(Platform::GetHostPlatform(), host_platform_sp);
|
||||
SetHostPlatform(std::make_shared<PlatformArm>());
|
||||
|
||||
const std::vector<ArchSpec> archs = {ArchSpec("arm64-apple-ps4"),
|
||||
ArchSpec("arm64e-apple-ps4")};
|
||||
std::vector<PlatformSP> candidates;
|
||||
|
||||
// The host platform matches all architectures.
|
||||
PlatformSP platform_sp =
|
||||
Platform::GetPlatformForArchitectures(archs, {}, {}, candidates);
|
||||
PlatformSP platform_sp = list.GetOrCreate(archs, {}, candidates);
|
||||
ASSERT_TRUE(platform_sp);
|
||||
EXPECT_EQ(platform_sp, host_platform_sp);
|
||||
EXPECT_EQ(platform_sp, Platform::GetHostPlatform());
|
||||
}
|
||||
|
||||
TEST_F(PlatformTest, GetPlatformForArchitecturesSelected) {
|
||||
const PlatformSP host_platform_sp = std::make_shared<PlatformIntel>();
|
||||
Platform::SetHostPlatform(host_platform_sp);
|
||||
ASSERT_EQ(Platform::GetHostPlatform(), host_platform_sp);
|
||||
SetHostPlatform(std::make_shared<PlatformIntel>());
|
||||
|
||||
const std::vector<ArchSpec> archs = {ArchSpec("arm64-apple-ps4"),
|
||||
ArchSpec("arm64e-apple-ps4")};
|
||||
std::vector<PlatformSP> candidates;
|
||||
|
||||
// The host platform matches no architectures. No selected platform.
|
||||
PlatformSP platform_sp =
|
||||
Platform::GetPlatformForArchitectures(archs, {}, {}, candidates);
|
||||
// The host platform matches no architectures.
|
||||
PlatformSP platform_sp = list.GetOrCreate(archs, {}, candidates);
|
||||
ASSERT_FALSE(platform_sp);
|
||||
|
||||
// The selected platform matches all architectures.
|
||||
const PlatformSP selected_platform_sp = std::make_shared<PlatformArm>();
|
||||
platform_sp = Platform::GetPlatformForArchitectures(
|
||||
archs, {}, selected_platform_sp, candidates);
|
||||
list.Append(selected_platform_sp, /*set_selected=*/true);
|
||||
platform_sp = list.GetOrCreate(archs, {}, candidates);
|
||||
ASSERT_TRUE(platform_sp);
|
||||
EXPECT_EQ(platform_sp, selected_platform_sp);
|
||||
}
|
||||
|
||||
TEST_F(PlatformTest, GetPlatformForArchitecturesSelectedOverHost) {
|
||||
const PlatformSP host_platform_sp = std::make_shared<PlatformIntel>();
|
||||
Platform::SetHostPlatform(host_platform_sp);
|
||||
ASSERT_EQ(Platform::GetHostPlatform(), host_platform_sp);
|
||||
SetHostPlatform(std::make_shared<PlatformIntel>());
|
||||
|
||||
const std::vector<ArchSpec> archs = {ArchSpec("arm64-apple-ps4"),
|
||||
ArchSpec("x86_64-apple-ps4")};
|
||||
std::vector<PlatformSP> candidates;
|
||||
|
||||
// The host platform matches one architecture. No selected platform.
|
||||
PlatformSP platform_sp =
|
||||
Platform::GetPlatformForArchitectures(archs, {}, {}, candidates);
|
||||
// The host platform matches one architecture.
|
||||
PlatformSP platform_sp = list.GetOrCreate(archs, {}, candidates);
|
||||
ASSERT_TRUE(platform_sp);
|
||||
EXPECT_EQ(platform_sp, host_platform_sp);
|
||||
EXPECT_EQ(platform_sp, Platform::GetHostPlatform());
|
||||
|
||||
// The selected and host platform each match one architecture.
|
||||
// The selected platform is preferred.
|
||||
const PlatformSP selected_platform_sp = std::make_shared<PlatformArm>();
|
||||
platform_sp = Platform::GetPlatformForArchitectures(
|
||||
archs, {}, selected_platform_sp, candidates);
|
||||
list.Append(selected_platform_sp, /*set_selected=*/true);
|
||||
platform_sp = list.GetOrCreate(archs, {}, candidates);
|
||||
ASSERT_TRUE(platform_sp);
|
||||
EXPECT_EQ(platform_sp, selected_platform_sp);
|
||||
}
|
||||
@@ -143,18 +141,17 @@ TEST_F(PlatformTest, GetPlatformForArchitecturesSelectedOverHost) {
|
||||
TEST_F(PlatformTest, GetPlatformForArchitecturesCandidates) {
|
||||
PlatformThumb::Initialize();
|
||||
|
||||
const PlatformSP host_platform_sp = std::make_shared<PlatformIntel>();
|
||||
Platform::SetHostPlatform(host_platform_sp);
|
||||
ASSERT_EQ(Platform::GetHostPlatform(), host_platform_sp);
|
||||
SetHostPlatform(std::make_shared<PlatformIntel>());
|
||||
|
||||
const PlatformSP selected_platform_sp = std::make_shared<PlatformArm>();
|
||||
list.Append(selected_platform_sp, /*set_selected=*/true);
|
||||
|
||||
const std::vector<ArchSpec> archs = {ArchSpec("thumbv7-apple-ps4"),
|
||||
ArchSpec("thumbv7f-apple-ps4")};
|
||||
std::vector<PlatformSP> candidates;
|
||||
|
||||
// The host platform matches one architecture. No selected platform.
|
||||
PlatformSP platform_sp = Platform::GetPlatformForArchitectures(
|
||||
archs, {}, selected_platform_sp, candidates);
|
||||
// The host platform matches one architecture.
|
||||
PlatformSP platform_sp = list.GetOrCreate(archs, {}, candidates);
|
||||
ASSERT_TRUE(platform_sp);
|
||||
EXPECT_EQ(platform_sp->GetName(), "thumb");
|
||||
|
||||
|
||||
Reference in New Issue
Block a user