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 ();
}
}
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)
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);
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
{
directories.push_back (installed_kdks);
}
-
}
void
}
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());
{
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);
+ }
}
}
((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;
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,
}
}
+ 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);
}
}
virtual uint32_t
- GetPluginVersion() override
+ GetPluginVersion() override
{
return 1;
}
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,
void
CalculateTrapHandlerSymbolNames () override;
-
protected:
// Map from kext bundle ID ("com.apple.filesystems.exfat") to FileSpec for the kext bundle on
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;
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
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
// 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);