Platforms can now auto-select themselves if you specify a full target triple when doing a "target create" command.

Each platform now knows if it can handle an architecture and a platform can be found using an architecture. Each platform can look at the arch, vendor and OS and know if it should be used or not.



git-svn-id: https://llvm.org/svn/llvm-project/lldb/trunk@153104 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/source/API/SBDebugger.cpp b/source/API/SBDebugger.cpp
index ac6fc20..b61acd7 100644
--- a/source/API/SBDebugger.cpp
+++ b/source/API/SBDebugger.cpp
@@ -612,11 +612,12 @@
         Error error;
         const bool add_dependent_modules = true;
 
+        PlatformSP platform_sp(m_opaque_sp->GetPlatformList().GetSelectedPlatform());
         error = m_opaque_sp->GetTargetList().CreateTarget (*m_opaque_sp, 
                                                            file, 
                                                            arch, 
                                                            add_dependent_modules, 
-                                                           m_opaque_sp->GetPlatformList().GetSelectedPlatform(),
+                                                           platform_sp,
                                                            target_sp);
 
         if (error.Success())
diff --git a/source/Commands/CommandObjectPlatform.cpp b/source/Commands/CommandObjectPlatform.cpp
index 855d8fb..9618c6c 100644
--- a/source/Commands/CommandObjectPlatform.cpp
+++ b/source/Commands/CommandObjectPlatform.cpp
@@ -63,7 +63,7 @@
                 const bool select = true;
                 m_platform_options.SetPlatformName (platform_name);
                 Error error;
-                PlatformSP platform_sp (m_platform_options.CreatePlatformWithOptions (m_interpreter, select, error));
+                PlatformSP platform_sp (m_platform_options.CreatePlatformWithOptions (m_interpreter, ArchSpec(), select, error));
                 if (platform_sp)
                 {
                     platform_sp->GetStatus (result.GetOutputStream());
diff --git a/source/Interpreter/OptionGroupPlatform.cpp b/source/Interpreter/OptionGroupPlatform.cpp
index 4e54c39..ca2f3ff 100644
--- a/source/Interpreter/OptionGroupPlatform.cpp
+++ b/source/Interpreter/OptionGroupPlatform.cpp
@@ -21,30 +21,36 @@
 using namespace lldb_private;
 
 PlatformSP 
-OptionGroupPlatform::CreatePlatformWithOptions (CommandInterpreter &interpreter, bool make_selected, Error& error) const
+OptionGroupPlatform::CreatePlatformWithOptions (CommandInterpreter &interpreter, const ArchSpec &arch, bool make_selected, Error& error) const
 {
     PlatformSP platform_sp;
+    
     if (!m_platform_name.empty())
     {
         platform_sp = Platform::Create (m_platform_name.c_str(), error);
-        
-        if (platform_sp)
-        {
-            interpreter.GetDebugger().GetPlatformList().Append (platform_sp, make_selected);
-            if (m_os_version_major != UINT32_MAX)
-            {
-                platform_sp->SetOSVersion (m_os_version_major,
-                                           m_os_version_minor,
-                                           m_os_version_update);
-            }
-            
-            if (m_sdk_sysroot)
-                platform_sp->SetSDKRootDirectory (m_sdk_sysroot);
-
-            if (m_sdk_build)
-                platform_sp->SetSDKBuild (m_sdk_build);
-        }
     }
+    else if (arch.IsValid())
+    {
+        platform_sp = Platform::Create (arch, error);
+    }
+    
+    if (platform_sp)
+    {
+        interpreter.GetDebugger().GetPlatformList().Append (platform_sp, make_selected);
+        if (m_os_version_major != UINT32_MAX)
+        {
+            platform_sp->SetOSVersion (m_os_version_major,
+                                       m_os_version_minor,
+                                       m_os_version_update);
+        }
+        
+        if (m_sdk_sysroot)
+            platform_sp->SetSDKRootDirectory (m_sdk_sysroot);
+        
+        if (m_sdk_build)
+            platform_sp->SetSDKBuild (m_sdk_build);
+    }
+
     return platform_sp;
 }
 
diff --git a/source/Plugins/Platform/FreeBSD/PlatformFreeBSD.cpp b/source/Plugins/Platform/FreeBSD/PlatformFreeBSD.cpp
index ecc96c3..f64235d 100644
--- a/source/Plugins/Platform/FreeBSD/PlatformFreeBSD.cpp
+++ b/source/Plugins/Platform/FreeBSD/PlatformFreeBSD.cpp
@@ -25,9 +25,20 @@
 using namespace lldb_private;
 
 Platform *
-PlatformFreeBSD::CreateInstance ()
+PlatformFreeBSD::CreateInstance (bool force, const lldb_private::ArchSpec *arch)
 {
-    return new PlatformFreeBSD (true);
+    bool create = force;
+    if (create == false && arch && arch->IsValid())
+    {
+        const llvm::Triple &triple = arch->GetTriple();
+        const llvm::Triple::OSType os = triple.getOS();
+        if (os == llvm::Triple::FreeBSD || os == llvm::Triple::KFreeBSD)
+            create = true;
+    }
+    if (create)
+        return new PlatformFreeBSD (true);
+    return NULL;
+
 }
 
 const char *
diff --git a/source/Plugins/Platform/FreeBSD/PlatformFreeBSD.h b/source/Plugins/Platform/FreeBSD/PlatformFreeBSD.h
index 438a0e6..80c4a63 100644
--- a/source/Plugins/Platform/FreeBSD/PlatformFreeBSD.h
+++ b/source/Plugins/Platform/FreeBSD/PlatformFreeBSD.h
@@ -25,7 +25,7 @@
     // Class functions
     //------------------------------------------------------------
     static lldb_private::Platform*
-    CreateInstance ();
+    CreateInstance (bool force, const lldb_private::ArchSpec *arch);
 
     static void
     Initialize ();
diff --git a/source/Plugins/Platform/Linux/PlatformLinux.cpp b/source/Plugins/Platform/Linux/PlatformLinux.cpp
index 80c9a86..58200da 100644
--- a/source/Plugins/Platform/Linux/PlatformLinux.cpp
+++ b/source/Plugins/Platform/Linux/PlatformLinux.cpp
@@ -33,9 +33,19 @@
 static uint32_t g_initialize_count = 0;
 
 Platform *
-PlatformLinux::CreateInstance ()
+PlatformLinux::CreateInstance (bool force, const ArchSpec *arch)
 {
-    return new PlatformLinux(true);
+    bool create = force;
+    if (create == false && arch && arch->IsValid())
+    {
+        const llvm::Triple &triple = arch->GetTriple();
+        const llvm::Triple::OSType os = triple.getOS();
+        if (os == llvm::Triple::Linux)
+            create = true;
+    }
+    if (create)
+        return new PlatformLinux(true);
+    return NULL;
 }
 
 const char *
diff --git a/source/Plugins/Platform/Linux/PlatformLinux.h b/source/Plugins/Platform/Linux/PlatformLinux.h
index 59dde3e..8b43def 100644
--- a/source/Plugins/Platform/Linux/PlatformLinux.h
+++ b/source/Plugins/Platform/Linux/PlatformLinux.h
@@ -37,7 +37,7 @@
         // lldb_private::PluginInterface functions
         //------------------------------------------------------------
         static Platform *
-        CreateInstance ();
+        CreateInstance (bool force, const lldb_private::ArchSpec *arch);
 
         static const char *
         GetPluginNameStatic();
diff --git a/source/Plugins/Platform/MacOSX/PlatformMacOSX.cpp b/source/Plugins/Platform/MacOSX/PlatformMacOSX.cpp
index 6262c59..f7c2374 100644
--- a/source/Plugins/Platform/MacOSX/PlatformMacOSX.cpp
+++ b/source/Plugins/Platform/MacOSX/PlatformMacOSX.cpp
@@ -61,12 +61,24 @@
 }
 
 Platform* 
-PlatformMacOSX::CreateInstance ()
+PlatformMacOSX::CreateInstance (bool force, const ArchSpec *arch)
 {
     // The only time we create an instance is when we are creating a remote
     // macosx platform
     const bool is_host = false;
-    return new PlatformMacOSX (is_host);
+    
+    bool create = force;
+    if (create == false && arch && arch->IsValid())
+    {
+        const llvm::Triple &triple = arch->GetTriple();
+        const llvm::Triple::OSType os = triple.getOS();
+        const llvm::Triple::VendorType vendor = triple.getVendor();
+        if (os == llvm::Triple::Darwin && vendor == llvm::Triple::Apple)
+            create = true;
+    }
+    if (create)
+        return new PlatformMacOSX (is_host);
+    return NULL;
 }
 
 
diff --git a/source/Plugins/Platform/MacOSX/PlatformMacOSX.h b/source/Plugins/Platform/MacOSX/PlatformMacOSX.h
index 4a47b7f..3a5eaf0 100644
--- a/source/Plugins/Platform/MacOSX/PlatformMacOSX.h
+++ b/source/Plugins/Platform/MacOSX/PlatformMacOSX.h
@@ -24,7 +24,7 @@
     // Class functions
     //------------------------------------------------------------
     static lldb_private::Platform* 
-    CreateInstance ();
+    CreateInstance (bool force, const lldb_private::ArchSpec *arch);
 
     static void
     Initialize ();
diff --git a/source/Plugins/Platform/MacOSX/PlatformRemoteiOS.cpp b/source/Plugins/Platform/MacOSX/PlatformRemoteiOS.cpp
index ad49573..61caafc 100644
--- a/source/Plugins/Platform/MacOSX/PlatformRemoteiOS.cpp
+++ b/source/Plugins/Platform/MacOSX/PlatformRemoteiOS.cpp
@@ -60,9 +60,31 @@
 }
 
 Platform* 
-PlatformRemoteiOS::CreateInstance ()
+PlatformRemoteiOS::CreateInstance (bool force, const ArchSpec *arch)
 {
-    return new PlatformRemoteiOS ();
+    bool create = force;
+    if (create == false && arch && arch->IsValid())
+    {
+        switch (arch->GetMachine())
+        {
+        case llvm::Triple::arm:
+        case llvm::Triple::thumb:
+            {
+                const llvm::Triple &triple = arch->GetTriple();
+                const llvm::Triple::OSType os = triple.getOS();
+                const llvm::Triple::VendorType vendor = triple.getVendor();
+                if (os == llvm::Triple::Darwin && vendor == llvm::Triple::Apple)
+                    create = true;
+            }
+            break;
+        default:
+            break;
+        }
+    }
+
+    if (create)
+        return new PlatformRemoteiOS ();
+    return NULL;
 }
 
 
diff --git a/source/Plugins/Platform/MacOSX/PlatformRemoteiOS.h b/source/Plugins/Platform/MacOSX/PlatformRemoteiOS.h
index 9aa33f8..051b584 100644
--- a/source/Plugins/Platform/MacOSX/PlatformRemoteiOS.h
+++ b/source/Plugins/Platform/MacOSX/PlatformRemoteiOS.h
@@ -24,7 +24,7 @@
     // Class Functions
     //------------------------------------------------------------
     static lldb_private::Platform* 
-    CreateInstance ();
+    CreateInstance (bool force, const lldb_private::ArchSpec *arch);
 
     static void
     Initialize ();
diff --git a/source/Plugins/Platform/MacOSX/PlatformiOSSimulator.cpp b/source/Plugins/Platform/MacOSX/PlatformiOSSimulator.cpp
index 18cd4eb..7a8884e 100644
--- a/source/Plugins/Platform/MacOSX/PlatformiOSSimulator.cpp
+++ b/source/Plugins/Platform/MacOSX/PlatformiOSSimulator.cpp
@@ -60,9 +60,30 @@
 }
 
 Platform* 
-PlatformiOSSimulator::CreateInstance ()
+PlatformiOSSimulator::CreateInstance (bool force, const ArchSpec *arch)
 {
-    return new PlatformiOSSimulator ();
+    bool create = force;
+    if (create == false && arch && arch->IsValid())
+    {
+        switch (arch->GetMachine())
+        {
+        // Currently simulator is i386 only...
+        case llvm::Triple::x86:
+            {
+                const llvm::Triple &triple = arch->GetTriple();
+                const llvm::Triple::OSType os = triple.getOS();
+                const llvm::Triple::VendorType vendor = triple.getVendor();
+                if (os == llvm::Triple::Darwin && vendor == llvm::Triple::Apple)
+                    create = true;
+            }
+            break;
+        default:
+            break;
+        }
+    }
+    if (create)
+        return new PlatformiOSSimulator ();
+    return NULL;
 }
 
 
diff --git a/source/Plugins/Platform/MacOSX/PlatformiOSSimulator.h b/source/Plugins/Platform/MacOSX/PlatformiOSSimulator.h
index d098642..3973c2f 100644
--- a/source/Plugins/Platform/MacOSX/PlatformiOSSimulator.h
+++ b/source/Plugins/Platform/MacOSX/PlatformiOSSimulator.h
@@ -24,7 +24,7 @@
     // Class Functions
     //------------------------------------------------------------
     static lldb_private::Platform* 
-    CreateInstance ();
+    CreateInstance (bool force, const lldb_private::ArchSpec *arch);
 
     static void
     Initialize ();
diff --git a/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.cpp b/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.cpp
index 248475a..4d9cd96 100644
--- a/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.cpp
+++ b/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.cpp
@@ -56,7 +56,7 @@
 }
 
 Platform* 
-PlatformRemoteGDBServer::CreateInstance ()
+PlatformRemoteGDBServer::CreateInstance (bool force, const lldb_private::ArchSpec *arch)
 {
     return new PlatformRemoteGDBServer ();
 }
diff --git a/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.h b/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.h
index 48f3613..ad2ffa5 100644
--- a/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.h
+++ b/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.h
@@ -30,7 +30,7 @@
     Terminate ();
     
     static lldb_private::Platform* 
-    CreateInstance ();
+    CreateInstance (bool force, const lldb_private::ArchSpec *arch);
 
     static const char *
     GetShortPluginNameStatic();
diff --git a/source/Target/Platform.cpp b/source/Target/Platform.cpp
index 403b10e..cc8070d 100644
--- a/source/Target/Platform.cpp
+++ b/source/Target/Platform.cpp
@@ -110,7 +110,6 @@
                                         always_create);
 }
 
-
 PlatformSP
 Platform::Create (const char *platform_name, Error &error)
 {
@@ -120,7 +119,7 @@
     {
         create_callback = PluginManager::GetPlatformCreateCallbackForPluginName (platform_name);
         if (create_callback)
-            platform_sp.reset(create_callback());
+            platform_sp.reset(create_callback(true, NULL));
         else
             error.SetErrorStringWithFormat ("unable to find a plug-in for the platform named \"%s\"", platform_name);
     }
@@ -129,6 +128,27 @@
     return platform_sp;
 }
 
+
+PlatformSP
+Platform::Create (const ArchSpec &arch, Error &error)
+{
+    lldb::PlatformSP platform_sp;
+    if (arch.IsValid())
+    {
+        PlatformCreateInstance create_callback;
+        for (uint32_t idx = 0; (create_callback = PluginManager::GetPlatformCreateCallbackAtIndex (idx)); ++idx)
+        {
+            if (create_callback)
+                platform_sp.reset(create_callback(false, &arch));
+            if (platform_sp && platform_sp->IsCompatibleWithArchitecture(arch))
+                break;
+        }
+    }
+    else
+        error.SetErrorString ("invalid platform name");
+    return platform_sp;
+}
+
 uint32_t
 Platform::GetNumConnectedRemotePlatforms ()
 {
@@ -592,3 +612,38 @@
     }
     return process_sp;
 }
+
+
+lldb::PlatformSP
+Platform::GetPlatformForArchitecture (const ArchSpec &arch)
+{
+    lldb::PlatformSP platform_sp;
+    Error error;
+    if (arch.IsValid())
+        platform_sp = Platform::Create (arch, error);
+    return platform_sp;
+}
+
+
+//------------------------------------------------------------------
+/// Lets a platform answer if it is compatible with a given
+/// architecture and the target triple contained within.
+//------------------------------------------------------------------
+bool
+Platform::IsCompatibleWithArchitecture (const ArchSpec &arch)
+{
+    // If the architecture is invalid, we must answer true...
+    if (!arch.IsValid())
+        return true;
+    
+    ArchSpec platform_arch;
+    for (uint32_t arch_idx=0; GetSupportedArchitectureAtIndex (arch_idx, platform_arch); ++arch_idx)
+    {
+        if (arch == platform_arch)
+            return true;
+    }
+    return false;
+    
+}
+
+
diff --git a/source/Target/TargetList.cpp b/source/Target/TargetList.cpp
index 38240e1..d987913 100644
--- a/source/Target/TargetList.cpp
+++ b/source/Target/TargetList.cpp
@@ -17,6 +17,7 @@
 #include "lldb/Core/State.h"
 #include "lldb/Core/Timer.h"
 #include "lldb/Host/Host.h"
+#include "lldb/Interpreter/CommandInterpreter.h"
 #include "lldb/Interpreter/OptionGroupPlatform.h"
 #include "lldb/Target/Platform.h"
 #include "lldb/Target/Process.h"
@@ -63,22 +64,7 @@
 {
     Error error;
     PlatformSP platform_sp;
-    if (platform_options)
-    {
-        if (platform_options->PlatformWasSpecified ())
-        {
-            const bool select_platform = true;
-            platform_sp = platform_options->CreatePlatformWithOptions (debugger.GetCommandInterpreter(), 
-                                                                       select_platform, 
-                                                                       error);
-            if (!platform_sp)
-                return error;
-        }
-    }
     
-    if (!platform_sp)
-        platform_sp = debugger.GetPlatformList().GetSelectedPlatform ();
-
     // This is purposely left empty unless it is specified by triple_cstr.
     // If not initialized via triple_cstr, then the currently selected platform
     // will set the architecture correctly.
@@ -93,6 +79,34 @@
             return error;
         }
     }
+
+    CommandInterpreter &interpreter = debugger.GetCommandInterpreter();
+    if (platform_options)
+    {
+        if (platform_options->PlatformWasSpecified ())
+        {
+            const bool select_platform = true;
+            platform_sp = platform_options->CreatePlatformWithOptions (interpreter,
+                                                                       arch,
+                                                                       select_platform, 
+                                                                       error);
+            if (!platform_sp)
+                return error;
+        }
+    }
+    
+    if (!platform_sp)
+    {
+        // Get the current platform and make sure it is compatible with the
+        // current architecture if we have a valid architecture.
+        platform_sp = debugger.GetPlatformList().GetSelectedPlatform ();
+        
+        if (arch.IsValid() && !platform_sp->IsCompatibleWithArchitecture(arch))
+        {
+            platform_sp = Platform::GetPlatformForArchitecture(arch);
+        }
+    }
+
     error = TargetList::CreateTarget (debugger,
                                       file,
                                       arch,
@@ -119,7 +133,7 @@
     const FileSpec& file,
     const ArchSpec& arch,
     bool get_dependent_files,
-    const PlatformSP &platform_sp,
+    PlatformSP &platform_sp,
     TargetSP &target_sp
 )
 {
@@ -142,6 +156,13 @@
             error = platform_sp->ResolveExecutable (file, arch, 
                                                     exe_module_sp, 
                                                     executable_search_paths.GetSize() ? &executable_search_paths : NULL);
+            
+            if (exe_module_sp)
+            {
+                const ArchSpec &arch = exe_module_sp->GetArchitecture();
+                if (arch.IsValid() && !platform_sp->IsCompatibleWithArchitecture(arch))
+                    platform_sp = Platform::GetPlatformForArchitecture(arch);
+            }
         }
 
         if (error.Success() && exe_module_sp)
diff --git a/source/lldb.cpp b/source/lldb.cpp
index 3c7b768..fb377b2 100644
--- a/source/lldb.cpp
+++ b/source/lldb.cpp
@@ -126,8 +126,8 @@
         ProcessGDBRemote::Initialize();
         ProcessMachCore::Initialize();
         SymbolVendorMacOSX::Initialize();
-        PlatformMacOSX::Initialize();
         PlatformRemoteiOS::Initialize();
+        PlatformMacOSX::Initialize();
         PlatformiOSSimulator::Initialize();
 #endif
 #if defined (__linux__)