1 //===-- PlatformLinux.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/lldb-python.h"
11 
12 #include "PlatformLinux.h"
13 #include "lldb/Host/Config.h"
14 
15 // C Includes
16 #include <stdio.h>
17 #ifndef LLDB_DISABLE_POSIX
18 #include <sys/utsname.h>
19 #endif
20 
21 // C++ Includes
22 // Other libraries and framework includes
23 // Project includes
24 #include "lldb/Core/Error.h"
25 #include "lldb/Core/Debugger.h"
26 #include "lldb/Core/Log.h"
27 #include "lldb/Core/Module.h"
28 #include "lldb/Core/ModuleList.h"
29 #include "lldb/Core/ModuleSpec.h"
30 #include "lldb/Core/PluginManager.h"
31 #include "lldb/Core/StreamString.h"
32 #include "lldb/Host/FileSpec.h"
33 #include "lldb/Host/HostInfo.h"
34 #include "lldb/Target/Target.h"
35 #include "lldb/Target/Process.h"
36 
37 #if defined(__linux__)
38 #include "../../Process/Linux/NativeProcessLinux.h"
39 #endif
40 
41 using namespace lldb;
42 using namespace lldb_private;
43 
44 static uint32_t g_initialize_count = 0;
45 
46 Platform *
47 PlatformLinux::CreateInstance (bool force, const ArchSpec *arch)
48 {
49     Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_PLATFORM));
50     if (log)
51     {
52         const char *arch_name;
53         if (arch && arch->GetArchitectureName ())
54             arch_name = arch->GetArchitectureName ();
55         else
56             arch_name = "<null>";
57 
58         const char *triple_cstr = arch ? arch->GetTriple ().getTriple ().c_str() : "<null>";
59 
60         log->Printf ("PlatformLinux::%s(force=%s, arch={%s,%s})", __FUNCTION__, force ? "true" : "false", arch_name, triple_cstr);
61     }
62 
63     bool create = force;
64     if (create == false && arch && arch->IsValid())
65     {
66         const llvm::Triple &triple = arch->GetTriple();
67         switch (triple.getVendor())
68         {
69             case llvm::Triple::PC:
70                 create = true;
71                 break;
72 
73 #if defined(__linux__)
74             // Only accept "unknown" for the vendor if the host is linux and
75             // it "unknown" wasn't specified (it was just returned because it
76             // was NOT specified_
77             case llvm::Triple::VendorType::UnknownVendor:
78                 create = !arch->TripleVendorWasSpecified();
79                 break;
80 #endif
81             default:
82                 break;
83         }
84 
85         if (create)
86         {
87             switch (triple.getOS())
88             {
89                 case llvm::Triple::Linux:
90                     break;
91 
92 #if defined(__linux__)
93                 // Only accept "unknown" for the OS if the host is linux and
94                 // it "unknown" wasn't specified (it was just returned because it
95                 // was NOT specified)
96                 case llvm::Triple::OSType::UnknownOS:
97                     create = !arch->TripleOSWasSpecified();
98                     break;
99 #endif
100                 default:
101                     create = false;
102                     break;
103             }
104         }
105     }
106 
107     if (create)
108     {
109         if (log)
110             log->Printf ("PlatformLinux::%s() creating remote-linux platform", __FUNCTION__);
111         return new PlatformLinux(false);
112     }
113 
114     if (log)
115         log->Printf ("PlatformLinux::%s() aborting creation of remote-linux platform", __FUNCTION__);
116 
117     return NULL;
118 }
119 
120 
121 lldb_private::ConstString
122 PlatformLinux::GetPluginNameStatic (bool is_host)
123 {
124     if (is_host)
125     {
126         static ConstString g_host_name(Platform::GetHostPlatformName ());
127         return g_host_name;
128     }
129     else
130     {
131         static ConstString g_remote_name("remote-linux");
132         return g_remote_name;
133     }
134 }
135 
136 const char *
137 PlatformLinux::GetPluginDescriptionStatic (bool is_host)
138 {
139     if (is_host)
140         return "Local Linux user platform plug-in.";
141     else
142         return "Remote Linux user platform plug-in.";
143 }
144 
145 lldb_private::ConstString
146 PlatformLinux::GetPluginName()
147 {
148     return GetPluginNameStatic(IsHost());
149 }
150 
151 void
152 PlatformLinux::Initialize ()
153 {
154     if (g_initialize_count++ == 0)
155     {
156 #if defined(__linux__)
157         PlatformSP default_platform_sp (new PlatformLinux(true));
158         default_platform_sp->SetSystemArchitecture(HostInfo::GetArchitecture());
159         Platform::SetDefaultPlatform (default_platform_sp);
160 #endif
161         PluginManager::RegisterPlugin(PlatformLinux::GetPluginNameStatic(false),
162                                       PlatformLinux::GetPluginDescriptionStatic(false),
163                                       PlatformLinux::CreateInstance);
164     }
165 }
166 
167 void
168 PlatformLinux::Terminate ()
169 {
170     if (g_initialize_count > 0)
171     {
172         if (--g_initialize_count == 0)
173         {
174             PluginManager::UnregisterPlugin (PlatformLinux::CreateInstance);
175         }
176     }
177 }
178 
179 Error
180 PlatformLinux::ResolveExecutable (const FileSpec &exe_file,
181                                   const ArchSpec &exe_arch,
182                                   lldb::ModuleSP &exe_module_sp,
183                                   const FileSpecList *module_search_paths_ptr)
184 {
185     Error error;
186     // Nothing special to do here, just use the actual file and architecture
187 
188     char exe_path[PATH_MAX];
189     FileSpec resolved_exe_file (exe_file);
190 
191     if (IsHost())
192     {
193         // If we have "ls" as the exe_file, resolve the executable location based on
194         // the current path variables
195         if (!resolved_exe_file.Exists())
196         {
197             exe_file.GetPath(exe_path, sizeof(exe_path));
198             resolved_exe_file.SetFile(exe_path, true);
199         }
200 
201         if (!resolved_exe_file.Exists())
202             resolved_exe_file.ResolveExecutableLocation ();
203 
204         if (resolved_exe_file.Exists())
205             error.Clear();
206         else
207         {
208             exe_file.GetPath(exe_path, sizeof(exe_path));
209             error.SetErrorStringWithFormat("unable to find executable for '%s'", exe_path);
210         }
211     }
212     else
213     {
214         if (m_remote_platform_sp)
215         {
216             error = m_remote_platform_sp->ResolveExecutable (exe_file,
217                                                              exe_arch,
218                                                              exe_module_sp,
219                                                              NULL);
220         }
221         else
222         {
223             // We may connect to a process and use the provided executable (Don't use local $PATH).
224 
225             if (resolved_exe_file.Exists())
226                 error.Clear();
227             else
228                 error.SetErrorStringWithFormat("the platform is not currently connected, and '%s' doesn't exist in the system root.", exe_path);
229         }
230     }
231 
232     if (error.Success())
233     {
234         ModuleSpec module_spec (resolved_exe_file, exe_arch);
235         if (exe_arch.IsValid())
236         {
237             error = ModuleList::GetSharedModule (module_spec,
238                                                  exe_module_sp,
239                                                  NULL,
240                                                  NULL,
241                                                  NULL);
242             if (error.Fail())
243             {
244                 // If we failed, it may be because the vendor and os aren't known. If that is the
245                 // case, try setting them to the host architecture and give it another try.
246                 llvm::Triple &module_triple = module_spec.GetArchitecture().GetTriple();
247                 bool is_vendor_specified = (module_triple.getVendor() != llvm::Triple::UnknownVendor);
248                 bool is_os_specified = (module_triple.getOS() != llvm::Triple::UnknownOS);
249                 if (!is_vendor_specified || !is_os_specified)
250                 {
251                     const llvm::Triple &host_triple = HostInfo::GetArchitecture(HostInfo::eArchKindDefault).GetTriple();
252 
253                     if (!is_vendor_specified)
254                         module_triple.setVendorName (host_triple.getVendorName());
255                     if (!is_os_specified)
256                         module_triple.setOSName (host_triple.getOSName());
257 
258                     error = ModuleList::GetSharedModule (module_spec,
259                                                          exe_module_sp,
260                                                          NULL,
261                                                          NULL,
262                                                          NULL);
263                 }
264             }
265 
266             // TODO find out why exe_module_sp might be NULL
267             if (!exe_module_sp || exe_module_sp->GetObjectFile() == NULL)
268             {
269                 exe_module_sp.reset();
270                 error.SetErrorStringWithFormat ("'%s' doesn't contain the architecture %s",
271                                                 exe_file.GetPath().c_str(),
272                                                 exe_arch.GetArchitectureName());
273             }
274         }
275         else
276         {
277             // No valid architecture was specified, ask the platform for
278             // the architectures that we should be using (in the correct order)
279             // and see if we can find a match that way
280             StreamString arch_names;
281             for (uint32_t idx = 0; GetSupportedArchitectureAtIndex (idx, module_spec.GetArchitecture()); ++idx)
282             {
283                 error = ModuleList::GetSharedModule (module_spec,
284                                                      exe_module_sp,
285                                                      NULL,
286                                                      NULL,
287                                                      NULL);
288                 // Did we find an executable using one of the
289                 if (error.Success())
290                 {
291                     if (exe_module_sp && exe_module_sp->GetObjectFile())
292                         break;
293                     else
294                         error.SetErrorToGenericError();
295                 }
296 
297                 if (idx > 0)
298                     arch_names.PutCString (", ");
299                 arch_names.PutCString (module_spec.GetArchitecture().GetArchitectureName());
300             }
301 
302             if (error.Fail() || !exe_module_sp)
303             {
304                 if (exe_file.Readable())
305                 {
306                     error.SetErrorStringWithFormat ("'%s' doesn't contain any '%s' platform architectures: %s",
307                                                     exe_file.GetPath().c_str(),
308                                                     GetPluginName().GetCString(),
309                                                     arch_names.GetString().c_str());
310                 }
311                 else
312                 {
313                     error.SetErrorStringWithFormat("'%s' is not readable", exe_file.GetPath().c_str());
314                 }
315             }
316         }
317     }
318 
319     return error;
320 }
321 
322 Error
323 PlatformLinux::GetFileWithUUID (const FileSpec &platform_file,
324                                 const UUID *uuid_ptr, FileSpec &local_file)
325 {
326     if (IsRemote())
327     {
328         if (m_remote_platform_sp)
329             return m_remote_platform_sp->GetFileWithUUID (platform_file, uuid_ptr, local_file);
330     }
331 
332     // Default to the local case
333     local_file = platform_file;
334     return Error();
335 }
336 
337 
338 //------------------------------------------------------------------
339 /// Default Constructor
340 //------------------------------------------------------------------
341 PlatformLinux::PlatformLinux (bool is_host) :
342     PlatformPOSIX(is_host)  // This is the local host platform
343 {
344 }
345 
346 //------------------------------------------------------------------
347 /// Destructor.
348 ///
349 /// The destructor is virtual since this class is designed to be
350 /// inherited from by the plug-in instance.
351 //------------------------------------------------------------------
352 PlatformLinux::~PlatformLinux()
353 {
354 }
355 
356 bool
357 PlatformLinux::GetProcessInfo (lldb::pid_t pid, ProcessInstanceInfo &process_info)
358 {
359     bool success = false;
360     if (IsHost())
361     {
362         success = Platform::GetProcessInfo (pid, process_info);
363     }
364     else
365     {
366         if (m_remote_platform_sp)
367             success = m_remote_platform_sp->GetProcessInfo (pid, process_info);
368     }
369     return success;
370 }
371 
372 bool
373 PlatformLinux::GetSupportedArchitectureAtIndex (uint32_t idx, ArchSpec &arch)
374 {
375     if (idx == 0)
376     {
377         arch = HostInfo::GetArchitecture(HostInfo::eArchKindDefault);
378         return arch.IsValid();
379     }
380     else if (idx == 1)
381     {
382         // If the default host architecture is 64-bit, look for a 32-bit variant
383         ArchSpec hostArch = HostInfo::GetArchitecture(HostInfo::eArchKindDefault);
384         if (hostArch.IsValid() && hostArch.GetTriple().isArch64Bit())
385         {
386             arch = HostInfo::GetArchitecture(HostInfo::eArchKind32);
387             return arch.IsValid();
388         }
389     }
390     return false;
391 }
392 
393 void
394 PlatformLinux::GetStatus (Stream &strm)
395 {
396     Platform::GetStatus(strm);
397 
398 #ifndef LLDB_DISABLE_POSIX
399     struct utsname un;
400 
401     if (uname(&un))
402         return;
403 
404     strm.Printf ("    Kernel: %s\n", un.sysname);
405     strm.Printf ("   Release: %s\n", un.release);
406     strm.Printf ("   Version: %s\n", un.version);
407 #endif
408 }
409 
410 size_t
411 PlatformLinux::GetSoftwareBreakpointTrapOpcode (Target &target,
412                                                 BreakpointSite *bp_site)
413 {
414     ArchSpec arch = target.GetArchitecture();
415     const uint8_t *trap_opcode = NULL;
416     size_t trap_opcode_size = 0;
417 
418     switch (arch.GetMachine())
419     {
420     default:
421         assert(false && "CPU type not supported!");
422         break;
423 
424     case llvm::Triple::aarch64:
425         {
426             static const uint8_t g_aarch64_opcode[] = { 0x00, 0x00, 0x20, 0xd4 };
427             trap_opcode = g_aarch64_opcode;
428             trap_opcode_size = sizeof(g_aarch64_opcode);
429         }
430         break;
431     case llvm::Triple::x86:
432     case llvm::Triple::x86_64:
433         {
434             static const uint8_t g_i386_breakpoint_opcode[] = { 0xCC };
435             trap_opcode = g_i386_breakpoint_opcode;
436             trap_opcode_size = sizeof(g_i386_breakpoint_opcode);
437         }
438         break;
439     case llvm::Triple::hexagon:
440         {
441             static const uint8_t g_hex_opcode[] = { 0x0c, 0xdb, 0x00, 0x54 };
442             trap_opcode = g_hex_opcode;
443             trap_opcode_size = sizeof(g_hex_opcode);
444         }
445         break;
446     }
447 
448     if (bp_site->SetTrapOpcode(trap_opcode, trap_opcode_size))
449         return trap_opcode_size;
450     return 0;
451 }
452 
453 Error
454 PlatformLinux::LaunchProcess (ProcessLaunchInfo &launch_info)
455 {
456     Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_PLATFORM));
457     Error error;
458 
459     if (IsHost())
460     {
461         if (log)
462             log->Printf ("PlatformLinux::%s() launching process as host", __FUNCTION__);
463 
464         if (launch_info.GetFlags().Test (eLaunchFlagLaunchInShell))
465         {
466             const bool is_localhost = true;
467             const bool will_debug = launch_info.GetFlags().Test(eLaunchFlagDebug);
468             const bool first_arg_is_full_shell_command = false;
469             uint32_t num_resumes = GetResumeCountForLaunchInfo (launch_info);
470             if (!launch_info.ConvertArgumentsForLaunchingInShell (error,
471                                                                   is_localhost,
472                                                                   will_debug,
473                                                                   first_arg_is_full_shell_command,
474                                                                   num_resumes))
475                 return error;
476         }
477         error = Platform::LaunchProcess (launch_info);
478     }
479     else
480     {
481         if (m_remote_platform_sp)
482         {
483             if (log)
484                 log->Printf ("PlatformLinux::%s() attempting to launch remote process", __FUNCTION__);
485             error = m_remote_platform_sp->LaunchProcess (launch_info);
486         }
487         else
488         {
489             if (log)
490                 log->Printf ("PlatformLinux::%s() attempted to launch process but is not the host and no remote platform set", __FUNCTION__);
491             error.SetErrorString ("the platform is not currently connected");
492         }
493     }
494     return error;
495 }
496 
497 // Linux processes can not be launched by spawning and attaching.
498 bool
499 PlatformLinux::CanDebugProcess ()
500 {
501     // If we're the host, launch via normal host setup.
502     if (IsHost ())
503         return false;
504 
505     // If we're connected, we can debug.
506     return IsConnected ();
507 }
508 
509 lldb::ProcessSP
510 PlatformLinux::Attach(ProcessAttachInfo &attach_info,
511                       Debugger &debugger,
512                       Target *target,
513                       Listener &listener,
514                       Error &error)
515 {
516     lldb::ProcessSP process_sp;
517     if (IsHost())
518     {
519         if (target == NULL)
520         {
521             TargetSP new_target_sp;
522             ArchSpec emptyArchSpec;
523 
524             error = debugger.GetTargetList().CreateTarget (debugger,
525                                                            NULL,
526                                                            emptyArchSpec,
527                                                            false,
528                                                            m_remote_platform_sp,
529                                                            new_target_sp);
530             target = new_target_sp.get();
531         }
532         else
533             error.Clear();
534 
535         if (target && error.Success())
536         {
537             debugger.GetTargetList().SetSelectedTarget(target);
538 
539             process_sp = target->CreateProcess (listener,
540                                                 attach_info.GetProcessPluginName(),
541                                                 NULL);
542 
543             if (process_sp)
544                 error = process_sp->Attach (attach_info);
545         }
546     }
547     else
548     {
549         if (m_remote_platform_sp)
550             process_sp = m_remote_platform_sp->Attach (attach_info, debugger, target, listener, error);
551         else
552             error.SetErrorString ("the platform is not currently connected");
553     }
554     return process_sp;
555 }
556 
557 void
558 PlatformLinux::CalculateTrapHandlerSymbolNames ()
559 {
560     m_trap_handlers.push_back (ConstString ("_sigtramp"));
561 }
562 
563 Error
564 PlatformLinux::LaunchNativeProcess (
565     ProcessLaunchInfo &launch_info,
566     lldb_private::NativeProcessProtocol::NativeDelegate &native_delegate,
567     NativeProcessProtocolSP &process_sp)
568 {
569 #if !defined(__linux__)
570     return Error("only implemented on Linux hosts");
571 #else
572     if (!IsHost ())
573         return Error("PlatformLinux::%s (): cannot launch a debug process when not the host", __FUNCTION__);
574 
575     // Retrieve the exe module.
576     lldb::ModuleSP exe_module_sp;
577 
578     Error error = ResolveExecutable (
579         launch_info.GetExecutableFile (),
580         launch_info.GetArchitecture (),
581         exe_module_sp,
582         NULL);
583 
584     if (!error.Success ())
585         return error;
586 
587     if (!exe_module_sp)
588         return Error("exe_module_sp could not be resolved for %s", launch_info.GetExecutableFile ().GetPath ().c_str ());
589 
590     // Launch it for debugging
591     error = NativeProcessLinux::LaunchProcess (
592         exe_module_sp.get (),
593         launch_info,
594         native_delegate,
595         process_sp);
596 
597     return error;
598 #endif
599 }
600 
601 Error
602 PlatformLinux::AttachNativeProcess (lldb::pid_t pid,
603                                     lldb_private::NativeProcessProtocol::NativeDelegate &native_delegate,
604                                     NativeProcessProtocolSP &process_sp)
605 {
606 #if !defined(__linux__)
607     return Error("only implemented on Linux hosts");
608 #else
609     if (!IsHost ())
610         return Error("PlatformLinux::%s (): cannot attach to a debug process when not the host", __FUNCTION__);
611 
612     // Launch it for debugging
613     return NativeProcessLinux::AttachToProcess (pid, native_delegate, process_sp);
614 #endif
615 }
616