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             default: return false;
489         }
490         // Leave the vendor as "llvm::Triple:UnknownVendor" and don't specify the vendor by
491         // calling triple.SetVendorName("unknown") so that it is a "unspecified unknown".
492         // This means when someone calls triple.GetVendorName() it will return an empty string
493         // which indicates that the vendor can be set when two architectures are merged
494 
495         // Now set the triple into "arch" and return true
496         arch.SetTriple(triple);
497         return true;
498     }
499     return false;
500 }
501 
502 void
503 PlatformLinux::GetStatus (Stream &strm)
504 {
505     Platform::GetStatus(strm);
506 
507 #ifndef LLDB_DISABLE_POSIX
508     // Display local kernel information only when we are running in host mode.
509     // Otherwise, we would end up printing non-Linux information (when running
510     // on Mac OS for example).
511     if (IsHost())
512     {
513         struct utsname un;
514 
515         if (uname(&un))
516             return;
517 
518         strm.Printf ("    Kernel: %s\n", un.sysname);
519         strm.Printf ("   Release: %s\n", un.release);
520         strm.Printf ("   Version: %s\n", un.version);
521     }
522 #endif
523 }
524 
525 int32_t
526 PlatformLinux::GetResumeCountForLaunchInfo (ProcessLaunchInfo &launch_info)
527 {
528     int32_t resume_count = 0;
529 
530     // Always resume past the initial stop when we use eLaunchFlagDebug
531     if (launch_info.GetFlags ().Test (eLaunchFlagDebug))
532     {
533         // Resume past the stop for the final exec into the true inferior.
534         ++resume_count;
535     }
536 
537     // If we're not launching a shell, we're done.
538     const FileSpec &shell = launch_info.GetShell();
539     if (!shell)
540         return resume_count;
541 
542     std::string shell_string = shell.GetPath();
543     // We're in a shell, so for sure we have to resume past the shell exec.
544     ++resume_count;
545 
546     // Figure out what shell we're planning on using.
547     const char *shell_name = strrchr (shell_string.c_str(), '/');
548     if (shell_name == NULL)
549         shell_name = shell_string.c_str();
550     else
551         shell_name++;
552 
553     if (strcmp (shell_name, "csh") == 0
554              || strcmp (shell_name, "tcsh") == 0
555              || strcmp (shell_name, "zsh") == 0
556              || strcmp (shell_name, "sh") == 0)
557     {
558         // These shells seem to re-exec themselves.  Add another resume.
559         ++resume_count;
560     }
561 
562     return resume_count;
563 }
564 
565 bool
566 PlatformLinux::CanDebugProcess ()
567 {
568     if (IsHost ())
569     {
570         return true;
571     }
572     else
573     {
574         // If we're connected, we can debug.
575         return IsConnected ();
576     }
577 }
578 
579 // For local debugging, Linux will override the debug logic to use llgs-launch rather than
580 // lldb-launch, llgs-attach.  This differs from current lldb-launch, debugserver-attach
581 // approach on MacOSX.
582 lldb::ProcessSP
583 PlatformLinux::DebugProcess (ProcessLaunchInfo &launch_info,
584                              Debugger &debugger,
585                              Target *target,       // Can be NULL, if NULL create a new target, else use existing one
586                              Error &error)
587 {
588     Log *log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_PLATFORM));
589     if (log)
590         log->Printf ("PlatformLinux::%s entered (target %p)", __FUNCTION__, static_cast<void*>(target));
591 
592     // If we're a remote host, use standard behavior from parent class.
593     if (!IsHost ())
594         return PlatformPOSIX::DebugProcess (launch_info, debugger, target, error);
595 
596     //
597     // For local debugging, we'll insist on having ProcessGDBRemote create the process.
598     //
599 
600     ProcessSP process_sp;
601 
602     // Make sure we stop at the entry point
603     launch_info.GetFlags ().Set (eLaunchFlagDebug);
604 
605     // We always launch the process we are going to debug in a separate process
606     // group, since then we can handle ^C interrupts ourselves w/o having to worry
607     // about the target getting them as well.
608     launch_info.SetLaunchInSeparateProcessGroup(true);
609 
610     // Ensure we have a target.
611     if (target == nullptr)
612     {
613         if (log)
614             log->Printf ("PlatformLinux::%s creating new target", __FUNCTION__);
615 
616         TargetSP new_target_sp;
617         error = debugger.GetTargetList().CreateTarget (debugger,
618                                                        nullptr,
619                                                        nullptr,
620                                                        false,
621                                                        nullptr,
622                                                        new_target_sp);
623         if (error.Fail ())
624         {
625             if (log)
626                 log->Printf ("PlatformLinux::%s failed to create new target: %s", __FUNCTION__, error.AsCString ());
627             return process_sp;
628         }
629 
630         target = new_target_sp.get();
631         if (!target)
632         {
633             error.SetErrorString ("CreateTarget() returned nullptr");
634             if (log)
635                 log->Printf ("PlatformLinux::%s failed: %s", __FUNCTION__, error.AsCString ());
636             return process_sp;
637         }
638     }
639     else
640     {
641         if (log)
642             log->Printf ("PlatformLinux::%s using provided target", __FUNCTION__);
643     }
644 
645     // Mark target as currently selected target.
646     debugger.GetTargetList().SetSelectedTarget(target);
647 
648     // Now create the gdb-remote process.
649     if (log)
650         log->Printf ("PlatformLinux::%s having target create process with gdb-remote plugin", __FUNCTION__);
651     process_sp = target->CreateProcess (launch_info.GetListenerForProcess(debugger), "gdb-remote", nullptr);
652 
653     if (!process_sp)
654     {
655         error.SetErrorString ("CreateProcess() failed for gdb-remote process");
656         if (log)
657             log->Printf ("PlatformLinux::%s failed: %s", __FUNCTION__, error.AsCString ());
658         return process_sp;
659     }
660     else
661     {
662         if (log)
663             log->Printf ("PlatformLinux::%s successfully created process", __FUNCTION__);
664     }
665 
666     // Adjust launch for a hijacker.
667     ListenerSP listener_sp;
668     if (!launch_info.GetHijackListener ())
669     {
670         if (log)
671             log->Printf ("PlatformLinux::%s setting up hijacker", __FUNCTION__);
672 
673         listener_sp = Listener::MakeListener("lldb.PlatformLinux.DebugProcess.hijack");
674         launch_info.SetHijackListener (listener_sp);
675         process_sp->HijackProcessEvents (listener_sp);
676     }
677 
678     // Log file actions.
679     if (log)
680     {
681         log->Printf ("PlatformLinux::%s launching process with the following file actions:", __FUNCTION__);
682 
683         StreamString stream;
684         size_t i = 0;
685         const FileAction *file_action;
686         while ((file_action = launch_info.GetFileActionAtIndex (i++)) != nullptr)
687         {
688             file_action->Dump (stream);
689             log->PutCString (stream.GetString().c_str ());
690             stream.Clear();
691         }
692     }
693 
694     // Do the launch.
695     error = process_sp->Launch(launch_info);
696     if (error.Success ())
697     {
698         // Handle the hijacking of process events.
699         if (listener_sp)
700         {
701             const StateType state = process_sp->WaitForProcessToStop (NULL, NULL, false, listener_sp);
702 
703             if (state == eStateStopped)
704             {
705                 if (log)
706                     log->Printf ("PlatformLinux::%s pid %" PRIu64 " state %s\n",
707                                  __FUNCTION__, process_sp->GetID (), StateAsCString (state));
708             }
709             else
710             {
711                 if (log)
712                     log->Printf ("PlatformLinux::%s pid %" PRIu64 " state is not stopped - %s\n",
713                                  __FUNCTION__, process_sp->GetID (), StateAsCString (state));
714             }
715         }
716 
717         // Hook up process PTY if we have one (which we should for local debugging with llgs).
718         int pty_fd = launch_info.GetPTY().ReleaseMasterFileDescriptor();
719         if (pty_fd != lldb_utility::PseudoTerminal::invalid_fd)
720         {
721             process_sp->SetSTDIOFileDescriptor(pty_fd);
722             if (log)
723                 log->Printf ("PlatformLinux::%s pid %" PRIu64 " hooked up STDIO pty to process", __FUNCTION__, process_sp->GetID ());
724         }
725         else
726         {
727             if (log)
728                 log->Printf ("PlatformLinux::%s pid %" PRIu64 " not using process STDIO pty", __FUNCTION__, process_sp->GetID ());
729         }
730     }
731     else
732     {
733         if (log)
734             log->Printf ("PlatformLinux::%s process launch failed: %s", __FUNCTION__, error.AsCString ());
735         // FIXME figure out appropriate cleanup here.  Do we delete the target? Do we delete the process?  Does our caller do that?
736     }
737 
738     return process_sp;
739 }
740 
741 void
742 PlatformLinux::CalculateTrapHandlerSymbolNames ()
743 {
744     m_trap_handlers.push_back (ConstString ("_sigtramp"));
745 }
746 
747 uint64_t
748 PlatformLinux::ConvertMmapFlagsToPlatform(const ArchSpec &arch, unsigned flags)
749 {
750     uint64_t flags_platform = 0;
751     uint64_t map_anon = MAP_ANON;
752 
753     // To get correct flags for MIPS Architecture
754     if (arch.GetTriple ().getArch () == llvm::Triple::mips64
755        || arch.GetTriple ().getArch () == llvm::Triple::mips64el
756        || arch.GetTriple ().getArch () == llvm::Triple::mips
757        || arch.GetTriple ().getArch () == llvm::Triple::mipsel)
758            map_anon = 0x800;
759 
760     if (flags & eMmapFlagsPrivate)
761         flags_platform |= MAP_PRIVATE;
762     if (flags & eMmapFlagsAnon)
763         flags_platform |= map_anon;
764     return flags_platform;
765 }
766 
767 ConstString
768 PlatformLinux::GetFullNameForDylib (ConstString basename)
769 {
770     if (basename.IsEmpty())
771         return basename;
772 
773     StreamString stream;
774     stream.Printf("lib%s.so", basename.GetCString());
775     return ConstString(stream.GetData());
776 }
777