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