PlatformDarwin.cpp revision 9ce953807eb814a93b449dc243de4f7bf32c3115
1//===-- PlatformDarwin.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 "PlatformDarwin.h" 11 12// C Includes 13// C++ Includes 14// Other libraries and framework includes 15// Project includes 16#include "lldb/Breakpoint/BreakpointLocation.h" 17#include "lldb/Core/Debugger.h" 18#include "lldb/Core/Error.h" 19#include "lldb/Host/Host.h" 20#include "lldb/Target/Target.h" 21 22using namespace lldb; 23using namespace lldb_private; 24 25 26//------------------------------------------------------------------ 27/// Default Constructor 28//------------------------------------------------------------------ 29PlatformDarwin::PlatformDarwin (bool is_host) : 30 Platform(is_host), // This is the local host platform 31 m_remote_platform_sp () 32{ 33} 34 35//------------------------------------------------------------------ 36/// Destructor. 37/// 38/// The destructor is virtual since this class is designed to be 39/// inherited from by the plug-in instance. 40//------------------------------------------------------------------ 41PlatformDarwin::~PlatformDarwin() 42{ 43} 44 45 46Error 47PlatformDarwin::ResolveExecutable (const FileSpec &exe_file, 48 const ArchSpec &exe_arch, 49 lldb::ModuleSP &exe_module_sp, 50 const FileSpecList *module_search_paths_ptr) 51{ 52 Error error; 53 // Nothing special to do here, just use the actual file and architecture 54 55 char exe_path[PATH_MAX]; 56 FileSpec resolved_exe_file (exe_file); 57 58 if (IsHost()) 59 { 60 // If we have "ls" as the exe_file, resolve the executable loation based on 61 // the current path variables 62 if (!resolved_exe_file.Exists()) 63 { 64 exe_file.GetPath (exe_path, sizeof(exe_path)); 65 resolved_exe_file.SetFile(exe_path, true); 66 } 67 68 if (!resolved_exe_file.Exists()) 69 resolved_exe_file.ResolveExecutableLocation (); 70 71 // Resolve any executable within a bundle on MacOSX 72 Host::ResolveExecutableInBundle (resolved_exe_file); 73 74 if (resolved_exe_file.Exists()) 75 error.Clear(); 76 else 77 { 78 exe_file.GetPath (exe_path, sizeof(exe_path)); 79 error.SetErrorStringWithFormat ("unable to find executable for '%s'", exe_path); 80 } 81 } 82 else 83 { 84 if (m_remote_platform_sp) 85 { 86 error = m_remote_platform_sp->ResolveExecutable (exe_file, 87 exe_arch, 88 exe_module_sp, 89 module_search_paths_ptr); 90 } 91 else 92 { 93 // We may connect to a process and use the provided executable (Don't use local $PATH). 94 95 // Resolve any executable within a bundle on MacOSX 96 Host::ResolveExecutableInBundle (resolved_exe_file); 97 98 if (resolved_exe_file.Exists()) 99 error.Clear(); 100 else 101 error.SetErrorStringWithFormat("the platform is not currently connected, and '%s' doesn't exist in the system root.", resolved_exe_file.GetFilename().AsCString("")); 102 } 103 } 104 105 106 if (error.Success()) 107 { 108 if (exe_arch.IsValid()) 109 { 110 error = ModuleList::GetSharedModule (resolved_exe_file, 111 exe_arch, 112 NULL, 113 NULL, 114 0, 115 exe_module_sp, 116 module_search_paths_ptr, 117 NULL, 118 NULL); 119 120 if (exe_module_sp->GetObjectFile() == NULL) 121 { 122 exe_module_sp.reset(); 123 error.SetErrorStringWithFormat ("'%s%s%s' doesn't contain the architecture %s", 124 exe_file.GetDirectory().AsCString(""), 125 exe_file.GetDirectory() ? "/" : "", 126 exe_file.GetFilename().AsCString(""), 127 exe_arch.GetArchitectureName()); 128 } 129 } 130 else 131 { 132 // No valid architecture was specified, ask the platform for 133 // the architectures that we should be using (in the correct order) 134 // and see if we can find a match that way 135 StreamString arch_names; 136 ArchSpec platform_arch; 137 for (uint32_t idx = 0; GetSupportedArchitectureAtIndex (idx, platform_arch); ++idx) 138 { 139 error = ModuleList::GetSharedModule (resolved_exe_file, 140 platform_arch, 141 NULL, 142 NULL, 143 0, 144 exe_module_sp, 145 module_search_paths_ptr, 146 NULL, 147 NULL); 148 // Did we find an executable using one of the 149 if (error.Success()) 150 { 151 if (exe_module_sp && exe_module_sp->GetObjectFile()) 152 break; 153 else 154 error.SetErrorToGenericError(); 155 } 156 157 if (idx > 0) 158 arch_names.PutCString (", "); 159 arch_names.PutCString (platform_arch.GetArchitectureName()); 160 } 161 162 if (error.Fail() || !exe_module_sp) 163 { 164 error.SetErrorStringWithFormat ("'%s%s%s' doesn't contain any '%s' platform architectures: %s", 165 exe_file.GetDirectory().AsCString(""), 166 exe_file.GetDirectory() ? "/" : "", 167 exe_file.GetFilename().AsCString(""), 168 GetShortPluginName(), 169 arch_names.GetString().c_str()); 170 } 171 } 172 } 173 174 return error; 175} 176 177 178 179Error 180PlatformDarwin::GetSharedModule (const FileSpec &platform_file, 181 const ArchSpec &arch, 182 const UUID *uuid_ptr, 183 const ConstString *object_name_ptr, 184 off_t object_offset, 185 ModuleSP &module_sp, 186 const FileSpecList *module_search_paths_ptr, 187 ModuleSP *old_module_sp_ptr, 188 bool *did_create_ptr) 189{ 190 Error error; 191 module_sp.reset(); 192 193 if (IsRemote()) 194 { 195 // If we have a remote platform always, let it try and locate 196 // the shared module first. 197 if (m_remote_platform_sp) 198 { 199 error = m_remote_platform_sp->GetSharedModule (platform_file, 200 arch, 201 uuid_ptr, 202 object_name_ptr, 203 object_offset, 204 module_sp, 205 module_search_paths_ptr, 206 old_module_sp_ptr, 207 did_create_ptr); 208 } 209 } 210 211 if (!module_sp) 212 { 213 // Fall back to the local platform and find the file locally 214 error = Platform::GetSharedModule (platform_file, 215 arch, 216 uuid_ptr, 217 object_name_ptr, 218 object_offset, 219 module_sp, 220 module_search_paths_ptr, 221 old_module_sp_ptr, 222 did_create_ptr); 223 224 if (!module_sp && module_search_paths_ptr && platform_file) 225 { 226 // We can try to pull off part of the file path up to the bundle 227 // directory level and try any module search paths... 228 FileSpec bundle_directory; 229 if (Host::GetBundleDirectory (platform_file, bundle_directory)) 230 { 231 char platform_path[PATH_MAX]; 232 char bundle_dir[PATH_MAX]; 233 platform_file.GetPath (platform_path, sizeof(platform_path)); 234 const size_t bundle_directory_len = bundle_directory.GetPath (bundle_dir, sizeof(bundle_dir)); 235 char new_path[PATH_MAX]; 236 size_t num_module_search_paths = module_search_paths_ptr->GetSize(); 237 for (size_t i=0; i<num_module_search_paths; ++i) 238 { 239 const size_t search_path_len = module_search_paths_ptr->GetFileSpecAtIndex(i).GetPath(new_path, sizeof(new_path)); 240 if (search_path_len < sizeof(new_path)) 241 { 242 snprintf (new_path + search_path_len, sizeof(new_path) - search_path_len, "/%s", platform_path + bundle_directory_len); 243 FileSpec new_file_spec (new_path, false); 244 if (new_file_spec.Exists()) 245 { 246 Error new_error (Platform::GetSharedModule (new_file_spec, 247 arch, 248 uuid_ptr, 249 object_name_ptr, 250 object_offset, 251 module_sp, 252 NULL, 253 old_module_sp_ptr, 254 did_create_ptr)); 255 256 if (module_sp) 257 { 258 module_sp->SetPlatformFileSpec(new_file_spec); 259 return new_error; 260 } 261 } 262 } 263 } 264 } 265 } 266 } 267 if (module_sp) 268 module_sp->SetPlatformFileSpec(platform_file); 269 return error; 270} 271 272size_t 273PlatformDarwin::GetSoftwareBreakpointTrapOpcode (Target &target, BreakpointSite *bp_site) 274{ 275 const uint8_t *trap_opcode = NULL; 276 uint32_t trap_opcode_size = 0; 277 bool bp_is_thumb = false; 278 279 llvm::Triple::ArchType machine = target.GetArchitecture().GetMachine(); 280 switch (machine) 281 { 282 case llvm::Triple::x86: 283 case llvm::Triple::x86_64: 284 { 285 static const uint8_t g_i386_breakpoint_opcode[] = { 0xCC }; 286 trap_opcode = g_i386_breakpoint_opcode; 287 trap_opcode_size = sizeof(g_i386_breakpoint_opcode); 288 } 289 break; 290 291 case llvm::Triple::thumb: 292 bp_is_thumb = true; // Fall through... 293 case llvm::Triple::arm: 294 { 295 static const uint8_t g_arm_breakpoint_opcode[] = { 0xFE, 0xDE, 0xFF, 0xE7 }; 296 static const uint8_t g_thumb_breakpooint_opcode[] = { 0xFE, 0xDE }; 297 298 // Auto detect arm/thumb if it wasn't explicitly specified 299 if (!bp_is_thumb) 300 { 301 lldb::BreakpointLocationSP bp_loc_sp (bp_site->GetOwnerAtIndex (0)); 302 if (bp_loc_sp) 303 bp_is_thumb = bp_loc_sp->GetAddress().GetAddressClass () == eAddressClassCodeAlternateISA; 304 } 305 if (bp_is_thumb) 306 { 307 trap_opcode = g_thumb_breakpooint_opcode; 308 trap_opcode_size = sizeof(g_thumb_breakpooint_opcode); 309 break; 310 } 311 trap_opcode = g_arm_breakpoint_opcode; 312 trap_opcode_size = sizeof(g_arm_breakpoint_opcode); 313 } 314 break; 315 316 case llvm::Triple::ppc: 317 case llvm::Triple::ppc64: 318 { 319 static const uint8_t g_ppc_breakpoint_opcode[] = { 0x7F, 0xC0, 0x00, 0x08 }; 320 trap_opcode = g_ppc_breakpoint_opcode; 321 trap_opcode_size = sizeof(g_ppc_breakpoint_opcode); 322 } 323 break; 324 325 default: 326 assert(!"Unhandled architecture in PlatformDarwin::GetSoftwareBreakpointTrapOpcode()"); 327 break; 328 } 329 330 if (trap_opcode && trap_opcode_size) 331 { 332 if (bp_site->SetTrapOpcode(trap_opcode, trap_opcode_size)) 333 return trap_opcode_size; 334 } 335 return 0; 336 337} 338 339bool 340PlatformDarwin::GetRemoteOSVersion () 341{ 342 if (m_remote_platform_sp) 343 return m_remote_platform_sp->GetOSVersion (m_major_os_version, 344 m_minor_os_version, 345 m_update_os_version); 346 return false; 347} 348 349bool 350PlatformDarwin::GetRemoteOSBuildString (std::string &s) 351{ 352 if (m_remote_platform_sp) 353 return m_remote_platform_sp->GetRemoteOSBuildString (s); 354 s.clear(); 355 return false; 356} 357 358bool 359PlatformDarwin::GetRemoteOSKernelDescription (std::string &s) 360{ 361 if (m_remote_platform_sp) 362 return m_remote_platform_sp->GetRemoteOSKernelDescription (s); 363 s.clear(); 364 return false; 365} 366 367// Remote Platform subclasses need to override this function 368ArchSpec 369PlatformDarwin::GetRemoteSystemArchitecture () 370{ 371 if (m_remote_platform_sp) 372 return m_remote_platform_sp->GetRemoteSystemArchitecture (); 373 return ArchSpec(); 374} 375 376 377const char * 378PlatformDarwin::GetHostname () 379{ 380 if (IsHost()) 381 return Platform::GetHostname(); 382 383 if (m_remote_platform_sp) 384 return m_remote_platform_sp->GetHostname (); 385 return NULL; 386} 387 388bool 389PlatformDarwin::IsConnected () const 390{ 391 if (IsHost()) 392 return true; 393 else if (m_remote_platform_sp) 394 return m_remote_platform_sp->IsConnected(); 395 return false; 396} 397 398Error 399PlatformDarwin::ConnectRemote (Args& args) 400{ 401 Error error; 402 if (IsHost()) 403 { 404 error.SetErrorStringWithFormat ("can't connect to the host platform '%s', always connected", GetShortPluginName()); 405 } 406 else 407 { 408 if (!m_remote_platform_sp) 409 m_remote_platform_sp = Platform::Create ("remote-gdb-server", error); 410 411 if (m_remote_platform_sp) 412 { 413 if (error.Success()) 414 { 415 if (m_remote_platform_sp) 416 { 417 error = m_remote_platform_sp->ConnectRemote (args); 418 } 419 else 420 { 421 error.SetErrorString ("\"platform connect\" takes a single argument: <connect-url>"); 422 } 423 } 424 } 425 else 426 error.SetErrorString ("failed to create a 'remote-gdb-server' platform"); 427 428 if (error.Fail()) 429 m_remote_platform_sp.reset(); 430 } 431 432 return error; 433} 434 435Error 436PlatformDarwin::DisconnectRemote () 437{ 438 Error error; 439 440 if (IsHost()) 441 { 442 error.SetErrorStringWithFormat ("can't disconnect from the host platform '%s', always connected", GetShortPluginName()); 443 } 444 else 445 { 446 if (m_remote_platform_sp) 447 error = m_remote_platform_sp->DisconnectRemote (); 448 else 449 error.SetErrorString ("the platform is not currently connected"); 450 } 451 return error; 452} 453 454 455bool 456PlatformDarwin::GetProcessInfo (lldb::pid_t pid, ProcessInstanceInfo &process_info) 457{ 458 bool sucess = false; 459 if (IsHost()) 460 { 461 sucess = Platform::GetProcessInfo (pid, process_info); 462 } 463 else 464 { 465 if (m_remote_platform_sp) 466 sucess = m_remote_platform_sp->GetProcessInfo (pid, process_info); 467 } 468 return sucess; 469} 470 471 472 473uint32_t 474PlatformDarwin::FindProcesses (const ProcessInstanceInfoMatch &match_info, 475 ProcessInstanceInfoList &process_infos) 476{ 477 uint32_t match_count = 0; 478 if (IsHost()) 479 { 480 // Let the base class figure out the host details 481 match_count = Platform::FindProcesses (match_info, process_infos); 482 } 483 else 484 { 485 // If we are remote, we can only return results if we are connected 486 if (m_remote_platform_sp) 487 match_count = m_remote_platform_sp->FindProcesses (match_info, process_infos); 488 } 489 return match_count; 490} 491 492Error 493PlatformDarwin::LaunchProcess (ProcessLaunchInfo &launch_info) 494{ 495 Error error; 496 497 if (IsHost()) 498 { 499 if (launch_info.GetFlags().Test (eLaunchFlagLaunchInShell)) 500 { 501 const bool is_localhost = true; 502 if (!launch_info.ConvertArgumentsForLaunchingInShell (error, is_localhost)) 503 return error; 504 } 505 error = Platform::LaunchProcess (launch_info); 506 } 507 else 508 { 509 if (m_remote_platform_sp) 510 error = m_remote_platform_sp->LaunchProcess (launch_info); 511 else 512 error.SetErrorString ("the platform is not currently connected"); 513 } 514 return error; 515} 516 517lldb::ProcessSP 518PlatformDarwin::Attach (ProcessAttachInfo &attach_info, 519 Debugger &debugger, 520 Target *target, 521 Listener &listener, 522 Error &error) 523{ 524 lldb::ProcessSP process_sp; 525 526 if (IsHost()) 527 { 528 if (target == NULL) 529 { 530 TargetSP new_target_sp; 531 FileSpec emptyFileSpec; 532 533 error = debugger.GetTargetList().CreateTarget (debugger, 534 emptyFileSpec, 535 NULL, 536 false, 537 NULL, 538 new_target_sp); 539 target = new_target_sp.get(); 540 } 541 else 542 error.Clear(); 543 544 if (target && error.Success()) 545 { 546 debugger.GetTargetList().SetSelectedTarget(target); 547 548 process_sp = target->CreateProcess (listener, attach_info.GetProcessPluginName(), NULL); 549 550 if (process_sp) 551 error = process_sp->Attach (attach_info); 552 } 553 } 554 else 555 { 556 if (m_remote_platform_sp) 557 process_sp = m_remote_platform_sp->Attach (attach_info, debugger, target, listener, error); 558 else 559 error.SetErrorString ("the platform is not currently connected"); 560 } 561 return process_sp; 562} 563 564const char * 565PlatformDarwin::GetUserName (uint32_t uid) 566{ 567 // Check the cache in Platform in case we have already looked this uid up 568 const char *user_name = Platform::GetUserName(uid); 569 if (user_name) 570 return user_name; 571 572 if (IsRemote() && m_remote_platform_sp) 573 return m_remote_platform_sp->GetUserName(uid); 574 return NULL; 575} 576 577const char * 578PlatformDarwin::GetGroupName (uint32_t gid) 579{ 580 const char *group_name = Platform::GetGroupName(gid); 581 if (group_name) 582 return group_name; 583 584 if (IsRemote() && m_remote_platform_sp) 585 return m_remote_platform_sp->GetGroupName(gid); 586 return NULL; 587} 588 589bool 590PlatformDarwin::ModuleIsExcludedForNonModuleSpecificSearches (lldb_private::Target &target, const lldb::ModuleSP &module_sp) 591{ 592 ObjectFile *obj_file = module_sp->GetObjectFile(); 593 if (!obj_file) 594 return false; 595 596 ObjectFile::Type obj_type = obj_file->GetType(); 597 if (obj_type == ObjectFile::eTypeDynamicLinker) 598 return true; 599 else 600 return false; 601} 602 603 604// The architecture selection rules for arm processors 605// These cpu subtypes have distinct names (e.g. armv7f) but armv7 binaries run fine on an armv7f processor. 606 607bool 608PlatformDarwin::ARMGetSupportedArchitectureAtIndex (uint32_t idx, ArchSpec &arch) 609{ 610 ArchSpec system_arch (GetSystemArchitecture()); 611 const ArchSpec::Core system_core = system_arch.GetCore(); 612 switch (system_core) 613 { 614 default: 615 switch (idx) 616 { 617 case 0: arch.SetTriple ("armv7-apple-darwin", NULL); return true; 618 case 1: arch.SetTriple ("armv7f-apple-darwin", NULL); return true; 619 case 2: arch.SetTriple ("armv7k-apple-darwin", NULL); return true; 620 case 3: arch.SetTriple ("armv7s-apple-darwin", NULL); return true; 621 case 4: arch.SetTriple ("armv6-apple-darwin", NULL); return true; 622 case 5: arch.SetTriple ("armv5-apple-darwin", NULL); return true; 623 case 6: arch.SetTriple ("armv4-apple-darwin", NULL); return true; 624 case 7: arch.SetTriple ("arm-apple-darwin", NULL); return true; 625 default: break; 626 } 627 break; 628 629 case ArchSpec::eCore_arm_armv7f: 630 switch (idx) 631 { 632 case 0: arch.SetTriple ("armv7f-apple-darwin", NULL); return true; 633 case 1: arch.SetTriple ("armv7-apple-darwin", NULL); return true; 634 case 2: arch.SetTriple ("armv6-apple-darwin", NULL); return true; 635 case 3: arch.SetTriple ("armv5-apple-darwin", NULL); return true; 636 case 4: arch.SetTriple ("armv4-apple-darwin", NULL); return true; 637 case 5: arch.SetTriple ("arm-apple-darwin", NULL); return true; 638 default: break; 639 } 640 break; 641 642 case ArchSpec::eCore_arm_armv7k: 643 switch (idx) 644 { 645 case 0: arch.SetTriple ("armv7k-apple-darwin", NULL); return true; 646 case 1: arch.SetTriple ("armv7-apple-darwin", NULL); return true; 647 case 2: arch.SetTriple ("armv6-apple-darwin", NULL); return true; 648 case 3: arch.SetTriple ("armv5-apple-darwin", NULL); return true; 649 case 4: arch.SetTriple ("armv4-apple-darwin", NULL); return true; 650 case 5: arch.SetTriple ("arm-apple-darwin", NULL); return true; 651 default: break; 652 } 653 break; 654 655 case ArchSpec::eCore_arm_armv7s: 656 switch (idx) 657 { 658 case 0: arch.SetTriple ("armv7s-apple-darwin", NULL); return true; 659 case 1: arch.SetTriple ("armv7-apple-darwin", NULL); return true; 660 case 2: arch.SetTriple ("armv6-apple-darwin", NULL); return true; 661 case 3: arch.SetTriple ("armv5-apple-darwin", NULL); return true; 662 case 4: arch.SetTriple ("armv4-apple-darwin", NULL); return true; 663 case 5: arch.SetTriple ("arm-apple-darwin", NULL); return true; 664 default: break; 665 } 666 break; 667 668 case ArchSpec::eCore_arm_armv7: 669 switch (idx) 670 { 671 case 0: arch.SetTriple ("armv7-apple-darwin", NULL); return true; 672 case 1: arch.SetTriple ("armv6-apple-darwin", NULL); return true; 673 case 2: arch.SetTriple ("armv5-apple-darwin", NULL); return true; 674 case 3: arch.SetTriple ("armv4-apple-darwin", NULL); return true; 675 case 4: arch.SetTriple ("arm-apple-darwin", NULL); return true; 676 default: break; 677 } 678 break; 679 680 case ArchSpec::eCore_arm_armv6: 681 switch (idx) 682 { 683 case 0: arch.SetTriple ("armv6-apple-darwin", NULL); return true; 684 case 1: arch.SetTriple ("armv5-apple-darwin", NULL); return true; 685 case 2: arch.SetTriple ("armv4-apple-darwin", NULL); return true; 686 case 3: arch.SetTriple ("arm-apple-darwin", NULL); return true; 687 default: break; 688 } 689 break; 690 691 case ArchSpec::eCore_arm_armv5: 692 switch (idx) 693 { 694 case 0: arch.SetTriple ("armv5-apple-darwin", NULL); return true; 695 case 1: arch.SetTriple ("armv4-apple-darwin", NULL); return true; 696 case 2: arch.SetTriple ("arm-apple-darwin", NULL); return true; 697 default: break; 698 } 699 break; 700 701 case ArchSpec::eCore_arm_armv4: 702 switch (idx) 703 { 704 case 0: arch.SetTriple ("armv4-apple-darwin", NULL); return true; 705 case 1: arch.SetTriple ("arm-apple-darwin", NULL); return true; 706 default: break; 707 } 708 break; 709 } 710 arch.Clear(); 711 return false; 712} 713