]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm/tools/lldb/source/Target/Platform.cpp
Upgrade to Unbound 1.5.1. Almost all our local changes to date have been
[FreeBSD/FreeBSD.git] / contrib / llvm / tools / lldb / source / Target / Platform.cpp
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/FileSystem.h"
23 #include "lldb/Host/Host.h"
24 #include "lldb/Host/HostInfo.h"
25 #include "lldb/Target/Process.h"
26 #include "lldb/Target/Target.h"
27 #include "lldb/Utility/Utils.h"
28
29 using namespace lldb;
30 using namespace lldb_private;
31     
32 // Use a singleton function for g_local_platform_sp to avoid init
33 // constructors since LLDB is often part of a shared library
34 static PlatformSP&
35 GetDefaultPlatformSP ()
36 {
37     static PlatformSP g_default_platform_sp;
38     return g_default_platform_sp;
39 }
40
41 static Mutex &
42 GetConnectedPlatformListMutex ()
43 {
44     static Mutex g_remote_connected_platforms_mutex (Mutex::eMutexTypeRecursive);
45     return g_remote_connected_platforms_mutex;
46 }
47 static std::vector<PlatformSP> &
48 GetConnectedPlatformList ()
49 {
50     static std::vector<PlatformSP> g_remote_connected_platforms;
51     return g_remote_connected_platforms;
52 }
53
54
55 const char *
56 Platform::GetHostPlatformName ()
57 {
58     return "host";
59 }
60
61 //------------------------------------------------------------------
62 /// Get the native host platform plug-in. 
63 ///
64 /// There should only be one of these for each host that LLDB runs
65 /// upon that should be statically compiled in and registered using
66 /// preprocessor macros or other similar build mechanisms.
67 ///
68 /// This platform will be used as the default platform when launching
69 /// or attaching to processes unless another platform is specified.
70 //------------------------------------------------------------------
71 PlatformSP
72 Platform::GetDefaultPlatform ()
73 {
74     return GetDefaultPlatformSP ();
75 }
76
77 void
78 Platform::SetDefaultPlatform (const lldb::PlatformSP &platform_sp)
79 {
80     // The native platform should use its static void Platform::Initialize()
81     // function to register itself as the native platform.
82     GetDefaultPlatformSP () = platform_sp;
83 }
84
85 Error
86 Platform::GetFileWithUUID (const FileSpec &platform_file, 
87                            const UUID *uuid_ptr,
88                            FileSpec &local_file)
89 {
90     // Default to the local case
91     local_file = platform_file;
92     return Error();
93 }
94
95 FileSpecList
96 Platform::LocateExecutableScriptingResources (Target *target, Module &module, Stream* feedback_stream)
97 {
98     return FileSpecList();
99 }
100
101 Platform*
102 Platform::FindPlugin (Process *process, const ConstString &plugin_name)
103 {
104     PlatformCreateInstance create_callback = NULL;
105     if (plugin_name)
106     {
107         create_callback  = PluginManager::GetPlatformCreateCallbackForPluginName (plugin_name);
108         if (create_callback)
109         {
110             ArchSpec arch;
111             if (process)
112             {
113                 arch = process->GetTarget().GetArchitecture();
114             }
115             std::unique_ptr<Platform> instance_ap(create_callback(process, &arch));
116             if (instance_ap.get())
117                 return instance_ap.release();
118         }
119     }
120     else
121     {
122         for (uint32_t idx = 0; (create_callback = PluginManager::GetPlatformCreateCallbackAtIndex(idx)) != NULL; ++idx)
123         {
124             std::unique_ptr<Platform> instance_ap(create_callback(process, nullptr));
125             if (instance_ap.get())
126                 return instance_ap.release();
127         }
128     }
129     return NULL;
130 }
131
132 Error
133 Platform::GetSharedModule (const ModuleSpec &module_spec,
134                            ModuleSP &module_sp,
135                            const FileSpecList *module_search_paths_ptr,
136                            ModuleSP *old_module_sp_ptr,
137                            bool *did_create_ptr)
138 {
139     // Don't do any path remapping for the default implementation
140     // of the platform GetSharedModule function, just call through
141     // to our static ModuleList function. Platform subclasses that
142     // implement remote debugging, might have a developer kits
143     // installed that have cached versions of the files for the
144     // remote target, or might implement a download and cache 
145     // locally implementation.
146     const bool always_create = false;
147     return ModuleList::GetSharedModule (module_spec, 
148                                         module_sp,
149                                         module_search_paths_ptr,
150                                         old_module_sp_ptr,
151                                         did_create_ptr,
152                                         always_create);
153 }
154
155 PlatformSP
156 Platform::Create (const char *platform_name, Error &error)
157 {
158     PlatformCreateInstance create_callback = NULL;
159     lldb::PlatformSP platform_sp;
160     if (platform_name && platform_name[0])
161     {
162         ConstString const_platform_name (platform_name);
163         create_callback = PluginManager::GetPlatformCreateCallbackForPluginName (const_platform_name);
164         if (create_callback)
165             platform_sp.reset(create_callback(true, NULL));
166         else
167             error.SetErrorStringWithFormat ("unable to find a plug-in for the platform named \"%s\"", platform_name);
168     }
169     else
170         error.SetErrorString ("invalid platform name");
171     return platform_sp;
172 }
173
174
175 PlatformSP
176 Platform::Create (const ArchSpec &arch, ArchSpec *platform_arch_ptr, Error &error)
177 {
178     lldb::PlatformSP platform_sp;
179     if (arch.IsValid())
180     {
181         uint32_t idx;
182         PlatformCreateInstance create_callback;
183         // First try exact arch matches across all platform plug-ins
184         bool exact = true;
185         for (idx = 0; (create_callback = PluginManager::GetPlatformCreateCallbackAtIndex (idx)); ++idx)
186         {
187             if (create_callback)
188             {
189                 platform_sp.reset(create_callback(false, &arch));
190                 if (platform_sp && platform_sp->IsCompatibleArchitecture(arch, exact, platform_arch_ptr))
191                     return platform_sp;
192             }
193         }
194         // Next try compatible arch matches across all platform plug-ins
195         exact = false;
196         for (idx = 0; (create_callback = PluginManager::GetPlatformCreateCallbackAtIndex (idx)); ++idx)
197         {
198             if (create_callback)
199             {
200                 platform_sp.reset(create_callback(false, &arch));
201                 if (platform_sp && platform_sp->IsCompatibleArchitecture(arch, exact, platform_arch_ptr))
202                     return platform_sp;
203             }
204         }
205     }
206     else
207         error.SetErrorString ("invalid platform name");
208     if (platform_arch_ptr)
209         platform_arch_ptr->Clear();
210     platform_sp.reset();
211     return platform_sp;
212 }
213
214 uint32_t
215 Platform::GetNumConnectedRemotePlatforms ()
216 {
217     Mutex::Locker locker (GetConnectedPlatformListMutex ());
218     return GetConnectedPlatformList().size();
219 }
220
221 PlatformSP
222 Platform::GetConnectedRemotePlatformAtIndex (uint32_t idx)
223 {
224     PlatformSP platform_sp;
225     {
226         Mutex::Locker locker (GetConnectedPlatformListMutex ());
227         if (idx < GetConnectedPlatformList().size())
228             platform_sp = GetConnectedPlatformList ()[idx];
229     }
230     return platform_sp;
231 }
232
233 //------------------------------------------------------------------
234 /// Default Constructor
235 //------------------------------------------------------------------
236 Platform::Platform (bool is_host) :
237     m_is_host (is_host),
238     m_os_version_set_while_connected (false),
239     m_system_arch_set_while_connected (false),
240     m_sdk_sysroot (),
241     m_sdk_build (),
242     m_working_dir (),
243     m_remote_url (),
244     m_name (),
245     m_major_os_version (UINT32_MAX),
246     m_minor_os_version (UINT32_MAX),
247     m_update_os_version (UINT32_MAX),
248     m_system_arch(),
249     m_uid_map_mutex (Mutex::eMutexTypeNormal),
250     m_gid_map_mutex (Mutex::eMutexTypeNormal),
251     m_uid_map(),
252     m_gid_map(),
253     m_max_uid_name_len (0),
254     m_max_gid_name_len (0),
255     m_supports_rsync (false),
256     m_rsync_opts (),
257     m_rsync_prefix (),
258     m_supports_ssh (false),
259     m_ssh_opts (),
260     m_ignores_remote_hostname (false),
261     m_trap_handlers(),
262     m_calculated_trap_handlers (false),
263     m_trap_handler_mutex()
264 {
265     Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_OBJECT));
266     if (log)
267         log->Printf ("%p Platform::Platform()", static_cast<void*>(this));
268 }
269
270 //------------------------------------------------------------------
271 /// Destructor.
272 ///
273 /// The destructor is virtual since this class is designed to be
274 /// inherited from by the plug-in instance.
275 //------------------------------------------------------------------
276 Platform::~Platform()
277 {
278     Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_OBJECT));
279     if (log)
280         log->Printf ("%p Platform::~Platform()", static_cast<void*>(this));
281 }
282
283 void
284 Platform::GetStatus (Stream &strm)
285 {
286     uint32_t major = UINT32_MAX;
287     uint32_t minor = UINT32_MAX;
288     uint32_t update = UINT32_MAX;
289     std::string s;
290     strm.Printf ("  Platform: %s\n", GetPluginName().GetCString());
291
292     ArchSpec arch (GetSystemArchitecture());
293     if (arch.IsValid())
294     {
295         if (!arch.GetTriple().str().empty())
296         strm.Printf("    Triple: %s\n", arch.GetTriple().str().c_str());        
297     }
298
299     if (GetOSVersion(major, minor, update))
300     {
301         strm.Printf("OS Version: %u", major);
302         if (minor != UINT32_MAX)
303             strm.Printf(".%u", minor);
304         if (update != UINT32_MAX)
305             strm.Printf(".%u", update);
306
307         if (GetOSBuildString (s))
308             strm.Printf(" (%s)", s.c_str());
309
310         strm.EOL();
311     }
312
313     if (GetOSKernelDescription (s))
314         strm.Printf("    Kernel: %s\n", s.c_str());
315
316     if (IsHost())
317     {
318         strm.Printf("  Hostname: %s\n", GetHostname());
319     }
320     else
321     {
322         const bool is_connected = IsConnected();
323         if (is_connected)
324             strm.Printf("  Hostname: %s\n", GetHostname());
325         strm.Printf(" Connected: %s\n", is_connected ? "yes" : "no");
326     }
327
328     if (GetWorkingDirectory())
329     {
330         strm.Printf("WorkingDir: %s\n", GetWorkingDirectory().GetCString());
331     }
332     if (!IsConnected())
333         return;
334
335     std::string specific_info(GetPlatformSpecificConnectionInformation());
336     
337     if (specific_info.empty() == false)
338         strm.Printf("Platform-specific connection: %s\n", specific_info.c_str());
339 }
340
341
342 bool
343 Platform::GetOSVersion (uint32_t &major, 
344                         uint32_t &minor, 
345                         uint32_t &update)
346 {
347     bool success = m_major_os_version != UINT32_MAX;
348     if (IsHost())
349     {
350         if (!success)
351         {
352             // We have a local host platform
353             success = HostInfo::GetOSVersion(m_major_os_version, m_minor_os_version, m_update_os_version);
354             m_os_version_set_while_connected = success;
355         }
356     }
357     else 
358     {
359         // We have a remote platform. We can only fetch the remote
360         // OS version if we are connected, and we don't want to do it
361         // more than once.
362         
363         const bool is_connected = IsConnected();
364
365         bool fetch = false;
366         if (success)
367         {
368             // We have valid OS version info, check to make sure it wasn't
369             // manually set prior to connecting. If it was manually set prior
370             // to connecting, then lets fetch the actual OS version info
371             // if we are now connected.
372             if (is_connected && !m_os_version_set_while_connected)
373                 fetch = true;
374         }
375         else
376         {
377             // We don't have valid OS version info, fetch it if we are connected
378             fetch = is_connected;
379         }
380
381         if (fetch)
382         {
383             success = GetRemoteOSVersion ();
384             m_os_version_set_while_connected = success;
385         }
386     }
387
388     if (success)
389     {
390         major = m_major_os_version;
391         minor = m_minor_os_version;
392         update = m_update_os_version;
393     }
394     return success;
395 }
396
397 bool
398 Platform::GetOSBuildString (std::string &s)
399 {
400     s.clear();
401
402     if (IsHost())
403 #if !defined(__linux__)
404         return HostInfo::GetOSBuildString(s);
405 #else
406         return false;
407 #endif
408     else
409         return GetRemoteOSBuildString (s);
410 }
411
412 bool
413 Platform::GetOSKernelDescription (std::string &s)
414 {
415     if (IsHost())
416 #if !defined(__linux__)
417         return HostInfo::GetOSKernelDescription(s);
418 #else
419         return false;
420 #endif
421     else
422         return GetRemoteOSKernelDescription (s);
423 }
424
425 ConstString
426 Platform::GetWorkingDirectory ()
427 {
428     if (IsHost())
429     {
430         char cwd[PATH_MAX];
431         if (getcwd(cwd, sizeof(cwd)))
432             return ConstString(cwd);
433         else
434             return ConstString();
435     }
436     else
437     {
438         if (!m_working_dir)
439             m_working_dir = GetRemoteWorkingDirectory();
440         return m_working_dir;
441     }
442 }
443
444
445 struct RecurseCopyBaton
446 {
447     const FileSpec& dst;
448     Platform *platform_ptr;
449     Error error;
450 };
451
452
453 static FileSpec::EnumerateDirectoryResult
454 RecurseCopy_Callback (void *baton,
455                       FileSpec::FileType file_type,
456                       const FileSpec &src)
457 {
458     RecurseCopyBaton* rc_baton = (RecurseCopyBaton*)baton;
459     switch (file_type)
460     {
461         case FileSpec::eFileTypePipe:
462         case FileSpec::eFileTypeSocket:
463             // we have no way to copy pipes and sockets - ignore them and continue
464             return FileSpec::eEnumerateDirectoryResultNext;
465             break;
466             
467         case FileSpec::eFileTypeDirectory:
468             {
469                 // make the new directory and get in there
470                 FileSpec dst_dir = rc_baton->dst;
471                 if (!dst_dir.GetFilename())
472                     dst_dir.GetFilename() = src.GetLastPathComponent();
473                 std::string dst_dir_path (dst_dir.GetPath());
474                 Error error = rc_baton->platform_ptr->MakeDirectory(dst_dir_path.c_str(), lldb::eFilePermissionsDirectoryDefault);
475                 if (error.Fail())
476                 {
477                     rc_baton->error.SetErrorStringWithFormat("unable to setup directory %s on remote end", dst_dir_path.c_str());
478                     return FileSpec::eEnumerateDirectoryResultQuit; // got an error, bail out
479                 }
480                 
481                 // now recurse
482                 std::string src_dir_path (src.GetPath());
483                 
484                 // Make a filespec that only fills in the directory of a FileSpec so
485                 // when we enumerate we can quickly fill in the filename for dst copies
486                 FileSpec recurse_dst;
487                 recurse_dst.GetDirectory().SetCString(dst_dir.GetPath().c_str());
488                 RecurseCopyBaton rc_baton2 = { recurse_dst, rc_baton->platform_ptr, Error() };
489                 FileSpec::EnumerateDirectory(src_dir_path.c_str(), true, true, true, RecurseCopy_Callback, &rc_baton2);
490                 if (rc_baton2.error.Fail())
491                 {
492                     rc_baton->error.SetErrorString(rc_baton2.error.AsCString());
493                     return FileSpec::eEnumerateDirectoryResultQuit; // got an error, bail out
494                 }
495                 return FileSpec::eEnumerateDirectoryResultNext;
496             }
497             break;
498             
499         case FileSpec::eFileTypeSymbolicLink:
500             {
501                 // copy the file and keep going
502                 FileSpec dst_file = rc_baton->dst;
503                 if (!dst_file.GetFilename())
504                     dst_file.GetFilename() = src.GetFilename();
505                 
506                 char buf[PATH_MAX];
507
508                 rc_baton->error = FileSystem::Readlink(src.GetPath().c_str(), buf, sizeof(buf));
509
510                 if (rc_baton->error.Fail())
511                     return FileSpec::eEnumerateDirectoryResultQuit; // got an error, bail out
512                 
513                 rc_baton->error = rc_baton->platform_ptr->CreateSymlink(dst_file.GetPath().c_str(), buf);
514
515                 if (rc_baton->error.Fail())
516                     return FileSpec::eEnumerateDirectoryResultQuit; // got an error, bail out
517
518                 return FileSpec::eEnumerateDirectoryResultNext;
519             }
520             break;
521         case FileSpec::eFileTypeRegular:
522             {
523                 // copy the file and keep going
524                 FileSpec dst_file = rc_baton->dst;
525                 if (!dst_file.GetFilename())
526                     dst_file.GetFilename() = src.GetFilename();
527                 Error err = rc_baton->platform_ptr->PutFile(src, dst_file);
528                 if (err.Fail())
529                 {
530                     rc_baton->error.SetErrorString(err.AsCString());
531                     return FileSpec::eEnumerateDirectoryResultQuit; // got an error, bail out
532                 }
533                 return FileSpec::eEnumerateDirectoryResultNext;
534             }
535             break;
536             
537         case FileSpec::eFileTypeInvalid:
538         case FileSpec::eFileTypeOther:
539         case FileSpec::eFileTypeUnknown:
540         default:
541             rc_baton->error.SetErrorStringWithFormat("invalid file detected during copy: %s", src.GetPath().c_str());
542             return FileSpec::eEnumerateDirectoryResultQuit; // got an error, bail out
543             break;
544     }
545 }
546
547 Error
548 Platform::Install (const FileSpec& src, const FileSpec& dst)
549 {
550     Error error;
551     
552     Log *log = GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PLATFORM);
553     if (log)
554         log->Printf ("Platform::Install (src='%s', dst='%s')", src.GetPath().c_str(), dst.GetPath().c_str());
555     FileSpec fixed_dst(dst);
556     
557     if (!fixed_dst.GetFilename())
558         fixed_dst.GetFilename() = src.GetFilename();
559
560     ConstString working_dir = GetWorkingDirectory();
561
562     if (dst)
563     {
564         if (dst.GetDirectory())
565         {
566             const char first_dst_dir_char = dst.GetDirectory().GetCString()[0];
567             if (first_dst_dir_char == '/' || first_dst_dir_char  == '\\')
568             {
569                 fixed_dst.GetDirectory() = dst.GetDirectory();
570             }
571             // If the fixed destination file doesn't have a directory yet,
572             // then we must have a relative path. We will resolve this relative
573             // path against the platform's working directory
574             if (!fixed_dst.GetDirectory())
575             {
576                 FileSpec relative_spec;
577                 std::string path;
578                 if (working_dir)
579                 {
580                     relative_spec.SetFile(working_dir.GetCString(), false);
581                     relative_spec.AppendPathComponent(dst.GetPath().c_str());
582                     fixed_dst.GetDirectory() = relative_spec.GetDirectory();
583                 }
584                 else
585                 {
586                     error.SetErrorStringWithFormat("platform working directory must be valid for relative path '%s'", dst.GetPath().c_str());
587                     return error;
588                 }
589             }
590         }
591         else
592         {
593             if (working_dir)
594             {
595                 fixed_dst.GetDirectory() = working_dir;
596             }
597             else
598             {
599                 error.SetErrorStringWithFormat("platform working directory must be valid for relative path '%s'", dst.GetPath().c_str());
600                 return error;
601             }
602         }
603     }
604     else
605     {
606         if (working_dir)
607         {
608             fixed_dst.GetDirectory() = working_dir;
609         }
610         else
611         {
612             error.SetErrorStringWithFormat("platform working directory must be valid when destination directory is empty");
613             return error;
614         }
615     }
616     
617     if (log)
618         log->Printf ("Platform::Install (src='%s', dst='%s') fixed_dst='%s'", src.GetPath().c_str(), dst.GetPath().c_str(), fixed_dst.GetPath().c_str());
619
620     if (GetSupportsRSync())
621     {
622         error = PutFile(src, dst);
623     }
624     else
625     {
626         switch (src.GetFileType())
627         {
628             case FileSpec::eFileTypeDirectory:
629                 {
630                     if (GetFileExists (fixed_dst))
631                         Unlink (fixed_dst.GetPath().c_str());
632                     uint32_t permissions = src.GetPermissions();
633                     if (permissions == 0)
634                         permissions = eFilePermissionsDirectoryDefault;
635                     std::string dst_dir_path(fixed_dst.GetPath());
636                     error = MakeDirectory(dst_dir_path.c_str(), permissions);
637                     if (error.Success())
638                     {
639                         // Make a filespec that only fills in the directory of a FileSpec so
640                         // when we enumerate we can quickly fill in the filename for dst copies
641                         FileSpec recurse_dst;
642                         recurse_dst.GetDirectory().SetCString(dst_dir_path.c_str());
643                         std::string src_dir_path (src.GetPath());
644                         RecurseCopyBaton baton = { recurse_dst, this, Error() };
645                         FileSpec::EnumerateDirectory(src_dir_path.c_str(), true, true, true, RecurseCopy_Callback, &baton);
646                         return baton.error;
647                     }
648                 }
649                 break;
650
651             case FileSpec::eFileTypeRegular:
652                 if (GetFileExists (fixed_dst))
653                     Unlink (fixed_dst.GetPath().c_str());
654                 error = PutFile(src, fixed_dst);
655                 break;
656
657             case FileSpec::eFileTypeSymbolicLink:
658                 {
659                     if (GetFileExists (fixed_dst))
660                         Unlink (fixed_dst.GetPath().c_str());
661                     char buf[PATH_MAX];
662                     error = FileSystem::Readlink(src.GetPath().c_str(), buf, sizeof(buf));
663                     if (error.Success())
664                         error = CreateSymlink(dst.GetPath().c_str(), buf);
665                 }
666                 break;
667             case FileSpec::eFileTypePipe:
668                 error.SetErrorString("platform install doesn't handle pipes");
669                 break;
670             case FileSpec::eFileTypeSocket:
671                 error.SetErrorString("platform install doesn't handle sockets");
672                 break;
673             case FileSpec::eFileTypeInvalid:
674             case FileSpec::eFileTypeUnknown:
675             case FileSpec::eFileTypeOther:
676                 error.SetErrorString("platform install doesn't handle non file or directory items");
677                 break;
678         }
679     }
680     return error;
681 }
682
683 bool
684 Platform::SetWorkingDirectory (const ConstString &path)
685 {
686     if (IsHost())
687     {
688         Log *log = GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PLATFORM);
689         if (log)
690             log->Printf("Platform::SetWorkingDirectory('%s')", path.GetCString());
691 #ifdef _WIN32
692         // Not implemented on Windows
693         return false;
694 #else
695         if (path)
696         {
697             if (chdir(path.GetCString()) == 0)
698                 return true;
699         }
700         return false;
701 #endif
702     }
703     else
704     {
705         m_working_dir.Clear();
706         return SetRemoteWorkingDirectory(path);
707     }
708 }
709
710 Error
711 Platform::MakeDirectory (const char *path, uint32_t permissions)
712 {
713     if (IsHost())
714         return FileSystem::MakeDirectory(path, permissions);
715     else
716     {
717         Error error;
718         error.SetErrorStringWithFormat("remote platform %s doesn't support %s", GetPluginName().GetCString(), __PRETTY_FUNCTION__);
719         return error;
720     }
721 }
722
723 Error
724 Platform::GetFilePermissions (const char *path, uint32_t &file_permissions)
725 {
726     if (IsHost())
727         return FileSystem::GetFilePermissions(path, file_permissions);
728     else
729     {
730         Error error;
731         error.SetErrorStringWithFormat("remote platform %s doesn't support %s", GetPluginName().GetCString(), __PRETTY_FUNCTION__);
732         return error;
733     }
734 }
735
736 Error
737 Platform::SetFilePermissions (const char *path, uint32_t file_permissions)
738 {
739     if (IsHost())
740         return FileSystem::SetFilePermissions(path, file_permissions);
741     else
742     {
743         Error error;
744         error.SetErrorStringWithFormat("remote platform %s doesn't support %s", GetPluginName().GetCString(), __PRETTY_FUNCTION__);
745         return error;
746     }
747 }
748
749 ConstString
750 Platform::GetName ()
751 {
752     return GetPluginName();
753 }
754
755 const char *
756 Platform::GetHostname ()
757 {
758     if (IsHost())
759         return "127.0.0.1";
760
761     if (m_name.empty())        
762         return NULL;
763     return m_name.c_str();
764 }
765
766 bool
767 Platform::SetRemoteWorkingDirectory(const ConstString &path)
768 {
769     Log *log = GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PLATFORM);
770     if (log)
771         log->Printf("Platform::SetRemoteWorkingDirectory('%s')", path.GetCString());
772     m_working_dir = path;
773     return true;
774 }
775
776 const char *
777 Platform::GetUserName (uint32_t uid)
778 {
779 #if !defined(LLDB_DISABLE_POSIX)
780     const char *user_name = GetCachedUserName(uid);
781     if (user_name)
782         return user_name;
783     if (IsHost())
784     {
785         std::string name;
786         if (HostInfo::LookupUserName(uid, name))
787             return SetCachedUserName (uid, name.c_str(), name.size());
788     }
789 #endif
790     return NULL;
791 }
792
793 const char *
794 Platform::GetGroupName (uint32_t gid)
795 {
796 #if !defined(LLDB_DISABLE_POSIX)
797     const char *group_name = GetCachedGroupName(gid);
798     if (group_name)
799         return group_name;
800     if (IsHost())
801     {
802         std::string name;
803         if (HostInfo::LookupGroupName(gid, name))
804             return SetCachedGroupName (gid, name.c_str(), name.size());
805     }
806 #endif
807     return NULL;
808 }
809
810 bool
811 Platform::SetOSVersion (uint32_t major, 
812                         uint32_t minor, 
813                         uint32_t update)
814 {
815     if (IsHost())
816     {
817         // We don't need anyone setting the OS version for the host platform,
818         // we should be able to figure it out by calling HostInfo::GetOSVersion(...).
819         return false; 
820     }
821     else
822     {
823         // We have a remote platform, allow setting the target OS version if
824         // we aren't connected, since if we are connected, we should be able to
825         // request the remote OS version from the connected platform.
826         if (IsConnected())
827             return false;
828         else
829         {
830             // We aren't connected and we might want to set the OS version
831             // ahead of time before we connect so we can peruse files and
832             // use a local SDK or PDK cache of support files to disassemble
833             // or do other things.
834             m_major_os_version = major;
835             m_minor_os_version = minor;
836             m_update_os_version = update;
837             return true;
838         }
839     }
840     return false;
841 }
842
843
844 Error
845 Platform::ResolveExecutable (const FileSpec &exe_file,
846                              const ArchSpec &exe_arch,
847                              lldb::ModuleSP &exe_module_sp,
848                              const FileSpecList *module_search_paths_ptr)
849 {
850     Error error;
851     if (exe_file.Exists())
852     {
853         ModuleSpec module_spec (exe_file, exe_arch);
854         if (module_spec.GetArchitecture().IsValid())
855         {
856             error = ModuleList::GetSharedModule (module_spec, 
857                                                  exe_module_sp, 
858                                                  module_search_paths_ptr,
859                                                  NULL, 
860                                                  NULL);
861         }
862         else
863         {
864             // No valid architecture was specified, ask the platform for
865             // the architectures that we should be using (in the correct order)
866             // and see if we can find a match that way
867             for (uint32_t idx = 0; GetSupportedArchitectureAtIndex (idx, module_spec.GetArchitecture()); ++idx)
868             {
869                 error = ModuleList::GetSharedModule (module_spec, 
870                                                      exe_module_sp, 
871                                                      module_search_paths_ptr,
872                                                      NULL, 
873                                                      NULL);
874                 // Did we find an executable using one of the 
875                 if (error.Success() && exe_module_sp)
876                     break;
877             }
878         }
879     }
880     else
881     {
882         error.SetErrorStringWithFormat ("'%s' does not exist",
883                                         exe_file.GetPath().c_str());
884     }
885     return error;
886 }
887
888 Error
889 Platform::ResolveSymbolFile (Target &target,
890                              const ModuleSpec &sym_spec,
891                              FileSpec &sym_file)
892 {
893     Error error;
894     if (sym_spec.GetSymbolFileSpec().Exists())
895         sym_file = sym_spec.GetSymbolFileSpec();
896     else
897         error.SetErrorString("unable to resolve symbol file");
898     return error;
899     
900 }
901
902
903
904 bool
905 Platform::ResolveRemotePath (const FileSpec &platform_path,
906                              FileSpec &resolved_platform_path)
907 {
908     resolved_platform_path = platform_path;
909     return resolved_platform_path.ResolvePath();
910 }
911
912
913 const ArchSpec &
914 Platform::GetSystemArchitecture()
915 {
916     if (IsHost())
917     {
918         if (!m_system_arch.IsValid())
919         {
920             // We have a local host platform
921             m_system_arch = HostInfo::GetArchitecture();
922             m_system_arch_set_while_connected = m_system_arch.IsValid();
923         }
924     }
925     else 
926     {
927         // We have a remote platform. We can only fetch the remote
928         // system architecture if we are connected, and we don't want to do it
929         // more than once.
930         
931         const bool is_connected = IsConnected();
932
933         bool fetch = false;
934         if (m_system_arch.IsValid())
935         {
936             // We have valid OS version info, check to make sure it wasn't
937             // manually set prior to connecting. If it was manually set prior
938             // to connecting, then lets fetch the actual OS version info
939             // if we are now connected.
940             if (is_connected && !m_system_arch_set_while_connected)
941                 fetch = true;
942         }
943         else
944         {
945             // We don't have valid OS version info, fetch it if we are connected
946             fetch = is_connected;
947         }
948
949         if (fetch)
950         {
951             m_system_arch = GetRemoteSystemArchitecture ();
952             m_system_arch_set_while_connected = m_system_arch.IsValid();
953         }
954     }
955     return m_system_arch;
956 }
957
958
959 Error
960 Platform::ConnectRemote (Args& args)
961 {
962     Error error;
963     if (IsHost())
964         error.SetErrorStringWithFormat ("The currently selected platform (%s) is the host platform and is always connected.", GetPluginName().GetCString());
965     else
966         error.SetErrorStringWithFormat ("Platform::ConnectRemote() is not supported by %s", GetPluginName().GetCString());
967     return error;
968 }
969
970 Error
971 Platform::DisconnectRemote ()
972 {
973     Error error;
974     if (IsHost())
975         error.SetErrorStringWithFormat ("The currently selected platform (%s) is the host platform and is always connected.", GetPluginName().GetCString());
976     else
977         error.SetErrorStringWithFormat ("Platform::DisconnectRemote() is not supported by %s", GetPluginName().GetCString());
978     return error;
979 }
980
981 bool
982 Platform::GetProcessInfo (lldb::pid_t pid, ProcessInstanceInfo &process_info)
983 {
984     // Take care of the host case so that each subclass can just 
985     // call this function to get the host functionality.
986     if (IsHost())
987         return Host::GetProcessInfo (pid, process_info);
988     return false;
989 }
990
991 uint32_t
992 Platform::FindProcesses (const ProcessInstanceInfoMatch &match_info,
993                          ProcessInstanceInfoList &process_infos)
994 {
995     // Take care of the host case so that each subclass can just 
996     // call this function to get the host functionality.
997     uint32_t match_count = 0;
998     if (IsHost())
999         match_count = Host::FindProcesses (match_info, process_infos);
1000     return match_count;    
1001 }
1002
1003
1004 Error
1005 Platform::LaunchProcess (ProcessLaunchInfo &launch_info)
1006 {
1007     Error error;
1008     // Take care of the host case so that each subclass can just 
1009     // call this function to get the host functionality.
1010     if (IsHost())
1011     {
1012         if (::getenv ("LLDB_LAUNCH_FLAG_LAUNCH_IN_TTY"))
1013             launch_info.GetFlags().Set (eLaunchFlagLaunchInTTY);
1014         
1015         if (launch_info.GetFlags().Test (eLaunchFlagLaunchInShell))
1016         {
1017             const bool is_localhost = true;
1018             const bool will_debug = launch_info.GetFlags().Test(eLaunchFlagDebug);
1019             const bool first_arg_is_full_shell_command = false;
1020             uint32_t num_resumes = GetResumeCountForLaunchInfo (launch_info);
1021             if (!launch_info.ConvertArgumentsForLaunchingInShell (error,
1022                                                                   is_localhost,
1023                                                                   will_debug,
1024                                                                   first_arg_is_full_shell_command,
1025                                                                   num_resumes))
1026                 return error;
1027         }
1028
1029         error = Host::LaunchProcess (launch_info);
1030     }
1031     else
1032         error.SetErrorString ("base lldb_private::Platform class can't launch remote processes");
1033     return error;
1034 }
1035
1036 lldb::ProcessSP
1037 Platform::DebugProcess (ProcessLaunchInfo &launch_info, 
1038                         Debugger &debugger,
1039                         Target *target,       // Can be NULL, if NULL create a new target, else use existing one
1040                         Listener &listener,
1041                         Error &error)
1042 {
1043     ProcessSP process_sp;
1044     // Make sure we stop at the entry point
1045     launch_info.GetFlags ().Set (eLaunchFlagDebug);
1046     // We always launch the process we are going to debug in a separate process
1047     // group, since then we can handle ^C interrupts ourselves w/o having to worry
1048     // about the target getting them as well.
1049     launch_info.SetLaunchInSeparateProcessGroup(true);
1050     
1051     error = LaunchProcess (launch_info);
1052     if (error.Success())
1053     {
1054         if (launch_info.GetProcessID() != LLDB_INVALID_PROCESS_ID)
1055         {
1056             ProcessAttachInfo attach_info (launch_info);
1057             process_sp = Attach (attach_info, debugger, target, listener, error);
1058             if (process_sp)
1059             {
1060                 launch_info.SetHijackListener(attach_info.GetHijackListener());
1061                 
1062                 // Since we attached to the process, it will think it needs to detach
1063                 // if the process object just goes away without an explicit call to
1064                 // Process::Kill() or Process::Detach(), so let it know to kill the 
1065                 // process if this happens.
1066                 process_sp->SetShouldDetach (false);
1067                 
1068                 // If we didn't have any file actions, the pseudo terminal might
1069                 // have been used where the slave side was given as the file to
1070                 // open for stdin/out/err after we have already opened the master
1071                 // so we can read/write stdin/out/err.
1072                 int pty_fd = launch_info.GetPTY().ReleaseMasterFileDescriptor();
1073                 if (pty_fd != lldb_utility::PseudoTerminal::invalid_fd)
1074                 {
1075                     process_sp->SetSTDIOFileDescriptor(pty_fd);
1076                 }
1077             }
1078         }
1079     }
1080     return process_sp;
1081 }
1082
1083
1084 lldb::PlatformSP
1085 Platform::GetPlatformForArchitecture (const ArchSpec &arch, ArchSpec *platform_arch_ptr)
1086 {
1087     lldb::PlatformSP platform_sp;
1088     Error error;
1089     if (arch.IsValid())
1090         platform_sp = Platform::Create (arch, platform_arch_ptr, error);
1091     return platform_sp;
1092 }
1093
1094
1095 //------------------------------------------------------------------
1096 /// Lets a platform answer if it is compatible with a given
1097 /// architecture and the target triple contained within.
1098 //------------------------------------------------------------------
1099 bool
1100 Platform::IsCompatibleArchitecture (const ArchSpec &arch, bool exact_arch_match, ArchSpec *compatible_arch_ptr)
1101 {
1102     // If the architecture is invalid, we must answer true...
1103     if (arch.IsValid())
1104     {
1105         ArchSpec platform_arch;
1106         // Try for an exact architecture match first.
1107         if (exact_arch_match)
1108         {
1109             for (uint32_t arch_idx=0; GetSupportedArchitectureAtIndex (arch_idx, platform_arch); ++arch_idx)
1110             {
1111                 if (arch.IsExactMatch(platform_arch))
1112                 {
1113                     if (compatible_arch_ptr)
1114                         *compatible_arch_ptr = platform_arch;
1115                     return true;
1116                 }
1117             }
1118         }
1119         else
1120         {
1121             for (uint32_t arch_idx=0; GetSupportedArchitectureAtIndex (arch_idx, platform_arch); ++arch_idx)
1122             {
1123                 if (arch.IsCompatibleMatch(platform_arch))
1124                 {
1125                     if (compatible_arch_ptr)
1126                         *compatible_arch_ptr = platform_arch;
1127                     return true;
1128                 }
1129             }
1130         }
1131     }
1132     if (compatible_arch_ptr)
1133         compatible_arch_ptr->Clear();
1134     return false;
1135 }
1136
1137 Error
1138 Platform::PutFile (const FileSpec& source,
1139                    const FileSpec& destination,
1140                    uint32_t uid,
1141                    uint32_t gid)
1142 {
1143     Error error("unimplemented");
1144     return error;
1145 }
1146
1147 Error
1148 Platform::GetFile (const FileSpec& source,
1149                    const FileSpec& destination)
1150 {
1151     Error error("unimplemented");
1152     return error;
1153 }
1154
1155 Error
1156 Platform::CreateSymlink (const char *src, // The name of the link is in src
1157                          const char *dst)// The symlink points to dst
1158 {
1159     Error error("unimplemented");
1160     return error;
1161 }
1162
1163 bool
1164 Platform::GetFileExists (const lldb_private::FileSpec& file_spec)
1165 {
1166     return false;
1167 }
1168
1169 Error
1170 Platform::Unlink (const char *path)
1171 {
1172     Error error("unimplemented");
1173     return error;
1174 }
1175
1176
1177
1178 lldb_private::Error
1179 Platform::RunShellCommand (const char *command,           // Shouldn't be NULL
1180                            const char *working_dir,       // Pass NULL to use the current working directory
1181                            int *status_ptr,               // Pass NULL if you don't want the process exit status
1182                            int *signo_ptr,                // Pass NULL if you don't want the signal that caused the process to exit
1183                            std::string *command_output,   // Pass NULL if you don't want the command output
1184                            uint32_t timeout_sec)          // Timeout in seconds to wait for shell program to finish
1185 {
1186     if (IsHost())
1187         return Host::RunShellCommand (command, working_dir, status_ptr, signo_ptr, command_output, timeout_sec);
1188     else
1189         return Error("unimplemented");
1190 }
1191
1192
1193 bool
1194 Platform::CalculateMD5 (const FileSpec& file_spec,
1195                         uint64_t &low,
1196                         uint64_t &high)
1197 {
1198     if (IsHost())
1199         return FileSystem::CalculateMD5(file_spec, low, high);
1200     else
1201         return false;
1202 }
1203
1204 Error
1205 Platform::LaunchNativeProcess (
1206     ProcessLaunchInfo &launch_info,
1207     lldb_private::NativeProcessProtocol::NativeDelegate &native_delegate,
1208     NativeProcessProtocolSP &process_sp)
1209 {
1210     // Platforms should override this implementation if they want to
1211     // support lldb-gdbserver.
1212     return Error("unimplemented");
1213 }
1214
1215 Error
1216 Platform::AttachNativeProcess (lldb::pid_t pid,
1217                                lldb_private::NativeProcessProtocol::NativeDelegate &native_delegate,
1218                                NativeProcessProtocolSP &process_sp)
1219 {
1220     // Platforms should override this implementation if they want to
1221     // support lldb-gdbserver.
1222     return Error("unimplemented");
1223 }
1224
1225 void
1226 Platform::SetLocalCacheDirectory (const char* local)
1227 {
1228     m_local_cache_directory.assign(local);
1229 }
1230
1231 const char*
1232 Platform::GetLocalCacheDirectory ()
1233 {
1234     return m_local_cache_directory.c_str();
1235 }
1236
1237 static OptionDefinition
1238 g_rsync_option_table[] =
1239 {
1240     {   LLDB_OPT_SET_ALL, false, "rsync"                  , 'r', OptionParser::eNoArgument,       NULL, NULL, 0, eArgTypeNone         , "Enable rsync." },
1241     {   LLDB_OPT_SET_ALL, false, "rsync-opts"             , 'R', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeCommandName  , "Platform-specific options required for rsync to work." },
1242     {   LLDB_OPT_SET_ALL, false, "rsync-prefix"           , 'P', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeCommandName  , "Platform-specific rsync prefix put before the remote path." },
1243     {   LLDB_OPT_SET_ALL, false, "ignore-remote-hostname" , 'i', OptionParser::eNoArgument,       NULL, NULL, 0, eArgTypeNone         , "Do not automatically fill in the remote hostname when composing the rsync command." },
1244 };
1245
1246 static OptionDefinition
1247 g_ssh_option_table[] =
1248 {
1249     {   LLDB_OPT_SET_ALL, false, "ssh"                    , 's', OptionParser::eNoArgument,       NULL, NULL, 0, eArgTypeNone         , "Enable SSH." },
1250     {   LLDB_OPT_SET_ALL, false, "ssh-opts"               , 'S', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeCommandName  , "Platform-specific options required for SSH to work." },
1251 };
1252
1253 static OptionDefinition
1254 g_caching_option_table[] =
1255 {
1256     {   LLDB_OPT_SET_ALL, false, "local-cache-dir"        , 'c', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypePath         , "Path in which to store local copies of files." },
1257 };
1258
1259 OptionGroupPlatformRSync::OptionGroupPlatformRSync ()
1260 {
1261 }
1262
1263 OptionGroupPlatformRSync::~OptionGroupPlatformRSync ()
1264 {
1265 }
1266
1267 const lldb_private::OptionDefinition*
1268 OptionGroupPlatformRSync::GetDefinitions ()
1269 {
1270     return g_rsync_option_table;
1271 }
1272
1273 void
1274 OptionGroupPlatformRSync::OptionParsingStarting (CommandInterpreter &interpreter)
1275 {
1276     m_rsync = false;
1277     m_rsync_opts.clear();
1278     m_rsync_prefix.clear();
1279     m_ignores_remote_hostname = false;
1280 }
1281
1282 lldb_private::Error
1283 OptionGroupPlatformRSync::SetOptionValue (CommandInterpreter &interpreter,
1284                 uint32_t option_idx,
1285                 const char *option_arg)
1286 {
1287     Error error;
1288     char short_option = (char) GetDefinitions()[option_idx].short_option;
1289     switch (short_option)
1290     {
1291         case 'r':
1292             m_rsync = true;
1293             break;
1294             
1295         case 'R':
1296             m_rsync_opts.assign(option_arg);
1297             break;
1298             
1299         case 'P':
1300             m_rsync_prefix.assign(option_arg);
1301             break;
1302             
1303         case 'i':
1304             m_ignores_remote_hostname = true;
1305             break;
1306             
1307         default:
1308             error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option);
1309             break;
1310     }
1311     
1312     return error;
1313 }
1314
1315 uint32_t
1316 OptionGroupPlatformRSync::GetNumDefinitions ()
1317 {
1318     return llvm::array_lengthof(g_rsync_option_table);
1319 }
1320
1321 lldb::BreakpointSP
1322 Platform::SetThreadCreationBreakpoint (lldb_private::Target &target)
1323 {
1324     return lldb::BreakpointSP();
1325 }
1326
1327 OptionGroupPlatformSSH::OptionGroupPlatformSSH ()
1328 {
1329 }
1330
1331 OptionGroupPlatformSSH::~OptionGroupPlatformSSH ()
1332 {
1333 }
1334
1335 const lldb_private::OptionDefinition*
1336 OptionGroupPlatformSSH::GetDefinitions ()
1337 {
1338     return g_ssh_option_table;
1339 }
1340
1341 void
1342 OptionGroupPlatformSSH::OptionParsingStarting (CommandInterpreter &interpreter)
1343 {
1344     m_ssh = false;
1345     m_ssh_opts.clear();
1346 }
1347
1348 lldb_private::Error
1349 OptionGroupPlatformSSH::SetOptionValue (CommandInterpreter &interpreter,
1350                                           uint32_t option_idx,
1351                                           const char *option_arg)
1352 {
1353     Error error;
1354     char short_option = (char) GetDefinitions()[option_idx].short_option;
1355     switch (short_option)
1356     {
1357         case 's':
1358             m_ssh = true;
1359             break;
1360             
1361         case 'S':
1362             m_ssh_opts.assign(option_arg);
1363             break;
1364             
1365         default:
1366             error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option);
1367             break;
1368     }
1369     
1370     return error;
1371 }
1372
1373 uint32_t
1374 OptionGroupPlatformSSH::GetNumDefinitions ()
1375 {
1376     return llvm::array_lengthof(g_ssh_option_table);
1377 }
1378
1379 OptionGroupPlatformCaching::OptionGroupPlatformCaching ()
1380 {
1381 }
1382
1383 OptionGroupPlatformCaching::~OptionGroupPlatformCaching ()
1384 {
1385 }
1386
1387 const lldb_private::OptionDefinition*
1388 OptionGroupPlatformCaching::GetDefinitions ()
1389 {
1390     return g_caching_option_table;
1391 }
1392
1393 void
1394 OptionGroupPlatformCaching::OptionParsingStarting (CommandInterpreter &interpreter)
1395 {
1396     m_cache_dir.clear();
1397 }
1398
1399 lldb_private::Error
1400 OptionGroupPlatformCaching::SetOptionValue (CommandInterpreter &interpreter,
1401                                         uint32_t option_idx,
1402                                         const char *option_arg)
1403 {
1404     Error error;
1405     char short_option = (char) GetDefinitions()[option_idx].short_option;
1406     switch (short_option)
1407     {
1408         case 'c':
1409             m_cache_dir.assign(option_arg);
1410             break;
1411             
1412         default:
1413             error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option);
1414             break;
1415     }
1416     
1417     return error;
1418 }
1419
1420 uint32_t
1421 OptionGroupPlatformCaching::GetNumDefinitions ()
1422 {
1423     return llvm::array_lengthof(g_caching_option_table);
1424 }
1425
1426 size_t
1427 Platform::GetEnvironment (StringList &environment)
1428 {
1429     environment.Clear();
1430     return false;
1431 }
1432
1433 const std::vector<ConstString> &
1434 Platform::GetTrapHandlerSymbolNames ()
1435 {
1436     if (!m_calculated_trap_handlers)
1437     {
1438         Mutex::Locker locker (m_trap_handler_mutex);
1439         if (!m_calculated_trap_handlers)
1440         {
1441             CalculateTrapHandlerSymbolNames();
1442             m_calculated_trap_handlers = true;
1443         }
1444     }
1445     return m_trap_handlers;
1446 }
1447