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 22 using namespace lldb; 23 using namespace lldb_private; 24 25 26 //------------------------------------------------------------------ 27 /// Default Constructor 28 //------------------------------------------------------------------ 29 PlatformDarwin::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 //------------------------------------------------------------------ 41 PlatformDarwin::~PlatformDarwin() 42 { 43 } 44 45 46 Error 47 PlatformDarwin::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 ("unable 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 174 size_t 175 PlatformDarwin::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 241 bool 242 PlatformDarwin::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 251 bool 252 PlatformDarwin::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 260 bool 261 PlatformDarwin::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 270 ArchSpec 271 PlatformDarwin::GetRemoteSystemArchitecture () 272 { 273 if (m_remote_platform_sp) 274 return m_remote_platform_sp->GetRemoteSystemArchitecture (); 275 return ArchSpec(); 276 } 277 278 279 const char * 280 PlatformDarwin::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 290 bool 291 PlatformDarwin::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 300 Error 301 PlatformDarwin::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 337 Error 338 PlatformDarwin::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 357 bool 358 PlatformDarwin::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 375 uint32_t 376 PlatformDarwin::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 394 Error 395 PlatformDarwin::LaunchProcess (ProcessLaunchInfo &launch_info) 396 { 397 Error error; 398 399 if (IsHost()) 400 { 401 if (launch_info.GetFlags().Test (eLaunchFlagLaunchInShell)) 402 { 403 const bool is_localhost = true; 404 if (!launch_info.ConvertArgumentsForLaunchingInShell (error, is_localhost)) 405 return error; 406 } 407 error = Platform::LaunchProcess (launch_info); 408 } 409 else 410 { 411 if (m_remote_platform_sp) 412 error = m_remote_platform_sp->LaunchProcess (launch_info); 413 else 414 error.SetErrorString ("the platform is not currently connected"); 415 } 416 return error; 417 } 418 419 lldb::ProcessSP 420 PlatformDarwin::Attach (ProcessAttachInfo &attach_info, 421 Debugger &debugger, 422 Target *target, 423 Listener &listener, 424 Error &error) 425 { 426 lldb::ProcessSP process_sp; 427 428 if (IsHost()) 429 { 430 if (target == NULL) 431 { 432 TargetSP new_target_sp; 433 FileSpec emptyFileSpec; 434 435 error = debugger.GetTargetList().CreateTarget (debugger, 436 emptyFileSpec, 437 NULL, 438 false, 439 NULL, 440 new_target_sp); 441 target = new_target_sp.get(); 442 } 443 else 444 error.Clear(); 445 446 if (target && error.Success()) 447 { 448 debugger.GetTargetList().SetSelectedTarget(target); 449 450 process_sp = target->CreateProcess (listener, attach_info.GetProcessPluginName()); 451 452 if (process_sp) 453 error = process_sp->Attach (attach_info); 454 } 455 } 456 else 457 { 458 if (m_remote_platform_sp) 459 process_sp = m_remote_platform_sp->Attach (attach_info, debugger, target, listener, error); 460 else 461 error.SetErrorString ("the platform is not currently connected"); 462 } 463 return process_sp; 464 } 465 466 const char * 467 PlatformDarwin::GetUserName (uint32_t uid) 468 { 469 // Check the cache in Platform in case we have already looked this uid up 470 const char *user_name = Platform::GetUserName(uid); 471 if (user_name) 472 return user_name; 473 474 if (IsRemote() && m_remote_platform_sp) 475 return m_remote_platform_sp->GetUserName(uid); 476 return NULL; 477 } 478 479 const char * 480 PlatformDarwin::GetGroupName (uint32_t gid) 481 { 482 const char *group_name = Platform::GetGroupName(gid); 483 if (group_name) 484 return group_name; 485 486 if (IsRemote() && m_remote_platform_sp) 487 return m_remote_platform_sp->GetGroupName(gid); 488 return NULL; 489 } 490 491 bool 492 PlatformDarwin::ModuleIsExcludedForNonModuleSpecificSearches (lldb_private::Target &target, const lldb::ModuleSP &module_sp) 493 { 494 ObjectFile *obj_file = module_sp->GetObjectFile(); 495 if (!obj_file) 496 return false; 497 498 ObjectFile::Type obj_type = obj_file->GetType(); 499 if (obj_type == ObjectFile::eTypeDynamicLinker) 500 return true; 501 else 502 return false; 503 } 504