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