1 //===-- PlatformPOSIX.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 "PlatformPOSIX.h"
11 
12 // C Includes
13 // C++ Includes
14 // Other libraries and framework includes
15 // Project includes
16 
17 #include "lldb/Core/Debugger.h"
18 #include "lldb/Core/Module.h"
19 #include "lldb/Core/ModuleSpec.h"
20 #include "lldb/Core/ValueObject.h"
21 #include "lldb/Expression/DiagnosticManager.h"
22 #include "lldb/Expression/FunctionCaller.h"
23 #include "lldb/Expression/UserExpression.h"
24 #include "lldb/Expression/UtilityFunction.h"
25 #include "lldb/Host/File.h"
26 #include "lldb/Host/FileCache.h"
27 #include "lldb/Host/FileSystem.h"
28 #include "lldb/Host/Host.h"
29 #include "lldb/Host/HostInfo.h"
30 #include "lldb/Symbol/ClangASTContext.h"
31 #include "lldb/Target/DynamicLoader.h"
32 #include "lldb/Target/ExecutionContext.h"
33 #include "lldb/Target/Process.h"
34 #include "lldb/Target/ProcessLaunchInfo.h"
35 #include "lldb/Target/Thread.h"
36 #include "lldb/Utility/CleanUp.h"
37 #include "lldb/Utility/DataBufferHeap.h"
38 #include "lldb/Utility/FileSpec.h"
39 #include "lldb/Utility/Log.h"
40 #include "lldb/Utility/StreamString.h"
41 
42 using namespace lldb;
43 using namespace lldb_private;
44 
45 //------------------------------------------------------------------
46 /// Default Constructor
47 //------------------------------------------------------------------
48 PlatformPOSIX::PlatformPOSIX(bool is_host)
49     : Platform(is_host), // This is the local host platform
50       m_option_group_platform_rsync(new OptionGroupPlatformRSync()),
51       m_option_group_platform_ssh(new OptionGroupPlatformSSH()),
52       m_option_group_platform_caching(new OptionGroupPlatformCaching()),
53       m_remote_platform_sp() {}
54 
55 //------------------------------------------------------------------
56 /// Destructor.
57 ///
58 /// The destructor is virtual since this class is designed to be
59 /// inherited from by the plug-in instance.
60 //------------------------------------------------------------------
61 PlatformPOSIX::~PlatformPOSIX() {}
62 
63 bool PlatformPOSIX::GetModuleSpec(const FileSpec &module_file_spec,
64                                   const ArchSpec &arch,
65                                   ModuleSpec &module_spec) {
66   if (m_remote_platform_sp)
67     return m_remote_platform_sp->GetModuleSpec(module_file_spec, arch,
68                                                module_spec);
69 
70   return Platform::GetModuleSpec(module_file_spec, arch, module_spec);
71 }
72 
73 lldb_private::OptionGroupOptions *PlatformPOSIX::GetConnectionOptions(
74     lldb_private::CommandInterpreter &interpreter) {
75   auto iter = m_options.find(&interpreter), end = m_options.end();
76   if (iter == end) {
77     std::unique_ptr<lldb_private::OptionGroupOptions> options(
78         new OptionGroupOptions());
79     options->Append(m_option_group_platform_rsync.get());
80     options->Append(m_option_group_platform_ssh.get());
81     options->Append(m_option_group_platform_caching.get());
82     m_options[&interpreter] = std::move(options);
83   }
84 
85   return m_options.at(&interpreter).get();
86 }
87 
88 bool PlatformPOSIX::IsConnected() const {
89   if (IsHost())
90     return true;
91   else if (m_remote_platform_sp)
92     return m_remote_platform_sp->IsConnected();
93   return false;
94 }
95 
96 lldb_private::Status PlatformPOSIX::RunShellCommand(
97     const char *command, // Shouldn't be NULL
98     const FileSpec &
99         working_dir, // Pass empty FileSpec to use the current working directory
100     int *status_ptr, // Pass NULL if you don't want the process exit status
101     int *signo_ptr,  // Pass NULL if you don't want the signal that caused the
102                      // process to exit
103     std::string
104         *command_output, // Pass NULL if you don't want the command output
105     const Timeout<std::micro> &timeout) {
106   if (IsHost())
107     return Host::RunShellCommand(command, working_dir, status_ptr, signo_ptr,
108                                  command_output, timeout);
109   else {
110     if (m_remote_platform_sp)
111       return m_remote_platform_sp->RunShellCommand(
112           command, working_dir, status_ptr, signo_ptr, command_output, timeout);
113     else
114       return Status("unable to run a remote command without a platform");
115   }
116 }
117 
118 Status
119 PlatformPOSIX::ResolveExecutable(const ModuleSpec &module_spec,
120                                  lldb::ModuleSP &exe_module_sp,
121                                  const FileSpecList *module_search_paths_ptr) {
122   Status error;
123   // Nothing special to do here, just use the actual file and architecture
124 
125   char exe_path[PATH_MAX];
126   ModuleSpec resolved_module_spec(module_spec);
127 
128   if (IsHost()) {
129     // If we have "ls" as the exe_file, resolve the executable location based
130     // on the current path variables
131     if (!FileSystem::Instance().Exists(resolved_module_spec.GetFileSpec())) {
132       resolved_module_spec.GetFileSpec().GetPath(exe_path, sizeof(exe_path));
133       resolved_module_spec.GetFileSpec().SetFile(exe_path,
134                                                  FileSpec::Style::native);
135       FileSystem::Instance().Resolve(resolved_module_spec.GetFileSpec());
136     }
137 
138     if (!FileSystem::Instance().Exists(resolved_module_spec.GetFileSpec()))
139       FileSystem::Instance().ResolveExecutableLocation(
140           resolved_module_spec.GetFileSpec());
141 
142     // Resolve any executable within a bundle on MacOSX
143     Host::ResolveExecutableInBundle(resolved_module_spec.GetFileSpec());
144 
145     if (FileSystem::Instance().Exists(resolved_module_spec.GetFileSpec()))
146       error.Clear();
147     else {
148       const uint32_t permissions = FileSystem::Instance().GetPermissions(
149           resolved_module_spec.GetFileSpec());
150       if (permissions && (permissions & eFilePermissionsEveryoneR) == 0)
151         error.SetErrorStringWithFormat(
152             "executable '%s' is not readable",
153             resolved_module_spec.GetFileSpec().GetPath().c_str());
154       else
155         error.SetErrorStringWithFormat(
156             "unable to find executable for '%s'",
157             resolved_module_spec.GetFileSpec().GetPath().c_str());
158     }
159   } else {
160     if (m_remote_platform_sp) {
161       error =
162           GetCachedExecutable(resolved_module_spec, exe_module_sp,
163                               module_search_paths_ptr, *m_remote_platform_sp);
164     } else {
165       // We may connect to a process and use the provided executable (Don't use
166       // local $PATH).
167 
168       // Resolve any executable within a bundle on MacOSX
169       Host::ResolveExecutableInBundle(resolved_module_spec.GetFileSpec());
170 
171       if (FileSystem::Instance().Exists(resolved_module_spec.GetFileSpec()))
172         error.Clear();
173       else
174         error.SetErrorStringWithFormat("the platform is not currently "
175                                        "connected, and '%s' doesn't exist in "
176                                        "the system root.",
177                                        exe_path);
178     }
179   }
180 
181   if (error.Success()) {
182     if (resolved_module_spec.GetArchitecture().IsValid()) {
183       error = ModuleList::GetSharedModule(resolved_module_spec, exe_module_sp,
184                                           module_search_paths_ptr, nullptr, nullptr);
185       if (error.Fail()) {
186         // If we failed, it may be because the vendor and os aren't known. If
187 	// that is the case, try setting them to the host architecture and give
188 	// it another try.
189         llvm::Triple &module_triple =
190             resolved_module_spec.GetArchitecture().GetTriple();
191         bool is_vendor_specified =
192             (module_triple.getVendor() != llvm::Triple::UnknownVendor);
193         bool is_os_specified =
194             (module_triple.getOS() != llvm::Triple::UnknownOS);
195         if (!is_vendor_specified || !is_os_specified) {
196           const llvm::Triple &host_triple =
197               HostInfo::GetArchitecture(HostInfo::eArchKindDefault).GetTriple();
198 
199           if (!is_vendor_specified)
200             module_triple.setVendorName(host_triple.getVendorName());
201           if (!is_os_specified)
202             module_triple.setOSName(host_triple.getOSName());
203 
204           error = ModuleList::GetSharedModule(resolved_module_spec,
205                                               exe_module_sp, module_search_paths_ptr, nullptr, nullptr);
206         }
207       }
208 
209       // TODO find out why exe_module_sp might be NULL
210       if (error.Fail() || !exe_module_sp || !exe_module_sp->GetObjectFile()) {
211         exe_module_sp.reset();
212         error.SetErrorStringWithFormat(
213             "'%s' doesn't contain the architecture %s",
214             resolved_module_spec.GetFileSpec().GetPath().c_str(),
215             resolved_module_spec.GetArchitecture().GetArchitectureName());
216       }
217     } else {
218       // No valid architecture was specified, ask the platform for the
219       // architectures that we should be using (in the correct order) and see
220       // if we can find a match that way
221       StreamString arch_names;
222       for (uint32_t idx = 0; GetSupportedArchitectureAtIndex(
223                idx, resolved_module_spec.GetArchitecture());
224            ++idx) {
225         error = ModuleList::GetSharedModule(resolved_module_spec, exe_module_sp,
226                                             module_search_paths_ptr, nullptr, nullptr);
227         // Did we find an executable using one of the
228         if (error.Success()) {
229           if (exe_module_sp && exe_module_sp->GetObjectFile())
230             break;
231           else
232             error.SetErrorToGenericError();
233         }
234 
235         if (idx > 0)
236           arch_names.PutCString(", ");
237         arch_names.PutCString(
238             resolved_module_spec.GetArchitecture().GetArchitectureName());
239       }
240 
241       if (error.Fail() || !exe_module_sp) {
242         if (FileSystem::Instance().Readable(
243                 resolved_module_spec.GetFileSpec())) {
244           error.SetErrorStringWithFormat(
245               "'%s' doesn't contain any '%s' platform architectures: %s",
246               resolved_module_spec.GetFileSpec().GetPath().c_str(),
247               GetPluginName().GetCString(), arch_names.GetData());
248         } else {
249           error.SetErrorStringWithFormat(
250               "'%s' is not readable",
251               resolved_module_spec.GetFileSpec().GetPath().c_str());
252         }
253       }
254     }
255   }
256 
257   return error;
258 }
259 
260 Status PlatformPOSIX::GetFileWithUUID(const FileSpec &platform_file,
261                                       const UUID *uuid_ptr,
262                                       FileSpec &local_file) {
263   if (IsRemote() && m_remote_platform_sp)
264       return m_remote_platform_sp->GetFileWithUUID(platform_file, uuid_ptr,
265                                                    local_file);
266 
267   // Default to the local case
268   local_file = platform_file;
269   return Status();
270 }
271 
272 bool PlatformPOSIX::GetProcessInfo(lldb::pid_t pid,
273                                      ProcessInstanceInfo &process_info) {
274   if (IsHost())
275     return Platform::GetProcessInfo(pid, process_info);
276   if (m_remote_platform_sp)
277     return m_remote_platform_sp->GetProcessInfo(pid, process_info);
278   return false;
279 }
280 
281 uint32_t
282 PlatformPOSIX::FindProcesses(const ProcessInstanceInfoMatch &match_info,
283                                ProcessInstanceInfoList &process_infos) {
284   if (IsHost())
285     return Platform::FindProcesses(match_info, process_infos);
286   if (m_remote_platform_sp)
287     return
288       m_remote_platform_sp->FindProcesses(match_info, process_infos);
289   return 0;
290 }
291 
292 Status PlatformPOSIX::MakeDirectory(const FileSpec &file_spec,
293                                     uint32_t file_permissions) {
294   if (m_remote_platform_sp)
295     return m_remote_platform_sp->MakeDirectory(file_spec, file_permissions);
296   else
297     return Platform::MakeDirectory(file_spec, file_permissions);
298 }
299 
300 Status PlatformPOSIX::GetFilePermissions(const FileSpec &file_spec,
301                                          uint32_t &file_permissions) {
302   if (m_remote_platform_sp)
303     return m_remote_platform_sp->GetFilePermissions(file_spec,
304                                                     file_permissions);
305   else
306     return Platform::GetFilePermissions(file_spec, file_permissions);
307 }
308 
309 Status PlatformPOSIX::SetFilePermissions(const FileSpec &file_spec,
310                                          uint32_t file_permissions) {
311   if (m_remote_platform_sp)
312     return m_remote_platform_sp->SetFilePermissions(file_spec,
313                                                     file_permissions);
314   else
315     return Platform::SetFilePermissions(file_spec, file_permissions);
316 }
317 
318 lldb::user_id_t PlatformPOSIX::OpenFile(const FileSpec &file_spec,
319                                         uint32_t flags, uint32_t mode,
320                                         Status &error) {
321   if (IsHost())
322     return FileCache::GetInstance().OpenFile(file_spec, flags, mode, error);
323   else if (m_remote_platform_sp)
324     return m_remote_platform_sp->OpenFile(file_spec, flags, mode, error);
325   else
326     return Platform::OpenFile(file_spec, flags, mode, error);
327 }
328 
329 bool PlatformPOSIX::CloseFile(lldb::user_id_t fd, Status &error) {
330   if (IsHost())
331     return FileCache::GetInstance().CloseFile(fd, error);
332   else if (m_remote_platform_sp)
333     return m_remote_platform_sp->CloseFile(fd, error);
334   else
335     return Platform::CloseFile(fd, error);
336 }
337 
338 uint64_t PlatformPOSIX::ReadFile(lldb::user_id_t fd, uint64_t offset, void *dst,
339                                  uint64_t dst_len, Status &error) {
340   if (IsHost())
341     return FileCache::GetInstance().ReadFile(fd, offset, dst, dst_len, error);
342   else if (m_remote_platform_sp)
343     return m_remote_platform_sp->ReadFile(fd, offset, dst, dst_len, error);
344   else
345     return Platform::ReadFile(fd, offset, dst, dst_len, error);
346 }
347 
348 uint64_t PlatformPOSIX::WriteFile(lldb::user_id_t fd, uint64_t offset,
349                                   const void *src, uint64_t src_len,
350                                   Status &error) {
351   if (IsHost())
352     return FileCache::GetInstance().WriteFile(fd, offset, src, src_len, error);
353   else if (m_remote_platform_sp)
354     return m_remote_platform_sp->WriteFile(fd, offset, src, src_len, error);
355   else
356     return Platform::WriteFile(fd, offset, src, src_len, error);
357 }
358 
359 static uint32_t chown_file(Platform *platform, const char *path,
360                            uint32_t uid = UINT32_MAX,
361                            uint32_t gid = UINT32_MAX) {
362   if (!platform || !path || *path == 0)
363     return UINT32_MAX;
364 
365   if (uid == UINT32_MAX && gid == UINT32_MAX)
366     return 0; // pretend I did chown correctly - actually I just didn't care
367 
368   StreamString command;
369   command.PutCString("chown ");
370   if (uid != UINT32_MAX)
371     command.Printf("%d", uid);
372   if (gid != UINT32_MAX)
373     command.Printf(":%d", gid);
374   command.Printf("%s", path);
375   int status;
376   platform->RunShellCommand(command.GetData(), NULL, &status, NULL, NULL,
377                             std::chrono::seconds(10));
378   return status;
379 }
380 
381 lldb_private::Status
382 PlatformPOSIX::PutFile(const lldb_private::FileSpec &source,
383                        const lldb_private::FileSpec &destination, uint32_t uid,
384                        uint32_t gid) {
385   Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PLATFORM));
386 
387   if (IsHost()) {
388     if (FileSpec::Equal(source, destination, true))
389       return Status();
390     // cp src dst
391     // chown uid:gid dst
392     std::string src_path(source.GetPath());
393     if (src_path.empty())
394       return Status("unable to get file path for source");
395     std::string dst_path(destination.GetPath());
396     if (dst_path.empty())
397       return Status("unable to get file path for destination");
398     StreamString command;
399     command.Printf("cp %s %s", src_path.c_str(), dst_path.c_str());
400     int status;
401     RunShellCommand(command.GetData(), NULL, &status, NULL, NULL,
402                     std::chrono::seconds(10));
403     if (status != 0)
404       return Status("unable to perform copy");
405     if (uid == UINT32_MAX && gid == UINT32_MAX)
406       return Status();
407     if (chown_file(this, dst_path.c_str(), uid, gid) != 0)
408       return Status("unable to perform chown");
409     return Status();
410   } else if (m_remote_platform_sp) {
411     if (GetSupportsRSync()) {
412       std::string src_path(source.GetPath());
413       if (src_path.empty())
414         return Status("unable to get file path for source");
415       std::string dst_path(destination.GetPath());
416       if (dst_path.empty())
417         return Status("unable to get file path for destination");
418       StreamString command;
419       if (GetIgnoresRemoteHostname()) {
420         if (!GetRSyncPrefix())
421           command.Printf("rsync %s %s %s", GetRSyncOpts(), src_path.c_str(),
422                          dst_path.c_str());
423         else
424           command.Printf("rsync %s %s %s%s", GetRSyncOpts(), src_path.c_str(),
425                          GetRSyncPrefix(), dst_path.c_str());
426       } else
427         command.Printf("rsync %s %s %s:%s", GetRSyncOpts(), src_path.c_str(),
428                        GetHostname(), dst_path.c_str());
429       if (log)
430         log->Printf("[PutFile] Running command: %s\n", command.GetData());
431       int retcode;
432       Host::RunShellCommand(command.GetData(), NULL, &retcode, NULL, NULL,
433                             std::chrono::minutes(1));
434       if (retcode == 0) {
435         // Don't chown a local file for a remote system
436         //                if (chown_file(this,dst_path.c_str(),uid,gid) != 0)
437         //                    return Status("unable to perform chown");
438         return Status();
439       }
440       // if we are still here rsync has failed - let's try the slow way before
441       // giving up
442     }
443   }
444   return Platform::PutFile(source, destination, uid, gid);
445 }
446 
447 lldb::user_id_t PlatformPOSIX::GetFileSize(const FileSpec &file_spec) {
448   if (IsHost()) {
449     uint64_t Size;
450     if (llvm::sys::fs::file_size(file_spec.GetPath(), Size))
451       return 0;
452     return Size;
453   } else if (m_remote_platform_sp)
454     return m_remote_platform_sp->GetFileSize(file_spec);
455   else
456     return Platform::GetFileSize(file_spec);
457 }
458 
459 Status PlatformPOSIX::CreateSymlink(const FileSpec &src, const FileSpec &dst) {
460   if (IsHost())
461     return FileSystem::Instance().Symlink(src, dst);
462   else if (m_remote_platform_sp)
463     return m_remote_platform_sp->CreateSymlink(src, dst);
464   else
465     return Platform::CreateSymlink(src, dst);
466 }
467 
468 bool PlatformPOSIX::GetFileExists(const FileSpec &file_spec) {
469   if (IsHost())
470     return FileSystem::Instance().Exists(file_spec);
471   else if (m_remote_platform_sp)
472     return m_remote_platform_sp->GetFileExists(file_spec);
473   else
474     return Platform::GetFileExists(file_spec);
475 }
476 
477 Status PlatformPOSIX::Unlink(const FileSpec &file_spec) {
478   if (IsHost())
479     return llvm::sys::fs::remove(file_spec.GetPath());
480   else if (m_remote_platform_sp)
481     return m_remote_platform_sp->Unlink(file_spec);
482   else
483     return Platform::Unlink(file_spec);
484 }
485 
486 lldb_private::Status PlatformPOSIX::GetFile(
487     const lldb_private::FileSpec &source,      // remote file path
488     const lldb_private::FileSpec &destination) // local file path
489 {
490   Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PLATFORM));
491 
492   // Check the args, first.
493   std::string src_path(source.GetPath());
494   if (src_path.empty())
495     return Status("unable to get file path for source");
496   std::string dst_path(destination.GetPath());
497   if (dst_path.empty())
498     return Status("unable to get file path for destination");
499   if (IsHost()) {
500     if (FileSpec::Equal(source, destination, true))
501       return Status("local scenario->source and destination are the same file "
502                     "path: no operation performed");
503     // cp src dst
504     StreamString cp_command;
505     cp_command.Printf("cp %s %s", src_path.c_str(), dst_path.c_str());
506     int status;
507     RunShellCommand(cp_command.GetData(), NULL, &status, NULL, NULL,
508                     std::chrono::seconds(10));
509     if (status != 0)
510       return Status("unable to perform copy");
511     return Status();
512   } else if (m_remote_platform_sp) {
513     if (GetSupportsRSync()) {
514       StreamString command;
515       if (GetIgnoresRemoteHostname()) {
516         if (!GetRSyncPrefix())
517           command.Printf("rsync %s %s %s", GetRSyncOpts(), src_path.c_str(),
518                          dst_path.c_str());
519         else
520           command.Printf("rsync %s %s%s %s", GetRSyncOpts(), GetRSyncPrefix(),
521                          src_path.c_str(), dst_path.c_str());
522       } else
523         command.Printf("rsync %s %s:%s %s", GetRSyncOpts(),
524                        m_remote_platform_sp->GetHostname(), src_path.c_str(),
525                        dst_path.c_str());
526       if (log)
527         log->Printf("[GetFile] Running command: %s\n", command.GetData());
528       int retcode;
529       Host::RunShellCommand(command.GetData(), NULL, &retcode, NULL, NULL,
530                             std::chrono::minutes(1));
531       if (retcode == 0)
532         return Status();
533       // If we are here, rsync has failed - let's try the slow way before
534       // giving up
535     }
536     // open src and dst
537     // read/write, read/write, read/write, ...
538     // close src
539     // close dst
540     if (log)
541       log->Printf("[GetFile] Using block by block transfer....\n");
542     Status error;
543     user_id_t fd_src = OpenFile(source, File::eOpenOptionRead,
544                                 lldb::eFilePermissionsFileDefault, error);
545 
546     if (fd_src == UINT64_MAX)
547       return Status("unable to open source file");
548 
549     uint32_t permissions = 0;
550     error = GetFilePermissions(source, permissions);
551 
552     if (permissions == 0)
553       permissions = lldb::eFilePermissionsFileDefault;
554 
555     user_id_t fd_dst = FileCache::GetInstance().OpenFile(
556         destination, File::eOpenOptionCanCreate | File::eOpenOptionWrite |
557                          File::eOpenOptionTruncate,
558         permissions, error);
559 
560     if (fd_dst == UINT64_MAX) {
561       if (error.Success())
562         error.SetErrorString("unable to open destination file");
563     }
564 
565     if (error.Success()) {
566       lldb::DataBufferSP buffer_sp(new DataBufferHeap(1024, 0));
567       uint64_t offset = 0;
568       error.Clear();
569       while (error.Success()) {
570         const uint64_t n_read = ReadFile(fd_src, offset, buffer_sp->GetBytes(),
571                                          buffer_sp->GetByteSize(), error);
572         if (error.Fail())
573           break;
574         if (n_read == 0)
575           break;
576         if (FileCache::GetInstance().WriteFile(fd_dst, offset,
577                                                buffer_sp->GetBytes(), n_read,
578                                                error) != n_read) {
579           if (!error.Fail())
580             error.SetErrorString("unable to write to destination file");
581           break;
582         }
583         offset += n_read;
584       }
585     }
586     // Ignore the close error of src.
587     if (fd_src != UINT64_MAX)
588       CloseFile(fd_src, error);
589     // And close the dst file descriptot.
590     if (fd_dst != UINT64_MAX &&
591         !FileCache::GetInstance().CloseFile(fd_dst, error)) {
592       if (!error.Fail())
593         error.SetErrorString("unable to close destination file");
594     }
595     return error;
596   }
597   return Platform::GetFile(source, destination);
598 }
599 
600 std::string PlatformPOSIX::GetPlatformSpecificConnectionInformation() {
601   StreamString stream;
602   if (GetSupportsRSync()) {
603     stream.PutCString("rsync");
604     if ((GetRSyncOpts() && *GetRSyncOpts()) ||
605         (GetRSyncPrefix() && *GetRSyncPrefix()) || GetIgnoresRemoteHostname()) {
606       stream.Printf(", options: ");
607       if (GetRSyncOpts() && *GetRSyncOpts())
608         stream.Printf("'%s' ", GetRSyncOpts());
609       stream.Printf(", prefix: ");
610       if (GetRSyncPrefix() && *GetRSyncPrefix())
611         stream.Printf("'%s' ", GetRSyncPrefix());
612       if (GetIgnoresRemoteHostname())
613         stream.Printf("ignore remote-hostname ");
614     }
615   }
616   if (GetSupportsSSH()) {
617     stream.PutCString("ssh");
618     if (GetSSHOpts() && *GetSSHOpts())
619       stream.Printf(", options: '%s' ", GetSSHOpts());
620   }
621   if (GetLocalCacheDirectory() && *GetLocalCacheDirectory())
622     stream.Printf("cache dir: %s", GetLocalCacheDirectory());
623   if (stream.GetSize())
624     return stream.GetString();
625   else
626     return "";
627 }
628 
629 bool PlatformPOSIX::CalculateMD5(const FileSpec &file_spec, uint64_t &low,
630                                  uint64_t &high) {
631   if (IsHost())
632     return Platform::CalculateMD5(file_spec, low, high);
633   if (m_remote_platform_sp)
634     return m_remote_platform_sp->CalculateMD5(file_spec, low, high);
635   return false;
636 }
637 
638 const lldb::UnixSignalsSP &PlatformPOSIX::GetRemoteUnixSignals() {
639   if (IsRemote() && m_remote_platform_sp)
640     return m_remote_platform_sp->GetRemoteUnixSignals();
641   return Platform::GetRemoteUnixSignals();
642 }
643 
644 FileSpec PlatformPOSIX::GetRemoteWorkingDirectory() {
645   if (IsRemote() && m_remote_platform_sp)
646     return m_remote_platform_sp->GetRemoteWorkingDirectory();
647   else
648     return Platform::GetRemoteWorkingDirectory();
649 }
650 
651 bool PlatformPOSIX::SetRemoteWorkingDirectory(const FileSpec &working_dir) {
652   if (IsRemote() && m_remote_platform_sp)
653     return m_remote_platform_sp->SetRemoteWorkingDirectory(working_dir);
654   else
655     return Platform::SetRemoteWorkingDirectory(working_dir);
656 }
657 
658 bool PlatformPOSIX::GetRemoteOSVersion() {
659   if (m_remote_platform_sp) {
660     m_os_version = m_remote_platform_sp->GetOSVersion();
661     return !m_os_version.empty();
662   }
663   return false;
664 }
665 
666 bool PlatformPOSIX::GetRemoteOSBuildString(std::string &s) {
667   if (m_remote_platform_sp)
668     return m_remote_platform_sp->GetRemoteOSBuildString(s);
669   s.clear();
670   return false;
671 }
672 
673 Environment PlatformPOSIX::GetEnvironment() {
674   if (IsRemote()) {
675     if (m_remote_platform_sp)
676       return m_remote_platform_sp->GetEnvironment();
677     return Environment();
678   }
679   return Host::GetEnvironment();
680 }
681 
682 bool PlatformPOSIX::GetRemoteOSKernelDescription(std::string &s) {
683   if (m_remote_platform_sp)
684     return m_remote_platform_sp->GetRemoteOSKernelDescription(s);
685   s.clear();
686   return false;
687 }
688 
689 // Remote Platform subclasses need to override this function
690 ArchSpec PlatformPOSIX::GetRemoteSystemArchitecture() {
691   if (m_remote_platform_sp)
692     return m_remote_platform_sp->GetRemoteSystemArchitecture();
693   return ArchSpec();
694 }
695 
696 const char *PlatformPOSIX::GetHostname() {
697   if (IsHost())
698     return Platform::GetHostname();
699 
700   if (m_remote_platform_sp)
701     return m_remote_platform_sp->GetHostname();
702   return NULL;
703 }
704 
705 const char *PlatformPOSIX::GetUserName(uint32_t uid) {
706   // Check the cache in Platform in case we have already looked this uid up
707   const char *user_name = Platform::GetUserName(uid);
708   if (user_name)
709     return user_name;
710 
711   if (IsRemote() && m_remote_platform_sp)
712     return m_remote_platform_sp->GetUserName(uid);
713   return NULL;
714 }
715 
716 const char *PlatformPOSIX::GetGroupName(uint32_t gid) {
717   const char *group_name = Platform::GetGroupName(gid);
718   if (group_name)
719     return group_name;
720 
721   if (IsRemote() && m_remote_platform_sp)
722     return m_remote_platform_sp->GetGroupName(gid);
723   return NULL;
724 }
725 
726 Status PlatformPOSIX::ConnectRemote(Args &args) {
727   Status error;
728   if (IsHost()) {
729     error.SetErrorStringWithFormat(
730         "can't connect to the host platform '%s', always connected",
731         GetPluginName().GetCString());
732   } else {
733     if (!m_remote_platform_sp)
734       m_remote_platform_sp =
735           Platform::Create(ConstString("remote-gdb-server"), error);
736 
737     if (m_remote_platform_sp && error.Success())
738       error = m_remote_platform_sp->ConnectRemote(args);
739     else
740       error.SetErrorString("failed to create a 'remote-gdb-server' platform");
741 
742     if (error.Fail())
743       m_remote_platform_sp.reset();
744   }
745 
746   if (error.Success() && m_remote_platform_sp) {
747     if (m_option_group_platform_rsync.get() &&
748         m_option_group_platform_ssh.get() &&
749         m_option_group_platform_caching.get()) {
750       if (m_option_group_platform_rsync->m_rsync) {
751         SetSupportsRSync(true);
752         SetRSyncOpts(m_option_group_platform_rsync->m_rsync_opts.c_str());
753         SetRSyncPrefix(m_option_group_platform_rsync->m_rsync_prefix.c_str());
754         SetIgnoresRemoteHostname(
755             m_option_group_platform_rsync->m_ignores_remote_hostname);
756       }
757       if (m_option_group_platform_ssh->m_ssh) {
758         SetSupportsSSH(true);
759         SetSSHOpts(m_option_group_platform_ssh->m_ssh_opts.c_str());
760       }
761       SetLocalCacheDirectory(
762           m_option_group_platform_caching->m_cache_dir.c_str());
763     }
764   }
765 
766   return error;
767 }
768 
769 Status PlatformPOSIX::DisconnectRemote() {
770   Status error;
771 
772   if (IsHost()) {
773     error.SetErrorStringWithFormat(
774         "can't disconnect from the host platform '%s', always connected",
775         GetPluginName().GetCString());
776   } else {
777     if (m_remote_platform_sp)
778       error = m_remote_platform_sp->DisconnectRemote();
779     else
780       error.SetErrorString("the platform is not currently connected");
781   }
782   return error;
783 }
784 
785 Status PlatformPOSIX::LaunchProcess(ProcessLaunchInfo &launch_info) {
786   Status error;
787 
788   if (IsHost()) {
789     error = Platform::LaunchProcess(launch_info);
790   } else {
791     if (m_remote_platform_sp)
792       error = m_remote_platform_sp->LaunchProcess(launch_info);
793     else
794       error.SetErrorString("the platform is not currently connected");
795   }
796   return error;
797 }
798 
799 lldb_private::Status PlatformPOSIX::KillProcess(const lldb::pid_t pid) {
800   if (IsHost())
801     return Platform::KillProcess(pid);
802 
803   if (m_remote_platform_sp)
804     return m_remote_platform_sp->KillProcess(pid);
805 
806   return Status("the platform is not currently connected");
807 }
808 
809 lldb::ProcessSP PlatformPOSIX::Attach(ProcessAttachInfo &attach_info,
810                                       Debugger &debugger, Target *target,
811                                       Status &error) {
812   lldb::ProcessSP process_sp;
813   Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PLATFORM));
814 
815   if (IsHost()) {
816     if (target == NULL) {
817       TargetSP new_target_sp;
818 
819       error = debugger.GetTargetList().CreateTarget(
820           debugger, "", "", eLoadDependentsNo, NULL, new_target_sp);
821       target = new_target_sp.get();
822       if (log)
823         log->Printf("PlatformPOSIX::%s created new target", __FUNCTION__);
824     } else {
825       error.Clear();
826       if (log)
827         log->Printf("PlatformPOSIX::%s target already existed, setting target",
828                     __FUNCTION__);
829     }
830 
831     if (target && error.Success()) {
832       debugger.GetTargetList().SetSelectedTarget(target);
833       if (log) {
834         ModuleSP exe_module_sp = target->GetExecutableModule();
835         log->Printf("PlatformPOSIX::%s set selected target to %p %s",
836                     __FUNCTION__, (void *)target,
837                     exe_module_sp
838                         ? exe_module_sp->GetFileSpec().GetPath().c_str()
839                         : "<null>");
840       }
841 
842       process_sp =
843           target->CreateProcess(attach_info.GetListenerForProcess(debugger),
844                                 attach_info.GetProcessPluginName(), NULL);
845 
846       if (process_sp) {
847         ListenerSP listener_sp = attach_info.GetHijackListener();
848         if (listener_sp == nullptr) {
849           listener_sp =
850               Listener::MakeListener("lldb.PlatformPOSIX.attach.hijack");
851           attach_info.SetHijackListener(listener_sp);
852         }
853         process_sp->HijackProcessEvents(listener_sp);
854         error = process_sp->Attach(attach_info);
855       }
856     }
857   } else {
858     if (m_remote_platform_sp)
859       process_sp =
860           m_remote_platform_sp->Attach(attach_info, debugger, target, error);
861     else
862       error.SetErrorString("the platform is not currently connected");
863   }
864   return process_sp;
865 }
866 
867 lldb::ProcessSP
868 PlatformPOSIX::DebugProcess(ProcessLaunchInfo &launch_info, Debugger &debugger,
869                             Target *target, // Can be NULL, if NULL create a new
870                                             // target, else use existing one
871                             Status &error) {
872   ProcessSP process_sp;
873 
874   if (IsHost()) {
875     // We are going to hand this process off to debugserver which will be in
876     // charge of setting the exit status.  However, we still need to reap it
877     // from lldb. So, make sure we use a exit callback which does not set exit
878     // status.
879     const bool monitor_signals = false;
880     launch_info.SetMonitorProcessCallback(
881         &ProcessLaunchInfo::NoOpMonitorCallback, monitor_signals);
882     process_sp = Platform::DebugProcess(launch_info, debugger, target, error);
883   } else {
884     if (m_remote_platform_sp)
885       process_sp = m_remote_platform_sp->DebugProcess(launch_info, debugger,
886                                                       target, error);
887     else
888       error.SetErrorString("the platform is not currently connected");
889   }
890   return process_sp;
891 }
892 
893 void PlatformPOSIX::CalculateTrapHandlerSymbolNames() {
894   m_trap_handlers.push_back(ConstString("_sigtramp"));
895 }
896 
897 Status PlatformPOSIX::EvaluateLibdlExpression(
898     lldb_private::Process *process, const char *expr_cstr,
899     llvm::StringRef expr_prefix, lldb::ValueObjectSP &result_valobj_sp) {
900   DynamicLoader *loader = process->GetDynamicLoader();
901   if (loader) {
902     Status error = loader->CanLoadImage();
903     if (error.Fail())
904       return error;
905   }
906 
907   ThreadSP thread_sp(process->GetThreadList().GetExpressionExecutionThread());
908   if (!thread_sp)
909     return Status("Selected thread isn't valid");
910 
911   StackFrameSP frame_sp(thread_sp->GetStackFrameAtIndex(0));
912   if (!frame_sp)
913     return Status("Frame 0 isn't valid");
914 
915   ExecutionContext exe_ctx;
916   frame_sp->CalculateExecutionContext(exe_ctx);
917   EvaluateExpressionOptions expr_options;
918   expr_options.SetUnwindOnError(true);
919   expr_options.SetIgnoreBreakpoints(true);
920   expr_options.SetExecutionPolicy(eExecutionPolicyAlways);
921   expr_options.SetLanguage(eLanguageTypeC_plus_plus);
922   expr_options.SetTrapExceptions(false); // dlopen can't throw exceptions, so
923                                          // don't do the work to trap them.
924   expr_options.SetTimeout(std::chrono::seconds(2));
925 
926   Status expr_error;
927   ExpressionResults result =
928       UserExpression::Evaluate(exe_ctx, expr_options, expr_cstr, expr_prefix,
929                                result_valobj_sp, expr_error);
930   if (result != eExpressionCompleted)
931     return expr_error;
932 
933   if (result_valobj_sp->GetError().Fail())
934     return result_valobj_sp->GetError();
935   return Status();
936 }
937 
938 std::unique_ptr<UtilityFunction>
939 PlatformPOSIX::MakeLoadImageUtilityFunction(ExecutionContext &exe_ctx,
940                                             Status &error) {
941   // Remember to prepend this with the prefix from
942   // GetLibdlFunctionDeclarations. The returned values are all in
943   // __lldb_dlopen_result for consistency. The wrapper returns a void * but
944   // doesn't use it because UtilityFunctions don't work with void returns at
945   // present.
946   static const char *dlopen_wrapper_code = R"(
947   struct __lldb_dlopen_result {
948     void *image_ptr;
949     const char *error_str;
950   };
951 
952   extern void *memcpy(void *, const void *, size_t size);
953   extern size_t strlen(const char *);
954 
955 
956   void * __lldb_dlopen_wrapper (const char *name,
957                                 const char *path_strings,
958                                 char *buffer,
959                                 __lldb_dlopen_result *result_ptr)
960   {
961     // This is the case where the name is the full path:
962     if (!path_strings) {
963       result_ptr->image_ptr = dlopen(name, 2);
964       if (result_ptr->image_ptr)
965         result_ptr->error_str = nullptr;
966       return nullptr;
967     }
968 
969     // This is the case where we have a list of paths:
970     size_t name_len = strlen(name);
971     while (path_strings && path_strings[0] != '\0') {
972       size_t path_len = strlen(path_strings);
973       memcpy((void *) buffer, (void *) path_strings, path_len);
974       buffer[path_len] = '/';
975       char *target_ptr = buffer+path_len+1;
976       memcpy((void *) target_ptr, (void *) name, name_len + 1);
977       result_ptr->image_ptr = dlopen(buffer, 2);
978       if (result_ptr->image_ptr) {
979         result_ptr->error_str = nullptr;
980         break;
981       }
982       result_ptr->error_str = dlerror();
983       path_strings = path_strings + path_len + 1;
984     }
985     return nullptr;
986   }
987   )";
988 
989   static const char *dlopen_wrapper_name = "__lldb_dlopen_wrapper";
990   Process *process = exe_ctx.GetProcessSP().get();
991   // Insert the dlopen shim defines into our generic expression:
992   std::string expr(GetLibdlFunctionDeclarations(process));
993   expr.append(dlopen_wrapper_code);
994   Status utility_error;
995   DiagnosticManager diagnostics;
996 
997   std::unique_ptr<UtilityFunction> dlopen_utility_func_up(process
998       ->GetTarget().GetUtilityFunctionForLanguage(expr.c_str(),
999                                                   eLanguageTypeObjC,
1000                                                   dlopen_wrapper_name,
1001                                                   utility_error));
1002   if (utility_error.Fail()) {
1003     error.SetErrorStringWithFormat("dlopen error: could not make utility"
1004                                    "function: %s", utility_error.AsCString());
1005     return nullptr;
1006   }
1007   if (!dlopen_utility_func_up->Install(diagnostics, exe_ctx)) {
1008     error.SetErrorStringWithFormat("dlopen error: could not install utility"
1009                                    "function: %s",
1010                                    diagnostics.GetString().c_str());
1011     return nullptr;
1012   }
1013 
1014   Value value;
1015   ValueList arguments;
1016   FunctionCaller *do_dlopen_function = nullptr;
1017 
1018   // Fetch the clang types we will need:
1019   ClangASTContext *ast = process->GetTarget().GetScratchClangASTContext();
1020 
1021   CompilerType clang_void_pointer_type
1022       = ast->GetBasicType(eBasicTypeVoid).GetPointerType();
1023   CompilerType clang_char_pointer_type
1024         = ast->GetBasicType(eBasicTypeChar).GetPointerType();
1025 
1026   // We are passing four arguments, the basename, the list of places to look,
1027   // a buffer big enough for all the path + name combos, and
1028   // a pointer to the storage we've made for the result:
1029   value.SetValueType(Value::eValueTypeScalar);
1030   value.SetCompilerType(clang_void_pointer_type);
1031   arguments.PushValue(value);
1032   value.SetCompilerType(clang_char_pointer_type);
1033   arguments.PushValue(value);
1034   arguments.PushValue(value);
1035   arguments.PushValue(value);
1036 
1037   do_dlopen_function = dlopen_utility_func_up->MakeFunctionCaller(
1038       clang_void_pointer_type, arguments, exe_ctx.GetThreadSP(), utility_error);
1039   if (utility_error.Fail()) {
1040     error.SetErrorStringWithFormat("dlopen error: could not make function"
1041                                    "caller: %s", utility_error.AsCString());
1042     return nullptr;
1043   }
1044 
1045   do_dlopen_function = dlopen_utility_func_up->GetFunctionCaller();
1046   if (!do_dlopen_function) {
1047     error.SetErrorString("dlopen error: could not get function caller.");
1048     return nullptr;
1049   }
1050 
1051   // We made a good utility function, so cache it in the process:
1052   return dlopen_utility_func_up;
1053 }
1054 
1055 uint32_t PlatformPOSIX::DoLoadImage(lldb_private::Process *process,
1056                                     const lldb_private::FileSpec &remote_file,
1057                                     const std::vector<std::string> *paths,
1058                                     lldb_private::Status &error,
1059                                     lldb_private::FileSpec *loaded_image) {
1060   if (loaded_image)
1061     loaded_image->Clear();
1062 
1063   std::string path;
1064   path = remote_file.GetPath();
1065 
1066   ThreadSP thread_sp = process->GetThreadList().GetExpressionExecutionThread();
1067   if (!thread_sp) {
1068     error.SetErrorString("dlopen error: no thread available to call dlopen.");
1069     return LLDB_INVALID_IMAGE_TOKEN;
1070   }
1071 
1072   DiagnosticManager diagnostics;
1073 
1074   ExecutionContext exe_ctx;
1075   thread_sp->CalculateExecutionContext(exe_ctx);
1076 
1077   Status utility_error;
1078   UtilityFunction *dlopen_utility_func;
1079   ValueList arguments;
1080   FunctionCaller *do_dlopen_function = nullptr;
1081 
1082   // The UtilityFunction is held in the Process.  Platforms don't track the
1083   // lifespan of the Targets that use them, we can't put this in the Platform.
1084   dlopen_utility_func = process->GetLoadImageUtilityFunction(
1085       this, [&]() -> std::unique_ptr<UtilityFunction> {
1086         return MakeLoadImageUtilityFunction(exe_ctx, error);
1087       });
1088   // If we couldn't make it, the error will be in error, so we can exit here.
1089   if (!dlopen_utility_func)
1090     return LLDB_INVALID_IMAGE_TOKEN;
1091 
1092   do_dlopen_function = dlopen_utility_func->GetFunctionCaller();
1093   if (!do_dlopen_function) {
1094     error.SetErrorString("dlopen error: could not get function caller.");
1095     return LLDB_INVALID_IMAGE_TOKEN;
1096   }
1097   arguments = do_dlopen_function->GetArgumentValues();
1098 
1099   // Now insert the path we are searching for and the result structure into the
1100   // target.
1101   uint32_t permissions = ePermissionsReadable|ePermissionsWritable;
1102   size_t path_len = path.size() + 1;
1103   lldb::addr_t path_addr = process->AllocateMemory(path_len,
1104                                                    permissions,
1105                                                    utility_error);
1106   if (path_addr == LLDB_INVALID_ADDRESS) {
1107     error.SetErrorStringWithFormat("dlopen error: could not allocate memory"
1108                                     "for path: %s", utility_error.AsCString());
1109     return LLDB_INVALID_IMAGE_TOKEN;
1110   }
1111 
1112   // Make sure we deallocate the input string memory:
1113   CleanUp path_cleanup([process, path_addr] {
1114       process->DeallocateMemory(path_addr);
1115   });
1116 
1117   process->WriteMemory(path_addr, path.c_str(), path_len, utility_error);
1118   if (utility_error.Fail()) {
1119     error.SetErrorStringWithFormat("dlopen error: could not write path string:"
1120                                     " %s", utility_error.AsCString());
1121     return LLDB_INVALID_IMAGE_TOKEN;
1122   }
1123 
1124   // Make space for our return structure.  It is two pointers big: the token
1125   // and the error string.
1126   const uint32_t addr_size = process->GetAddressByteSize();
1127   lldb::addr_t return_addr = process->CallocateMemory(2*addr_size,
1128                                                       permissions,
1129                                                       utility_error);
1130   if (utility_error.Fail()) {
1131     error.SetErrorStringWithFormat("dlopen error: could not allocate memory"
1132                                     "for path: %s", utility_error.AsCString());
1133     return LLDB_INVALID_IMAGE_TOKEN;
1134   }
1135 
1136   // Make sure we deallocate the result structure memory
1137   CleanUp return_cleanup([process, return_addr] {
1138       process->DeallocateMemory(return_addr);
1139   });
1140 
1141   // This will be the address of the storage for paths, if we are using them,
1142   // or nullptr to signal we aren't.
1143   lldb::addr_t path_array_addr = 0x0;
1144   llvm::Optional<CleanUp> path_array_cleanup;
1145 
1146   // This is the address to a buffer large enough to hold the largest path
1147   // conjoined with the library name we're passing in.  This is a convenience
1148   // to avoid having to call malloc in the dlopen function.
1149   lldb::addr_t buffer_addr = 0x0;
1150   llvm::Optional<CleanUp> buffer_cleanup;
1151 
1152   // Set the values into our args and write them to the target:
1153   if (paths != nullptr) {
1154     // First insert the paths into the target.  This is expected to be a
1155     // continuous buffer with the strings laid out null terminated and
1156     // end to end with an empty string terminating the buffer.
1157     // We also compute the buffer's required size as we go.
1158     size_t buffer_size = 0;
1159     std::string path_array;
1160     for (auto path : *paths) {
1161       // Don't insert empty paths, they will make us abort the path
1162       // search prematurely.
1163       if (path.empty())
1164         continue;
1165       size_t path_size = path.size();
1166       path_array.append(path);
1167       path_array.push_back('\0');
1168       if (path_size > buffer_size)
1169         buffer_size = path_size;
1170     }
1171     path_array.push_back('\0');
1172 
1173     path_array_addr = process->AllocateMemory(path_array.size(),
1174                                               permissions,
1175                                               utility_error);
1176     if (path_array_addr == LLDB_INVALID_ADDRESS) {
1177       error.SetErrorStringWithFormat("dlopen error: could not allocate memory"
1178                                       "for path array: %s",
1179                                       utility_error.AsCString());
1180       return LLDB_INVALID_IMAGE_TOKEN;
1181     }
1182 
1183     // Make sure we deallocate the paths array.
1184     path_array_cleanup.emplace([process, path_array_addr] {
1185         process->DeallocateMemory(path_array_addr);
1186     });
1187 
1188     process->WriteMemory(path_array_addr, path_array.data(),
1189                          path_array.size(), utility_error);
1190 
1191     if (utility_error.Fail()) {
1192       error.SetErrorStringWithFormat("dlopen error: could not write path array:"
1193                                      " %s", utility_error.AsCString());
1194       return LLDB_INVALID_IMAGE_TOKEN;
1195     }
1196     // Now make spaces in the target for the buffer.  We need to add one for
1197     // the '/' that the utility function will insert and one for the '\0':
1198     buffer_size += path.size() + 2;
1199 
1200     buffer_addr = process->AllocateMemory(buffer_size,
1201                                           permissions,
1202                                           utility_error);
1203     if (buffer_addr == LLDB_INVALID_ADDRESS) {
1204       error.SetErrorStringWithFormat("dlopen error: could not allocate memory"
1205                                       "for buffer: %s",
1206                                       utility_error.AsCString());
1207       return LLDB_INVALID_IMAGE_TOKEN;
1208     }
1209 
1210     // Make sure we deallocate the buffer memory:
1211     buffer_cleanup.emplace([process, buffer_addr] {
1212         process->DeallocateMemory(buffer_addr);
1213     });
1214   }
1215 
1216   arguments.GetValueAtIndex(0)->GetScalar() = path_addr;
1217   arguments.GetValueAtIndex(1)->GetScalar() = path_array_addr;
1218   arguments.GetValueAtIndex(2)->GetScalar() = buffer_addr;
1219   arguments.GetValueAtIndex(3)->GetScalar() = return_addr;
1220 
1221   lldb::addr_t func_args_addr = LLDB_INVALID_ADDRESS;
1222 
1223   diagnostics.Clear();
1224   if (!do_dlopen_function->WriteFunctionArguments(exe_ctx,
1225                                                  func_args_addr,
1226                                                  arguments,
1227                                                  diagnostics)) {
1228     error.SetErrorStringWithFormat("dlopen error: could not write function "
1229                                    "arguments: %s",
1230                                    diagnostics.GetString().c_str());
1231     return LLDB_INVALID_IMAGE_TOKEN;
1232   }
1233 
1234   // Make sure we clean up the args structure.  We can't reuse it because the
1235   // Platform lives longer than the process and the Platforms don't get a
1236   // signal to clean up cached data when a process goes away.
1237   CleanUp args_cleanup([do_dlopen_function, &exe_ctx, func_args_addr] {
1238     do_dlopen_function->DeallocateFunctionResults(exe_ctx, func_args_addr);
1239   });
1240 
1241   // Now run the caller:
1242   EvaluateExpressionOptions options;
1243   options.SetExecutionPolicy(eExecutionPolicyAlways);
1244   options.SetLanguage(eLanguageTypeC_plus_plus);
1245   options.SetIgnoreBreakpoints(true);
1246   options.SetUnwindOnError(true);
1247   options.SetTrapExceptions(false); // dlopen can't throw exceptions, so
1248                                     // don't do the work to trap them.
1249   options.SetTimeout(std::chrono::seconds(2));
1250   options.SetIsForUtilityExpr(true);
1251 
1252   Value return_value;
1253   // Fetch the clang types we will need:
1254   ClangASTContext *ast = process->GetTarget().GetScratchClangASTContext();
1255 
1256   CompilerType clang_void_pointer_type
1257       = ast->GetBasicType(eBasicTypeVoid).GetPointerType();
1258 
1259   return_value.SetCompilerType(clang_void_pointer_type);
1260 
1261   ExpressionResults results = do_dlopen_function->ExecuteFunction(
1262       exe_ctx, &func_args_addr, options, diagnostics, return_value);
1263   if (results != eExpressionCompleted) {
1264     error.SetErrorStringWithFormat("dlopen error: failed executing "
1265                                    "dlopen wrapper function: %s",
1266                                    diagnostics.GetString().c_str());
1267     return LLDB_INVALID_IMAGE_TOKEN;
1268   }
1269 
1270   // Read the dlopen token from the return area:
1271   lldb::addr_t token = process->ReadPointerFromMemory(return_addr,
1272                                                       utility_error);
1273   if (utility_error.Fail()) {
1274     error.SetErrorStringWithFormat("dlopen error: could not read the return "
1275                                     "struct: %s", utility_error.AsCString());
1276     return LLDB_INVALID_IMAGE_TOKEN;
1277   }
1278 
1279   // The dlopen succeeded!
1280   if (token != 0x0) {
1281     if (loaded_image && buffer_addr != 0x0)
1282     {
1283       // Capture the image which was loaded.  We leave it in the buffer on
1284       // exit from the dlopen function, so we can just read it from there:
1285       std::string name_string;
1286       process->ReadCStringFromMemory(buffer_addr, name_string, utility_error);
1287       if (utility_error.Success())
1288         loaded_image->SetFile(name_string, llvm::sys::path::Style::posix);
1289     }
1290     return process->AddImageToken(token);
1291   }
1292 
1293   // We got an error, lets read in the error string:
1294   std::string dlopen_error_str;
1295   lldb::addr_t error_addr
1296     = process->ReadPointerFromMemory(return_addr + addr_size, utility_error);
1297   if (utility_error.Fail()) {
1298     error.SetErrorStringWithFormat("dlopen error: could not read error string: "
1299                                     "%s", utility_error.AsCString());
1300     return LLDB_INVALID_IMAGE_TOKEN;
1301   }
1302 
1303   size_t num_chars = process->ReadCStringFromMemory(error_addr + addr_size,
1304                                                     dlopen_error_str,
1305                                                     utility_error);
1306   if (utility_error.Success() && num_chars > 0)
1307     error.SetErrorStringWithFormat("dlopen error: %s",
1308                                    dlopen_error_str.c_str());
1309   else
1310     error.SetErrorStringWithFormat("dlopen failed for unknown reasons.");
1311 
1312   return LLDB_INVALID_IMAGE_TOKEN;
1313 }
1314 
1315 Status PlatformPOSIX::UnloadImage(lldb_private::Process *process,
1316                                   uint32_t image_token) {
1317   const addr_t image_addr = process->GetImagePtrFromToken(image_token);
1318   if (image_addr == LLDB_INVALID_ADDRESS)
1319     return Status("Invalid image token");
1320 
1321   StreamString expr;
1322   expr.Printf("dlclose((void *)0x%" PRIx64 ")", image_addr);
1323   llvm::StringRef prefix = GetLibdlFunctionDeclarations(process);
1324   lldb::ValueObjectSP result_valobj_sp;
1325   Status error = EvaluateLibdlExpression(process, expr.GetData(), prefix,
1326                                          result_valobj_sp);
1327   if (error.Fail())
1328     return error;
1329 
1330   if (result_valobj_sp->GetError().Fail())
1331     return result_valobj_sp->GetError();
1332 
1333   Scalar scalar;
1334   if (result_valobj_sp->ResolveValue(scalar)) {
1335     if (scalar.UInt(1))
1336       return Status("expression failed: \"%s\"", expr.GetData());
1337     process->ResetImageToken(image_token);
1338   }
1339   return Status();
1340 }
1341 
1342 lldb::ProcessSP PlatformPOSIX::ConnectProcess(llvm::StringRef connect_url,
1343                                               llvm::StringRef plugin_name,
1344                                               lldb_private::Debugger &debugger,
1345                                               lldb_private::Target *target,
1346                                               lldb_private::Status &error) {
1347   if (m_remote_platform_sp)
1348     return m_remote_platform_sp->ConnectProcess(connect_url, plugin_name,
1349                                                 debugger, target, error);
1350 
1351   return Platform::ConnectProcess(connect_url, plugin_name, debugger, target,
1352                                   error);
1353 }
1354 
1355 llvm::StringRef
1356 PlatformPOSIX::GetLibdlFunctionDeclarations(lldb_private::Process *process) {
1357   return R"(
1358               extern "C" void* dlopen(const char*, int);
1359               extern "C" void* dlsym(void*, const char*);
1360               extern "C" int   dlclose(void*);
1361               extern "C" char* dlerror(void);
1362              )";
1363 }
1364 
1365 size_t PlatformPOSIX::ConnectToWaitingProcesses(Debugger &debugger,
1366                                                 Status &error) {
1367   if (m_remote_platform_sp)
1368     return m_remote_platform_sp->ConnectToWaitingProcesses(debugger, error);
1369   return Platform::ConnectToWaitingProcesses(debugger, error);
1370 }
1371 
1372 ConstString PlatformPOSIX::GetFullNameForDylib(ConstString basename) {
1373   if (basename.IsEmpty())
1374     return basename;
1375 
1376   StreamString stream;
1377   stream.Printf("lib%s.so", basename.GetCString());
1378   return ConstString(stream.GetString());
1379 }
1380