1 //===-- PlatformRemoteAppleTV.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 // C Includes 11 // C++ Includes 12 #include <string> 13 #include <vector> 14 15 // Other libraries and framework includes 16 // Project includes 17 #include "PlatformRemoteAppleTV.h" 18 19 #include "lldb/Breakpoint/BreakpointLocation.h" 20 #include "lldb/Core/ArchSpec.h" 21 #include "lldb/Core/Error.h" 22 #include "lldb/Core/Log.h" 23 #include "lldb/Core/Module.h" 24 #include "lldb/Core/ModuleList.h" 25 #include "lldb/Core/ModuleSpec.h" 26 #include "lldb/Core/PluginManager.h" 27 #include "lldb/Core/StreamString.h" 28 #include "lldb/Host/FileSpec.h" 29 #include "lldb/Host/Host.h" 30 #include "lldb/Target/Process.h" 31 #include "lldb/Target/Target.h" 32 33 using namespace lldb; 34 using namespace lldb_private; 35 36 //------------------------------------------------------------------ 37 /// Default Constructor 38 //------------------------------------------------------------------ 39 PlatformRemoteAppleTV::PlatformRemoteAppleTV() 40 : PlatformDarwin(false), // This is a remote platform 41 m_sdk_directory_infos(), m_device_support_directory(), 42 m_device_support_directory_for_os_version(), m_build_update(), 43 m_last_module_sdk_idx(UINT32_MAX), 44 m_connected_module_sdk_idx(UINT32_MAX) {} 45 46 PlatformRemoteAppleTV::SDKDirectoryInfo::SDKDirectoryInfo( 47 const lldb_private::FileSpec &sdk_dir) 48 : directory(sdk_dir), build(), version_major(0), version_minor(0), 49 version_update(0), user_cached(false) { 50 llvm::StringRef dirname_str = sdk_dir.GetFilename().GetStringRef(); 51 llvm::StringRef build_str; 52 std::tie(version_major, version_minor, version_update, build_str) = 53 ParseVersionBuildDir(dirname_str); 54 build.SetString(build_str); 55 } 56 57 //------------------------------------------------------------------ 58 // Static Variables 59 //------------------------------------------------------------------ 60 static uint32_t g_initialize_count = 0; 61 62 //------------------------------------------------------------------ 63 // Static Functions 64 //------------------------------------------------------------------ 65 void PlatformRemoteAppleTV::Initialize() { 66 PlatformDarwin::Initialize(); 67 68 if (g_initialize_count++ == 0) { 69 PluginManager::RegisterPlugin(PlatformRemoteAppleTV::GetPluginNameStatic(), 70 PlatformRemoteAppleTV::GetDescriptionStatic(), 71 PlatformRemoteAppleTV::CreateInstance); 72 } 73 } 74 75 void PlatformRemoteAppleTV::Terminate() { 76 if (g_initialize_count > 0) { 77 if (--g_initialize_count == 0) { 78 PluginManager::UnregisterPlugin(PlatformRemoteAppleTV::CreateInstance); 79 } 80 } 81 82 PlatformDarwin::Terminate(); 83 } 84 85 PlatformSP PlatformRemoteAppleTV::CreateInstance(bool force, 86 const ArchSpec *arch) { 87 Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PLATFORM)); 88 if (log) { 89 const char *arch_name; 90 if (arch && arch->GetArchitectureName()) 91 arch_name = arch->GetArchitectureName(); 92 else 93 arch_name = "<null>"; 94 95 const char *triple_cstr = 96 arch ? arch->GetTriple().getTriple().c_str() : "<null>"; 97 98 log->Printf("PlatformRemoteAppleTV::%s(force=%s, arch={%s,%s})", 99 __FUNCTION__, force ? "true" : "false", arch_name, triple_cstr); 100 } 101 102 bool create = force; 103 if (!create && arch && arch->IsValid()) { 104 switch (arch->GetMachine()) { 105 case llvm::Triple::arm: 106 case llvm::Triple::aarch64: 107 case llvm::Triple::thumb: { 108 const llvm::Triple &triple = arch->GetTriple(); 109 llvm::Triple::VendorType vendor = triple.getVendor(); 110 switch (vendor) { 111 case llvm::Triple::Apple: 112 create = true; 113 break; 114 115 #if defined(__APPLE__) 116 // Only accept "unknown" for the vendor if the host is Apple and 117 // it "unknown" wasn't specified (it was just returned because it 118 // was NOT specified) 119 case llvm::Triple::UnknownArch: 120 create = !arch->TripleVendorWasSpecified(); 121 break; 122 123 #endif 124 default: 125 break; 126 } 127 if (create) { 128 switch (triple.getOS()) { 129 case llvm::Triple::TvOS: // This is the right triple value for Apple TV 130 // debugging 131 break; 132 133 default: 134 create = false; 135 break; 136 } 137 } 138 } break; 139 default: 140 break; 141 } 142 } 143 144 if (create) { 145 if (log) 146 log->Printf("PlatformRemoteAppleTV::%s() creating platform", 147 __FUNCTION__); 148 149 return lldb::PlatformSP(new PlatformRemoteAppleTV()); 150 } 151 152 if (log) 153 log->Printf("PlatformRemoteAppleTV::%s() aborting creation of platform", 154 __FUNCTION__); 155 156 return lldb::PlatformSP(); 157 } 158 159 lldb_private::ConstString PlatformRemoteAppleTV::GetPluginNameStatic() { 160 static ConstString g_name("remote-tvos"); 161 return g_name; 162 } 163 164 const char *PlatformRemoteAppleTV::GetDescriptionStatic() { 165 return "Remote Apple TV platform plug-in."; 166 } 167 168 void PlatformRemoteAppleTV::GetStatus(Stream &strm) { 169 Platform::GetStatus(strm); 170 const char *sdk_directory = GetDeviceSupportDirectoryForOSVersion(); 171 if (sdk_directory) 172 strm.Printf(" SDK Path: \"%s\"\n", sdk_directory); 173 else 174 strm.PutCString(" SDK Path: error: unable to locate SDK\n"); 175 176 const uint32_t num_sdk_infos = m_sdk_directory_infos.size(); 177 for (uint32_t i = 0; i < num_sdk_infos; ++i) { 178 const SDKDirectoryInfo &sdk_dir_info = m_sdk_directory_infos[i]; 179 strm.Printf(" SDK Roots: [%2u] \"%s\"\n", i, 180 sdk_dir_info.directory.GetPath().c_str()); 181 } 182 } 183 184 Error PlatformRemoteAppleTV::ResolveExecutable( 185 const ModuleSpec &ms, lldb::ModuleSP &exe_module_sp, 186 const FileSpecList *module_search_paths_ptr) { 187 Error error; 188 // Nothing special to do here, just use the actual file and architecture 189 190 ModuleSpec resolved_module_spec(ms); 191 192 // Resolve any executable within a bundle on MacOSX 193 // TODO: verify that this handles shallow bundles, if not then implement one 194 // ourselves 195 Host::ResolveExecutableInBundle(resolved_module_spec.GetFileSpec()); 196 197 if (resolved_module_spec.GetFileSpec().Exists()) { 198 if (resolved_module_spec.GetArchitecture().IsValid() || 199 resolved_module_spec.GetUUID().IsValid()) { 200 error = ModuleList::GetSharedModule(resolved_module_spec, exe_module_sp, 201 nullptr, nullptr, nullptr); 202 203 if (exe_module_sp && exe_module_sp->GetObjectFile()) 204 return error; 205 exe_module_sp.reset(); 206 } 207 // No valid architecture was specified or the exact ARM slice wasn't 208 // found so ask the platform for the architectures that we should be 209 // using (in the correct order) and see if we can find a match that way 210 StreamString arch_names; 211 for (uint32_t idx = 0; GetSupportedArchitectureAtIndex( 212 idx, resolved_module_spec.GetArchitecture()); 213 ++idx) { 214 error = ModuleList::GetSharedModule(resolved_module_spec, exe_module_sp, 215 nullptr, nullptr, nullptr); 216 // Did we find an executable using one of the 217 if (error.Success()) { 218 if (exe_module_sp && exe_module_sp->GetObjectFile()) 219 break; 220 else 221 error.SetErrorToGenericError(); 222 } 223 224 if (idx > 0) 225 arch_names.PutCString(", "); 226 arch_names.PutCString( 227 resolved_module_spec.GetArchitecture().GetArchitectureName()); 228 } 229 230 if (error.Fail() || !exe_module_sp) { 231 if (resolved_module_spec.GetFileSpec().Readable()) { 232 error.SetErrorStringWithFormat( 233 "'%s' doesn't contain any '%s' platform architectures: %s", 234 resolved_module_spec.GetFileSpec().GetPath().c_str(), 235 GetPluginName().GetCString(), arch_names.GetData()); 236 } else { 237 error.SetErrorStringWithFormat( 238 "'%s' is not readable", 239 resolved_module_spec.GetFileSpec().GetPath().c_str()); 240 } 241 } 242 } else { 243 error.SetErrorStringWithFormat( 244 "'%s' does not exist", 245 resolved_module_spec.GetFileSpec().GetPath().c_str()); 246 } 247 248 return error; 249 } 250 251 FileSpec::EnumerateDirectoryResult 252 PlatformRemoteAppleTV::GetContainedFilesIntoVectorOfStringsCallback( 253 void *baton, FileSpec::FileType file_type, const FileSpec &file_spec) { 254 ((PlatformRemoteAppleTV::SDKDirectoryInfoCollection *)baton) 255 ->push_back(PlatformRemoteAppleTV::SDKDirectoryInfo(file_spec)); 256 return FileSpec::eEnumerateDirectoryResultNext; 257 } 258 259 bool PlatformRemoteAppleTV::UpdateSDKDirectoryInfosIfNeeded() { 260 Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST); 261 std::lock_guard<std::mutex> guard(m_sdk_dir_mutex); 262 if (m_sdk_directory_infos.empty()) { 263 const char *device_support_dir = GetDeviceSupportDirectory(); 264 if (log) { 265 log->Printf("PlatformRemoteAppleTV::UpdateSDKDirectoryInfosIfNeeded Got " 266 "DeviceSupport directory %s", 267 device_support_dir); 268 } 269 if (device_support_dir) { 270 const bool find_directories = true; 271 const bool find_files = false; 272 const bool find_other = false; 273 274 SDKDirectoryInfoCollection builtin_sdk_directory_infos; 275 FileSpec::EnumerateDirectory(m_device_support_directory, find_directories, 276 find_files, find_other, 277 GetContainedFilesIntoVectorOfStringsCallback, 278 &builtin_sdk_directory_infos); 279 280 // Only add SDK directories that have symbols in them, some SDKs only 281 // contain 282 // developer disk images and no symbols, so they aren't useful to us. 283 FileSpec sdk_symbols_symlink_fspec; 284 for (const auto &sdk_directory_info : builtin_sdk_directory_infos) { 285 sdk_symbols_symlink_fspec = sdk_directory_info.directory; 286 sdk_symbols_symlink_fspec.AppendPathComponent("Symbols.Internal"); 287 if (sdk_symbols_symlink_fspec.Exists()) { 288 m_sdk_directory_infos.push_back(sdk_directory_info); 289 if (log) { 290 log->Printf("PlatformRemoteAppleTV::" 291 "UpdateSDKDirectoryInfosIfNeeded added builtin SDK " 292 "directory %s", 293 sdk_symbols_symlink_fspec.GetPath().c_str()); 294 } 295 } else { 296 sdk_symbols_symlink_fspec.GetFilename().SetCString("Symbols"); 297 if (sdk_symbols_symlink_fspec.Exists()) 298 m_sdk_directory_infos.push_back(sdk_directory_info); 299 if (log) { 300 log->Printf("PlatformRemoteAppleTV::" 301 "UpdateSDKDirectoryInfosIfNeeded added builtin SDK " 302 "directory %s", 303 sdk_symbols_symlink_fspec.GetPath().c_str()); 304 } 305 } 306 } 307 308 const uint32_t num_installed = m_sdk_directory_infos.size(); 309 FileSpec local_sdk_cache("~/Library/Developer/Xcode/tvOS DeviceSupport", 310 true); 311 if (!local_sdk_cache.Exists()) { 312 // Try looking for another possible name 313 local_sdk_cache = FileSpec( 314 "~/Library/Developer/Xcode/Apple TVOS DeviceSupport", true); 315 } 316 if (!local_sdk_cache.Exists()) { 317 // Try looking for another possible name 318 local_sdk_cache = 319 FileSpec("~/Library/Developer/Xcode/AppleTVOS DeviceSupport", true); 320 } 321 if (!local_sdk_cache.Exists()) { 322 // Try looking for another possible name 323 local_sdk_cache = FileSpec( 324 "~/Library/Developer/Xcode/AppleTV OS DeviceSupport", true); 325 } 326 if (!local_sdk_cache.Exists()) { 327 // Try looking for another possible name 328 local_sdk_cache = FileSpec( 329 "~/Library/Developer/Xcode/Apple TV OS DeviceSupport", true); 330 } 331 if (local_sdk_cache.Exists()) { 332 if (log) { 333 log->Printf("PlatformRemoteAppleTV::UpdateSDKDirectoryInfosIfNeeded " 334 "searching %s for additional SDKs", 335 local_sdk_cache.GetPath().c_str()); 336 } 337 char path[PATH_MAX]; 338 if (local_sdk_cache.GetPath(path, sizeof(path))) { 339 FileSpec::EnumerateDirectory( 340 path, find_directories, find_files, find_other, 341 GetContainedFilesIntoVectorOfStringsCallback, 342 &m_sdk_directory_infos); 343 const uint32_t num_sdk_infos = m_sdk_directory_infos.size(); 344 // First try for an exact match of major, minor and update 345 for (uint32_t i = num_installed; i < num_sdk_infos; ++i) { 346 m_sdk_directory_infos[i].user_cached = true; 347 if (log) { 348 log->Printf("PlatformRemoteAppleTV::" 349 "UpdateSDKDirectoryInfosIfNeeded user SDK directory " 350 "%s", 351 m_sdk_directory_infos[i].directory.GetPath().c_str()); 352 } 353 } 354 } 355 } 356 } 357 } 358 return !m_sdk_directory_infos.empty(); 359 } 360 361 const PlatformRemoteAppleTV::SDKDirectoryInfo * 362 PlatformRemoteAppleTV::GetSDKDirectoryForCurrentOSVersion() { 363 uint32_t i; 364 if (UpdateSDKDirectoryInfosIfNeeded()) { 365 const uint32_t num_sdk_infos = m_sdk_directory_infos.size(); 366 367 // Check to see if the user specified a build string. If they did, then 368 // be sure to match it. 369 std::vector<bool> check_sdk_info(num_sdk_infos, true); 370 ConstString build(m_sdk_build); 371 if (build) { 372 for (i = 0; i < num_sdk_infos; ++i) 373 check_sdk_info[i] = m_sdk_directory_infos[i].build == build; 374 } 375 376 // If we are connected we can find the version of the OS the platform 377 // us running on and select the right SDK 378 uint32_t major, minor, update; 379 if (GetOSVersion(major, minor, update)) { 380 if (UpdateSDKDirectoryInfosIfNeeded()) { 381 // First try for an exact match of major, minor and update 382 for (i = 0; i < num_sdk_infos; ++i) { 383 if (check_sdk_info[i]) { 384 if (m_sdk_directory_infos[i].version_major == major && 385 m_sdk_directory_infos[i].version_minor == minor && 386 m_sdk_directory_infos[i].version_update == update) { 387 return &m_sdk_directory_infos[i]; 388 } 389 } 390 } 391 // First try for an exact match of major and minor 392 for (i = 0; i < num_sdk_infos; ++i) { 393 if (check_sdk_info[i]) { 394 if (m_sdk_directory_infos[i].version_major == major && 395 m_sdk_directory_infos[i].version_minor == minor) { 396 return &m_sdk_directory_infos[i]; 397 } 398 } 399 } 400 // Lastly try to match of major version only.. 401 for (i = 0; i < num_sdk_infos; ++i) { 402 if (check_sdk_info[i]) { 403 if (m_sdk_directory_infos[i].version_major == major) { 404 return &m_sdk_directory_infos[i]; 405 } 406 } 407 } 408 } 409 } else if (build) { 410 // No version, just a build number, search for the first one that matches 411 for (i = 0; i < num_sdk_infos; ++i) 412 if (check_sdk_info[i]) 413 return &m_sdk_directory_infos[i]; 414 } 415 } 416 return nullptr; 417 } 418 419 const PlatformRemoteAppleTV::SDKDirectoryInfo * 420 PlatformRemoteAppleTV::GetSDKDirectoryForLatestOSVersion() { 421 const PlatformRemoteAppleTV::SDKDirectoryInfo *result = nullptr; 422 if (UpdateSDKDirectoryInfosIfNeeded()) { 423 const uint32_t num_sdk_infos = m_sdk_directory_infos.size(); 424 // First try for an exact match of major, minor and update 425 for (uint32_t i = 0; i < num_sdk_infos; ++i) { 426 const SDKDirectoryInfo &sdk_dir_info = m_sdk_directory_infos[i]; 427 if (sdk_dir_info.version_major != UINT32_MAX) { 428 if (result == nullptr || 429 sdk_dir_info.version_major > result->version_major) { 430 result = &sdk_dir_info; 431 } else if (sdk_dir_info.version_major == result->version_major) { 432 if (sdk_dir_info.version_minor > result->version_minor) { 433 result = &sdk_dir_info; 434 } else if (sdk_dir_info.version_minor == result->version_minor) { 435 if (sdk_dir_info.version_update > result->version_update) { 436 result = &sdk_dir_info; 437 } 438 } 439 } 440 } 441 } 442 } 443 return result; 444 } 445 446 const char *PlatformRemoteAppleTV::GetDeviceSupportDirectory() { 447 if (m_device_support_directory.empty()) { 448 const char *device_support_dir = GetDeveloperDirectory(); 449 if (device_support_dir) { 450 m_device_support_directory.assign(device_support_dir); 451 m_device_support_directory.append( 452 "/Platforms/AppleTVOS.platform/DeviceSupport"); 453 } else { 454 // Assign a single NULL character so we know we tried to find the device 455 // support directory and we don't keep trying to find it over and over. 456 m_device_support_directory.assign(1, '\0'); 457 } 458 } 459 // We should have put a single NULL character into m_device_support_directory 460 // or it should have a valid path if the code gets here 461 assert(m_device_support_directory.empty() == false); 462 if (m_device_support_directory[0]) 463 return m_device_support_directory.c_str(); 464 return nullptr; 465 } 466 467 const char *PlatformRemoteAppleTV::GetDeviceSupportDirectoryForOSVersion() { 468 if (m_sdk_sysroot) 469 return m_sdk_sysroot.GetCString(); 470 471 if (m_device_support_directory_for_os_version.empty()) { 472 const PlatformRemoteAppleTV::SDKDirectoryInfo *sdk_dir_info = 473 GetSDKDirectoryForCurrentOSVersion(); 474 if (sdk_dir_info == nullptr) 475 sdk_dir_info = GetSDKDirectoryForLatestOSVersion(); 476 if (sdk_dir_info) { 477 char path[PATH_MAX]; 478 if (sdk_dir_info->directory.GetPath(path, sizeof(path))) { 479 m_device_support_directory_for_os_version = path; 480 return m_device_support_directory_for_os_version.c_str(); 481 } 482 } else { 483 // Assign a single NULL character so we know we tried to find the device 484 // support directory and we don't keep trying to find it over and over. 485 m_device_support_directory_for_os_version.assign(1, '\0'); 486 } 487 } 488 // We should have put a single NULL character into 489 // m_device_support_directory_for_os_version 490 // or it should have a valid path if the code gets here 491 assert(m_device_support_directory_for_os_version.empty() == false); 492 if (m_device_support_directory_for_os_version[0]) 493 return m_device_support_directory_for_os_version.c_str(); 494 return nullptr; 495 } 496 497 uint32_t 498 PlatformRemoteAppleTV::FindFileInAllSDKs(const char *platform_file_path, 499 FileSpecList &file_list) { 500 Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST | 501 LIBLLDB_LOG_VERBOSE); 502 if (platform_file_path && platform_file_path[0] && 503 UpdateSDKDirectoryInfosIfNeeded()) { 504 const uint32_t num_sdk_infos = m_sdk_directory_infos.size(); 505 lldb_private::FileSpec local_file; 506 // First try for an exact match of major, minor and update 507 for (uint32_t sdk_idx = 0; sdk_idx < num_sdk_infos; ++sdk_idx) { 508 if (log) { 509 log->Printf("Searching for %s in sdk path %s", platform_file_path, 510 m_sdk_directory_infos[sdk_idx].directory.GetPath().c_str()); 511 } 512 if (GetFileInSDK(platform_file_path, sdk_idx, local_file)) { 513 file_list.Append(local_file); 514 } 515 } 516 } 517 return file_list.GetSize(); 518 } 519 520 bool PlatformRemoteAppleTV::GetFileInSDK(const char *platform_file_path, 521 uint32_t sdk_idx, 522 lldb_private::FileSpec &local_file) { 523 Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST); 524 if (sdk_idx < m_sdk_directory_infos.size()) { 525 std::string sdkroot_path = 526 m_sdk_directory_infos[sdk_idx].directory.GetPath(); 527 if (!sdkroot_path.empty() && platform_file_path && platform_file_path[0]) { 528 // We may need to interpose "/Symbols/" or "/Symbols.Internal/" between 529 // the 530 // SDK root directory and the file path. 531 532 const char *paths_to_try[] = {"Symbols", "", "Symbols.Internal", nullptr}; 533 for (size_t i = 0; paths_to_try[i] != nullptr; i++) { 534 local_file.SetFile(sdkroot_path, false); 535 if (paths_to_try[i][0] != '\0') 536 local_file.AppendPathComponent(paths_to_try[i]); 537 local_file.AppendPathComponent(platform_file_path); 538 local_file.ResolvePath(); 539 if (local_file.Exists()) { 540 if (log) 541 log->Printf("Found a copy of %s in the SDK dir %s/%s", 542 platform_file_path, sdkroot_path.c_str(), 543 paths_to_try[i]); 544 return true; 545 } 546 local_file.Clear(); 547 } 548 } 549 } 550 return false; 551 } 552 553 Error PlatformRemoteAppleTV::GetSymbolFile(const FileSpec &platform_file, 554 const UUID *uuid_ptr, 555 FileSpec &local_file) { 556 Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST); 557 Error error; 558 char platform_file_path[PATH_MAX]; 559 if (platform_file.GetPath(platform_file_path, sizeof(platform_file_path))) { 560 char resolved_path[PATH_MAX]; 561 562 const char *os_version_dir = GetDeviceSupportDirectoryForOSVersion(); 563 if (os_version_dir) { 564 ::snprintf(resolved_path, sizeof(resolved_path), "%s/%s", os_version_dir, 565 platform_file_path); 566 567 local_file.SetFile(resolved_path, true); 568 if (local_file.Exists()) { 569 if (log) { 570 log->Printf("Found a copy of %s in the DeviceSupport dir %s", 571 platform_file_path, os_version_dir); 572 } 573 return error; 574 } 575 576 ::snprintf(resolved_path, sizeof(resolved_path), "%s/Symbols.Internal/%s", 577 os_version_dir, platform_file_path); 578 579 local_file.SetFile(resolved_path, true); 580 if (local_file.Exists()) { 581 if (log) { 582 log->Printf( 583 "Found a copy of %s in the DeviceSupport dir %s/Symbols.Internal", 584 platform_file_path, os_version_dir); 585 } 586 return error; 587 } 588 ::snprintf(resolved_path, sizeof(resolved_path), "%s/Symbols/%s", 589 os_version_dir, platform_file_path); 590 591 local_file.SetFile(resolved_path, true); 592 if (local_file.Exists()) { 593 if (log) { 594 log->Printf("Found a copy of %s in the DeviceSupport dir %s/Symbols", 595 platform_file_path, os_version_dir); 596 } 597 return error; 598 } 599 } 600 local_file = platform_file; 601 if (local_file.Exists()) 602 return error; 603 604 error.SetErrorStringWithFormat( 605 "unable to locate a platform file for '%s' in platform '%s'", 606 platform_file_path, GetPluginName().GetCString()); 607 } else { 608 error.SetErrorString("invalid platform file argument"); 609 } 610 return error; 611 } 612 613 Error PlatformRemoteAppleTV::GetSharedModule( 614 const ModuleSpec &module_spec, lldb_private::Process *process, 615 ModuleSP &module_sp, const FileSpecList *module_search_paths_ptr, 616 ModuleSP *old_module_sp_ptr, bool *did_create_ptr) { 617 // For Apple TV, the SDK files are all cached locally on the host 618 // system. So first we ask for the file in the cached SDK, 619 // then we attempt to get a shared module for the right architecture 620 // with the right UUID. 621 const FileSpec &platform_file = module_spec.GetFileSpec(); 622 Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST | 623 LIBLLDB_LOG_VERBOSE); 624 625 Error error; 626 char platform_file_path[PATH_MAX]; 627 628 if (platform_file.GetPath(platform_file_path, sizeof(platform_file_path))) { 629 ModuleSpec platform_module_spec(module_spec); 630 631 UpdateSDKDirectoryInfosIfNeeded(); 632 633 const uint32_t num_sdk_infos = m_sdk_directory_infos.size(); 634 635 // If we are connected we migth be able to correctly deduce the SDK 636 // directory 637 // using the OS build. 638 const uint32_t connected_sdk_idx = GetConnectedSDKIndex(); 639 if (connected_sdk_idx < num_sdk_infos) { 640 if (log) { 641 log->Printf("Searching for %s in sdk path %s", platform_file_path, 642 m_sdk_directory_infos[connected_sdk_idx] 643 .directory.GetPath() 644 .c_str()); 645 } 646 if (GetFileInSDK(platform_file_path, connected_sdk_idx, 647 platform_module_spec.GetFileSpec())) { 648 module_sp.reset(); 649 error = ResolveExecutable(platform_module_spec, module_sp, nullptr); 650 if (module_sp) { 651 m_last_module_sdk_idx = connected_sdk_idx; 652 error.Clear(); 653 return error; 654 } 655 } 656 } 657 658 // Try the last SDK index if it is set as most files from an SDK 659 // will tend to be valid in that same SDK. 660 if (m_last_module_sdk_idx < num_sdk_infos) { 661 if (log) { 662 log->Printf("Searching for %s in sdk path %s", platform_file_path, 663 m_sdk_directory_infos[m_last_module_sdk_idx] 664 .directory.GetPath() 665 .c_str()); 666 } 667 if (GetFileInSDK(platform_file_path, m_last_module_sdk_idx, 668 platform_module_spec.GetFileSpec())) { 669 module_sp.reset(); 670 error = ResolveExecutable(platform_module_spec, module_sp, nullptr); 671 if (module_sp) { 672 error.Clear(); 673 return error; 674 } 675 } 676 } 677 678 // First try for an exact match of major, minor and update 679 for (uint32_t sdk_idx = 0; sdk_idx < num_sdk_infos; ++sdk_idx) { 680 if (m_last_module_sdk_idx == sdk_idx) { 681 // Skip the last module SDK index if we already searched 682 // it above 683 continue; 684 } 685 if (log) { 686 log->Printf("Searching for %s in sdk path %s", platform_file_path, 687 m_sdk_directory_infos[sdk_idx].directory.GetPath().c_str()); 688 } 689 if (GetFileInSDK(platform_file_path, sdk_idx, 690 platform_module_spec.GetFileSpec())) { 691 // printf ("sdk[%u]: '%s'\n", sdk_idx, local_file.GetPath().c_str()); 692 693 error = ResolveExecutable(platform_module_spec, module_sp, nullptr); 694 if (module_sp) { 695 // Remember the index of the last SDK that we found a file 696 // in in case the wrong SDK was selected. 697 m_last_module_sdk_idx = sdk_idx; 698 error.Clear(); 699 return error; 700 } 701 } 702 } 703 } 704 // Not the module we are looking for... Nothing to see here... 705 module_sp.reset(); 706 707 // This may not be an SDK-related module. Try whether we can bring in the 708 // thing to our local cache. 709 error = GetSharedModuleWithLocalCache(module_spec, module_sp, 710 module_search_paths_ptr, 711 old_module_sp_ptr, did_create_ptr); 712 if (error.Success()) 713 return error; 714 715 // See if the file is present in any of the module_search_paths_ptr 716 // directories. 717 if (!module_sp && module_search_paths_ptr && platform_file) { 718 // create a vector of all the file / directory names in platform_file 719 // e.g. this might be 720 // /System/Library/PrivateFrameworks/UIFoundation.framework/UIFoundation 721 // 722 // We'll need to look in the module_search_paths_ptr directories for 723 // both "UIFoundation" and "UIFoundation.framework" -- most likely the 724 // latter will be the one we find there. 725 726 FileSpec platform_pull_apart(platform_file); 727 std::vector<std::string> path_parts; 728 ConstString unix_root_dir("/"); 729 while (true) { 730 ConstString part = platform_pull_apart.GetLastPathComponent(); 731 platform_pull_apart.RemoveLastPathComponent(); 732 if (part.IsEmpty() || part == unix_root_dir) 733 break; 734 path_parts.push_back(part.AsCString()); 735 } 736 const size_t path_parts_size = path_parts.size(); 737 738 size_t num_module_search_paths = module_search_paths_ptr->GetSize(); 739 for (size_t i = 0; i < num_module_search_paths; ++i) { 740 // Create a new FileSpec with this module_search_paths_ptr 741 // plus just the filename ("UIFoundation"), then the parent 742 // dir plus filename ("UIFoundation.framework/UIFoundation") 743 // etc - up to four names (to handle "Foo.framework/Contents/MacOS/Foo") 744 745 for (size_t j = 0; j < 4 && j < path_parts_size - 1; ++j) { 746 FileSpec path_to_try(module_search_paths_ptr->GetFileSpecAtIndex(i)); 747 748 // Add the components backwards. For 749 // .../PrivateFrameworks/UIFoundation.framework/UIFoundation 750 // path_parts is 751 // [0] UIFoundation 752 // [1] UIFoundation.framework 753 // [2] PrivateFrameworks 754 // 755 // and if 'j' is 2, we want to append path_parts[1] and then 756 // path_parts[0], aka 757 // 'UIFoundation.framework/UIFoundation', to the module_search_paths_ptr 758 // path. 759 760 for (int k = j; k >= 0; --k) { 761 path_to_try.AppendPathComponent(path_parts[k]); 762 } 763 764 if (path_to_try.Exists()) { 765 ModuleSpec new_module_spec(module_spec); 766 new_module_spec.GetFileSpec() = path_to_try; 767 Error new_error(Platform::GetSharedModule( 768 new_module_spec, process, module_sp, NULL, old_module_sp_ptr, 769 did_create_ptr)); 770 771 if (module_sp) { 772 module_sp->SetPlatformFileSpec(path_to_try); 773 return new_error; 774 } 775 } 776 } 777 } 778 } 779 780 const bool always_create = false; 781 error = ModuleList::GetSharedModule( 782 module_spec, module_sp, module_search_paths_ptr, old_module_sp_ptr, 783 did_create_ptr, always_create); 784 785 if (module_sp) 786 module_sp->SetPlatformFileSpec(platform_file); 787 788 return error; 789 } 790 791 bool PlatformRemoteAppleTV::GetSupportedArchitectureAtIndex(uint32_t idx, 792 ArchSpec &arch) { 793 ArchSpec system_arch(GetSystemArchitecture()); 794 795 const ArchSpec::Core system_core = system_arch.GetCore(); 796 switch (system_core) { 797 default: 798 switch (idx) { 799 case 0: 800 arch.SetTriple("arm64-apple-tvos"); 801 return true; 802 case 1: 803 arch.SetTriple("armv7s-apple-tvos"); 804 return true; 805 case 2: 806 arch.SetTriple("armv7-apple-tvos"); 807 return true; 808 case 3: 809 arch.SetTriple("thumbv7s-apple-tvos"); 810 return true; 811 case 4: 812 arch.SetTriple("thumbv7-apple-tvos"); 813 return true; 814 default: 815 break; 816 } 817 break; 818 819 case ArchSpec::eCore_arm_arm64: 820 switch (idx) { 821 case 0: 822 arch.SetTriple("arm64-apple-tvos"); 823 return true; 824 case 1: 825 arch.SetTriple("armv7s-apple-tvos"); 826 return true; 827 case 2: 828 arch.SetTriple("armv7-apple-tvos"); 829 return true; 830 case 3: 831 arch.SetTriple("thumbv7s-apple-tvos"); 832 return true; 833 case 4: 834 arch.SetTriple("thumbv7-apple-tvos"); 835 return true; 836 default: 837 break; 838 } 839 break; 840 841 case ArchSpec::eCore_arm_armv7s: 842 switch (idx) { 843 case 0: 844 arch.SetTriple("armv7s-apple-tvos"); 845 return true; 846 case 1: 847 arch.SetTriple("armv7-apple-tvos"); 848 return true; 849 case 2: 850 arch.SetTriple("thumbv7s-apple-tvos"); 851 return true; 852 case 3: 853 arch.SetTriple("thumbv7-apple-tvos"); 854 return true; 855 default: 856 break; 857 } 858 break; 859 860 case ArchSpec::eCore_arm_armv7: 861 switch (idx) { 862 case 0: 863 arch.SetTriple("armv7-apple-tvos"); 864 return true; 865 case 1: 866 arch.SetTriple("thumbv7-apple-tvos"); 867 return true; 868 default: 869 break; 870 } 871 break; 872 } 873 arch.Clear(); 874 return false; 875 } 876 877 uint32_t PlatformRemoteAppleTV::GetConnectedSDKIndex() { 878 if (IsConnected()) { 879 if (m_connected_module_sdk_idx == UINT32_MAX) { 880 std::string build; 881 if (GetRemoteOSBuildString(build)) { 882 const uint32_t num_sdk_infos = m_sdk_directory_infos.size(); 883 for (uint32_t i = 0; i < num_sdk_infos; ++i) { 884 const SDKDirectoryInfo &sdk_dir_info = m_sdk_directory_infos[i]; 885 if (strstr(sdk_dir_info.directory.GetFilename().AsCString(""), 886 build.c_str())) { 887 m_connected_module_sdk_idx = i; 888 } 889 } 890 } 891 } 892 } else { 893 m_connected_module_sdk_idx = UINT32_MAX; 894 } 895 return m_connected_module_sdk_idx; 896 } 897