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