[Lldb-commits] [lldb] r227419 - When starting a kernel debug session (PlatformDarwinKernel), scan

Jason Molenda jmolenda at apple.com
Wed Jan 28 22:20:05 PST 2015


Author: jmolenda
Date: Thu Jan 29 00:20:05 2015
New Revision: 227419

URL: http://llvm.org/viewvc/llvm-project?rev=227419&view=rev
Log:
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.

<rdar://problem/18126501> 


Modified:
    lldb/trunk/source/Plugins/Platform/MacOSX/PlatformDarwinKernel.cpp
    lldb/trunk/source/Plugins/Platform/MacOSX/PlatformDarwinKernel.h

Modified: lldb/trunk/source/Plugins/Platform/MacOSX/PlatformDarwinKernel.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Platform/MacOSX/PlatformDarwinKernel.cpp?rev=227419&r1=227418&r2=227419&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Platform/MacOSX/PlatformDarwinKernel.cpp (original)
+++ lldb/trunk/source/Plugins/Platform/MacOSX/PlatformDarwinKernel.cpp Thu Jan 29 00:20:05 2015
@@ -250,13 +250,16 @@ PlatformDarwinKernel::DebuggerInitialize
 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.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::GetGenericSDKDirec
     {
         directories.push_back (installed_kdks);
     }
-
 }
 
 void
@@ -427,6 +440,50 @@ PlatformDarwinKernel::GetGenericDirector
 }
 
 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::GetUserSpecifiedDi
             {
                 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::GetKextDirectories
             ((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::GetKextsInDirector
     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,
@@ -639,6 +781,28 @@ PlatformDarwinKernel::GetSharedModule (c
                     {
                         return error;
                     }
+                }
+            }
+        }
+    }
+
+    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;
+                    }
                 }
             }
         }

Modified: lldb/trunk/source/Plugins/Platform/MacOSX/PlatformDarwinKernel.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Platform/MacOSX/PlatformDarwinKernel.h?rev=227419&r1=227418&r2=227419&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Platform/MacOSX/PlatformDarwinKernel.h (original)
+++ lldb/trunk/source/Plugins/Platform/MacOSX/PlatformDarwinKernel.h Thu Jan 29 00:20:05 2015
@@ -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);
 





More information about the lldb-commits mailing list