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