diff options
| -rw-r--r-- | lldb/source/Plugins/Platform/MacOSX/PlatformDarwinKernel.cpp | 194 | ||||
| -rw-r--r-- | lldb/source/Plugins/Platform/MacOSX/PlatformDarwinKernel.h | 36 |
2 files changed, 207 insertions, 23 deletions
diff --git a/lldb/source/Plugins/Platform/MacOSX/PlatformDarwinKernel.cpp b/lldb/source/Plugins/Platform/MacOSX/PlatformDarwinKernel.cpp index 8170275c765..919c10fcad5 100644 --- a/lldb/source/Plugins/Platform/MacOSX/PlatformDarwinKernel.cpp +++ b/lldb/source/Plugins/Platform/MacOSX/PlatformDarwinKernel.cpp @@ -250,13 +250,16 @@ PlatformDarwinKernel::DebuggerInitialize (lldb_private::Debugger &debugger) PlatformDarwinKernel::PlatformDarwinKernel (lldb_private::LazyBool is_ios_debug_session) : PlatformDarwin (false), // This is a remote platform m_name_to_kext_path_map(), - m_directories_searched(), + m_search_directories(), + m_kernel_binaries(), m_ios_debug_session(is_ios_debug_session) { if (GetGlobalProperties()->GetSearchForKexts()) { - SearchForKexts (); + CollectKextAndKernelDirectories (); + IndexKextsInDirectories (); + IndexKernelsInDirectories (); } } @@ -282,23 +285,26 @@ PlatformDarwinKernel::GetStatus (Stream &strm) strm.Printf ("Mac OS X kernel debugging\n"); else strm.Printf ("unknown kernel debugging\n"); - const uint32_t num_kext_dirs = m_directories_searched.size(); + const uint32_t num_kext_dirs = m_search_directories.size(); for (uint32_t i=0; i<num_kext_dirs; ++i) { - const FileSpec &kext_dir = m_directories_searched[i]; + const FileSpec &kext_dir = m_search_directories[i]; strm.Printf (" Kext directories: [%2u] \"%s\"\n", i, kext_dir.GetPath().c_str()); } strm.Printf (" Total number of kexts indexed: %d\n", (int) m_name_to_kext_path_map.size()); } +// Populate the m_search_directories vector with directories we should search +// for kernel & kext binaries. + void -PlatformDarwinKernel::SearchForKexts () +PlatformDarwinKernel::CollectKextAndKernelDirectories () { // Differentiate between "ios debug session" and "mac debug session" so we don't index // kext bundles that won't be used in this debug session. If this is an ios kext debug // session, looking in /System/Library/Extensions is a waste of stat()s, for example. - // Build up a list of all SDKs we'll be searching for directories of kexts + // Build up a list of all SDKs we'll be searching for directories of kexts/kernels // e.g. /Applications/Xcode.app//Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.8.Internal.sdk std::vector<FileSpec> sdk_dirs; if (m_ios_debug_session != eLazyBoolNo) @@ -308,8 +314,14 @@ PlatformDarwinKernel::SearchForKexts () GetGenericSDKDirectoriesToSearch (sdk_dirs); - // Build up a list of directories that hold kext bundles on the system - // e.g. /Applications/Xcode.app//Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.8.Internal.sdk/System/Library/Extensions + // Build up a list of directories that hold may kext bundles & kernels + // + // e.g. given /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/ + // find + // /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.8.Internal.sdk/ + // and + // /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.8.Internal.sdk/System/Library/Extensions + std::vector<FileSpec> kext_dirs; SearchSDKsForKextDirectories (sdk_dirs, kext_dirs); @@ -322,10 +334,12 @@ PlatformDarwinKernel::SearchForKexts () GetUserSpecifiedDirectoriesToSearch (kext_dirs); - // We now have a complete list of directories that we will search for kext bundles - m_directories_searched = kext_dirs; + GetKernelDirectoriesToSearch (kext_dirs); - IndexKextsInDirectories (kext_dirs); + GetCurrentDirectoryToSearch (kext_dirs); + + // We now have a complete list of directories that we will search for kext bundles + m_search_directories = kext_dirs; } void @@ -379,7 +393,6 @@ PlatformDarwinKernel::GetGenericSDKDirectoriesToSearch (std::vector<lldb_private { directories.push_back (installed_kdks); } - } void @@ -427,6 +440,50 @@ PlatformDarwinKernel::GetGenericDirectoriesToSearch (std::vector<lldb_private::F } void +PlatformDarwinKernel::GetKernelDirectoriesToSearch (std::vector<lldb_private::FileSpec> &directories) +{ + FileSpec system_library_kernels ("/System/Library/Kernels", true); + if (system_library_kernels.Exists() && system_library_kernels.IsDirectory()) + { + directories.push_back (system_library_kernels); + } + FileSpec slek("/System/Library/Extensions/KDK", true); + if (slek.Exists() && slek.IsDirectory()) + { + directories.push_back(slek); + } +} + +void +PlatformDarwinKernel::GetCurrentDirectoryToSearch (std::vector<lldb_private::FileSpec> &directories) +{ + directories.push_back (FileSpec (".", true)); + + FileSpec sle_directory ("System/Library/Extensions", true); + if (sle_directory.Exists() && sle_directory.IsDirectory()) + { + directories.push_back (sle_directory); + } + + FileSpec le_directory ("Library/Extensions", true); + if (le_directory.Exists() && le_directory.IsDirectory()) + { + directories.push_back (le_directory); + } + + FileSpec slk_directory ("System/Library/Kernels", true); + if (slk_directory.Exists() && slk_directory.IsDirectory()) + { + directories.push_back (slk_directory); + } + FileSpec slek("System/Library/Extensions/KDK", true); + if (slek.Exists() && slek.IsDirectory()) + { + directories.push_back(slek); + } +} + +void PlatformDarwinKernel::GetUserSpecifiedDirectoriesToSearch (std::vector<lldb_private::FileSpec> &directories) { FileSpecList user_dirs(GetGlobalProperties()->GetKextDirectories()); @@ -450,6 +507,24 @@ PlatformDarwinKernel::GetUserSpecifiedDirectoriesToSearch (std::vector<lldb_priv { directories.push_back (dir_sle); } + + // Is there a "System/Library/Kernels" subdir of this directory? + std::string dir_slk_path = dir.GetPath(); + dir_slk_path.append ("/System/Library/Kernels"); + FileSpec dir_slk(dir_slk_path.c_str(), true); + if (dir_slk.Exists() && dir_slk.IsDirectory()) + { + directories.push_back (dir_slk); + } + + // Is there a "System/Library/Extensions/KDK" subdir of this directory? + std::string dir_slek_path = dir.GetPath(); + dir_slek_path.append ("/System/Library/Kernels"); + FileSpec dir_slek(dir_slek_path.c_str(), true); + if (dir_slek.Exists() && dir_slek.IsDirectory()) + { + directories.push_back (dir_slek); + } } } @@ -523,19 +598,36 @@ PlatformDarwinKernel::GetKextDirectoriesInSDK (void *baton, ((std::vector<lldb_private::FileSpec> *)baton)->push_back(le_kext_directory); } + // Check to see if there is a System/Library/Kernels subdir & add it if it exists + std::string slk_kernel_path (kext_directory_path); + slk_kernel_path.append ("/System/Library/Kernels"); + FileSpec slk_kernel_directory (slk_kernel_path.c_str(), true); + if (slk_kernel_directory.Exists() && slk_kernel_directory.IsDirectory()) + { + ((std::vector<lldb_private::FileSpec> *)baton)->push_back(slk_kernel_directory); + } + + // Check to see if there is a System/Library/Extensions/KDK subdir & add it if it exists + std::string slek_kernel_path (kext_directory_path); + slek_kernel_path.append ("/System/Library/Extensions/KDK"); + FileSpec slek_kernel_directory (slek_kernel_path.c_str(), true); + if (slek_kernel_directory.Exists() && slek_kernel_directory.IsDirectory()) + { + ((std::vector<lldb_private::FileSpec> *)baton)->push_back(slek_kernel_directory); + } } return FileSpec::eEnumerateDirectoryResultNext; } void -PlatformDarwinKernel::IndexKextsInDirectories (std::vector<lldb_private::FileSpec> kext_dirs) +PlatformDarwinKernel::IndexKextsInDirectories () { std::vector<FileSpec> kext_bundles; - const uint32_t num_dirs = kext_dirs.size(); + const uint32_t num_dirs = m_search_directories.size(); for (uint32_t i = 0; i < num_dirs; i++) { - const FileSpec &dir = kext_dirs[i]; + const FileSpec &dir = m_search_directories[i]; const bool find_directories = true; const bool find_files = false; const bool find_other = false; @@ -612,6 +704,56 @@ PlatformDarwinKernel::GetKextsInDirectory (void *baton, return FileSpec::eEnumerateDirectoryResultNext; } +void +PlatformDarwinKernel::IndexKernelsInDirectories () +{ + std::vector<FileSpec> kernels; + + + const uint32_t num_dirs = m_search_directories.size(); + for (uint32_t i = 0; i < num_dirs; i++) + { + const FileSpec &dir = m_search_directories[i]; + const bool find_directories = false; + const bool find_files = true; + const bool find_other = true; // I think eFileTypeSymbolicLink are "other"s. + FileSpec::EnumerateDirectory (dir.GetPath().c_str(), + find_directories, + find_files, + find_other, + GetKernelsInDirectory, + &m_kernel_binaries); + } +} + +// Callback for FileSpec::EnumerateDirectory(). +// Step through the entries in a directory like /System/Library/Kernels/, find kernel binaries, +// add them to m_kernel_binaries. + +// We're only doing a filename match here. We won't try opening the file to see if it's really +// a kernel or not until we need to find a kernel of a given UUID. There's no cheap way to find +// the UUID of a file (or if it's a Mach-O binary at all) without creating a whole Module for +// the file and throwing it away if it's not wanted. + +FileSpec::EnumerateDirectoryResult +PlatformDarwinKernel::GetKernelsInDirectory (void *baton, + FileSpec::FileType file_type, + const FileSpec &file_spec) +{ + if (file_type == FileSpec::eFileTypeRegular || file_type == FileSpec::eFileTypeSymbolicLink) + { + ConstString filename = file_spec.GetFilename(); + if (strncmp (filename.GetCString(), "kernel", 6) == 0 + || strncmp (filename.GetCString(), "mach.", 5) == 0) + { + // This is m_kernel_binaries but we're in a class method here + ((std::vector<lldb_private::FileSpec> *)baton)->push_back(file_spec); + } + } + return FileSpec::eEnumerateDirectoryResultNext; +} + + Error PlatformDarwinKernel::GetSharedModule (const ModuleSpec &module_spec, ModuleSP &module_sp, @@ -644,6 +786,28 @@ PlatformDarwinKernel::GetSharedModule (const ModuleSpec &module_spec, } } + if (kext_bundle_id.compare("mach_kernel") == 0 && module_spec.GetUUID().IsValid()) + { + for (auto possible_kernel : m_kernel_binaries) + { + if (possible_kernel.Exists()) + { + ModuleSpec kern_spec (possible_kernel); + kern_spec.GetUUID() = module_spec.GetUUID(); + ModuleSP module_sp (new Module (kern_spec)); + if (module_sp && module_sp->GetObjectFile() && module_sp->MatchesModuleSpec (kern_spec)) + { + Error error; + error = ModuleList::GetSharedModule (kern_spec, module_sp, NULL, NULL, NULL); + if (module_sp && module_sp->GetObjectFile()) + { + return error; + } + } + } + } + } + // Else fall back to treating the file's path as an actual file path - defer to PlatformDarwin's GetSharedModule. return PlatformDarwin::GetSharedModule (module_spec, module_sp, module_search_paths_ptr, old_module_sp_ptr, did_create_ptr); } diff --git a/lldb/source/Plugins/Platform/MacOSX/PlatformDarwinKernel.h b/lldb/source/Plugins/Platform/MacOSX/PlatformDarwinKernel.h index 1ba26803ce6..ad0bc6205b8 100644 --- a/lldb/source/Plugins/Platform/MacOSX/PlatformDarwinKernel.h +++ b/lldb/source/Plugins/Platform/MacOSX/PlatformDarwinKernel.h @@ -66,7 +66,7 @@ public: } virtual uint32_t - GetPluginVersion() override + GetPluginVersion() override { return 1; } @@ -88,7 +88,7 @@ public: lldb::ModuleSP &module_sp, const lldb_private::FileSpecList *module_search_paths_ptr, lldb::ModuleSP *old_module_sp_ptr, - bool *did_create_ptr) override; + bool *did_create_ptr) override; bool GetSupportedArchitectureAtIndex (uint32_t idx, @@ -100,7 +100,6 @@ public: void CalculateTrapHandlerSymbolNames () override; - protected: // Map from kext bundle ID ("com.apple.filesystems.exfat") to FileSpec for the kext bundle on @@ -108,6 +107,7 @@ protected: typedef std::multimap<lldb_private::ConstString, lldb_private::FileSpec> BundleIDToKextMap; typedef BundleIDToKextMap::iterator BundleIDToKextIterator; + typedef std::vector<lldb_private::FileSpec> KernelBinaryCollection; // Array of directories that were searched for kext bundles (used only for reporting to user) typedef std::vector<lldb_private::FileSpec> DirectoriesSearchedCollection; @@ -124,8 +124,9 @@ protected: lldb_private::FileSpec::FileType file_type, const lldb_private::FileSpec &file_spec); + // Populate m_search_directories vector of directories void - SearchForKexts(); + CollectKextAndKernelDirectories (); // Directories where we may find iOS SDKs with kext bundles in them void @@ -155,6 +156,13 @@ protected: void GetUserSpecifiedDirectoriesToSearch (std::vector<lldb_private::FileSpec> &directories); + void + GetCurrentDirectoryToSearch (std::vector<lldb_private::FileSpec> &directories); + + // Directories where we may find kernels exclusively + void + GetKernelDirectoriesToSearch (std::vector<lldb_private::FileSpec> &directories); + // Search through a vector of SDK FileSpecs, add any directories that may contain kexts // to the vector of kext dir FileSpecs void @@ -163,16 +171,28 @@ protected: // Search through all of the directories passed in, find all .kext bundles in those directories, // get the CFBundleIDs out of the Info.plists and add the bundle ID and kext path to m_name_to_kext_path_map. void - IndexKextsInDirectories (std::vector<lldb_private::FileSpec> kext_dirs); + IndexKextsInDirectories (); + + // Search through all of the directories passed in, find all kernel binaries in those directories + // (look for "kernel*", "mach.*", assume those are kernels. False positives aren't a huge problem.) + void + IndexKernelsInDirectories (); + + // Callback which iterates over all the files in a given directory, looking for kernel binaries + static lldb_private::FileSpec::EnumerateDirectoryResult + GetKernelsInDirectory (void *baton, + lldb_private::FileSpec::FileType file_type, + const lldb_private::FileSpec &file_spec); lldb_private::Error ExamineKextForMatchingUUID (const lldb_private::FileSpec &kext_bundle_path, const lldb_private::UUID &uuid, const lldb_private::ArchSpec &arch, lldb::ModuleSP &exe_module_sp); private: - BundleIDToKextMap m_name_to_kext_path_map; - DirectoriesSearchedCollection m_directories_searched; - lldb_private::LazyBool m_ios_debug_session; + BundleIDToKextMap m_name_to_kext_path_map; // multimap of CFBundleID to FileSpec on local filesystem + DirectoriesSearchedCollection m_search_directories; // list of directories we search for kexts/kernels + KernelBinaryCollection m_kernel_binaries; // list of kernel binaries we found on local filesystem + lldb_private::LazyBool m_ios_debug_session; DISALLOW_COPY_AND_ASSIGN (PlatformDarwinKernel); |

