1 //===-- PlatformDarwinKernel.cpp -----------------------------------*- C++ -*-===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 10 #include "PlatformDarwinKernel.h" 11 12 #if defined (__APPLE__) // This Plugin uses the Mac-specific source/Host/macosx/cfcpp utilities 13 14 15 // C Includes 16 // C++ Includes 17 // Other libraries and framework includes 18 // Project includes 19 #include "lldb/Breakpoint/BreakpointLocation.h" 20 #include "lldb/Core/ArchSpec.h" 21 #include "lldb/Core/Error.h" 22 #include "lldb/Core/Log.h" 23 #include "lldb/Core/Module.h" 24 #include "lldb/Core/ModuleList.h" 25 #include "lldb/Core/ModuleSpec.h" 26 #include "lldb/Core/PluginManager.h" 27 #include "lldb/Core/StreamString.h" 28 #include "lldb/Host/FileSpec.h" 29 #include "lldb/Host/Host.h" 30 #include "lldb/Interpreter/OptionValueFileSpecList.h" 31 #include "lldb/Interpreter/OptionValueProperties.h" 32 #include "lldb/Interpreter/Property.h" 33 #include "lldb/Target/Platform.h" 34 #include "lldb/Target/Process.h" 35 #include "lldb/Target/Target.h" 36 37 #include <CoreFoundation/CoreFoundation.h> 38 39 #include "Host/macosx/cfcpp/CFCBundle.h" 40 41 using namespace lldb; 42 using namespace lldb_private; 43 44 //------------------------------------------------------------------ 45 // Static Variables 46 //------------------------------------------------------------------ 47 static uint32_t g_initialize_count = 0; 48 49 //------------------------------------------------------------------ 50 // Static Functions 51 //------------------------------------------------------------------ 52 void 53 PlatformDarwinKernel::Initialize () 54 { 55 PlatformDarwin::Initialize (); 56 57 if (g_initialize_count++ == 0) 58 { 59 PluginManager::RegisterPlugin (PlatformDarwinKernel::GetPluginNameStatic(), 60 PlatformDarwinKernel::GetDescriptionStatic(), 61 PlatformDarwinKernel::CreateInstance, 62 PlatformDarwinKernel::DebuggerInitialize); 63 } 64 } 65 66 void 67 PlatformDarwinKernel::Terminate () 68 { 69 if (g_initialize_count > 0) 70 { 71 if (--g_initialize_count == 0) 72 { 73 PluginManager::UnregisterPlugin (PlatformDarwinKernel::CreateInstance); 74 } 75 } 76 77 PlatformDarwin::Terminate (); 78 } 79 80 PlatformSP 81 PlatformDarwinKernel::CreateInstance (bool force, const ArchSpec *arch) 82 { 83 Log *log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_PLATFORM)); 84 if (log) 85 { 86 const char *arch_name; 87 if (arch && arch->GetArchitectureName ()) 88 arch_name = arch->GetArchitectureName (); 89 else 90 arch_name = "<null>"; 91 92 const char *triple_cstr = arch ? arch->GetTriple ().getTriple ().c_str() : "<null>"; 93 94 log->Printf ("PlatformDarwinKernel::%s(force=%s, arch={%s,%s})", __FUNCTION__, force ? "true" : "false", arch_name, triple_cstr); 95 } 96 97 // This is a special plugin that we don't want to activate just based on an ArchSpec for normal 98 // userland debugging. It is only useful in kernel debug sessions and the DynamicLoaderDarwinPlugin 99 // (or a user doing 'platform select') will force the creation of this Platform plugin. 100 if (force == false) 101 { 102 if (log) 103 log->Printf ("PlatformDarwinKernel::%s() aborting creation of platform because force == false", __FUNCTION__); 104 return PlatformSP(); 105 } 106 107 bool create = force; 108 LazyBool is_ios_debug_session = eLazyBoolCalculate; 109 110 if (create == false && arch && arch->IsValid()) 111 { 112 const llvm::Triple &triple = arch->GetTriple(); 113 switch (triple.getVendor()) 114 { 115 case llvm::Triple::Apple: 116 create = true; 117 break; 118 119 // Only accept "unknown" for vendor if the host is Apple and 120 // it "unknown" wasn't specified (it was just returned because it 121 // was NOT specified) 122 case llvm::Triple::UnknownArch: 123 create = !arch->TripleVendorWasSpecified(); 124 break; 125 default: 126 break; 127 } 128 129 if (create) 130 { 131 switch (triple.getOS()) 132 { 133 case llvm::Triple::Darwin: 134 case llvm::Triple::MacOSX: 135 case llvm::Triple::IOS: 136 case llvm::Triple::WatchOS: 137 case llvm::Triple::TvOS: 138 break; 139 // Only accept "vendor" for vendor if the host is Apple and 140 // it "unknown" wasn't specified (it was just returned because it 141 // was NOT specified) 142 case llvm::Triple::UnknownOS: 143 create = !arch->TripleOSWasSpecified(); 144 break; 145 default: 146 create = false; 147 break; 148 } 149 } 150 } 151 if (arch && arch->IsValid()) 152 { 153 switch (arch->GetMachine()) 154 { 155 case llvm::Triple::x86: 156 case llvm::Triple::x86_64: 157 case llvm::Triple::ppc: 158 case llvm::Triple::ppc64: 159 is_ios_debug_session = eLazyBoolNo; 160 break; 161 case llvm::Triple::arm: 162 case llvm::Triple::aarch64: 163 case llvm::Triple::thumb: 164 is_ios_debug_session = eLazyBoolYes; 165 break; 166 default: 167 is_ios_debug_session = eLazyBoolCalculate; 168 break; 169 } 170 } 171 if (create) 172 { 173 if (log) 174 log->Printf ("PlatformDarwinKernel::%s() creating platform", __FUNCTION__); 175 176 return PlatformSP(new PlatformDarwinKernel (is_ios_debug_session)); 177 } 178 179 if (log) 180 log->Printf ("PlatformDarwinKernel::%s() aborting creation of platform", __FUNCTION__); 181 182 return PlatformSP(); 183 } 184 185 186 lldb_private::ConstString 187 PlatformDarwinKernel::GetPluginNameStatic () 188 { 189 static ConstString g_name("darwin-kernel"); 190 return g_name; 191 } 192 193 const char * 194 PlatformDarwinKernel::GetDescriptionStatic() 195 { 196 return "Darwin Kernel platform plug-in."; 197 } 198 199 //------------------------------------------------------------------ 200 /// Code to handle the PlatformDarwinKernel settings 201 //------------------------------------------------------------------ 202 203 static PropertyDefinition 204 g_properties[] = 205 { 206 { "search-locally-for-kexts" , OptionValue::eTypeBoolean, true, true, NULL, NULL, "Automatically search for kexts on the local system when doing kernel debugging." }, 207 { "kext-directories", OptionValue::eTypeFileSpecList, false, 0, NULL, NULL, "Directories/KDKs to search for kexts in when starting a kernel debug session." }, 208 { NULL , OptionValue::eTypeInvalid, false, 0 , NULL, NULL, NULL } 209 }; 210 211 enum { 212 ePropertySearchForKexts = 0, 213 ePropertyKextDirectories 214 }; 215 216 217 218 class PlatformDarwinKernelProperties : public Properties 219 { 220 public: 221 222 static ConstString & 223 GetSettingName () 224 { 225 static ConstString g_setting_name("darwin-kernel"); 226 return g_setting_name; 227 } 228 229 PlatformDarwinKernelProperties() : 230 Properties () 231 { 232 m_collection_sp.reset (new OptionValueProperties(GetSettingName())); 233 m_collection_sp->Initialize(g_properties); 234 } 235 236 virtual 237 ~PlatformDarwinKernelProperties() 238 { 239 } 240 241 bool 242 GetSearchForKexts() const 243 { 244 const uint32_t idx = ePropertySearchForKexts; 245 return m_collection_sp->GetPropertyAtIndexAsBoolean (NULL, idx, g_properties[idx].default_uint_value != 0); 246 } 247 248 FileSpecList & 249 GetKextDirectories() const 250 { 251 const uint32_t idx = ePropertyKextDirectories; 252 OptionValueFileSpecList *option_value = m_collection_sp->GetPropertyAtIndexAsOptionValueFileSpecList (NULL, false, idx); 253 assert(option_value); 254 return option_value->GetCurrentValue(); 255 } 256 }; 257 258 typedef std::shared_ptr<PlatformDarwinKernelProperties> PlatformDarwinKernelPropertiesSP; 259 260 static const PlatformDarwinKernelPropertiesSP & 261 GetGlobalProperties() 262 { 263 static PlatformDarwinKernelPropertiesSP g_settings_sp; 264 if (!g_settings_sp) 265 g_settings_sp.reset (new PlatformDarwinKernelProperties ()); 266 return g_settings_sp; 267 } 268 269 void 270 PlatformDarwinKernel::DebuggerInitialize (lldb_private::Debugger &debugger) 271 { 272 if (!PluginManager::GetSettingForPlatformPlugin (debugger, PlatformDarwinKernelProperties::GetSettingName())) 273 { 274 const bool is_global_setting = true; 275 PluginManager::CreateSettingForPlatformPlugin (debugger, 276 GetGlobalProperties()->GetValueProperties(), 277 ConstString ("Properties for the PlatformDarwinKernel plug-in."), 278 is_global_setting); 279 } 280 } 281 282 //------------------------------------------------------------------ 283 /// Default Constructor 284 //------------------------------------------------------------------ 285 PlatformDarwinKernel::PlatformDarwinKernel (lldb_private::LazyBool is_ios_debug_session) : 286 PlatformDarwin (false), // This is a remote platform 287 m_name_to_kext_path_map(), 288 m_search_directories(), 289 m_kernel_binaries(), 290 m_ios_debug_session(is_ios_debug_session) 291 292 { 293 if (GetGlobalProperties()->GetSearchForKexts()) 294 { 295 CollectKextAndKernelDirectories (); 296 IndexKextsInDirectories (); 297 IndexKernelsInDirectories (); 298 } 299 } 300 301 //------------------------------------------------------------------ 302 /// Destructor. 303 /// 304 /// The destructor is virtual since this class is designed to be 305 /// inherited from by the plug-in instance. 306 //------------------------------------------------------------------ 307 PlatformDarwinKernel::~PlatformDarwinKernel() 308 { 309 } 310 311 312 void 313 PlatformDarwinKernel::GetStatus (Stream &strm) 314 { 315 Platform::GetStatus (strm); 316 strm.Printf (" Debug session type: "); 317 if (m_ios_debug_session == eLazyBoolYes) 318 strm.Printf ("iOS kernel debugging\n"); 319 else if (m_ios_debug_session == eLazyBoolNo) 320 strm.Printf ("Mac OS X kernel debugging\n"); 321 else 322 strm.Printf ("unknown kernel debugging\n"); 323 const uint32_t num_kext_dirs = m_search_directories.size(); 324 for (uint32_t i=0; i<num_kext_dirs; ++i) 325 { 326 const FileSpec &kext_dir = m_search_directories[i]; 327 strm.Printf (" Kext directories: [%2u] \"%s\"\n", i, kext_dir.GetPath().c_str()); 328 } 329 strm.Printf (" Total number of kexts indexed: %d\n", (int) m_name_to_kext_path_map.size()); 330 } 331 332 // Populate the m_search_directories vector with directories we should search 333 // for kernel & kext binaries. 334 335 void 336 PlatformDarwinKernel::CollectKextAndKernelDirectories () 337 { 338 // Differentiate between "ios debug session" and "mac debug session" so we don't index 339 // kext bundles that won't be used in this debug session. If this is an ios kext debug 340 // session, looking in /System/Library/Extensions is a waste of stat()s, for example. 341 342 // Build up a list of all SDKs we'll be searching for directories of kexts/kernels 343 // e.g. /Applications/Xcode.app//Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.8.Internal.sdk 344 std::vector<FileSpec> sdk_dirs; 345 if (m_ios_debug_session != eLazyBoolNo) 346 { 347 GetiOSSDKDirectoriesToSearch (sdk_dirs); 348 GetAppleTVOSSDKDirectoriesToSearch (sdk_dirs); 349 GetWatchOSSDKDirectoriesToSearch (sdk_dirs); 350 } 351 if (m_ios_debug_session != eLazyBoolYes) 352 GetMacSDKDirectoriesToSearch (sdk_dirs); 353 354 GetGenericSDKDirectoriesToSearch (sdk_dirs); 355 356 // Build up a list of directories that hold may kext bundles & kernels 357 // 358 // e.g. given /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/ 359 // find 360 // /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.8.Internal.sdk/ 361 // and 362 // /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.8.Internal.sdk/System/Library/Extensions 363 364 std::vector<FileSpec> kext_dirs; 365 SearchSDKsForKextDirectories (sdk_dirs, kext_dirs); 366 367 if (m_ios_debug_session != eLazyBoolNo) 368 GetiOSDirectoriesToSearch (kext_dirs); 369 if (m_ios_debug_session != eLazyBoolYes) 370 GetMacDirectoriesToSearch (kext_dirs); 371 372 GetGenericDirectoriesToSearch (kext_dirs); 373 374 GetUserSpecifiedDirectoriesToSearch (kext_dirs); 375 376 GetKernelDirectoriesToSearch (kext_dirs); 377 378 GetCurrentDirectoryToSearch (kext_dirs); 379 380 // We now have a complete list of directories that we will search for kext bundles 381 m_search_directories = kext_dirs; 382 } 383 384 void 385 PlatformDarwinKernel::GetiOSSDKDirectoriesToSearch (std::vector<lldb_private::FileSpec> &directories) 386 { 387 // DeveloperDirectory is something like "/Applications/Xcode.app/Contents/Developer" 388 const char *developer_dir = GetDeveloperDirectory(); 389 if (developer_dir == NULL) 390 developer_dir = "/Applications/Xcode.app/Contents/Developer"; 391 392 char pathbuf[PATH_MAX]; 393 ::snprintf (pathbuf, sizeof (pathbuf), "%s/Platforms/iPhoneOS.platform/Developer/SDKs", developer_dir); 394 FileSpec ios_sdk(pathbuf, true); 395 if (ios_sdk.Exists() && ios_sdk.IsDirectory()) 396 { 397 directories.push_back (ios_sdk); 398 } 399 } 400 401 void 402 PlatformDarwinKernel::GetAppleTVOSSDKDirectoriesToSearch (std::vector<lldb_private::FileSpec> &directories) 403 { 404 // DeveloperDirectory is something like "/Applications/Xcode.app/Contents/Developer" 405 const char *developer_dir = GetDeveloperDirectory(); 406 if (developer_dir == NULL) 407 developer_dir = "/Applications/Xcode.app/Contents/Developer"; 408 409 char pathbuf[PATH_MAX]; 410 ::snprintf (pathbuf, sizeof (pathbuf), "%s/Platforms/AppleTVOS.platform/Developer/SDKs", developer_dir); 411 FileSpec ios_sdk(pathbuf, true); 412 if (ios_sdk.Exists() && ios_sdk.IsDirectory()) 413 { 414 directories.push_back (ios_sdk); 415 } 416 } 417 418 void 419 PlatformDarwinKernel::GetWatchOSSDKDirectoriesToSearch (std::vector<lldb_private::FileSpec> &directories) 420 { 421 // DeveloperDirectory is something like "/Applications/Xcode.app/Contents/Developer" 422 const char *developer_dir = GetDeveloperDirectory(); 423 if (developer_dir == NULL) 424 developer_dir = "/Applications/Xcode.app/Contents/Developer"; 425 426 char pathbuf[PATH_MAX]; 427 ::snprintf (pathbuf, sizeof (pathbuf), "%s/Platforms/watchOS.platform/Developer/SDKs", developer_dir); 428 FileSpec ios_sdk(pathbuf, true); 429 if (ios_sdk.Exists() && ios_sdk.IsDirectory()) 430 { 431 directories.push_back (ios_sdk); 432 } 433 else 434 { 435 ::snprintf (pathbuf, sizeof (pathbuf), "%s/Platforms/WatchOS.platform/Developer/SDKs", developer_dir); 436 FileSpec alt_watch_sdk(pathbuf, true); 437 if (ios_sdk.Exists() && ios_sdk.IsDirectory()) 438 { 439 directories.push_back (ios_sdk); 440 } 441 } 442 } 443 444 445 void 446 PlatformDarwinKernel::GetMacSDKDirectoriesToSearch (std::vector<lldb_private::FileSpec> &directories) 447 { 448 // DeveloperDirectory is something like "/Applications/Xcode.app/Contents/Developer" 449 const char *developer_dir = GetDeveloperDirectory(); 450 if (developer_dir == NULL) 451 developer_dir = "/Applications/Xcode.app/Contents/Developer"; 452 453 char pathbuf[PATH_MAX]; 454 ::snprintf (pathbuf, sizeof (pathbuf), "%s/Platforms/MacOSX.platform/Developer/SDKs", developer_dir); 455 FileSpec mac_sdk(pathbuf, true); 456 if (mac_sdk.Exists() && mac_sdk.IsDirectory()) 457 { 458 directories.push_back (mac_sdk); 459 } 460 } 461 462 void 463 PlatformDarwinKernel::GetGenericSDKDirectoriesToSearch (std::vector<lldb_private::FileSpec> &directories) 464 { 465 FileSpec generic_sdk("/AppleInternal/Developer/KDKs", true); 466 if (generic_sdk.Exists() && generic_sdk.IsDirectory()) 467 { 468 directories.push_back (generic_sdk); 469 } 470 471 // The KDKs distributed from Apple installed on external 472 // developer systems may be in directories like 473 // /Library/Developer/KDKs/KDK_10.10_14A298i.kdk 474 FileSpec installed_kdks("/Library/Developer/KDKs", true); 475 if (installed_kdks.Exists() && installed_kdks.IsDirectory()) 476 { 477 directories.push_back (installed_kdks); 478 } 479 } 480 481 void 482 PlatformDarwinKernel::GetiOSDirectoriesToSearch (std::vector<lldb_private::FileSpec> &directories) 483 { 484 } 485 486 void 487 PlatformDarwinKernel::GetMacDirectoriesToSearch (std::vector<lldb_private::FileSpec> &directories) 488 { 489 FileSpec sle("/System/Library/Extensions", true); 490 if (sle.Exists() && sle.IsDirectory()) 491 { 492 directories.push_back(sle); 493 } 494 495 FileSpec le("/Library/Extensions", true); 496 if (le.Exists() && le.IsDirectory()) 497 { 498 directories.push_back(le); 499 } 500 501 FileSpec kdk("/Volumes/KernelDebugKit", true); 502 if (kdk.Exists() && kdk.IsDirectory()) 503 { 504 directories.push_back(kdk); 505 } 506 } 507 508 void 509 PlatformDarwinKernel::GetGenericDirectoriesToSearch (std::vector<lldb_private::FileSpec> &directories) 510 { 511 // DeveloperDirectory is something like "/Applications/Xcode.app/Contents/Developer" 512 const char *developer_dir = GetDeveloperDirectory(); 513 if (developer_dir == NULL) 514 developer_dir = "/Applications/Xcode.app/Contents/Developer"; 515 516 char pathbuf[PATH_MAX]; 517 ::snprintf (pathbuf, sizeof (pathbuf), "%s/../Symbols", developer_dir); 518 FileSpec symbols_dir (pathbuf, true); 519 if (symbols_dir.Exists() && symbols_dir.IsDirectory()) 520 { 521 directories.push_back (symbols_dir); 522 } 523 } 524 525 void 526 PlatformDarwinKernel::GetKernelDirectoriesToSearch (std::vector<lldb_private::FileSpec> &directories) 527 { 528 FileSpec system_library_kernels ("/System/Library/Kernels", true); 529 if (system_library_kernels.Exists() && system_library_kernels.IsDirectory()) 530 { 531 directories.push_back (system_library_kernels); 532 } 533 FileSpec slek("/System/Library/Extensions/KDK", true); 534 if (slek.Exists() && slek.IsDirectory()) 535 { 536 directories.push_back(slek); 537 } 538 } 539 540 void 541 PlatformDarwinKernel::GetCurrentDirectoryToSearch (std::vector<lldb_private::FileSpec> &directories) 542 { 543 directories.push_back (FileSpec (".", true)); 544 545 FileSpec sle_directory ("System/Library/Extensions", true); 546 if (sle_directory.Exists() && sle_directory.IsDirectory()) 547 { 548 directories.push_back (sle_directory); 549 } 550 551 FileSpec le_directory ("Library/Extensions", true); 552 if (le_directory.Exists() && le_directory.IsDirectory()) 553 { 554 directories.push_back (le_directory); 555 } 556 557 FileSpec slk_directory ("System/Library/Kernels", true); 558 if (slk_directory.Exists() && slk_directory.IsDirectory()) 559 { 560 directories.push_back (slk_directory); 561 } 562 FileSpec slek("System/Library/Extensions/KDK", true); 563 if (slek.Exists() && slek.IsDirectory()) 564 { 565 directories.push_back(slek); 566 } 567 } 568 569 void 570 PlatformDarwinKernel::GetUserSpecifiedDirectoriesToSearch (std::vector<lldb_private::FileSpec> &directories) 571 { 572 FileSpecList user_dirs(GetGlobalProperties()->GetKextDirectories()); 573 std::vector<FileSpec> possible_sdk_dirs; 574 575 const uint32_t user_dirs_count = user_dirs.GetSize(); 576 for (uint32_t i = 0; i < user_dirs_count; i++) 577 { 578 FileSpec dir = user_dirs.GetFileSpecAtIndex (i); 579 dir.ResolvePath(); 580 if (dir.Exists() && dir.IsDirectory()) 581 { 582 directories.push_back (dir); 583 possible_sdk_dirs.push_back (dir); // does this directory have a *.sdk or *.kdk that we should look in? 584 585 // Is there a "System/Library/Extensions" subdir of this directory? 586 std::string dir_sle_path = dir.GetPath(); 587 dir_sle_path.append ("/System/Library/Extensions"); 588 FileSpec dir_sle(dir_sle_path.c_str(), true); 589 if (dir_sle.Exists() && dir_sle.IsDirectory()) 590 { 591 directories.push_back (dir_sle); 592 } 593 594 // Is there a "System/Library/Kernels" subdir of this directory? 595 std::string dir_slk_path = dir.GetPath(); 596 dir_slk_path.append ("/System/Library/Kernels"); 597 FileSpec dir_slk(dir_slk_path.c_str(), true); 598 if (dir_slk.Exists() && dir_slk.IsDirectory()) 599 { 600 directories.push_back (dir_slk); 601 } 602 603 // Is there a "System/Library/Extensions/KDK" subdir of this directory? 604 std::string dir_slek_path = dir.GetPath(); 605 dir_slek_path.append ("/System/Library/Kernels"); 606 FileSpec dir_slek(dir_slek_path.c_str(), true); 607 if (dir_slek.Exists() && dir_slek.IsDirectory()) 608 { 609 directories.push_back (dir_slek); 610 } 611 } 612 } 613 614 SearchSDKsForKextDirectories (possible_sdk_dirs, directories); 615 } 616 617 // Scan through the SDK directories, looking for directories where kexts are likely. 618 // Add those directories to kext_dirs. 619 void 620 PlatformDarwinKernel::SearchSDKsForKextDirectories (std::vector<lldb_private::FileSpec> sdk_dirs, std::vector<lldb_private::FileSpec> &kext_dirs) 621 { 622 const uint32_t num_sdks = sdk_dirs.size(); 623 for (uint32_t i = 0; i < num_sdks; i++) 624 { 625 const FileSpec &sdk_dir = sdk_dirs[i]; 626 std::string sdk_dir_path = sdk_dir.GetPath(); 627 if (!sdk_dir_path.empty()) 628 { 629 const bool find_directories = true; 630 const bool find_files = false; 631 const bool find_other = false; 632 FileSpec::EnumerateDirectory (sdk_dir_path.c_str(), 633 find_directories, 634 find_files, 635 find_other, 636 GetKextDirectoriesInSDK, 637 &kext_dirs); 638 } 639 } 640 } 641 642 // Callback for FileSpec::EnumerateDirectory(). 643 // Step through the entries in a directory like 644 // /Applications/Xcode.app//Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs 645 // looking for any subdirectories of the form MacOSX10.8.Internal.sdk/System/Library/Extensions 646 // Adds these to the vector of FileSpec's. 647 648 FileSpec::EnumerateDirectoryResult 649 PlatformDarwinKernel::GetKextDirectoriesInSDK (void *baton, 650 FileSpec::FileType file_type, 651 const FileSpec &file_spec) 652 { 653 if (file_type == FileSpec::eFileTypeDirectory 654 && (file_spec.GetFileNameExtension() == ConstString("sdk") 655 || file_spec.GetFileNameExtension() == ConstString("kdk"))) 656 { 657 std::string kext_directory_path = file_spec.GetPath(); 658 659 // Append the raw directory path, e.g. /Library/Developer/KDKs/KDK_10.10_14A298i.kdk 660 // to the directory search list -- there may be kexts sitting directly 661 // in that directory instead of being in a System/Library/Extensions subdir. 662 ((std::vector<lldb_private::FileSpec> *)baton)->push_back(file_spec); 663 664 // Check to see if there is a System/Library/Extensions subdir & add it if it exists 665 666 std::string sle_kext_directory_path (kext_directory_path); 667 sle_kext_directory_path.append ("/System/Library/Extensions"); 668 FileSpec sle_kext_directory (sle_kext_directory_path.c_str(), true); 669 if (sle_kext_directory.Exists() && sle_kext_directory.IsDirectory()) 670 { 671 ((std::vector<lldb_private::FileSpec> *)baton)->push_back(sle_kext_directory); 672 } 673 674 // Check to see if there is a Library/Extensions subdir & add it if it exists 675 676 std::string le_kext_directory_path (kext_directory_path); 677 le_kext_directory_path.append ("/Library/Extensions"); 678 FileSpec le_kext_directory (le_kext_directory_path.c_str(), true); 679 if (le_kext_directory.Exists() && le_kext_directory.IsDirectory()) 680 { 681 ((std::vector<lldb_private::FileSpec> *)baton)->push_back(le_kext_directory); 682 } 683 684 // Check to see if there is a System/Library/Kernels subdir & add it if it exists 685 std::string slk_kernel_path (kext_directory_path); 686 slk_kernel_path.append ("/System/Library/Kernels"); 687 FileSpec slk_kernel_directory (slk_kernel_path.c_str(), true); 688 if (slk_kernel_directory.Exists() && slk_kernel_directory.IsDirectory()) 689 { 690 ((std::vector<lldb_private::FileSpec> *)baton)->push_back(slk_kernel_directory); 691 } 692 693 // Check to see if there is a System/Library/Extensions/KDK subdir & add it if it exists 694 std::string slek_kernel_path (kext_directory_path); 695 slek_kernel_path.append ("/System/Library/Extensions/KDK"); 696 FileSpec slek_kernel_directory (slek_kernel_path.c_str(), true); 697 if (slek_kernel_directory.Exists() && slek_kernel_directory.IsDirectory()) 698 { 699 ((std::vector<lldb_private::FileSpec> *)baton)->push_back(slek_kernel_directory); 700 } 701 } 702 return FileSpec::eEnumerateDirectoryResultNext; 703 } 704 705 void 706 PlatformDarwinKernel::IndexKextsInDirectories () 707 { 708 std::vector<FileSpec> kext_bundles; 709 710 const uint32_t num_dirs = m_search_directories.size(); 711 for (uint32_t i = 0; i < num_dirs; i++) 712 { 713 const FileSpec &dir = m_search_directories[i]; 714 const bool find_directories = true; 715 const bool find_files = false; 716 const bool find_other = false; 717 FileSpec::EnumerateDirectory (dir.GetPath().c_str(), 718 find_directories, 719 find_files, 720 find_other, 721 GetKextsInDirectory, 722 &kext_bundles); 723 } 724 725 const uint32_t num_kexts = kext_bundles.size(); 726 for (uint32_t i = 0; i < num_kexts; i++) 727 { 728 const FileSpec &kext = kext_bundles[i]; 729 CFCBundle bundle (kext.GetPath().c_str()); 730 CFStringRef bundle_id (bundle.GetIdentifier()); 731 if (bundle_id && CFGetTypeID (bundle_id) == CFStringGetTypeID ()) 732 { 733 char bundle_id_buf[PATH_MAX]; 734 if (CFStringGetCString (bundle_id, bundle_id_buf, sizeof (bundle_id_buf), kCFStringEncodingUTF8)) 735 { 736 ConstString bundle_conststr(bundle_id_buf); 737 m_name_to_kext_path_map.insert(std::pair<ConstString, FileSpec>(bundle_conststr, kext)); 738 } 739 } 740 } 741 } 742 743 // Callback for FileSpec::EnumerateDirectory(). 744 // Step through the entries in a directory like /System/Library/Extensions, find .kext bundles, add them 745 // to the vector of FileSpecs. 746 // If a .kext bundle has a Contents/PlugIns or PlugIns subdir, search for kexts in there too. 747 748 FileSpec::EnumerateDirectoryResult 749 PlatformDarwinKernel::GetKextsInDirectory (void *baton, 750 FileSpec::FileType file_type, 751 const FileSpec &file_spec) 752 { 753 if (file_type == FileSpec::eFileTypeDirectory && file_spec.GetFileNameExtension() == ConstString("kext")) 754 { 755 ((std::vector<lldb_private::FileSpec> *)baton)->push_back(file_spec); 756 std::string kext_bundle_path = file_spec.GetPath(); 757 std::string search_here_too; 758 std::string contents_plugins_path = kext_bundle_path + "/Contents/PlugIns"; 759 FileSpec contents_plugins (contents_plugins_path.c_str(), false); 760 if (contents_plugins.Exists() && contents_plugins.IsDirectory()) 761 { 762 search_here_too = contents_plugins_path; 763 } 764 else 765 { 766 std::string plugins_path = kext_bundle_path + "/PlugIns"; 767 FileSpec plugins (plugins_path.c_str(), false); 768 if (plugins.Exists() && plugins.IsDirectory()) 769 { 770 search_here_too = plugins_path; 771 } 772 } 773 774 if (!search_here_too.empty()) 775 { 776 const bool find_directories = true; 777 const bool find_files = false; 778 const bool find_other = false; 779 FileSpec::EnumerateDirectory (search_here_too.c_str(), 780 find_directories, 781 find_files, 782 find_other, 783 GetKextsInDirectory, 784 baton); 785 } 786 } 787 return FileSpec::eEnumerateDirectoryResultNext; 788 } 789 790 void 791 PlatformDarwinKernel::IndexKernelsInDirectories () 792 { 793 std::vector<FileSpec> kernels; 794 795 796 const uint32_t num_dirs = m_search_directories.size(); 797 for (uint32_t i = 0; i < num_dirs; i++) 798 { 799 const FileSpec &dir = m_search_directories[i]; 800 const bool find_directories = false; 801 const bool find_files = true; 802 const bool find_other = true; // I think eFileTypeSymbolicLink are "other"s. 803 FileSpec::EnumerateDirectory (dir.GetPath().c_str(), 804 find_directories, 805 find_files, 806 find_other, 807 GetKernelsInDirectory, 808 &m_kernel_binaries); 809 } 810 } 811 812 // Callback for FileSpec::EnumerateDirectory(). 813 // Step through the entries in a directory like /System/Library/Kernels/, find kernel binaries, 814 // add them to m_kernel_binaries. 815 816 // We're only doing a filename match here. We won't try opening the file to see if it's really 817 // a kernel or not until we need to find a kernel of a given UUID. There's no cheap way to find 818 // the UUID of a file (or if it's a Mach-O binary at all) without creating a whole Module for 819 // the file and throwing it away if it's not wanted. 820 821 FileSpec::EnumerateDirectoryResult 822 PlatformDarwinKernel::GetKernelsInDirectory (void *baton, 823 FileSpec::FileType file_type, 824 const FileSpec &file_spec) 825 { 826 if (file_type == FileSpec::eFileTypeRegular || file_type == FileSpec::eFileTypeSymbolicLink) 827 { 828 ConstString filename = file_spec.GetFilename(); 829 if (strncmp (filename.GetCString(), "kernel", 6) == 0 830 || strncmp (filename.GetCString(), "mach", 4) == 0) 831 { 832 // This is m_kernel_binaries but we're in a class method here 833 ((std::vector<lldb_private::FileSpec> *)baton)->push_back(file_spec); 834 } 835 } 836 return FileSpec::eEnumerateDirectoryResultNext; 837 } 838 839 840 Error 841 PlatformDarwinKernel::GetSharedModule (const ModuleSpec &module_spec, 842 Process *process, 843 ModuleSP &module_sp, 844 const FileSpecList *module_search_paths_ptr, 845 ModuleSP *old_module_sp_ptr, 846 bool *did_create_ptr) 847 { 848 Error error; 849 module_sp.reset(); 850 const FileSpec &platform_file = module_spec.GetFileSpec(); 851 852 // Treat the file's path as a kext bundle ID (e.g. "com.apple.driver.AppleIRController") and search our kext index. 853 std::string kext_bundle_id = platform_file.GetPath(); 854 if (!kext_bundle_id.empty()) 855 { 856 ConstString kext_bundle_cs(kext_bundle_id.c_str()); 857 if (m_name_to_kext_path_map.count(kext_bundle_cs) > 0) 858 { 859 for (BundleIDToKextIterator it = m_name_to_kext_path_map.begin (); it != m_name_to_kext_path_map.end (); ++it) 860 { 861 if (it->first == kext_bundle_cs) 862 { 863 error = ExamineKextForMatchingUUID (it->second, module_spec.GetUUID(), module_spec.GetArchitecture(), module_sp); 864 if (module_sp.get()) 865 { 866 return error; 867 } 868 } 869 } 870 } 871 } 872 873 if (kext_bundle_id.compare("mach_kernel") == 0 && module_spec.GetUUID().IsValid()) 874 { 875 for (auto possible_kernel : m_kernel_binaries) 876 { 877 if (possible_kernel.Exists()) 878 { 879 ModuleSpec kern_spec (possible_kernel); 880 kern_spec.GetUUID() = module_spec.GetUUID(); 881 ModuleSP module_sp (new Module (kern_spec)); 882 if (module_sp && module_sp->GetObjectFile() && module_sp->MatchesModuleSpec (kern_spec)) 883 { 884 Error error; 885 error = ModuleList::GetSharedModule (kern_spec, module_sp, NULL, NULL, NULL); 886 if (module_sp && module_sp->GetObjectFile()) 887 { 888 return error; 889 } 890 } 891 } 892 } 893 } 894 895 // Else fall back to treating the file's path as an actual file path - defer to PlatformDarwin's GetSharedModule. 896 return PlatformDarwin::GetSharedModule (module_spec, process, module_sp, module_search_paths_ptr, old_module_sp_ptr, did_create_ptr); 897 } 898 899 Error 900 PlatformDarwinKernel::ExamineKextForMatchingUUID (const FileSpec &kext_bundle_path, const lldb_private::UUID &uuid, const ArchSpec &arch, ModuleSP &exe_module_sp) 901 { 902 Error error; 903 FileSpec exe_file = kext_bundle_path; 904 Host::ResolveExecutableInBundle (exe_file); 905 if (exe_file.Exists()) 906 { 907 ModuleSpec exe_spec (exe_file); 908 exe_spec.GetUUID() = uuid; 909 if (!uuid.IsValid()) 910 { 911 exe_spec.GetArchitecture() = arch; 912 } 913 914 // First try to create a ModuleSP with the file / arch and see if the UUID matches. 915 // If that fails (this exec file doesn't have the correct uuid), don't call GetSharedModule 916 // (which may call in to the DebugSymbols framework and therefore can be slow.) 917 ModuleSP module_sp (new Module (exe_spec)); 918 if (module_sp && module_sp->GetObjectFile() && module_sp->MatchesModuleSpec (exe_spec)) 919 { 920 error = ModuleList::GetSharedModule (exe_spec, exe_module_sp, NULL, NULL, NULL); 921 if (exe_module_sp && exe_module_sp->GetObjectFile()) 922 { 923 return error; 924 } 925 } 926 exe_module_sp.reset(); 927 } 928 return error; 929 } 930 931 bool 932 PlatformDarwinKernel::GetSupportedArchitectureAtIndex (uint32_t idx, ArchSpec &arch) 933 { 934 #if defined (__arm__) || defined (__arm64__) || defined (__aarch64__) 935 return ARMGetSupportedArchitectureAtIndex (idx, arch); 936 #else 937 return x86GetSupportedArchitectureAtIndex (idx, arch); 938 #endif 939 } 940 941 void 942 PlatformDarwinKernel::CalculateTrapHandlerSymbolNames () 943 { 944 m_trap_handlers.push_back(ConstString ("trap_from_kernel")); 945 m_trap_handlers.push_back(ConstString ("hndl_machine_check")); 946 m_trap_handlers.push_back(ConstString ("hndl_double_fault")); 947 m_trap_handlers.push_back(ConstString ("hndl_allintrs")); 948 m_trap_handlers.push_back(ConstString ("hndl_alltraps")); 949 m_trap_handlers.push_back(ConstString ("interrupt")); 950 m_trap_handlers.push_back(ConstString ("fleh_prefabt")); 951 m_trap_handlers.push_back(ConstString ("ExceptionVectorsBase")); 952 m_trap_handlers.push_back(ConstString ("ExceptionVectorsTable")); 953 m_trap_handlers.push_back(ConstString ("fleh_undef")); 954 m_trap_handlers.push_back(ConstString ("fleh_dataabt")); 955 m_trap_handlers.push_back(ConstString ("fleh_irq")); 956 m_trap_handlers.push_back(ConstString ("fleh_decirq")); 957 m_trap_handlers.push_back(ConstString ("fleh_fiq_generic")); 958 m_trap_handlers.push_back(ConstString ("fleh_dec")); 959 960 } 961 962 #else // __APPLE__ 963 964 // Since DynamicLoaderDarwinKernel is compiled in for all systems, and relies on 965 // PlatformDarwinKernel for the plug-in name, we compile just the plug-in name in 966 // here to avoid issues. We are tracking an internal bug to resolve this issue by 967 // either not compiling in DynamicLoaderDarwinKernel for non-apple builds, or to make 968 // PlatformDarwinKernel build on all systems. PlatformDarwinKernel is currently not 969 // compiled on other platforms due to the use of the Mac-specific 970 // source/Host/macosx/cfcpp utilities. 971 972 lldb_private::ConstString 973 PlatformDarwinKernel::GetPluginNameStatic () 974 { 975 static lldb_private::ConstString g_name("darwin-kernel"); 976 return g_name; 977 } 978 979 #endif // __APPLE__ 980