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