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 ("SDKROOT: \"%s\"\n", sdk_directory); 116 else 117 strm.PutCString ("SDKROOT: 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_device_support_directory_for_os_version.empty()) 274 { 275 const char *device_support_dir = GetDeviceSupportDirectory(); 276 const bool resolve_path = true; 277 if (device_support_dir) 278 { 279 m_device_support_directory_for_os_version.assign (device_support_dir); 280 m_device_support_directory_for_os_version.append ("/Platforms/iPhoneOS.platform/DeviceSupport"); 281 282 uint32_t major = 0; 283 uint32_t minor = 0; 284 uint32_t update = 0; 285 FileSpec file_spec; 286 char resolved_path[PATH_MAX]; 287 if (GetOSVersion(major, minor, update)) 288 { 289 if (major != UINT32_MAX && minor != UINT32_MAX && update != UINT32_MAX) 290 { 291 ::snprintf (resolved_path, 292 sizeof(resolved_path), 293 "%s/%i.%i.%i", 294 m_device_support_directory_for_os_version.c_str(), 295 major, 296 minor, 297 update); 298 299 file_spec.SetFile(resolved_path, resolve_path); 300 if (file_spec.Exists() && file_spec.GetPath(resolved_path, sizeof(resolved_path))) 301 { 302 m_device_support_directory_for_os_version.assign (resolved_path); 303 return m_device_support_directory_for_os_version.c_str(); 304 } 305 } 306 307 if (major != UINT32_MAX && minor != UINT32_MAX) 308 { 309 ::snprintf (resolved_path, 310 sizeof(resolved_path), 311 "%s/%i.%i", 312 m_device_support_directory_for_os_version.c_str(), 313 major, 314 minor); 315 316 file_spec.SetFile(resolved_path, resolve_path); 317 if (file_spec.Exists() && file_spec.GetPath(resolved_path, sizeof(resolved_path))) 318 { 319 m_device_support_directory_for_os_version.assign (resolved_path); 320 return m_device_support_directory_for_os_version.c_str(); 321 } 322 } 323 } 324 else 325 { 326 // Use the default as we have no OS version selected 327 m_device_support_directory_for_os_version.append ("/Latest"); 328 file_spec.SetFile(m_device_support_directory_for_os_version.c_str(), resolve_path); 329 330 if (file_spec.Exists() && file_spec.GetPath(resolved_path, sizeof(resolved_path))) 331 { 332 if (m_major_os_version == UINT32_MAX) 333 { 334 const char *resolved_latest_dirname = file_spec.GetFilename().GetCString(); 335 const char *pos = Args::StringToVersion (resolved_latest_dirname, 336 m_major_os_version, 337 m_minor_os_version, 338 m_update_os_version); 339 340 if (m_build_update.empty() && pos[0] == ' ' && pos[1] == '(') 341 { 342 const char *end_paren = strchr (pos + 2, ')'); 343 m_build_update.assign (pos + 2, end_paren); 344 } 345 } 346 m_device_support_directory_for_os_version.assign (resolved_path); 347 return m_device_support_directory_for_os_version.c_str(); 348 } 349 } 350 } 351 // Assign a single NULL character so we know we tried to find the device 352 // support directory and we don't keep trying to find it over and over. 353 m_device_support_directory_for_os_version.assign (1, '\0'); 354 } 355 // We should have put a single NULL character into m_device_support_directory_for_os_version 356 // or it should have a valid path if the code gets here 357 assert (m_device_support_directory_for_os_version.empty() == false); 358 if (m_device_support_directory_for_os_version[0]) 359 return m_device_support_directory_for_os_version.c_str(); 360 return NULL; 361 } 362 363 Error 364 PlatformRemoteiOS::GetFile (const FileSpec &platform_file, 365 const UUID *uuid_ptr, 366 FileSpec &local_file) 367 { 368 Error error; 369 char platform_file_path[PATH_MAX]; 370 if (platform_file.GetPath(platform_file_path, sizeof(platform_file_path))) 371 { 372 char resolved_path[PATH_MAX]; 373 374 const char * os_version_dir = GetDeviceSupportDirectoryForOSVersion(); 375 if (os_version_dir) 376 { 377 ::snprintf (resolved_path, 378 sizeof(resolved_path), 379 "%s/Symbols.Internal/%s", 380 os_version_dir, 381 platform_file_path); 382 383 local_file.SetFile(resolved_path, true); 384 if (local_file.Exists()) 385 return error; 386 ::snprintf (resolved_path, 387 sizeof(resolved_path), 388 "%s/Symbols/%s", 389 os_version_dir, 390 platform_file_path); 391 392 local_file.SetFile(resolved_path, true); 393 if (local_file.Exists()) 394 return error; 395 396 } 397 local_file = platform_file; 398 if (local_file.Exists()) 399 return error; 400 401 error.SetErrorStringWithFormat ("unable to locate a platform file for '%s' in platform '%s'", 402 platform_file_path, 403 GetPluginName()); 404 } 405 else 406 { 407 error.SetErrorString ("invalid platform file argument"); 408 } 409 return error; 410 } 411 412 Error 413 PlatformRemoteiOS::GetSharedModule (const FileSpec &platform_file, 414 const ArchSpec &arch, 415 const UUID *uuid_ptr, 416 const ConstString *object_name_ptr, 417 off_t object_offset, 418 ModuleSP &module_sp, 419 ModuleSP *old_module_sp_ptr, 420 bool *did_create_ptr) 421 { 422 // For iOS, the SDK files are all cached locally on the host 423 // system. So first we ask for the file in the cached SDK, 424 // then we attempt to get a shared module for the right architecture 425 // with the right UUID. 426 Error error; 427 FileSpec local_file; 428 error = GetFile (platform_file, uuid_ptr, local_file); 429 if (error.Success()) 430 { 431 const bool always_create = false; 432 error = ModuleList::GetSharedModule (local_file, 433 arch, 434 uuid_ptr, 435 object_name_ptr, 436 object_offset, 437 module_sp, 438 old_module_sp_ptr, 439 did_create_ptr, 440 always_create); 441 } 442 if (module_sp) 443 module_sp->SetPlatformFileSpec(platform_file); 444 445 return error; 446 } 447 448 449 uint32_t 450 PlatformRemoteiOS::FindProcesses (const ProcessInstanceInfoMatch &match_info, 451 ProcessInstanceInfoList &process_infos) 452 { 453 // TODO: if connected, send a packet to get the remote process infos by name 454 process_infos.Clear(); 455 return 0; 456 } 457 458 bool 459 PlatformRemoteiOS::GetProcessInfo (lldb::pid_t pid, ProcessInstanceInfo &process_info) 460 { 461 // TODO: if connected, send a packet to get the remote process info 462 process_info.Clear(); 463 return false; 464 } 465 466 bool 467 PlatformRemoteiOS::GetSupportedArchitectureAtIndex (uint32_t idx, ArchSpec &arch) 468 { 469 ArchSpec system_arch (GetSystemArchitecture()); 470 const ArchSpec::Core system_core = system_arch.GetCore(); 471 switch (system_core) 472 { 473 default: 474 switch (idx) 475 { 476 case 0: arch.SetTriple ("armv7-apple-darwin", NULL); return true; 477 case 1: arch.SetTriple ("armv7f-apple-darwin", NULL); return true; 478 case 2: arch.SetTriple ("armv7k-apple-darwin", NULL); return true; 479 case 3: arch.SetTriple ("armv7s-apple-darwin", NULL); return true; 480 case 4: arch.SetTriple ("armv6-apple-darwin", NULL); return true; 481 case 5: arch.SetTriple ("armv5-apple-darwin", NULL); return true; 482 case 6: arch.SetTriple ("armv4-apple-darwin", NULL); return true; 483 case 7: arch.SetTriple ("arm-apple-darwin", NULL); return true; 484 default: break; 485 } 486 break; 487 488 case ArchSpec::eCore_arm_armv7f: 489 switch (idx) 490 { 491 case 0: arch.SetTriple ("armv7f-apple-darwin", NULL); return true; 492 case 1: arch.SetTriple ("armv7-apple-darwin", NULL); return true; 493 case 2: arch.SetTriple ("armv6-apple-darwin", NULL); return true; 494 case 3: arch.SetTriple ("armv5-apple-darwin", NULL); return true; 495 case 4: arch.SetTriple ("armv4-apple-darwin", NULL); return true; 496 case 5: arch.SetTriple ("arm-apple-darwin", NULL); return true; 497 default: break; 498 } 499 break; 500 501 case ArchSpec::eCore_arm_armv7k: 502 switch (idx) 503 { 504 case 0: arch.SetTriple ("armv7k-apple-darwin", NULL); return true; 505 case 1: arch.SetTriple ("armv7-apple-darwin", NULL); return true; 506 case 2: arch.SetTriple ("armv6-apple-darwin", NULL); return true; 507 case 3: arch.SetTriple ("armv5-apple-darwin", NULL); return true; 508 case 4: arch.SetTriple ("armv4-apple-darwin", NULL); return true; 509 case 5: arch.SetTriple ("arm-apple-darwin", NULL); return true; 510 default: break; 511 } 512 break; 513 514 case ArchSpec::eCore_arm_armv7s: 515 switch (idx) 516 { 517 case 0: arch.SetTriple ("armv7s-apple-darwin", NULL); return true; 518 case 1: arch.SetTriple ("armv7-apple-darwin", NULL); return true; 519 case 2: arch.SetTriple ("armv6-apple-darwin", NULL); return true; 520 case 3: arch.SetTriple ("armv5-apple-darwin", NULL); return true; 521 case 4: arch.SetTriple ("armv4-apple-darwin", NULL); return true; 522 case 5: arch.SetTriple ("arm-apple-darwin", NULL); return true; 523 default: break; 524 } 525 break; 526 527 case ArchSpec::eCore_arm_armv7: 528 switch (idx) 529 { 530 case 0: arch.SetTriple ("armv7-apple-darwin", NULL); return true; 531 case 1: arch.SetTriple ("armv6-apple-darwin", NULL); return true; 532 case 2: arch.SetTriple ("armv5-apple-darwin", NULL); return true; 533 case 3: arch.SetTriple ("armv4-apple-darwin", NULL); return true; 534 case 4: arch.SetTriple ("arm-apple-darwin", NULL); return true; 535 default: break; 536 } 537 break; 538 539 case ArchSpec::eCore_arm_armv6: 540 switch (idx) 541 { 542 case 0: arch.SetTriple ("armv6-apple-darwin", NULL); return true; 543 case 1: arch.SetTriple ("armv5-apple-darwin", NULL); return true; 544 case 2: arch.SetTriple ("armv4-apple-darwin", NULL); return true; 545 case 3: arch.SetTriple ("arm-apple-darwin", NULL); return true; 546 default: break; 547 } 548 break; 549 550 case ArchSpec::eCore_arm_armv5: 551 switch (idx) 552 { 553 case 0: arch.SetTriple ("armv5-apple-darwin", NULL); return true; 554 case 1: arch.SetTriple ("armv4-apple-darwin", NULL); return true; 555 case 2: arch.SetTriple ("arm-apple-darwin", NULL); return true; 556 default: break; 557 } 558 break; 559 560 case ArchSpec::eCore_arm_armv4: 561 switch (idx) 562 { 563 case 0: arch.SetTriple ("armv4-apple-darwin", NULL); return true; 564 case 1: arch.SetTriple ("arm-apple-darwin", NULL); return true; 565 default: break; 566 } 567 break; 568 } 569 arch.Clear(); 570 return false; 571 } 572