Many GDB users always want to display disassembly when they stop by using

something like "display/4i $pc" (or something like this). With LLDB we already
were showing 3 lines of source before and 3 lines of source after the current
source line when showing a stop context. We now improve this by allowing the
user to control the number of lines with the new "stop-line-count-before" and
"stop-line-count-after" settings. Also, there is a new setting for how many
disassembly lines to show: "stop-disassembly-count". This will control how many
source lines are shown when there is no source or when we have no source line
info. 

settings set stop-line-count-before 3
settings set stop-line-count-after 3
settings set stop-disassembly-count 4
settings set stop-disassembly-display no-source

The default values are set as shown above and allow 3 lines of source before 
and after (what we used to do) the current stop location, and will display 4 
lines of disassembly if the source is not available or if we have no debug
info. If both "stop-source-context-before" and "stop-source-context-after" are
set to zero, this will disable showing any source when stopped. The 
"stop-disassembly-display" setting is an enumeration that allows you to control
when to display disassembly. It has 3 possible values:

"never" - never show disassembly no matter what
"no-source" - only show disassembly when there is no source line info or the source files are missing
"always" - always show disassembly.

llvm-svn: 145050
This commit is contained in:
Greg Clayton 2011-11-21 21:44:34 +00:00
parent f13b855809
commit e372b98d18
3 changed files with 261 additions and 90 deletions

View File

@ -44,6 +44,14 @@ class DebuggerInstanceSettings : public InstanceSettings
{ {
public: public:
enum StopDisassemblyType
{
eStopDisassemblyTypeNever = 0,
eStopDisassemblyTypeNoSource,
eStopDisassemblyTypeAlways
};
DebuggerInstanceSettings (UserSettingsController &owner, bool live_instance = true, const char *name = NULL); DebuggerInstanceSettings (UserSettingsController &owner, bool live_instance = true, const char *name = NULL);
DebuggerInstanceSettings (const DebuggerInstanceSettings &rhs); DebuggerInstanceSettings (const DebuggerInstanceSettings &rhs);
@ -82,6 +90,44 @@ public:
m_term_width = term_width; m_term_width = term_width;
} }
uint32_t
GetStopSourceLineCount (bool before) const
{
if (before)
return m_stop_source_before_count;
else
return m_stop_source_after_count;
}
void
SetStopSourceLineCount (bool before, uint32_t n)
{
if (before)
m_stop_source_before_count = n;
else
m_stop_source_after_count = n;
}
StopDisassemblyType
GetStopDisassemblyDisplay () const
{
return m_stop_disassembly_display;
}
uint32_t
GetDisassemblyLineCount () const
{
return m_stop_disassembly_count;
}
void
SetDisassemblyLineCount (uint32_t n)
{
m_stop_disassembly_count = n;
}
const char * const char *
GetPrompt() const GetPrompt() const
{ {
@ -185,30 +231,15 @@ protected:
const ConstString const ConstString
CreateInstanceName (); CreateInstanceName ();
static const ConstString & static OptionEnumValueElement g_show_disassembly_enum_values[];
PromptVarName ();
static const ConstString &
GetFrameFormatName ();
static const ConstString &
GetThreadFormatName ();
static const ConstString &
ScriptLangVarName ();
static const ConstString &
TermWidthVarName ();
static const ConstString &
UseExternalEditorVarName ();
static const ConstString &
AutoConfirmName ();
private: private:
uint32_t m_term_width; uint32_t m_term_width;
uint32_t m_stop_source_before_count;
uint32_t m_stop_source_after_count;
uint32_t m_stop_disassembly_count;
StopDisassemblyType m_stop_disassembly_display;
std::string m_prompt; std::string m_prompt;
std::string m_frame_format; std::string m_frame_format;
std::string m_thread_format; std::string m_thread_format;

View File

@ -61,6 +61,94 @@ GetDebuggerList()
} }
static const ConstString &
PromptVarName ()
{
static ConstString g_const_string ("prompt");
return g_const_string;
}
static const ConstString &
GetFrameFormatName ()
{
static ConstString g_const_string ("frame-format");
return g_const_string;
}
static const ConstString &
GetThreadFormatName ()
{
static ConstString g_const_string ("thread-format");
return g_const_string;
}
static const ConstString &
ScriptLangVarName ()
{
static ConstString g_const_string ("script-lang");
return g_const_string;
}
static const ConstString &
TermWidthVarName ()
{
static ConstString g_const_string ("term-width");
return g_const_string;
}
static const ConstString &
UseExternalEditorVarName ()
{
static ConstString g_const_string ("use-external-editor");
return g_const_string;
}
static const ConstString &
AutoConfirmName ()
{
static ConstString g_const_string ("auto-confirm");
return g_const_string;
}
static const ConstString &
StopSourceContextBeforeName ()
{
static ConstString g_const_string ("stop-line-count-before");
return g_const_string;
}
static const ConstString &
StopSourceContextAfterName ()
{
static ConstString g_const_string ("stop-line-count-after");
return g_const_string;
}
static const ConstString &
StopDisassemblyCountName ()
{
static ConstString g_const_string ("stop-disassembly-count");
return g_const_string;
}
static const ConstString &
StopDisassemblyDisplayName ()
{
static ConstString g_const_string ("stop-disassembly-display");
return g_const_string;
}
OptionEnumValueElement
DebuggerInstanceSettings::g_show_disassembly_enum_values[] =
{
{ eStopDisassemblyTypeNever, "never", "Never show disassembly when displaying a stop context."},
{ eStopDisassemblyTypeNoSource, "no-source", "Show disassembly when there is no source information, or the source file is missing when displaying a stop context."},
{ eStopDisassemblyTypeAlways, "always", "Always show disassembly when displaying a stop context."},
{ 0, NULL, NULL }
};
#pragma mark Debugger #pragma mark Debugger
UserSettingsControllerSP & UserSettingsControllerSP &
@ -2108,6 +2196,10 @@ DebuggerInstanceSettings::DebuggerInstanceSettings
) : ) :
InstanceSettings (owner, name ? name : InstanceSettings::InvalidName().AsCString(), live_instance), InstanceSettings (owner, name ? name : InstanceSettings::InvalidName().AsCString(), live_instance),
m_term_width (80), m_term_width (80),
m_stop_source_before_count (3),
m_stop_source_after_count (3),
m_stop_disassembly_count (4),
m_stop_disassembly_display (eStopDisassemblyTypeNoSource),
m_prompt (), m_prompt (),
m_frame_format (), m_frame_format (),
m_thread_format (), m_thread_format (),
@ -2255,6 +2347,37 @@ DebuggerInstanceSettings::UpdateInstanceSettingsVariable (const ConstString &var
{ {
UserSettingsController::UpdateBooleanVariable (op, m_auto_confirm_on, value, false, err); UserSettingsController::UpdateBooleanVariable (op, m_auto_confirm_on, value, false, err);
} }
else if (var_name == StopSourceContextBeforeName ())
{
uint32_t new_value = Args::StringToUInt32(value, UINT32_MAX, 10, NULL);
if (new_value != UINT32_MAX)
m_stop_source_before_count = new_value;
else
err.SetErrorStringWithFormat("invalid unsigned string value '%s' for the '%s' setting", value, StopSourceContextAfterName ().GetCString());
}
else if (var_name == StopSourceContextAfterName ())
{
uint32_t new_value = Args::StringToUInt32(value, UINT32_MAX, 10, NULL);
if (new_value != UINT32_MAX)
m_stop_source_after_count = new_value;
else
err.SetErrorStringWithFormat("invalid unsigned string value '%s' for the '%s' setting", value, StopSourceContextBeforeName ().GetCString());
}
else if (var_name == StopDisassemblyCountName ())
{
uint32_t new_value = Args::StringToUInt32(value, UINT32_MAX, 10, NULL);
if (new_value != UINT32_MAX)
m_stop_disassembly_count = new_value;
else
err.SetErrorStringWithFormat("invalid unsigned string value '%s' for the '%s' setting", value, StopDisassemblyCountName ().GetCString());
}
else if (var_name == StopDisassemblyDisplayName ())
{
int new_value;
UserSettingsController::UpdateEnumVariable (g_show_disassembly_enum_values, &new_value, value, err);
if (err.Success())
m_stop_disassembly_display = (StopDisassemblyType)new_value;
}
} }
bool bool
@ -2275,7 +2398,7 @@ DebuggerInstanceSettings::GetInstanceSettingsValue (const SettingEntry &entry,
else if (var_name == TermWidthVarName()) else if (var_name == TermWidthVarName())
{ {
StreamString width_str; StreamString width_str;
width_str.Printf ("%d", m_term_width); width_str.Printf ("%u", m_term_width);
value.AppendString (width_str.GetData()); value.AppendString (width_str.GetData());
} }
else if (var_name == GetFrameFormatName ()) else if (var_name == GetFrameFormatName ())
@ -2300,6 +2423,31 @@ DebuggerInstanceSettings::GetInstanceSettingsValue (const SettingEntry &entry,
else else
value.AppendString ("false"); value.AppendString ("false");
} }
else if (var_name == StopSourceContextAfterName ())
{
StreamString strm;
strm.Printf ("%u", m_stop_source_before_count);
value.AppendString (strm.GetData());
}
else if (var_name == StopSourceContextBeforeName ())
{
StreamString strm;
strm.Printf ("%u", m_stop_source_after_count);
value.AppendString (strm.GetData());
}
else if (var_name == StopDisassemblyCountName ())
{
StreamString strm;
strm.Printf ("%u", m_stop_disassembly_count);
value.AppendString (strm.GetData());
}
else if (var_name == StopDisassemblyDisplayName ())
{
if (m_stop_disassembly_display >= eStopDisassemblyTypeNever && m_stop_disassembly_display <= eStopDisassemblyTypeAlways)
value.AppendString (g_show_disassembly_enum_values[m_stop_disassembly_display].string_value);
else
value.AppendString ("<invalid>");
}
else else
{ {
if (err) if (err)
@ -2391,61 +2539,6 @@ DebuggerInstanceSettings::CreateInstanceName ()
return ret_val; return ret_val;
} }
const ConstString &
DebuggerInstanceSettings::PromptVarName ()
{
static ConstString prompt_var_name ("prompt");
return prompt_var_name;
}
const ConstString &
DebuggerInstanceSettings::GetFrameFormatName ()
{
static ConstString prompt_var_name ("frame-format");
return prompt_var_name;
}
const ConstString &
DebuggerInstanceSettings::GetThreadFormatName ()
{
static ConstString prompt_var_name ("thread-format");
return prompt_var_name;
}
const ConstString &
DebuggerInstanceSettings::ScriptLangVarName ()
{
static ConstString script_lang_var_name ("script-lang");
return script_lang_var_name;
}
const ConstString &
DebuggerInstanceSettings::TermWidthVarName ()
{
static ConstString term_width_var_name ("term-width");
return term_width_var_name;
}
const ConstString &
DebuggerInstanceSettings::UseExternalEditorVarName ()
{
static ConstString use_external_editor_var_name ("use-external-editor");
return use_external_editor_var_name;
}
const ConstString &
DebuggerInstanceSettings::AutoConfirmName ()
{
static ConstString use_external_editor_var_name ("auto-confirm");
return use_external_editor_var_name;
}
//-------------------------------------------------- //--------------------------------------------------
// SettingsController Variable Tables // SettingsController Variable Tables
@ -2497,5 +2590,9 @@ Debugger::SettingsController::instance_settings_table[] =
{ "thread-format", eSetVarTypeString, DEFAULT_THREAD_FORMAT, NULL, false, false, "The default thread format string to use when displaying thread information." }, { "thread-format", eSetVarTypeString, DEFAULT_THREAD_FORMAT, NULL, false, false, "The default thread format string to use when displaying thread information." },
{ "use-external-editor", eSetVarTypeBoolean, "false", NULL, false, false, "Whether to use an external editor or not." }, { "use-external-editor", eSetVarTypeBoolean, "false", NULL, false, false, "Whether to use an external editor or not." },
{ "auto-confirm", eSetVarTypeBoolean, "false", NULL, false, false, "If true all confirmation prompts will receive their default reply." }, { "auto-confirm", eSetVarTypeBoolean, "false", NULL, false, false, "If true all confirmation prompts will receive their default reply." },
{ "stop-line-count-before",eSetVarTypeInt, "3", NULL, false, false, "The number of sources lines to display that come before the current source line when displaying a stopped context." },
{ "stop-line-count-after", eSetVarTypeInt, "3", NULL, false, false, "The number of sources lines to display that come after the current source line when displaying a stopped context." },
{ "stop-disassembly-count", eSetVarTypeInt, "0", NULL, false, false, "The number of disassembly lines to show when displaying a stopped context." },
{ "stop-disassembly-display", eSetVarTypeEnum, "no-source", g_show_disassembly_enum_values, false, false, "Control when to display disassembly when displaying a stopped context." },
{ NULL, eSetVarTypeNone, NULL, NULL, false, false, NULL } { NULL, eSetVarTypeNone, NULL, NULL, false, false, NULL }
}; };

View File

@ -1269,20 +1269,63 @@ StackFrame::GetStatus (Stream& strm,
} }
if (show_source) if (show_source)
{
Target &target = GetThread().GetProcess().GetTarget();
Debugger &debugger = target.GetDebugger();
const uint32_t source_before = debugger.GetStopSourceLineCount(true);
const uint32_t source_after = debugger.GetStopSourceLineCount(false);
bool have_source = false;
if (source_before || source_after)
{ {
GetSymbolContext(eSymbolContextCompUnit | eSymbolContextLineEntry); GetSymbolContext(eSymbolContextCompUnit | eSymbolContextLineEntry);
if (m_sc.comp_unit && m_sc.line_entry.IsValid()) if (m_sc.comp_unit && m_sc.line_entry.IsValid())
{ {
Target &target = GetThread().GetProcess().GetTarget(); if (target.GetSourceManager().DisplaySourceLinesWithLineNumbers (m_sc.line_entry.file,
target.GetSourceManager().DisplaySourceLinesWithLineNumbers (
m_sc.line_entry.file,
m_sc.line_entry.line, m_sc.line_entry.line,
3, source_before,
3, source_after,
"->", "->",
&strm); &strm))
{
have_source = true;
}
}
}
DebuggerInstanceSettings::StopDisassemblyType disasm_display = debugger.GetStopDisassemblyDisplay ();
switch (disasm_display)
{
case DebuggerInstanceSettings::eStopDisassemblyTypeNever:
break;
case DebuggerInstanceSettings::eStopDisassemblyTypeNoSource:
if (have_source)
break;
// Fall through to next case
case DebuggerInstanceSettings::eStopDisassemblyTypeAlways:
{
const uint32_t disasm_lines = debugger.GetDisassemblyLineCount();
if (disasm_lines > 0)
{
const ArchSpec &target_arch = target.GetArchitecture();
AddressRange pc_range;
pc_range.GetBaseAddress() = GetFrameCodeAddress();
pc_range.SetByteSize(disasm_lines * target_arch.GetMaximumOpcodeByteSize());
ExecutionContext exe_ctx;
CalculateExecutionContext(exe_ctx);
Disassembler::Disassemble (debugger,
target_arch,
NULL,
exe_ctx,
pc_range,
disasm_lines,
0,
Disassembler::eOptionMarkPCAddress,
strm);
}
}
break;
} }
} }
return true; return true;