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