Added new target instance settings for execution settings:

Targets can now specify some additional parameters for when we debug 
executables that can help with plug-in selection:

target.execution-level = auto | user | kernel
target.execution-mode  = auto | dynamic | static
target.execution-os-type = auto | none | halted | live

On some systems, the binaries that are created are the same wether you use
them to debug a kernel, or a user space program. Many times inspecting an 
object file can reveal what an executable should be. For these cases we can
now be a little more complete by specifying wether to detect all of these
things automatically (inspect the main executable file and select a plug-in
accordingly), or manually to force the selection of certain plug-ins.

To do this we now allow the specficifation of wether one is debugging a user
space program (target.execution-level = user) or a kernel program 
(target.execution-level = kernel).

We can also specify if we want to debug a program where shared libraries
are dynamically loaded using a DynamicLoader plug-in 
(target.execution-mode = dynamic), or wether we will treat all symbol files
as already linked at the correct address (target.execution-mode = static).

We can also specify if the inferior we are debugging is being debugged on 
a bare board (target.execution-os-type = none), or debugging an OS where
we have a JTAG or other direct connection to the inferior stops the entire
OS (target.execution-os-type = halted), or if we are debugging a program on
something that has live debug services (target.execution-os-type = live).

For the "target.execution-os-type = halted" mode, we will need to create 
ProcessHelper plug-ins that allow us to extract the process/thread and other
OS information by reading/writing memory.

This should allow LLDB to be used for a wide variety of debugging tasks and
handle them all correctly.

llvm-svn: 125815
This commit is contained in:
Greg Clayton 2011-02-18 01:44:25 +00:00
parent 951e22e2c9
commit bfe5f3bf06
10 changed files with 548 additions and 330 deletions

View File

@ -185,6 +185,12 @@ public:
static ProcessCreateInstance
GetProcessCreateCallbackForPluginName (const char *name);
static const char *
GetProcessPluginNameAtIndex (uint32_t idx);
static const char *
GetProcessPluginDescriptionAtIndex (uint32_t idx);
//------------------------------------------------------------------
// SymbolFile

View File

@ -394,8 +394,6 @@ public:
lldb::InstanceSettingsSP
CreateInstanceSettings (const char *instance_name);
static lldb::OptionEnumValueElement g_plugins[];
private:
// Class-wide settings.
@ -408,6 +406,9 @@ public:
static void
Initialize ();
static void
DidInitialize ();
static void
Terminate ();

View File

@ -15,7 +15,7 @@
// Other libraries and framework includes
// Project includes
#include "lldb/lldb-private.h"
#include "lldb/lldb-include.h"
#include "lldb/Breakpoint/BreakpointList.h"
#include "lldb/Breakpoint/BreakpointLocationCollection.h"
#include "lldb/Core/Broadcaster.h"
@ -32,6 +32,9 @@
namespace lldb_private {
//----------------------------------------------------------------------
// TargetInstanceSettings
//----------------------------------------------------------------------
class TargetInstanceSettings : public InstanceSettings
{
public:
@ -62,6 +65,43 @@ public:
StringList &value,
Error *err);
lldb::ExecutionLevel
GetExecutionLevel () const
{
return m_execution_level;
}
void
SetExecutionLevel (lldb::ExecutionLevel execution_level)
{
m_execution_level = execution_level;
}
lldb::ExecutionMode
GetExecutionMode () const
{
return m_execution_mode;
}
void
SetExecutionMode (lldb::ExecutionMode execution_mode)
{
m_execution_mode = execution_mode;
}
lldb::ExecutionOSType
GetExecutionOSType () const
{
return m_execution_os_type;
}
void
SetExecutionOSType (lldb::ExecutionOSType execution_os_type)
{
m_execution_os_type = execution_os_type;
}
protected:
void
@ -73,8 +113,15 @@ protected:
std::string m_expr_prefix_path;
std::string m_expr_prefix_contents;
lldb::ExecutionLevel m_execution_level;
lldb::ExecutionMode m_execution_mode;
lldb::ExecutionOSType m_execution_os_type;
};
//----------------------------------------------------------------------
// Target
//----------------------------------------------------------------------
class Target :
public Broadcaster,
public ExecutionContextScope,
@ -83,46 +130,16 @@ class Target :
public:
friend class TargetList;
class SettingsController : public UserSettingsController
//------------------------------------------------------------------
/// Broadcaster event bits definitions.
//------------------------------------------------------------------
enum
{
public:
SettingsController ();
virtual
~SettingsController ();
bool
SetGlobalVariable (const ConstString &var_name,
const char *index_value,
const char *value,
const SettingEntry &entry,
const lldb::VarSetOperationType op,
Error&err);
bool
GetGlobalVariable (const ConstString &var_name,
StringList &value,
Error &err);
static SettingEntry global_settings_table[];
static SettingEntry instance_settings_table[];
protected:
lldb::InstanceSettingsSP
CreateInstanceSettings (const char *instance_name);
static const ConstString &
DefArchVarName ();
private:
// Class-wide settings.
ArchSpec m_default_architecture;
DISALLOW_COPY_AND_ASSIGN (SettingsController);
eBroadcastBitBreakpointChanged = (1 << 0),
eBroadcastBitModulesLoaded = (1 << 1),
eBroadcastBitModulesUnloaded = (1 << 2)
};
static void
Initialize ();
@ -141,16 +158,6 @@ public:
void
UpdateInstanceName ();
//------------------------------------------------------------------
/// Broadcaster event bits definitions.
//------------------------------------------------------------------
enum
{
eBroadcastBitBreakpointChanged = (1 << 0),
eBroadcastBitModulesLoaded = (1 << 1),
eBroadcastBitModulesUnloaded = (1 << 2)
};
lldb::ModuleSP
GetSharedModule (const FileSpec& file_spec,
const ArchSpec& arch,
@ -206,7 +213,6 @@ public:
lldb::TargetSP
GetSP();
//------------------------------------------------------------------
// This part handles the breakpoints.
//------------------------------------------------------------------
@ -501,6 +507,46 @@ public:
}
//------------------------------------------------------------------
// Target::SettingsController
//------------------------------------------------------------------
class SettingsController : public UserSettingsController
{
public:
SettingsController ();
virtual
~SettingsController ();
bool
SetGlobalVariable (const ConstString &var_name,
const char *index_value,
const char *value,
const SettingEntry &entry,
const lldb::VarSetOperationType op,
Error&err);
bool
GetGlobalVariable (const ConstString &var_name,
StringList &value,
Error &err);
static SettingEntry global_settings_table[];
static SettingEntry instance_settings_table[];
protected:
lldb::InstanceSettingsSP
CreateInstanceSettings (const char *instance_name);
private:
// Class-wide settings.
ArchSpec m_default_architecture;
DISALLOW_COPY_AND_ASSIGN (SettingsController);
};
protected:
friend class lldb::SBTarget;

View File

@ -618,6 +618,60 @@ typedef enum LazyBool {
eLazyBoolYes = 1
} LazyBool;
//------------------------------------------------------------------
/// Execution Level
//------------------------------------------------------------------
typedef enum ExecutionLevel
{
eExecutionLevelAuto, // Automatically detect how to run an executable
eExecutionLevelKernel, // Execute a program as a kernel executable
eExecutionLevelUser // Execute a program as a user space executable
} ExecutionLevel;
//------------------------------------------------------------------
/// Execution mode
//------------------------------------------------------------------
typedef enum ExecutionMode
{
// Automatically detect the execution mode
eExecutionModeAuto,
// Execute with no shared libraries, everything is where the executable
// files say they are (file addresses == load addresses)
eExecutionModeStatic,
// Execute with shared libraries using a dynamic loader plug-in to
// detect when shared libraries are loaded/unloaded.
eExecutionModeDynamic
} ExecutionMode;
//------------------------------------------------------------------
/// Execution OS
//------------------------------------------------------------------
typedef enum ExecutionOSType
{
// Automatically detect the execution operating system
eExecutionOSTypeAuto,
// There is no operating system (no processes or threads).
eExecutionOSTypeNone,
// There is an OS, but when we execution stops, the entire OS is halted
// (common when debugging in eExecutionLevelKernel modes). Processes and
// threads can be queried, selected and switched between using memory
// reads/writes using a ProcessHelper plug-in (which has yet to be
// designed).
eExecutionOSTypeHalted,
// There is live OS with debug services that we can talk to for process,
// thread, and other OS queries.
eExecutionOSTypeLive
} ExecutionOSType;
} // namespace lldb

View File

@ -1278,6 +1278,24 @@ PluginManager::RegisterPlugin
return false;
}
const char *
PluginManager::GetProcessPluginNameAtIndex (uint32_t idx)
{
ProcessInstance instance;
if (AccessProcessInstances (ePluginGetInstanceAtIndex, instance, idx))
return instance.name.c_str();
return NULL;
}
const char *
PluginManager::GetProcessPluginDescriptionAtIndex (uint32_t idx)
{
ProcessInstance instance;
if (AccessProcessInstances (ePluginGetInstanceAtIndex, instance, idx))
return instance.description.c_str();
return NULL;
}
bool
PluginManager::UnregisterPlugin (ProcessCreateInstance create_callback)
{

File diff suppressed because it is too large Load Diff

View File

@ -1687,12 +1687,17 @@ CommandInterpreter::OutputFormattedHelpText (Stream &strm,
int indent_size = max_word_len + strlen (separator) + 2;
strm.IndentMore (indent_size);
int len = indent_size + strlen (help_text) + 1;
char *text = (char *) malloc (len);
sprintf (text, "%-*s %s %s", max_word_len, word_text, separator, help_text);
StreamString text_strm;
text_strm.Printf ("%-*s %s %s", max_word_len, word_text, separator, help_text);
size_t len = text_strm.GetSize();
const char *text = text_strm.GetData();
if (text[len - 1] == '\n')
text[--len] = '\0';
{
text_strm.EOL();
len = text_strm.GetSize();
}
if (len < max_columns)
{
@ -1750,7 +1755,6 @@ CommandInterpreter::OutputFormattedHelpText (Stream &strm,
}
strm.EOL();
strm.IndentLess(indent_size);
free (text);
}
void

View File

@ -2644,10 +2644,39 @@ Process::PopProcessInputReader ()
m_target.GetDebugger().PopInputReader (m_process_input_reader);
}
// The process needs to know about installed plug-ins
void
Process::Initialize ()
Process::DidInitialize ()
{
static std::vector<lldb::OptionEnumValueElement> g_plugins;
int i=0;
const char *name;
OptionEnumValueElement option_enum;
while ((name = PluginManager::GetProcessPluginNameAtIndex (i)) != NULL)
{
if (name)
{
option_enum.value = i;
option_enum.string_value = name;
option_enum.usage = PluginManager::GetProcessPluginDescriptionAtIndex (i);
g_plugins.push_back (option_enum);
}
++i;
}
option_enum.value = 0;
option_enum.string_value = NULL;
option_enum.usage = NULL;
g_plugins.push_back (option_enum);
for (i=0; (name = SettingsController::instance_settings_table[i].var_name); ++i)
{
if (::strcmp (name, "plugin") == 0)
{
SettingsController::instance_settings_table[i].enum_values = &g_plugins[0];
break;
}
}
UserSettingsControllerSP &usc = GetSettingsController();
usc.reset (new SettingsController);
UserSettingsController::InitializeSettingsController (usc,
@ -2655,6 +2684,11 @@ Process::Initialize ()
SettingsController::instance_settings_table);
}
void
Process::Initialize ()
{
}
void
Process::Terminate ()
{
@ -3550,14 +3584,6 @@ Process::SettingsController::global_settings_table[] =
};
lldb::OptionEnumValueElement
Process::SettingsController::g_plugins[] =
{
{ eMacosx, "process.macosx", "Use the native MacOSX debugger plugin" },
{ eRemoteDebugger, "process.gdb-remote" , "Use the GDB Remote protocol based debugger plugin" },
{ 0, NULL, NULL }
};
SettingEntry
Process::SettingsController::instance_settings_table[] =
{
@ -3568,7 +3594,7 @@ Process::SettingsController::instance_settings_table[] =
{ "input-path", eSetVarTypeString, NULL, NULL, false, false, "The file/path to be used by the executable program for reading its input." },
{ "output-path", eSetVarTypeString, NULL, NULL, false, false, "The file/path to be used by the executable program for writing its output." },
{ "error-path", eSetVarTypeString, NULL, NULL, false, false, "The file/path to be used by the executable program for writings its error messages." },
{ "plugin", eSetVarTypeEnum, NULL, g_plugins, false, false, "The plugin to be used to run the process." },
{ "plugin", eSetVarTypeEnum, NULL, NULL, false, false, "The plugin to be used to run the process." },
{ "disable-aslr", eSetVarTypeBoolean, "true", NULL, false, false, "Disable Address Space Layout Randomization (ASLR)" },
{ "disable-stdio", eSetVarTypeBoolean, "false", NULL, false, false, "Disable stdin/stdout for process (e.g. for a GUI application)" },
{ NULL, eSetVarTypeNone, NULL, NULL, false, false, NULL }

View File

@ -998,14 +998,51 @@ Target::SettingsController::CreateInstanceSettings (const char *instance_name)
return new_settings_sp;
}
const ConstString &
Target::SettingsController::DefArchVarName ()
{
static ConstString def_arch_var_name ("default-arch");
return def_arch_var_name;
#define TSC_DEFAULT_ARCH "default-arch"
#define TSC_EXPR_PREFIX "expr-prefix"
#define TSC_EXEC_LEVEL "execution-level"
#define TSC_EXEC_MODE "execution-mode"
#define TSC_EXEC_OS_TYPE "execution-os-type"
static const ConstString &
GetSettingNameForDefaultArch ()
{
static ConstString g_const_string (TSC_DEFAULT_ARCH);
return g_const_string;
}
static const ConstString &
GetSettingNameForExpressionPrefix ()
{
static ConstString g_const_string (TSC_EXPR_PREFIX);
return g_const_string;
}
static const ConstString &
GetSettingNameForExecutionLevel ()
{
static ConstString g_const_string (TSC_EXEC_LEVEL);
return g_const_string;
}
static const ConstString &
GetSettingNameForExecutionMode ()
{
static ConstString g_const_string (TSC_EXEC_MODE);
return g_const_string;
}
static const ConstString &
GetSettingNameForExecutionOSType ()
{
static ConstString g_const_string (TSC_EXEC_OS_TYPE);
return g_const_string;
}
bool
Target::SettingsController::SetGlobalVariable (const ConstString &var_name,
const char *index_value,
@ -1014,7 +1051,7 @@ Target::SettingsController::SetGlobalVariable (const ConstString &var_name,
const lldb::VarSetOperationType op,
Error&err)
{
if (var_name == DefArchVarName())
if (var_name == GetSettingNameForDefaultArch())
{
ArchSpec tmp_spec (value);
if (tmp_spec.IsValid())
@ -1031,7 +1068,7 @@ Target::SettingsController::GetGlobalVariable (const ConstString &var_name,
StringList &value,
Error &err)
{
if (var_name == DefArchVarName())
if (var_name == GetSettingNameForDefaultArch())
{
// If the arch is invalid (the default), don't show a string for it
if (m_default_architecture.IsValid())
@ -1054,7 +1091,12 @@ TargetInstanceSettings::TargetInstanceSettings
bool live_instance,
const char *name
) :
InstanceSettings (owner, name ? name : InstanceSettings::InvalidName().AsCString(), live_instance)
InstanceSettings (owner, name ? name : InstanceSettings::InvalidName().AsCString(), live_instance),
m_expr_prefix_path (),
m_expr_prefix_contents (),
m_execution_level (eExecutionLevelAuto),
m_execution_mode (eExecutionModeAuto),
m_execution_os_type (eExecutionOSTypeAuto)
{
// CopyInstanceSettings is a pure virtual function in InstanceSettings; it therefore cannot be called
// until the vtables for TargetInstanceSettings are properly set up, i.e. AFTER all the initializers.
@ -1100,8 +1142,6 @@ TargetInstanceSettings::operator= (const TargetInstanceSettings &rhs)
return *this;
}
#define EXPR_PREFIX_STRING "expr-prefix"
void
TargetInstanceSettings::UpdateInstanceSettingsVariable (const ConstString &var_name,
const char *index_value,
@ -1112,9 +1152,9 @@ TargetInstanceSettings::UpdateInstanceSettingsVariable (const ConstString &var_n
Error &err,
bool pending)
{
static ConstString expr_prefix_str (EXPR_PREFIX_STRING);
if (var_name == expr_prefix_str)
int new_enum = -1;
if (var_name == GetSettingNameForExpressionPrefix ())
{
switch (op)
{
@ -1156,19 +1196,39 @@ TargetInstanceSettings::UpdateInstanceSettingsVariable (const ConstString &var_n
return;
}
}
else if (var_name == GetSettingNameForExecutionLevel ())
{
UserSettingsController::UpdateEnumVariable (entry.enum_values, &new_enum, value, err);
if (err.Success())
m_execution_level = (ExecutionLevel)new_enum;
}
else if (var_name == GetSettingNameForExecutionMode ())
{
UserSettingsController::UpdateEnumVariable (entry.enum_values, &new_enum, value, err);
if (err.Success())
m_execution_mode = (ExecutionMode)new_enum;
}
else if (var_name == GetSettingNameForExecutionOSType ())
{
UserSettingsController::UpdateEnumVariable (entry.enum_values, &new_enum, value, err);
if (err.Success())
m_execution_os_type = (ExecutionOSType)new_enum;
}
}
void
TargetInstanceSettings::CopyInstanceSettings (const lldb::InstanceSettingsSP &new_settings,
bool pending)
TargetInstanceSettings::CopyInstanceSettings (const lldb::InstanceSettingsSP &new_settings, bool pending)
{
TargetInstanceSettings *new_settings_ptr = static_cast <TargetInstanceSettings *> (new_settings.get());
if (!new_settings_ptr)
return;
m_expr_prefix_path = new_settings_ptr->m_expr_prefix_path;
m_expr_prefix_contents = new_settings_ptr->m_expr_prefix_contents;
m_expr_prefix_path = new_settings_ptr->m_expr_prefix_path;
m_expr_prefix_contents = new_settings_ptr->m_expr_prefix_contents;
m_execution_level = new_settings_ptr->m_execution_level;
m_execution_mode = new_settings_ptr->m_execution_mode;
m_execution_os_type = new_settings_ptr->m_execution_os_type;
}
bool
@ -1177,12 +1237,22 @@ TargetInstanceSettings::GetInstanceSettingsValue (const SettingEntry &entry,
StringList &value,
Error *err)
{
static ConstString expr_prefix_str (EXPR_PREFIX_STRING);
if (var_name == expr_prefix_str)
if (var_name == GetSettingNameForExpressionPrefix ())
{
value.AppendString (m_expr_prefix_path.c_str(), m_expr_prefix_path.size());
}
else if (var_name == GetSettingNameForExecutionLevel ())
{
value.AppendString (UserSettingsController::EnumToString (entry.enum_values, m_execution_level));
}
else if (var_name == GetSettingNameForExecutionMode ())
{
value.AppendString (UserSettingsController::EnumToString (entry.enum_values, m_execution_mode));
}
else if (var_name == GetSettingNameForExecutionOSType ())
{
value.AppendString (UserSettingsController::EnumToString (entry.enum_values, m_execution_os_type));
}
else
{
if (err)
@ -1213,15 +1283,51 @@ TargetInstanceSettings::CreateInstanceName ()
SettingEntry
Target::SettingsController::global_settings_table[] =
{
//{ "var-name", var-type, "default", enum-table, init'd, hidden, "help-text"},
{ "default-arch", eSetVarTypeString, NULL, NULL, false, false, "Default architecture to choose, when there's a choice." },
{ NULL, eSetVarTypeNone, NULL, NULL, 0, 0, NULL }
// var-name var-type default enum init'd hidden help-text
// ================= ================== =========== ==== ====== ====== =========================================================================
{ TSC_DEFAULT_ARCH , eSetVarTypeString , NULL , NULL, false, false, "Default architecture to choose, when there's a choice." },
{ NULL , eSetVarTypeNone , NULL , NULL, false, false, NULL }
};
static lldb::OptionEnumValueElement
g_execution_level_enums[] =
{
{ eExecutionLevelAuto , "auto" , "Automatically detect the execution level (user/kernel)." },
{ eExecutionLevelKernel , "kernel" , "Treat executables as kernel executables." },
{ eExecutionLevelUser , "user" , "Treat executables as user space executables." },
{ 0 , NULL , NULL }
};
static lldb::OptionEnumValueElement
g_execution_mode_enums[] =
{
{ eExecutionModeAuto , "auto" , "Automatically detect the execution mode (static/dynamic)." },
{ eExecutionModeStatic , "static" , "All executables are static and addresses at the virtual addresses in the object files." },
{ eExecutionModeDynamic , "dynamic" , "Executables and shared libraries are dynamically loaded.." },
{ 0 , NULL , NULL }
};
static lldb::OptionEnumValueElement
g_execution_os_enums[] =
{
{ eExecutionOSTypeAuto , "auto" , "Automatically detect the execution OS (none/halted/live)." },
{ eExecutionOSTypeNone , "none" , "There is no operating system available (no processes or threads)." },
{ eExecutionOSTypeHalted, "halted" , "There is an operating system, but it is halted when the debugger is halted. "
"Processes and threads must be discovered by accessing symbols and reading "
"memory." },
{ eExecutionOSTypeLive , "live" , "There is a live operating system with debug services that can be used to "
"get processes, threads and theirs states." },
{ 0, NULL, NULL }
};
SettingEntry
Target::SettingsController::instance_settings_table[] =
{
//{ "var-name", var-type, "default", enum-table, init'd, hidden, "help-text"},
{ EXPR_PREFIX_STRING, eSetVarTypeString, NULL, NULL, false, false, "Path to a file containing expressions to be prepended to all expressions." },
{ NULL, eSetVarTypeNone, NULL, NULL, 0, 0, NULL }
// var-name var-type default enum-table init'd hidden help-text
// ================= ================== =========== ========================= ====== ====== =========================================================================
{ TSC_EXPR_PREFIX , eSetVarTypeString , NULL , NULL , false, false, "Path to a file containing expressions to be prepended to all expressions." },
{ TSC_EXEC_LEVEL , eSetVarTypeEnum , "auto" , g_execution_level_enums , false, false, "Sets the execution level for a target." },
{ TSC_EXEC_MODE , eSetVarTypeEnum , "auto" , g_execution_mode_enums , false, false, "Sets the execution mode for a target." },
{ TSC_EXEC_OS_TYPE , eSetVarTypeEnum , "auto" , g_execution_os_enums , false, false, "Sets the execution OS for a target." },
{ NULL , eSetVarTypeNone , NULL , NULL , false, false, NULL }
};

View File

@ -101,6 +101,10 @@ lldb_private::Initialize ()
#endif
// Scan for any system or user LLDB plug-ins
PluginManager::Initialize();
// The process needs to know about installed plug-ins
Process::DidInitialize ();
}
}