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