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