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