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