PlatformDarwin.cpp revision 2d9adb73af7520bec430e0585ca40467828e6ed1
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{ 51 Error error; 52 // Nothing special to do here, just use the actual file and architecture 53 54 char exe_path[PATH_MAX]; 55 FileSpec resolved_exe_file (exe_file); 56 57 if (IsHost()) 58 { 59 // If we have "ls" as the exe_file, resolve the executable loation based on 60 // the current path variables 61 if (!resolved_exe_file.Exists()) 62 { 63 exe_file.GetPath (exe_path, sizeof(exe_path)); 64 resolved_exe_file.SetFile(exe_path, true); 65 } 66 67 if (!resolved_exe_file.Exists()) 68 resolved_exe_file.ResolveExecutableLocation (); 69 70 // Resolve any executable within a bundle on MacOSX 71 Host::ResolveExecutableInBundle (resolved_exe_file); 72 73 if (resolved_exe_file.Exists()) 74 error.Clear(); 75 else 76 { 77 exe_file.GetPath (exe_path, sizeof(exe_path)); 78 error.SetErrorStringWithFormat ("enable to find executable for '%s'", exe_path); 79 } 80 } 81 else 82 { 83 if (m_remote_platform_sp) 84 { 85 error = m_remote_platform_sp->ResolveExecutable (exe_file, 86 exe_arch, 87 exe_module_sp); 88 } 89 else 90 { 91 // We may connect to a process and use the provided executable (Don't use local $PATH). 92 93 // Resolve any executable within a bundle on MacOSX 94 Host::ResolveExecutableInBundle (resolved_exe_file); 95 96 if (resolved_exe_file.Exists()) 97 error.Clear(); 98 else 99 error.SetErrorStringWithFormat("the platform is not currently connected, and '%s' doesn't exist in the system root.", resolved_exe_file.GetFilename().AsCString("")); 100 } 101 } 102 103 104 if (error.Success()) 105 { 106 if (exe_arch.IsValid()) 107 { 108 error = ModuleList::GetSharedModule (resolved_exe_file, 109 exe_arch, 110 NULL, 111 NULL, 112 0, 113 exe_module_sp, 114 NULL, 115 NULL); 116 117 if (exe_module_sp->GetObjectFile() == NULL) 118 { 119 exe_module_sp.reset(); 120 error.SetErrorStringWithFormat ("'%s%s%s' doesn't contain the architecture %s", 121 exe_file.GetDirectory().AsCString(""), 122 exe_file.GetDirectory() ? "/" : "", 123 exe_file.GetFilename().AsCString(""), 124 exe_arch.GetArchitectureName()); 125 } 126 } 127 else 128 { 129 // No valid architecture was specified, ask the platform for 130 // the architectures that we should be using (in the correct order) 131 // and see if we can find a match that way 132 StreamString arch_names; 133 ArchSpec platform_arch; 134 for (uint32_t idx = 0; GetSupportedArchitectureAtIndex (idx, platform_arch); ++idx) 135 { 136 error = ModuleList::GetSharedModule (resolved_exe_file, 137 platform_arch, 138 NULL, 139 NULL, 140 0, 141 exe_module_sp, 142 NULL, 143 NULL); 144 // Did we find an executable using one of the 145 if (error.Success()) 146 { 147 if (exe_module_sp && exe_module_sp->GetObjectFile()) 148 break; 149 else 150 error.SetErrorToGenericError(); 151 } 152 153 if (idx > 0) 154 arch_names.PutCString (", "); 155 arch_names.PutCString (platform_arch.GetArchitectureName()); 156 } 157 158 if (error.Fail() || !exe_module_sp) 159 { 160 error.SetErrorStringWithFormat ("'%s%s%s' doesn't contain any '%s' platform architectures: %s", 161 exe_file.GetDirectory().AsCString(""), 162 exe_file.GetDirectory() ? "/" : "", 163 exe_file.GetFilename().AsCString(""), 164 GetShortPluginName(), 165 arch_names.GetString().c_str()); 166 } 167 } 168 } 169 170 return error; 171} 172 173 174size_t 175PlatformDarwin::GetSoftwareBreakpointTrapOpcode (Target &target, BreakpointSite *bp_site) 176{ 177 const uint8_t *trap_opcode = NULL; 178 uint32_t trap_opcode_size = 0; 179 bool bp_is_thumb = false; 180 181 llvm::Triple::ArchType machine = target.GetArchitecture().GetMachine(); 182 switch (machine) 183 { 184 case llvm::Triple::x86: 185 case llvm::Triple::x86_64: 186 { 187 static const uint8_t g_i386_breakpoint_opcode[] = { 0xCC }; 188 trap_opcode = g_i386_breakpoint_opcode; 189 trap_opcode_size = sizeof(g_i386_breakpoint_opcode); 190 } 191 break; 192 193 case llvm::Triple::thumb: 194 bp_is_thumb = true; // Fall through... 195 case llvm::Triple::arm: 196 { 197 static const uint8_t g_arm_breakpoint_opcode[] = { 0xFE, 0xDE, 0xFF, 0xE7 }; 198 static const uint8_t g_thumb_breakpooint_opcode[] = { 0xFE, 0xDE }; 199 200 // Auto detect arm/thumb if it wasn't explicitly specified 201 if (!bp_is_thumb) 202 { 203 lldb::BreakpointLocationSP bp_loc_sp (bp_site->GetOwnerAtIndex (0)); 204 if (bp_loc_sp) 205 bp_is_thumb = bp_loc_sp->GetAddress().GetAddressClass () == eAddressClassCodeAlternateISA; 206 } 207 if (bp_is_thumb) 208 { 209 trap_opcode = g_thumb_breakpooint_opcode; 210 trap_opcode_size = sizeof(g_thumb_breakpooint_opcode); 211 break; 212 } 213 trap_opcode = g_arm_breakpoint_opcode; 214 trap_opcode_size = sizeof(g_arm_breakpoint_opcode); 215 } 216 break; 217 218 case llvm::Triple::ppc: 219 case llvm::Triple::ppc64: 220 { 221 static const uint8_t g_ppc_breakpoint_opcode[] = { 0x7F, 0xC0, 0x00, 0x08 }; 222 trap_opcode = g_ppc_breakpoint_opcode; 223 trap_opcode_size = sizeof(g_ppc_breakpoint_opcode); 224 } 225 break; 226 227 default: 228 assert(!"Unhandled architecture in PlatformDarwin::GetSoftwareBreakpointTrapOpcode()"); 229 break; 230 } 231 232 if (trap_opcode && trap_opcode_size) 233 { 234 if (bp_site->SetTrapOpcode(trap_opcode, trap_opcode_size)) 235 return trap_opcode_size; 236 } 237 return 0; 238 239} 240 241bool 242PlatformDarwin::GetRemoteOSVersion () 243{ 244 if (m_remote_platform_sp) 245 return m_remote_platform_sp->GetOSVersion (m_major_os_version, 246 m_minor_os_version, 247 m_update_os_version); 248 return false; 249} 250 251bool 252PlatformDarwin::GetRemoteOSBuildString (std::string &s) 253{ 254 if (m_remote_platform_sp) 255 return m_remote_platform_sp->GetRemoteOSBuildString (s); 256 s.clear(); 257 return false; 258} 259 260bool 261PlatformDarwin::GetRemoteOSKernelDescription (std::string &s) 262{ 263 if (m_remote_platform_sp) 264 return m_remote_platform_sp->GetRemoteOSKernelDescription (s); 265 s.clear(); 266 return false; 267} 268 269// Remote Platform subclasses need to override this function 270ArchSpec 271PlatformDarwin::GetRemoteSystemArchitecture () 272{ 273 if (m_remote_platform_sp) 274 return m_remote_platform_sp->GetRemoteSystemArchitecture (); 275 return ArchSpec(); 276} 277 278 279const char * 280PlatformDarwin::GetHostname () 281{ 282 if (IsHost()) 283 return Platform::GetHostname(); 284 285 if (m_remote_platform_sp) 286 return m_remote_platform_sp->GetHostname (); 287 return NULL; 288} 289 290bool 291PlatformDarwin::IsConnected () const 292{ 293 if (IsHost()) 294 return true; 295 else if (m_remote_platform_sp) 296 return m_remote_platform_sp->IsConnected(); 297 return false; 298} 299 300Error 301PlatformDarwin::ConnectRemote (Args& args) 302{ 303 Error error; 304 if (IsHost()) 305 { 306 error.SetErrorStringWithFormat ("can't connect to the host platform '%s', always connected", GetShortPluginName()); 307 } 308 else 309 { 310 if (!m_remote_platform_sp) 311 m_remote_platform_sp = Platform::Create ("remote-gdb-server", error); 312 313 if (m_remote_platform_sp) 314 { 315 if (error.Success()) 316 { 317 if (m_remote_platform_sp) 318 { 319 error = m_remote_platform_sp->ConnectRemote (args); 320 } 321 else 322 { 323 error.SetErrorString ("\"platform connect\" takes a single argument: <connect-url>"); 324 } 325 } 326 } 327 else 328 error.SetErrorString ("failed to create a 'remote-gdb-server' platform"); 329 330 if (error.Fail()) 331 m_remote_platform_sp.reset(); 332 } 333 334 return error; 335} 336 337Error 338PlatformDarwin::DisconnectRemote () 339{ 340 Error error; 341 342 if (IsHost()) 343 { 344 error.SetErrorStringWithFormat ("can't disconnect from the host platform '%s', always connected", GetShortPluginName()); 345 } 346 else 347 { 348 if (m_remote_platform_sp) 349 error = m_remote_platform_sp->DisconnectRemote (); 350 else 351 error.SetErrorString ("the platform is not currently connected"); 352 } 353 return error; 354} 355 356 357bool 358PlatformDarwin::GetProcessInfo (lldb::pid_t pid, ProcessInstanceInfo &process_info) 359{ 360 bool sucess = false; 361 if (IsHost()) 362 { 363 sucess = Platform::GetProcessInfo (pid, process_info); 364 } 365 else 366 { 367 if (m_remote_platform_sp) 368 sucess = m_remote_platform_sp->GetProcessInfo (pid, process_info); 369 } 370 return sucess; 371} 372 373 374 375uint32_t 376PlatformDarwin::FindProcesses (const ProcessInstanceInfoMatch &match_info, 377 ProcessInstanceInfoList &process_infos) 378{ 379 uint32_t match_count = 0; 380 if (IsHost()) 381 { 382 // Let the base class figure out the host details 383 match_count = Platform::FindProcesses (match_info, process_infos); 384 } 385 else 386 { 387 // If we are remote, we can only return results if we are connected 388 if (m_remote_platform_sp) 389 match_count = m_remote_platform_sp->FindProcesses (match_info, process_infos); 390 } 391 return match_count; 392} 393 394Error 395PlatformDarwin::LaunchProcess (ProcessLaunchInfo &launch_info) 396{ 397 Error error; 398 if (IsHost()) 399 { 400 error = Platform::LaunchProcess (launch_info); 401 } 402 else 403 { 404 if (m_remote_platform_sp) 405 error = m_remote_platform_sp->LaunchProcess (launch_info); 406 else 407 error.SetErrorString ("the platform is not currently connected"); 408 } 409 return error; 410} 411 412lldb::ProcessSP 413PlatformDarwin::Attach (lldb::pid_t pid, 414 Debugger &debugger, 415 Target *target, 416 Listener &listener, 417 Error &error) 418{ 419 lldb::ProcessSP process_sp; 420 if (IsHost()) 421 { 422 if (target == NULL) 423 { 424 TargetSP new_target_sp; 425 FileSpec emptyFileSpec; 426 427 error = debugger.GetTargetList().CreateTarget (debugger, 428 emptyFileSpec, 429 NULL, 430 false, 431 NULL, 432 new_target_sp); 433 target = new_target_sp.get(); 434 } 435 else 436 error.Clear(); 437 438 if (target && error.Success()) 439 { 440 debugger.GetTargetList().SetSelectedTarget(target); 441 // The darwin always currently uses the GDB remote debugger plug-in 442 // so even when debugging locally we are debugging remotely! 443 process_sp = target->CreateProcess (listener, "gdb-remote"); 444 445 if (process_sp) 446 error = process_sp->Attach (pid, 2); 447 } 448 } 449 else 450 { 451 if (m_remote_platform_sp) 452 process_sp = m_remote_platform_sp->Attach (pid, debugger, target, listener, error); 453 else 454 error.SetErrorString ("the platform is not currently connected"); 455 } 456 return process_sp; 457} 458 459const char * 460PlatformDarwin::GetUserName (uint32_t uid) 461{ 462 // Check the cache in Platform in case we have already looked this uid up 463 const char *user_name = Platform::GetUserName(uid); 464 if (user_name) 465 return user_name; 466 467 if (IsRemote() && m_remote_platform_sp) 468 return m_remote_platform_sp->GetUserName(uid); 469 return NULL; 470} 471 472const char * 473PlatformDarwin::GetGroupName (uint32_t gid) 474{ 475 const char *group_name = Platform::GetGroupName(gid); 476 if (group_name) 477 return group_name; 478 479 if (IsRemote() && m_remote_platform_sp) 480 return m_remote_platform_sp->GetGroupName(gid); 481 return NULL; 482} 483 484bool 485PlatformDarwin::ModuleIsExcludedForNonModuleSpecificSearches (lldb_private::Target &target, const lldb::ModuleSP &module_sp) 486{ 487 ObjectFile *obj_file = module_sp->GetObjectFile(); 488 if (!obj_file) 489 return false; 490 491 ObjectFile::Type obj_type = obj_file->GetType(); 492 if (obj_type == ObjectFile::eTypeDynamicLinker) 493 return true; 494 else 495 return false; 496} 497