1 //===-- PlatformDarwinKernel.cpp -----------------------------------*- C++ 2 //-*-===// 3 // 4 // The LLVM Compiler Infrastructure 5 // 6 // This file is distributed under the University of Illinois Open Source 7 // License. See LICENSE.TXT for details. 8 // 9 //===----------------------------------------------------------------------===// 10 11 #include "PlatformDarwinKernel.h" 12 13 #if defined(__APPLE__) // This Plugin uses the Mac-specific 14 // source/Host/macosx/cfcpp utilities 15 16 // C Includes 17 // C++ Includes 18 // Other libraries and framework includes 19 // Project includes 20 #include "lldb/Breakpoint/BreakpointLocation.h" 21 #include "lldb/Core/ArchSpec.h" 22 #include "lldb/Core/Error.h" 23 #include "lldb/Core/Log.h" 24 #include "lldb/Core/Module.h" 25 #include "lldb/Core/ModuleList.h" 26 #include "lldb/Core/ModuleSpec.h" 27 #include "lldb/Core/PluginManager.h" 28 #include "lldb/Core/StreamString.h" 29 #include "lldb/Host/FileSpec.h" 30 #include "lldb/Host/Host.h" 31 #include "lldb/Interpreter/OptionValueFileSpecList.h" 32 #include "lldb/Interpreter/OptionValueProperties.h" 33 #include "lldb/Interpreter/Property.h" 34 #include "lldb/Symbol/ObjectFile.h" 35 #include "lldb/Target/Platform.h" 36 #include "lldb/Target/Process.h" 37 #include "lldb/Target/Target.h" 38 39 #include <CoreFoundation/CoreFoundation.h> 40 41 #include "Host/macosx/cfcpp/CFCBundle.h" 42 43 using namespace lldb; 44 using namespace lldb_private; 45 46 //------------------------------------------------------------------ 47 // Static Variables 48 //------------------------------------------------------------------ 49 static uint32_t g_initialize_count = 0; 50 51 //------------------------------------------------------------------ 52 // Static Functions 53 //------------------------------------------------------------------ 54 void PlatformDarwinKernel::Initialize() { 55 PlatformDarwin::Initialize(); 56 57 if (g_initialize_count++ == 0) { 58 PluginManager::RegisterPlugin(PlatformDarwinKernel::GetPluginNameStatic(), 59 PlatformDarwinKernel::GetDescriptionStatic(), 60 PlatformDarwinKernel::CreateInstance, 61 PlatformDarwinKernel::DebuggerInitialize); 62 } 63 } 64 65 void PlatformDarwinKernel::Terminate() { 66 if (g_initialize_count > 0) { 67 if (--g_initialize_count == 0) { 68 PluginManager::UnregisterPlugin(PlatformDarwinKernel::CreateInstance); 69 } 70 } 71 72 PlatformDarwin::Terminate(); 73 } 74 75 PlatformSP PlatformDarwinKernel::CreateInstance(bool force, 76 const ArchSpec *arch) { 77 Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PLATFORM)); 78 if (log) { 79 const char *arch_name; 80 if (arch && arch->GetArchitectureName()) 81 arch_name = arch->GetArchitectureName(); 82 else 83 arch_name = "<null>"; 84 85 const char *triple_cstr = 86 arch ? arch->GetTriple().getTriple().c_str() : "<null>"; 87 88 log->Printf("PlatformDarwinKernel::%s(force=%s, arch={%s,%s})", 89 __FUNCTION__, force ? "true" : "false", arch_name, triple_cstr); 90 } 91 92 // This is a special plugin that we don't want to activate just based on an 93 // ArchSpec for normal 94 // userland debugging. It is only useful in kernel debug sessions and the 95 // DynamicLoaderDarwinPlugin 96 // (or a user doing 'platform select') will force the creation of this 97 // Platform plugin. 98 if (force == false) { 99 if (log) 100 log->Printf("PlatformDarwinKernel::%s() aborting creation of platform " 101 "because force == false", 102 __FUNCTION__); 103 return PlatformSP(); 104 } 105 106 bool create = force; 107 LazyBool is_ios_debug_session = eLazyBoolCalculate; 108 109 if (create == false && arch && arch->IsValid()) { 110 const llvm::Triple &triple = arch->GetTriple(); 111 switch (triple.getVendor()) { 112 case llvm::Triple::Apple: 113 create = true; 114 break; 115 116 // Only accept "unknown" for vendor if the host is Apple and 117 // it "unknown" wasn't specified (it was just returned because it 118 // was NOT specified) 119 case llvm::Triple::UnknownArch: 120 create = !arch->TripleVendorWasSpecified(); 121 break; 122 default: 123 break; 124 } 125 126 if (create) { 127 switch (triple.getOS()) { 128 case llvm::Triple::Darwin: 129 case llvm::Triple::MacOSX: 130 case llvm::Triple::IOS: 131 case llvm::Triple::WatchOS: 132 case llvm::Triple::TvOS: 133 break; 134 // Only accept "vendor" for vendor if the host is Apple and 135 // it "unknown" wasn't specified (it was just returned because it 136 // was NOT specified) 137 case llvm::Triple::UnknownOS: 138 create = !arch->TripleOSWasSpecified(); 139 break; 140 default: 141 create = false; 142 break; 143 } 144 } 145 } 146 if (arch && arch->IsValid()) { 147 switch (arch->GetMachine()) { 148 case llvm::Triple::x86: 149 case llvm::Triple::x86_64: 150 case llvm::Triple::ppc: 151 case llvm::Triple::ppc64: 152 is_ios_debug_session = eLazyBoolNo; 153 break; 154 case llvm::Triple::arm: 155 case llvm::Triple::aarch64: 156 case llvm::Triple::thumb: 157 is_ios_debug_session = eLazyBoolYes; 158 break; 159 default: 160 is_ios_debug_session = eLazyBoolCalculate; 161 break; 162 } 163 } 164 if (create) { 165 if (log) 166 log->Printf("PlatformDarwinKernel::%s() creating platform", __FUNCTION__); 167 168 return PlatformSP(new PlatformDarwinKernel(is_ios_debug_session)); 169 } 170 171 if (log) 172 log->Printf("PlatformDarwinKernel::%s() aborting creation of platform", 173 __FUNCTION__); 174 175 return PlatformSP(); 176 } 177 178 lldb_private::ConstString PlatformDarwinKernel::GetPluginNameStatic() { 179 static ConstString g_name("darwin-kernel"); 180 return g_name; 181 } 182 183 const char *PlatformDarwinKernel::GetDescriptionStatic() { 184 return "Darwin Kernel platform plug-in."; 185 } 186 187 //------------------------------------------------------------------ 188 /// Code to handle the PlatformDarwinKernel settings 189 //------------------------------------------------------------------ 190 191 static PropertyDefinition g_properties[] = { 192 {"search-locally-for-kexts", OptionValue::eTypeBoolean, true, true, NULL, 193 NULL, "Automatically search for kexts on the local system when doing " 194 "kernel debugging."}, 195 {"kext-directories", OptionValue::eTypeFileSpecList, false, 0, NULL, NULL, 196 "Directories/KDKs to search for kexts in when starting a kernel debug " 197 "session."}, 198 {NULL, OptionValue::eTypeInvalid, false, 0, NULL, NULL, NULL}}; 199 200 enum { ePropertySearchForKexts = 0, ePropertyKextDirectories }; 201 202 class PlatformDarwinKernelProperties : public Properties { 203 public: 204 static ConstString &GetSettingName() { 205 static ConstString g_setting_name("darwin-kernel"); 206 return g_setting_name; 207 } 208 209 PlatformDarwinKernelProperties() : Properties() { 210 m_collection_sp.reset(new OptionValueProperties(GetSettingName())); 211 m_collection_sp->Initialize(g_properties); 212 } 213 214 virtual ~PlatformDarwinKernelProperties() {} 215 216 bool GetSearchForKexts() const { 217 const uint32_t idx = ePropertySearchForKexts; 218 return m_collection_sp->GetPropertyAtIndexAsBoolean( 219 NULL, idx, g_properties[idx].default_uint_value != 0); 220 } 221 222 FileSpecList &GetKextDirectories() const { 223 const uint32_t idx = ePropertyKextDirectories; 224 OptionValueFileSpecList *option_value = 225 m_collection_sp->GetPropertyAtIndexAsOptionValueFileSpecList( 226 NULL, false, idx); 227 assert(option_value); 228 return option_value->GetCurrentValue(); 229 } 230 }; 231 232 typedef std::shared_ptr<PlatformDarwinKernelProperties> 233 PlatformDarwinKernelPropertiesSP; 234 235 static const PlatformDarwinKernelPropertiesSP &GetGlobalProperties() { 236 static PlatformDarwinKernelPropertiesSP g_settings_sp; 237 if (!g_settings_sp) 238 g_settings_sp.reset(new PlatformDarwinKernelProperties()); 239 return g_settings_sp; 240 } 241 242 void PlatformDarwinKernel::DebuggerInitialize( 243 lldb_private::Debugger &debugger) { 244 if (!PluginManager::GetSettingForPlatformPlugin( 245 debugger, PlatformDarwinKernelProperties::GetSettingName())) { 246 const bool is_global_setting = true; 247 PluginManager::CreateSettingForPlatformPlugin( 248 debugger, 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( 258 lldb_private::LazyBool is_ios_debug_session) 259 : PlatformDarwin(false), // This is a remote platform 260 m_name_to_kext_path_map_with_dsyms(), 261 m_name_to_kext_path_map_without_dsyms(), m_search_directories(), 262 m_search_directories_no_recursing(), m_kernel_binaries_with_dsyms(), 263 m_kernel_binaries_without_dsyms(), 264 m_ios_debug_session(is_ios_debug_session) 265 266 { 267 if (GetGlobalProperties()->GetSearchForKexts()) { 268 CollectKextAndKernelDirectories(); 269 SearchForKextsAndKernelsRecursively(); 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 void PlatformDarwinKernel::GetStatus(Stream &strm) { 282 Platform::GetStatus(strm); 283 strm.Printf(" Debug session type: "); 284 if (m_ios_debug_session == eLazyBoolYes) 285 strm.Printf("iOS kernel debugging\n"); 286 else if (m_ios_debug_session == eLazyBoolNo) 287 strm.Printf("Mac OS X kernel debugging\n"); 288 else 289 strm.Printf("unknown kernel debugging\n"); 290 291 strm.Printf("Directories searched recursively:\n"); 292 const uint32_t num_kext_dirs = m_search_directories.size(); 293 for (uint32_t i = 0; i < num_kext_dirs; ++i) { 294 strm.Printf("[%d] %s\n", i, m_search_directories[i].GetPath().c_str()); 295 } 296 297 strm.Printf("Directories not searched recursively:\n"); 298 const uint32_t num_kext_dirs_no_recursion = 299 m_search_directories_no_recursing.size(); 300 for (uint32_t i = 0; i < num_kext_dirs_no_recursion; i++) { 301 strm.Printf("[%d] %s\n", i, 302 m_search_directories_no_recursing[i].GetPath().c_str()); 303 } 304 305 strm.Printf(" Number of kexts with dSYMs indexed: %d\n", 306 (int)m_name_to_kext_path_map_with_dsyms.size()); 307 strm.Printf(" Number of kexts without dSYMs indexed: %d\n", 308 (int)m_name_to_kext_path_map_without_dsyms.size()); 309 strm.Printf(" Number of Kernel binaries with dSYMs indexed: %d\n", 310 (int)m_kernel_binaries_with_dsyms.size()); 311 strm.Printf(" Number of Kernel binaries without dSYMs indexed: %d\n", 312 (int)m_kernel_binaries_without_dsyms.size()); 313 314 Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PLATFORM)); 315 if (log) { 316 log->Printf("\nkexts with dSYMs"); 317 for (auto pos : m_name_to_kext_path_map_with_dsyms) { 318 log->Printf("%s", pos.second.GetPath().c_str()); 319 } 320 log->Printf("\nkexts without dSYMs"); 321 322 for (auto pos : m_name_to_kext_path_map_without_dsyms) { 323 log->Printf("%s", pos.second.GetPath().c_str()); 324 } 325 log->Printf("\nkernels with dSYMS"); 326 for (auto fs : m_kernel_binaries_with_dsyms) { 327 log->Printf("%s", fs.GetPath().c_str()); 328 } 329 log->Printf("\nkernels without dSYMS"); 330 for (auto fs : m_kernel_binaries_without_dsyms) { 331 log->Printf("%s", fs.GetPath().c_str()); 332 } 333 log->Printf("\n"); 334 } 335 } 336 337 // Populate the m_search_directories vector with directories we should search 338 // for kernel & kext binaries. 339 340 void PlatformDarwinKernel::CollectKextAndKernelDirectories() { 341 // Differentiate between "ios debug session" and "mac debug session" so we 342 // don't index 343 // kext bundles that won't be used in this debug session. If this is an ios 344 // kext debug 345 // session, looking in /System/Library/Extensions is a waste of stat()s, for 346 // example. 347 348 // DeveloperDirectory is something like 349 // "/Applications/Xcode.app/Contents/Developer" 350 std::string developer_dir = GetDeveloperDirectory(); 351 if (developer_dir.empty()) 352 developer_dir = "/Applications/Xcode.app/Contents/Developer"; 353 354 if (m_ios_debug_session != eLazyBoolNo) { 355 AddSDKSubdirsToSearchPaths(developer_dir + 356 "/Platforms/iPhoneOS.platform/Developer/SDKs"); 357 AddSDKSubdirsToSearchPaths(developer_dir + 358 "/Platforms/AppleTVOS.platform/Developer/SDKs"); 359 AddSDKSubdirsToSearchPaths(developer_dir + 360 "/Platforms/WatchOS.platform/Developer/SDKs"); 361 } 362 if (m_ios_debug_session != eLazyBoolYes) { 363 AddSDKSubdirsToSearchPaths(developer_dir + 364 "/Platforms/MacOSX.platform/Developer/SDKs"); 365 } 366 367 AddSDKSubdirsToSearchPaths("/Volumes/KernelDebugKit"); 368 AddSDKSubdirsToSearchPaths("/AppleInternal/Developer/KDKs"); 369 // The KDKs distributed from Apple installed on external 370 // developer systems may be in directories like 371 // /Library/Developer/KDKs/KDK_10.10_14A298i.kdk 372 AddSDKSubdirsToSearchPaths("/Library/Developer/KDKs"); 373 374 if (m_ios_debug_session != eLazyBoolNo) { 375 } 376 if (m_ios_debug_session != eLazyBoolYes) { 377 AddRootSubdirsToSearchPaths(this, "/"); 378 } 379 380 GetUserSpecifiedDirectoriesToSearch(); 381 382 // Add simple directory /Applications/Xcode.app/Contents/Developer/../Symbols 383 FileSpec possible_dir(developer_dir + "/../Symbols", true); 384 if (possible_dir.Exists() && possible_dir.IsDirectory()) 385 m_search_directories.push_back(possible_dir); 386 387 // Add simple directory of the current working directory 388 m_search_directories_no_recursing.push_back(FileSpec(".", true)); 389 } 390 391 void PlatformDarwinKernel::GetUserSpecifiedDirectoriesToSearch() { 392 FileSpecList user_dirs(GetGlobalProperties()->GetKextDirectories()); 393 std::vector<FileSpec> possible_sdk_dirs; 394 395 const uint32_t user_dirs_count = user_dirs.GetSize(); 396 for (uint32_t i = 0; i < user_dirs_count; i++) { 397 FileSpec dir = user_dirs.GetFileSpecAtIndex(i); 398 dir.ResolvePath(); 399 if (dir.Exists() && dir.IsDirectory()) { 400 m_search_directories.push_back(dir); 401 } 402 } 403 } 404 405 void PlatformDarwinKernel::AddRootSubdirsToSearchPaths( 406 PlatformDarwinKernel *thisp, const std::string &dir) { 407 const char *subdirs[] = { 408 "/System/Library/Extensions", "/Library/Extensions", 409 "/System/Library/Kernels", 410 "/System/Library/Extensions/KDK", // this one probably only exist in 411 // /AppleInternal/Developer/KDKs/*.kdk/... 412 nullptr}; 413 for (int i = 0; subdirs[i] != nullptr; i++) { 414 FileSpec testdir(dir + subdirs[i], true); 415 if (testdir.Exists() && testdir.IsDirectory()) 416 thisp->m_search_directories.push_back(testdir); 417 } 418 419 // Look for kernel binaries in the top level directory, without any recursion 420 thisp->m_search_directories_no_recursing.push_back( 421 FileSpec(dir + "/", false)); 422 } 423 424 // Given a directory path dir, look for any subdirs named *.kdk and *.sdk 425 void PlatformDarwinKernel::AddSDKSubdirsToSearchPaths(const std::string &dir) { 426 // Look for *.kdk and *.sdk in dir 427 const bool find_directories = true; 428 const bool find_files = false; 429 const bool find_other = false; 430 FileSpec::EnumerateDirectory(dir.c_str(), find_directories, find_files, 431 find_other, FindKDKandSDKDirectoriesInDirectory, 432 this); 433 } 434 435 // Helper function to find *.sdk and *.kdk directories in a given directory. 436 FileSpec::EnumerateDirectoryResult 437 PlatformDarwinKernel::FindKDKandSDKDirectoriesInDirectory( 438 void *baton, FileSpec::FileType file_type, const FileSpec &file_spec) { 439 static ConstString g_sdk_suffix = ConstString("sdk"); 440 static ConstString g_kdk_suffix = ConstString("kdk"); 441 442 PlatformDarwinKernel *thisp = (PlatformDarwinKernel *)baton; 443 if (file_type == FileSpec::eFileTypeDirectory && 444 (file_spec.GetFileNameExtension() == g_sdk_suffix || 445 file_spec.GetFileNameExtension() == g_kdk_suffix)) { 446 AddRootSubdirsToSearchPaths(thisp, file_spec.GetPath()); 447 } 448 return FileSpec::eEnumerateDirectoryResultNext; 449 } 450 451 // Recursively search trough m_search_directories looking for 452 // kext and kernel binaries, adding files found to the appropriate 453 // lists. 454 void PlatformDarwinKernel::SearchForKextsAndKernelsRecursively() { 455 const uint32_t num_dirs = m_search_directories.size(); 456 for (uint32_t i = 0; i < num_dirs; i++) { 457 const FileSpec &dir = m_search_directories[i]; 458 const bool find_directories = true; 459 const bool find_files = true; 460 const bool find_other = true; // I think eFileTypeSymbolicLink are "other"s. 461 FileSpec::EnumerateDirectory( 462 dir.GetPath().c_str(), find_directories, find_files, find_other, 463 GetKernelsAndKextsInDirectoryWithRecursion, this); 464 } 465 const uint32_t num_dirs_no_recurse = m_search_directories_no_recursing.size(); 466 for (uint32_t i = 0; i < num_dirs_no_recurse; i++) { 467 const FileSpec &dir = m_search_directories_no_recursing[i]; 468 const bool find_directories = true; 469 const bool find_files = true; 470 const bool find_other = true; // I think eFileTypeSymbolicLink are "other"s. 471 FileSpec::EnumerateDirectory( 472 dir.GetPath().c_str(), find_directories, find_files, find_other, 473 GetKernelsAndKextsInDirectoryNoRecursion, this); 474 } 475 } 476 477 // We're only doing a filename match here. We won't try opening the file to see 478 // if it's really 479 // a kernel or not until we need to find a kernel of a given UUID. There's no 480 // cheap way to find 481 // the UUID of a file (or if it's a Mach-O binary at all) without creating a 482 // whole Module for 483 // the file and throwing it away if it's not wanted. 484 // 485 // Recurse into any subdirectories found. 486 487 FileSpec::EnumerateDirectoryResult 488 PlatformDarwinKernel::GetKernelsAndKextsInDirectoryWithRecursion( 489 void *baton, FileSpec::FileType file_type, const FileSpec &file_spec) { 490 return GetKernelsAndKextsInDirectoryHelper(baton, file_type, file_spec, true); 491 } 492 493 FileSpec::EnumerateDirectoryResult 494 PlatformDarwinKernel::GetKernelsAndKextsInDirectoryNoRecursion( 495 void *baton, FileSpec::FileType file_type, const FileSpec &file_spec) { 496 return GetKernelsAndKextsInDirectoryHelper(baton, file_type, file_spec, 497 false); 498 } 499 500 FileSpec::EnumerateDirectoryResult 501 PlatformDarwinKernel::GetKernelsAndKextsInDirectoryHelper( 502 void *baton, FileSpec::FileType file_type, const FileSpec &file_spec, 503 bool recurse) { 504 static ConstString g_kext_suffix = ConstString("kext"); 505 static ConstString g_dsym_suffix = ConstString("dSYM"); 506 static ConstString g_bundle_suffix = ConstString("Bundle"); 507 ConstString file_spec_extension = file_spec.GetFileNameExtension(); 508 509 Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PLATFORM)); 510 if (log) 511 log->Printf("PlatformDarwinKernel examining %s", 512 file_spec.GetPath().c_str()); 513 514 PlatformDarwinKernel *thisp = (PlatformDarwinKernel *)baton; 515 if (file_type == FileSpec::eFileTypeRegular || 516 file_type == FileSpec::eFileTypeSymbolicLink) { 517 ConstString filename = file_spec.GetFilename(); 518 if ((strncmp(filename.GetCString(), "kernel", 6) == 0 || 519 strncmp(filename.GetCString(), "mach", 4) == 0) && 520 file_spec_extension != g_dsym_suffix) { 521 if (KernelHasdSYMSibling(file_spec)) 522 thisp->m_kernel_binaries_with_dsyms.push_back(file_spec); 523 else 524 thisp->m_kernel_binaries_without_dsyms.push_back(file_spec); 525 return FileSpec::eEnumerateDirectoryResultNext; 526 } 527 } else if (file_type == FileSpec::eFileTypeDirectory && 528 file_spec_extension == g_kext_suffix) { 529 AddKextToMap(thisp, file_spec); 530 // Look to see if there is a PlugIns subdir with more kexts 531 FileSpec contents_plugins(file_spec.GetPath() + "/Contents/PlugIns", false); 532 std::string search_here_too; 533 if (contents_plugins.Exists() && contents_plugins.IsDirectory()) { 534 search_here_too = contents_plugins.GetPath(); 535 } else { 536 FileSpec plugins(file_spec.GetPath() + "/PlugIns", false); 537 if (plugins.Exists() && plugins.IsDirectory()) { 538 search_here_too = plugins.GetPath(); 539 } 540 } 541 542 if (!search_here_too.empty()) { 543 const bool find_directories = true; 544 const bool find_files = false; 545 const bool find_other = false; 546 FileSpec::EnumerateDirectory( 547 search_here_too.c_str(), find_directories, find_files, find_other, 548 recurse ? GetKernelsAndKextsInDirectoryWithRecursion 549 : GetKernelsAndKextsInDirectoryNoRecursion, 550 baton); 551 } 552 return FileSpec::eEnumerateDirectoryResultNext; 553 } 554 // Don't recurse into dSYM/kext/bundle directories 555 if (recurse && file_spec_extension != g_dsym_suffix && 556 file_spec_extension != g_kext_suffix && 557 file_spec_extension != g_bundle_suffix) { 558 return FileSpec::eEnumerateDirectoryResultEnter; 559 } else { 560 return FileSpec::eEnumerateDirectoryResultNext; 561 } 562 } 563 564 void PlatformDarwinKernel::AddKextToMap(PlatformDarwinKernel *thisp, 565 const FileSpec &file_spec) { 566 CFCBundle bundle(file_spec.GetPath().c_str()); 567 CFStringRef bundle_id(bundle.GetIdentifier()); 568 if (bundle_id && CFGetTypeID(bundle_id) == CFStringGetTypeID()) { 569 char bundle_id_buf[PATH_MAX]; 570 if (CFStringGetCString(bundle_id, bundle_id_buf, sizeof(bundle_id_buf), 571 kCFStringEncodingUTF8)) { 572 ConstString bundle_conststr(bundle_id_buf); 573 if (KextHasdSYMSibling(file_spec)) 574 thisp->m_name_to_kext_path_map_with_dsyms.insert( 575 std::pair<ConstString, FileSpec>(bundle_conststr, file_spec)); 576 else 577 thisp->m_name_to_kext_path_map_without_dsyms.insert( 578 std::pair<ConstString, FileSpec>(bundle_conststr, file_spec)); 579 } 580 } 581 } 582 583 // Given a FileSpec of /dir/dir/foo.kext 584 // Return true if any of these exist: 585 // /dir/dir/foo.kext.dSYM 586 // /dir/dir/foo.kext/Contents/MacOS/foo.dSYM 587 // /dir/dir/foo.kext/foo.dSYM 588 bool PlatformDarwinKernel::KextHasdSYMSibling( 589 const FileSpec &kext_bundle_filepath) { 590 FileSpec dsym_fspec = kext_bundle_filepath; 591 std::string filename = dsym_fspec.GetFilename().AsCString(); 592 filename += ".dSYM"; 593 dsym_fspec.GetFilename() = ConstString(filename); 594 if (dsym_fspec.Exists() && dsym_fspec.IsDirectory()) { 595 return true; 596 } 597 // Should probably get the CFBundleExecutable here or call 598 // CFBundleCopyExecutableURL 599 600 // Look for a deep bundle foramt 601 ConstString executable_name = 602 kext_bundle_filepath.GetFileNameStrippingExtension(); 603 std::string deep_bundle_str = 604 kext_bundle_filepath.GetPath() + "/Contents/MacOS/"; 605 deep_bundle_str += executable_name.AsCString(); 606 deep_bundle_str += ".dSYM"; 607 dsym_fspec.SetFile(deep_bundle_str, true); 608 if (dsym_fspec.Exists() && dsym_fspec.IsDirectory()) { 609 return true; 610 } 611 612 // look for a shallow bundle format 613 // 614 std::string shallow_bundle_str = kext_bundle_filepath.GetPath() + "/"; 615 shallow_bundle_str += executable_name.AsCString(); 616 shallow_bundle_str += ".dSYM"; 617 dsym_fspec.SetFile(shallow_bundle_str, true); 618 if (dsym_fspec.Exists() && dsym_fspec.IsDirectory()) { 619 return true; 620 } 621 return false; 622 } 623 624 // Given a FileSpec of /dir/dir/mach.development.t7004 625 // Return true if a dSYM exists next to it: 626 // /dir/dir/mach.development.t7004.dSYM 627 bool PlatformDarwinKernel::KernelHasdSYMSibling(const FileSpec &kernel_binary) { 628 FileSpec kernel_dsym = kernel_binary; 629 std::string filename = kernel_binary.GetFilename().AsCString(); 630 filename += ".dSYM"; 631 kernel_dsym.GetFilename() = ConstString(filename); 632 if (kernel_dsym.Exists() && kernel_dsym.IsDirectory()) { 633 return true; 634 } 635 return false; 636 } 637 638 Error PlatformDarwinKernel::GetSharedModule( 639 const ModuleSpec &module_spec, Process *process, ModuleSP &module_sp, 640 const FileSpecList *module_search_paths_ptr, ModuleSP *old_module_sp_ptr, 641 bool *did_create_ptr) { 642 Error error; 643 module_sp.reset(); 644 const FileSpec &platform_file = module_spec.GetFileSpec(); 645 646 // Treat the file's path as a kext bundle ID (e.g. 647 // "com.apple.driver.AppleIRController") and search our kext index. 648 std::string kext_bundle_id = platform_file.GetPath(); 649 if (!kext_bundle_id.empty()) { 650 ConstString kext_bundle_cs(kext_bundle_id.c_str()); 651 652 // First look through the kext bundles that had a dsym next to them 653 if (m_name_to_kext_path_map_with_dsyms.count(kext_bundle_cs) > 0) { 654 for (BundleIDToKextIterator it = 655 m_name_to_kext_path_map_with_dsyms.begin(); 656 it != m_name_to_kext_path_map_with_dsyms.end(); ++it) { 657 if (it->first == kext_bundle_cs) { 658 error = ExamineKextForMatchingUUID(it->second, module_spec.GetUUID(), 659 module_spec.GetArchitecture(), 660 module_sp); 661 if (module_sp.get()) { 662 return error; 663 } 664 } 665 } 666 } 667 668 // Second look through the kext binarys without dSYMs 669 if (m_name_to_kext_path_map_without_dsyms.count(kext_bundle_cs) > 0) { 670 for (BundleIDToKextIterator it = 671 m_name_to_kext_path_map_without_dsyms.begin(); 672 it != m_name_to_kext_path_map_without_dsyms.end(); ++it) { 673 if (it->first == kext_bundle_cs) { 674 error = ExamineKextForMatchingUUID(it->second, module_spec.GetUUID(), 675 module_spec.GetArchitecture(), 676 module_sp); 677 if (module_sp.get()) { 678 return error; 679 } 680 } 681 } 682 } 683 } 684 685 if (kext_bundle_id.compare("mach_kernel") == 0 && 686 module_spec.GetUUID().IsValid()) { 687 // First try all kernel binaries that have a dSYM next to them 688 for (auto possible_kernel : m_kernel_binaries_with_dsyms) { 689 if (possible_kernel.Exists()) { 690 ModuleSpec kern_spec(possible_kernel); 691 kern_spec.GetUUID() = module_spec.GetUUID(); 692 ModuleSP module_sp(new Module(kern_spec)); 693 if (module_sp && module_sp->GetObjectFile() && 694 module_sp->MatchesModuleSpec(kern_spec)) { 695 // module_sp is an actual kernel binary we want to add. 696 if (process) { 697 process->GetTarget().GetImages().AppendIfNeeded(module_sp); 698 error.Clear(); 699 return error; 700 } else { 701 error = ModuleList::GetSharedModule(kern_spec, module_sp, NULL, 702 NULL, NULL); 703 if (module_sp && module_sp->GetObjectFile() && 704 module_sp->GetObjectFile()->GetType() != 705 ObjectFile::Type::eTypeCoreFile) { 706 return error; 707 } 708 module_sp.reset(); 709 } 710 } 711 } 712 } 713 // Second try all kernel binaries that don't have a dSYM 714 for (auto possible_kernel : m_kernel_binaries_without_dsyms) { 715 if (possible_kernel.Exists()) { 716 ModuleSpec kern_spec(possible_kernel); 717 kern_spec.GetUUID() = module_spec.GetUUID(); 718 ModuleSP module_sp(new Module(kern_spec)); 719 if (module_sp && module_sp->GetObjectFile() && 720 module_sp->MatchesModuleSpec(kern_spec)) { 721 // module_sp is an actual kernel binary we want to add. 722 if (process) { 723 process->GetTarget().GetImages().AppendIfNeeded(module_sp); 724 error.Clear(); 725 return error; 726 } else { 727 error = ModuleList::GetSharedModule(kern_spec, module_sp, NULL, 728 NULL, NULL); 729 if (module_sp && module_sp->GetObjectFile() && 730 module_sp->GetObjectFile()->GetType() != 731 ObjectFile::Type::eTypeCoreFile) { 732 return error; 733 } 734 module_sp.reset(); 735 } 736 } 737 } 738 } 739 } 740 741 // Else fall back to treating the file's path as an actual file path - defer 742 // to PlatformDarwin's GetSharedModule. 743 return PlatformDarwin::GetSharedModule(module_spec, process, module_sp, 744 module_search_paths_ptr, 745 old_module_sp_ptr, did_create_ptr); 746 } 747 748 Error PlatformDarwinKernel::ExamineKextForMatchingUUID( 749 const FileSpec &kext_bundle_path, const lldb_private::UUID &uuid, 750 const ArchSpec &arch, ModuleSP &exe_module_sp) { 751 Error error; 752 FileSpec exe_file = kext_bundle_path; 753 Host::ResolveExecutableInBundle(exe_file); 754 if (exe_file.Exists()) { 755 ModuleSpec exe_spec(exe_file); 756 exe_spec.GetUUID() = uuid; 757 if (!uuid.IsValid()) { 758 exe_spec.GetArchitecture() = arch; 759 } 760 761 // First try to create a ModuleSP with the file / arch and see if the UUID 762 // matches. 763 // If that fails (this exec file doesn't have the correct uuid), don't call 764 // GetSharedModule 765 // (which may call in to the DebugSymbols framework and therefore can be 766 // slow.) 767 ModuleSP module_sp(new Module(exe_spec)); 768 if (module_sp && module_sp->GetObjectFile() && 769 module_sp->MatchesModuleSpec(exe_spec)) { 770 error = ModuleList::GetSharedModule(exe_spec, exe_module_sp, NULL, NULL, 771 NULL); 772 if (exe_module_sp && exe_module_sp->GetObjectFile()) { 773 return error; 774 } 775 } 776 exe_module_sp.reset(); 777 } 778 return error; 779 } 780 781 bool PlatformDarwinKernel::GetSupportedArchitectureAtIndex(uint32_t idx, 782 ArchSpec &arch) { 783 #if defined(__arm__) || defined(__arm64__) || defined(__aarch64__) 784 return ARMGetSupportedArchitectureAtIndex(idx, arch); 785 #else 786 return x86GetSupportedArchitectureAtIndex(idx, arch); 787 #endif 788 } 789 790 void PlatformDarwinKernel::CalculateTrapHandlerSymbolNames() { 791 m_trap_handlers.push_back(ConstString("trap_from_kernel")); 792 m_trap_handlers.push_back(ConstString("hndl_machine_check")); 793 m_trap_handlers.push_back(ConstString("hndl_double_fault")); 794 m_trap_handlers.push_back(ConstString("hndl_allintrs")); 795 m_trap_handlers.push_back(ConstString("hndl_alltraps")); 796 m_trap_handlers.push_back(ConstString("interrupt")); 797 m_trap_handlers.push_back(ConstString("fleh_prefabt")); 798 m_trap_handlers.push_back(ConstString("ExceptionVectorsBase")); 799 m_trap_handlers.push_back(ConstString("ExceptionVectorsTable")); 800 m_trap_handlers.push_back(ConstString("fleh_undef")); 801 m_trap_handlers.push_back(ConstString("fleh_dataabt")); 802 m_trap_handlers.push_back(ConstString("fleh_irq")); 803 m_trap_handlers.push_back(ConstString("fleh_decirq")); 804 m_trap_handlers.push_back(ConstString("fleh_fiq_generic")); 805 m_trap_handlers.push_back(ConstString("fleh_dec")); 806 } 807 808 #else // __APPLE__ 809 810 // Since DynamicLoaderDarwinKernel is compiled in for all systems, and relies on 811 // PlatformDarwinKernel for the plug-in name, we compile just the plug-in name 812 // in 813 // here to avoid issues. We are tracking an internal bug to resolve this issue 814 // by 815 // either not compiling in DynamicLoaderDarwinKernel for non-apple builds, or to 816 // make 817 // PlatformDarwinKernel build on all systems. PlatformDarwinKernel is currently 818 // not 819 // compiled on other platforms due to the use of the Mac-specific 820 // source/Host/macosx/cfcpp utilities. 821 822 lldb_private::ConstString PlatformDarwinKernel::GetPluginNameStatic() { 823 static lldb_private::ConstString g_name("darwin-kernel"); 824 return g_name; 825 } 826 827 #endif // __APPLE__ 828