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