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&
GetDefaultPlatformSP()32 GetDefaultPlatformSP ()
33 {
34     static PlatformSP g_default_platform_sp;
35     return g_default_platform_sp;
36 }
37 
38 static Mutex &
GetConnectedPlatformListMutex()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> &
GetConnectedPlatformList()45 GetConnectedPlatformList ()
46 {
47     static std::vector<PlatformSP> g_remote_connected_platforms;
48     return g_remote_connected_platforms;
49 }
50 
51 
52 const char *
GetHostPlatformName()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
GetDefaultPlatform()69 Platform::GetDefaultPlatform ()
70 {
71     return GetDefaultPlatformSP ();
72 }
73 
74 void
SetDefaultPlatform(const lldb::PlatformSP & platform_sp)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
GetFile(const FileSpec & platform_file,const UUID * uuid_ptr,FileSpec & local_file)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
LocateExecutableScriptingResources(Target * target,Module & module)93 Platform::LocateExecutableScriptingResources (Target *target, Module &module)
94 {
95     return FileSpecList();
96 }
97 
98 Platform*
FindPlugin(Process * process,const ConstString & plugin_name)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
GetSharedModule(const ModuleSpec & module_spec,ModuleSP & module_sp,const FileSpecList * module_search_paths_ptr,ModuleSP * old_module_sp_ptr,bool * did_create_ptr)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
Create(const char * platform_name,Error & error)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
Create(const ArchSpec & arch,ArchSpec * platform_arch_ptr,Error & error)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
GetNumConnectedRemotePlatforms()212 Platform::GetNumConnectedRemotePlatforms ()
213 {
214     Mutex::Locker locker (GetConnectedPlatformListMutex ());
215     return GetConnectedPlatformList().size();
216 }
217 
218 PlatformSP
GetConnectedRemotePlatformAtIndex(uint32_t idx)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 //------------------------------------------------------------------
Platform(bool is_host)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 //------------------------------------------------------------------
~Platform()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
GetStatus(Stream & strm)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
GetOSVersion(uint32_t & major,uint32_t & minor,uint32_t & update)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
GetOSBuildString(std::string & s)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
GetOSKernelDescription(std::string & s)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
GetName()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 *
GetHostname()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 *
GetUserName(uint32_t uid)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 *
GetGroupName(uint32_t gid)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
SetOSVersion(uint32_t major,uint32_t minor,uint32_t update)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
ResolveExecutable(const FileSpec & exe_file,const ArchSpec & exe_arch,lldb::ModuleSP & exe_module_sp,const FileSpecList * module_search_paths_ptr)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
ResolveSymbolFile(Target & target,const ModuleSpec & sym_spec,FileSpec & sym_file)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
ResolveRemotePath(const FileSpec & platform_path,FileSpec & resolved_platform_path)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 &
GetSystemArchitecture()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
ConnectRemote(Args & args)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
DisconnectRemote()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
GetProcessInfo(lldb::pid_t pid,ProcessInstanceInfo & process_info)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
FindProcesses(const ProcessInstanceInfoMatch & match_info,ProcessInstanceInfoList & process_infos)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
LaunchProcess(ProcessLaunchInfo & launch_info)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
DebugProcess(ProcessLaunchInfo & launch_info,Debugger & debugger,Target * target,Listener & listener,Error & error)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
GetPlatformForArchitecture(const ArchSpec & arch,ArchSpec * platform_arch_ptr)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
IsCompatibleArchitecture(const ArchSpec & arch,bool exact_arch_match,ArchSpec * compatible_arch_ptr)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
SetThreadCreationBreakpoint(lldb_private::Target & target)768 Platform::SetThreadCreationBreakpoint (lldb_private::Target &target)
769 {
770     return lldb::BreakpointSP();
771 }
772 
773 size_t
GetEnvironment(StringList & environment)774 Platform::GetEnvironment (StringList &environment)
775 {
776     environment.Clear();
777     return false;
778 }
779 
780