Add the ability to disassemble "n" instructions from the current PC, or the first "n" instructions in a function.
Also added a "-p" flag that disassembles from the current pc.
git-svn-id: https://llvm.org/svn/llvm-project/llvdb/trunk@128063 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/source/Commands/CommandObjectDisassemble.cpp b/source/Commands/CommandObjectDisassemble.cpp
index a4dd5ac..ecfd30f 100644
--- a/source/Commands/CommandObjectDisassemble.cpp
+++ b/source/Commands/CommandObjectDisassemble.cpp
@@ -27,15 +27,19 @@
#include "lldb/Target/Target.h"
#define DEFAULT_DISASM_BYTE_SIZE 32
+#define DEFAULT_DISASM_NUM_INS 4
using namespace lldb;
using namespace lldb_private;
CommandObjectDisassemble::CommandOptions::CommandOptions () :
Options(),
+ num_lines_context(0),
+ num_instructions (0),
m_func_name(),
m_start_addr(),
- m_end_addr ()
+ m_end_addr (),
+ m_at_pc (false)
{
ResetOptionValues();
}
@@ -51,14 +55,24 @@
char short_option = (char) m_getopt_table[option_idx].val;
+ bool success;
+
switch (short_option)
{
case 'm':
show_mixed = true;
break;
+ case 'x':
+ num_lines_context = Args::StringToUInt32(option_arg, 0, 0, &success);
+ if (!success)
+ error.SetErrorStringWithFormat ("Invalid num context lines string: \"%s\".\n", option_arg);
+ break;
+
case 'c':
- num_lines_context = Args::StringToUInt32(option_arg, 0, 0);
+ num_instructions = Args::StringToUInt32(option_arg, 0, 0, &success);
+ if (!success)
+ error.SetErrorStringWithFormat ("Invalid num of instructions string: \"%s\".\n", option_arg);
break;
case 'b':
@@ -66,26 +80,30 @@
break;
case 's':
- m_start_addr = Args::StringToUInt64(optarg, LLDB_INVALID_ADDRESS, 0);
+ m_start_addr = Args::StringToUInt64(option_arg, LLDB_INVALID_ADDRESS, 0);
if (m_start_addr == LLDB_INVALID_ADDRESS)
- m_start_addr = Args::StringToUInt64(optarg, LLDB_INVALID_ADDRESS, 16);
+ m_start_addr = Args::StringToUInt64(option_arg, LLDB_INVALID_ADDRESS, 16);
if (m_start_addr == LLDB_INVALID_ADDRESS)
- error.SetErrorStringWithFormat ("Invalid start address string '%s'.\n", optarg);
+ error.SetErrorStringWithFormat ("Invalid start address string '%s'.\n", option_arg);
break;
case 'e':
- m_end_addr = Args::StringToUInt64(optarg, LLDB_INVALID_ADDRESS, 0);
+ m_end_addr = Args::StringToUInt64(option_arg, LLDB_INVALID_ADDRESS, 0);
if (m_end_addr == LLDB_INVALID_ADDRESS)
- m_end_addr = Args::StringToUInt64(optarg, LLDB_INVALID_ADDRESS, 16);
+ m_end_addr = Args::StringToUInt64(option_arg, LLDB_INVALID_ADDRESS, 16);
if (m_end_addr == LLDB_INVALID_ADDRESS)
- error.SetErrorStringWithFormat ("Invalid end address string '%s'.\n", optarg);
+ error.SetErrorStringWithFormat ("Invalid end address string '%s'.\n", option_arg);
break;
case 'n':
m_func_name = option_arg;
break;
+ case 'p':
+ m_at_pc = true;
+ break;
+
case 'r':
raw = true;
break;
@@ -110,7 +128,9 @@
show_mixed = false;
show_bytes = false;
num_lines_context = 0;
+ num_instructions = 0;
m_func_name.clear();
+ m_at_pc = false;
m_start_addr = LLDB_INVALID_ADDRESS;
m_end_addr = LLDB_INVALID_ADDRESS;
raw = false;
@@ -126,16 +146,24 @@
CommandObjectDisassemble::CommandOptions::g_option_table[] =
{
{ LLDB_OPT_SET_ALL, false, "bytes", 'b', no_argument, NULL, 0, eArgTypeNone, "Show opcode bytes when disassembling."},
-{ LLDB_OPT_SET_ALL, false, "context", 'c', required_argument, NULL, 0, eArgTypeNumLines, "Number of context lines of source to show."},
+{ LLDB_OPT_SET_ALL, false, "context", 'x', required_argument, NULL, 0, eArgTypeNumLines, "Number of context lines of source to show."},
{ LLDB_OPT_SET_ALL, false, "mixed", 'm', no_argument, NULL, 0, eArgTypeNone, "Enable mixed source and assembly display."},
{ LLDB_OPT_SET_ALL, false, "raw", 'r', no_argument, NULL, 0, eArgTypeNone, "Print raw disassembly with no symbol information."},
{ LLDB_OPT_SET_1, true, "start-address", 's', required_argument, NULL, 0, eArgTypeStartAddress, "Address at which to start disassembling."},
{ LLDB_OPT_SET_1, false, "end-address", 'e', required_argument, NULL, 0, eArgTypeEndAddress, "Address at which to end disassembling."},
-{ LLDB_OPT_SET_2, true, "name", 'n', required_argument, NULL, CommandCompletions::eSymbolCompletion, eArgTypeFunctionName, "Disassemble entire contents of the given function name."},
+{ LLDB_OPT_SET_2, true, "start-address", 's', required_argument, NULL, 0, eArgTypeStartAddress, "Address at which to start disassembling."},
+{ LLDB_OPT_SET_2, false, "instruction-count", 'c', required_argument, NULL, 0, eArgTypeNumLines, "Number of instructions to display."},
-{ LLDB_OPT_SET_3, true, "current-frame", 'f', no_argument, NULL, 0, eArgTypeNone, "Disassemble entire contents of the current frame's function."},
+{ LLDB_OPT_SET_3, true, "name", 'n', required_argument, NULL, CommandCompletions::eSymbolCompletion, eArgTypeFunctionName, "Disassemble entire contents of the given function name."},
+{ LLDB_OPT_SET_3, false, "instruction-count", 'c', required_argument, NULL, 0, eArgTypeNumLines, "Number of instructions to display."},
+
+{ LLDB_OPT_SET_4, true, "current-frame", 'f', no_argument, NULL, 0, eArgTypeNone, "Disassemble from the start of the current frame's function."},
+{ LLDB_OPT_SET_4, false, "instruction-count", 'c', required_argument, NULL, 0, eArgTypeNumLines, "Number of instructions to display."},
+
+{ LLDB_OPT_SET_5, true, "current-pc", 'p', no_argument, NULL, 0, eArgTypeNone, "Disassemble from the current pc."},
+{ LLDB_OPT_SET_5, false, "instruction-count", 'c', required_argument, NULL, 0, eArgTypeNumLines, "Number of instructions to display."},
{ 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL }
};
@@ -202,11 +230,12 @@
result.SetStatus (eReturnStatusFailed);
return false;
}
- ExecutionContext exe_ctx(m_interpreter.GetDebugger().GetExecutionContext());
-
+
if (m_options.show_mixed && m_options.num_lines_context == 0)
m_options.num_lines_context = 1;
+ ExecutionContext exe_ctx(m_interpreter.GetDebugger().GetExecutionContext());
+
if (!m_options.m_func_name.empty())
{
ConstString name(m_options.m_func_name.c_str());
@@ -216,6 +245,7 @@
exe_ctx,
name,
NULL, // Module *
+ m_options.num_instructions,
m_options.show_mixed ? m_options.num_lines_context : 0,
m_options.show_bytes,
m_options.raw,
@@ -231,61 +261,132 @@
}
else
{
- AddressRange range;
- if (m_options.m_start_addr != LLDB_INVALID_ADDRESS)
+ Address start_addr;
+ lldb::addr_t range_byte_size = DEFAULT_DISASM_BYTE_SIZE;
+
+ if (m_options.m_at_pc)
{
- range.GetBaseAddress().SetOffset (m_options.m_start_addr);
- if (m_options.m_end_addr != LLDB_INVALID_ADDRESS)
+ if (exe_ctx.frame == NULL)
{
- if (m_options.m_end_addr < m_options.m_start_addr)
- {
- result.AppendErrorWithFormat ("End address before start address.\n");
- result.SetStatus (eReturnStatusFailed);
- return false;
- }
- range.SetByteSize (m_options.m_end_addr - m_options.m_start_addr);
- }
- else
- range.SetByteSize (DEFAULT_DISASM_BYTE_SIZE);
- }
- else
- {
- // The default action is to disassemble the current frame function.
- if (exe_ctx.frame)
- {
- SymbolContext sc(exe_ctx.frame->GetSymbolContext(eSymbolContextFunction | eSymbolContextSymbol));
- if (sc.function)
- range = sc.function->GetAddressRange();
- else if (sc.symbol && sc.symbol->GetAddressRangePtr())
- range = *sc.symbol->GetAddressRangePtr();
- else
- range.GetBaseAddress() = exe_ctx.frame->GetFrameCodeAddress();
- }
- else
- {
- result.AppendError ("invalid frame");
+ result.AppendError ("Cannot disassemble around the current PC without a selected frame.\n");
result.SetStatus (eReturnStatusFailed);
return false;
}
- }
- if (range.GetByteSize() == 0)
- range.SetByteSize(DEFAULT_DISASM_BYTE_SIZE);
-
- if (Disassembler::Disassemble (m_interpreter.GetDebugger(),
- arch,
- exe_ctx,
- range,
- m_options.show_mixed ? m_options.num_lines_context : 0,
- m_options.show_bytes,
- m_options.raw,
- result.GetOutputStream()))
- {
- result.SetStatus (eReturnStatusSuccessFinishResult);
+ start_addr = exe_ctx.frame->GetFrameCodeAddress();
+ if (m_options.num_instructions == 0)
+ {
+ // Disassembling at the PC always disassembles some number of instructions (not the whole function).
+ m_options.num_instructions = DEFAULT_DISASM_NUM_INS;
+ }
}
else
{
- result.AppendErrorWithFormat ("Failed to disassemble memory at 0x%8.8llx.\n", m_options.m_start_addr);
- result.SetStatus (eReturnStatusFailed);
+ start_addr.SetOffset (m_options.m_start_addr);
+ if (start_addr.IsValid())
+ {
+ if (m_options.m_end_addr != LLDB_INVALID_ADDRESS)
+ {
+ if (m_options.m_end_addr < m_options.m_start_addr)
+ {
+ result.AppendErrorWithFormat ("End address before start address.\n");
+ result.SetStatus (eReturnStatusFailed);
+ return false;
+ }
+ range_byte_size = m_options.m_end_addr - m_options.m_start_addr;
+ }
+ }
+ }
+
+ if (m_options.num_instructions != 0)
+ {
+ if (!start_addr.IsValid())
+ {
+ // The default action is to disassemble the current frame function.
+ if (exe_ctx.frame)
+ {
+ SymbolContext sc(exe_ctx.frame->GetSymbolContext(eSymbolContextFunction | eSymbolContextSymbol));
+ if (sc.function)
+ start_addr = sc.function->GetAddressRange().GetBaseAddress();
+ else if (sc.symbol && sc.symbol->GetAddressRangePtr())
+ start_addr = sc.symbol->GetAddressRangePtr()->GetBaseAddress();
+ else
+ start_addr = exe_ctx.frame->GetFrameCodeAddress();
+ }
+
+ if (!start_addr.IsValid())
+ {
+ result.AppendError ("invalid frame");
+ result.SetStatus (eReturnStatusFailed);
+ return false;
+ }
+ }
+
+ if (Disassembler::Disassemble (m_interpreter.GetDebugger(),
+ arch,
+ exe_ctx,
+ start_addr,
+ m_options.num_instructions,
+ m_options.show_mixed ? m_options.num_lines_context : 0,
+ m_options.show_bytes,
+ m_options.raw,
+ result.GetOutputStream()))
+ {
+ result.SetStatus (eReturnStatusSuccessFinishResult);
+ }
+ else
+ {
+ result.AppendErrorWithFormat ("Failed to disassemble memory at 0x%8.8llx.\n", m_options.m_start_addr);
+ result.SetStatus (eReturnStatusFailed);
+ }
+ }
+ else
+ {
+ AddressRange range;
+ if (start_addr.IsValid())
+ {
+ range.GetBaseAddress() = start_addr;
+ range.SetByteSize (range_byte_size);
+ }
+ else
+ {
+ // The default action is to disassemble the current frame function.
+ if (exe_ctx.frame)
+ {
+ SymbolContext sc(exe_ctx.frame->GetSymbolContext(eSymbolContextFunction | eSymbolContextSymbol));
+ if (sc.function)
+ range = sc.function->GetAddressRange();
+ else if (sc.symbol && sc.symbol->GetAddressRangePtr())
+ range = *sc.symbol->GetAddressRangePtr();
+ else
+ range.GetBaseAddress() = exe_ctx.frame->GetFrameCodeAddress();
+ }
+ else
+ {
+ result.AppendError ("invalid frame");
+ result.SetStatus (eReturnStatusFailed);
+ return false;
+ }
+ }
+ if (range.GetByteSize() == 0)
+ range.SetByteSize(DEFAULT_DISASM_BYTE_SIZE);
+
+ if (Disassembler::Disassemble (m_interpreter.GetDebugger(),
+ arch,
+ exe_ctx,
+ range,
+ m_options.num_instructions,
+ m_options.show_mixed ? m_options.num_lines_context : 0,
+ m_options.show_bytes,
+ m_options.raw,
+ result.GetOutputStream()))
+ {
+ result.SetStatus (eReturnStatusSuccessFinishResult);
+ }
+ else
+ {
+ result.AppendErrorWithFormat ("Failed to disassemble memory at 0x%8.8llx.\n", m_options.m_start_addr);
+ result.SetStatus (eReturnStatusFailed);
+ }
}
}