]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm/tools/lldb/source/Plugins/Platform/POSIX/PlatformPOSIX.cpp
Update LLDB snapshot to upstream r225923 (git 2b588ecd)
[FreeBSD/FreeBSD.git] / contrib / llvm / tools / lldb / source / Plugins / Platform / POSIX / PlatformPOSIX.cpp
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/DataBufferHeap.h"
18 #include "lldb/Core/Debugger.h"
19 #include "lldb/Core/Log.h"
20 #include "lldb/Core/Module.h"
21 #include "lldb/Core/StreamString.h"
22 #include "lldb/Host/File.h"
23 #include "lldb/Host/FileCache.h"
24 #include "lldb/Host/FileSpec.h"
25 #include "lldb/Host/FileSystem.h"
26 #include "lldb/Host/Host.h"
27 #include "lldb/Target/ProcessLaunchInfo.h"
28
29 using namespace lldb;
30 using namespace lldb_private;
31
32
33 //------------------------------------------------------------------
34 /// Default Constructor
35 //------------------------------------------------------------------
36 PlatformPOSIX::PlatformPOSIX (bool is_host) :
37 Platform(is_host),  // This is the local host platform
38 m_remote_platform_sp ()
39 {
40 }
41
42 //------------------------------------------------------------------
43 /// Destructor.
44 ///
45 /// The destructor is virtual since this class is designed to be
46 /// inherited from by the plug-in instance.
47 //------------------------------------------------------------------
48 PlatformPOSIX::~PlatformPOSIX()
49 {
50 }
51
52 lldb_private::OptionGroupOptions*
53 PlatformPOSIX::GetConnectionOptions (lldb_private::CommandInterpreter& interpreter)
54 {
55     if (m_options.get() == NULL)
56     {
57         m_options.reset(new OptionGroupOptions(interpreter));
58         m_options->Append(new OptionGroupPlatformRSync());
59         m_options->Append(new OptionGroupPlatformSSH());
60         m_options->Append(new OptionGroupPlatformCaching());
61     }
62     return m_options.get();
63 }
64
65 bool
66 PlatformPOSIX::IsConnected () const
67 {
68     if (IsHost())
69         return true;
70     else if (m_remote_platform_sp)
71         return m_remote_platform_sp->IsConnected();
72     return false;
73 }
74
75 lldb_private::Error
76 PlatformPOSIX::RunShellCommand (const char *command,           // Shouldn't be NULL
77                                 const char *working_dir,       // Pass NULL to use the current working directory
78                                 int *status_ptr,               // Pass NULL if you don't want the process exit status
79                                 int *signo_ptr,                // Pass NULL if you don't want the signal that caused the process to exit
80                                 std::string *command_output,   // Pass NULL if you don't want the command output
81                                 uint32_t timeout_sec)         // Timeout in seconds to wait for shell program to finish
82 {
83     if (IsHost())
84         return Host::RunShellCommand(command, working_dir, status_ptr, signo_ptr, command_output, timeout_sec);
85     else
86     {
87         if (m_remote_platform_sp)
88             return m_remote_platform_sp->RunShellCommand(command, working_dir, status_ptr, signo_ptr, command_output, timeout_sec);
89         else
90             return Error("unable to run a remote command without a platform");
91     }
92 }
93
94 Error
95 PlatformPOSIX::MakeDirectory (const char *path, uint32_t file_permissions)
96 {
97     if (m_remote_platform_sp)
98         return m_remote_platform_sp->MakeDirectory(path, file_permissions);
99     else
100         return Platform::MakeDirectory(path ,file_permissions);
101 }
102
103 Error
104 PlatformPOSIX::GetFilePermissions (const char *path, uint32_t &file_permissions)
105 {
106     if (m_remote_platform_sp)
107         return m_remote_platform_sp->GetFilePermissions(path, file_permissions);
108     else
109         return Platform::GetFilePermissions(path ,file_permissions);
110 }
111
112 Error
113 PlatformPOSIX::SetFilePermissions (const char *path, uint32_t file_permissions)
114 {
115     if (m_remote_platform_sp)
116         return m_remote_platform_sp->SetFilePermissions(path, file_permissions);
117     else
118         return Platform::SetFilePermissions(path ,file_permissions);
119 }
120
121 lldb::user_id_t
122 PlatformPOSIX::OpenFile (const FileSpec& file_spec,
123                          uint32_t flags,
124                          uint32_t mode,
125                          Error &error)
126 {
127     if (IsHost())
128         return FileCache::GetInstance().OpenFile(file_spec, flags, mode, error);
129     else if (m_remote_platform_sp)
130         return m_remote_platform_sp->OpenFile(file_spec, flags, mode, error);
131     else
132         return Platform::OpenFile(file_spec, flags, mode, error);
133 }
134
135 bool
136 PlatformPOSIX::CloseFile (lldb::user_id_t fd, Error &error)
137 {
138     if (IsHost())
139         return FileCache::GetInstance().CloseFile(fd, error);
140     else if (m_remote_platform_sp)
141         return m_remote_platform_sp->CloseFile(fd, error);
142     else
143         return Platform::CloseFile(fd, error);
144 }
145
146 uint64_t
147 PlatformPOSIX::ReadFile (lldb::user_id_t fd,
148                          uint64_t offset,
149                          void *dst,
150                          uint64_t dst_len,
151                          Error &error)
152 {
153     if (IsHost())
154         return FileCache::GetInstance().ReadFile(fd, offset, dst, dst_len, error);
155     else if (m_remote_platform_sp)
156         return m_remote_platform_sp->ReadFile(fd, offset, dst, dst_len, error);
157     else
158         return Platform::ReadFile(fd, offset, dst, dst_len, error);
159 }
160
161 uint64_t
162 PlatformPOSIX::WriteFile (lldb::user_id_t fd,
163                           uint64_t offset,
164                           const void* src,
165                           uint64_t src_len,
166                           Error &error)
167 {
168     if (IsHost())
169         return FileCache::GetInstance().WriteFile(fd, offset, src, src_len, error);
170     else if (m_remote_platform_sp)
171         return m_remote_platform_sp->WriteFile(fd, offset, src, src_len, error);
172     else
173         return Platform::WriteFile(fd, offset, src, src_len, error);
174 }
175
176 static uint32_t
177 chown_file(Platform *platform,
178            const char* path,
179            uint32_t uid = UINT32_MAX,
180            uint32_t gid = UINT32_MAX)
181 {
182     if (!platform || !path || *path == 0)
183         return UINT32_MAX;
184     
185     if (uid == UINT32_MAX && gid == UINT32_MAX)
186         return 0;   // pretend I did chown correctly - actually I just didn't care
187     
188     StreamString command;
189     command.PutCString("chown ");
190     if (uid != UINT32_MAX)
191         command.Printf("%d",uid);
192     if (gid != UINT32_MAX)
193         command.Printf(":%d",gid);
194     command.Printf("%s",path);
195     int status;
196     platform->RunShellCommand(command.GetData(),
197                               NULL,
198                               &status,
199                               NULL,
200                               NULL,
201                               10);
202     return status;
203 }
204
205 lldb_private::Error
206 PlatformPOSIX::PutFile (const lldb_private::FileSpec& source,
207                          const lldb_private::FileSpec& destination,
208                          uint32_t uid,
209                          uint32_t gid)
210 {
211     Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PLATFORM));
212
213     if (IsHost())
214     {
215         if (FileSpec::Equal(source, destination, true))
216             return Error();
217         // cp src dst
218         // chown uid:gid dst
219         std::string src_path (source.GetPath());
220         if (src_path.empty())
221             return Error("unable to get file path for source");
222         std::string dst_path (destination.GetPath());
223         if (dst_path.empty())
224             return Error("unable to get file path for destination");
225         StreamString command;
226         command.Printf("cp %s %s", src_path.c_str(), dst_path.c_str());
227         int status;
228         RunShellCommand(command.GetData(),
229                         NULL,
230                         &status,
231                         NULL,
232                         NULL,
233                         10);
234         if (status != 0)
235             return Error("unable to perform copy");
236         if (uid == UINT32_MAX && gid == UINT32_MAX)
237             return Error();
238         if (chown_file(this,dst_path.c_str(),uid,gid) != 0)
239             return Error("unable to perform chown");
240         return Error();
241     }
242     else if (m_remote_platform_sp)
243     {
244         if (GetSupportsRSync())
245         {
246             std::string src_path (source.GetPath());
247             if (src_path.empty())
248                 return Error("unable to get file path for source");
249             std::string dst_path (destination.GetPath());
250             if (dst_path.empty())
251                 return Error("unable to get file path for destination");
252             StreamString command;
253             if (GetIgnoresRemoteHostname())
254             {
255                 if (!GetRSyncPrefix())
256                     command.Printf("rsync %s %s %s",
257                                    GetRSyncOpts(),
258                                    src_path.c_str(),
259                                    dst_path.c_str());
260                 else
261                     command.Printf("rsync %s %s %s%s",
262                                    GetRSyncOpts(),
263                                    src_path.c_str(),
264                                    GetRSyncPrefix(),
265                                    dst_path.c_str());
266             }
267             else
268                 command.Printf("rsync %s %s %s:%s",
269                                GetRSyncOpts(),
270                                src_path.c_str(),
271                                GetHostname(),
272                                dst_path.c_str());
273             if (log)
274                 log->Printf("[PutFile] Running command: %s\n", command.GetData());
275             int retcode;
276             Host::RunShellCommand(command.GetData(),
277                                   NULL,
278                                   &retcode,
279                                   NULL,
280                                   NULL,
281                                   60);
282             if (retcode == 0)
283             {
284                 // Don't chown a local file for a remote system
285 //                if (chown_file(this,dst_path.c_str(),uid,gid) != 0)
286 //                    return Error("unable to perform chown");
287                 return Error();
288             }
289             // if we are still here rsync has failed - let's try the slow way before giving up
290         }
291         
292         if (log)
293             log->Printf ("PlatformPOSIX::PutFile(src='%s', dst='%s', uid=%u, gid=%u)",
294                          source.GetPath().c_str(),
295                          destination.GetPath().c_str(),
296                          uid,
297                          gid); // REMOVE THIS PRINTF PRIOR TO CHECKIN
298         // open
299         // read, write, read, write, ...
300         // close
301         // chown uid:gid dst
302         if (log)
303             log->Printf("[PutFile] Using block by block transfer....\n");
304         
305         uint32_t source_open_options = File::eOpenOptionRead;
306         if (source.GetFileType() == FileSpec::eFileTypeSymbolicLink)
307             source_open_options |= File::eOpenoptionDontFollowSymlinks;
308
309         File source_file(source, source_open_options, lldb::eFilePermissionsUserRW);
310         Error error;
311         uint32_t permissions = source_file.GetPermissions(error);
312         if (permissions == 0)
313             permissions = lldb::eFilePermissionsFileDefault;
314
315         if (!source_file.IsValid())
316             return Error("unable to open source file");
317         lldb::user_id_t dest_file = OpenFile (destination,
318                                               File::eOpenOptionCanCreate | File::eOpenOptionWrite | File::eOpenOptionTruncate,
319                                               permissions,
320                                               error);
321         if (log)
322             log->Printf ("dest_file = %" PRIu64 "\n", dest_file);
323         if (error.Fail())
324             return error;
325         if (dest_file == UINT64_MAX)
326             return Error("unable to open target file");
327         lldb::DataBufferSP buffer_sp(new DataBufferHeap(1024, 0));
328         uint64_t offset = 0;
329         while (error.Success())
330         {
331             size_t bytes_read = buffer_sp->GetByteSize();
332             error = source_file.Read(buffer_sp->GetBytes(), bytes_read);
333             if (bytes_read)
334             {
335                 const uint64_t bytes_written = WriteFile(dest_file, offset, buffer_sp->GetBytes(), bytes_read, error);
336                 offset += bytes_written;
337                 if (bytes_written != bytes_read)
338                 {
339                     // We didn't write the correct numbe of bytes, so adjust
340                     // the file position in the source file we are reading from...
341                     source_file.SeekFromStart(offset);
342                 }
343             }
344             else
345                 break;
346         }
347         CloseFile(dest_file, error);
348         if (uid == UINT32_MAX && gid == UINT32_MAX)
349             return error;
350         // This is remopve, don't chown a local file...
351 //        std::string dst_path (destination.GetPath());
352 //        if (chown_file(this,dst_path.c_str(),uid,gid) != 0)
353 //            return Error("unable to perform chown");
354
355
356         uint64_t src_md5[2];
357         uint64_t dst_md5[2];
358
359         if (FileSystem::CalculateMD5 (source, src_md5[0], src_md5[1]) && CalculateMD5 (destination, dst_md5[0], dst_md5[1]))
360         {
361             if (src_md5[0] != dst_md5[0] || src_md5[1] != dst_md5[1])
362             {
363                 error.SetErrorString("md5 checksum of installed file doesn't match, installation failed");
364             }
365         }
366         return error;
367     }
368     return Platform::PutFile(source,destination,uid,gid);
369 }
370
371 lldb::user_id_t
372 PlatformPOSIX::GetFileSize (const FileSpec& file_spec)
373 {
374     if (IsHost())
375         return FileSystem::GetFileSize(file_spec);
376     else if (m_remote_platform_sp)
377         return m_remote_platform_sp->GetFileSize(file_spec);
378     else
379         return Platform::GetFileSize(file_spec);
380 }
381
382 Error
383 PlatformPOSIX::CreateSymlink(const char *src, const char *dst)
384 {
385     if (IsHost())
386         return FileSystem::Symlink(src, dst);
387     else if (m_remote_platform_sp)
388         return m_remote_platform_sp->CreateSymlink(src, dst);
389     else
390         return Platform::CreateSymlink(src, dst);
391 }
392
393 bool
394 PlatformPOSIX::GetFileExists (const FileSpec& file_spec)
395 {
396     if (IsHost())
397         return file_spec.Exists();
398     else if (m_remote_platform_sp)
399         return m_remote_platform_sp->GetFileExists(file_spec);
400     else
401         return Platform::GetFileExists(file_spec);
402 }
403
404 Error
405 PlatformPOSIX::Unlink (const char *path)
406 {
407     if (IsHost())
408         return FileSystem::Unlink(path);
409     else if (m_remote_platform_sp)
410         return m_remote_platform_sp->Unlink(path);
411     else
412         return Platform::Unlink(path);
413 }
414
415 lldb_private::Error
416 PlatformPOSIX::GetFile (const lldb_private::FileSpec& source /* remote file path */,
417                         const lldb_private::FileSpec& destination /* local file path */)
418 {
419     Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PLATFORM));
420
421     // Check the args, first.
422     std::string src_path (source.GetPath());
423     if (src_path.empty())
424         return Error("unable to get file path for source");
425     std::string dst_path (destination.GetPath());
426     if (dst_path.empty())
427         return Error("unable to get file path for destination");
428     if (IsHost())
429     {
430         if (FileSpec::Equal(source, destination, true))
431             return Error("local scenario->source and destination are the same file path: no operation performed");
432         // cp src dst
433         StreamString cp_command;
434         cp_command.Printf("cp %s %s", src_path.c_str(), dst_path.c_str());
435         int status;
436         RunShellCommand(cp_command.GetData(),
437                         NULL,
438                         &status,
439                         NULL,
440                         NULL,
441                         10);
442         if (status != 0)
443             return Error("unable to perform copy");
444         return Error();
445     }
446     else if (m_remote_platform_sp)
447     {
448         if (GetSupportsRSync())
449         {
450             StreamString command;
451             if (GetIgnoresRemoteHostname())
452             {
453                 if (!GetRSyncPrefix())
454                     command.Printf("rsync %s %s %s",
455                                    GetRSyncOpts(),
456                                    src_path.c_str(),
457                                    dst_path.c_str());
458                 else
459                     command.Printf("rsync %s %s%s %s",
460                                    GetRSyncOpts(),
461                                    GetRSyncPrefix(),
462                                    src_path.c_str(),
463                                    dst_path.c_str());
464             }
465             else
466                 command.Printf("rsync %s %s:%s %s",
467                                GetRSyncOpts(),
468                                m_remote_platform_sp->GetHostname(),
469                                src_path.c_str(),
470                                dst_path.c_str());
471             if (log)
472                 log->Printf("[GetFile] Running command: %s\n", command.GetData());
473             int retcode;
474             Host::RunShellCommand(command.GetData(),
475                                   NULL,
476                                   &retcode,
477                                   NULL,
478                                   NULL,
479                                   60);
480             if (retcode == 0)
481                 return Error();
482             // If we are here, rsync has failed - let's try the slow way before giving up
483         }
484         // open src and dst
485         // read/write, read/write, read/write, ...
486         // close src
487         // close dst
488         if (log)
489             log->Printf("[GetFile] Using block by block transfer....\n");
490         Error error;
491         user_id_t fd_src = OpenFile (source,
492                                      File::eOpenOptionRead,
493                                      lldb::eFilePermissionsFileDefault,
494                                      error);
495
496         if (fd_src == UINT64_MAX)
497             return Error("unable to open source file");
498
499         uint32_t permissions = 0;
500         error = GetFilePermissions(source.GetPath().c_str(), permissions);
501         
502         if (permissions == 0)
503             permissions = lldb::eFilePermissionsFileDefault;
504
505         user_id_t fd_dst = FileCache::GetInstance().OpenFile(
506             destination, File::eOpenOptionCanCreate | File::eOpenOptionWrite | File::eOpenOptionTruncate, permissions,
507             error);
508
509         if (fd_dst == UINT64_MAX)
510         {
511             if (error.Success())
512                 error.SetErrorString("unable to open destination file");
513         }
514
515         if (error.Success())
516         {
517             lldb::DataBufferSP buffer_sp(new DataBufferHeap(1024, 0));
518             uint64_t offset = 0;
519             error.Clear();
520             while (error.Success())
521             {
522                 const uint64_t n_read = ReadFile (fd_src,
523                                                   offset,
524                                                   buffer_sp->GetBytes(),
525                                                   buffer_sp->GetByteSize(),
526                                                   error);
527                 if (error.Fail())
528                     break;
529                 if (n_read == 0)
530                     break;
531                 if (FileCache::GetInstance().WriteFile(fd_dst, offset, buffer_sp->GetBytes(), n_read, error) != n_read)
532                 {
533                     if (!error.Fail())
534                         error.SetErrorString("unable to write to destination file");
535                     break;
536                 }
537                 offset += n_read;
538             }
539         }
540         // Ignore the close error of src.
541         if (fd_src != UINT64_MAX)
542             CloseFile(fd_src, error);
543         // And close the dst file descriptot.
544         if (fd_dst != UINT64_MAX && !FileCache::GetInstance().CloseFile(fd_dst, error))
545         {
546             if (!error.Fail())
547                 error.SetErrorString("unable to close destination file");
548
549         }
550         return error;
551     }
552     return Platform::GetFile(source,destination);
553 }
554
555 std::string
556 PlatformPOSIX::GetPlatformSpecificConnectionInformation()
557 {
558     StreamString stream;
559     if (GetSupportsRSync())
560     {
561         stream.PutCString("rsync");
562         if ( (GetRSyncOpts() && *GetRSyncOpts()) ||
563              (GetRSyncPrefix() && *GetRSyncPrefix()) ||
564              GetIgnoresRemoteHostname())
565         {
566             stream.Printf(", options: ");
567             if (GetRSyncOpts() && *GetRSyncOpts())
568                 stream.Printf("'%s' ",GetRSyncOpts());
569             stream.Printf(", prefix: ");
570             if (GetRSyncPrefix() && *GetRSyncPrefix())
571                 stream.Printf("'%s' ",GetRSyncPrefix());
572             if (GetIgnoresRemoteHostname())
573                 stream.Printf("ignore remote-hostname ");
574         }
575     }
576     if (GetSupportsSSH())
577     {
578         stream.PutCString("ssh");
579         if (GetSSHOpts() && *GetSSHOpts())
580             stream.Printf(", options: '%s' ",GetSSHOpts());
581     }
582     if (GetLocalCacheDirectory() && *GetLocalCacheDirectory())
583         stream.Printf("cache dir: %s",GetLocalCacheDirectory());
584     if (stream.GetSize())
585         return stream.GetData();
586     else
587         return "";
588 }
589
590 bool
591 PlatformPOSIX::CalculateMD5 (const FileSpec& file_spec,
592                             uint64_t &low,
593                             uint64_t &high)
594 {
595     if (IsHost())
596         return Platform::CalculateMD5 (file_spec, low, high);
597     if (m_remote_platform_sp)
598         return m_remote_platform_sp->CalculateMD5(file_spec, low, high);
599     return false;
600 }
601
602 lldb_private::ConstString
603 PlatformPOSIX::GetRemoteWorkingDirectory()
604 {
605     if (IsRemote() && m_remote_platform_sp)
606         return m_remote_platform_sp->GetRemoteWorkingDirectory();
607     else
608         return Platform::GetRemoteWorkingDirectory();
609 }
610
611 bool
612 PlatformPOSIX::SetRemoteWorkingDirectory(const lldb_private::ConstString &path)
613 {
614     if (IsRemote() && m_remote_platform_sp)
615         return m_remote_platform_sp->SetRemoteWorkingDirectory(path);
616     else
617         return Platform::SetRemoteWorkingDirectory(path);
618 }
619
620 bool
621 PlatformPOSIX::GetRemoteOSVersion ()
622 {
623     if (m_remote_platform_sp)
624         return m_remote_platform_sp->GetOSVersion (m_major_os_version,
625                                                    m_minor_os_version,
626                                                    m_update_os_version);
627     return false;
628 }
629
630 bool
631 PlatformPOSIX::GetRemoteOSBuildString (std::string &s)
632 {
633     if (m_remote_platform_sp)
634         return m_remote_platform_sp->GetRemoteOSBuildString (s);
635     s.clear();
636     return false;
637 }
638
639 size_t
640 PlatformPOSIX::GetEnvironment (StringList &env)
641 {
642     if (IsRemote())
643     {
644         if (m_remote_platform_sp)
645             return m_remote_platform_sp->GetEnvironment(env);
646         return 0;
647     }
648     return Host::GetEnvironment(env);
649 }
650
651 bool
652 PlatformPOSIX::GetRemoteOSKernelDescription (std::string &s)
653 {
654     if (m_remote_platform_sp)
655         return m_remote_platform_sp->GetRemoteOSKernelDescription (s);
656     s.clear();
657     return false;
658 }
659
660 // Remote Platform subclasses need to override this function
661 ArchSpec
662 PlatformPOSIX::GetRemoteSystemArchitecture ()
663 {
664     if (m_remote_platform_sp)
665         return m_remote_platform_sp->GetRemoteSystemArchitecture ();
666     return ArchSpec();
667 }
668
669 const char *
670 PlatformPOSIX::GetHostname ()
671 {
672     if (IsHost())
673         return Platform::GetHostname();
674
675     if (m_remote_platform_sp)
676         return m_remote_platform_sp->GetHostname ();
677     return NULL;
678 }
679
680 const char *
681 PlatformPOSIX::GetUserName (uint32_t uid)
682 {
683     // Check the cache in Platform in case we have already looked this uid up
684     const char *user_name = Platform::GetUserName(uid);
685     if (user_name)
686         return user_name;
687
688     if (IsRemote() && m_remote_platform_sp)
689         return m_remote_platform_sp->GetUserName(uid);
690     return NULL;
691 }
692
693 const char *
694 PlatformPOSIX::GetGroupName (uint32_t gid)
695 {
696     const char *group_name = Platform::GetGroupName(gid);
697     if (group_name)
698         return group_name;
699
700     if (IsRemote() && m_remote_platform_sp)
701         return m_remote_platform_sp->GetGroupName(gid);
702     return NULL;
703 }
704
705 Error
706 PlatformPOSIX::ConnectRemote (Args& args)
707 {
708     Error error;
709     if (IsHost())
710     {
711         error.SetErrorStringWithFormat ("can't connect to the host platform '%s', always connected", GetPluginName().GetCString());
712     }
713     else
714     {
715         if (!m_remote_platform_sp)
716             m_remote_platform_sp = Platform::Create (ConstString("remote-gdb-server"), error);
717
718         if (m_remote_platform_sp && error.Success())
719             error = m_remote_platform_sp->ConnectRemote (args);
720         else
721             error.SetErrorString ("failed to create a 'remote-gdb-server' platform");
722
723         if (error.Fail())
724             m_remote_platform_sp.reset();
725     }
726
727     if (error.Success() && m_remote_platform_sp)
728     {
729         if (m_options.get())
730         {
731             OptionGroupOptions* options = m_options.get();
732             OptionGroupPlatformRSync* m_rsync_options = (OptionGroupPlatformRSync*)options->GetGroupWithOption('r');
733             OptionGroupPlatformSSH* m_ssh_options = (OptionGroupPlatformSSH*)options->GetGroupWithOption('s');
734             OptionGroupPlatformCaching* m_cache_options = (OptionGroupPlatformCaching*)options->GetGroupWithOption('c');
735
736             if (m_rsync_options->m_rsync)
737             {
738                 SetSupportsRSync(true);
739                 SetRSyncOpts(m_rsync_options->m_rsync_opts.c_str());
740                 SetRSyncPrefix(m_rsync_options->m_rsync_prefix.c_str());
741                 SetIgnoresRemoteHostname(m_rsync_options->m_ignores_remote_hostname);
742             }
743             if (m_ssh_options->m_ssh)
744             {
745                 SetSupportsSSH(true);
746                 SetSSHOpts(m_ssh_options->m_ssh_opts.c_str());
747             }
748             SetLocalCacheDirectory(m_cache_options->m_cache_dir.c_str());
749         }
750     }
751
752     return error;
753 }
754
755 Error
756 PlatformPOSIX::DisconnectRemote ()
757 {
758     Error error;
759
760     if (IsHost())
761     {
762         error.SetErrorStringWithFormat ("can't disconnect from the host platform '%s', always connected", GetPluginName().GetCString());
763     }
764     else
765     {
766         if (m_remote_platform_sp)
767             error = m_remote_platform_sp->DisconnectRemote ();
768         else
769             error.SetErrorString ("the platform is not currently connected");
770     }
771     return error;
772 }
773
774 Error
775 PlatformPOSIX::LaunchProcess (ProcessLaunchInfo &launch_info)
776 {
777     Error error;
778
779     if (IsHost())
780     {
781         error = Platform::LaunchProcess (launch_info);
782     }
783     else
784     {
785         if (m_remote_platform_sp)
786             error = m_remote_platform_sp->LaunchProcess (launch_info);
787         else
788             error.SetErrorString ("the platform is not currently connected");
789     }
790     return error;
791 }
792
793 lldb::ProcessSP
794 PlatformPOSIX::Attach (ProcessAttachInfo &attach_info,
795                        Debugger &debugger,
796                        Target *target,
797                        Error &error)
798 {
799     lldb::ProcessSP process_sp;
800     Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PLATFORM));
801
802     if (IsHost())
803     {
804         if (target == NULL)
805         {
806             TargetSP new_target_sp;
807
808             error = debugger.GetTargetList().CreateTarget (debugger,
809                                                            NULL,
810                                                            NULL,
811                                                            false,
812                                                            NULL,
813                                                            new_target_sp);
814             target = new_target_sp.get();
815             if (log)
816                 log->Printf ("PlatformPOSIX::%s created new target", __FUNCTION__);
817         }
818         else
819         {
820             error.Clear();
821             if (log)
822                 log->Printf ("PlatformPOSIX::%s target already existed, setting target", __FUNCTION__);
823         }
824
825         if (target && error.Success())
826         {
827             debugger.GetTargetList().SetSelectedTarget(target);
828             if (log)
829             {
830                 ModuleSP exe_module_sp = target->GetExecutableModule ();
831                 log->Printf ("PlatformPOSIX::%s set selected target to %p %s", __FUNCTION__,
832                              target,
833                              exe_module_sp ? exe_module_sp->GetFileSpec().GetPath().c_str () : "<null>" );
834             }
835
836
837             process_sp = target->CreateProcess (attach_info.GetListenerForProcess(debugger), attach_info.GetProcessPluginName(), NULL);
838
839             if (process_sp)
840             {
841                 // Set UnixSignals appropriately.
842                 process_sp->SetUnixSignals (Host::GetUnixSignals ());
843
844                 ListenerSP listener_sp (new Listener("lldb.PlatformPOSIX.attach.hijack"));
845                 attach_info.SetHijackListener(listener_sp);
846                 process_sp->HijackProcessEvents(listener_sp.get());
847                 error = process_sp->Attach (attach_info);
848             }
849         }
850     }
851     else
852     {
853         if (m_remote_platform_sp)
854             process_sp = m_remote_platform_sp->Attach (attach_info, debugger, target, error);
855         else
856             error.SetErrorString ("the platform is not currently connected");
857     }
858     return process_sp;
859 }
860
861 lldb::ProcessSP
862 PlatformPOSIX::DebugProcess (ProcessLaunchInfo &launch_info,
863                               Debugger &debugger,
864                               Target *target,       // Can be NULL, if NULL create a new target, else use existing one
865                               Error &error)
866 {
867     ProcessSP process_sp;
868
869     if (IsHost())
870     {
871         // We are going to hand this process off to debugserver which will be in charge of setting the exit status.
872         // We still need to reap it from lldb but if we let the monitor thread also set the exit status, we set up a
873         // race between debugserver & us for who will find out about the debugged process's death.
874         launch_info.GetFlags().Set(eLaunchFlagDontSetExitStatus);
875         process_sp = Platform::DebugProcess (launch_info, debugger, target, error);
876     }
877     else
878     {
879         if (m_remote_platform_sp)
880             process_sp = m_remote_platform_sp->DebugProcess (launch_info, debugger, target, error);
881         else
882             error.SetErrorString ("the platform is not currently connected");
883     }
884     return process_sp;
885
886 }
887
888 void
889 PlatformPOSIX::CalculateTrapHandlerSymbolNames ()
890 {   
891     m_trap_handlers.push_back (ConstString ("_sigtramp"));
892 }