1 //===-- PlatformRemoteiOS.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 "PlatformRemoteiOS.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/ArchSpec.h" 18 #include "lldb/Core/Error.h" 19 #include "lldb/Core/Module.h" 20 #include "lldb/Core/ModuleList.h" 21 #include "lldb/Core/PluginManager.h" 22 #include "lldb/Core/StreamString.h" 23 #include "lldb/Host/FileSpec.h" 24 #include "lldb/Host/Host.h" 25 #include "lldb/Target/Process.h" 26 #include "lldb/Target/Target.h" 27 28 using namespace lldb; 29 using namespace lldb_private; 30 31 //------------------------------------------------------------------ 32 // Static Variables 33 //------------------------------------------------------------------ 34 static uint32_t g_initialize_count = 0; 35 36 //------------------------------------------------------------------ 37 // Static Functions 38 //------------------------------------------------------------------ 39 void 40 PlatformRemoteiOS::Initialize () 41 { 42 if (g_initialize_count++ == 0) 43 { 44 PluginManager::RegisterPlugin (PlatformRemoteiOS::GetShortPluginNameStatic(), 45 PlatformRemoteiOS::GetDescriptionStatic(), 46 PlatformRemoteiOS::CreateInstance); 47 } 48 } 49 50 void 51 PlatformRemoteiOS::Terminate () 52 { 53 if (g_initialize_count > 0) 54 { 55 if (--g_initialize_count == 0) 56 { 57 PluginManager::UnregisterPlugin (PlatformRemoteiOS::CreateInstance); 58 } 59 } 60 } 61 62 Platform* 63 PlatformRemoteiOS::CreateInstance () 64 { 65 return new PlatformRemoteiOS (); 66 } 67 68 69 const char * 70 PlatformRemoteiOS::GetPluginNameStatic () 71 { 72 return "PlatformRemoteiOS"; 73 } 74 75 const char * 76 PlatformRemoteiOS::GetShortPluginNameStatic() 77 { 78 return "remote-ios"; 79 } 80 81 const char * 82 PlatformRemoteiOS::GetDescriptionStatic() 83 { 84 return "Remote iOS platform plug-in."; 85 } 86 87 88 //------------------------------------------------------------------ 89 /// Default Constructor 90 //------------------------------------------------------------------ 91 PlatformRemoteiOS::PlatformRemoteiOS () : 92 PlatformDarwin (false), // This is a remote platform 93 m_device_support_directory (), 94 m_device_support_directory_for_os_version () 95 { 96 } 97 98 //------------------------------------------------------------------ 99 /// Destructor. 100 /// 101 /// The destructor is virtual since this class is designed to be 102 /// inherited from by the plug-in instance. 103 //------------------------------------------------------------------ 104 PlatformRemoteiOS::~PlatformRemoteiOS() 105 { 106 } 107 108 109 void 110 PlatformRemoteiOS::GetStatus (Stream &strm) 111 { 112 Platform::GetStatus (strm); 113 const char *sdk_directory = GetDeviceSupportDirectoryForOSVersion(); 114 if (sdk_directory) 115 strm.Printf (" SDK Path: \"%s\"\n", sdk_directory); 116 else 117 strm.PutCString (" SDK Path: error: unable to locate SDK\n"); 118 } 119 120 121 Error 122 PlatformRemoteiOS::ResolveExecutable (const FileSpec &exe_file, 123 const ArchSpec &exe_arch, 124 lldb::ModuleSP &exe_module_sp) 125 { 126 Error error; 127 // Nothing special to do here, just use the actual file and architecture 128 129 FileSpec resolved_exe_file (exe_file); 130 131 // If we have "ls" as the exe_file, resolve the executable loation based on 132 // the current path variables 133 // TODO: resolve bare executables in the Platform SDK 134 // if (!resolved_exe_file.Exists()) 135 // resolved_exe_file.ResolveExecutableLocation (); 136 137 // Resolve any executable within a bundle on MacOSX 138 // TODO: verify that this handles shallow bundles, if not then implement one ourselves 139 Host::ResolveExecutableInBundle (resolved_exe_file); 140 141 if (resolved_exe_file.Exists()) 142 { 143 if (exe_arch.IsValid()) 144 { 145 error = ModuleList::GetSharedModule (resolved_exe_file, 146 exe_arch, 147 NULL, 148 NULL, 149 0, 150 exe_module_sp, 151 NULL, 152 NULL); 153 154 if (exe_module_sp->GetObjectFile()) 155 return error; 156 exe_module_sp.reset(); 157 } 158 // No valid architecture was specified or the exact ARM slice wasn't 159 // found so ask the platform for the architectures that we should be 160 // using (in the correct order) and see if we can find a match that way 161 StreamString arch_names; 162 ArchSpec platform_arch; 163 for (uint32_t idx = 0; GetSupportedArchitectureAtIndex (idx, platform_arch); ++idx) 164 { 165 error = ModuleList::GetSharedModule (resolved_exe_file, 166 platform_arch, 167 NULL, 168 NULL, 169 0, 170 exe_module_sp, 171 NULL, 172 NULL); 173 // Did we find an executable using one of the 174 if (error.Success()) 175 { 176 if (exe_module_sp && exe_module_sp->GetObjectFile()) 177 break; 178 else 179 error.SetErrorToGenericError(); 180 } 181 182 if (idx > 0) 183 arch_names.PutCString (", "); 184 arch_names.PutCString (platform_arch.GetArchitectureName()); 185 } 186 187 if (error.Fail() || !exe_module_sp) 188 { 189 error.SetErrorStringWithFormat ("'%s%s%s' doesn't contain any '%s' platform architectures: %s", 190 exe_file.GetDirectory().AsCString(""), 191 exe_file.GetDirectory() ? "/" : "", 192 exe_file.GetFilename().AsCString(""), 193 GetShortPluginName(), 194 arch_names.GetString().c_str()); 195 } 196 } 197 else 198 { 199 error.SetErrorStringWithFormat ("'%s%s%s' does not exist", 200 exe_file.GetDirectory().AsCString(""), 201 exe_file.GetDirectory() ? "/" : "", 202 exe_file.GetFilename().AsCString("")); 203 } 204 205 return error; 206 } 207 208 const char * 209 PlatformRemoteiOS::GetDeviceSupportDirectory() 210 { 211 if (m_device_support_directory.empty()) 212 { 213 bool developer_dir_path_valid = false; 214 char developer_dir_path[PATH_MAX]; 215 FileSpec temp_file_spec; 216 if (Host::GetLLDBPath (ePathTypeLLDBShlibDir, temp_file_spec)) 217 { 218 if (temp_file_spec.GetPath (developer_dir_path, sizeof(developer_dir_path))) 219 { 220 char *lib_priv_frameworks = strstr (developer_dir_path, "/Library/PrivateFrameworks/LLDB.framework"); 221 if (lib_priv_frameworks) 222 { 223 *lib_priv_frameworks = '\0'; 224 developer_dir_path_valid = true; 225 } 226 } 227 } 228 229 if (!developer_dir_path_valid) 230 { 231 std::string xcode_dir_path; 232 const char *xcode_select_prefix_dir = getenv ("XCODE_SELECT_PREFIX_DIR"); 233 if (xcode_select_prefix_dir) 234 xcode_dir_path.append (xcode_select_prefix_dir); 235 xcode_dir_path.append ("/usr/share/xcode-select/xcode_dir_path"); 236 temp_file_spec.SetFile(xcode_dir_path.c_str(), false); 237 size_t bytes_read = temp_file_spec.ReadFileContents(0, developer_dir_path, sizeof(developer_dir_path)); 238 if (bytes_read > 0) 239 { 240 developer_dir_path[bytes_read] = '\0'; 241 while (developer_dir_path[bytes_read-1] == '\r' || 242 developer_dir_path[bytes_read-1] == '\n') 243 developer_dir_path[--bytes_read] = '\0'; 244 developer_dir_path_valid = true; 245 } 246 } 247 248 if (developer_dir_path_valid) 249 { 250 temp_file_spec.SetFile (developer_dir_path, false); 251 if (temp_file_spec.Exists()) 252 { 253 m_device_support_directory.assign (developer_dir_path); 254 return m_device_support_directory.c_str(); 255 } 256 } 257 // Assign a single NULL character so we know we tried to find the device 258 // support directory and we don't keep trying to find it over and over. 259 m_device_support_directory.assign (1, '\0'); 260 } 261 262 // We should have put a single NULL character into m_device_support_directory 263 // or it should have a valid path if the code gets here 264 assert (m_device_support_directory.empty() == false); 265 if (m_device_support_directory[0]) 266 return m_device_support_directory.c_str(); 267 return NULL; 268 } 269 270 const char * 271 PlatformRemoteiOS::GetDeviceSupportDirectoryForOSVersion() 272 { 273 if (m_sdk_sysroot) 274 return m_sdk_sysroot.GetCString(); 275 276 if (m_device_support_directory_for_os_version.empty()) 277 { 278 const char *device_support_dir = GetDeviceSupportDirectory(); 279 const bool resolve_path = true; 280 if (device_support_dir) 281 { 282 m_device_support_directory_for_os_version.assign (device_support_dir); 283 m_device_support_directory_for_os_version.append ("/Platforms/iPhoneOS.platform/DeviceSupport"); 284 285 uint32_t major = 0; 286 uint32_t minor = 0; 287 uint32_t update = 0; 288 FileSpec file_spec; 289 char resolved_path[PATH_MAX]; 290 if (GetOSVersion(major, minor, update)) 291 { 292 if (major != UINT32_MAX && minor != UINT32_MAX && update != UINT32_MAX) 293 { 294 ::snprintf (resolved_path, 295 sizeof(resolved_path), 296 "%s/%i.%i.%i", 297 m_device_support_directory_for_os_version.c_str(), 298 major, 299 minor, 300 update); 301 302 file_spec.SetFile(resolved_path, resolve_path); 303 if (file_spec.Exists() && file_spec.GetPath(resolved_path, sizeof(resolved_path))) 304 { 305 m_device_support_directory_for_os_version.assign (resolved_path); 306 return m_device_support_directory_for_os_version.c_str(); 307 } 308 } 309 310 if (major != UINT32_MAX && minor != UINT32_MAX) 311 { 312 ::snprintf (resolved_path, 313 sizeof(resolved_path), 314 "%s/%i.%i", 315 m_device_support_directory_for_os_version.c_str(), 316 major, 317 minor); 318 319 file_spec.SetFile(resolved_path, resolve_path); 320 if (file_spec.Exists() && file_spec.GetPath(resolved_path, sizeof(resolved_path))) 321 { 322 m_device_support_directory_for_os_version.assign (resolved_path); 323 return m_device_support_directory_for_os_version.c_str(); 324 } 325 } 326 } 327 else 328 { 329 // Use the default as we have no OS version selected 330 m_device_support_directory_for_os_version.append ("/Latest"); 331 file_spec.SetFile(m_device_support_directory_for_os_version.c_str(), resolve_path); 332 333 if (file_spec.Exists() && file_spec.GetPath(resolved_path, sizeof(resolved_path))) 334 { 335 if (m_major_os_version == UINT32_MAX) 336 { 337 const char *resolved_latest_dirname = file_spec.GetFilename().GetCString(); 338 const char *pos = Args::StringToVersion (resolved_latest_dirname, 339 m_major_os_version, 340 m_minor_os_version, 341 m_update_os_version); 342 343 if (m_build_update.empty() && pos[0] == ' ' && pos[1] == '(') 344 { 345 const char *end_paren = strchr (pos + 2, ')'); 346 m_build_update.assign (pos + 2, end_paren); 347 } 348 } 349 m_device_support_directory_for_os_version.assign (resolved_path); 350 return m_device_support_directory_for_os_version.c_str(); 351 } 352 } 353 } 354 // Assign a single NULL character so we know we tried to find the device 355 // support directory and we don't keep trying to find it over and over. 356 m_device_support_directory_for_os_version.assign (1, '\0'); 357 } 358 // We should have put a single NULL character into m_device_support_directory_for_os_version 359 // or it should have a valid path if the code gets here 360 assert (m_device_support_directory_for_os_version.empty() == false); 361 if (m_device_support_directory_for_os_version[0]) 362 return m_device_support_directory_for_os_version.c_str(); 363 return NULL; 364 } 365 366 Error 367 PlatformRemoteiOS::GetFile (const FileSpec &platform_file, 368 const UUID *uuid_ptr, 369 FileSpec &local_file) 370 { 371 Error error; 372 char platform_file_path[PATH_MAX]; 373 if (platform_file.GetPath(platform_file_path, sizeof(platform_file_path))) 374 { 375 char resolved_path[PATH_MAX]; 376 377 const char * os_version_dir = GetDeviceSupportDirectoryForOSVersion(); 378 if (os_version_dir) 379 { 380 ::snprintf (resolved_path, 381 sizeof(resolved_path), 382 "%s/%s", 383 os_version_dir, 384 platform_file_path); 385 386 local_file.SetFile(resolved_path, true); 387 if (local_file.Exists()) 388 return error; 389 390 ::snprintf (resolved_path, 391 sizeof(resolved_path), 392 "%s/Symbols.Internal/%s", 393 os_version_dir, 394 platform_file_path); 395 396 local_file.SetFile(resolved_path, true); 397 if (local_file.Exists()) 398 return error; 399 ::snprintf (resolved_path, 400 sizeof(resolved_path), 401 "%s/Symbols/%s", 402 os_version_dir, 403 platform_file_path); 404 405 local_file.SetFile(resolved_path, true); 406 if (local_file.Exists()) 407 return error; 408 409 } 410 local_file = platform_file; 411 if (local_file.Exists()) 412 return error; 413 414 error.SetErrorStringWithFormat ("unable to locate a platform file for '%s' in platform '%s'", 415 platform_file_path, 416 GetPluginName()); 417 } 418 else 419 { 420 error.SetErrorString ("invalid platform file argument"); 421 } 422 return error; 423 } 424 425 Error 426 PlatformRemoteiOS::GetSharedModule (const FileSpec &platform_file, 427 const ArchSpec &arch, 428 const UUID *uuid_ptr, 429 const ConstString *object_name_ptr, 430 off_t object_offset, 431 ModuleSP &module_sp, 432 ModuleSP *old_module_sp_ptr, 433 bool *did_create_ptr) 434 { 435 // For iOS, the SDK files are all cached locally on the host 436 // system. So first we ask for the file in the cached SDK, 437 // then we attempt to get a shared module for the right architecture 438 // with the right UUID. 439 Error error; 440 FileSpec local_file; 441 error = GetFile (platform_file, uuid_ptr, local_file); 442 if (error.Success()) 443 { 444 445 error = ResolveExecutable (local_file, arch, module_sp); 446 } 447 else 448 { 449 const bool always_create = false; 450 error = ModuleList::GetSharedModule (platform_file, 451 arch, 452 uuid_ptr, 453 object_name_ptr, 454 object_offset, 455 module_sp, 456 old_module_sp_ptr, 457 did_create_ptr, 458 always_create); 459 460 } 461 if (module_sp) 462 module_sp->SetPlatformFileSpec(platform_file); 463 464 return error; 465 } 466 467 468 uint32_t 469 PlatformRemoteiOS::FindProcesses (const ProcessInstanceInfoMatch &match_info, 470 ProcessInstanceInfoList &process_infos) 471 { 472 // TODO: if connected, send a packet to get the remote process infos by name 473 process_infos.Clear(); 474 return 0; 475 } 476 477 bool 478 PlatformRemoteiOS::GetProcessInfo (lldb::pid_t pid, ProcessInstanceInfo &process_info) 479 { 480 // TODO: if connected, send a packet to get the remote process info 481 process_info.Clear(); 482 return false; 483 } 484 485 bool 486 PlatformRemoteiOS::GetSupportedArchitectureAtIndex (uint32_t idx, ArchSpec &arch) 487 { 488 ArchSpec system_arch (GetSystemArchitecture()); 489 const ArchSpec::Core system_core = system_arch.GetCore(); 490 switch (system_core) 491 { 492 default: 493 switch (idx) 494 { 495 case 0: arch.SetTriple ("armv7-apple-darwin", NULL); return true; 496 case 1: arch.SetTriple ("armv7f-apple-darwin", NULL); return true; 497 case 2: arch.SetTriple ("armv7k-apple-darwin", NULL); return true; 498 case 3: arch.SetTriple ("armv7s-apple-darwin", NULL); return true; 499 case 4: arch.SetTriple ("armv6-apple-darwin", NULL); return true; 500 case 5: arch.SetTriple ("armv5-apple-darwin", NULL); return true; 501 case 6: arch.SetTriple ("armv4-apple-darwin", NULL); return true; 502 case 7: arch.SetTriple ("arm-apple-darwin", NULL); return true; 503 default: break; 504 } 505 break; 506 507 case ArchSpec::eCore_arm_armv7f: 508 switch (idx) 509 { 510 case 0: arch.SetTriple ("armv7f-apple-darwin", NULL); return true; 511 case 1: arch.SetTriple ("armv7-apple-darwin", NULL); return true; 512 case 2: arch.SetTriple ("armv6-apple-darwin", NULL); return true; 513 case 3: arch.SetTriple ("armv5-apple-darwin", NULL); return true; 514 case 4: arch.SetTriple ("armv4-apple-darwin", NULL); return true; 515 case 5: arch.SetTriple ("arm-apple-darwin", NULL); return true; 516 default: break; 517 } 518 break; 519 520 case ArchSpec::eCore_arm_armv7k: 521 switch (idx) 522 { 523 case 0: arch.SetTriple ("armv7k-apple-darwin", NULL); return true; 524 case 1: arch.SetTriple ("armv7-apple-darwin", NULL); return true; 525 case 2: arch.SetTriple ("armv6-apple-darwin", NULL); return true; 526 case 3: arch.SetTriple ("armv5-apple-darwin", NULL); return true; 527 case 4: arch.SetTriple ("armv4-apple-darwin", NULL); return true; 528 case 5: arch.SetTriple ("arm-apple-darwin", NULL); return true; 529 default: break; 530 } 531 break; 532 533 case ArchSpec::eCore_arm_armv7s: 534 switch (idx) 535 { 536 case 0: arch.SetTriple ("armv7s-apple-darwin", NULL); return true; 537 case 1: arch.SetTriple ("armv7-apple-darwin", NULL); return true; 538 case 2: arch.SetTriple ("armv6-apple-darwin", NULL); return true; 539 case 3: arch.SetTriple ("armv5-apple-darwin", NULL); return true; 540 case 4: arch.SetTriple ("armv4-apple-darwin", NULL); return true; 541 case 5: arch.SetTriple ("arm-apple-darwin", NULL); return true; 542 default: break; 543 } 544 break; 545 546 case ArchSpec::eCore_arm_armv7: 547 switch (idx) 548 { 549 case 0: arch.SetTriple ("armv7-apple-darwin", NULL); return true; 550 case 1: arch.SetTriple ("armv6-apple-darwin", NULL); return true; 551 case 2: arch.SetTriple ("armv5-apple-darwin", NULL); return true; 552 case 3: arch.SetTriple ("armv4-apple-darwin", NULL); return true; 553 case 4: arch.SetTriple ("arm-apple-darwin", NULL); return true; 554 default: break; 555 } 556 break; 557 558 case ArchSpec::eCore_arm_armv6: 559 switch (idx) 560 { 561 case 0: arch.SetTriple ("armv6-apple-darwin", NULL); return true; 562 case 1: arch.SetTriple ("armv5-apple-darwin", NULL); return true; 563 case 2: arch.SetTriple ("armv4-apple-darwin", NULL); return true; 564 case 3: arch.SetTriple ("arm-apple-darwin", NULL); return true; 565 default: break; 566 } 567 break; 568 569 case ArchSpec::eCore_arm_armv5: 570 switch (idx) 571 { 572 case 0: arch.SetTriple ("armv5-apple-darwin", NULL); return true; 573 case 1: arch.SetTriple ("armv4-apple-darwin", NULL); return true; 574 case 2: arch.SetTriple ("arm-apple-darwin", NULL); return true; 575 default: break; 576 } 577 break; 578 579 case ArchSpec::eCore_arm_armv4: 580 switch (idx) 581 { 582 case 0: arch.SetTriple ("armv4-apple-darwin", NULL); return true; 583 case 1: arch.SetTriple ("arm-apple-darwin", NULL); return true; 584 default: break; 585 } 586 break; 587 } 588 arch.Clear(); 589 return false; 590 } 591