Added the infrastructure necessary for plug-ins to be able to add their own settings instead of having settings added to existing ones. In particular "target.disable-kext-loading" was added to "target" where it should actually be specific to the the dynamic loader plugin. Now the plug-in manager has the ability to create settings at the root level starting with "plugin". Each plug-in type can add new sub dictionaries, and then each plug-in can register a setting dictionary under its own short name. For example the DynamicLoaderDarwinKernel plug-in now registers a setting dictionary at:

plugin
    dynamic-loader
        macosx-kernel
            (bool) disable-kext-loading
            
To settings can be set using:

(lldb) settings set plugin.dynamic-loader.macosx-kernel.disable-kext-loading true

I currently only hooked up the DynamicLoader plug-ins, but the code is very easy to duplicate when and if we need settings for other plug-ins.

llvm-svn: 166294
This commit is contained in:
Greg Clayton 2012-10-19 18:02:49 +00:00
parent db97454f8e
commit e8cd0c9859
12 changed files with 231 additions and 30 deletions

View File

@ -67,7 +67,8 @@ public:
static bool
RegisterPlugin (const char *name,
const char *description,
DynamicLoaderCreateInstance create_callback);
DynamicLoaderCreateInstance create_callback,
DebuggerInitializeCallback debugger_init_callback = NULL);
static bool
UnregisterPlugin (DynamicLoaderCreateInstance create_callback);
@ -78,7 +79,6 @@ public:
static DynamicLoaderCreateInstance
GetDynamicLoaderCreateCallbackForPluginName (const char *name);
//------------------------------------------------------------------
// EmulateInstruction
//------------------------------------------------------------------
@ -294,6 +294,25 @@ public:
static UnwindAssemblyCreateInstance
GetUnwindAssemblyCreateCallbackForPluginName (const char *name);
//------------------------------------------------------------------
// Some plug-ins might register a DebuggerInitializeCallback
// 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.
//------------------------------------------------------------------
static void
DebuggerInitialize (Debugger &debugger);
static lldb::OptionValuePropertiesSP
GetSettingForDynamicLoaderPlugin (Debugger &debugger,
const ConstString &setting_name);
static bool
CreateSettingForDynamicLoaderPlugin (Debugger &debugger,
const lldb::OptionValuePropertiesSP &properties_sp,
const ConstString &description,
bool is_global_property);
};

View File

@ -86,6 +86,9 @@ public:
Apropos (const char *keyword,
std::vector<const Property *> &matching_properties) const;
lldb::OptionValuePropertiesSP
GetSubProperty (const ExecutionContext *exe_ctx,
const ConstString &name);
protected:
lldb::OptionValuePropertiesSP m_collection_sp;
};

View File

@ -235,7 +235,10 @@ public:
bool is_global,
const lldb::OptionValueSP &value_sp);
lldb::OptionValuePropertiesSP
GetSubProperty (const ExecutionContext *exe_ctx,
const ConstString &name);
protected:
const Property *

View File

@ -140,11 +140,6 @@ public:
const char *
GetExpressionPrefixContentsAsCString ();
bool
GetDisableKextLoading () const;
void
SetDisableKextLoading (bool b);
};
typedef STD_SHARED_PTR(TargetProperties) TargetPropertiesSP;

View File

@ -36,6 +36,7 @@ namespace lldb_private
typedef UnwindAssembly* (*UnwindAssemblyCreateInstance) (const ArchSpec &arch);
typedef int (*ComparisonFunction)(const void *, const void *);
typedef bool (*CommandOverrideCallback)(void *baton, const char **argv);
typedef void (*DebuggerInitializeCallback)(Debugger &debugger);
} // namespace lldb_private

View File

@ -22,6 +22,7 @@
#include "lldb/Core/FormatManager.h"
#include "lldb/Core/InputReader.h"
#include "lldb/Core/Module.h"
#include "lldb/Core/PluginManager.h"
#include "lldb/Core/RegisterValue.h"
#include "lldb/Core/State.h"
#include "lldb/Core/StreamAsynchronousIO.h"
@ -125,7 +126,8 @@ g_properties[] =
{ "term-width", OptionValue::eTypeSInt64 , true, 80 , NULL, NULL, "The maximum number of columns to use for displaying text." },
{ "thread-format", OptionValue::eTypeString , true, 0 , DEFAULT_THREAD_FORMAT, NULL, "The default thread format string to use when displaying thread information." },
{ "use-external-editor", OptionValue::eTypeBoolean, true, false, NULL, NULL, "Whether to use an external editor or not." },
{ NULL, OptionValue::eTypeInvalid, true, 0 , NULL, NULL, NULL }
{ NULL, OptionValue::eTypeInvalid, true, 0 , NULL, NULL, NULL }
};
enum
@ -438,6 +440,8 @@ Debugger::InstanceInitialize ()
this);
}
}
PluginManager::DebuggerInitialize (*this);
}
DebuggerSP

View File

@ -14,10 +14,12 @@
#include <string>
#include <vector>
#include "lldb/Core/Debugger.h"
#include "lldb/Core/Error.h"
#include "lldb/Host/FileSpec.h"
#include "lldb/Host/Host.h"
#include "lldb/Host/Mutex.h"
#include "lldb/Interpreter/OptionValueProperties.h"
#include "llvm/ADT/StringRef.h"
@ -436,13 +438,15 @@ struct DynamicLoaderInstance
DynamicLoaderInstance() :
name(),
description(),
create_callback(NULL)
create_callback(NULL),
debugger_init_callback (NULL)
{
}
std::string name;
std::string description;
DynamicLoaderCreateInstance create_callback;
DebuggerInitializeCallback debugger_init_callback;
};
typedef std::vector<DynamicLoaderInstance> DynamicLoaderInstances;
@ -468,7 +472,8 @@ PluginManager::RegisterPlugin
(
const char *name,
const char *description,
DynamicLoaderCreateInstance create_callback
DynamicLoaderCreateInstance create_callback,
DebuggerInitializeCallback debugger_init_callback
)
{
if (create_callback)
@ -479,6 +484,7 @@ PluginManager::RegisterPlugin
if (description && description[0])
instance.description = description;
instance.create_callback = create_callback;
instance.debugger_init_callback = debugger_init_callback;
Mutex::Locker locker (GetDynamicLoaderMutex ());
GetDynamicLoaderInstances ().push_back (instance);
}
@ -1802,3 +1808,92 @@ PluginManager::GetUnwindAssemblyCreateCallbackForPluginName (const char *name)
return NULL;
}
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)
{
if (pos->debugger_init_callback)
pos->debugger_init_callback (debugger);
}
}
static lldb::OptionValuePropertiesSP
GetDebuggerPropertyForPlugins (Debugger &debugger,
const ConstString &plugin_type_name,
const ConstString &plugin_type_desc,
bool can_create)
{
lldb::OptionValuePropertiesSP parent_properties_sp (debugger.GetValueProperties());
if (parent_properties_sp)
{
static ConstString g_property_name("plugin");
OptionValuePropertiesSP plugin_properties_sp = parent_properties_sp->GetSubProperty (NULL, g_property_name);
if (!plugin_properties_sp && can_create)
{
plugin_properties_sp.reset (new OptionValueProperties (g_property_name));
parent_properties_sp->AppendProperty (g_property_name,
ConstString("Settings specify to plugins."),
true,
plugin_properties_sp);
}
if (plugin_properties_sp)
{
lldb::OptionValuePropertiesSP plugin_type_properties_sp = plugin_properties_sp->GetSubProperty (NULL, plugin_type_name);
if (!plugin_type_properties_sp && can_create)
{
plugin_type_properties_sp.reset (new OptionValueProperties (plugin_type_name));
plugin_properties_sp->AppendProperty (plugin_type_name,
plugin_type_desc,
true,
plugin_type_properties_sp);
}
return plugin_type_properties_sp;
}
}
return lldb::OptionValuePropertiesSP();
}
lldb::OptionValuePropertiesSP
PluginManager::GetSettingForDynamicLoaderPlugin (Debugger &debugger, const ConstString &setting_name)
{
lldb::OptionValuePropertiesSP properties_sp;
lldb::OptionValuePropertiesSP plugin_type_properties_sp (GetDebuggerPropertyForPlugins (debugger,
ConstString("dynamic-loader"),
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::CreateSettingForDynamicLoaderPlugin (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("dynamic-loader"),
ConstString("Settings for dynamic loader 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

@ -95,3 +95,15 @@ Properties::Apropos (const char *keyword, std::vector<const Property *> &matchin
}
return matching_properties.size();
}
lldb::OptionValuePropertiesSP
Properties::GetSubProperty (const ExecutionContext *exe_ctx,
const ConstString &name)
{
OptionValuePropertiesSP properties_sp (GetValueProperties ());
if (properties_sp)
return properties_sp->GetSubProperty (exe_ctx, name);
return lldb::OptionValuePropertiesSP();
}

View File

@ -740,4 +740,19 @@ OptionValueProperties::Apropos (const char *keyword, std::vector<const Property
}
}
lldb::OptionValuePropertiesSP
OptionValueProperties::GetSubProperty (const ExecutionContext *exe_ctx,
const ConstString &name)
{
lldb::OptionValueSP option_value_sp(GetValueForKey(exe_ctx, name, false));
if (option_value_sp)
{
OptionValueProperties *ov_properties = option_value_sp->GetAsProperties ();
if (ov_properties)
return ov_properties->shared_from_this();
}
return lldb::OptionValuePropertiesSP();
}

View File

@ -39,6 +39,60 @@
using namespace lldb;
using namespace lldb_private;
static PropertyDefinition
g_properties[] =
{
{ "disable-kext-loading" , OptionValue::eTypeBoolean, false, false, NULL, NULL, "Disable kext image loading in a Darwin kernel debug session." },
{ NULL , OptionValue::eTypeInvalid, false, 0 , NULL, NULL, NULL }
};
enum {
ePropertyDisableKextLoading
};
class DynamicLoaderDarwinKernelProperties : public Properties
{
public:
static ConstString &
GetSettingName ()
{
static ConstString g_setting_name("macosx-kernel");
return g_setting_name;
}
DynamicLoaderDarwinKernelProperties() :
Properties ()
{
m_collection_sp.reset (new OptionValueProperties(GetSettingName()));
m_collection_sp->Initialize(g_properties);
}
virtual
~DynamicLoaderDarwinKernelProperties()
{
}
bool
GetDisableKextLoading() const
{
const uint32_t idx = ePropertyDisableKextLoading;
return m_collection_sp->GetPropertyAtIndexAsBoolean (NULL, idx, g_properties[idx].default_uint_value != 0);
}
};
typedef STD_SHARED_PTR(DynamicLoaderDarwinKernelProperties) DynamicLoaderDarwinKernelPropertiesSP;
static const DynamicLoaderDarwinKernelPropertiesSP &
GetGlobalProperties()
{
static DynamicLoaderDarwinKernelPropertiesSP g_settings_sp;
if (!g_settings_sp)
g_settings_sp.reset (new DynamicLoaderDarwinKernelProperties ());
return g_settings_sp;
}
//----------------------------------------------------------------------
// Create an instance of this class. This function is filled into
// the plugin info class that gets handed out by the plugin factory and
@ -190,7 +244,7 @@ DynamicLoaderDarwinKernel::OSKextLoadedKextSummary::LoadImageUsingMemoryModule (
ModuleSP memory_module_sp;
// If this is a kext and the user asked us to ignore kexts, don't try to load it.
if (kernel_image == false && target.GetDisableKextLoading() == true)
if (kernel_image == false && GetGlobalProperties()->GetDisableKextLoading() == true)
{
return false;
}
@ -872,7 +926,8 @@ DynamicLoaderDarwinKernel::Initialize()
{
PluginManager::RegisterPlugin (GetPluginNameStatic(),
GetPluginDescriptionStatic(),
CreateInstance);
CreateInstance,
DebuggerInitialize);
}
void
@ -881,6 +936,18 @@ DynamicLoaderDarwinKernel::Terminate()
PluginManager::UnregisterPlugin (CreateInstance);
}
void
DynamicLoaderDarwinKernel::DebuggerInitialize (lldb_private::Debugger &debugger)
{
if (!PluginManager::GetSettingForDynamicLoaderPlugin (debugger, DynamicLoaderDarwinKernelProperties::GetSettingName()))
{
const bool is_global_setting = true;
PluginManager::CreateSettingForDynamicLoaderPlugin (debugger,
GetGlobalProperties()->GetValueProperties(),
ConstString ("Properties for the DynamicLoaderDarwinKernel plug-in."),
is_global_setting);
}
}
const char *
DynamicLoaderDarwinKernel::GetPluginNameStatic()

View File

@ -47,6 +47,9 @@ public:
static lldb_private::DynamicLoader *
CreateInstance (lldb_private::Process *process, bool force);
static void
DebuggerInitialize (lldb_private::Debugger &debugger);
DynamicLoaderDarwinKernel (lldb_private::Process *process);
virtual

View File

@ -2167,7 +2167,6 @@ g_properties[] =
"Always checking for inlined breakpoint locations can be expensive (memory and time), so we try to minimize the "
"times we look for inlined locations. This setting allows you to control exactly which strategy is used when settings "
"file and line breakpoints." },
{ "disable-kext-loading" , OptionValue::eTypeBoolean , false, false , NULL, NULL, "Disable kext image loading in a Darwin kernel debug session" },
{ NULL , OptionValue::eTypeInvalid , false, 0 , NULL, NULL, NULL }
};
enum
@ -2191,8 +2190,7 @@ enum
ePropertyErrorPath,
ePropertyDisableASLR,
ePropertyDisableSTDIO,
ePropertyInlineStrategy,
ePropertyDisableKextLoading
ePropertyInlineStrategy
};
@ -2520,20 +2518,6 @@ TargetProperties::GetBreakpointsConsultPlatformAvoidList ()
return m_collection_sp->GetPropertyAtIndexAsBoolean (NULL, idx, g_properties[idx].default_uint_value != 0);
}
bool
TargetProperties::GetDisableKextLoading () const
{
const uint32_t idx = ePropertyDisableKextLoading;
return m_collection_sp->GetPropertyAtIndexAsBoolean (NULL, idx, g_properties[idx].default_uint_value != 0);
}
void
TargetProperties::SetDisableKextLoading (bool b)
{
const uint32_t idx = ePropertyDisableKextLoading;
m_collection_sp->SetPropertyAtIndexAsBoolean (NULL, idx, b);
}
const TargetPropertiesSP &
Target::GetGlobalProperties()
{