1 //===-- PlatformDarwin.cpp ------------------------------------------------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #include "PlatformDarwin.h" 10 11 #include <string.h> 12 13 #include <algorithm> 14 #include <memory> 15 #include <mutex> 16 17 #include "lldb/Breakpoint/BreakpointLocation.h" 18 #include "lldb/Breakpoint/BreakpointSite.h" 19 #include "lldb/Core/Debugger.h" 20 #include "lldb/Core/Module.h" 21 #include "lldb/Core/ModuleSpec.h" 22 #include "lldb/Core/Section.h" 23 #include "lldb/Host/Host.h" 24 #include "lldb/Host/HostInfo.h" 25 #include "lldb/Host/XML.h" 26 #include "lldb/Interpreter/CommandInterpreter.h" 27 #include "lldb/Symbol/LocateSymbolFile.h" 28 #include "lldb/Symbol/ObjectFile.h" 29 #include "lldb/Symbol/SymbolFile.h" 30 #include "lldb/Symbol/SymbolVendor.h" 31 #include "lldb/Target/Platform.h" 32 #include "lldb/Target/Process.h" 33 #include "lldb/Target/Target.h" 34 #include "lldb/Utility/Log.h" 35 #include "lldb/Utility/ProcessInfo.h" 36 #include "lldb/Utility/Status.h" 37 #include "lldb/Utility/Timer.h" 38 #include "llvm/ADT/STLExtras.h" 39 #include "llvm/Support/FileSystem.h" 40 #include "llvm/Support/Threading.h" 41 #include "llvm/Support/VersionTuple.h" 42 43 #if defined(__APPLE__) 44 #include <TargetConditionals.h> 45 #endif 46 47 using namespace lldb; 48 using namespace lldb_private; 49 50 /// Default Constructor 51 PlatformDarwin::PlatformDarwin(bool is_host) : PlatformPOSIX(is_host) {} 52 53 /// Destructor. 54 /// 55 /// The destructor is virtual since this class is designed to be 56 /// inherited from by the plug-in instance. 57 PlatformDarwin::~PlatformDarwin() {} 58 59 lldb_private::Status 60 PlatformDarwin::PutFile(const lldb_private::FileSpec &source, 61 const lldb_private::FileSpec &destination, uint32_t uid, 62 uint32_t gid) { 63 // Unconditionally unlink the destination. If it is an executable, 64 // simply opening it and truncating its contents would invalidate 65 // its cached code signature. 66 Unlink(destination); 67 return PlatformPOSIX::PutFile(source, destination, uid, gid); 68 } 69 70 FileSpecList PlatformDarwin::LocateExecutableScriptingResources( 71 Target *target, Module &module, Stream *feedback_stream) { 72 FileSpecList file_list; 73 if (target && 74 target->GetDebugger().GetScriptLanguage() == eScriptLanguagePython) { 75 // NB some extensions might be meaningful and should not be stripped - 76 // "this.binary.file" 77 // should not lose ".file" but GetFileNameStrippingExtension() will do 78 // precisely that. Ideally, we should have a per-platform list of 79 // extensions (".exe", ".app", ".dSYM", ".framework") which should be 80 // stripped while leaving "this.binary.file" as-is. 81 82 FileSpec module_spec = module.GetFileSpec(); 83 84 if (module_spec) { 85 if (SymbolFile *symfile = module.GetSymbolFile()) { 86 ObjectFile *objfile = symfile->GetObjectFile(); 87 if (objfile) { 88 FileSpec symfile_spec(objfile->GetFileSpec()); 89 if (symfile_spec && 90 strcasestr(symfile_spec.GetPath().c_str(), 91 ".dSYM/Contents/Resources/DWARF") != nullptr && 92 FileSystem::Instance().Exists(symfile_spec)) { 93 while (module_spec.GetFilename()) { 94 std::string module_basename( 95 module_spec.GetFilename().GetCString()); 96 std::string original_module_basename(module_basename); 97 98 bool was_keyword = false; 99 100 // FIXME: for Python, we cannot allow certain characters in 101 // module 102 // filenames we import. Theoretically, different scripting 103 // languages may have different sets of forbidden tokens in 104 // filenames, and that should be dealt with by each 105 // ScriptInterpreter. For now, we just replace dots with 106 // underscores, but if we ever support anything other than 107 // Python we will need to rework this 108 std::replace(module_basename.begin(), module_basename.end(), '.', 109 '_'); 110 std::replace(module_basename.begin(), module_basename.end(), ' ', 111 '_'); 112 std::replace(module_basename.begin(), module_basename.end(), '-', 113 '_'); 114 ScriptInterpreter *script_interpreter = 115 target->GetDebugger().GetScriptInterpreter(); 116 if (script_interpreter && 117 script_interpreter->IsReservedWord(module_basename.c_str())) { 118 module_basename.insert(module_basename.begin(), '_'); 119 was_keyword = true; 120 } 121 122 StreamString path_string; 123 StreamString original_path_string; 124 // for OSX we are going to be in 125 // .dSYM/Contents/Resources/DWARF/<basename> let us go to 126 // .dSYM/Contents/Resources/Python/<basename>.py and see if the 127 // file exists 128 path_string.Printf("%s/../Python/%s.py", 129 symfile_spec.GetDirectory().GetCString(), 130 module_basename.c_str()); 131 original_path_string.Printf( 132 "%s/../Python/%s.py", 133 symfile_spec.GetDirectory().GetCString(), 134 original_module_basename.c_str()); 135 FileSpec script_fspec(path_string.GetString()); 136 FileSystem::Instance().Resolve(script_fspec); 137 FileSpec orig_script_fspec(original_path_string.GetString()); 138 FileSystem::Instance().Resolve(orig_script_fspec); 139 140 // if we did some replacements of reserved characters, and a 141 // file with the untampered name exists, then warn the user 142 // that the file as-is shall not be loaded 143 if (feedback_stream) { 144 if (module_basename != original_module_basename && 145 FileSystem::Instance().Exists(orig_script_fspec)) { 146 const char *reason_for_complaint = 147 was_keyword ? "conflicts with a keyword" 148 : "contains reserved characters"; 149 if (FileSystem::Instance().Exists(script_fspec)) 150 feedback_stream->Printf( 151 "warning: the symbol file '%s' contains a debug " 152 "script. However, its name" 153 " '%s' %s and as such cannot be loaded. LLDB will" 154 " load '%s' instead. Consider removing the file with " 155 "the malformed name to" 156 " eliminate this warning.\n", 157 symfile_spec.GetPath().c_str(), 158 original_path_string.GetData(), reason_for_complaint, 159 path_string.GetData()); 160 else 161 feedback_stream->Printf( 162 "warning: the symbol file '%s' contains a debug " 163 "script. However, its name" 164 " %s and as such cannot be loaded. If you intend" 165 " to have this script loaded, please rename '%s' to " 166 "'%s' and retry.\n", 167 symfile_spec.GetPath().c_str(), reason_for_complaint, 168 original_path_string.GetData(), path_string.GetData()); 169 } 170 } 171 172 if (FileSystem::Instance().Exists(script_fspec)) { 173 file_list.Append(script_fspec); 174 break; 175 } 176 177 // If we didn't find the python file, then keep stripping the 178 // extensions and try again 179 ConstString filename_no_extension( 180 module_spec.GetFileNameStrippingExtension()); 181 if (module_spec.GetFilename() == filename_no_extension) 182 break; 183 184 module_spec.GetFilename() = filename_no_extension; 185 } 186 } 187 } 188 } 189 } 190 } 191 return file_list; 192 } 193 194 Status PlatformDarwin::ResolveSymbolFile(Target &target, 195 const ModuleSpec &sym_spec, 196 FileSpec &sym_file) { 197 sym_file = sym_spec.GetSymbolFileSpec(); 198 if (FileSystem::Instance().IsDirectory(sym_file)) { 199 sym_file = Symbols::FindSymbolFileInBundle(sym_file, sym_spec.GetUUIDPtr(), 200 sym_spec.GetArchitecturePtr()); 201 } 202 return {}; 203 } 204 205 static lldb_private::Status 206 MakeCacheFolderForFile(const FileSpec &module_cache_spec) { 207 FileSpec module_cache_folder = 208 module_cache_spec.CopyByRemovingLastPathComponent(); 209 return llvm::sys::fs::create_directory(module_cache_folder.GetPath()); 210 } 211 212 static lldb_private::Status 213 BringInRemoteFile(Platform *platform, 214 const lldb_private::ModuleSpec &module_spec, 215 const FileSpec &module_cache_spec) { 216 MakeCacheFolderForFile(module_cache_spec); 217 Status err = platform->GetFile(module_spec.GetFileSpec(), module_cache_spec); 218 return err; 219 } 220 221 lldb_private::Status PlatformDarwin::GetSharedModuleWithLocalCache( 222 const lldb_private::ModuleSpec &module_spec, lldb::ModuleSP &module_sp, 223 const lldb_private::FileSpecList *module_search_paths_ptr, 224 lldb::ModuleSP *old_module_sp_ptr, bool *did_create_ptr) { 225 226 Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PLATFORM)); 227 LLDB_LOGF(log, 228 "[%s] Trying to find module %s/%s - platform path %s/%s symbol " 229 "path %s/%s", 230 (IsHost() ? "host" : "remote"), 231 module_spec.GetFileSpec().GetDirectory().AsCString(), 232 module_spec.GetFileSpec().GetFilename().AsCString(), 233 module_spec.GetPlatformFileSpec().GetDirectory().AsCString(), 234 module_spec.GetPlatformFileSpec().GetFilename().AsCString(), 235 module_spec.GetSymbolFileSpec().GetDirectory().AsCString(), 236 module_spec.GetSymbolFileSpec().GetFilename().AsCString()); 237 238 Status err; 239 240 err = ModuleList::GetSharedModule(module_spec, module_sp, 241 module_search_paths_ptr, old_module_sp_ptr, 242 did_create_ptr); 243 if (module_sp) 244 return err; 245 246 if (!IsHost()) { 247 std::string cache_path(GetLocalCacheDirectory()); 248 // Only search for a locally cached file if we have a valid cache path 249 if (!cache_path.empty()) { 250 std::string module_path(module_spec.GetFileSpec().GetPath()); 251 cache_path.append(module_path); 252 FileSpec module_cache_spec(cache_path); 253 254 // if rsync is supported, always bring in the file - rsync will be very 255 // efficient when files are the same on the local and remote end of the 256 // connection 257 if (this->GetSupportsRSync()) { 258 err = BringInRemoteFile(this, module_spec, module_cache_spec); 259 if (err.Fail()) 260 return err; 261 if (FileSystem::Instance().Exists(module_cache_spec)) { 262 Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PLATFORM)); 263 LLDB_LOGF(log, "[%s] module %s/%s was rsynced and is now there", 264 (IsHost() ? "host" : "remote"), 265 module_spec.GetFileSpec().GetDirectory().AsCString(), 266 module_spec.GetFileSpec().GetFilename().AsCString()); 267 ModuleSpec local_spec(module_cache_spec, 268 module_spec.GetArchitecture()); 269 module_sp = std::make_shared<Module>(local_spec); 270 module_sp->SetPlatformFileSpec(module_spec.GetFileSpec()); 271 return Status(); 272 } 273 } 274 275 // try to find the module in the cache 276 if (FileSystem::Instance().Exists(module_cache_spec)) { 277 // get the local and remote MD5 and compare 278 if (m_remote_platform_sp) { 279 // when going over the *slow* GDB remote transfer mechanism we first 280 // check the hashes of the files - and only do the actual transfer if 281 // they differ 282 uint64_t high_local, high_remote, low_local, low_remote; 283 auto MD5 = llvm::sys::fs::md5_contents(module_cache_spec.GetPath()); 284 if (!MD5) 285 return Status(MD5.getError()); 286 std::tie(high_local, low_local) = MD5->words(); 287 288 m_remote_platform_sp->CalculateMD5(module_spec.GetFileSpec(), 289 low_remote, high_remote); 290 if (low_local != low_remote || high_local != high_remote) { 291 // bring in the remote file 292 Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PLATFORM)); 293 LLDB_LOGF(log, 294 "[%s] module %s/%s needs to be replaced from remote copy", 295 (IsHost() ? "host" : "remote"), 296 module_spec.GetFileSpec().GetDirectory().AsCString(), 297 module_spec.GetFileSpec().GetFilename().AsCString()); 298 Status err = 299 BringInRemoteFile(this, module_spec, module_cache_spec); 300 if (err.Fail()) 301 return err; 302 } 303 } 304 305 ModuleSpec local_spec(module_cache_spec, module_spec.GetArchitecture()); 306 module_sp = std::make_shared<Module>(local_spec); 307 module_sp->SetPlatformFileSpec(module_spec.GetFileSpec()); 308 Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PLATFORM)); 309 LLDB_LOGF(log, "[%s] module %s/%s was found in the cache", 310 (IsHost() ? "host" : "remote"), 311 module_spec.GetFileSpec().GetDirectory().AsCString(), 312 module_spec.GetFileSpec().GetFilename().AsCString()); 313 return Status(); 314 } 315 316 // bring in the remote module file 317 LLDB_LOGF(log, "[%s] module %s/%s needs to come in remotely", 318 (IsHost() ? "host" : "remote"), 319 module_spec.GetFileSpec().GetDirectory().AsCString(), 320 module_spec.GetFileSpec().GetFilename().AsCString()); 321 Status err = BringInRemoteFile(this, module_spec, module_cache_spec); 322 if (err.Fail()) 323 return err; 324 if (FileSystem::Instance().Exists(module_cache_spec)) { 325 Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PLATFORM)); 326 LLDB_LOGF(log, "[%s] module %s/%s is now cached and fine", 327 (IsHost() ? "host" : "remote"), 328 module_spec.GetFileSpec().GetDirectory().AsCString(), 329 module_spec.GetFileSpec().GetFilename().AsCString()); 330 ModuleSpec local_spec(module_cache_spec, module_spec.GetArchitecture()); 331 module_sp = std::make_shared<Module>(local_spec); 332 module_sp->SetPlatformFileSpec(module_spec.GetFileSpec()); 333 return Status(); 334 } else 335 return Status("unable to obtain valid module file"); 336 } else 337 return Status("no cache path"); 338 } else 339 return Status("unable to resolve module"); 340 } 341 342 Status PlatformDarwin::GetSharedModule( 343 const ModuleSpec &module_spec, Process *process, ModuleSP &module_sp, 344 const FileSpecList *module_search_paths_ptr, ModuleSP *old_module_sp_ptr, 345 bool *did_create_ptr) { 346 Status error; 347 module_sp.reset(); 348 349 if (IsRemote()) { 350 // If we have a remote platform always, let it try and locate the shared 351 // module first. 352 if (m_remote_platform_sp) { 353 error = m_remote_platform_sp->GetSharedModule( 354 module_spec, process, module_sp, module_search_paths_ptr, 355 old_module_sp_ptr, did_create_ptr); 356 } 357 } 358 359 if (!module_sp) { 360 // Fall back to the local platform and find the file locally 361 error = Platform::GetSharedModule(module_spec, process, module_sp, 362 module_search_paths_ptr, 363 old_module_sp_ptr, did_create_ptr); 364 365 const FileSpec &platform_file = module_spec.GetFileSpec(); 366 if (!module_sp && module_search_paths_ptr && platform_file) { 367 // We can try to pull off part of the file path up to the bundle 368 // directory level and try any module search paths... 369 FileSpec bundle_directory; 370 if (Host::GetBundleDirectory(platform_file, bundle_directory)) { 371 if (platform_file == bundle_directory) { 372 ModuleSpec new_module_spec(module_spec); 373 new_module_spec.GetFileSpec() = bundle_directory; 374 if (Host::ResolveExecutableInBundle(new_module_spec.GetFileSpec())) { 375 Status new_error(Platform::GetSharedModule( 376 new_module_spec, process, module_sp, nullptr, old_module_sp_ptr, 377 did_create_ptr)); 378 379 if (module_sp) 380 return new_error; 381 } 382 } else { 383 char platform_path[PATH_MAX]; 384 char bundle_dir[PATH_MAX]; 385 platform_file.GetPath(platform_path, sizeof(platform_path)); 386 const size_t bundle_directory_len = 387 bundle_directory.GetPath(bundle_dir, sizeof(bundle_dir)); 388 char new_path[PATH_MAX]; 389 size_t num_module_search_paths = module_search_paths_ptr->GetSize(); 390 for (size_t i = 0; i < num_module_search_paths; ++i) { 391 const size_t search_path_len = 392 module_search_paths_ptr->GetFileSpecAtIndex(i).GetPath( 393 new_path, sizeof(new_path)); 394 if (search_path_len < sizeof(new_path)) { 395 snprintf(new_path + search_path_len, 396 sizeof(new_path) - search_path_len, "/%s", 397 platform_path + bundle_directory_len); 398 FileSpec new_file_spec(new_path); 399 if (FileSystem::Instance().Exists(new_file_spec)) { 400 ModuleSpec new_module_spec(module_spec); 401 new_module_spec.GetFileSpec() = new_file_spec; 402 Status new_error(Platform::GetSharedModule( 403 new_module_spec, process, module_sp, nullptr, 404 old_module_sp_ptr, did_create_ptr)); 405 406 if (module_sp) { 407 module_sp->SetPlatformFileSpec(new_file_spec); 408 return new_error; 409 } 410 } 411 } 412 } 413 } 414 } 415 } 416 } 417 if (module_sp) 418 module_sp->SetPlatformFileSpec(module_spec.GetFileSpec()); 419 return error; 420 } 421 422 size_t 423 PlatformDarwin::GetSoftwareBreakpointTrapOpcode(Target &target, 424 BreakpointSite *bp_site) { 425 const uint8_t *trap_opcode = nullptr; 426 uint32_t trap_opcode_size = 0; 427 bool bp_is_thumb = false; 428 429 llvm::Triple::ArchType machine = target.GetArchitecture().GetMachine(); 430 switch (machine) { 431 case llvm::Triple::aarch64_32: 432 case llvm::Triple::aarch64: { 433 // 'brk #0' or 0xd4200000 in BE byte order 434 static const uint8_t g_arm64_breakpoint_opcode[] = {0x00, 0x00, 0x20, 0xD4}; 435 trap_opcode = g_arm64_breakpoint_opcode; 436 trap_opcode_size = sizeof(g_arm64_breakpoint_opcode); 437 } break; 438 439 case llvm::Triple::thumb: 440 bp_is_thumb = true; 441 LLVM_FALLTHROUGH; 442 case llvm::Triple::arm: { 443 static const uint8_t g_arm_breakpoint_opcode[] = {0xFE, 0xDE, 0xFF, 0xE7}; 444 static const uint8_t g_thumb_breakpooint_opcode[] = {0xFE, 0xDE}; 445 446 // Auto detect arm/thumb if it wasn't explicitly specified 447 if (!bp_is_thumb) { 448 lldb::BreakpointLocationSP bp_loc_sp(bp_site->GetOwnerAtIndex(0)); 449 if (bp_loc_sp) 450 bp_is_thumb = bp_loc_sp->GetAddress().GetAddressClass() == 451 AddressClass::eCodeAlternateISA; 452 } 453 if (bp_is_thumb) { 454 trap_opcode = g_thumb_breakpooint_opcode; 455 trap_opcode_size = sizeof(g_thumb_breakpooint_opcode); 456 break; 457 } 458 trap_opcode = g_arm_breakpoint_opcode; 459 trap_opcode_size = sizeof(g_arm_breakpoint_opcode); 460 } break; 461 462 case llvm::Triple::ppc: 463 case llvm::Triple::ppc64: { 464 static const uint8_t g_ppc_breakpoint_opcode[] = {0x7F, 0xC0, 0x00, 0x08}; 465 trap_opcode = g_ppc_breakpoint_opcode; 466 trap_opcode_size = sizeof(g_ppc_breakpoint_opcode); 467 } break; 468 469 default: 470 return Platform::GetSoftwareBreakpointTrapOpcode(target, bp_site); 471 } 472 473 if (trap_opcode && trap_opcode_size) { 474 if (bp_site->SetTrapOpcode(trap_opcode, trap_opcode_size)) 475 return trap_opcode_size; 476 } 477 return 0; 478 } 479 480 bool PlatformDarwin::ModuleIsExcludedForUnconstrainedSearches( 481 lldb_private::Target &target, const lldb::ModuleSP &module_sp) { 482 if (!module_sp) 483 return false; 484 485 ObjectFile *obj_file = module_sp->GetObjectFile(); 486 if (!obj_file) 487 return false; 488 489 ObjectFile::Type obj_type = obj_file->GetType(); 490 return obj_type == ObjectFile::eTypeDynamicLinker; 491 } 492 493 bool PlatformDarwin::x86GetSupportedArchitectureAtIndex(uint32_t idx, 494 ArchSpec &arch) { 495 ArchSpec host_arch = HostInfo::GetArchitecture(HostInfo::eArchKindDefault); 496 if (host_arch.GetCore() == ArchSpec::eCore_x86_64_x86_64h) { 497 switch (idx) { 498 case 0: 499 arch = host_arch; 500 return true; 501 502 case 1: 503 arch.SetTriple("x86_64-apple-macosx"); 504 return true; 505 506 case 2: 507 arch = HostInfo::GetArchitecture(HostInfo::eArchKind32); 508 return true; 509 510 default: 511 return false; 512 } 513 } else { 514 if (idx == 0) { 515 arch = HostInfo::GetArchitecture(HostInfo::eArchKindDefault); 516 return arch.IsValid(); 517 } else if (idx == 1) { 518 ArchSpec platform_arch( 519 HostInfo::GetArchitecture(HostInfo::eArchKindDefault)); 520 ArchSpec platform_arch64( 521 HostInfo::GetArchitecture(HostInfo::eArchKind64)); 522 if (platform_arch.IsExactMatch(platform_arch64)) { 523 // This macosx platform supports both 32 and 64 bit. Since we already 524 // returned the 64 bit arch for idx == 0, return the 32 bit arch for 525 // idx == 1 526 arch = HostInfo::GetArchitecture(HostInfo::eArchKind32); 527 return arch.IsValid(); 528 } 529 } 530 } 531 return false; 532 } 533 534 // The architecture selection rules for arm processors These cpu subtypes have 535 // distinct names (e.g. armv7f) but armv7 binaries run fine on an armv7f 536 // processor. 537 538 bool PlatformDarwin::ARMGetSupportedArchitectureAtIndex(uint32_t idx, 539 ArchSpec &arch) { 540 ArchSpec system_arch(GetSystemArchitecture()); 541 542 // When lldb is running on a watch or tv, set the arch OS name appropriately. 543 #if defined(TARGET_OS_TV) && TARGET_OS_TV == 1 544 #define OSNAME "tvos" 545 #elif defined(TARGET_OS_WATCH) && TARGET_OS_WATCH == 1 546 #define OSNAME "watchos" 547 #elif defined(TARGET_OS_BRIDGE) && TARGET_OS_BRIDGE == 1 548 #define OSNAME "bridgeos" 549 #else 550 #define OSNAME "ios" 551 #endif 552 553 const ArchSpec::Core system_core = system_arch.GetCore(); 554 switch (system_core) { 555 default: 556 switch (idx) { 557 case 0: 558 arch.SetTriple("arm64-apple-" OSNAME); 559 return true; 560 case 1: 561 arch.SetTriple("armv7-apple-" OSNAME); 562 return true; 563 case 2: 564 arch.SetTriple("armv7f-apple-" OSNAME); 565 return true; 566 case 3: 567 arch.SetTriple("armv7k-apple-" OSNAME); 568 return true; 569 case 4: 570 arch.SetTriple("armv7s-apple-" OSNAME); 571 return true; 572 case 5: 573 arch.SetTriple("armv7m-apple-" OSNAME); 574 return true; 575 case 6: 576 arch.SetTriple("armv7em-apple-" OSNAME); 577 return true; 578 case 7: 579 arch.SetTriple("armv6m-apple-" OSNAME); 580 return true; 581 case 8: 582 arch.SetTriple("armv6-apple-" OSNAME); 583 return true; 584 case 9: 585 arch.SetTriple("armv5-apple-" OSNAME); 586 return true; 587 case 10: 588 arch.SetTriple("armv4-apple-" OSNAME); 589 return true; 590 case 11: 591 arch.SetTriple("arm-apple-" OSNAME); 592 return true; 593 case 12: 594 arch.SetTriple("thumbv7-apple-" OSNAME); 595 return true; 596 case 13: 597 arch.SetTriple("thumbv7f-apple-" OSNAME); 598 return true; 599 case 14: 600 arch.SetTriple("thumbv7k-apple-" OSNAME); 601 return true; 602 case 15: 603 arch.SetTriple("thumbv7s-apple-" OSNAME); 604 return true; 605 case 16: 606 arch.SetTriple("thumbv7m-apple-" OSNAME); 607 return true; 608 case 17: 609 arch.SetTriple("thumbv7em-apple-" OSNAME); 610 return true; 611 case 18: 612 arch.SetTriple("thumbv6m-apple-" OSNAME); 613 return true; 614 case 19: 615 arch.SetTriple("thumbv6-apple-" OSNAME); 616 return true; 617 case 20: 618 arch.SetTriple("thumbv5-apple-" OSNAME); 619 return true; 620 case 21: 621 arch.SetTriple("thumbv4t-apple-" OSNAME); 622 return true; 623 case 22: 624 arch.SetTriple("thumb-apple-" OSNAME); 625 return true; 626 default: 627 break; 628 } 629 break; 630 631 case ArchSpec::eCore_arm_arm64: 632 switch (idx) { 633 case 0: 634 arch.SetTriple("arm64-apple-" OSNAME); 635 return true; 636 case 1: 637 arch.SetTriple("armv7s-apple-" OSNAME); 638 return true; 639 case 2: 640 arch.SetTriple("armv7f-apple-" OSNAME); 641 return true; 642 case 3: 643 arch.SetTriple("armv7m-apple-" OSNAME); 644 return true; 645 case 4: 646 arch.SetTriple("armv7em-apple-" OSNAME); 647 return true; 648 case 5: 649 arch.SetTriple("armv7-apple-" OSNAME); 650 return true; 651 case 6: 652 arch.SetTriple("armv6m-apple-" OSNAME); 653 return true; 654 case 7: 655 arch.SetTriple("armv6-apple-" OSNAME); 656 return true; 657 case 8: 658 arch.SetTriple("armv5-apple-" OSNAME); 659 return true; 660 case 9: 661 arch.SetTriple("armv4-apple-" OSNAME); 662 return true; 663 case 10: 664 arch.SetTriple("arm-apple-" OSNAME); 665 return true; 666 case 11: 667 arch.SetTriple("thumbv7-apple-" OSNAME); 668 return true; 669 case 12: 670 arch.SetTriple("thumbv7f-apple-" OSNAME); 671 return true; 672 case 13: 673 arch.SetTriple("thumbv7k-apple-" OSNAME); 674 return true; 675 case 14: 676 arch.SetTriple("thumbv7s-apple-" OSNAME); 677 return true; 678 case 15: 679 arch.SetTriple("thumbv7m-apple-" OSNAME); 680 return true; 681 case 16: 682 arch.SetTriple("thumbv7em-apple-" OSNAME); 683 return true; 684 case 17: 685 arch.SetTriple("thumbv6m-apple-" OSNAME); 686 return true; 687 case 18: 688 arch.SetTriple("thumbv6-apple-" OSNAME); 689 return true; 690 case 19: 691 arch.SetTriple("thumbv5-apple-" OSNAME); 692 return true; 693 case 20: 694 arch.SetTriple("thumbv4t-apple-" OSNAME); 695 return true; 696 case 21: 697 arch.SetTriple("thumb-apple-" OSNAME); 698 return true; 699 default: 700 break; 701 } 702 break; 703 704 case ArchSpec::eCore_arm_armv7f: 705 switch (idx) { 706 case 0: 707 arch.SetTriple("armv7f-apple-" OSNAME); 708 return true; 709 case 1: 710 arch.SetTriple("armv7-apple-" OSNAME); 711 return true; 712 case 2: 713 arch.SetTriple("armv6m-apple-" OSNAME); 714 return true; 715 case 3: 716 arch.SetTriple("armv6-apple-" OSNAME); 717 return true; 718 case 4: 719 arch.SetTriple("armv5-apple-" OSNAME); 720 return true; 721 case 5: 722 arch.SetTriple("armv4-apple-" OSNAME); 723 return true; 724 case 6: 725 arch.SetTriple("arm-apple-" OSNAME); 726 return true; 727 case 7: 728 arch.SetTriple("thumbv7f-apple-" OSNAME); 729 return true; 730 case 8: 731 arch.SetTriple("thumbv7-apple-" OSNAME); 732 return true; 733 case 9: 734 arch.SetTriple("thumbv6m-apple-" OSNAME); 735 return true; 736 case 10: 737 arch.SetTriple("thumbv6-apple-" OSNAME); 738 return true; 739 case 11: 740 arch.SetTriple("thumbv5-apple-" OSNAME); 741 return true; 742 case 12: 743 arch.SetTriple("thumbv4t-apple-" OSNAME); 744 return true; 745 case 13: 746 arch.SetTriple("thumb-apple-" OSNAME); 747 return true; 748 default: 749 break; 750 } 751 break; 752 753 case ArchSpec::eCore_arm_armv7k: 754 switch (idx) { 755 case 0: 756 arch.SetTriple("armv7k-apple-" OSNAME); 757 return true; 758 case 1: 759 arch.SetTriple("armv7-apple-" OSNAME); 760 return true; 761 case 2: 762 arch.SetTriple("armv6m-apple-" OSNAME); 763 return true; 764 case 3: 765 arch.SetTriple("armv6-apple-" OSNAME); 766 return true; 767 case 4: 768 arch.SetTriple("armv5-apple-" OSNAME); 769 return true; 770 case 5: 771 arch.SetTriple("armv4-apple-" OSNAME); 772 return true; 773 case 6: 774 arch.SetTriple("arm-apple-" OSNAME); 775 return true; 776 case 7: 777 arch.SetTriple("thumbv7k-apple-" OSNAME); 778 return true; 779 case 8: 780 arch.SetTriple("thumbv7-apple-" OSNAME); 781 return true; 782 case 9: 783 arch.SetTriple("thumbv6m-apple-" OSNAME); 784 return true; 785 case 10: 786 arch.SetTriple("thumbv6-apple-" OSNAME); 787 return true; 788 case 11: 789 arch.SetTriple("thumbv5-apple-" OSNAME); 790 return true; 791 case 12: 792 arch.SetTriple("thumbv4t-apple-" OSNAME); 793 return true; 794 case 13: 795 arch.SetTriple("thumb-apple-" OSNAME); 796 return true; 797 default: 798 break; 799 } 800 break; 801 802 case ArchSpec::eCore_arm_armv7s: 803 switch (idx) { 804 case 0: 805 arch.SetTriple("armv7s-apple-" OSNAME); 806 return true; 807 case 1: 808 arch.SetTriple("armv7-apple-" OSNAME); 809 return true; 810 case 2: 811 arch.SetTriple("armv6m-apple-" OSNAME); 812 return true; 813 case 3: 814 arch.SetTriple("armv6-apple-" OSNAME); 815 return true; 816 case 4: 817 arch.SetTriple("armv5-apple-" OSNAME); 818 return true; 819 case 5: 820 arch.SetTriple("armv4-apple-" OSNAME); 821 return true; 822 case 6: 823 arch.SetTriple("arm-apple-" OSNAME); 824 return true; 825 case 7: 826 arch.SetTriple("thumbv7s-apple-" OSNAME); 827 return true; 828 case 8: 829 arch.SetTriple("thumbv7-apple-" OSNAME); 830 return true; 831 case 9: 832 arch.SetTriple("thumbv6m-apple-" OSNAME); 833 return true; 834 case 10: 835 arch.SetTriple("thumbv6-apple-" OSNAME); 836 return true; 837 case 11: 838 arch.SetTriple("thumbv5-apple-" OSNAME); 839 return true; 840 case 12: 841 arch.SetTriple("thumbv4t-apple-" OSNAME); 842 return true; 843 case 13: 844 arch.SetTriple("thumb-apple-" OSNAME); 845 return true; 846 default: 847 break; 848 } 849 break; 850 851 case ArchSpec::eCore_arm_armv7m: 852 switch (idx) { 853 case 0: 854 arch.SetTriple("armv7m-apple-" OSNAME); 855 return true; 856 case 1: 857 arch.SetTriple("armv7-apple-" OSNAME); 858 return true; 859 case 2: 860 arch.SetTriple("armv6m-apple-" OSNAME); 861 return true; 862 case 3: 863 arch.SetTriple("armv6-apple-" OSNAME); 864 return true; 865 case 4: 866 arch.SetTriple("armv5-apple-" OSNAME); 867 return true; 868 case 5: 869 arch.SetTriple("armv4-apple-" OSNAME); 870 return true; 871 case 6: 872 arch.SetTriple("arm-apple-" OSNAME); 873 return true; 874 case 7: 875 arch.SetTriple("thumbv7m-apple-" OSNAME); 876 return true; 877 case 8: 878 arch.SetTriple("thumbv7-apple-" OSNAME); 879 return true; 880 case 9: 881 arch.SetTriple("thumbv6m-apple-" OSNAME); 882 return true; 883 case 10: 884 arch.SetTriple("thumbv6-apple-" OSNAME); 885 return true; 886 case 11: 887 arch.SetTriple("thumbv5-apple-" OSNAME); 888 return true; 889 case 12: 890 arch.SetTriple("thumbv4t-apple-" OSNAME); 891 return true; 892 case 13: 893 arch.SetTriple("thumb-apple-" OSNAME); 894 return true; 895 default: 896 break; 897 } 898 break; 899 900 case ArchSpec::eCore_arm_armv7em: 901 switch (idx) { 902 case 0: 903 arch.SetTriple("armv7em-apple-" OSNAME); 904 return true; 905 case 1: 906 arch.SetTriple("armv7-apple-" OSNAME); 907 return true; 908 case 2: 909 arch.SetTriple("armv6m-apple-" OSNAME); 910 return true; 911 case 3: 912 arch.SetTriple("armv6-apple-" OSNAME); 913 return true; 914 case 4: 915 arch.SetTriple("armv5-apple-" OSNAME); 916 return true; 917 case 5: 918 arch.SetTriple("armv4-apple-" OSNAME); 919 return true; 920 case 6: 921 arch.SetTriple("arm-apple-" OSNAME); 922 return true; 923 case 7: 924 arch.SetTriple("thumbv7em-apple-" OSNAME); 925 return true; 926 case 8: 927 arch.SetTriple("thumbv7-apple-" OSNAME); 928 return true; 929 case 9: 930 arch.SetTriple("thumbv6m-apple-" OSNAME); 931 return true; 932 case 10: 933 arch.SetTriple("thumbv6-apple-" OSNAME); 934 return true; 935 case 11: 936 arch.SetTriple("thumbv5-apple-" OSNAME); 937 return true; 938 case 12: 939 arch.SetTriple("thumbv4t-apple-" OSNAME); 940 return true; 941 case 13: 942 arch.SetTriple("thumb-apple-" OSNAME); 943 return true; 944 default: 945 break; 946 } 947 break; 948 949 case ArchSpec::eCore_arm_armv7: 950 switch (idx) { 951 case 0: 952 arch.SetTriple("armv7-apple-" OSNAME); 953 return true; 954 case 1: 955 arch.SetTriple("armv6m-apple-" OSNAME); 956 return true; 957 case 2: 958 arch.SetTriple("armv6-apple-" OSNAME); 959 return true; 960 case 3: 961 arch.SetTriple("armv5-apple-" OSNAME); 962 return true; 963 case 4: 964 arch.SetTriple("armv4-apple-" OSNAME); 965 return true; 966 case 5: 967 arch.SetTriple("arm-apple-" OSNAME); 968 return true; 969 case 6: 970 arch.SetTriple("thumbv7-apple-" OSNAME); 971 return true; 972 case 7: 973 arch.SetTriple("thumbv6m-apple-" OSNAME); 974 return true; 975 case 8: 976 arch.SetTriple("thumbv6-apple-" OSNAME); 977 return true; 978 case 9: 979 arch.SetTriple("thumbv5-apple-" OSNAME); 980 return true; 981 case 10: 982 arch.SetTriple("thumbv4t-apple-" OSNAME); 983 return true; 984 case 11: 985 arch.SetTriple("thumb-apple-" OSNAME); 986 return true; 987 default: 988 break; 989 } 990 break; 991 992 case ArchSpec::eCore_arm_armv6m: 993 switch (idx) { 994 case 0: 995 arch.SetTriple("armv6m-apple-" OSNAME); 996 return true; 997 case 1: 998 arch.SetTriple("armv6-apple-" OSNAME); 999 return true; 1000 case 2: 1001 arch.SetTriple("armv5-apple-" OSNAME); 1002 return true; 1003 case 3: 1004 arch.SetTriple("armv4-apple-" OSNAME); 1005 return true; 1006 case 4: 1007 arch.SetTriple("arm-apple-" OSNAME); 1008 return true; 1009 case 5: 1010 arch.SetTriple("thumbv6m-apple-" OSNAME); 1011 return true; 1012 case 6: 1013 arch.SetTriple("thumbv6-apple-" OSNAME); 1014 return true; 1015 case 7: 1016 arch.SetTriple("thumbv5-apple-" OSNAME); 1017 return true; 1018 case 8: 1019 arch.SetTriple("thumbv4t-apple-" OSNAME); 1020 return true; 1021 case 9: 1022 arch.SetTriple("thumb-apple-" OSNAME); 1023 return true; 1024 default: 1025 break; 1026 } 1027 break; 1028 1029 case ArchSpec::eCore_arm_armv6: 1030 switch (idx) { 1031 case 0: 1032 arch.SetTriple("armv6-apple-" OSNAME); 1033 return true; 1034 case 1: 1035 arch.SetTriple("armv5-apple-" OSNAME); 1036 return true; 1037 case 2: 1038 arch.SetTriple("armv4-apple-" OSNAME); 1039 return true; 1040 case 3: 1041 arch.SetTriple("arm-apple-" OSNAME); 1042 return true; 1043 case 4: 1044 arch.SetTriple("thumbv6-apple-" OSNAME); 1045 return true; 1046 case 5: 1047 arch.SetTriple("thumbv5-apple-" OSNAME); 1048 return true; 1049 case 6: 1050 arch.SetTriple("thumbv4t-apple-" OSNAME); 1051 return true; 1052 case 7: 1053 arch.SetTriple("thumb-apple-" OSNAME); 1054 return true; 1055 default: 1056 break; 1057 } 1058 break; 1059 1060 case ArchSpec::eCore_arm_armv5: 1061 switch (idx) { 1062 case 0: 1063 arch.SetTriple("armv5-apple-" OSNAME); 1064 return true; 1065 case 1: 1066 arch.SetTriple("armv4-apple-" OSNAME); 1067 return true; 1068 case 2: 1069 arch.SetTriple("arm-apple-" OSNAME); 1070 return true; 1071 case 3: 1072 arch.SetTriple("thumbv5-apple-" OSNAME); 1073 return true; 1074 case 4: 1075 arch.SetTriple("thumbv4t-apple-" OSNAME); 1076 return true; 1077 case 5: 1078 arch.SetTriple("thumb-apple-" OSNAME); 1079 return true; 1080 default: 1081 break; 1082 } 1083 break; 1084 1085 case ArchSpec::eCore_arm_armv4: 1086 switch (idx) { 1087 case 0: 1088 arch.SetTriple("armv4-apple-" OSNAME); 1089 return true; 1090 case 1: 1091 arch.SetTriple("arm-apple-" OSNAME); 1092 return true; 1093 case 2: 1094 arch.SetTriple("thumbv4t-apple-" OSNAME); 1095 return true; 1096 case 3: 1097 arch.SetTriple("thumb-apple-" OSNAME); 1098 return true; 1099 default: 1100 break; 1101 } 1102 break; 1103 } 1104 arch.Clear(); 1105 return false; 1106 } 1107 1108 static FileSpec GetXcodeSelectPath() { 1109 static FileSpec g_xcode_select_filespec; 1110 1111 if (!g_xcode_select_filespec) { 1112 FileSpec xcode_select_cmd("/usr/bin/xcode-select"); 1113 if (FileSystem::Instance().Exists(xcode_select_cmd)) { 1114 int exit_status = -1; 1115 int signo = -1; 1116 std::string command_output; 1117 Status status = 1118 Host::RunShellCommand("/usr/bin/xcode-select --print-path", 1119 FileSpec(), // current working directory 1120 &exit_status, &signo, &command_output, 1121 std::chrono::seconds(2), // short timeout 1122 false); // don't run in a shell 1123 if (status.Success() && exit_status == 0 && !command_output.empty()) { 1124 size_t first_non_newline = command_output.find_last_not_of("\r\n"); 1125 if (first_non_newline != std::string::npos) { 1126 command_output.erase(first_non_newline + 1); 1127 } 1128 g_xcode_select_filespec = FileSpec(command_output); 1129 } 1130 } 1131 } 1132 1133 return g_xcode_select_filespec; 1134 } 1135 1136 lldb_private::FileSpec PlatformDarwin::GetXcodeDeveloperDirectory() { 1137 static lldb_private::FileSpec g_developer_directory; 1138 static llvm::once_flag g_once_flag; 1139 llvm::call_once(g_once_flag, []() { 1140 if (FileSpec fspec = GetXcodeContentsDirectory()) { 1141 fspec.AppendPathComponent("Developer"); 1142 if (FileSystem::Instance().Exists(fspec)) 1143 g_developer_directory = fspec; 1144 } 1145 }); 1146 return g_developer_directory; 1147 } 1148 1149 BreakpointSP PlatformDarwin::SetThreadCreationBreakpoint(Target &target) { 1150 BreakpointSP bp_sp; 1151 static const char *g_bp_names[] = { 1152 "start_wqthread", "_pthread_wqthread", "_pthread_start", 1153 }; 1154 1155 static const char *g_bp_modules[] = {"libsystem_c.dylib", 1156 "libSystem.B.dylib"}; 1157 1158 FileSpecList bp_modules; 1159 for (size_t i = 0; i < llvm::array_lengthof(g_bp_modules); i++) { 1160 const char *bp_module = g_bp_modules[i]; 1161 bp_modules.EmplaceBack(bp_module); 1162 } 1163 1164 bool internal = true; 1165 bool hardware = false; 1166 LazyBool skip_prologue = eLazyBoolNo; 1167 bp_sp = target.CreateBreakpoint(&bp_modules, nullptr, g_bp_names, 1168 llvm::array_lengthof(g_bp_names), 1169 eFunctionNameTypeFull, eLanguageTypeUnknown, 1170 0, skip_prologue, internal, hardware); 1171 bp_sp->SetBreakpointKind("thread-creation"); 1172 1173 return bp_sp; 1174 } 1175 1176 int32_t 1177 PlatformDarwin::GetResumeCountForLaunchInfo(ProcessLaunchInfo &launch_info) { 1178 const FileSpec &shell = launch_info.GetShell(); 1179 if (!shell) 1180 return 1; 1181 1182 std::string shell_string = shell.GetPath(); 1183 const char *shell_name = strrchr(shell_string.c_str(), '/'); 1184 if (shell_name == nullptr) 1185 shell_name = shell_string.c_str(); 1186 else 1187 shell_name++; 1188 1189 if (strcmp(shell_name, "sh") == 0) { 1190 // /bin/sh re-exec's itself as /bin/bash requiring another resume. But it 1191 // only does this if the COMMAND_MODE environment variable is set to 1192 // "legacy". 1193 if (launch_info.GetEnvironment().lookup("COMMAND_MODE") == "legacy") 1194 return 2; 1195 return 1; 1196 } else if (strcmp(shell_name, "csh") == 0 || 1197 strcmp(shell_name, "tcsh") == 0 || 1198 strcmp(shell_name, "zsh") == 0) { 1199 // csh and tcsh always seem to re-exec themselves. 1200 return 2; 1201 } else 1202 return 1; 1203 } 1204 1205 void PlatformDarwin::CalculateTrapHandlerSymbolNames() { 1206 m_trap_handlers.push_back(ConstString("_sigtramp")); 1207 } 1208 1209 static FileSpec GetCommandLineToolsLibraryPath() { 1210 static FileSpec g_command_line_tools_filespec; 1211 1212 if (!g_command_line_tools_filespec) { 1213 FileSpec command_line_tools_path(GetXcodeSelectPath()); 1214 command_line_tools_path.AppendPathComponent("Library"); 1215 if (FileSystem::Instance().Exists(command_line_tools_path)) { 1216 g_command_line_tools_filespec = command_line_tools_path; 1217 } 1218 } 1219 1220 return g_command_line_tools_filespec; 1221 } 1222 1223 bool PlatformDarwin::SDKSupportsModules(SDKType sdk_type, 1224 llvm::VersionTuple version) { 1225 switch (sdk_type) { 1226 case SDKType::MacOSX: 1227 return version >= llvm::VersionTuple(10, 10); 1228 case SDKType::iPhoneOS: 1229 case SDKType::iPhoneSimulator: 1230 case SDKType::AppleTVOS: 1231 case SDKType::AppleTVSimulator: 1232 return version >= llvm::VersionTuple(8); 1233 case SDKType::watchOS: 1234 case SDKType::WatchSimulator: 1235 return version >= llvm::VersionTuple(6); 1236 default: 1237 return false; 1238 } 1239 1240 return false; 1241 } 1242 1243 bool PlatformDarwin::SDKSupportsModules(SDKType desired_type, 1244 const FileSpec &sdk_path) { 1245 ConstString last_path_component = sdk_path.GetLastPathComponent(); 1246 1247 if (last_path_component) { 1248 const llvm::StringRef sdk_name = last_path_component.GetStringRef(); 1249 1250 const std::string sdk_name_lower = sdk_name.lower(); 1251 const llvm::StringRef sdk_string = GetSDKNameForType(desired_type); 1252 if (!llvm::StringRef(sdk_name_lower).startswith(sdk_string)) 1253 return false; 1254 1255 auto version_part = sdk_name.drop_front(sdk_string.size()); 1256 version_part.consume_back(".sdk"); 1257 1258 llvm::VersionTuple version; 1259 if (version.tryParse(version_part)) 1260 return false; 1261 return SDKSupportsModules(desired_type, version); 1262 } 1263 1264 return false; 1265 } 1266 1267 FileSystem::EnumerateDirectoryResult PlatformDarwin::DirectoryEnumerator( 1268 void *baton, llvm::sys::fs::file_type file_type, llvm::StringRef path) { 1269 SDKEnumeratorInfo *enumerator_info = static_cast<SDKEnumeratorInfo *>(baton); 1270 1271 FileSpec spec(path); 1272 if (SDKSupportsModules(enumerator_info->sdk_type, spec)) { 1273 enumerator_info->found_path = spec; 1274 return FileSystem::EnumerateDirectoryResult::eEnumerateDirectoryResultNext; 1275 } 1276 1277 return FileSystem::EnumerateDirectoryResult::eEnumerateDirectoryResultNext; 1278 } 1279 1280 FileSpec PlatformDarwin::FindSDKInXcodeForModules(SDKType sdk_type, 1281 const FileSpec &sdks_spec) { 1282 // Look inside Xcode for the required installed iOS SDK version 1283 1284 if (!FileSystem::Instance().IsDirectory(sdks_spec)) { 1285 return FileSpec(); 1286 } 1287 1288 const bool find_directories = true; 1289 const bool find_files = false; 1290 const bool find_other = true; // include symlinks 1291 1292 SDKEnumeratorInfo enumerator_info; 1293 1294 enumerator_info.sdk_type = sdk_type; 1295 1296 FileSystem::Instance().EnumerateDirectory( 1297 sdks_spec.GetPath(), find_directories, find_files, find_other, 1298 DirectoryEnumerator, &enumerator_info); 1299 1300 if (FileSystem::Instance().IsDirectory(enumerator_info.found_path)) 1301 return enumerator_info.found_path; 1302 else 1303 return FileSpec(); 1304 } 1305 1306 FileSpec PlatformDarwin::GetSDKDirectoryForModules(SDKType sdk_type) { 1307 FileSpec sdks_spec = GetXcodeContentsDirectory(); 1308 sdks_spec.AppendPathComponent("Developer"); 1309 sdks_spec.AppendPathComponent("Platforms"); 1310 1311 switch (sdk_type) { 1312 case SDKType::MacOSX: 1313 sdks_spec.AppendPathComponent("MacOSX.platform"); 1314 break; 1315 case SDKType::iPhoneSimulator: 1316 sdks_spec.AppendPathComponent("iPhoneSimulator.platform"); 1317 break; 1318 case SDKType::iPhoneOS: 1319 sdks_spec.AppendPathComponent("iPhoneOS.platform"); 1320 break; 1321 default: 1322 llvm_unreachable("unsupported sdk"); 1323 } 1324 1325 sdks_spec.AppendPathComponent("Developer"); 1326 sdks_spec.AppendPathComponent("SDKs"); 1327 1328 if (sdk_type == SDKType::MacOSX) { 1329 llvm::VersionTuple version = HostInfo::GetOSVersion(); 1330 1331 if (!version.empty()) { 1332 if (SDKSupportsModules(SDKType::MacOSX, version)) { 1333 // If the Xcode SDKs are not available then try to use the 1334 // Command Line Tools one which is only for MacOSX. 1335 if (!FileSystem::Instance().Exists(sdks_spec)) { 1336 sdks_spec = GetCommandLineToolsLibraryPath(); 1337 sdks_spec.AppendPathComponent("SDKs"); 1338 } 1339 1340 // We slightly prefer the exact SDK for this machine. See if it is 1341 // there. 1342 1343 FileSpec native_sdk_spec = sdks_spec; 1344 StreamString native_sdk_name; 1345 native_sdk_name.Printf("MacOSX%u.%u.sdk", version.getMajor(), 1346 version.getMinor().getValueOr(0)); 1347 native_sdk_spec.AppendPathComponent(native_sdk_name.GetString()); 1348 1349 if (FileSystem::Instance().Exists(native_sdk_spec)) { 1350 return native_sdk_spec; 1351 } 1352 } 1353 } 1354 } 1355 1356 return FindSDKInXcodeForModules(sdk_type, sdks_spec); 1357 } 1358 1359 std::tuple<llvm::VersionTuple, llvm::StringRef> 1360 PlatformDarwin::ParseVersionBuildDir(llvm::StringRef dir) { 1361 llvm::StringRef build; 1362 llvm::StringRef version_str; 1363 llvm::StringRef build_str; 1364 std::tie(version_str, build_str) = dir.split(' '); 1365 llvm::VersionTuple version; 1366 if (!version.tryParse(version_str) || 1367 build_str.empty()) { 1368 if (build_str.consume_front("(")) { 1369 size_t pos = build_str.find(')'); 1370 build = build_str.slice(0, pos); 1371 } 1372 } 1373 1374 return std::make_tuple(version, build); 1375 } 1376 1377 llvm::Expected<StructuredData::DictionarySP> 1378 PlatformDarwin::FetchExtendedCrashInformation(Process &process) { 1379 Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS)); 1380 1381 StructuredData::ArraySP annotations = ExtractCrashInfoAnnotations(process); 1382 1383 if (!annotations || !annotations->GetSize()) { 1384 LLDB_LOG(log, "Couldn't extract crash information annotations"); 1385 return nullptr; 1386 } 1387 1388 StructuredData::DictionarySP extended_crash_info = 1389 std::make_shared<StructuredData::Dictionary>(); 1390 1391 extended_crash_info->AddItem("crash-info annotations", annotations); 1392 1393 return extended_crash_info; 1394 } 1395 1396 StructuredData::ArraySP 1397 PlatformDarwin::ExtractCrashInfoAnnotations(Process &process) { 1398 Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS)); 1399 1400 ConstString section_name("__crash_info"); 1401 Target &target = process.GetTarget(); 1402 StructuredData::ArraySP array_sp = std::make_shared<StructuredData::Array>(); 1403 1404 for (ModuleSP module : target.GetImages().Modules()) { 1405 SectionList *sections = module->GetSectionList(); 1406 1407 std::string module_name = module->GetSpecificationDescription(); 1408 1409 // The DYDL module is skipped since it's always loaded when running the 1410 // binary. 1411 if (module_name == "/usr/lib/dyld") 1412 continue; 1413 1414 if (!sections) { 1415 LLDB_LOG(log, "Module {0} doesn't have any section!", module_name); 1416 continue; 1417 } 1418 1419 SectionSP crash_info = sections->FindSectionByName(section_name); 1420 if (!crash_info) { 1421 LLDB_LOG(log, "Module {0} doesn't have section {1}!", module_name, 1422 section_name); 1423 continue; 1424 } 1425 1426 addr_t load_addr = crash_info->GetLoadBaseAddress(&target); 1427 1428 if (load_addr == LLDB_INVALID_ADDRESS) { 1429 LLDB_LOG(log, "Module {0} has an invalid '{1}' section load address: {2}", 1430 module_name, section_name, load_addr); 1431 continue; 1432 } 1433 1434 Status error; 1435 CrashInfoAnnotations annotations; 1436 size_t expected_size = sizeof(CrashInfoAnnotations); 1437 size_t bytes_read = process.ReadMemoryFromInferior(load_addr, &annotations, 1438 expected_size, error); 1439 1440 if (expected_size != bytes_read || error.Fail()) { 1441 LLDB_LOG(log, "Failed to read {0} section from memory in module {1}: {2}", 1442 section_name, module_name, error); 1443 continue; 1444 } 1445 1446 // initial support added for version 5 1447 if (annotations.version < 5) { 1448 LLDB_LOG(log, 1449 "Annotation version lower than 5 unsupported! Module {0} has " 1450 "version {1} instead.", 1451 module_name, annotations.version); 1452 continue; 1453 } 1454 1455 if (!annotations.message) { 1456 LLDB_LOG(log, "No message available for module {0}.", module_name); 1457 continue; 1458 } 1459 1460 std::string message; 1461 bytes_read = 1462 process.ReadCStringFromMemory(annotations.message, message, error); 1463 1464 if (message.empty() || bytes_read != message.size() || error.Fail()) { 1465 LLDB_LOG(log, "Failed to read the message from memory in module {0}: {1}", 1466 module_name, error); 1467 continue; 1468 } 1469 1470 // Remove trailing newline from message 1471 if (message.back() == '\n') 1472 message.pop_back(); 1473 1474 if (!annotations.message2) 1475 LLDB_LOG(log, "No message2 available for module {0}.", module_name); 1476 1477 std::string message2; 1478 bytes_read = 1479 process.ReadCStringFromMemory(annotations.message2, message2, error); 1480 1481 if (!message2.empty() && bytes_read == message2.size() && error.Success()) 1482 if (message2.back() == '\n') 1483 message2.pop_back(); 1484 1485 StructuredData::DictionarySP entry_sp = 1486 std::make_shared<StructuredData::Dictionary>(); 1487 1488 entry_sp->AddStringItem("image", module->GetFileSpec().GetPath(false)); 1489 entry_sp->AddStringItem("uuid", module->GetUUID().GetAsString()); 1490 entry_sp->AddStringItem("message", message); 1491 entry_sp->AddStringItem("message2", message2); 1492 entry_sp->AddIntegerItem("abort-cause", annotations.abort_cause); 1493 1494 array_sp->AddItem(entry_sp); 1495 } 1496 1497 return array_sp; 1498 } 1499 1500 void PlatformDarwin::AddClangModuleCompilationOptionsForSDKType( 1501 Target *target, std::vector<std::string> &options, SDKType sdk_type) { 1502 const std::vector<std::string> apple_arguments = { 1503 "-x", "objective-c++", "-fobjc-arc", 1504 "-fblocks", "-D_ISO646_H", "-D__ISO646_H", 1505 "-fgnuc-version=4.2.1"}; 1506 1507 options.insert(options.end(), apple_arguments.begin(), apple_arguments.end()); 1508 1509 StreamString minimum_version_option; 1510 bool use_current_os_version = false; 1511 switch (sdk_type) { 1512 case SDKType::iPhoneOS: 1513 #if defined(__arm__) || defined(__arm64__) || defined(__aarch64__) 1514 use_current_os_version = true; 1515 #else 1516 use_current_os_version = false; 1517 #endif 1518 break; 1519 1520 case SDKType::iPhoneSimulator: 1521 use_current_os_version = false; 1522 break; 1523 1524 case SDKType::MacOSX: 1525 #if defined(__i386__) || defined(__x86_64__) 1526 use_current_os_version = true; 1527 #else 1528 use_current_os_version = false; 1529 #endif 1530 break; 1531 default: 1532 break; 1533 } 1534 1535 llvm::VersionTuple version; 1536 if (use_current_os_version) 1537 version = GetOSVersion(); 1538 else if (target) { 1539 // Our OS doesn't match our executable so we need to get the min OS version 1540 // from the object file 1541 ModuleSP exe_module_sp = target->GetExecutableModule(); 1542 if (exe_module_sp) { 1543 ObjectFile *object_file = exe_module_sp->GetObjectFile(); 1544 if (object_file) 1545 version = object_file->GetMinimumOSVersion(); 1546 } 1547 } 1548 // Only add the version-min options if we got a version from somewhere 1549 if (!version.empty()) { 1550 switch (sdk_type) { 1551 case SDKType::iPhoneOS: 1552 minimum_version_option.PutCString("-mios-version-min="); 1553 minimum_version_option.PutCString(version.getAsString()); 1554 break; 1555 case SDKType::iPhoneSimulator: 1556 minimum_version_option.PutCString("-mios-simulator-version-min="); 1557 minimum_version_option.PutCString(version.getAsString()); 1558 break; 1559 case SDKType::MacOSX: 1560 minimum_version_option.PutCString("-mmacosx-version-min="); 1561 minimum_version_option.PutCString(version.getAsString()); 1562 break; 1563 default: 1564 llvm_unreachable("unsupported sdk"); 1565 } 1566 options.push_back(std::string(minimum_version_option.GetString())); 1567 } 1568 1569 FileSpec sysroot_spec; 1570 // Scope for mutex locker below 1571 { 1572 std::lock_guard<std::mutex> guard(m_mutex); 1573 sysroot_spec = GetSDKDirectoryForModules(sdk_type); 1574 } 1575 1576 if (FileSystem::Instance().IsDirectory(sysroot_spec.GetPath())) { 1577 options.push_back("-isysroot"); 1578 options.push_back(sysroot_spec.GetPath()); 1579 } 1580 } 1581 1582 ConstString PlatformDarwin::GetFullNameForDylib(ConstString basename) { 1583 if (basename.IsEmpty()) 1584 return basename; 1585 1586 StreamString stream; 1587 stream.Printf("lib%s.dylib", basename.GetCString()); 1588 return ConstString(stream.GetString()); 1589 } 1590 1591 llvm::VersionTuple PlatformDarwin::GetOSVersion(Process *process) { 1592 if (process && strstr(GetPluginName().GetCString(), "-simulator")) { 1593 lldb_private::ProcessInstanceInfo proc_info; 1594 if (Host::GetProcessInfo(process->GetID(), proc_info)) { 1595 const Environment &env = proc_info.GetEnvironment(); 1596 1597 llvm::VersionTuple result; 1598 if (!result.tryParse(env.lookup("SIMULATOR_RUNTIME_VERSION"))) 1599 return result; 1600 1601 std::string dyld_root_path = env.lookup("DYLD_ROOT_PATH"); 1602 if (!dyld_root_path.empty()) { 1603 dyld_root_path += "/System/Library/CoreServices/SystemVersion.plist"; 1604 ApplePropertyList system_version_plist(dyld_root_path.c_str()); 1605 std::string product_version; 1606 if (system_version_plist.GetValueAsString("ProductVersion", 1607 product_version)) { 1608 if (!result.tryParse(product_version)) 1609 return result; 1610 } 1611 } 1612 } 1613 // For simulator platforms, do NOT call back through 1614 // Platform::GetOSVersion() as it might call Process::GetHostOSVersion() 1615 // which we don't want as it will be incorrect 1616 return llvm::VersionTuple(); 1617 } 1618 1619 return Platform::GetOSVersion(process); 1620 } 1621 1622 lldb_private::FileSpec PlatformDarwin::LocateExecutable(const char *basename) { 1623 // A collection of SBFileSpec whose SBFileSpec.m_directory members are filled 1624 // in with any executable directories that should be searched. 1625 static std::vector<FileSpec> g_executable_dirs; 1626 1627 // Find the global list of directories that we will search for executables 1628 // once so we don't keep doing the work over and over. 1629 static llvm::once_flag g_once_flag; 1630 llvm::call_once(g_once_flag, []() { 1631 1632 // When locating executables, trust the DEVELOPER_DIR first if it is set 1633 FileSpec xcode_contents_dir = GetXcodeContentsDirectory(); 1634 if (xcode_contents_dir) { 1635 FileSpec xcode_lldb_resources = xcode_contents_dir; 1636 xcode_lldb_resources.AppendPathComponent("SharedFrameworks"); 1637 xcode_lldb_resources.AppendPathComponent("LLDB.framework"); 1638 xcode_lldb_resources.AppendPathComponent("Resources"); 1639 if (FileSystem::Instance().Exists(xcode_lldb_resources)) { 1640 FileSpec dir; 1641 dir.GetDirectory().SetCString(xcode_lldb_resources.GetPath().c_str()); 1642 g_executable_dirs.push_back(dir); 1643 } 1644 } 1645 // Xcode might not be installed so we also check for the Command Line Tools. 1646 FileSpec command_line_tools_dir = GetCommandLineToolsLibraryPath(); 1647 if (command_line_tools_dir) { 1648 FileSpec cmd_line_lldb_resources = command_line_tools_dir; 1649 cmd_line_lldb_resources.AppendPathComponent("PrivateFrameworks"); 1650 cmd_line_lldb_resources.AppendPathComponent("LLDB.framework"); 1651 cmd_line_lldb_resources.AppendPathComponent("Resources"); 1652 if (FileSystem::Instance().Exists(cmd_line_lldb_resources)) { 1653 FileSpec dir; 1654 dir.GetDirectory().SetCString( 1655 cmd_line_lldb_resources.GetPath().c_str()); 1656 g_executable_dirs.push_back(dir); 1657 } 1658 } 1659 }); 1660 1661 // Now search the global list of executable directories for the executable we 1662 // are looking for 1663 for (const auto &executable_dir : g_executable_dirs) { 1664 FileSpec executable_file; 1665 executable_file.GetDirectory() = executable_dir.GetDirectory(); 1666 executable_file.GetFilename().SetCString(basename); 1667 if (FileSystem::Instance().Exists(executable_file)) 1668 return executable_file; 1669 } 1670 1671 return FileSpec(); 1672 } 1673 1674 lldb_private::Status 1675 PlatformDarwin::LaunchProcess(lldb_private::ProcessLaunchInfo &launch_info) { 1676 // Starting in Fall 2016 OSes, NSLog messages only get mirrored to stderr if 1677 // the OS_ACTIVITY_DT_MODE environment variable is set. (It doesn't require 1678 // any specific value; rather, it just needs to exist). We will set it here 1679 // as long as the IDE_DISABLED_OS_ACTIVITY_DT_MODE flag is not set. Xcode 1680 // makes use of IDE_DISABLED_OS_ACTIVITY_DT_MODE to tell 1681 // LLDB *not* to muck with the OS_ACTIVITY_DT_MODE flag when they 1682 // specifically want it unset. 1683 const char *disable_env_var = "IDE_DISABLED_OS_ACTIVITY_DT_MODE"; 1684 auto &env_vars = launch_info.GetEnvironment(); 1685 if (!env_vars.count(disable_env_var)) { 1686 // We want to make sure that OS_ACTIVITY_DT_MODE is set so that we get 1687 // os_log and NSLog messages mirrored to the target process stderr. 1688 env_vars.try_emplace("OS_ACTIVITY_DT_MODE", "enable"); 1689 } 1690 1691 // Let our parent class do the real launching. 1692 return PlatformPOSIX::LaunchProcess(launch_info); 1693 } 1694 1695 lldb_private::Status PlatformDarwin::FindBundleBinaryInExecSearchPaths( 1696 const ModuleSpec &module_spec, Process *process, ModuleSP &module_sp, 1697 const FileSpecList *module_search_paths_ptr, ModuleSP *old_module_sp_ptr, 1698 bool *did_create_ptr) { 1699 const FileSpec &platform_file = module_spec.GetFileSpec(); 1700 // See if the file is present in any of the module_search_paths_ptr 1701 // directories. 1702 if (!module_sp && module_search_paths_ptr && platform_file) { 1703 // create a vector of all the file / directory names in platform_file e.g. 1704 // this might be 1705 // /System/Library/PrivateFrameworks/UIFoundation.framework/UIFoundation 1706 // 1707 // We'll need to look in the module_search_paths_ptr directories for both 1708 // "UIFoundation" and "UIFoundation.framework" -- most likely the latter 1709 // will be the one we find there. 1710 1711 FileSpec platform_pull_upart(platform_file); 1712 std::vector<std::string> path_parts; 1713 path_parts.push_back( 1714 platform_pull_upart.GetLastPathComponent().AsCString()); 1715 while (platform_pull_upart.RemoveLastPathComponent()) { 1716 ConstString part = platform_pull_upart.GetLastPathComponent(); 1717 path_parts.push_back(part.AsCString()); 1718 } 1719 const size_t path_parts_size = path_parts.size(); 1720 1721 size_t num_module_search_paths = module_search_paths_ptr->GetSize(); 1722 for (size_t i = 0; i < num_module_search_paths; ++i) { 1723 Log *log_verbose = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST); 1724 LLDB_LOGF( 1725 log_verbose, 1726 "PlatformRemoteDarwinDevice::GetSharedModule searching for binary in " 1727 "search-path %s", 1728 module_search_paths_ptr->GetFileSpecAtIndex(i).GetPath().c_str()); 1729 // Create a new FileSpec with this module_search_paths_ptr plus just the 1730 // filename ("UIFoundation"), then the parent dir plus filename 1731 // ("UIFoundation.framework/UIFoundation") etc - up to four names (to 1732 // handle "Foo.framework/Contents/MacOS/Foo") 1733 1734 for (size_t j = 0; j < 4 && j < path_parts_size - 1; ++j) { 1735 FileSpec path_to_try(module_search_paths_ptr->GetFileSpecAtIndex(i)); 1736 1737 // Add the components backwards. For 1738 // .../PrivateFrameworks/UIFoundation.framework/UIFoundation path_parts 1739 // is 1740 // [0] UIFoundation 1741 // [1] UIFoundation.framework 1742 // [2] PrivateFrameworks 1743 // 1744 // and if 'j' is 2, we want to append path_parts[1] and then 1745 // path_parts[0], aka 'UIFoundation.framework/UIFoundation', to the 1746 // module_search_paths_ptr path. 1747 1748 for (int k = j; k >= 0; --k) { 1749 path_to_try.AppendPathComponent(path_parts[k]); 1750 } 1751 1752 if (FileSystem::Instance().Exists(path_to_try)) { 1753 ModuleSpec new_module_spec(module_spec); 1754 new_module_spec.GetFileSpec() = path_to_try; 1755 Status new_error(Platform::GetSharedModule( 1756 new_module_spec, process, module_sp, nullptr, old_module_sp_ptr, 1757 did_create_ptr)); 1758 1759 if (module_sp) { 1760 module_sp->SetPlatformFileSpec(path_to_try); 1761 return new_error; 1762 } 1763 } 1764 } 1765 } 1766 } 1767 return Status(); 1768 } 1769 1770 std::string PlatformDarwin::FindComponentInPath(llvm::StringRef path, 1771 llvm::StringRef component) { 1772 auto begin = llvm::sys::path::begin(path); 1773 auto end = llvm::sys::path::end(path); 1774 for (auto it = begin; it != end; ++it) { 1775 if (it->contains(component)) { 1776 llvm::SmallString<128> buffer; 1777 llvm::sys::path::append(buffer, begin, ++it, 1778 llvm::sys::path::Style::posix); 1779 return buffer.str().str(); 1780 } 1781 } 1782 return {}; 1783 } 1784 1785 std::string 1786 PlatformDarwin::FindXcodeContentsDirectoryInPath(llvm::StringRef path) { 1787 auto begin = llvm::sys::path::begin(path); 1788 auto end = llvm::sys::path::end(path); 1789 1790 // Iterate over the path components until we find something that ends with 1791 // .app. If the next component is Contents then we've found the Contents 1792 // directory. 1793 for (auto it = begin; it != end; ++it) { 1794 if (it->endswith(".app")) { 1795 auto next = it; 1796 if (++next != end && *next == "Contents") { 1797 llvm::SmallString<128> buffer; 1798 llvm::sys::path::append(buffer, begin, ++next, 1799 llvm::sys::path::Style::posix); 1800 return buffer.str().str(); 1801 } 1802 } 1803 } 1804 1805 return {}; 1806 } 1807 1808 llvm::StringRef PlatformDarwin::GetSDKNameForType(SDKType type) { 1809 switch (type) { 1810 case MacOSX: 1811 return "macosx"; 1812 case iPhoneSimulator: 1813 return "iphonesimulator"; 1814 case iPhoneOS: 1815 return "iphoneos"; 1816 case AppleTVSimulator: 1817 return "appletvsimulator"; 1818 case AppleTVOS: 1819 return "appletvos"; 1820 case WatchSimulator: 1821 return "watchsimulator"; 1822 case watchOS: 1823 return "watchos"; 1824 case bridgeOS: 1825 return "bridgeos"; 1826 case Linux: 1827 return "linux"; 1828 case numSDKTypes: 1829 case unknown: 1830 return ""; 1831 } 1832 llvm_unreachable("unhandled switch case"); 1833 } 1834 1835 FileSpec PlatformDarwin::GetXcodeSDK(SDKType type) { 1836 std::string xcrun_cmd = 1837 "xcrun --show-sdk-path --sdk " + GetSDKNameForType(type).str(); 1838 1839 int status = 0; 1840 int signo = 0; 1841 std::string output_str; 1842 lldb_private::Status error = 1843 Host::RunShellCommand(xcrun_cmd.c_str(), FileSpec(), &status, &signo, 1844 &output_str, std::chrono::seconds(15)); 1845 1846 // Check that xcrun return something useful. 1847 if (status != 0 || output_str.empty()) 1848 return {}; 1849 1850 // Convert to a StringRef so we can manipulate the string without modifying 1851 // the underlying data. 1852 llvm::StringRef output(output_str); 1853 1854 // Remove any trailing newline characters. 1855 output = output.rtrim(); 1856 1857 // Strip any leading newline characters and everything before them. 1858 const size_t last_newline = output.rfind('\n'); 1859 if (last_newline != llvm::StringRef::npos) 1860 output = output.substr(last_newline + 1); 1861 1862 // Whatever is left in output should be a valid path. 1863 if (!FileSystem::Instance().Exists(output)) 1864 return {}; 1865 1866 // Find the contents dir in the xcrun provided path. 1867 std::string xcode_contents_dir = FindXcodeContentsDirectoryInPath(output); 1868 if (xcode_contents_dir.empty()) 1869 return {}; 1870 1871 return FileSpec(xcode_contents_dir); 1872 } 1873 1874 FileSpec PlatformDarwin::GetXcodeContentsDirectory() { 1875 static FileSpec g_xcode_contents_path; 1876 static std::once_flag g_once_flag; 1877 std::call_once(g_once_flag, [&]() { 1878 // Try the shlib dir first. 1879 if (FileSpec fspec = HostInfo::GetShlibDir()) { 1880 if (FileSystem::Instance().Exists(fspec)) { 1881 std::string xcode_contents_dir = 1882 FindXcodeContentsDirectoryInPath(fspec.GetPath()); 1883 if (!xcode_contents_dir.empty()) { 1884 g_xcode_contents_path = FileSpec(xcode_contents_dir); 1885 return; 1886 } 1887 } 1888 } 1889 1890 if (const char *developer_dir_env_var = getenv("DEVELOPER_DIR")) { 1891 FileSpec fspec(developer_dir_env_var); 1892 if (FileSystem::Instance().Exists(fspec)) { 1893 std::string xcode_contents_dir = 1894 FindXcodeContentsDirectoryInPath(fspec.GetPath()); 1895 if (!xcode_contents_dir.empty()) { 1896 g_xcode_contents_path = FileSpec(xcode_contents_dir); 1897 return; 1898 } 1899 } 1900 } 1901 1902 if (FileSpec fspec = GetXcodeSDK(SDKType::MacOSX)) { 1903 if (FileSystem::Instance().Exists(fspec)) { 1904 std::string xcode_contents_dir = 1905 FindXcodeContentsDirectoryInPath(fspec.GetPath()); 1906 if (!xcode_contents_dir.empty()) { 1907 g_xcode_contents_path = FileSpec(xcode_contents_dir); 1908 return; 1909 } 1910 } 1911 } 1912 }); 1913 return g_xcode_contents_path; 1914 } 1915 1916 FileSpec PlatformDarwin::GetCurrentToolchainDirectory() { 1917 if (FileSpec fspec = HostInfo::GetShlibDir()) 1918 return FileSpec(FindComponentInPath(fspec.GetPath(), ".xctoolchain")); 1919 return {}; 1920 } 1921 1922 FileSpec PlatformDarwin::GetCurrentCommandLineToolsDirectory() { 1923 if (FileSpec fspec = HostInfo::GetShlibDir()) 1924 return FileSpec(FindComponentInPath(fspec.GetPath(), "CommandLineTools")); 1925 return {}; 1926 } 1927