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.GetString().c_str()); 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 if (m_sdk_directory_infos.empty()) { 262 const char *device_support_dir = GetDeviceSupportDirectory(); 263 if (log) { 264 log->Printf("PlatformRemoteAppleTV::UpdateSDKDirectoryInfosIfNeeded Got " 265 "DeviceSupport directory %s", 266 device_support_dir); 267 } 268 if (device_support_dir) { 269 const bool find_directories = true; 270 const bool find_files = false; 271 const bool find_other = false; 272 273 SDKDirectoryInfoCollection builtin_sdk_directory_infos; 274 FileSpec::EnumerateDirectory(m_device_support_directory.c_str(), 275 find_directories, find_files, find_other, 276 GetContainedFilesIntoVectorOfStringsCallback, 277 &builtin_sdk_directory_infos); 278 279 // Only add SDK directories that have symbols in them, some SDKs only 280 // contain 281 // developer disk images and no symbols, so they aren't useful to us. 282 FileSpec sdk_symbols_symlink_fspec; 283 for (const auto &sdk_directory_info : builtin_sdk_directory_infos) { 284 sdk_symbols_symlink_fspec = sdk_directory_info.directory; 285 sdk_symbols_symlink_fspec.AppendPathComponent("Symbols.Internal"); 286 if (sdk_symbols_symlink_fspec.Exists()) { 287 m_sdk_directory_infos.push_back(sdk_directory_info); 288 if (log) { 289 log->Printf("PlatformRemoteAppleTV::" 290 "UpdateSDKDirectoryInfosIfNeeded added builtin SDK " 291 "directory %s", 292 sdk_symbols_symlink_fspec.GetPath().c_str()); 293 } 294 } else { 295 sdk_symbols_symlink_fspec.GetFilename().SetCString("Symbols"); 296 if (sdk_symbols_symlink_fspec.Exists()) 297 m_sdk_directory_infos.push_back(sdk_directory_info); 298 if (log) { 299 log->Printf("PlatformRemoteAppleTV::" 300 "UpdateSDKDirectoryInfosIfNeeded added builtin SDK " 301 "directory %s", 302 sdk_symbols_symlink_fspec.GetPath().c_str()); 303 } 304 } 305 } 306 307 const uint32_t num_installed = m_sdk_directory_infos.size(); 308 FileSpec local_sdk_cache("~/Library/Developer/Xcode/tvOS DeviceSupport", 309 true); 310 if (!local_sdk_cache.Exists()) { 311 // Try looking for another possible name 312 local_sdk_cache = FileSpec( 313 "~/Library/Developer/Xcode/Apple TVOS DeviceSupport", true); 314 } 315 if (!local_sdk_cache.Exists()) { 316 // Try looking for another possible name 317 local_sdk_cache = 318 FileSpec("~/Library/Developer/Xcode/AppleTVOS DeviceSupport", true); 319 } 320 if (!local_sdk_cache.Exists()) { 321 // Try looking for another possible name 322 local_sdk_cache = FileSpec( 323 "~/Library/Developer/Xcode/AppleTV OS DeviceSupport", true); 324 } 325 if (!local_sdk_cache.Exists()) { 326 // Try looking for another possible name 327 local_sdk_cache = FileSpec( 328 "~/Library/Developer/Xcode/Apple TV OS DeviceSupport", true); 329 } 330 if (local_sdk_cache.Exists()) { 331 if (log) { 332 log->Printf("PlatformRemoteAppleTV::UpdateSDKDirectoryInfosIfNeeded " 333 "searching %s for additional SDKs", 334 local_sdk_cache.GetPath().c_str()); 335 } 336 char path[PATH_MAX]; 337 if (local_sdk_cache.GetPath(path, sizeof(path))) { 338 FileSpec::EnumerateDirectory( 339 path, find_directories, find_files, find_other, 340 GetContainedFilesIntoVectorOfStringsCallback, 341 &m_sdk_directory_infos); 342 const uint32_t num_sdk_infos = m_sdk_directory_infos.size(); 343 // First try for an exact match of major, minor and update 344 for (uint32_t i = num_installed; i < num_sdk_infos; ++i) { 345 m_sdk_directory_infos[i].user_cached = true; 346 if (log) { 347 log->Printf("PlatformRemoteAppleTV::" 348 "UpdateSDKDirectoryInfosIfNeeded user SDK directory " 349 "%s", 350 m_sdk_directory_infos[i].directory.GetPath().c_str()); 351 } 352 } 353 } 354 } 355 } 356 } 357 return !m_sdk_directory_infos.empty(); 358 } 359 360 const PlatformRemoteAppleTV::SDKDirectoryInfo * 361 PlatformRemoteAppleTV::GetSDKDirectoryForCurrentOSVersion() { 362 uint32_t i; 363 if (UpdateSDKDirectoryInfosIfNeeded()) { 364 const uint32_t num_sdk_infos = m_sdk_directory_infos.size(); 365 366 // Check to see if the user specified a build string. If they did, then 367 // be sure to match it. 368 std::vector<bool> check_sdk_info(num_sdk_infos, true); 369 ConstString build(m_sdk_build); 370 if (build) { 371 for (i = 0; i < num_sdk_infos; ++i) 372 check_sdk_info[i] = m_sdk_directory_infos[i].build == build; 373 } 374 375 // If we are connected we can find the version of the OS the platform 376 // us running on and select the right SDK 377 uint32_t major, minor, update; 378 if (GetOSVersion(major, minor, update)) { 379 if (UpdateSDKDirectoryInfosIfNeeded()) { 380 // First try for an exact match of major, minor and update 381 for (i = 0; i < num_sdk_infos; ++i) { 382 if (check_sdk_info[i]) { 383 if (m_sdk_directory_infos[i].version_major == major && 384 m_sdk_directory_infos[i].version_minor == minor && 385 m_sdk_directory_infos[i].version_update == update) { 386 return &m_sdk_directory_infos[i]; 387 } 388 } 389 } 390 // First try for an exact match of major and minor 391 for (i = 0; i < num_sdk_infos; ++i) { 392 if (check_sdk_info[i]) { 393 if (m_sdk_directory_infos[i].version_major == major && 394 m_sdk_directory_infos[i].version_minor == minor) { 395 return &m_sdk_directory_infos[i]; 396 } 397 } 398 } 399 // Lastly try to match of major version only.. 400 for (i = 0; i < num_sdk_infos; ++i) { 401 if (check_sdk_info[i]) { 402 if (m_sdk_directory_infos[i].version_major == major) { 403 return &m_sdk_directory_infos[i]; 404 } 405 } 406 } 407 } 408 } else if (build) { 409 // No version, just a build number, search for the first one that matches 410 for (i = 0; i < num_sdk_infos; ++i) 411 if (check_sdk_info[i]) 412 return &m_sdk_directory_infos[i]; 413 } 414 } 415 return nullptr; 416 } 417 418 const PlatformRemoteAppleTV::SDKDirectoryInfo * 419 PlatformRemoteAppleTV::GetSDKDirectoryForLatestOSVersion() { 420 const PlatformRemoteAppleTV::SDKDirectoryInfo *result = nullptr; 421 if (UpdateSDKDirectoryInfosIfNeeded()) { 422 const uint32_t num_sdk_infos = m_sdk_directory_infos.size(); 423 // First try for an exact match of major, minor and update 424 for (uint32_t i = 0; i < num_sdk_infos; ++i) { 425 const SDKDirectoryInfo &sdk_dir_info = m_sdk_directory_infos[i]; 426 if (sdk_dir_info.version_major != UINT32_MAX) { 427 if (result == nullptr || 428 sdk_dir_info.version_major > result->version_major) { 429 result = &sdk_dir_info; 430 } else if (sdk_dir_info.version_major == result->version_major) { 431 if (sdk_dir_info.version_minor > result->version_minor) { 432 result = &sdk_dir_info; 433 } else if (sdk_dir_info.version_minor == result->version_minor) { 434 if (sdk_dir_info.version_update > result->version_update) { 435 result = &sdk_dir_info; 436 } 437 } 438 } 439 } 440 } 441 } 442 return result; 443 } 444 445 const char *PlatformRemoteAppleTV::GetDeviceSupportDirectory() { 446 if (m_device_support_directory.empty()) { 447 const char *device_support_dir = GetDeveloperDirectory(); 448 if (device_support_dir) { 449 m_device_support_directory.assign(device_support_dir); 450 m_device_support_directory.append( 451 "/Platforms/AppleTVOS.platform/DeviceSupport"); 452 } else { 453 // Assign a single NULL character so we know we tried to find the device 454 // support directory and we don't keep trying to find it over and over. 455 m_device_support_directory.assign(1, '\0'); 456 } 457 } 458 // We should have put a single NULL character into m_device_support_directory 459 // or it should have a valid path if the code gets here 460 assert(m_device_support_directory.empty() == false); 461 if (m_device_support_directory[0]) 462 return m_device_support_directory.c_str(); 463 return nullptr; 464 } 465 466 const char *PlatformRemoteAppleTV::GetDeviceSupportDirectoryForOSVersion() { 467 if (m_sdk_sysroot) 468 return m_sdk_sysroot.GetCString(); 469 470 if (m_device_support_directory_for_os_version.empty()) { 471 const PlatformRemoteAppleTV::SDKDirectoryInfo *sdk_dir_info = 472 GetSDKDirectoryForCurrentOSVersion(); 473 if (sdk_dir_info == nullptr) 474 sdk_dir_info = GetSDKDirectoryForLatestOSVersion(); 475 if (sdk_dir_info) { 476 char path[PATH_MAX]; 477 if (sdk_dir_info->directory.GetPath(path, sizeof(path))) { 478 m_device_support_directory_for_os_version = path; 479 return m_device_support_directory_for_os_version.c_str(); 480 } 481 } else { 482 // Assign a single NULL character so we know we tried to find the device 483 // support directory and we don't keep trying to find it over and over. 484 m_device_support_directory_for_os_version.assign(1, '\0'); 485 } 486 } 487 // We should have put a single NULL character into 488 // m_device_support_directory_for_os_version 489 // or it should have a valid path if the code gets here 490 assert(m_device_support_directory_for_os_version.empty() == false); 491 if (m_device_support_directory_for_os_version[0]) 492 return m_device_support_directory_for_os_version.c_str(); 493 return nullptr; 494 } 495 496 uint32_t 497 PlatformRemoteAppleTV::FindFileInAllSDKs(const char *platform_file_path, 498 FileSpecList &file_list) { 499 Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST | 500 LIBLLDB_LOG_VERBOSE); 501 if (platform_file_path && platform_file_path[0] && 502 UpdateSDKDirectoryInfosIfNeeded()) { 503 const uint32_t num_sdk_infos = m_sdk_directory_infos.size(); 504 lldb_private::FileSpec local_file; 505 // First try for an exact match of major, minor and update 506 for (uint32_t sdk_idx = 0; sdk_idx < num_sdk_infos; ++sdk_idx) { 507 if (log) { 508 log->Printf("Searching for %s in sdk path %s", platform_file_path, 509 m_sdk_directory_infos[sdk_idx].directory.GetPath().c_str()); 510 } 511 if (GetFileInSDK(platform_file_path, sdk_idx, local_file)) { 512 file_list.Append(local_file); 513 } 514 } 515 } 516 return file_list.GetSize(); 517 } 518 519 bool PlatformRemoteAppleTV::GetFileInSDK(const char *platform_file_path, 520 uint32_t sdk_idx, 521 lldb_private::FileSpec &local_file) { 522 Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST); 523 if (sdk_idx < m_sdk_directory_infos.size()) { 524 std::string sdkroot_path = 525 m_sdk_directory_infos[sdk_idx].directory.GetPath(); 526 if (!sdkroot_path.empty() && platform_file_path && platform_file_path[0]) { 527 // We may need to interpose "/Symbols/" or "/Symbols.Internal/" between 528 // the 529 // SDK root directory and the file path. 530 531 const char *paths_to_try[] = {"Symbols", "", "Symbols.Internal", nullptr}; 532 for (size_t i = 0; paths_to_try[i] != nullptr; i++) { 533 local_file.SetFile(sdkroot_path.c_str(), false); 534 if (paths_to_try[i][0] != '\0') 535 local_file.AppendPathComponent(paths_to_try[i]); 536 local_file.AppendPathComponent(platform_file_path); 537 local_file.ResolvePath(); 538 if (local_file.Exists()) { 539 if (log) 540 log->Printf("Found a copy of %s in the SDK dir %s/%s", 541 platform_file_path, sdkroot_path.c_str(), 542 paths_to_try[i]); 543 return true; 544 } 545 local_file.Clear(); 546 } 547 } 548 } 549 return false; 550 } 551 552 Error PlatformRemoteAppleTV::GetSymbolFile(const FileSpec &platform_file, 553 const UUID *uuid_ptr, 554 FileSpec &local_file) { 555 Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST); 556 Error error; 557 char platform_file_path[PATH_MAX]; 558 if (platform_file.GetPath(platform_file_path, sizeof(platform_file_path))) { 559 char resolved_path[PATH_MAX]; 560 561 const char *os_version_dir = GetDeviceSupportDirectoryForOSVersion(); 562 if (os_version_dir) { 563 ::snprintf(resolved_path, sizeof(resolved_path), "%s/%s", os_version_dir, 564 platform_file_path); 565 566 local_file.SetFile(resolved_path, true); 567 if (local_file.Exists()) { 568 if (log) { 569 log->Printf("Found a copy of %s in the DeviceSupport dir %s", 570 platform_file_path, os_version_dir); 571 } 572 return error; 573 } 574 575 ::snprintf(resolved_path, sizeof(resolved_path), "%s/Symbols.Internal/%s", 576 os_version_dir, platform_file_path); 577 578 local_file.SetFile(resolved_path, true); 579 if (local_file.Exists()) { 580 if (log) { 581 log->Printf( 582 "Found a copy of %s in the DeviceSupport dir %s/Symbols.Internal", 583 platform_file_path, os_version_dir); 584 } 585 return error; 586 } 587 ::snprintf(resolved_path, sizeof(resolved_path), "%s/Symbols/%s", 588 os_version_dir, platform_file_path); 589 590 local_file.SetFile(resolved_path, true); 591 if (local_file.Exists()) { 592 if (log) { 593 log->Printf("Found a copy of %s in the DeviceSupport dir %s/Symbols", 594 platform_file_path, os_version_dir); 595 } 596 return error; 597 } 598 } 599 local_file = platform_file; 600 if (local_file.Exists()) 601 return error; 602 603 error.SetErrorStringWithFormat( 604 "unable to locate a platform file for '%s' in platform '%s'", 605 platform_file_path, GetPluginName().GetCString()); 606 } else { 607 error.SetErrorString("invalid platform file argument"); 608 } 609 return error; 610 } 611 612 Error PlatformRemoteAppleTV::GetSharedModule( 613 const ModuleSpec &module_spec, lldb_private::Process *process, 614 ModuleSP &module_sp, const FileSpecList *module_search_paths_ptr, 615 ModuleSP *old_module_sp_ptr, bool *did_create_ptr) { 616 // For Apple TV, the SDK files are all cached locally on the host 617 // system. So first we ask for the file in the cached SDK, 618 // then we attempt to get a shared module for the right architecture 619 // with the right UUID. 620 const FileSpec &platform_file = module_spec.GetFileSpec(); 621 Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST | 622 LIBLLDB_LOG_VERBOSE); 623 624 Error error; 625 char platform_file_path[PATH_MAX]; 626 627 if (platform_file.GetPath(platform_file_path, sizeof(platform_file_path))) { 628 ModuleSpec platform_module_spec(module_spec); 629 630 UpdateSDKDirectoryInfosIfNeeded(); 631 632 const uint32_t num_sdk_infos = m_sdk_directory_infos.size(); 633 634 // If we are connected we migth be able to correctly deduce the SDK 635 // directory 636 // using the OS build. 637 const uint32_t connected_sdk_idx = GetConnectedSDKIndex(); 638 if (connected_sdk_idx < num_sdk_infos) { 639 if (log) { 640 log->Printf("Searching for %s in sdk path %s", platform_file_path, 641 m_sdk_directory_infos[connected_sdk_idx] 642 .directory.GetPath() 643 .c_str()); 644 } 645 if (GetFileInSDK(platform_file_path, connected_sdk_idx, 646 platform_module_spec.GetFileSpec())) { 647 module_sp.reset(); 648 error = ResolveExecutable(platform_module_spec, module_sp, nullptr); 649 if (module_sp) { 650 m_last_module_sdk_idx = connected_sdk_idx; 651 error.Clear(); 652 return error; 653 } 654 } 655 } 656 657 // Try the last SDK index if it is set as most files from an SDK 658 // will tend to be valid in that same SDK. 659 if (m_last_module_sdk_idx < num_sdk_infos) { 660 if (log) { 661 log->Printf("Searching for %s in sdk path %s", platform_file_path, 662 m_sdk_directory_infos[m_last_module_sdk_idx] 663 .directory.GetPath() 664 .c_str()); 665 } 666 if (GetFileInSDK(platform_file_path, m_last_module_sdk_idx, 667 platform_module_spec.GetFileSpec())) { 668 module_sp.reset(); 669 error = ResolveExecutable(platform_module_spec, module_sp, nullptr); 670 if (module_sp) { 671 error.Clear(); 672 return error; 673 } 674 } 675 } 676 677 // First try for an exact match of major, minor and update 678 for (uint32_t sdk_idx = 0; sdk_idx < num_sdk_infos; ++sdk_idx) { 679 if (m_last_module_sdk_idx == sdk_idx) { 680 // Skip the last module SDK index if we already searched 681 // it above 682 continue; 683 } 684 if (log) { 685 log->Printf("Searching for %s in sdk path %s", platform_file_path, 686 m_sdk_directory_infos[sdk_idx].directory.GetPath().c_str()); 687 } 688 if (GetFileInSDK(platform_file_path, sdk_idx, 689 platform_module_spec.GetFileSpec())) { 690 // printf ("sdk[%u]: '%s'\n", sdk_idx, local_file.GetPath().c_str()); 691 692 error = ResolveExecutable(platform_module_spec, module_sp, nullptr); 693 if (module_sp) { 694 // Remember the index of the last SDK that we found a file 695 // in in case the wrong SDK was selected. 696 m_last_module_sdk_idx = sdk_idx; 697 error.Clear(); 698 return error; 699 } 700 } 701 } 702 } 703 // Not the module we are looking for... Nothing to see here... 704 module_sp.reset(); 705 706 // This may not be an SDK-related module. Try whether we can bring in the 707 // thing to our local cache. 708 error = GetSharedModuleWithLocalCache(module_spec, module_sp, 709 module_search_paths_ptr, 710 old_module_sp_ptr, did_create_ptr); 711 if (error.Success()) 712 return error; 713 714 // See if the file is present in any of the module_search_paths_ptr 715 // directories. 716 if (!module_sp && module_search_paths_ptr && platform_file) { 717 // create a vector of all the file / directory names in platform_file 718 // e.g. this might be 719 // /System/Library/PrivateFrameworks/UIFoundation.framework/UIFoundation 720 // 721 // We'll need to look in the module_search_paths_ptr directories for 722 // both "UIFoundation" and "UIFoundation.framework" -- most likely the 723 // latter will be the one we find there. 724 725 FileSpec platform_pull_apart(platform_file); 726 std::vector<std::string> path_parts; 727 ConstString unix_root_dir("/"); 728 while (true) { 729 ConstString part = platform_pull_apart.GetLastPathComponent(); 730 platform_pull_apart.RemoveLastPathComponent(); 731 if (part.IsEmpty() || part == unix_root_dir) 732 break; 733 path_parts.push_back(part.AsCString()); 734 } 735 const size_t path_parts_size = path_parts.size(); 736 737 size_t num_module_search_paths = module_search_paths_ptr->GetSize(); 738 for (size_t i = 0; i < num_module_search_paths; ++i) { 739 // Create a new FileSpec with this module_search_paths_ptr 740 // plus just the filename ("UIFoundation"), then the parent 741 // dir plus filename ("UIFoundation.framework/UIFoundation") 742 // etc - up to four names (to handle "Foo.framework/Contents/MacOS/Foo") 743 744 for (size_t j = 0; j < 4 && j < path_parts_size - 1; ++j) { 745 FileSpec path_to_try(module_search_paths_ptr->GetFileSpecAtIndex(i)); 746 747 // Add the components backwards. For 748 // .../PrivateFrameworks/UIFoundation.framework/UIFoundation 749 // path_parts is 750 // [0] UIFoundation 751 // [1] UIFoundation.framework 752 // [2] PrivateFrameworks 753 // 754 // and if 'j' is 2, we want to append path_parts[1] and then 755 // path_parts[0], aka 756 // 'UIFoundation.framework/UIFoundation', to the module_search_paths_ptr 757 // path. 758 759 for (int k = j; k >= 0; --k) { 760 path_to_try.AppendPathComponent(path_parts[k]); 761 } 762 763 if (path_to_try.Exists()) { 764 ModuleSpec new_module_spec(module_spec); 765 new_module_spec.GetFileSpec() = path_to_try; 766 Error new_error(Platform::GetSharedModule( 767 new_module_spec, process, module_sp, NULL, old_module_sp_ptr, 768 did_create_ptr)); 769 770 if (module_sp) { 771 module_sp->SetPlatformFileSpec(path_to_try); 772 return new_error; 773 } 774 } 775 } 776 } 777 } 778 779 const bool always_create = false; 780 error = ModuleList::GetSharedModule( 781 module_spec, module_sp, module_search_paths_ptr, old_module_sp_ptr, 782 did_create_ptr, always_create); 783 784 if (module_sp) 785 module_sp->SetPlatformFileSpec(platform_file); 786 787 return error; 788 } 789 790 bool PlatformRemoteAppleTV::GetSupportedArchitectureAtIndex(uint32_t idx, 791 ArchSpec &arch) { 792 ArchSpec system_arch(GetSystemArchitecture()); 793 794 const ArchSpec::Core system_core = system_arch.GetCore(); 795 switch (system_core) { 796 default: 797 switch (idx) { 798 case 0: 799 arch.SetTriple("arm64-apple-tvos"); 800 return true; 801 case 1: 802 arch.SetTriple("armv7s-apple-tvos"); 803 return true; 804 case 2: 805 arch.SetTriple("armv7-apple-tvos"); 806 return true; 807 case 3: 808 arch.SetTriple("thumbv7s-apple-tvos"); 809 return true; 810 case 4: 811 arch.SetTriple("thumbv7-apple-tvos"); 812 return true; 813 default: 814 break; 815 } 816 break; 817 818 case ArchSpec::eCore_arm_arm64: 819 switch (idx) { 820 case 0: 821 arch.SetTriple("arm64-apple-tvos"); 822 return true; 823 case 1: 824 arch.SetTriple("armv7s-apple-tvos"); 825 return true; 826 case 2: 827 arch.SetTriple("armv7-apple-tvos"); 828 return true; 829 case 3: 830 arch.SetTriple("thumbv7s-apple-tvos"); 831 return true; 832 case 4: 833 arch.SetTriple("thumbv7-apple-tvos"); 834 return true; 835 default: 836 break; 837 } 838 break; 839 840 case ArchSpec::eCore_arm_armv7s: 841 switch (idx) { 842 case 0: 843 arch.SetTriple("armv7s-apple-tvos"); 844 return true; 845 case 1: 846 arch.SetTriple("armv7-apple-tvos"); 847 return true; 848 case 2: 849 arch.SetTriple("thumbv7s-apple-tvos"); 850 return true; 851 case 3: 852 arch.SetTriple("thumbv7-apple-tvos"); 853 return true; 854 default: 855 break; 856 } 857 break; 858 859 case ArchSpec::eCore_arm_armv7: 860 switch (idx) { 861 case 0: 862 arch.SetTriple("armv7-apple-tvos"); 863 return true; 864 case 1: 865 arch.SetTriple("thumbv7-apple-tvos"); 866 return true; 867 default: 868 break; 869 } 870 break; 871 } 872 arch.Clear(); 873 return false; 874 } 875 876 uint32_t PlatformRemoteAppleTV::GetConnectedSDKIndex() { 877 if (IsConnected()) { 878 if (m_connected_module_sdk_idx == UINT32_MAX) { 879 std::string build; 880 if (GetRemoteOSBuildString(build)) { 881 const uint32_t num_sdk_infos = m_sdk_directory_infos.size(); 882 for (uint32_t i = 0; i < num_sdk_infos; ++i) { 883 const SDKDirectoryInfo &sdk_dir_info = m_sdk_directory_infos[i]; 884 if (strstr(sdk_dir_info.directory.GetFilename().AsCString(""), 885 build.c_str())) { 886 m_connected_module_sdk_idx = i; 887 } 888 } 889 } 890 } 891 } else { 892 m_connected_module_sdk_idx = UINT32_MAX; 893 } 894 return m_connected_module_sdk_idx; 895 } 896