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