Add support for Platform plugins to have settings.

Add two initial settings for the PlatformDarwinKernel plugin,

plugin.platform.darwin-kernel.search-locally-for-kexts [true|false]
plugin.platform.darwin-kernel.kext-directories [directory list]

llvm-svn: 178846
This commit is contained in:
Jason Molenda 2013-04-05 05:06:39 +00:00
parent e6f48e4e2f
commit 9b837a1e42
4 changed files with 213 additions and 15 deletions

View File

@ -199,7 +199,8 @@ public:
static bool static bool
RegisterPlugin (const char *name, RegisterPlugin (const char *name,
const char *description, const char *description,
PlatformCreateInstance create_callback); PlatformCreateInstance create_callback,
DebuggerInitializeCallback debugger_init_callback = NULL);
static bool static bool
UnregisterPlugin (PlatformCreateInstance create_callback); UnregisterPlugin (PlatformCreateInstance create_callback);
@ -299,7 +300,7 @@ public:
// callback when registering the plug-in. After a new Debugger // callback when registering the plug-in. After a new Debugger
// instance is created, this DebuggerInitialize function will get // instance is created, this DebuggerInitialize function will get
// called. This allows plug-ins to install Properties and do any // called. This allows plug-ins to install Properties and do any
// other intialization that requires a debugger instance. // other initialization that requires a debugger instance.
//------------------------------------------------------------------ //------------------------------------------------------------------
static void static void
DebuggerInitialize (Debugger &debugger); DebuggerInitialize (Debugger &debugger);
@ -313,6 +314,16 @@ public:
const lldb::OptionValuePropertiesSP &properties_sp, const lldb::OptionValuePropertiesSP &properties_sp,
const ConstString &description, const ConstString &description,
bool is_global_property); bool is_global_property);
static lldb::OptionValuePropertiesSP
GetSettingForPlatformPlugin (Debugger &debugger,
const ConstString &setting_name);
static bool
CreateSettingForPlatformPlugin (Debugger &debugger,
const lldb::OptionValuePropertiesSP &properties_sp,
const ConstString &description,
bool is_global_property);
}; };

View File

@ -1229,13 +1229,15 @@ struct PlatformInstance
PlatformInstance() : PlatformInstance() :
name(), name(),
description(), description(),
create_callback(NULL) create_callback(NULL),
debugger_init_callback (NULL)
{ {
} }
std::string name; std::string name;
std::string description; std::string description;
PlatformCreateInstance create_callback; PlatformCreateInstance create_callback;
DebuggerInitializeCallback debugger_init_callback;
}; };
typedef std::vector<PlatformInstance> PlatformInstances; typedef std::vector<PlatformInstance> PlatformInstances;
@ -1258,7 +1260,8 @@ GetPlatformInstances ()
bool bool
PluginManager::RegisterPlugin (const char *name, PluginManager::RegisterPlugin (const char *name,
const char *description, const char *description,
PlatformCreateInstance create_callback) PlatformCreateInstance create_callback,
DebuggerInitializeCallback debugger_init_callback)
{ {
if (create_callback) if (create_callback)
{ {
@ -1270,12 +1273,14 @@ PluginManager::RegisterPlugin (const char *name,
if (description && description[0]) if (description && description[0])
instance.description = description; instance.description = description;
instance.create_callback = create_callback; instance.create_callback = create_callback;
instance.debugger_init_callback = debugger_init_callback;
GetPlatformInstances ().push_back (instance); GetPlatformInstances ().push_back (instance);
return true; return true;
} }
return false; return false;
} }
const char * const char *
PluginManager::GetPlatformPluginNameAtIndex (uint32_t idx) PluginManager::GetPlatformPluginNameAtIndex (uint32_t idx)
{ {
@ -1365,7 +1370,6 @@ PluginManager::AutoCompletePlatformName (const char *name, StringList &matches)
} }
return matches.GetSize(); return matches.GetSize();
} }
#pragma mark Process #pragma mark Process
struct ProcessInstance struct ProcessInstance
@ -1813,6 +1817,8 @@ PluginManager::GetUnwindAssemblyCreateCallbackForPluginName (const char *name)
void void
PluginManager::DebuggerInitialize (Debugger &debugger) PluginManager::DebuggerInitialize (Debugger &debugger)
{ {
// Initialize the DynamicLoader plugins
{
Mutex::Locker locker (GetDynamicLoaderMutex ()); Mutex::Locker locker (GetDynamicLoaderMutex ());
DynamicLoaderInstances &instances = GetDynamicLoaderInstances (); DynamicLoaderInstances &instances = GetDynamicLoaderInstances ();
@ -1822,6 +1828,20 @@ PluginManager::DebuggerInitialize (Debugger &debugger)
if (pos->debugger_init_callback) if (pos->debugger_init_callback)
pos->debugger_init_callback (debugger); pos->debugger_init_callback (debugger);
} }
}
// Initialize the Platform plugins
{
Mutex::Locker locker (GetPlatformInstancesMutex ());
PlatformInstances &instances = GetPlatformInstances ();
PlatformInstances::iterator pos, end = instances.end();
for (pos = instances.begin(); pos != end; ++ pos)
{
if (pos->debugger_init_callback)
pos->debugger_init_callback (debugger);
}
}
} }
static lldb::OptionValuePropertiesSP static lldb::OptionValuePropertiesSP
@ -1899,3 +1919,41 @@ PluginManager::CreateSettingForDynamicLoaderPlugin (Debugger &debugger,
return false; return false;
} }
lldb::OptionValuePropertiesSP
PluginManager::GetSettingForPlatformPlugin (Debugger &debugger, const ConstString &setting_name)
{
lldb::OptionValuePropertiesSP properties_sp;
lldb::OptionValuePropertiesSP plugin_type_properties_sp (GetDebuggerPropertyForPlugins (debugger,
ConstString("platform"),
ConstString(), // not creating to so we don't need the description
false));
if (plugin_type_properties_sp)
properties_sp = plugin_type_properties_sp->GetSubProperty (NULL, setting_name);
return properties_sp;
}
bool
PluginManager::CreateSettingForPlatformPlugin (Debugger &debugger,
const lldb::OptionValuePropertiesSP &properties_sp,
const ConstString &description,
bool is_global_property)
{
if (properties_sp)
{
lldb::OptionValuePropertiesSP plugin_type_properties_sp (GetDebuggerPropertyForPlugins (debugger,
ConstString("platform"),
ConstString("Settings for platform plug-ins"),
true));
if (plugin_type_properties_sp)
{
plugin_type_properties_sp->AppendProperty (properties_sp->GetName(),
description,
is_global_property,
properties_sp);
return true;
}
}
return false;
}

View File

@ -26,6 +26,10 @@
#include "lldb/Core/StreamString.h" #include "lldb/Core/StreamString.h"
#include "lldb/Host/FileSpec.h" #include "lldb/Host/FileSpec.h"
#include "lldb/Host/Host.h" #include "lldb/Host/Host.h"
#include "lldb/Interpreter/OptionValueFileSpecList.h"
#include "lldb/Interpreter/OptionValueProperties.h"
#include "lldb/Interpreter/Property.h"
#include "lldb/Target/Platform.h"
#include "lldb/Target/Process.h" #include "lldb/Target/Process.h"
#include "lldb/Target/Target.h" #include "lldb/Target/Target.h"
@ -51,7 +55,8 @@ PlatformDarwinKernel::Initialize ()
{ {
PluginManager::RegisterPlugin (PlatformDarwinKernel::GetShortPluginNameStatic(), PluginManager::RegisterPlugin (PlatformDarwinKernel::GetShortPluginNameStatic(),
PlatformDarwinKernel::GetDescriptionStatic(), PlatformDarwinKernel::GetDescriptionStatic(),
PlatformDarwinKernel::CreateInstance); PlatformDarwinKernel::CreateInstance,
PlatformDarwinKernel::DebuggerInitialize);
} }
} }
@ -160,6 +165,88 @@ PlatformDarwinKernel::GetDescriptionStatic()
return "Darwin Kernel platform plug-in."; return "Darwin Kernel platform plug-in.";
} }
//------------------------------------------------------------------
/// Code to handle the PlatformDarwinKernel settings
//------------------------------------------------------------------
static PropertyDefinition
g_properties[] =
{
{ "search-locally-for-kexts" , OptionValue::eTypeBoolean, true, true, NULL, NULL, "Automatically search for kexts on the local system when doing kernel debugging." },
{ "kext-directories", OptionValue::eTypeFileSpecList, false, 0, NULL, NULL, "Directories/KDKs to search for kexts in when starting a kernel debug session." },
{ NULL , OptionValue::eTypeInvalid, false, 0 , NULL, NULL, NULL }
};
enum {
ePropertySearchForKexts = 0,
ePropertyKextDirectories
};
class PlatformDarwinKernelProperties : public Properties
{
public:
static ConstString &
GetSettingName ()
{
static ConstString g_setting_name("darwin-kernel");
return g_setting_name;
}
PlatformDarwinKernelProperties() :
Properties ()
{
m_collection_sp.reset (new OptionValueProperties(GetSettingName()));
m_collection_sp->Initialize(g_properties);
}
virtual
~PlatformDarwinKernelProperties()
{
}
bool
GetSearchForKexts() const
{
const uint32_t idx = ePropertySearchForKexts;
return m_collection_sp->GetPropertyAtIndexAsBoolean (NULL, idx, g_properties[idx].default_uint_value != 0);
}
FileSpecList &
GetKextDirectories() const
{
const uint32_t idx = ePropertyKextDirectories;
OptionValueFileSpecList *option_value = m_collection_sp->GetPropertyAtIndexAsOptionValueFileSpecList (NULL, false, idx);
assert(option_value);
return option_value->GetCurrentValue();
}
};
typedef STD_SHARED_PTR(PlatformDarwinKernelProperties) PlatformDarwinKernelPropertiesSP;
static const PlatformDarwinKernelPropertiesSP &
GetGlobalProperties()
{
static PlatformDarwinKernelPropertiesSP g_settings_sp;
if (!g_settings_sp)
g_settings_sp.reset (new PlatformDarwinKernelProperties ());
return g_settings_sp;
}
void
PlatformDarwinKernel::DebuggerInitialize (lldb_private::Debugger &debugger)
{
if (!PluginManager::GetSettingForPlatformPlugin (debugger, PlatformDarwinKernelProperties::GetSettingName()))
{
const bool is_global_setting = true;
PluginManager::CreateSettingForPlatformPlugin (debugger,
GetGlobalProperties()->GetValueProperties(),
ConstString ("Properties for the PlatformDarwinKernel plug-in."),
is_global_setting);
}
}
//------------------------------------------------------------------ //------------------------------------------------------------------
/// Default Constructor /// Default Constructor
@ -171,7 +258,10 @@ PlatformDarwinKernel::PlatformDarwinKernel (lldb_private::LazyBool is_ios_debug_
m_ios_debug_session(is_ios_debug_session) m_ios_debug_session(is_ios_debug_session)
{ {
if (GetGlobalProperties()->GetSearchForKexts())
{
SearchForKexts (); SearchForKexts ();
}
} }
//------------------------------------------------------------------ //------------------------------------------------------------------
@ -201,7 +291,7 @@ PlatformDarwinKernel::GetStatus (Stream &strm)
{ {
const FileSpec &kdk_dir = m_directories_searched[i]; const FileSpec &kdk_dir = m_directories_searched[i];
strm.Printf (" KDK Roots: [%2u] \"%s/%s\"\n", strm.Printf (" Kext directories: [%2u] \"%s/%s\"\n",
i, i,
kdk_dir.GetDirectory().GetCString(), kdk_dir.GetDirectory().GetCString(),
kdk_dir.GetFilename().GetCString()); kdk_dir.GetFilename().GetCString());
@ -238,6 +328,8 @@ PlatformDarwinKernel::SearchForKexts ()
GetGenericDirectoriesToSearch (kext_dirs); GetGenericDirectoriesToSearch (kext_dirs);
GetUserSpecifiedDirectoriesToSearch (kext_dirs);
// We now have a complete list of directories that we will search for kext bundles // We now have a complete list of directories that we will search for kext bundles
m_directories_searched = kext_dirs; m_directories_searched = kext_dirs;
@ -320,6 +412,35 @@ PlatformDarwinKernel::GetGenericDirectoriesToSearch (std::vector<lldb_private::F
} }
} }
void
PlatformDarwinKernel::GetUserSpecifiedDirectoriesToSearch (std::vector<lldb_private::FileSpec> &directories)
{
FileSpecList user_dirs(GetGlobalProperties()->GetKextDirectories());
std::vector<FileSpec> possible_sdk_dirs;
const uint32_t user_dirs_count = user_dirs.GetSize();
for (uint32_t i = 0; i < user_dirs_count; i++)
{
const FileSpec &dir = user_dirs.GetFileSpecAtIndex (i);
if (dir.Exists() && dir.GetFileType() == FileSpec::eFileTypeDirectory)
{
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?
char pathbuf[PATH_MAX];
::snprintf (pathbuf, sizeof (pathbuf), "%s/%s/System/Library/Extensions", dir.GetDirectory().GetCString(), dir.GetFilename().GetCString());
FileSpec dir_sle(pathbuf, true);
if (dir_sle.Exists() && dir_sle.GetFileType() == FileSpec::eFileTypeDirectory)
{
directories.push_back (dir_sle);
}
}
}
SearchSDKsForKextDirectories (possible_sdk_dirs, directories);
}
// Scan through the SDK directories, looking for directories where kexts are likely. // Scan through the SDK directories, looking for directories where kexts are likely.
// Add those directories to kext_dirs. // Add those directories to kext_dirs.
void void
@ -379,6 +500,7 @@ void
PlatformDarwinKernel::IndexKextsInDirectories (std::vector<lldb_private::FileSpec> kext_dirs) PlatformDarwinKernel::IndexKextsInDirectories (std::vector<lldb_private::FileSpec> kext_dirs)
{ {
std::vector<FileSpec> kext_bundles; std::vector<FileSpec> kext_bundles;
const uint32_t num_dirs = kext_dirs.size(); const uint32_t num_dirs = kext_dirs.size();
for (uint32_t i = 0; i < num_dirs; i++) for (uint32_t i = 0; i < num_dirs; i++)
{ {

View File

@ -31,6 +31,9 @@ public:
static lldb_private::Platform* static lldb_private::Platform*
CreateInstance (bool force, const lldb_private::ArchSpec *arch); CreateInstance (bool force, const lldb_private::ArchSpec *arch);
static void
DebuggerInitialize (lldb_private::Debugger &debugger);
static void static void
Initialize (); Initialize ();
@ -148,6 +151,10 @@ protected:
void void
GetGenericDirectoriesToSearch (std::vector<lldb_private::FileSpec> &directories); 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);
// Search through a vector of SDK FileSpecs, add any directories that may contain kexts // Search through a vector of SDK FileSpecs, add any directories that may contain kexts
// to the vector of kext dir FileSpecs // to the vector of kext dir FileSpecs
void void