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 } 893