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