Home | History | Annotate | Download | only in Target
      1 //===-- Platform.cpp --------------------------------------------*- C++ -*-===//
      2 //
      3 //                     The LLVM Compiler Infrastructure
      4 //
      5 // This file is distributed under the University of Illinois Open Source
      6 // License. See LICENSE.TXT for details.
      7 //
      8 //===----------------------------------------------------------------------===//
      9 
     10 #include "lldb/Target/Platform.h"
     11 
     12 // C Includes
     13 // C++ Includes
     14 // Other libraries and framework includes
     15 // Project includes
     16 #include "lldb/Breakpoint/BreakpointIDList.h"
     17 #include "lldb/Core/Error.h"
     18 #include "lldb/Core/Log.h"
     19 #include "lldb/Core/ModuleSpec.h"
     20 #include "lldb/Core/PluginManager.h"
     21 #include "lldb/Host/FileSpec.h"
     22 #include "lldb/Host/Host.h"
     23 #include "lldb/Target/Process.h"
     24 #include "lldb/Target/Target.h"
     25 
     26 using namespace lldb;
     27 using namespace lldb_private;
     28 
     29 // Use a singleton function for g_local_platform_sp to avoid init
     30 // constructors since LLDB is often part of a shared library
     31 static PlatformSP&
     32 GetDefaultPlatformSP ()
     33 {
     34     static PlatformSP g_default_platform_sp;
     35     return g_default_platform_sp;
     36 }
     37 
     38 static Mutex &
     39 GetConnectedPlatformListMutex ()
     40 {
     41     static Mutex g_remote_connected_platforms_mutex (Mutex::eMutexTypeRecursive);
     42     return g_remote_connected_platforms_mutex;
     43 }
     44 static std::vector<PlatformSP> &
     45 GetConnectedPlatformList ()
     46 {
     47     static std::vector<PlatformSP> g_remote_connected_platforms;
     48     return g_remote_connected_platforms;
     49 }
     50 
     51 
     52 const char *
     53 Platform::GetHostPlatformName ()
     54 {
     55     return "host";
     56 }
     57 
     58 //------------------------------------------------------------------
     59 /// Get the native host platform plug-in.
     60 ///
     61 /// There should only be one of these for each host that LLDB runs
     62 /// upon that should be statically compiled in and registered using
     63 /// preprocessor macros or other similar build mechanisms.
     64 ///
     65 /// This platform will be used as the default platform when launching
     66 /// or attaching to processes unless another platform is specified.
     67 //------------------------------------------------------------------
     68 PlatformSP
     69 Platform::GetDefaultPlatform ()
     70 {
     71     return GetDefaultPlatformSP ();
     72 }
     73 
     74 void
     75 Platform::SetDefaultPlatform (const lldb::PlatformSP &platform_sp)
     76 {
     77     // The native platform should use its static void Platform::Initialize()
     78     // function to register itself as the native platform.
     79     GetDefaultPlatformSP () = platform_sp;
     80 }
     81 
     82 Error
     83 Platform::GetFile (const FileSpec &platform_file,
     84                    const UUID *uuid_ptr,
     85                    FileSpec &local_file)
     86 {
     87     // Default to the local case
     88     local_file = platform_file;
     89     return Error();
     90 }
     91 
     92 FileSpecList
     93 Platform::LocateExecutableScriptingResources (Target *target, Module &module)
     94 {
     95     return FileSpecList();
     96 }
     97 
     98 Platform*
     99 Platform::FindPlugin (Process *process, const ConstString &plugin_name)
    100 {
    101     PlatformCreateInstance create_callback = NULL;
    102     if (plugin_name)
    103     {
    104         create_callback  = PluginManager::GetPlatformCreateCallbackForPluginName (plugin_name);
    105         if (create_callback)
    106         {
    107             ArchSpec arch;
    108             if (process)
    109             {
    110                 arch = process->GetTarget().GetArchitecture();
    111             }
    112             std::unique_ptr<Platform> instance_ap(create_callback(process, &arch));
    113             if (instance_ap.get())
    114                 return instance_ap.release();
    115         }
    116     }
    117     else
    118     {
    119         for (uint32_t idx = 0; (create_callback = PluginManager::GetPlatformCreateCallbackAtIndex(idx)) != NULL; ++idx)
    120         {
    121             std::unique_ptr<Platform> instance_ap(create_callback(process, nullptr));
    122             if (instance_ap.get())
    123                 return instance_ap.release();
    124         }
    125     }
    126     return NULL;
    127 }
    128 
    129 Error
    130 Platform::GetSharedModule (const ModuleSpec &module_spec,
    131                            ModuleSP &module_sp,
    132                            const FileSpecList *module_search_paths_ptr,
    133                            ModuleSP *old_module_sp_ptr,
    134                            bool *did_create_ptr)
    135 {
    136     // Don't do any path remapping for the default implementation
    137     // of the platform GetSharedModule function, just call through
    138     // to our static ModuleList function. Platform subclasses that
    139     // implement remote debugging, might have a developer kits
    140     // installed that have cached versions of the files for the
    141     // remote target, or might implement a download and cache
    142     // locally implementation.
    143     const bool always_create = false;
    144     return ModuleList::GetSharedModule (module_spec,
    145                                         module_sp,
    146                                         module_search_paths_ptr,
    147                                         old_module_sp_ptr,
    148                                         did_create_ptr,
    149                                         always_create);
    150 }
    151 
    152 PlatformSP
    153 Platform::Create (const char *platform_name, Error &error)
    154 {
    155     PlatformCreateInstance create_callback = NULL;
    156     lldb::PlatformSP platform_sp;
    157     if (platform_name && platform_name[0])
    158     {
    159         ConstString const_platform_name (platform_name);
    160         create_callback = PluginManager::GetPlatformCreateCallbackForPluginName (const_platform_name);
    161         if (create_callback)
    162             platform_sp.reset(create_callback(true, NULL));
    163         else
    164             error.SetErrorStringWithFormat ("unable to find a plug-in for the platform named \"%s\"", platform_name);
    165     }
    166     else
    167         error.SetErrorString ("invalid platform name");
    168     return platform_sp;
    169 }
    170 
    171 
    172 PlatformSP
    173 Platform::Create (const ArchSpec &arch, ArchSpec *platform_arch_ptr, Error &error)
    174 {
    175     lldb::PlatformSP platform_sp;
    176     if (arch.IsValid())
    177     {
    178         uint32_t idx;
    179         PlatformCreateInstance create_callback;
    180         // First try exact arch matches across all platform plug-ins
    181         bool exact = true;
    182         for (idx = 0; (create_callback = PluginManager::GetPlatformCreateCallbackAtIndex (idx)); ++idx)
    183         {
    184             if (create_callback)
    185             {
    186                 platform_sp.reset(create_callback(false, &arch));
    187                 if (platform_sp && platform_sp->IsCompatibleArchitecture(arch, exact, platform_arch_ptr))
    188                     return platform_sp;
    189             }
    190         }
    191         // Next try compatible arch matches across all platform plug-ins
    192         exact = false;
    193         for (idx = 0; (create_callback = PluginManager::GetPlatformCreateCallbackAtIndex (idx)); ++idx)
    194         {
    195             if (create_callback)
    196             {
    197                 platform_sp.reset(create_callback(false, &arch));
    198                 if (platform_sp && platform_sp->IsCompatibleArchitecture(arch, exact, platform_arch_ptr))
    199                     return platform_sp;
    200             }
    201         }
    202     }
    203     else
    204         error.SetErrorString ("invalid platform name");
    205     if (platform_arch_ptr)
    206         platform_arch_ptr->Clear();
    207     platform_sp.reset();
    208     return platform_sp;
    209 }
    210 
    211 uint32_t
    212 Platform::GetNumConnectedRemotePlatforms ()
    213 {
    214     Mutex::Locker locker (GetConnectedPlatformListMutex ());
    215     return GetConnectedPlatformList().size();
    216 }
    217 
    218 PlatformSP
    219 Platform::GetConnectedRemotePlatformAtIndex (uint32_t idx)
    220 {
    221     PlatformSP platform_sp;
    222     {
    223         Mutex::Locker locker (GetConnectedPlatformListMutex ());
    224         if (idx < GetConnectedPlatformList().size())
    225             platform_sp = GetConnectedPlatformList ()[idx];
    226     }
    227     return platform_sp;
    228 }
    229 
    230 //------------------------------------------------------------------
    231 /// Default Constructor
    232 //------------------------------------------------------------------
    233 Platform::Platform (bool is_host) :
    234     m_is_host (is_host),
    235     m_os_version_set_while_connected (false),
    236     m_system_arch_set_while_connected (false),
    237     m_sdk_sysroot (),
    238     m_sdk_build (),
    239     m_remote_url (),
    240     m_name (),
    241     m_major_os_version (UINT32_MAX),
    242     m_minor_os_version (UINT32_MAX),
    243     m_update_os_version (UINT32_MAX),
    244     m_system_arch(),
    245     m_uid_map_mutex (Mutex::eMutexTypeNormal),
    246     m_gid_map_mutex (Mutex::eMutexTypeNormal),
    247     m_uid_map(),
    248     m_gid_map(),
    249     m_max_uid_name_len (0),
    250     m_max_gid_name_len (0)
    251 {
    252     Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_OBJECT));
    253     if (log)
    254         log->Printf ("%p Platform::Platform()", this);
    255 }
    256 
    257 //------------------------------------------------------------------
    258 /// Destructor.
    259 ///
    260 /// The destructor is virtual since this class is designed to be
    261 /// inherited from by the plug-in instance.
    262 //------------------------------------------------------------------
    263 Platform::~Platform()
    264 {
    265     Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_OBJECT));
    266     if (log)
    267         log->Printf ("%p Platform::~Platform()", this);
    268 }
    269 
    270 void
    271 Platform::GetStatus (Stream &strm)
    272 {
    273     uint32_t major = UINT32_MAX;
    274     uint32_t minor = UINT32_MAX;
    275     uint32_t update = UINT32_MAX;
    276     std::string s;
    277     strm.Printf ("  Platform: %s\n", GetPluginName().GetCString());
    278 
    279     ArchSpec arch (GetSystemArchitecture());
    280     if (arch.IsValid())
    281     {
    282         if (!arch.GetTriple().str().empty())
    283         strm.Printf("    Triple: %s\n", arch.GetTriple().str().c_str());
    284     }
    285 
    286     if (GetOSVersion(major, minor, update))
    287     {
    288         strm.Printf("OS Version: %u", major);
    289         if (minor != UINT32_MAX)
    290             strm.Printf(".%u", minor);
    291         if (update != UINT32_MAX)
    292             strm.Printf(".%u", update);
    293 
    294         if (GetOSBuildString (s))
    295             strm.Printf(" (%s)", s.c_str());
    296 
    297         strm.EOL();
    298     }
    299 
    300     if (GetOSKernelDescription (s))
    301         strm.Printf("    Kernel: %s\n", s.c_str());
    302 
    303     if (IsHost())
    304     {
    305         strm.Printf("  Hostname: %s\n", GetHostname());
    306     }
    307     else
    308     {
    309         const bool is_connected = IsConnected();
    310         if (is_connected)
    311             strm.Printf("  Hostname: %s\n", GetHostname());
    312         strm.Printf(" Connected: %s\n", is_connected ? "yes" : "no");
    313     }
    314 }
    315 
    316 
    317 bool
    318 Platform::GetOSVersion (uint32_t &major,
    319                         uint32_t &minor,
    320                         uint32_t &update)
    321 {
    322     bool success = m_major_os_version != UINT32_MAX;
    323     if (IsHost())
    324     {
    325         if (!success)
    326         {
    327             // We have a local host platform
    328             success = Host::GetOSVersion (m_major_os_version,
    329                                           m_minor_os_version,
    330                                           m_update_os_version);
    331             m_os_version_set_while_connected = success;
    332         }
    333     }
    334     else
    335     {
    336         // We have a remote platform. We can only fetch the remote
    337         // OS version if we are connected, and we don't want to do it
    338         // more than once.
    339 
    340         const bool is_connected = IsConnected();
    341 
    342         bool fetch = false;
    343         if (success)
    344         {
    345             // We have valid OS version info, check to make sure it wasn't
    346             // manually set prior to connecting. If it was manually set prior
    347             // to connecting, then lets fetch the actual OS version info
    348             // if we are now connected.
    349             if (is_connected && !m_os_version_set_while_connected)
    350                 fetch = true;
    351         }
    352         else
    353         {
    354             // We don't have valid OS version info, fetch it if we are connected
    355             fetch = is_connected;
    356         }
    357 
    358         if (fetch)
    359         {
    360             success = GetRemoteOSVersion ();
    361             m_os_version_set_while_connected = success;
    362         }
    363     }
    364 
    365     if (success)
    366     {
    367         major = m_major_os_version;
    368         minor = m_minor_os_version;
    369         update = m_update_os_version;
    370     }
    371     return success;
    372 }
    373 
    374 bool
    375 Platform::GetOSBuildString (std::string &s)
    376 {
    377     if (IsHost())
    378         return Host::GetOSBuildString (s);
    379     else
    380         return GetRemoteOSBuildString (s);
    381 }
    382 
    383 bool
    384 Platform::GetOSKernelDescription (std::string &s)
    385 {
    386     if (IsHost())
    387         return Host::GetOSKernelDescription (s);
    388     else
    389         return GetRemoteOSKernelDescription (s);
    390 }
    391 
    392 ConstString
    393 Platform::GetName ()
    394 {
    395     const char *name = GetHostname();
    396     if (name == NULL || name[0] == '\0')
    397         return GetPluginName();
    398     return ConstString (name);
    399 }
    400 
    401 const char *
    402 Platform::GetHostname ()
    403 {
    404     if (IsHost())
    405         return "localhost";
    406 
    407     if (m_name.empty())
    408         return NULL;
    409     return m_name.c_str();
    410 }
    411 
    412 const char *
    413 Platform::GetUserName (uint32_t uid)
    414 {
    415     const char *user_name = GetCachedUserName(uid);
    416     if (user_name)
    417         return user_name;
    418     if (IsHost())
    419     {
    420         std::string name;
    421         if (Host::GetUserName(uid, name))
    422             return SetCachedUserName (uid, name.c_str(), name.size());
    423     }
    424     return NULL;
    425 }
    426 
    427 const char *
    428 Platform::GetGroupName (uint32_t gid)
    429 {
    430     const char *group_name = GetCachedGroupName(gid);
    431     if (group_name)
    432         return group_name;
    433     if (IsHost())
    434     {
    435         std::string name;
    436         if (Host::GetGroupName(gid, name))
    437             return SetCachedGroupName (gid, name.c_str(), name.size());
    438     }
    439     return NULL;
    440 }
    441 
    442 bool
    443 Platform::SetOSVersion (uint32_t major,
    444                         uint32_t minor,
    445                         uint32_t update)
    446 {
    447     if (IsHost())
    448     {
    449         // We don't need anyone setting the OS version for the host platform,
    450         // we should be able to figure it out by calling Host::GetOSVersion(...).
    451         return false;
    452     }
    453     else
    454     {
    455         // We have a remote platform, allow setting the target OS version if
    456         // we aren't connected, since if we are connected, we should be able to
    457         // request the remote OS version from the connected platform.
    458         if (IsConnected())
    459             return false;
    460         else
    461         {
    462             // We aren't connected and we might want to set the OS version
    463             // ahead of time before we connect so we can peruse files and
    464             // use a local SDK or PDK cache of support files to disassemble
    465             // or do other things.
    466             m_major_os_version = major;
    467             m_minor_os_version = minor;
    468             m_update_os_version = update;
    469             return true;
    470         }
    471     }
    472     return false;
    473 }
    474 
    475 
    476 Error
    477 Platform::ResolveExecutable (const FileSpec &exe_file,
    478                              const ArchSpec &exe_arch,
    479                              lldb::ModuleSP &exe_module_sp,
    480                              const FileSpecList *module_search_paths_ptr)
    481 {
    482     Error error;
    483     if (exe_file.Exists())
    484     {
    485         ModuleSpec module_spec (exe_file, exe_arch);
    486         if (module_spec.GetArchitecture().IsValid())
    487         {
    488             error = ModuleList::GetSharedModule (module_spec,
    489                                                  exe_module_sp,
    490                                                  module_search_paths_ptr,
    491                                                  NULL,
    492                                                  NULL);
    493         }
    494         else
    495         {
    496             // No valid architecture was specified, ask the platform for
    497             // the architectures that we should be using (in the correct order)
    498             // and see if we can find a match that way
    499             for (uint32_t idx = 0; GetSupportedArchitectureAtIndex (idx, module_spec.GetArchitecture()); ++idx)
    500             {
    501                 error = ModuleList::GetSharedModule (module_spec,
    502                                                      exe_module_sp,
    503                                                      module_search_paths_ptr,
    504                                                      NULL,
    505                                                      NULL);
    506                 // Did we find an executable using one of the
    507                 if (error.Success() && exe_module_sp)
    508                     break;
    509             }
    510         }
    511     }
    512     else
    513     {
    514         error.SetErrorStringWithFormat ("'%s' does not exist",
    515                                         exe_file.GetPath().c_str());
    516     }
    517     return error;
    518 }
    519 
    520 Error
    521 Platform::ResolveSymbolFile (Target &target,
    522                              const ModuleSpec &sym_spec,
    523                              FileSpec &sym_file)
    524 {
    525     Error error;
    526     if (sym_spec.GetSymbolFileSpec().Exists())
    527         sym_file = sym_spec.GetSymbolFileSpec();
    528     else
    529         error.SetErrorString("unable to resolve symbol file");
    530     return error;
    531 
    532 }
    533 
    534 
    535 
    536 bool
    537 Platform::ResolveRemotePath (const FileSpec &platform_path,
    538                              FileSpec &resolved_platform_path)
    539 {
    540     resolved_platform_path = platform_path;
    541     return resolved_platform_path.ResolvePath();
    542 }
    543 
    544 
    545 const ArchSpec &
    546 Platform::GetSystemArchitecture()
    547 {
    548     if (IsHost())
    549     {
    550         if (!m_system_arch.IsValid())
    551         {
    552             // We have a local host platform
    553             m_system_arch = Host::GetArchitecture();
    554             m_system_arch_set_while_connected = m_system_arch.IsValid();
    555         }
    556     }
    557     else
    558     {
    559         // We have a remote platform. We can only fetch the remote
    560         // system architecture if we are connected, and we don't want to do it
    561         // more than once.
    562 
    563         const bool is_connected = IsConnected();
    564 
    565         bool fetch = false;
    566         if (m_system_arch.IsValid())
    567         {
    568             // We have valid OS version info, check to make sure it wasn't
    569             // manually set prior to connecting. If it was manually set prior
    570             // to connecting, then lets fetch the actual OS version info
    571             // if we are now connected.
    572             if (is_connected && !m_system_arch_set_while_connected)
    573                 fetch = true;
    574         }
    575         else
    576         {
    577             // We don't have valid OS version info, fetch it if we are connected
    578             fetch = is_connected;
    579         }
    580 
    581         if (fetch)
    582         {
    583             m_system_arch = GetRemoteSystemArchitecture ();
    584             m_system_arch_set_while_connected = m_system_arch.IsValid();
    585         }
    586     }
    587     return m_system_arch;
    588 }
    589 
    590 
    591 Error
    592 Platform::ConnectRemote (Args& args)
    593 {
    594     Error error;
    595     if (IsHost())
    596         error.SetErrorStringWithFormat ("The currently selected platform (%s) is the host platform and is always connected.", GetPluginName().GetCString());
    597     else
    598         error.SetErrorStringWithFormat ("Platform::ConnectRemote() is not supported by %s", GetPluginName().GetCString());
    599     return error;
    600 }
    601 
    602 Error
    603 Platform::DisconnectRemote ()
    604 {
    605     Error error;
    606     if (IsHost())
    607         error.SetErrorStringWithFormat ("The currently selected platform (%s) is the host platform and is always connected.", GetPluginName().GetCString());
    608     else
    609         error.SetErrorStringWithFormat ("Platform::DisconnectRemote() is not supported by %s", GetPluginName().GetCString());
    610     return error;
    611 }
    612 
    613 bool
    614 Platform::GetProcessInfo (lldb::pid_t pid, ProcessInstanceInfo &process_info)
    615 {
    616     // Take care of the host case so that each subclass can just
    617     // call this function to get the host functionality.
    618     if (IsHost())
    619         return Host::GetProcessInfo (pid, process_info);
    620     return false;
    621 }
    622 
    623 uint32_t
    624 Platform::FindProcesses (const ProcessInstanceInfoMatch &match_info,
    625                          ProcessInstanceInfoList &process_infos)
    626 {
    627     // Take care of the host case so that each subclass can just
    628     // call this function to get the host functionality.
    629     uint32_t match_count = 0;
    630     if (IsHost())
    631         match_count = Host::FindProcesses (match_info, process_infos);
    632     return match_count;
    633 }
    634 
    635 
    636 Error
    637 Platform::LaunchProcess (ProcessLaunchInfo &launch_info)
    638 {
    639     Error error;
    640     // Take care of the host case so that each subclass can just
    641     // call this function to get the host functionality.
    642     if (IsHost())
    643     {
    644         if (::getenv ("LLDB_LAUNCH_FLAG_LAUNCH_IN_TTY"))
    645             launch_info.GetFlags().Set (eLaunchFlagLaunchInTTY);
    646 
    647         if (launch_info.GetFlags().Test (eLaunchFlagLaunchInShell))
    648         {
    649             const bool is_localhost = true;
    650             const bool will_debug = launch_info.GetFlags().Test(eLaunchFlagDebug);
    651             const bool first_arg_is_full_shell_command = false;
    652             if (!launch_info.ConvertArgumentsForLaunchingInShell (error,
    653                                                                   is_localhost,
    654                                                                   will_debug,
    655                                                                   first_arg_is_full_shell_command))
    656                 return error;
    657         }
    658 
    659         error = Host::LaunchProcess (launch_info);
    660     }
    661     else
    662         error.SetErrorString ("base lldb_private::Platform class can't launch remote processes");
    663     return error;
    664 }
    665 
    666 lldb::ProcessSP
    667 Platform::DebugProcess (ProcessLaunchInfo &launch_info,
    668                         Debugger &debugger,
    669                         Target *target,       // Can be NULL, if NULL create a new target, else use existing one
    670                         Listener &listener,
    671                         Error &error)
    672 {
    673     ProcessSP process_sp;
    674     // Make sure we stop at the entry point
    675     launch_info.GetFlags ().Set (eLaunchFlagDebug);
    676     // We always launch the process we are going to debug in a separate process
    677     // group, since then we can handle ^C interrupts ourselves w/o having to worry
    678     // about the target getting them as well.
    679     launch_info.SetLaunchInSeparateProcessGroup(true);
    680 
    681     error = LaunchProcess (launch_info);
    682     if (error.Success())
    683     {
    684         if (launch_info.GetProcessID() != LLDB_INVALID_PROCESS_ID)
    685         {
    686             ProcessAttachInfo attach_info (launch_info);
    687             process_sp = Attach (attach_info, debugger, target, listener, error);
    688             if (process_sp)
    689             {
    690                 // Since we attached to the process, it will think it needs to detach
    691                 // if the process object just goes away without an explicit call to
    692                 // Process::Kill() or Process::Detach(), so let it know to kill the
    693                 // process if this happens.
    694                 process_sp->SetShouldDetach (false);
    695 
    696                 // If we didn't have any file actions, the pseudo terminal might
    697                 // have been used where the slave side was given as the file to
    698                 // open for stdin/out/err after we have already opened the master
    699                 // so we can read/write stdin/out/err.
    700                 int pty_fd = launch_info.GetPTY().ReleaseMasterFileDescriptor();
    701                 if (pty_fd != lldb_utility::PseudoTerminal::invalid_fd)
    702                 {
    703                     process_sp->SetSTDIOFileDescriptor(pty_fd);
    704                 }
    705             }
    706         }
    707     }
    708     return process_sp;
    709 }
    710 
    711 
    712 lldb::PlatformSP
    713 Platform::GetPlatformForArchitecture (const ArchSpec &arch, ArchSpec *platform_arch_ptr)
    714 {
    715     lldb::PlatformSP platform_sp;
    716     Error error;
    717     if (arch.IsValid())
    718         platform_sp = Platform::Create (arch, platform_arch_ptr, error);
    719     return platform_sp;
    720 }
    721 
    722 
    723 //------------------------------------------------------------------
    724 /// Lets a platform answer if it is compatible with a given
    725 /// architecture and the target triple contained within.
    726 //------------------------------------------------------------------
    727 bool
    728 Platform::IsCompatibleArchitecture (const ArchSpec &arch, bool exact_arch_match, ArchSpec *compatible_arch_ptr)
    729 {
    730     // If the architecture is invalid, we must answer true...
    731     if (arch.IsValid())
    732     {
    733         ArchSpec platform_arch;
    734         // Try for an exact architecture match first.
    735         if (exact_arch_match)
    736         {
    737             for (uint32_t arch_idx=0; GetSupportedArchitectureAtIndex (arch_idx, platform_arch); ++arch_idx)
    738             {
    739                 if (arch.IsExactMatch(platform_arch))
    740                 {
    741                     if (compatible_arch_ptr)
    742                         *compatible_arch_ptr = platform_arch;
    743                     return true;
    744                 }
    745             }
    746         }
    747         else
    748         {
    749             for (uint32_t arch_idx=0; GetSupportedArchitectureAtIndex (arch_idx, platform_arch); ++arch_idx)
    750             {
    751                 if (arch.IsCompatibleMatch(platform_arch))
    752                 {
    753                     if (compatible_arch_ptr)
    754                         *compatible_arch_ptr = platform_arch;
    755                     return true;
    756                 }
    757             }
    758         }
    759     }
    760     if (compatible_arch_ptr)
    761         compatible_arch_ptr->Clear();
    762     return false;
    763 
    764 }
    765 
    766 
    767 lldb::BreakpointSP
    768 Platform::SetThreadCreationBreakpoint (lldb_private::Target &target)
    769 {
    770     return lldb::BreakpointSP();
    771 }
    772 
    773 size_t
    774 Platform::GetEnvironment (StringList &environment)
    775 {
    776     environment.Clear();
    777     return false;
    778 }
    779 
    780