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 "PlatformLinux.h"
11 #include "lldb/Host/Config.h"
12 
13 // C Includes
14 #include <stdio.h>
15 #ifndef LLDB_DISABLE_POSIX
16 #include <sys/utsname.h>
17 #endif
18 
19 // C++ Includes
20 // Other libraries and framework includes
21 // Project includes
22 #include "lldb/Breakpoint/BreakpointLocation.h"
23 #include "lldb/Core/Debugger.h"
24 #include "lldb/Core/Error.h"
25 #include "lldb/Core/Log.h"
26 #include "lldb/Core/Module.h"
27 #include "lldb/Core/ModuleList.h"
28 #include "lldb/Core/ModuleSpec.h"
29 #include "lldb/Core/PluginManager.h"
30 #include "lldb/Core/State.h"
31 #include "lldb/Core/StreamString.h"
32 #include "lldb/Host/FileSpec.h"
33 #include "lldb/Host/HostInfo.h"
34 #include "lldb/Interpreter/OptionValueProperties.h"
35 #include "lldb/Interpreter/Property.h"
36 #include "lldb/Target/Target.h"
37 #include "lldb/Target/Process.h"
38 
39 // Define these constants from Linux mman.h for use when targeting
40 // remote linux systems even when host has different values.
41 #define MAP_PRIVATE 2
42 #define MAP_ANON 0x20
43 
44 using namespace lldb;
45 using namespace lldb_private;
46 using namespace lldb_private::platform_linux;
47 
48 static uint32_t g_initialize_count = 0;
49 
50 //------------------------------------------------------------------
51 /// Code to handle the PlatformLinux settings
52 //------------------------------------------------------------------
53 
54 namespace
55 {
56     class PlatformLinuxProperties : public Properties
57     {
58     public:
59         PlatformLinuxProperties();
60 
61         ~PlatformLinuxProperties() override = default;
62 
63         static ConstString&
64         GetSettingName ();
65 
66     private:
67         static const PropertyDefinition*
68         GetStaticPropertyDefinitions();
69     };
70 
71     typedef std::shared_ptr<PlatformLinuxProperties> PlatformLinuxPropertiesSP;
72 
73 } // anonymous namespace
74 
75 PlatformLinuxProperties::PlatformLinuxProperties() :
76     Properties ()
77 {
78     m_collection_sp.reset (new OptionValueProperties(GetSettingName ()));
79     m_collection_sp->Initialize (GetStaticPropertyDefinitions ());
80 }
81 
82 ConstString&
83 PlatformLinuxProperties::GetSettingName ()
84 {
85     static ConstString g_setting_name("linux");
86     return g_setting_name;
87 }
88 
89 const PropertyDefinition*
90 PlatformLinuxProperties::GetStaticPropertyDefinitions()
91 {
92     static PropertyDefinition
93     g_properties[] =
94     {
95         {  NULL        , OptionValue::eTypeInvalid, false, 0  , NULL, NULL, NULL  }
96     };
97 
98     return g_properties;
99 }
100 
101 static const PlatformLinuxPropertiesSP &
102 GetGlobalProperties()
103 {
104     static PlatformLinuxPropertiesSP g_settings_sp;
105     if (!g_settings_sp)
106         g_settings_sp.reset (new PlatformLinuxProperties ());
107     return g_settings_sp;
108 }
109 
110 void
111 PlatformLinux::DebuggerInitialize (Debugger &debugger)
112 {
113     if (!PluginManager::GetSettingForPlatformPlugin (debugger, PlatformLinuxProperties::GetSettingName()))
114     {
115         const bool is_global_setting = true;
116         PluginManager::CreateSettingForPlatformPlugin (debugger,
117                                                        GetGlobalProperties()->GetValueProperties(),
118                                                        ConstString ("Properties for the PlatformLinux plug-in."),
119                                                        is_global_setting);
120     }
121 }
122 
123 //------------------------------------------------------------------
124 
125 PlatformSP
126 PlatformLinux::CreateInstance (bool force, const ArchSpec *arch)
127 {
128     Log *log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_PLATFORM));
129     if (log)
130     {
131         const char *arch_name;
132         if (arch && arch->GetArchitectureName ())
133             arch_name = arch->GetArchitectureName ();
134         else
135             arch_name = "<null>";
136 
137         const char *triple_cstr = arch ? arch->GetTriple ().getTriple ().c_str() : "<null>";
138 
139         log->Printf ("PlatformLinux::%s(force=%s, arch={%s,%s})", __FUNCTION__, force ? "true" : "false", arch_name, triple_cstr);
140     }
141 
142     bool create = force;
143     if (create == false && arch && arch->IsValid())
144     {
145         const llvm::Triple &triple = arch->GetTriple();
146         switch (triple.getOS())
147         {
148             case llvm::Triple::Linux:
149                 create = true;
150                 break;
151 
152 #if defined(__linux__)
153             // Only accept "unknown" for the OS if the host is linux and
154             // it "unknown" wasn't specified (it was just returned because it
155             // was NOT specified)
156             case llvm::Triple::OSType::UnknownOS:
157                 create = !arch->TripleOSWasSpecified();
158                 break;
159 #endif
160             default:
161                 break;
162         }
163     }
164 
165     if (create)
166     {
167         if (log)
168             log->Printf ("PlatformLinux::%s() creating remote-linux platform", __FUNCTION__);
169         return PlatformSP(new PlatformLinux(false));
170     }
171 
172     if (log)
173         log->Printf ("PlatformLinux::%s() aborting creation of remote-linux platform", __FUNCTION__);
174 
175     return PlatformSP();
176 }
177 
178 ConstString
179 PlatformLinux::GetPluginNameStatic (bool is_host)
180 {
181     if (is_host)
182     {
183         static ConstString g_host_name(Platform::GetHostPlatformName ());
184         return g_host_name;
185     }
186     else
187     {
188         static ConstString g_remote_name("remote-linux");
189         return g_remote_name;
190     }
191 }
192 
193 const char *
194 PlatformLinux::GetPluginDescriptionStatic (bool is_host)
195 {
196     if (is_host)
197         return "Local Linux user platform plug-in.";
198     else
199         return "Remote Linux user platform plug-in.";
200 }
201 
202 ConstString
203 PlatformLinux::GetPluginName()
204 {
205     return GetPluginNameStatic(IsHost());
206 }
207 
208 void
209 PlatformLinux::Initialize ()
210 {
211     PlatformPOSIX::Initialize ();
212 
213     if (g_initialize_count++ == 0)
214     {
215 #if defined(__linux__) && !defined(__ANDROID__)
216         PlatformSP default_platform_sp (new PlatformLinux(true));
217         default_platform_sp->SetSystemArchitecture(HostInfo::GetArchitecture());
218         Platform::SetHostPlatform (default_platform_sp);
219 #endif
220         PluginManager::RegisterPlugin(PlatformLinux::GetPluginNameStatic(false),
221                                       PlatformLinux::GetPluginDescriptionStatic(false),
222                                       PlatformLinux::CreateInstance,
223                                       PlatformLinux::DebuggerInitialize);
224     }
225 }
226 
227 void
228 PlatformLinux::Terminate ()
229 {
230     if (g_initialize_count > 0)
231     {
232         if (--g_initialize_count == 0)
233         {
234             PluginManager::UnregisterPlugin (PlatformLinux::CreateInstance);
235         }
236     }
237 
238     PlatformPOSIX::Terminate ();
239 }
240 
241 Error
242 PlatformLinux::ResolveExecutable (const ModuleSpec &ms,
243                                   lldb::ModuleSP &exe_module_sp,
244                                   const FileSpecList *module_search_paths_ptr)
245 {
246     Error error;
247     // Nothing special to do here, just use the actual file and architecture
248 
249     char exe_path[PATH_MAX];
250     ModuleSpec resolved_module_spec (ms);
251 
252     if (IsHost())
253     {
254         // If we have "ls" as the exe_file, resolve the executable location based on
255         // the current path variables
256         if (!resolved_module_spec.GetFileSpec().Exists())
257         {
258             resolved_module_spec.GetFileSpec().GetPath(exe_path, sizeof(exe_path));
259             resolved_module_spec.GetFileSpec().SetFile(exe_path, true);
260         }
261 
262         if (!resolved_module_spec.GetFileSpec().Exists())
263             resolved_module_spec.GetFileSpec().ResolveExecutableLocation ();
264 
265         if (resolved_module_spec.GetFileSpec().Exists())
266             error.Clear();
267         else
268         {
269             error.SetErrorStringWithFormat("unable to find executable for '%s'", resolved_module_spec.GetFileSpec().GetPath().c_str());
270         }
271     }
272     else
273     {
274         if (m_remote_platform_sp)
275         {
276             error = GetCachedExecutable (resolved_module_spec, exe_module_sp, module_search_paths_ptr, *m_remote_platform_sp);
277         }
278         else
279         {
280             // We may connect to a process and use the provided executable (Don't use local $PATH).
281 
282             if (resolved_module_spec.GetFileSpec().Exists())
283                 error.Clear();
284             else
285                 error.SetErrorStringWithFormat("the platform is not currently connected, and '%s' doesn't exist in the system root.", exe_path);
286         }
287     }
288 
289     if (error.Success())
290     {
291         if (resolved_module_spec.GetArchitecture().IsValid())
292         {
293             error = ModuleList::GetSharedModule (resolved_module_spec,
294                                                  exe_module_sp,
295                                                  NULL,
296                                                  NULL,
297                                                  NULL);
298             if (error.Fail())
299             {
300                 // If we failed, it may be because the vendor and os aren't known. If that is the
301                 // case, try setting them to the host architecture and give it another try.
302                 llvm::Triple &module_triple = resolved_module_spec.GetArchitecture().GetTriple();
303                 bool is_vendor_specified = (module_triple.getVendor() != llvm::Triple::UnknownVendor);
304                 bool is_os_specified = (module_triple.getOS() != llvm::Triple::UnknownOS);
305                 if (!is_vendor_specified || !is_os_specified)
306                 {
307                     const llvm::Triple &host_triple = HostInfo::GetArchitecture(HostInfo::eArchKindDefault).GetTriple();
308 
309                     if (!is_vendor_specified)
310                         module_triple.setVendorName (host_triple.getVendorName());
311                     if (!is_os_specified)
312                         module_triple.setOSName (host_triple.getOSName());
313 
314                     error = ModuleList::GetSharedModule (resolved_module_spec,
315                                                          exe_module_sp,
316                                                          NULL,
317                                                          NULL,
318                                                          NULL);
319                 }
320             }
321 
322             // TODO find out why exe_module_sp might be NULL
323             if (!exe_module_sp || exe_module_sp->GetObjectFile() == NULL)
324             {
325                 exe_module_sp.reset();
326                 error.SetErrorStringWithFormat ("'%s' doesn't contain the architecture %s",
327                                                 resolved_module_spec.GetFileSpec().GetPath().c_str(),
328                                                 resolved_module_spec.GetArchitecture().GetArchitectureName());
329             }
330         }
331         else
332         {
333             // No valid architecture was specified, ask the platform for
334             // the architectures that we should be using (in the correct order)
335             // and see if we can find a match that way
336             StreamString arch_names;
337             for (uint32_t idx = 0; GetSupportedArchitectureAtIndex (idx, resolved_module_spec.GetArchitecture()); ++idx)
338             {
339                 error = ModuleList::GetSharedModule (resolved_module_spec,
340                                                      exe_module_sp,
341                                                      NULL,
342                                                      NULL,
343                                                      NULL);
344                 // Did we find an executable using one of the
345                 if (error.Success())
346                 {
347                     if (exe_module_sp && exe_module_sp->GetObjectFile())
348                         break;
349                     else
350                         error.SetErrorToGenericError();
351                 }
352 
353                 if (idx > 0)
354                     arch_names.PutCString (", ");
355                 arch_names.PutCString (resolved_module_spec.GetArchitecture().GetArchitectureName());
356             }
357 
358             if (error.Fail() || !exe_module_sp)
359             {
360                 if (resolved_module_spec.GetFileSpec().Readable())
361                 {
362                     error.SetErrorStringWithFormat ("'%s' doesn't contain any '%s' platform architectures: %s",
363                                                     resolved_module_spec.GetFileSpec().GetPath().c_str(),
364                                                     GetPluginName().GetCString(),
365                                                     arch_names.GetString().c_str());
366                 }
367                 else
368                 {
369                     error.SetErrorStringWithFormat("'%s' is not readable", resolved_module_spec.GetFileSpec().GetPath().c_str());
370                 }
371             }
372         }
373     }
374 
375     return error;
376 }
377 
378 Error
379 PlatformLinux::GetFileWithUUID (const FileSpec &platform_file,
380                                 const UUID *uuid_ptr, FileSpec &local_file)
381 {
382     if (IsRemote())
383     {
384         if (m_remote_platform_sp)
385             return m_remote_platform_sp->GetFileWithUUID (platform_file, uuid_ptr, local_file);
386     }
387 
388     // Default to the local case
389     local_file = platform_file;
390     return Error();
391 }
392 
393 //------------------------------------------------------------------
394 /// Default Constructor
395 //------------------------------------------------------------------
396 PlatformLinux::PlatformLinux (bool is_host) :
397     PlatformPOSIX(is_host)  // This is the local host platform
398 {
399 }
400 
401 //------------------------------------------------------------------
402 /// Destructor.
403 ///
404 /// The destructor is virtual since this class is designed to be
405 /// inherited from by the plug-in instance.
406 //------------------------------------------------------------------
407 PlatformLinux::~PlatformLinux() = default;
408 
409 bool
410 PlatformLinux::GetProcessInfo (lldb::pid_t pid, ProcessInstanceInfo &process_info)
411 {
412     bool success = false;
413     if (IsHost())
414     {
415         success = Platform::GetProcessInfo (pid, process_info);
416     }
417     else
418     {
419         if (m_remote_platform_sp)
420             success = m_remote_platform_sp->GetProcessInfo (pid, process_info);
421     }
422     return success;
423 }
424 
425 uint32_t
426 PlatformLinux::FindProcesses (const ProcessInstanceInfoMatch &match_info,
427                               ProcessInstanceInfoList &process_infos)
428 {
429     uint32_t match_count = 0;
430     if (IsHost())
431     {
432         // Let the base class figure out the host details
433         match_count = Platform::FindProcesses (match_info, process_infos);
434     }
435     else
436     {
437         // If we are remote, we can only return results if we are connected
438         if (m_remote_platform_sp)
439             match_count = m_remote_platform_sp->FindProcesses (match_info, process_infos);
440     }
441     return match_count;
442 }
443 
444 bool
445 PlatformLinux::GetSupportedArchitectureAtIndex (uint32_t idx, ArchSpec &arch)
446 {
447     if (IsHost())
448     {
449         ArchSpec hostArch = HostInfo::GetArchitecture(HostInfo::eArchKindDefault);
450         if (hostArch.GetTriple().isOSLinux())
451         {
452             if (idx == 0)
453             {
454                 arch = hostArch;
455                 return arch.IsValid();
456             }
457             else if (idx == 1)
458             {
459                 // If the default host architecture is 64-bit, look for a 32-bit variant
460                 if (hostArch.IsValid() && hostArch.GetTriple().isArch64Bit())
461                 {
462                     arch = HostInfo::GetArchitecture(HostInfo::eArchKind32);
463                     return arch.IsValid();
464                 }
465             }
466         }
467     }
468     else
469     {
470         if (m_remote_platform_sp)
471             return m_remote_platform_sp->GetSupportedArchitectureAtIndex(idx, arch);
472 
473         llvm::Triple triple;
474         // Set the OS to linux
475         triple.setOS(llvm::Triple::Linux);
476         // Set the architecture
477         switch (idx)
478         {
479             case 0: triple.setArchName("x86_64"); break;
480             case 1: triple.setArchName("i386"); break;
481             case 2: triple.setArchName("arm"); break;
482             case 3: triple.setArchName("aarch64"); break;
483             case 4: triple.setArchName("mips64"); break;
484             case 5: triple.setArchName("hexagon"); break;
485             case 6: triple.setArchName("mips"); break;
486             case 7: triple.setArchName("mips64el"); break;
487             case 8: triple.setArchName("mipsel"); break;
488             case 9: triple.setArchName("s390x"); break;
489             default: return false;
490         }
491         // Leave the vendor as "llvm::Triple:UnknownVendor" and don't specify the vendor by
492         // calling triple.SetVendorName("unknown") so that it is a "unspecified unknown".
493         // This means when someone calls triple.GetVendorName() it will return an empty string
494         // which indicates that the vendor can be set when two architectures are merged
495 
496         // Now set the triple into "arch" and return true
497         arch.SetTriple(triple);
498         return true;
499     }
500     return false;
501 }
502 
503 void
504 PlatformLinux::GetStatus (Stream &strm)
505 {
506     Platform::GetStatus(strm);
507 
508 #ifndef LLDB_DISABLE_POSIX
509     // Display local kernel information only when we are running in host mode.
510     // Otherwise, we would end up printing non-Linux information (when running
511     // on Mac OS for example).
512     if (IsHost())
513     {
514         struct utsname un;
515 
516         if (uname(&un))
517             return;
518 
519         strm.Printf ("    Kernel: %s\n", un.sysname);
520         strm.Printf ("   Release: %s\n", un.release);
521         strm.Printf ("   Version: %s\n", un.version);
522     }
523 #endif
524 }
525 
526 int32_t
527 PlatformLinux::GetResumeCountForLaunchInfo (ProcessLaunchInfo &launch_info)
528 {
529     int32_t resume_count = 0;
530 
531     // Always resume past the initial stop when we use eLaunchFlagDebug
532     if (launch_info.GetFlags ().Test (eLaunchFlagDebug))
533     {
534         // Resume past the stop for the final exec into the true inferior.
535         ++resume_count;
536     }
537 
538     // If we're not launching a shell, we're done.
539     const FileSpec &shell = launch_info.GetShell();
540     if (!shell)
541         return resume_count;
542 
543     std::string shell_string = shell.GetPath();
544     // We're in a shell, so for sure we have to resume past the shell exec.
545     ++resume_count;
546 
547     // Figure out what shell we're planning on using.
548     const char *shell_name = strrchr (shell_string.c_str(), '/');
549     if (shell_name == NULL)
550         shell_name = shell_string.c_str();
551     else
552         shell_name++;
553 
554     if (strcmp (shell_name, "csh") == 0
555              || strcmp (shell_name, "tcsh") == 0
556              || strcmp (shell_name, "zsh") == 0
557              || strcmp (shell_name, "sh") == 0)
558     {
559         // These shells seem to re-exec themselves.  Add another resume.
560         ++resume_count;
561     }
562 
563     return resume_count;
564 }
565 
566 bool
567 PlatformLinux::CanDebugProcess ()
568 {
569     if (IsHost ())
570     {
571         return true;
572     }
573     else
574     {
575         // If we're connected, we can debug.
576         return IsConnected ();
577     }
578 }
579 
580 // For local debugging, Linux will override the debug logic to use llgs-launch rather than
581 // lldb-launch, llgs-attach.  This differs from current lldb-launch, debugserver-attach
582 // approach on MacOSX.
583 lldb::ProcessSP
584 PlatformLinux::DebugProcess (ProcessLaunchInfo &launch_info,
585                              Debugger &debugger,
586                              Target *target,       // Can be NULL, if NULL create a new target, else use existing one
587                              Error &error)
588 {
589     Log *log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_PLATFORM));
590     if (log)
591         log->Printf ("PlatformLinux::%s entered (target %p)", __FUNCTION__, static_cast<void*>(target));
592 
593     // If we're a remote host, use standard behavior from parent class.
594     if (!IsHost ())
595         return PlatformPOSIX::DebugProcess (launch_info, debugger, target, error);
596 
597     //
598     // For local debugging, we'll insist on having ProcessGDBRemote create the process.
599     //
600 
601     ProcessSP process_sp;
602 
603     // Make sure we stop at the entry point
604     launch_info.GetFlags ().Set (eLaunchFlagDebug);
605 
606     // We always launch the process we are going to debug in a separate process
607     // group, since then we can handle ^C interrupts ourselves w/o having to worry
608     // about the target getting them as well.
609     launch_info.SetLaunchInSeparateProcessGroup(true);
610 
611     // Ensure we have a target.
612     if (target == nullptr)
613     {
614         if (log)
615             log->Printf ("PlatformLinux::%s creating new target", __FUNCTION__);
616 
617         TargetSP new_target_sp;
618         error = debugger.GetTargetList().CreateTarget (debugger,
619                                                        nullptr,
620                                                        nullptr,
621                                                        false,
622                                                        nullptr,
623                                                        new_target_sp);
624         if (error.Fail ())
625         {
626             if (log)
627                 log->Printf ("PlatformLinux::%s failed to create new target: %s", __FUNCTION__, error.AsCString ());
628             return process_sp;
629         }
630 
631         target = new_target_sp.get();
632         if (!target)
633         {
634             error.SetErrorString ("CreateTarget() returned nullptr");
635             if (log)
636                 log->Printf ("PlatformLinux::%s failed: %s", __FUNCTION__, error.AsCString ());
637             return process_sp;
638         }
639     }
640     else
641     {
642         if (log)
643             log->Printf ("PlatformLinux::%s using provided target", __FUNCTION__);
644     }
645 
646     // Mark target as currently selected target.
647     debugger.GetTargetList().SetSelectedTarget(target);
648 
649     // Now create the gdb-remote process.
650     if (log)
651         log->Printf ("PlatformLinux::%s having target create process with gdb-remote plugin", __FUNCTION__);
652     process_sp = target->CreateProcess (launch_info.GetListenerForProcess(debugger), "gdb-remote", nullptr);
653 
654     if (!process_sp)
655     {
656         error.SetErrorString ("CreateProcess() failed for gdb-remote process");
657         if (log)
658             log->Printf ("PlatformLinux::%s failed: %s", __FUNCTION__, error.AsCString ());
659         return process_sp;
660     }
661     else
662     {
663         if (log)
664             log->Printf ("PlatformLinux::%s successfully created process", __FUNCTION__);
665     }
666 
667     // Adjust launch for a hijacker.
668     ListenerSP listener_sp;
669     if (!launch_info.GetHijackListener ())
670     {
671         if (log)
672             log->Printf ("PlatformLinux::%s setting up hijacker", __FUNCTION__);
673 
674         listener_sp = Listener::MakeListener("lldb.PlatformLinux.DebugProcess.hijack");
675         launch_info.SetHijackListener (listener_sp);
676         process_sp->HijackProcessEvents (listener_sp);
677     }
678 
679     // Log file actions.
680     if (log)
681     {
682         log->Printf ("PlatformLinux::%s launching process with the following file actions:", __FUNCTION__);
683 
684         StreamString stream;
685         size_t i = 0;
686         const FileAction *file_action;
687         while ((file_action = launch_info.GetFileActionAtIndex (i++)) != nullptr)
688         {
689             file_action->Dump (stream);
690             log->PutCString (stream.GetString().c_str ());
691             stream.Clear();
692         }
693     }
694 
695     // Do the launch.
696     error = process_sp->Launch(launch_info);
697     if (error.Success ())
698     {
699         // Handle the hijacking of process events.
700         if (listener_sp)
701         {
702             const StateType state = process_sp->WaitForProcessToStop (NULL, NULL, false, listener_sp);
703 
704             if (state == eStateStopped)
705             {
706                 if (log)
707                     log->Printf ("PlatformLinux::%s pid %" PRIu64 " state %s\n",
708                                  __FUNCTION__, process_sp->GetID (), StateAsCString (state));
709             }
710             else
711             {
712                 if (log)
713                     log->Printf ("PlatformLinux::%s pid %" PRIu64 " state is not stopped - %s\n",
714                                  __FUNCTION__, process_sp->GetID (), StateAsCString (state));
715             }
716         }
717 
718         // Hook up process PTY if we have one (which we should for local debugging with llgs).
719         int pty_fd = launch_info.GetPTY().ReleaseMasterFileDescriptor();
720         if (pty_fd != lldb_utility::PseudoTerminal::invalid_fd)
721         {
722             process_sp->SetSTDIOFileDescriptor(pty_fd);
723             if (log)
724                 log->Printf ("PlatformLinux::%s pid %" PRIu64 " hooked up STDIO pty to process", __FUNCTION__, process_sp->GetID ());
725         }
726         else
727         {
728             if (log)
729                 log->Printf ("PlatformLinux::%s pid %" PRIu64 " not using process STDIO pty", __FUNCTION__, process_sp->GetID ());
730         }
731     }
732     else
733     {
734         if (log)
735             log->Printf ("PlatformLinux::%s process launch failed: %s", __FUNCTION__, error.AsCString ());
736         // FIXME figure out appropriate cleanup here.  Do we delete the target? Do we delete the process?  Does our caller do that?
737     }
738 
739     return process_sp;
740 }
741 
742 void
743 PlatformLinux::CalculateTrapHandlerSymbolNames ()
744 {
745     m_trap_handlers.push_back (ConstString ("_sigtramp"));
746 }
747 
748 uint64_t
749 PlatformLinux::ConvertMmapFlagsToPlatform(const ArchSpec &arch, unsigned flags)
750 {
751     uint64_t flags_platform = 0;
752     uint64_t map_anon = MAP_ANON;
753 
754     // To get correct flags for MIPS Architecture
755     if (arch.GetTriple ().getArch () == llvm::Triple::mips64
756        || arch.GetTriple ().getArch () == llvm::Triple::mips64el
757        || arch.GetTriple ().getArch () == llvm::Triple::mips
758        || arch.GetTriple ().getArch () == llvm::Triple::mipsel)
759            map_anon = 0x800;
760 
761     if (flags & eMmapFlagsPrivate)
762         flags_platform |= MAP_PRIVATE;
763     if (flags & eMmapFlagsAnon)
764         flags_platform |= map_anon;
765     return flags_platform;
766 }
767 
768 ConstString
769 PlatformLinux::GetFullNameForDylib (ConstString basename)
770 {
771     if (basename.IsEmpty())
772         return basename;
773 
774     StreamString stream;
775     stream.Printf("lib%s.so", basename.GetCString());
776     return ConstString(stream.GetData());
777 }
778