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 <cstring> 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/LLDBLog.h" 35 #include "lldb/Utility/Log.h" 36 #include "lldb/Utility/ProcessInfo.h" 37 #include "lldb/Utility/Status.h" 38 #include "lldb/Utility/Timer.h" 39 #include "llvm/ADT/STLExtras.h" 40 #include "llvm/Support/FileSystem.h" 41 #include "llvm/Support/Threading.h" 42 #include "llvm/Support/VersionTuple.h" 43 44 #if defined(__APPLE__) 45 #include <TargetConditionals.h> 46 #endif 47 48 using namespace lldb; 49 using namespace lldb_private; 50 51 /// Destructor. 52 /// 53 /// The destructor is virtual since this class is designed to be 54 /// inherited from by the plug-in instance. 55 PlatformDarwin::~PlatformDarwin() = default; 56 57 lldb_private::Status 58 PlatformDarwin::PutFile(const lldb_private::FileSpec &source, 59 const lldb_private::FileSpec &destination, uint32_t uid, 60 uint32_t gid) { 61 // Unconditionally unlink the destination. If it is an executable, 62 // simply opening it and truncating its contents would invalidate 63 // its cached code signature. 64 Unlink(destination); 65 return PlatformPOSIX::PutFile(source, destination, uid, gid); 66 } 67 68 FileSpecList PlatformDarwin::LocateExecutableScriptingResources( 69 Target *target, Module &module, Stream *feedback_stream) { 70 FileSpecList file_list; 71 if (target && 72 target->GetDebugger().GetScriptLanguage() == eScriptLanguagePython) { 73 // NB some extensions might be meaningful and should not be stripped - 74 // "this.binary.file" 75 // should not lose ".file" but GetFileNameStrippingExtension() will do 76 // precisely that. Ideally, we should have a per-platform list of 77 // extensions (".exe", ".app", ".dSYM", ".framework") which should be 78 // stripped while leaving "this.binary.file" as-is. 79 80 FileSpec module_spec = module.GetFileSpec(); 81 82 if (module_spec) { 83 if (SymbolFile *symfile = module.GetSymbolFile()) { 84 ObjectFile *objfile = symfile->GetObjectFile(); 85 if (objfile) { 86 FileSpec symfile_spec(objfile->GetFileSpec()); 87 if (symfile_spec && 88 strcasestr(symfile_spec.GetPath().c_str(), 89 ".dSYM/Contents/Resources/DWARF") != nullptr && 90 FileSystem::Instance().Exists(symfile_spec)) { 91 while (module_spec.GetFilename()) { 92 std::string module_basename( 93 module_spec.GetFilename().GetCString()); 94 std::string original_module_basename(module_basename); 95 96 bool was_keyword = false; 97 98 // FIXME: for Python, we cannot allow certain characters in 99 // module 100 // filenames we import. Theoretically, different scripting 101 // languages may have different sets of forbidden tokens in 102 // filenames, and that should be dealt with by each 103 // ScriptInterpreter. For now, we just replace dots with 104 // underscores, but if we ever support anything other than 105 // Python we will need to rework this 106 std::replace(module_basename.begin(), module_basename.end(), '.', 107 '_'); 108 std::replace(module_basename.begin(), module_basename.end(), ' ', 109 '_'); 110 std::replace(module_basename.begin(), module_basename.end(), '-', 111 '_'); 112 ScriptInterpreter *script_interpreter = 113 target->GetDebugger().GetScriptInterpreter(); 114 if (script_interpreter && 115 script_interpreter->IsReservedWord(module_basename.c_str())) { 116 module_basename.insert(module_basename.begin(), '_'); 117 was_keyword = true; 118 } 119 120 StreamString path_string; 121 StreamString original_path_string; 122 // for OSX we are going to be in 123 // .dSYM/Contents/Resources/DWARF/<basename> let us go to 124 // .dSYM/Contents/Resources/Python/<basename>.py and see if the 125 // file exists 126 path_string.Printf("%s/../Python/%s.py", 127 symfile_spec.GetDirectory().GetCString(), 128 module_basename.c_str()); 129 original_path_string.Printf( 130 "%s/../Python/%s.py", 131 symfile_spec.GetDirectory().GetCString(), 132 original_module_basename.c_str()); 133 FileSpec script_fspec(path_string.GetString()); 134 FileSystem::Instance().Resolve(script_fspec); 135 FileSpec orig_script_fspec(original_path_string.GetString()); 136 FileSystem::Instance().Resolve(orig_script_fspec); 137 138 // if we did some replacements of reserved characters, and a 139 // file with the untampered name exists, then warn the user 140 // that the file as-is shall not be loaded 141 if (feedback_stream) { 142 if (module_basename != original_module_basename && 143 FileSystem::Instance().Exists(orig_script_fspec)) { 144 const char *reason_for_complaint = 145 was_keyword ? "conflicts with a keyword" 146 : "contains reserved characters"; 147 if (FileSystem::Instance().Exists(script_fspec)) 148 feedback_stream->Printf( 149 "warning: the symbol file '%s' contains a debug " 150 "script. However, its name" 151 " '%s' %s and as such cannot be loaded. LLDB will" 152 " load '%s' instead. Consider removing the file with " 153 "the malformed name to" 154 " eliminate this warning.\n", 155 symfile_spec.GetPath().c_str(), 156 original_path_string.GetData(), reason_for_complaint, 157 path_string.GetData()); 158 else 159 feedback_stream->Printf( 160 "warning: the symbol file '%s' contains a debug " 161 "script. However, its name" 162 " %s and as such cannot be loaded. If you intend" 163 " to have this script loaded, please rename '%s' to " 164 "'%s' and retry.\n", 165 symfile_spec.GetPath().c_str(), reason_for_complaint, 166 original_path_string.GetData(), path_string.GetData()); 167 } 168 } 169 170 if (FileSystem::Instance().Exists(script_fspec)) { 171 file_list.Append(script_fspec); 172 break; 173 } 174 175 // If we didn't find the python file, then keep stripping the 176 // extensions and try again 177 ConstString filename_no_extension( 178 module_spec.GetFileNameStrippingExtension()); 179 if (module_spec.GetFilename() == filename_no_extension) 180 break; 181 182 module_spec.GetFilename() = filename_no_extension; 183 } 184 } 185 } 186 } 187 } 188 } 189 return file_list; 190 } 191 192 Status PlatformDarwin::ResolveSymbolFile(Target &target, 193 const ModuleSpec &sym_spec, 194 FileSpec &sym_file) { 195 sym_file = sym_spec.GetSymbolFileSpec(); 196 if (FileSystem::Instance().IsDirectory(sym_file)) { 197 sym_file = Symbols::FindSymbolFileInBundle(sym_file, sym_spec.GetUUIDPtr(), 198 sym_spec.GetArchitecturePtr()); 199 } 200 return {}; 201 } 202 203 static lldb_private::Status 204 MakeCacheFolderForFile(const FileSpec &module_cache_spec) { 205 FileSpec module_cache_folder = 206 module_cache_spec.CopyByRemovingLastPathComponent(); 207 return llvm::sys::fs::create_directory(module_cache_folder.GetPath()); 208 } 209 210 static lldb_private::Status 211 BringInRemoteFile(Platform *platform, 212 const lldb_private::ModuleSpec &module_spec, 213 const FileSpec &module_cache_spec) { 214 MakeCacheFolderForFile(module_cache_spec); 215 Status err = platform->GetFile(module_spec.GetFileSpec(), module_cache_spec); 216 return err; 217 } 218 219 lldb_private::Status PlatformDarwin::GetSharedModuleWithLocalCache( 220 const lldb_private::ModuleSpec &module_spec, lldb::ModuleSP &module_sp, 221 const lldb_private::FileSpecList *module_search_paths_ptr, 222 llvm::SmallVectorImpl<lldb::ModuleSP> *old_modules, bool *did_create_ptr) { 223 224 Log *log = GetLog(LLDBLog::Platform); 225 LLDB_LOGF(log, 226 "[%s] Trying to find module %s/%s - platform path %s/%s symbol " 227 "path %s/%s", 228 (IsHost() ? "host" : "remote"), 229 module_spec.GetFileSpec().GetDirectory().AsCString(), 230 module_spec.GetFileSpec().GetFilename().AsCString(), 231 module_spec.GetPlatformFileSpec().GetDirectory().AsCString(), 232 module_spec.GetPlatformFileSpec().GetFilename().AsCString(), 233 module_spec.GetSymbolFileSpec().GetDirectory().AsCString(), 234 module_spec.GetSymbolFileSpec().GetFilename().AsCString()); 235 236 Status err; 237 238 if (CheckLocalSharedCache()) { 239 // When debugging on the host, we are most likely using the same shared 240 // cache as our inferior. The dylibs from the shared cache might not 241 // exist on the filesystem, so let's use the images in our own memory 242 // to create the modules. 243 244 // Check if the requested image is in our shared cache. 245 SharedCacheImageInfo image_info = 246 HostInfo::GetSharedCacheImageInfo(module_spec.GetFileSpec().GetPath()); 247 248 // If we found it and it has the correct UUID, let's proceed with 249 // creating a module from the memory contents. 250 if (image_info.uuid && 251 (!module_spec.GetUUID() || module_spec.GetUUID() == image_info.uuid)) { 252 ModuleSpec shared_cache_spec(module_spec.GetFileSpec(), image_info.uuid, 253 image_info.data_sp); 254 err = ModuleList::GetSharedModule(shared_cache_spec, module_sp, 255 module_search_paths_ptr, old_modules, 256 did_create_ptr); 257 if (module_sp) 258 return err; 259 } 260 } 261 262 err = ModuleList::GetSharedModule(module_spec, module_sp, 263 module_search_paths_ptr, old_modules, 264 did_create_ptr); 265 if (module_sp) 266 return err; 267 268 if (!IsHost()) { 269 std::string cache_path(GetLocalCacheDirectory()); 270 // Only search for a locally cached file if we have a valid cache path 271 if (!cache_path.empty()) { 272 std::string module_path(module_spec.GetFileSpec().GetPath()); 273 cache_path.append(module_path); 274 FileSpec module_cache_spec(cache_path); 275 276 // if rsync is supported, always bring in the file - rsync will be very 277 // efficient when files are the same on the local and remote end of the 278 // connection 279 if (this->GetSupportsRSync()) { 280 err = BringInRemoteFile(this, module_spec, module_cache_spec); 281 if (err.Fail()) 282 return err; 283 if (FileSystem::Instance().Exists(module_cache_spec)) { 284 Log *log = GetLog(LLDBLog::Platform); 285 LLDB_LOGF(log, "[%s] module %s/%s was rsynced and is now there", 286 (IsHost() ? "host" : "remote"), 287 module_spec.GetFileSpec().GetDirectory().AsCString(), 288 module_spec.GetFileSpec().GetFilename().AsCString()); 289 ModuleSpec local_spec(module_cache_spec, 290 module_spec.GetArchitecture()); 291 module_sp = std::make_shared<Module>(local_spec); 292 module_sp->SetPlatformFileSpec(module_spec.GetFileSpec()); 293 return Status(); 294 } 295 } 296 297 // try to find the module in the cache 298 if (FileSystem::Instance().Exists(module_cache_spec)) { 299 // get the local and remote MD5 and compare 300 if (m_remote_platform_sp) { 301 // when going over the *slow* GDB remote transfer mechanism we first 302 // check the hashes of the files - and only do the actual transfer if 303 // they differ 304 uint64_t high_local, high_remote, low_local, low_remote; 305 auto MD5 = llvm::sys::fs::md5_contents(module_cache_spec.GetPath()); 306 if (!MD5) 307 return Status(MD5.getError()); 308 std::tie(high_local, low_local) = MD5->words(); 309 310 m_remote_platform_sp->CalculateMD5(module_spec.GetFileSpec(), 311 low_remote, high_remote); 312 if (low_local != low_remote || high_local != high_remote) { 313 // bring in the remote file 314 Log *log = GetLog(LLDBLog::Platform); 315 LLDB_LOGF(log, 316 "[%s] module %s/%s needs to be replaced from remote copy", 317 (IsHost() ? "host" : "remote"), 318 module_spec.GetFileSpec().GetDirectory().AsCString(), 319 module_spec.GetFileSpec().GetFilename().AsCString()); 320 Status err = 321 BringInRemoteFile(this, module_spec, module_cache_spec); 322 if (err.Fail()) 323 return err; 324 } 325 } 326 327 ModuleSpec local_spec(module_cache_spec, module_spec.GetArchitecture()); 328 module_sp = std::make_shared<Module>(local_spec); 329 module_sp->SetPlatformFileSpec(module_spec.GetFileSpec()); 330 Log *log = GetLog(LLDBLog::Platform); 331 LLDB_LOGF(log, "[%s] module %s/%s was found in the cache", 332 (IsHost() ? "host" : "remote"), 333 module_spec.GetFileSpec().GetDirectory().AsCString(), 334 module_spec.GetFileSpec().GetFilename().AsCString()); 335 return Status(); 336 } 337 338 // bring in the remote module file 339 LLDB_LOGF(log, "[%s] module %s/%s needs to come in remotely", 340 (IsHost() ? "host" : "remote"), 341 module_spec.GetFileSpec().GetDirectory().AsCString(), 342 module_spec.GetFileSpec().GetFilename().AsCString()); 343 Status err = BringInRemoteFile(this, module_spec, module_cache_spec); 344 if (err.Fail()) 345 return err; 346 if (FileSystem::Instance().Exists(module_cache_spec)) { 347 Log *log = GetLog(LLDBLog::Platform); 348 LLDB_LOGF(log, "[%s] module %s/%s is now cached and fine", 349 (IsHost() ? "host" : "remote"), 350 module_spec.GetFileSpec().GetDirectory().AsCString(), 351 module_spec.GetFileSpec().GetFilename().AsCString()); 352 ModuleSpec local_spec(module_cache_spec, module_spec.GetArchitecture()); 353 module_sp = std::make_shared<Module>(local_spec); 354 module_sp->SetPlatformFileSpec(module_spec.GetFileSpec()); 355 return Status(); 356 } else 357 return Status("unable to obtain valid module file"); 358 } else 359 return Status("no cache path"); 360 } else 361 return Status("unable to resolve module"); 362 } 363 364 Status PlatformDarwin::GetSharedModule( 365 const ModuleSpec &module_spec, Process *process, ModuleSP &module_sp, 366 const FileSpecList *module_search_paths_ptr, 367 llvm::SmallVectorImpl<ModuleSP> *old_modules, bool *did_create_ptr) { 368 Status error; 369 module_sp.reset(); 370 371 if (IsRemote()) { 372 // If we have a remote platform always, let it try and locate the shared 373 // module first. 374 if (m_remote_platform_sp) { 375 error = m_remote_platform_sp->GetSharedModule( 376 module_spec, process, module_sp, module_search_paths_ptr, old_modules, 377 did_create_ptr); 378 } 379 } 380 381 if (!module_sp) { 382 // Fall back to the local platform and find the file locally 383 error = Platform::GetSharedModule(module_spec, process, module_sp, 384 module_search_paths_ptr, old_modules, 385 did_create_ptr); 386 387 const FileSpec &platform_file = module_spec.GetFileSpec(); 388 if (!module_sp && module_search_paths_ptr && platform_file) { 389 // We can try to pull off part of the file path up to the bundle 390 // directory level and try any module search paths... 391 FileSpec bundle_directory; 392 if (Host::GetBundleDirectory(platform_file, bundle_directory)) { 393 if (platform_file == bundle_directory) { 394 ModuleSpec new_module_spec(module_spec); 395 new_module_spec.GetFileSpec() = bundle_directory; 396 if (Host::ResolveExecutableInBundle(new_module_spec.GetFileSpec())) { 397 Status new_error(Platform::GetSharedModule( 398 new_module_spec, process, module_sp, nullptr, old_modules, 399 did_create_ptr)); 400 401 if (module_sp) 402 return new_error; 403 } 404 } else { 405 char platform_path[PATH_MAX]; 406 char bundle_dir[PATH_MAX]; 407 platform_file.GetPath(platform_path, sizeof(platform_path)); 408 const size_t bundle_directory_len = 409 bundle_directory.GetPath(bundle_dir, sizeof(bundle_dir)); 410 char new_path[PATH_MAX]; 411 size_t num_module_search_paths = module_search_paths_ptr->GetSize(); 412 for (size_t i = 0; i < num_module_search_paths; ++i) { 413 const size_t search_path_len = 414 module_search_paths_ptr->GetFileSpecAtIndex(i).GetPath( 415 new_path, sizeof(new_path)); 416 if (search_path_len < sizeof(new_path)) { 417 snprintf(new_path + search_path_len, 418 sizeof(new_path) - search_path_len, "/%s", 419 platform_path + bundle_directory_len); 420 FileSpec new_file_spec(new_path); 421 if (FileSystem::Instance().Exists(new_file_spec)) { 422 ModuleSpec new_module_spec(module_spec); 423 new_module_spec.GetFileSpec() = new_file_spec; 424 Status new_error(Platform::GetSharedModule( 425 new_module_spec, process, module_sp, nullptr, old_modules, 426 did_create_ptr)); 427 428 if (module_sp) { 429 module_sp->SetPlatformFileSpec(new_file_spec); 430 return new_error; 431 } 432 } 433 } 434 } 435 } 436 } 437 } 438 } 439 if (module_sp) 440 module_sp->SetPlatformFileSpec(module_spec.GetFileSpec()); 441 return error; 442 } 443 444 size_t 445 PlatformDarwin::GetSoftwareBreakpointTrapOpcode(Target &target, 446 BreakpointSite *bp_site) { 447 const uint8_t *trap_opcode = nullptr; 448 uint32_t trap_opcode_size = 0; 449 bool bp_is_thumb = false; 450 451 llvm::Triple::ArchType machine = target.GetArchitecture().GetMachine(); 452 switch (machine) { 453 case llvm::Triple::aarch64_32: 454 case llvm::Triple::aarch64: { 455 // 'brk #0' or 0xd4200000 in BE byte order 456 static const uint8_t g_arm64_breakpoint_opcode[] = {0x00, 0x00, 0x20, 0xD4}; 457 trap_opcode = g_arm64_breakpoint_opcode; 458 trap_opcode_size = sizeof(g_arm64_breakpoint_opcode); 459 } break; 460 461 case llvm::Triple::thumb: 462 bp_is_thumb = true; 463 LLVM_FALLTHROUGH; 464 case llvm::Triple::arm: { 465 static const uint8_t g_arm_breakpoint_opcode[] = {0xFE, 0xDE, 0xFF, 0xE7}; 466 static const uint8_t g_thumb_breakpooint_opcode[] = {0xFE, 0xDE}; 467 468 // Auto detect arm/thumb if it wasn't explicitly specified 469 if (!bp_is_thumb) { 470 lldb::BreakpointLocationSP bp_loc_sp(bp_site->GetOwnerAtIndex(0)); 471 if (bp_loc_sp) 472 bp_is_thumb = bp_loc_sp->GetAddress().GetAddressClass() == 473 AddressClass::eCodeAlternateISA; 474 } 475 if (bp_is_thumb) { 476 trap_opcode = g_thumb_breakpooint_opcode; 477 trap_opcode_size = sizeof(g_thumb_breakpooint_opcode); 478 break; 479 } 480 trap_opcode = g_arm_breakpoint_opcode; 481 trap_opcode_size = sizeof(g_arm_breakpoint_opcode); 482 } break; 483 484 case llvm::Triple::ppc: 485 case llvm::Triple::ppc64: { 486 static const uint8_t g_ppc_breakpoint_opcode[] = {0x7F, 0xC0, 0x00, 0x08}; 487 trap_opcode = g_ppc_breakpoint_opcode; 488 trap_opcode_size = sizeof(g_ppc_breakpoint_opcode); 489 } break; 490 491 default: 492 return Platform::GetSoftwareBreakpointTrapOpcode(target, bp_site); 493 } 494 495 if (trap_opcode && trap_opcode_size) { 496 if (bp_site->SetTrapOpcode(trap_opcode, trap_opcode_size)) 497 return trap_opcode_size; 498 } 499 return 0; 500 } 501 502 bool PlatformDarwin::ModuleIsExcludedForUnconstrainedSearches( 503 lldb_private::Target &target, const lldb::ModuleSP &module_sp) { 504 if (!module_sp) 505 return false; 506 507 ObjectFile *obj_file = module_sp->GetObjectFile(); 508 if (!obj_file) 509 return false; 510 511 ObjectFile::Type obj_type = obj_file->GetType(); 512 return obj_type == ObjectFile::eTypeDynamicLinker; 513 } 514 515 void PlatformDarwin::x86GetSupportedArchitectures( 516 std::vector<ArchSpec> &archs) { 517 ArchSpec host_arch = HostInfo::GetArchitecture(HostInfo::eArchKindDefault); 518 archs.push_back(host_arch); 519 520 if (host_arch.GetCore() == ArchSpec::eCore_x86_64_x86_64h) { 521 archs.push_back(ArchSpec("x86_64-apple-macosx")); 522 archs.push_back(HostInfo::GetArchitecture(HostInfo::eArchKind32)); 523 } else { 524 ArchSpec host_arch64 = HostInfo::GetArchitecture(HostInfo::eArchKind64); 525 if (host_arch.IsExactMatch(host_arch64)) 526 archs.push_back(HostInfo::GetArchitecture(HostInfo::eArchKind32)); 527 } 528 } 529 530 static llvm::ArrayRef<const char *> GetCompatibleArchs(ArchSpec::Core core) { 531 switch (core) { 532 default: 533 LLVM_FALLTHROUGH; 534 case ArchSpec::eCore_arm_arm64e: { 535 static const char *g_arm64e_compatible_archs[] = { 536 "arm64e", "arm64", "armv7", "armv7f", "armv7k", "armv7s", 537 "armv7m", "armv7em", "armv6m", "armv6", "armv5", "armv4", 538 "arm", "thumbv7", "thumbv7f", "thumbv7k", "thumbv7s", "thumbv7m", 539 "thumbv7em", "thumbv6m", "thumbv6", "thumbv5", "thumbv4t", "thumb", 540 }; 541 return {g_arm64e_compatible_archs}; 542 } 543 case ArchSpec::eCore_arm_arm64: { 544 static const char *g_arm64_compatible_archs[] = { 545 "arm64", "armv7", "armv7f", "armv7k", "armv7s", "armv7m", 546 "armv7em", "armv6m", "armv6", "armv5", "armv4", "arm", 547 "thumbv7", "thumbv7f", "thumbv7k", "thumbv7s", "thumbv7m", "thumbv7em", 548 "thumbv6m", "thumbv6", "thumbv5", "thumbv4t", "thumb", 549 }; 550 return {g_arm64_compatible_archs}; 551 } 552 case ArchSpec::eCore_arm_armv7: { 553 static const char *g_armv7_compatible_archs[] = { 554 "armv7", "armv6m", "armv6", "armv5", "armv4", "arm", 555 "thumbv7", "thumbv6m", "thumbv6", "thumbv5", "thumbv4t", "thumb", 556 }; 557 return {g_armv7_compatible_archs}; 558 } 559 case ArchSpec::eCore_arm_armv7f: { 560 static const char *g_armv7f_compatible_archs[] = { 561 "armv7f", "armv7", "armv6m", "armv6", "armv5", 562 "armv4", "arm", "thumbv7f", "thumbv7", "thumbv6m", 563 "thumbv6", "thumbv5", "thumbv4t", "thumb", 564 }; 565 return {g_armv7f_compatible_archs}; 566 } 567 case ArchSpec::eCore_arm_armv7k: { 568 static const char *g_armv7k_compatible_archs[] = { 569 "armv7k", "armv7", "armv6m", "armv6", "armv5", 570 "armv4", "arm", "thumbv7k", "thumbv7", "thumbv6m", 571 "thumbv6", "thumbv5", "thumbv4t", "thumb", 572 }; 573 return {g_armv7k_compatible_archs}; 574 } 575 case ArchSpec::eCore_arm_armv7s: { 576 static const char *g_armv7s_compatible_archs[] = { 577 "armv7s", "armv7", "armv6m", "armv6", "armv5", 578 "armv4", "arm", "thumbv7s", "thumbv7", "thumbv6m", 579 "thumbv6", "thumbv5", "thumbv4t", "thumb", 580 }; 581 return {g_armv7s_compatible_archs}; 582 } 583 case ArchSpec::eCore_arm_armv7m: { 584 static const char *g_armv7m_compatible_archs[] = { 585 "armv7m", "armv7", "armv6m", "armv6", "armv5", 586 "armv4", "arm", "thumbv7m", "thumbv7", "thumbv6m", 587 "thumbv6", "thumbv5", "thumbv4t", "thumb", 588 }; 589 return {g_armv7m_compatible_archs}; 590 } 591 case ArchSpec::eCore_arm_armv7em: { 592 static const char *g_armv7em_compatible_archs[] = { 593 "armv7em", "armv7", "armv6m", "armv6", "armv5", 594 "armv4", "arm", "thumbv7em", "thumbv7", "thumbv6m", 595 "thumbv6", "thumbv5", "thumbv4t", "thumb", 596 }; 597 return {g_armv7em_compatible_archs}; 598 } 599 case ArchSpec::eCore_arm_armv6m: { 600 static const char *g_armv6m_compatible_archs[] = { 601 "armv6m", "armv6", "armv5", "armv4", "arm", 602 "thumbv6m", "thumbv6", "thumbv5", "thumbv4t", "thumb", 603 }; 604 return {g_armv6m_compatible_archs}; 605 } 606 case ArchSpec::eCore_arm_armv6: { 607 static const char *g_armv6_compatible_archs[] = { 608 "armv6", "armv5", "armv4", "arm", 609 "thumbv6", "thumbv5", "thumbv4t", "thumb", 610 }; 611 return {g_armv6_compatible_archs}; 612 } 613 case ArchSpec::eCore_arm_armv5: { 614 static const char *g_armv5_compatible_archs[] = { 615 "armv5", "armv4", "arm", "thumbv5", "thumbv4t", "thumb", 616 }; 617 return {g_armv5_compatible_archs}; 618 } 619 case ArchSpec::eCore_arm_armv4: { 620 static const char *g_armv4_compatible_archs[] = { 621 "armv4", 622 "arm", 623 "thumbv4t", 624 "thumb", 625 }; 626 return {g_armv4_compatible_archs}; 627 } 628 } 629 return {}; 630 } 631 632 /// The architecture selection rules for arm processors These cpu subtypes have 633 /// distinct names (e.g. armv7f) but armv7 binaries run fine on an armv7f 634 /// processor. 635 void PlatformDarwin::ARMGetSupportedArchitectures( 636 std::vector<ArchSpec> &archs, llvm::Optional<llvm::Triple::OSType> os) { 637 const ArchSpec system_arch = GetSystemArchitecture(); 638 const ArchSpec::Core system_core = system_arch.GetCore(); 639 for (const char *arch : GetCompatibleArchs(system_core)) { 640 llvm::Triple triple; 641 triple.setArchName(arch); 642 triple.setVendor(llvm::Triple::VendorType::Apple); 643 if (os) 644 triple.setOS(*os); 645 archs.push_back(ArchSpec(triple)); 646 } 647 } 648 649 static FileSpec GetXcodeSelectPath() { 650 static FileSpec g_xcode_select_filespec; 651 652 if (!g_xcode_select_filespec) { 653 FileSpec xcode_select_cmd("/usr/bin/xcode-select"); 654 if (FileSystem::Instance().Exists(xcode_select_cmd)) { 655 int exit_status = -1; 656 int signo = -1; 657 std::string command_output; 658 Status status = 659 Host::RunShellCommand("/usr/bin/xcode-select --print-path", 660 FileSpec(), // current working directory 661 &exit_status, &signo, &command_output, 662 std::chrono::seconds(2), // short timeout 663 false); // don't run in a shell 664 if (status.Success() && exit_status == 0 && !command_output.empty()) { 665 size_t first_non_newline = command_output.find_last_not_of("\r\n"); 666 if (first_non_newline != std::string::npos) { 667 command_output.erase(first_non_newline + 1); 668 } 669 g_xcode_select_filespec = FileSpec(command_output); 670 } 671 } 672 } 673 674 return g_xcode_select_filespec; 675 } 676 677 BreakpointSP PlatformDarwin::SetThreadCreationBreakpoint(Target &target) { 678 BreakpointSP bp_sp; 679 static const char *g_bp_names[] = { 680 "start_wqthread", "_pthread_wqthread", "_pthread_start", 681 }; 682 683 static const char *g_bp_modules[] = {"libsystem_c.dylib", 684 "libSystem.B.dylib"}; 685 686 FileSpecList bp_modules; 687 for (size_t i = 0; i < llvm::array_lengthof(g_bp_modules); i++) { 688 const char *bp_module = g_bp_modules[i]; 689 bp_modules.EmplaceBack(bp_module); 690 } 691 692 bool internal = true; 693 bool hardware = false; 694 LazyBool skip_prologue = eLazyBoolNo; 695 bp_sp = target.CreateBreakpoint(&bp_modules, nullptr, g_bp_names, 696 llvm::array_lengthof(g_bp_names), 697 eFunctionNameTypeFull, eLanguageTypeUnknown, 698 0, skip_prologue, internal, hardware); 699 bp_sp->SetBreakpointKind("thread-creation"); 700 701 return bp_sp; 702 } 703 704 uint32_t 705 PlatformDarwin::GetResumeCountForLaunchInfo(ProcessLaunchInfo &launch_info) { 706 const FileSpec &shell = launch_info.GetShell(); 707 if (!shell) 708 return 1; 709 710 std::string shell_string = shell.GetPath(); 711 const char *shell_name = strrchr(shell_string.c_str(), '/'); 712 if (shell_name == nullptr) 713 shell_name = shell_string.c_str(); 714 else 715 shell_name++; 716 717 if (strcmp(shell_name, "sh") == 0) { 718 // /bin/sh re-exec's itself as /bin/bash requiring another resume. But it 719 // only does this if the COMMAND_MODE environment variable is set to 720 // "legacy". 721 if (launch_info.GetEnvironment().lookup("COMMAND_MODE") == "legacy") 722 return 2; 723 return 1; 724 } else if (strcmp(shell_name, "csh") == 0 || 725 strcmp(shell_name, "tcsh") == 0 || 726 strcmp(shell_name, "zsh") == 0) { 727 // csh and tcsh always seem to re-exec themselves. 728 return 2; 729 } else 730 return 1; 731 } 732 733 lldb::ProcessSP PlatformDarwin::DebugProcess(ProcessLaunchInfo &launch_info, 734 Debugger &debugger, Target &target, 735 Status &error) { 736 ProcessSP process_sp; 737 738 if (IsHost()) { 739 // We are going to hand this process off to debugserver which will be in 740 // charge of setting the exit status. However, we still need to reap it 741 // from lldb. So, make sure we use a exit callback which does not set exit 742 // status. 743 launch_info.SetMonitorProcessCallback( 744 &ProcessLaunchInfo::NoOpMonitorCallback); 745 process_sp = Platform::DebugProcess(launch_info, debugger, target, error); 746 } else { 747 if (m_remote_platform_sp) 748 process_sp = m_remote_platform_sp->DebugProcess(launch_info, debugger, 749 target, error); 750 else 751 error.SetErrorString("the platform is not currently connected"); 752 } 753 return process_sp; 754 } 755 756 void PlatformDarwin::CalculateTrapHandlerSymbolNames() { 757 m_trap_handlers.push_back(ConstString("_sigtramp")); 758 } 759 760 static FileSpec GetCommandLineToolsLibraryPath() { 761 static FileSpec g_command_line_tools_filespec; 762 763 if (!g_command_line_tools_filespec) { 764 FileSpec command_line_tools_path(GetXcodeSelectPath()); 765 command_line_tools_path.AppendPathComponent("Library"); 766 if (FileSystem::Instance().Exists(command_line_tools_path)) { 767 g_command_line_tools_filespec = command_line_tools_path; 768 } 769 } 770 771 return g_command_line_tools_filespec; 772 } 773 774 FileSystem::EnumerateDirectoryResult PlatformDarwin::DirectoryEnumerator( 775 void *baton, llvm::sys::fs::file_type file_type, llvm::StringRef path) { 776 SDKEnumeratorInfo *enumerator_info = static_cast<SDKEnumeratorInfo *>(baton); 777 778 FileSpec spec(path); 779 if (XcodeSDK::SDKSupportsModules(enumerator_info->sdk_type, spec)) { 780 enumerator_info->found_path = spec; 781 return FileSystem::EnumerateDirectoryResult::eEnumerateDirectoryResultNext; 782 } 783 784 return FileSystem::EnumerateDirectoryResult::eEnumerateDirectoryResultNext; 785 } 786 787 FileSpec PlatformDarwin::FindSDKInXcodeForModules(XcodeSDK::Type sdk_type, 788 const FileSpec &sdks_spec) { 789 // Look inside Xcode for the required installed iOS SDK version 790 791 if (!FileSystem::Instance().IsDirectory(sdks_spec)) { 792 return FileSpec(); 793 } 794 795 const bool find_directories = true; 796 const bool find_files = false; 797 const bool find_other = true; // include symlinks 798 799 SDKEnumeratorInfo enumerator_info; 800 801 enumerator_info.sdk_type = sdk_type; 802 803 FileSystem::Instance().EnumerateDirectory( 804 sdks_spec.GetPath(), find_directories, find_files, find_other, 805 DirectoryEnumerator, &enumerator_info); 806 807 if (FileSystem::Instance().IsDirectory(enumerator_info.found_path)) 808 return enumerator_info.found_path; 809 else 810 return FileSpec(); 811 } 812 813 FileSpec PlatformDarwin::GetSDKDirectoryForModules(XcodeSDK::Type sdk_type) { 814 FileSpec sdks_spec = HostInfo::GetXcodeContentsDirectory(); 815 sdks_spec.AppendPathComponent("Developer"); 816 sdks_spec.AppendPathComponent("Platforms"); 817 818 switch (sdk_type) { 819 case XcodeSDK::Type::MacOSX: 820 sdks_spec.AppendPathComponent("MacOSX.platform"); 821 break; 822 case XcodeSDK::Type::iPhoneSimulator: 823 sdks_spec.AppendPathComponent("iPhoneSimulator.platform"); 824 break; 825 case XcodeSDK::Type::iPhoneOS: 826 sdks_spec.AppendPathComponent("iPhoneOS.platform"); 827 break; 828 case XcodeSDK::Type::WatchSimulator: 829 sdks_spec.AppendPathComponent("WatchSimulator.platform"); 830 break; 831 case XcodeSDK::Type::AppleTVSimulator: 832 sdks_spec.AppendPathComponent("AppleTVSimulator.platform"); 833 break; 834 default: 835 llvm_unreachable("unsupported sdk"); 836 } 837 838 sdks_spec.AppendPathComponent("Developer"); 839 sdks_spec.AppendPathComponent("SDKs"); 840 841 if (sdk_type == XcodeSDK::Type::MacOSX) { 842 llvm::VersionTuple version = HostInfo::GetOSVersion(); 843 844 if (!version.empty()) { 845 if (XcodeSDK::SDKSupportsModules(XcodeSDK::Type::MacOSX, version)) { 846 // If the Xcode SDKs are not available then try to use the 847 // Command Line Tools one which is only for MacOSX. 848 if (!FileSystem::Instance().Exists(sdks_spec)) { 849 sdks_spec = GetCommandLineToolsLibraryPath(); 850 sdks_spec.AppendPathComponent("SDKs"); 851 } 852 853 // We slightly prefer the exact SDK for this machine. See if it is 854 // there. 855 856 FileSpec native_sdk_spec = sdks_spec; 857 StreamString native_sdk_name; 858 native_sdk_name.Printf("MacOSX%u.%u.sdk", version.getMajor(), 859 version.getMinor().getValueOr(0)); 860 native_sdk_spec.AppendPathComponent(native_sdk_name.GetString()); 861 862 if (FileSystem::Instance().Exists(native_sdk_spec)) { 863 return native_sdk_spec; 864 } 865 } 866 } 867 } 868 869 return FindSDKInXcodeForModules(sdk_type, sdks_spec); 870 } 871 872 std::tuple<llvm::VersionTuple, llvm::StringRef> 873 PlatformDarwin::ParseVersionBuildDir(llvm::StringRef dir) { 874 llvm::StringRef build; 875 llvm::StringRef version_str; 876 llvm::StringRef build_str; 877 std::tie(version_str, build_str) = dir.split(' '); 878 llvm::VersionTuple version; 879 if (!version.tryParse(version_str) || 880 build_str.empty()) { 881 if (build_str.consume_front("(")) { 882 size_t pos = build_str.find(')'); 883 build = build_str.slice(0, pos); 884 } 885 } 886 887 return std::make_tuple(version, build); 888 } 889 890 llvm::Expected<StructuredData::DictionarySP> 891 PlatformDarwin::FetchExtendedCrashInformation(Process &process) { 892 Log *log = GetLog(LLDBLog::Process); 893 894 StructuredData::ArraySP annotations = ExtractCrashInfoAnnotations(process); 895 896 if (!annotations || !annotations->GetSize()) { 897 LLDB_LOG(log, "Couldn't extract crash information annotations"); 898 return nullptr; 899 } 900 901 StructuredData::DictionarySP extended_crash_info = 902 std::make_shared<StructuredData::Dictionary>(); 903 904 extended_crash_info->AddItem("crash-info annotations", annotations); 905 906 return extended_crash_info; 907 } 908 909 StructuredData::ArraySP 910 PlatformDarwin::ExtractCrashInfoAnnotations(Process &process) { 911 Log *log = GetLog(LLDBLog::Process); 912 913 ConstString section_name("__crash_info"); 914 Target &target = process.GetTarget(); 915 StructuredData::ArraySP array_sp = std::make_shared<StructuredData::Array>(); 916 917 for (ModuleSP module : target.GetImages().Modules()) { 918 SectionList *sections = module->GetSectionList(); 919 920 std::string module_name = module->GetSpecificationDescription(); 921 922 // The DYDL module is skipped since it's always loaded when running the 923 // binary. 924 if (module_name == "/usr/lib/dyld") 925 continue; 926 927 if (!sections) { 928 LLDB_LOG(log, "Module {0} doesn't have any section!", module_name); 929 continue; 930 } 931 932 SectionSP crash_info = sections->FindSectionByName(section_name); 933 if (!crash_info) { 934 LLDB_LOG(log, "Module {0} doesn't have section {1}!", module_name, 935 section_name); 936 continue; 937 } 938 939 addr_t load_addr = crash_info->GetLoadBaseAddress(&target); 940 941 if (load_addr == LLDB_INVALID_ADDRESS) { 942 LLDB_LOG(log, "Module {0} has an invalid '{1}' section load address: {2}", 943 module_name, section_name, load_addr); 944 continue; 945 } 946 947 Status error; 948 CrashInfoAnnotations annotations; 949 size_t expected_size = sizeof(CrashInfoAnnotations); 950 size_t bytes_read = process.ReadMemoryFromInferior(load_addr, &annotations, 951 expected_size, error); 952 953 if (expected_size != bytes_read || error.Fail()) { 954 LLDB_LOG(log, "Failed to read {0} section from memory in module {1}: {2}", 955 section_name, module_name, error); 956 continue; 957 } 958 959 // initial support added for version 5 960 if (annotations.version < 5) { 961 LLDB_LOG(log, 962 "Annotation version lower than 5 unsupported! Module {0} has " 963 "version {1} instead.", 964 module_name, annotations.version); 965 continue; 966 } 967 968 if (!annotations.message) { 969 LLDB_LOG(log, "No message available for module {0}.", module_name); 970 continue; 971 } 972 973 std::string message; 974 bytes_read = 975 process.ReadCStringFromMemory(annotations.message, message, error); 976 977 if (message.empty() || bytes_read != message.size() || error.Fail()) { 978 LLDB_LOG(log, "Failed to read the message from memory in module {0}: {1}", 979 module_name, error); 980 continue; 981 } 982 983 // Remove trailing newline from message 984 if (message.back() == '\n') 985 message.pop_back(); 986 987 if (!annotations.message2) 988 LLDB_LOG(log, "No message2 available for module {0}.", module_name); 989 990 std::string message2; 991 bytes_read = 992 process.ReadCStringFromMemory(annotations.message2, message2, error); 993 994 if (!message2.empty() && bytes_read == message2.size() && error.Success()) 995 if (message2.back() == '\n') 996 message2.pop_back(); 997 998 StructuredData::DictionarySP entry_sp = 999 std::make_shared<StructuredData::Dictionary>(); 1000 1001 entry_sp->AddStringItem("image", module->GetFileSpec().GetPath(false)); 1002 entry_sp->AddStringItem("uuid", module->GetUUID().GetAsString()); 1003 entry_sp->AddStringItem("message", message); 1004 entry_sp->AddStringItem("message2", message2); 1005 entry_sp->AddIntegerItem("abort-cause", annotations.abort_cause); 1006 1007 array_sp->AddItem(entry_sp); 1008 } 1009 1010 return array_sp; 1011 } 1012 1013 void PlatformDarwin::AddClangModuleCompilationOptionsForSDKType( 1014 Target *target, std::vector<std::string> &options, XcodeSDK::Type sdk_type) { 1015 const std::vector<std::string> apple_arguments = { 1016 "-x", "objective-c++", "-fobjc-arc", 1017 "-fblocks", "-D_ISO646_H", "-D__ISO646_H", 1018 "-fgnuc-version=4.2.1"}; 1019 1020 options.insert(options.end(), apple_arguments.begin(), apple_arguments.end()); 1021 1022 StreamString minimum_version_option; 1023 bool use_current_os_version = false; 1024 // If the SDK type is for the host OS, use its version number. 1025 auto get_host_os = []() { return HostInfo::GetTargetTriple().getOS(); }; 1026 switch (sdk_type) { 1027 case XcodeSDK::Type::MacOSX: 1028 use_current_os_version = get_host_os() == llvm::Triple::MacOSX; 1029 break; 1030 case XcodeSDK::Type::iPhoneOS: 1031 use_current_os_version = get_host_os() == llvm::Triple::IOS; 1032 break; 1033 case XcodeSDK::Type::AppleTVOS: 1034 use_current_os_version = get_host_os() == llvm::Triple::TvOS; 1035 break; 1036 case XcodeSDK::Type::watchOS: 1037 use_current_os_version = get_host_os() == llvm::Triple::WatchOS; 1038 break; 1039 default: 1040 break; 1041 } 1042 1043 llvm::VersionTuple version; 1044 if (use_current_os_version) 1045 version = GetOSVersion(); 1046 else if (target) { 1047 // Our OS doesn't match our executable so we need to get the min OS version 1048 // from the object file 1049 ModuleSP exe_module_sp = target->GetExecutableModule(); 1050 if (exe_module_sp) { 1051 ObjectFile *object_file = exe_module_sp->GetObjectFile(); 1052 if (object_file) 1053 version = object_file->GetMinimumOSVersion(); 1054 } 1055 } 1056 // Only add the version-min options if we got a version from somewhere 1057 if (!version.empty() && sdk_type != XcodeSDK::Type::Linux) { 1058 #define OPTION(PREFIX, NAME, VAR, ...) \ 1059 const char *opt_##VAR = NAME; \ 1060 (void)opt_##VAR; 1061 #include "clang/Driver/Options.inc" 1062 #undef OPTION 1063 minimum_version_option << '-'; 1064 switch (sdk_type) { 1065 case XcodeSDK::Type::MacOSX: 1066 minimum_version_option << opt_mmacosx_version_min_EQ; 1067 break; 1068 case XcodeSDK::Type::iPhoneSimulator: 1069 minimum_version_option << opt_mios_simulator_version_min_EQ; 1070 break; 1071 case XcodeSDK::Type::iPhoneOS: 1072 minimum_version_option << opt_mios_version_min_EQ; 1073 break; 1074 case XcodeSDK::Type::AppleTVSimulator: 1075 minimum_version_option << opt_mtvos_simulator_version_min_EQ; 1076 break; 1077 case XcodeSDK::Type::AppleTVOS: 1078 minimum_version_option << opt_mtvos_version_min_EQ; 1079 break; 1080 case XcodeSDK::Type::WatchSimulator: 1081 minimum_version_option << opt_mwatchos_simulator_version_min_EQ; 1082 break; 1083 case XcodeSDK::Type::watchOS: 1084 minimum_version_option << opt_mwatchos_version_min_EQ; 1085 break; 1086 case XcodeSDK::Type::bridgeOS: 1087 case XcodeSDK::Type::Linux: 1088 case XcodeSDK::Type::unknown: 1089 if (Log *log = GetLog(LLDBLog::Host)) { 1090 XcodeSDK::Info info; 1091 info.type = sdk_type; 1092 LLDB_LOGF(log, "Clang modules on %s are not supported", 1093 XcodeSDK::GetCanonicalName(info).c_str()); 1094 } 1095 return; 1096 } 1097 minimum_version_option << version.getAsString(); 1098 options.emplace_back(std::string(minimum_version_option.GetString())); 1099 } 1100 1101 FileSpec sysroot_spec; 1102 // Scope for mutex locker below 1103 { 1104 std::lock_guard<std::mutex> guard(m_mutex); 1105 sysroot_spec = GetSDKDirectoryForModules(sdk_type); 1106 } 1107 1108 if (FileSystem::Instance().IsDirectory(sysroot_spec.GetPath())) { 1109 options.push_back("-isysroot"); 1110 options.push_back(sysroot_spec.GetPath()); 1111 } 1112 } 1113 1114 ConstString PlatformDarwin::GetFullNameForDylib(ConstString basename) { 1115 if (basename.IsEmpty()) 1116 return basename; 1117 1118 StreamString stream; 1119 stream.Printf("lib%s.dylib", basename.GetCString()); 1120 return ConstString(stream.GetString()); 1121 } 1122 1123 llvm::VersionTuple PlatformDarwin::GetOSVersion(Process *process) { 1124 if (process && GetPluginName().contains("-simulator")) { 1125 lldb_private::ProcessInstanceInfo proc_info; 1126 if (Host::GetProcessInfo(process->GetID(), proc_info)) { 1127 const Environment &env = proc_info.GetEnvironment(); 1128 1129 llvm::VersionTuple result; 1130 if (!result.tryParse(env.lookup("SIMULATOR_RUNTIME_VERSION"))) 1131 return result; 1132 1133 std::string dyld_root_path = env.lookup("DYLD_ROOT_PATH"); 1134 if (!dyld_root_path.empty()) { 1135 dyld_root_path += "/System/Library/CoreServices/SystemVersion.plist"; 1136 ApplePropertyList system_version_plist(dyld_root_path.c_str()); 1137 std::string product_version; 1138 if (system_version_plist.GetValueAsString("ProductVersion", 1139 product_version)) { 1140 if (!result.tryParse(product_version)) 1141 return result; 1142 } 1143 } 1144 } 1145 // For simulator platforms, do NOT call back through 1146 // Platform::GetOSVersion() as it might call Process::GetHostOSVersion() 1147 // which we don't want as it will be incorrect 1148 return llvm::VersionTuple(); 1149 } 1150 1151 return Platform::GetOSVersion(process); 1152 } 1153 1154 lldb_private::FileSpec PlatformDarwin::LocateExecutable(const char *basename) { 1155 // A collection of SBFileSpec whose SBFileSpec.m_directory members are filled 1156 // in with any executable directories that should be searched. 1157 static std::vector<FileSpec> g_executable_dirs; 1158 1159 // Find the global list of directories that we will search for executables 1160 // once so we don't keep doing the work over and over. 1161 static llvm::once_flag g_once_flag; 1162 llvm::call_once(g_once_flag, []() { 1163 1164 // When locating executables, trust the DEVELOPER_DIR first if it is set 1165 FileSpec xcode_contents_dir = HostInfo::GetXcodeContentsDirectory(); 1166 if (xcode_contents_dir) { 1167 FileSpec xcode_lldb_resources = xcode_contents_dir; 1168 xcode_lldb_resources.AppendPathComponent("SharedFrameworks"); 1169 xcode_lldb_resources.AppendPathComponent("LLDB.framework"); 1170 xcode_lldb_resources.AppendPathComponent("Resources"); 1171 if (FileSystem::Instance().Exists(xcode_lldb_resources)) { 1172 FileSpec dir; 1173 dir.GetDirectory().SetCString(xcode_lldb_resources.GetPath().c_str()); 1174 g_executable_dirs.push_back(dir); 1175 } 1176 } 1177 // Xcode might not be installed so we also check for the Command Line Tools. 1178 FileSpec command_line_tools_dir = GetCommandLineToolsLibraryPath(); 1179 if (command_line_tools_dir) { 1180 FileSpec cmd_line_lldb_resources = command_line_tools_dir; 1181 cmd_line_lldb_resources.AppendPathComponent("PrivateFrameworks"); 1182 cmd_line_lldb_resources.AppendPathComponent("LLDB.framework"); 1183 cmd_line_lldb_resources.AppendPathComponent("Resources"); 1184 if (FileSystem::Instance().Exists(cmd_line_lldb_resources)) { 1185 FileSpec dir; 1186 dir.GetDirectory().SetCString( 1187 cmd_line_lldb_resources.GetPath().c_str()); 1188 g_executable_dirs.push_back(dir); 1189 } 1190 } 1191 }); 1192 1193 // Now search the global list of executable directories for the executable we 1194 // are looking for 1195 for (const auto &executable_dir : g_executable_dirs) { 1196 FileSpec executable_file; 1197 executable_file.GetDirectory() = executable_dir.GetDirectory(); 1198 executable_file.GetFilename().SetCString(basename); 1199 if (FileSystem::Instance().Exists(executable_file)) 1200 return executable_file; 1201 } 1202 1203 return FileSpec(); 1204 } 1205 1206 lldb_private::Status 1207 PlatformDarwin::LaunchProcess(lldb_private::ProcessLaunchInfo &launch_info) { 1208 // Starting in Fall 2016 OSes, NSLog messages only get mirrored to stderr if 1209 // the OS_ACTIVITY_DT_MODE environment variable is set. (It doesn't require 1210 // any specific value; rather, it just needs to exist). We will set it here 1211 // as long as the IDE_DISABLED_OS_ACTIVITY_DT_MODE flag is not set. Xcode 1212 // makes use of IDE_DISABLED_OS_ACTIVITY_DT_MODE to tell 1213 // LLDB *not* to muck with the OS_ACTIVITY_DT_MODE flag when they 1214 // specifically want it unset. 1215 const char *disable_env_var = "IDE_DISABLED_OS_ACTIVITY_DT_MODE"; 1216 auto &env_vars = launch_info.GetEnvironment(); 1217 if (!env_vars.count(disable_env_var)) { 1218 // We want to make sure that OS_ACTIVITY_DT_MODE is set so that we get 1219 // os_log and NSLog messages mirrored to the target process stderr. 1220 env_vars.try_emplace("OS_ACTIVITY_DT_MODE", "enable"); 1221 } 1222 1223 // Let our parent class do the real launching. 1224 return PlatformPOSIX::LaunchProcess(launch_info); 1225 } 1226 1227 lldb_private::Status PlatformDarwin::FindBundleBinaryInExecSearchPaths( 1228 const ModuleSpec &module_spec, Process *process, ModuleSP &module_sp, 1229 const FileSpecList *module_search_paths_ptr, 1230 llvm::SmallVectorImpl<ModuleSP> *old_modules, bool *did_create_ptr) { 1231 const FileSpec &platform_file = module_spec.GetFileSpec(); 1232 // See if the file is present in any of the module_search_paths_ptr 1233 // directories. 1234 if (!module_sp && module_search_paths_ptr && platform_file) { 1235 // create a vector of all the file / directory names in platform_file e.g. 1236 // this might be 1237 // /System/Library/PrivateFrameworks/UIFoundation.framework/UIFoundation 1238 // 1239 // We'll need to look in the module_search_paths_ptr directories for both 1240 // "UIFoundation" and "UIFoundation.framework" -- most likely the latter 1241 // will be the one we find there. 1242 1243 FileSpec platform_pull_upart(platform_file); 1244 std::vector<std::string> path_parts; 1245 path_parts.push_back( 1246 platform_pull_upart.GetLastPathComponent().AsCString()); 1247 while (platform_pull_upart.RemoveLastPathComponent()) { 1248 ConstString part = platform_pull_upart.GetLastPathComponent(); 1249 path_parts.push_back(part.AsCString()); 1250 } 1251 const size_t path_parts_size = path_parts.size(); 1252 1253 size_t num_module_search_paths = module_search_paths_ptr->GetSize(); 1254 for (size_t i = 0; i < num_module_search_paths; ++i) { 1255 Log *log_verbose = GetLog(LLDBLog::Host); 1256 LLDB_LOGF( 1257 log_verbose, 1258 "PlatformRemoteDarwinDevice::GetSharedModule searching for binary in " 1259 "search-path %s", 1260 module_search_paths_ptr->GetFileSpecAtIndex(i).GetPath().c_str()); 1261 // Create a new FileSpec with this module_search_paths_ptr plus just the 1262 // filename ("UIFoundation"), then the parent dir plus filename 1263 // ("UIFoundation.framework/UIFoundation") etc - up to four names (to 1264 // handle "Foo.framework/Contents/MacOS/Foo") 1265 1266 for (size_t j = 0; j < 4 && j < path_parts_size - 1; ++j) { 1267 FileSpec path_to_try(module_search_paths_ptr->GetFileSpecAtIndex(i)); 1268 1269 // Add the components backwards. For 1270 // .../PrivateFrameworks/UIFoundation.framework/UIFoundation path_parts 1271 // is 1272 // [0] UIFoundation 1273 // [1] UIFoundation.framework 1274 // [2] PrivateFrameworks 1275 // 1276 // and if 'j' is 2, we want to append path_parts[1] and then 1277 // path_parts[0], aka 'UIFoundation.framework/UIFoundation', to the 1278 // module_search_paths_ptr path. 1279 1280 for (int k = j; k >= 0; --k) { 1281 path_to_try.AppendPathComponent(path_parts[k]); 1282 } 1283 1284 if (FileSystem::Instance().Exists(path_to_try)) { 1285 ModuleSpec new_module_spec(module_spec); 1286 new_module_spec.GetFileSpec() = path_to_try; 1287 Status new_error( 1288 Platform::GetSharedModule(new_module_spec, process, module_sp, 1289 nullptr, old_modules, did_create_ptr)); 1290 1291 if (module_sp) { 1292 module_sp->SetPlatformFileSpec(path_to_try); 1293 return new_error; 1294 } 1295 } 1296 } 1297 } 1298 } 1299 return Status(); 1300 } 1301 1302 std::string PlatformDarwin::FindComponentInPath(llvm::StringRef path, 1303 llvm::StringRef component) { 1304 auto begin = llvm::sys::path::begin(path); 1305 auto end = llvm::sys::path::end(path); 1306 for (auto it = begin; it != end; ++it) { 1307 if (it->contains(component)) { 1308 llvm::SmallString<128> buffer; 1309 llvm::sys::path::append(buffer, begin, ++it, 1310 llvm::sys::path::Style::posix); 1311 return buffer.str().str(); 1312 } 1313 } 1314 return {}; 1315 } 1316 1317 FileSpec PlatformDarwin::GetCurrentToolchainDirectory() { 1318 if (FileSpec fspec = HostInfo::GetShlibDir()) 1319 return FileSpec(FindComponentInPath(fspec.GetPath(), ".xctoolchain")); 1320 return {}; 1321 } 1322 1323 FileSpec PlatformDarwin::GetCurrentCommandLineToolsDirectory() { 1324 if (FileSpec fspec = HostInfo::GetShlibDir()) 1325 return FileSpec(FindComponentInPath(fspec.GetPath(), "CommandLineTools")); 1326 return {}; 1327 } 1328 1329 llvm::Triple::OSType PlatformDarwin::GetHostOSType() { 1330 #if !defined(__APPLE__) 1331 return llvm::Triple::MacOSX; 1332 #else 1333 #if TARGET_OS_OSX 1334 return llvm::Triple::MacOSX; 1335 #elif TARGET_OS_IOS 1336 return llvm::Triple::IOS; 1337 #elif TARGET_OS_WATCH 1338 return llvm::Triple::WatchOS; 1339 #elif TARGET_OS_TV 1340 return llvm::Triple::TvOS; 1341 #elif TARGET_OS_BRIDGE 1342 return llvm::Triple::BridgeOS; 1343 #else 1344 #error "LLDB being compiled for an unrecognized Darwin OS" 1345 #endif 1346 #endif // __APPLE__ 1347 } 1348