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