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
RegisterPlugin (const char *name,
const char *description,
PlatformCreateInstance create_callback);
PlatformCreateInstance create_callback,
DebuggerInitializeCallback debugger_init_callback = NULL);
static bool
UnregisterPlugin (PlatformCreateInstance create_callback);
@ -299,7 +300,7 @@ public:
// callback when registering the plug-in. After a new Debugger
// instance is created, this DebuggerInitialize function will get
// 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
DebuggerInitialize (Debugger &debugger);
@ -313,6 +314,16 @@ public:
const lldb::OptionValuePropertiesSP &properties_sp,
const ConstString &description,
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() :
name(),
description(),
create_callback(NULL)
create_callback(NULL),
debugger_init_callback (NULL)
{
}
std::string name;
std::string description;
PlatformCreateInstance create_callback;
DebuggerInitializeCallback debugger_init_callback;
};
typedef std::vector<PlatformInstance> PlatformInstances;
@ -1258,7 +1260,8 @@ GetPlatformInstances ()
bool
PluginManager::RegisterPlugin (const char *name,
const char *description,
PlatformCreateInstance create_callback)
PlatformCreateInstance create_callback,
DebuggerInitializeCallback debugger_init_callback)
{
if (create_callback)
{
@ -1270,12 +1273,14 @@ PluginManager::RegisterPlugin (const char *name,
if (description && description[0])
instance.description = description;
instance.create_callback = create_callback;
instance.debugger_init_callback = debugger_init_callback;
GetPlatformInstances ().push_back (instance);
return true;
}
return false;
}
const char *
PluginManager::GetPlatformPluginNameAtIndex (uint32_t idx)
{
@ -1365,7 +1370,6 @@ PluginManager::AutoCompletePlatformName (const char *name, StringList &matches)
}
return matches.GetSize();
}
#pragma mark Process
struct ProcessInstance
@ -1813,14 +1817,30 @@ PluginManager::GetUnwindAssemblyCreateCallbackForPluginName (const char *name)
void
PluginManager::DebuggerInitialize (Debugger &debugger)
{
Mutex::Locker locker (GetDynamicLoaderMutex ());
DynamicLoaderInstances &instances = GetDynamicLoaderInstances ();
DynamicLoaderInstances::iterator pos, end = instances.end();
for (pos = instances.begin(); pos != end; ++ pos)
// Initialize the DynamicLoader plugins
{
if (pos->debugger_init_callback)
pos->debugger_init_callback (debugger);
Mutex::Locker locker (GetDynamicLoaderMutex ());
DynamicLoaderInstances &instances = GetDynamicLoaderInstances ();
DynamicLoaderInstances::iterator pos, end = instances.end();
for (pos = instances.begin(); pos != end; ++ pos)
{
if (pos->debugger_init_callback)
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);
}
}
}
@ -1899,3 +1919,41 @@ PluginManager::CreateSettingForDynamicLoaderPlugin (Debugger &debugger,
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/Host/FileSpec.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/Target.h"
@ -51,7 +55,8 @@ PlatformDarwinKernel::Initialize ()
{
PluginManager::RegisterPlugin (PlatformDarwinKernel::GetShortPluginNameStatic(),
PlatformDarwinKernel::GetDescriptionStatic(),
PlatformDarwinKernel::CreateInstance);
PlatformDarwinKernel::CreateInstance,
PlatformDarwinKernel::DebuggerInitialize);
}
}
@ -160,6 +165,88 @@ PlatformDarwinKernel::GetDescriptionStatic()
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
@ -171,7 +258,10 @@ PlatformDarwinKernel::PlatformDarwinKernel (lldb_private::LazyBool is_ios_debug_
m_ios_debug_session(is_ios_debug_session)
{
SearchForKexts ();
if (GetGlobalProperties()->GetSearchForKexts())
{
SearchForKexts ();
}
}
//------------------------------------------------------------------
@ -201,7 +291,7 @@ PlatformDarwinKernel::GetStatus (Stream &strm)
{
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,
kdk_dir.GetDirectory().GetCString(),
kdk_dir.GetFilename().GetCString());
@ -238,6 +328,8 @@ PlatformDarwinKernel::SearchForKexts ()
GetGenericDirectoriesToSearch (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;
@ -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.
// Add those directories to kext_dirs.
void
@ -379,6 +500,7 @@ void
PlatformDarwinKernel::IndexKextsInDirectories (std::vector<lldb_private::FileSpec> kext_dirs)
{
std::vector<FileSpec> kext_bundles;
const uint32_t num_dirs = kext_dirs.size();
for (uint32_t i = 0; i < num_dirs; i++)
{

View File

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