Change the indexing done for kernel/kext directories to be recursive.

Also re-write how most of the directory indexing is done - as it has 
grown over the years, it has become a bit of a mess and was overdue
for a cleanup.

Most importantly, this allows you to specify a directory with the 
platform.plugin.darwin-kernel.kext-directories setting and now lldb
will search for kexts and kernels in those directories recursively.

<rdar://problem/20754467> 

llvm-svn: 277789
This commit is contained in:
Jason Molenda 2016-08-05 00:44:34 +00:00
parent 358e60a6b3
commit 243bd763ec
2 changed files with 289 additions and 530 deletions

View File

@ -288,6 +288,7 @@ PlatformDarwinKernel::PlatformDarwinKernel (lldb_private::LazyBool is_ios_debug_
m_name_to_kext_path_map_with_dsyms(), m_name_to_kext_path_map_with_dsyms(),
m_name_to_kext_path_map_without_dsyms(), m_name_to_kext_path_map_without_dsyms(),
m_search_directories(), m_search_directories(),
m_search_directories_no_recursing(),
m_kernel_binaries_with_dsyms(), m_kernel_binaries_with_dsyms(),
m_kernel_binaries_without_dsyms(), m_kernel_binaries_without_dsyms(),
m_ios_debug_session(is_ios_debug_session) m_ios_debug_session(is_ios_debug_session)
@ -296,8 +297,7 @@ PlatformDarwinKernel::PlatformDarwinKernel (lldb_private::LazyBool is_ios_debug_
if (GetGlobalProperties()->GetSearchForKexts()) if (GetGlobalProperties()->GetSearchForKexts())
{ {
CollectKextAndKernelDirectories (); CollectKextAndKernelDirectories ();
IndexKextsInDirectories (); SearchForKextsAndKernelsRecursively ();
IndexKernelsInDirectories ();
} }
} }
@ -322,17 +322,53 @@ PlatformDarwinKernel::GetStatus (Stream &strm)
else if (m_ios_debug_session == eLazyBoolNo) else if (m_ios_debug_session == eLazyBoolNo)
strm.Printf ("Mac OS X kernel debugging\n"); strm.Printf ("Mac OS X kernel debugging\n");
else else
strm.Printf ("unknown kernel debugging\n"); strm.Printf ("unknown kernel debugging\n");
strm.Printf ("Directories searched recursively:\n");
const uint32_t num_kext_dirs = m_search_directories.size(); const uint32_t num_kext_dirs = m_search_directories.size();
for (uint32_t i=0; i<num_kext_dirs; ++i) for (uint32_t i=0; i<num_kext_dirs; ++i)
{ {
const FileSpec &kext_dir = m_search_directories[i]; strm.Printf ("[%d] %s\n", i, m_search_directories[i].GetPath().c_str());
strm.Printf (" Kext directories: [%2u] \"%s\"\n", i, kext_dir.GetPath().c_str());
} }
strm.Printf ("Directories not searched recursively:\n");
const uint32_t num_kext_dirs_no_recursion = m_search_directories_no_recursing.size();
for (uint32_t i = 0; i < num_kext_dirs_no_recursion; i++)
{
strm.Printf ("[%d] %s\n", i, m_search_directories_no_recursing[i].GetPath().c_str());
}
strm.Printf (" Number of kexts with dSYMs indexed: %d\n", (int) m_name_to_kext_path_map_with_dsyms.size()); strm.Printf (" Number of kexts with dSYMs indexed: %d\n", (int) m_name_to_kext_path_map_with_dsyms.size());
strm.Printf (" Number of kexts without dSYMs indexed: %d\n", (int) m_name_to_kext_path_map_without_dsyms.size()); strm.Printf (" Number of kexts without dSYMs indexed: %d\n", (int) m_name_to_kext_path_map_without_dsyms.size());
strm.Printf (" Number of Kernel binaries with dSYMs indexed: %d\n", (int) m_kernel_binaries_with_dsyms.size()); strm.Printf (" Number of Kernel binaries with dSYMs indexed: %d\n", (int) m_kernel_binaries_with_dsyms.size());
strm.Printf (" Number of Kernel binaries without dSYMs indexed: %d\n", (int) m_kernel_binaries_without_dsyms.size()); strm.Printf (" Number of Kernel binaries without dSYMs indexed: %d\n", (int) m_kernel_binaries_without_dsyms.size());
Log *log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_PLATFORM));
if (log)
{
log->Printf("\nkexts with dSYMs");
for (auto pos : m_name_to_kext_path_map_with_dsyms)
{
log->Printf ("%s", pos.second.GetPath().c_str());
}
log->Printf("\nkexts without dSYMs");
for (auto pos : m_name_to_kext_path_map_without_dsyms)
{
log->Printf ("%s", pos.second.GetPath().c_str());
}
log->Printf("\nkernels with dSYMS");
for (auto fs : m_kernel_binaries_with_dsyms)
{
log->Printf ("%s", fs.GetPath().c_str());
}
log->Printf("\nkernels without dSYMS");
for (auto fs : m_kernel_binaries_without_dsyms)
{
log->Printf ("%s", fs.GetPath().c_str());
}
log->Printf("\n");
}
} }
// Populate the m_search_directories vector with directories we should search // Populate the m_search_directories vector with directories we should search
@ -345,235 +381,51 @@ PlatformDarwinKernel::CollectKextAndKernelDirectories ()
// kext bundles that won't be used in this debug session. If this is an ios kext debug // 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. // 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/kernels // DeveloperDirectory is something like "/Applications/Xcode.app/Contents/Developer"
// e.g. /Applications/Xcode.app//Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.8.Internal.sdk std::string developer_dir = GetDeveloperDirectory();
std::vector<FileSpec> sdk_dirs; if (developer_dir.empty())
developer_dir = "/Applications/Xcode.app/Contents/Developer";
if (m_ios_debug_session != eLazyBoolNo) if (m_ios_debug_session != eLazyBoolNo)
{ {
GetiOSSDKDirectoriesToSearch (sdk_dirs); AddSDKSubdirsToSearchPaths (developer_dir + "/Platforms/iPhoneOS.platform/Developer/SDKs");
GetAppleTVOSSDKDirectoriesToSearch (sdk_dirs); AddSDKSubdirsToSearchPaths (developer_dir + "/Platforms/AppleTVOS.platform/Developer/SDKs");
GetWatchOSSDKDirectoriesToSearch (sdk_dirs); AddSDKSubdirsToSearchPaths (developer_dir + "/Platforms/WatchOS.platform/Developer/SDKs");
} }
if (m_ios_debug_session != eLazyBoolYes) if (m_ios_debug_session != eLazyBoolYes)
GetMacSDKDirectoriesToSearch (sdk_dirs);
GetGenericSDKDirectoriesToSearch (sdk_dirs);
// 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);
if (m_ios_debug_session != eLazyBoolNo)
GetiOSDirectoriesToSearch (kext_dirs);
if (m_ios_debug_session != eLazyBoolYes)
GetMacDirectoriesToSearch (kext_dirs);
GetGenericDirectoriesToSearch (kext_dirs);
GetUserSpecifiedDirectoriesToSearch (kext_dirs);
GetKernelDirectoriesToSearch (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
PlatformDarwinKernel::GetiOSSDKDirectoriesToSearch (std::vector<lldb_private::FileSpec> &directories)
{
// DeveloperDirectory is something like "/Applications/Xcode.app/Contents/Developer"
const char *developer_dir = GetDeveloperDirectory();
if (developer_dir == NULL)
developer_dir = "/Applications/Xcode.app/Contents/Developer";
char pathbuf[PATH_MAX];
::snprintf (pathbuf, sizeof (pathbuf), "%s/Platforms/iPhoneOS.platform/Developer/SDKs", developer_dir);
FileSpec ios_sdk(pathbuf, true);
if (ios_sdk.Exists() && ios_sdk.IsDirectory())
{ {
directories.push_back (ios_sdk); AddSDKSubdirsToSearchPaths (developer_dir + "/Platforms/MacOSX.platform/Developer/SDKs");
}
}
void
PlatformDarwinKernel::GetAppleTVOSSDKDirectoriesToSearch (std::vector<lldb_private::FileSpec> &directories)
{
// DeveloperDirectory is something like "/Applications/Xcode.app/Contents/Developer"
const char *developer_dir = GetDeveloperDirectory();
if (developer_dir == NULL)
developer_dir = "/Applications/Xcode.app/Contents/Developer";
char pathbuf[PATH_MAX];
::snprintf (pathbuf, sizeof (pathbuf), "%s/Platforms/AppleTVOS.platform/Developer/SDKs", developer_dir);
FileSpec ios_sdk(pathbuf, true);
if (ios_sdk.Exists() && ios_sdk.IsDirectory())
{
directories.push_back (ios_sdk);
}
}
void
PlatformDarwinKernel::GetWatchOSSDKDirectoriesToSearch (std::vector<lldb_private::FileSpec> &directories)
{
// DeveloperDirectory is something like "/Applications/Xcode.app/Contents/Developer"
const char *developer_dir = GetDeveloperDirectory();
if (developer_dir == NULL)
developer_dir = "/Applications/Xcode.app/Contents/Developer";
char pathbuf[PATH_MAX];
::snprintf (pathbuf, sizeof (pathbuf), "%s/Platforms/watchOS.platform/Developer/SDKs", developer_dir);
FileSpec ios_sdk(pathbuf, true);
if (ios_sdk.Exists() && ios_sdk.IsDirectory())
{
directories.push_back (ios_sdk);
}
else
{
::snprintf (pathbuf, sizeof (pathbuf), "%s/Platforms/WatchOS.platform/Developer/SDKs", developer_dir);
FileSpec alt_watch_sdk(pathbuf, true);
if (ios_sdk.Exists() && ios_sdk.IsDirectory())
{
directories.push_back (ios_sdk);
}
}
}
void
PlatformDarwinKernel::GetMacSDKDirectoriesToSearch (std::vector<lldb_private::FileSpec> &directories)
{
// DeveloperDirectory is something like "/Applications/Xcode.app/Contents/Developer"
const char *developer_dir = GetDeveloperDirectory();
if (developer_dir == NULL)
developer_dir = "/Applications/Xcode.app/Contents/Developer";
char pathbuf[PATH_MAX];
::snprintf (pathbuf, sizeof (pathbuf), "%s/Platforms/MacOSX.platform/Developer/SDKs", developer_dir);
FileSpec mac_sdk(pathbuf, true);
if (mac_sdk.Exists() && mac_sdk.IsDirectory())
{
directories.push_back (mac_sdk);
}
}
void
PlatformDarwinKernel::GetGenericSDKDirectoriesToSearch (std::vector<lldb_private::FileSpec> &directories)
{
FileSpec generic_sdk("/AppleInternal/Developer/KDKs", true);
if (generic_sdk.Exists() && generic_sdk.IsDirectory())
{
directories.push_back (generic_sdk);
} }
AddSDKSubdirsToSearchPaths ("/Volumes/KernelDebugKit");
AddSDKSubdirsToSearchPaths ("/AppleInternal/Developer/KDKs");
// The KDKs distributed from Apple installed on external // The KDKs distributed from Apple installed on external
// developer systems may be in directories like // developer systems may be in directories like
// /Library/Developer/KDKs/KDK_10.10_14A298i.kdk // /Library/Developer/KDKs/KDK_10.10_14A298i.kdk
FileSpec installed_kdks("/Library/Developer/KDKs", true); AddSDKSubdirsToSearchPaths ("/Library/Developer/KDKs");
if (installed_kdks.Exists() && installed_kdks.IsDirectory())
if (m_ios_debug_session != eLazyBoolNo)
{ {
directories.push_back (installed_kdks);
} }
if (m_ios_debug_session != eLazyBoolYes)
{
AddRootSubdirsToSearchPaths (this, "/");
}
GetUserSpecifiedDirectoriesToSearch ();
// Add simple directory /Applications/Xcode.app/Contents/Developer/../Symbols
FileSpec possible_dir (developer_dir + "/../Symbols", true);
if (possible_dir.Exists() && possible_dir.IsDirectory())
m_search_directories.push_back (possible_dir);
// Add simple directory of the current working directory
m_search_directories_no_recursing.push_back (FileSpec (".", true));
} }
void void
PlatformDarwinKernel::GetiOSDirectoriesToSearch (std::vector<lldb_private::FileSpec> &directories) PlatformDarwinKernel::GetUserSpecifiedDirectoriesToSearch ()
{
}
void
PlatformDarwinKernel::GetMacDirectoriesToSearch (std::vector<lldb_private::FileSpec> &directories)
{
FileSpec sle("/System/Library/Extensions", true);
if (sle.Exists() && sle.IsDirectory())
{
directories.push_back(sle);
}
FileSpec le("/Library/Extensions", true);
if (le.Exists() && le.IsDirectory())
{
directories.push_back(le);
}
FileSpec kdk("/Volumes/KernelDebugKit", true);
if (kdk.Exists() && kdk.IsDirectory())
{
directories.push_back(kdk);
}
}
void
PlatformDarwinKernel::GetGenericDirectoriesToSearch (std::vector<lldb_private::FileSpec> &directories)
{
// DeveloperDirectory is something like "/Applications/Xcode.app/Contents/Developer"
const char *developer_dir = GetDeveloperDirectory();
if (developer_dir == NULL)
developer_dir = "/Applications/Xcode.app/Contents/Developer";
char pathbuf[PATH_MAX];
::snprintf (pathbuf, sizeof (pathbuf), "%s/../Symbols", developer_dir);
FileSpec symbols_dir (pathbuf, true);
if (symbols_dir.Exists() && symbols_dir.IsDirectory())
{
directories.push_back (symbols_dir);
}
}
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()); FileSpecList user_dirs(GetGlobalProperties()->GetKextDirectories());
std::vector<FileSpec> possible_sdk_dirs; std::vector<FileSpec> possible_sdk_dirs;
@ -585,127 +437,220 @@ PlatformDarwinKernel::GetUserSpecifiedDirectoriesToSearch (std::vector<lldb_priv
dir.ResolvePath(); dir.ResolvePath();
if (dir.Exists() && dir.IsDirectory()) if (dir.Exists() && dir.IsDirectory())
{ {
directories.push_back (dir); m_search_directories.push_back (dir);
possible_sdk_dirs.push_back (dir); // does this directory have a *.sdk or *.kdk that we should look in?
// Is there a "System/Library/Extensions" subdir of this directory?
std::string dir_sle_path = dir.GetPath();
dir_sle_path.append ("/System/Library/Extensions");
FileSpec dir_sle(dir_sle_path.c_str(), true);
if (dir_sle.Exists() && dir_sle.IsDirectory())
{
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);
}
} }
} }
SearchSDKsForKextDirectories (possible_sdk_dirs, directories);
} }
// Scan through the SDK directories, looking for directories where kexts are likely.
// Add those directories to kext_dirs.
void void
PlatformDarwinKernel::SearchSDKsForKextDirectories (std::vector<lldb_private::FileSpec> sdk_dirs, std::vector<lldb_private::FileSpec> &kext_dirs) PlatformDarwinKernel::AddRootSubdirsToSearchPaths (PlatformDarwinKernel *thisp, const std::string &dir)
{ {
const uint32_t num_sdks = sdk_dirs.size(); const char *subdirs[] = {
for (uint32_t i = 0; i < num_sdks; i++) "/System/Library/Extensions",
"/Library/Extensions",
"/System/Library/Kernels",
"/System/Library/Extensions/KDK", // this one probably only exist in /AppleInternal/Developer/KDKs/*.kdk/...
nullptr
};
for (int i = 0; subdirs[i] != nullptr; i++)
{ {
const FileSpec &sdk_dir = sdk_dirs[i]; FileSpec testdir (dir + subdirs[i], true);
std::string sdk_dir_path = sdk_dir.GetPath(); if (testdir.Exists() && testdir.IsDirectory())
if (!sdk_dir_path.empty()) thisp->m_search_directories.push_back (testdir);
}
// Look for kernel binaries in the top level directory, without any recursion
thisp->m_search_directories_no_recursing.push_back (FileSpec (dir + "/", false));
}
// Given a directory path dir, look for any subdirs named *.kdk and *.sdk
void
PlatformDarwinKernel::AddSDKSubdirsToSearchPaths (const std::string &dir)
{
// Look for *.kdk and *.sdk in dir
const bool find_directories = true;
const bool find_files = false;
const bool find_other = false;
FileSpec::EnumerateDirectory (dir.c_str(),
find_directories,
find_files,
find_other,
FindKDKandSDKDirectoriesInDirectory,
this);
}
// Helper function to find *.sdk and *.kdk directories in a given directory.
FileSpec::EnumerateDirectoryResult
PlatformDarwinKernel::FindKDKandSDKDirectoriesInDirectory (void *baton,
FileSpec::FileType file_type,
const FileSpec &file_spec)
{
static ConstString g_sdk_suffix = ConstString ("sdk");
static ConstString g_kdk_suffix = ConstString ("kdk");
PlatformDarwinKernel *thisp = (PlatformDarwinKernel *) baton;
if (file_type == FileSpec::eFileTypeDirectory
&& (file_spec.GetFileNameExtension() == g_sdk_suffix
|| file_spec.GetFileNameExtension() == g_kdk_suffix))
{
AddRootSubdirsToSearchPaths (thisp, file_spec.GetPath());
}
return FileSpec::eEnumerateDirectoryResultNext;
}
// Recursively search trough m_search_directories looking for
// kext and kernel binaries, adding files found to the appropriate
// lists.
void
PlatformDarwinKernel::SearchForKextsAndKernelsRecursively ()
{
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 = true;
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,
GetKernelsAndKextsInDirectoryWithRecursion,
this);
}
const uint32_t num_dirs_no_recurse = m_search_directories_no_recursing.size();
for (uint32_t i = 0; i < num_dirs_no_recurse; i++)
{
const FileSpec &dir = m_search_directories_no_recursing[i];
const bool find_directories = true;
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,
GetKernelsAndKextsInDirectoryNoRecursion,
this);
}
}
// 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.
//
// Recurse into any subdirectories found.
FileSpec::EnumerateDirectoryResult
PlatformDarwinKernel::GetKernelsAndKextsInDirectoryWithRecursion (void *baton,
FileSpec::FileType file_type,
const FileSpec &file_spec)
{
return GetKernelsAndKextsInDirectoryHelper (baton, file_type, file_spec, true);
}
FileSpec::EnumerateDirectoryResult
PlatformDarwinKernel::GetKernelsAndKextsInDirectoryNoRecursion (void *baton,
FileSpec::FileType file_type,
const FileSpec &file_spec)
{
return GetKernelsAndKextsInDirectoryHelper (baton, file_type, file_spec, false);
}
FileSpec::EnumerateDirectoryResult
PlatformDarwinKernel::GetKernelsAndKextsInDirectoryHelper (void *baton,
FileSpec::FileType file_type,
const FileSpec &file_spec,
bool recurse)
{
static ConstString g_kext_suffix = ConstString ("kext");
static ConstString g_dsym_suffix = ConstString ("dSYM");
static ConstString g_bundle_suffix = ConstString ("Bundle");
ConstString file_spec_extension = file_spec.GetFileNameExtension();
Log *log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_PLATFORM));
if (log)
log->Printf ("PlatformDarwinKernel examining %s", file_spec.GetPath().c_str());
PlatformDarwinKernel *thisp = (PlatformDarwinKernel *) baton;
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", 4) == 0)
&& file_spec_extension != g_dsym_suffix)
{
if (KernelHasdSYMSibling (file_spec))
thisp->m_kernel_binaries_with_dsyms.push_back (file_spec);
else
thisp->m_kernel_binaries_without_dsyms.push_back (file_spec);
return FileSpec::eEnumerateDirectoryResultNext;
}
}
else if (file_type == FileSpec::eFileTypeDirectory && file_spec_extension == g_kext_suffix)
{
AddKextToMap (thisp, file_spec);
// Look to see if there is a PlugIns subdir with more kexts
FileSpec contents_plugins (file_spec.GetPath() + "/Contents/PlugIns", false);
std::string search_here_too;
if (contents_plugins.Exists() && contents_plugins.IsDirectory())
{
search_here_too = contents_plugins.GetPath();
}
else
{
FileSpec plugins (file_spec.GetPath() + "/PlugIns", false);
if (plugins.Exists() && plugins.IsDirectory())
{
search_here_too = plugins.GetPath();
}
}
if (!search_here_too.empty())
{ {
const bool find_directories = true; const bool find_directories = true;
const bool find_files = false; const bool find_files = false;
const bool find_other = false; const bool find_other = false;
FileSpec::EnumerateDirectory (sdk_dir_path.c_str(), FileSpec::EnumerateDirectory (search_here_too.c_str(),
find_directories, find_directories,
find_files, find_files,
find_other, find_other,
GetKextDirectoriesInSDK, recurse ? GetKernelsAndKextsInDirectoryWithRecursion : GetKernelsAndKextsInDirectoryNoRecursion,
&kext_dirs); baton);
} }
return FileSpec::eEnumerateDirectoryResultNext;
}
// Don't recurse into dSYM/kext/bundle directories
if (recurse
&& file_spec_extension != g_dsym_suffix
&& file_spec_extension != g_kext_suffix
&& file_spec_extension != g_bundle_suffix)
{
return FileSpec::eEnumerateDirectoryResultEnter;
}
else
{
return FileSpec::eEnumerateDirectoryResultNext;
} }
} }
// Callback for FileSpec::EnumerateDirectory(). void
// Step through the entries in a directory like PlatformDarwinKernel::AddKextToMap (PlatformDarwinKernel *thisp, const FileSpec &file_spec)
// /Applications/Xcode.app//Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs
// looking for any subdirectories of the form MacOSX10.8.Internal.sdk/System/Library/Extensions
// Adds these to the vector of FileSpec's.
FileSpec::EnumerateDirectoryResult
PlatformDarwinKernel::GetKextDirectoriesInSDK (void *baton,
FileSpec::FileType file_type,
const FileSpec &file_spec)
{ {
if (file_type == FileSpec::eFileTypeDirectory CFCBundle bundle (file_spec.GetPath().c_str());
&& (file_spec.GetFileNameExtension() == ConstString("sdk") CFStringRef bundle_id (bundle.GetIdentifier());
|| file_spec.GetFileNameExtension() == ConstString("kdk"))) if (bundle_id && CFGetTypeID (bundle_id) == CFStringGetTypeID ())
{ {
std::string kext_directory_path = file_spec.GetPath(); char bundle_id_buf[PATH_MAX];
if (CFStringGetCString (bundle_id, bundle_id_buf, sizeof (bundle_id_buf), kCFStringEncodingUTF8))
// Append the raw directory path, e.g. /Library/Developer/KDKs/KDK_10.10_14A298i.kdk
// to the directory search list -- there may be kexts sitting directly
// in that directory instead of being in a System/Library/Extensions subdir.
((std::vector<lldb_private::FileSpec> *)baton)->push_back(file_spec);
// Check to see if there is a System/Library/Extensions subdir & add it if it exists
std::string sle_kext_directory_path (kext_directory_path);
sle_kext_directory_path.append ("/System/Library/Extensions");
FileSpec sle_kext_directory (sle_kext_directory_path.c_str(), true);
if (sle_kext_directory.Exists() && sle_kext_directory.IsDirectory())
{ {
((std::vector<lldb_private::FileSpec> *)baton)->push_back(sle_kext_directory); ConstString bundle_conststr(bundle_id_buf);
} if (KextHasdSYMSibling (file_spec))
thisp->m_name_to_kext_path_map_with_dsyms.insert(std::pair<ConstString, FileSpec>(bundle_conststr, file_spec));
// Check to see if there is a Library/Extensions subdir & add it if it exists else
thisp->m_name_to_kext_path_map_without_dsyms.insert(std::pair<ConstString, FileSpec>(bundle_conststr, file_spec));
std::string le_kext_directory_path (kext_directory_path);
le_kext_directory_path.append ("/Library/Extensions");
FileSpec le_kext_directory (le_kext_directory_path.c_str(), true);
if (le_kext_directory.Exists() && le_kext_directory.IsDirectory())
{
((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;
} }
// Given a FileSpec of /dir/dir/foo.kext // Given a FileSpec of /dir/dir/foo.kext
@ -767,151 +712,6 @@ PlatformDarwinKernel::KernelHasdSYMSibling (const FileSpec &kernel_binary)
return false; return false;
} }
void
PlatformDarwinKernel::IndexKextsInDirectories ()
{
std::vector<FileSpec> kext_bundles;
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 = true;
const bool find_files = false;
const bool find_other = false;
FileSpec::EnumerateDirectory (dir.GetPath().c_str(),
find_directories,
find_files,
find_other,
GetKextsInDirectory,
&kext_bundles);
}
const uint32_t num_kexts = kext_bundles.size();
for (uint32_t i = 0; i < num_kexts; i++)
{
const FileSpec &kext = kext_bundles[i];
CFCBundle bundle (kext.GetPath().c_str());
CFStringRef bundle_id (bundle.GetIdentifier());
if (bundle_id && CFGetTypeID (bundle_id) == CFStringGetTypeID ())
{
char bundle_id_buf[PATH_MAX];
if (CFStringGetCString (bundle_id, bundle_id_buf, sizeof (bundle_id_buf), kCFStringEncodingUTF8))
{
ConstString bundle_conststr(bundle_id_buf);
if (KextHasdSYMSibling (kext))
m_name_to_kext_path_map_with_dsyms.insert(std::pair<ConstString, FileSpec>(bundle_conststr, kext));
else
m_name_to_kext_path_map_without_dsyms.insert(std::pair<ConstString, FileSpec>(bundle_conststr, kext));
}
}
}
}
// Callback for FileSpec::EnumerateDirectory().
// Step through the entries in a directory like /System/Library/Extensions, find .kext bundles, add them
// to the vector of FileSpecs.
// If a .kext bundle has a Contents/PlugIns or PlugIns subdir, search for kexts in there too.
FileSpec::EnumerateDirectoryResult
PlatformDarwinKernel::GetKextsInDirectory (void *baton,
FileSpec::FileType file_type,
const FileSpec &file_spec)
{
if (file_type == FileSpec::eFileTypeDirectory && file_spec.GetFileNameExtension() == ConstString("kext"))
{
((std::vector<lldb_private::FileSpec> *)baton)->push_back(file_spec);
std::string kext_bundle_path = file_spec.GetPath();
std::string search_here_too;
std::string contents_plugins_path = kext_bundle_path + "/Contents/PlugIns";
FileSpec contents_plugins (contents_plugins_path.c_str(), false);
if (contents_plugins.Exists() && contents_plugins.IsDirectory())
{
search_here_too = contents_plugins_path;
}
else
{
std::string plugins_path = kext_bundle_path + "/PlugIns";
FileSpec plugins (plugins_path.c_str(), false);
if (plugins.Exists() && plugins.IsDirectory())
{
search_here_too = plugins_path;
}
}
if (!search_here_too.empty())
{
const bool find_directories = true;
const bool find_files = false;
const bool find_other = false;
FileSpec::EnumerateDirectory (search_here_too.c_str(),
find_directories,
find_files,
find_other,
GetKextsInDirectory,
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,
&kernels);
}
size_t kernels_size = kernels.size();
for (size_t i = 0; i < kernels_size; i++)
{
if (KernelHasdSYMSibling (kernels[i]))
m_kernel_binaries_with_dsyms.push_back (kernels[i]);
else
m_kernel_binaries_without_dsyms.push_back (kernels[i]);
}
}
// Callback for FileSpec::EnumerateDirectory().
// Step through the entries in a directory like /System/Library/Kernels/, find kernel binaries,
// add them to m_kernel_binaries_with_dsyms and m_kernel_binaries_without_dsyms.
// 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", 4) == 0)
{
((std::vector<lldb_private::FileSpec> *)baton)->push_back(file_spec);
}
}
return FileSpec::eEnumerateDirectoryResultNext;
}
Error Error
PlatformDarwinKernel::GetSharedModule (const ModuleSpec &module_spec, PlatformDarwinKernel::GetSharedModule (const ModuleSpec &module_spec,

View File

@ -115,100 +115,59 @@ protected:
typedef DirectoriesSearchedCollection::iterator DirectoriesSearchedIterator; typedef DirectoriesSearchedCollection::iterator DirectoriesSearchedIterator;
static lldb_private::FileSpec::EnumerateDirectoryResult // Populate m_search_directories and m_search_directories_no_recursing vectors of directories
GetKextDirectoriesInSDK (void *baton,
lldb_private::FileSpec::FileType file_type,
const lldb_private::FileSpec &file_spec);
static lldb_private::FileSpec::EnumerateDirectoryResult
GetKextsInDirectory (void *baton,
lldb_private::FileSpec::FileType file_type,
const lldb_private::FileSpec &file_spec);
// Populate m_search_directories vector of directories
void void
CollectKextAndKernelDirectories (); CollectKextAndKernelDirectories ();
// Directories where we may find iOS SDKs with kext bundles in them
void void
GetiOSSDKDirectoriesToSearch (std::vector<lldb_private::FileSpec> &directories); GetUserSpecifiedDirectoriesToSearch ();
// Directories where we may find AppleTVOS SDKs with kext bundles in them static void
void AddRootSubdirsToSearchPaths (PlatformDarwinKernel *thisp, const std::string &dir);
GetAppleTVOSSDKDirectoriesToSearch (std::vector<lldb_private::FileSpec> &directories);
// Directories where we may find WatchOS SDKs with kext bundles in them
void void
GetWatchOSSDKDirectoriesToSearch (std::vector<lldb_private::FileSpec> &directories); AddSDKSubdirsToSearchPaths (const std::string &dir);
// Directories where we may find Mac OS X SDKs with kext bundles in them static lldb_private::FileSpec::EnumerateDirectoryResult
void FindKDKandSDKDirectoriesInDirectory (void *baton, lldb_private::FileSpec::FileType file_type, const lldb_private::FileSpec &file_spec);
GetMacSDKDirectoriesToSearch (std::vector<lldb_private::FileSpec> &directories);
// Directories where we may find Mac OS X or iOS SDKs with kext bundles in them
void
GetGenericSDKDirectoriesToSearch (std::vector<lldb_private::FileSpec> &directories);
// Directories where we may find iOS kext bundles
void
GetiOSDirectoriesToSearch (std::vector<lldb_private::FileSpec> &directories);
// Directories where we may find MacOSX kext bundles
void
GetMacDirectoriesToSearch (std::vector<lldb_private::FileSpec> &directories);
// Directories where we may find iOS or MacOSX kext bundles
void
GetGenericDirectoriesToSearch (std::vector<lldb_private::FileSpec> &directories);
// Directories specified via the "kext-directories" setting - maybe KDK/SDKs, may be plain directories
void
GetUserSpecifiedDirectoriesToSearch (std::vector<lldb_private::FileSpec> &directories);
void void
GetCurrentDirectoryToSearch (std::vector<lldb_private::FileSpec> &directories); SearchForKextsAndKernelsRecursively ();
// Directories where we may find kernels exclusively static lldb_private::FileSpec::EnumerateDirectoryResult
void GetKernelsAndKextsInDirectoryWithRecursion (void *baton, lldb_private::FileSpec::FileType file_type, const lldb_private::FileSpec &file_spec);
GetKernelDirectoriesToSearch (std::vector<lldb_private::FileSpec> &directories);
// Search through a vector of SDK FileSpecs, add any directories that may contain kexts static lldb_private::FileSpec::EnumerateDirectoryResult
// to the vector of kext dir FileSpecs GetKernelsAndKextsInDirectoryNoRecursion (void *baton, lldb_private::FileSpec::FileType file_type, const lldb_private::FileSpec &file_spec);
void
SearchSDKsForKextDirectories (std::vector<lldb_private::FileSpec> sdk_dirs, std::vector<lldb_private::FileSpec> &kext_dirs); static lldb_private::FileSpec::EnumerateDirectoryResult
GetKernelsAndKextsInDirectoryHelper (void *baton, lldb_private::FileSpec::FileType file_type, const lldb_private::FileSpec &file_spec, bool recurse);
static void
AddKextToMap (PlatformDarwinKernel *thisp, const lldb_private::FileSpec &file_spec);
// Returns true if there is a .dSYM bundle next to the kext, or next to the binary inside the kext. // Returns true if there is a .dSYM bundle next to the kext, or next to the binary inside the kext.
bool static bool
KextHasdSYMSibling (const lldb_private::FileSpec &kext_bundle_filepath); KextHasdSYMSibling (const lldb_private::FileSpec &kext_bundle_filepath);
// Returns true if there is a .dSYM bundle next to the kernel // Returns true if there is a .dSYM bundle next to the kernel
bool static bool
KernelHasdSYMSibling (const lldb_private::FileSpec &kext_bundle_filepath); KernelHasdSYMSibling (const lldb_private::FileSpec &kext_bundle_filepath);
// 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 ();
// 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 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); ExamineKextForMatchingUUID (const lldb_private::FileSpec &kext_bundle_path, const lldb_private::UUID &uuid, const lldb_private::ArchSpec &arch, lldb::ModuleSP &exe_module_sp);
private: // Most of the ivars are assembled under FileSpec::EnumerateDirectory calls where the
// function being called for each file/directory must be static. We'll pass a this pointer
// as a baton and access the ivars directly. Toss-up whether this should just be a struct
// at this point.
public:
BundleIDToKextMap m_name_to_kext_path_map_with_dsyms; // multimap of CFBundleID to FileSpec on local filesystem, kexts with dSYMs next to them BundleIDToKextMap m_name_to_kext_path_map_with_dsyms; // multimap of CFBundleID to FileSpec on local filesystem, kexts with dSYMs next to them
BundleIDToKextMap m_name_to_kext_path_map_without_dsyms; // multimap of CFBundleID to FileSpec on local filesystem, kexts without dSYMs next to them BundleIDToKextMap m_name_to_kext_path_map_without_dsyms; // multimap of CFBundleID to FileSpec on local filesystem, kexts without dSYMs next to them
DirectoriesSearchedCollection m_search_directories; // list of directories we search for kexts/kernels DirectoriesSearchedCollection m_search_directories; // list of directories we search for kexts/kernels
DirectoriesSearchedCollection m_search_directories_no_recursing; // list of directories we search for kexts/kernels, no recursion
KernelBinaryCollection m_kernel_binaries_with_dsyms; // list of kernel binaries we found on local filesystem, without dSYMs next to them KernelBinaryCollection m_kernel_binaries_with_dsyms; // list of kernel binaries we found on local filesystem, without dSYMs next to them
KernelBinaryCollection m_kernel_binaries_without_dsyms; // list of kernel binaries we found on local filesystem, with dSYMs next to them KernelBinaryCollection m_kernel_binaries_without_dsyms; // list of kernel binaries we found on local filesystem, with dSYMs next to them
lldb_private::LazyBool m_ios_debug_session; lldb_private::LazyBool m_ios_debug_session;