From 9a435729b4b7d94a8c126f4c186da1a202f05b9a Mon Sep 17 00:00:00 2001 From: Jason Molenda Date: Thu, 29 Jan 2015 06:20:05 +0000 Subject: [PATCH] When starting a kernel debug session (PlatformDarwinKernel), scan for executable binaries on the local filesystem so the user doesn't need to provide the path to the correct binary manually. Also have lldb search for kexts/the kernel in the current working directory in addition to all the usual places. llvm-svn: 227419 --- .../Platform/MacOSX/PlatformDarwinKernel.cpp | 194 +++++++++++++++++++-- .../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 8170275..919c10f 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 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 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 &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 &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 &directories) { FileSpecList user_dirs(GetGlobalProperties()->GetKextDirectories()); @@ -450,6 +507,24 @@ PlatformDarwinKernel::GetUserSpecifiedDirectoriesToSearch (std::vector *)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 *)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 *)baton)->push_back(slek_kernel_directory); + } } return FileSpec::eEnumerateDirectoryResultNext; } void -PlatformDarwinKernel::IndexKextsInDirectories (std::vector kext_dirs) +PlatformDarwinKernel::IndexKextsInDirectories () { std::vector 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 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 *)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 1ba2680..ad0bc620 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 BundleIDToKextMap; typedef BundleIDToKextMap::iterator BundleIDToKextIterator; + typedef std::vector KernelBinaryCollection; // Array of directories that were searched for kext bundles (used only for reporting to user) typedef std::vector 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 &directories); + void + GetCurrentDirectoryToSearch (std::vector &directories); + + // Directories where we may find kernels exclusively + void + GetKernelDirectoriesToSearch (std::vector &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 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); -- 2.7.4