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