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