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.

llvm-svn: 128063
This commit is contained in:
Jim Ingham 2011-03-22 01:48:42 +00:00
parent 381e25b793
commit 37023b06bd
10 changed files with 479 additions and 171 deletions

View File

@ -111,6 +111,18 @@ public:
const ArchSpec &arch,
const ExecutionContext &exe_ctx,
const AddressRange &range,
uint32_t num_instructions,
uint32_t num_mixed_context_lines,
bool show_bytes,
bool raw,
Stream &strm);
static bool
Disassemble (Debugger &debugger,
const ArchSpec &arch,
const ExecutionContext &exe_ctx,
const Address &start,
uint32_t num_instructions,
uint32_t num_mixed_context_lines,
bool show_bytes,
bool raw,
@ -121,6 +133,7 @@ public:
const ArchSpec &arch,
const ExecutionContext &exe_ctx,
SymbolContextList &sc_list,
uint32_t num_instructions,
uint32_t num_mixed_context_lines,
bool show_bytes,
bool raw,
@ -132,6 +145,7 @@ public:
const ExecutionContext &exe_ctx,
const ConstString &name,
Module *module,
uint32_t num_instructions,
uint32_t num_mixed_context_lines,
bool show_bytes,
bool raw,
@ -141,6 +155,7 @@ public:
Disassemble (Debugger &debugger,
const ArchSpec &arch,
const ExecutionContext &exe_ctx,
uint32_t num_instructions,
uint32_t num_mixed_context_lines,
bool show_bytes,
bool raw,
@ -154,16 +169,36 @@ public:
typedef const char * (*SummaryCallback)(const Instruction& inst, ExecutionContext *exe_context, void *user_data);
static bool
PrintInstructions (Disassembler *disasm_ptr,
DataExtractor &data,
Debugger &debugger,
const ArchSpec &arch,
const ExecutionContext &exe_ctx,
const Address &start_addr,
uint32_t num_instructions,
uint32_t num_mixed_context_lines,
bool show_bytes,
bool raw,
Stream &strm);
size_t
ParseInstructions (const ExecutionContext *exe_ctx,
const AddressRange &range,
DataExtractor& data);
size_t
ParseInstructions (const ExecutionContext *exe_ctx,
const Address &range,
uint32_t num_instructions,
DataExtractor& data);
virtual size_t
DecodeInstructions (const Address &base_addr,
const DataExtractor& data,
uint32_t data_offset,
uint32_t num_instructions) = 0;
uint32_t num_instructions,
bool append) = 0;
InstructionList &
GetInstructionList ();

View File

@ -1231,11 +1231,11 @@
08FB7794FE84155DC02AAC07 /* lldb */ = {
isa = PBXGroup;
children = (
2689FFCA13353D7A00698AC0 /* liblldb-core.a */,
26F5C32810F3DF7D009D5894 /* Libraries */,
08FB7795FE84155DC02AAC07 /* Source */,
26F5C22410F3D950009D5894 /* Tools */,
1AB674ADFE9D54B511CA2CBB /* Products */,
2689FFCA13353D7A00698AC0 /* liblldb-core.a */,
);
name = lldb;
sourceTree = "<group>";

View File

@ -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 @@ CommandObjectDisassemble::CommandOptions::SetOptionValue (int option_idx, const
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 @@ CommandObjectDisassemble::CommandOptions::SetOptionValue (int option_idx, const
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 @@ CommandObjectDisassemble::CommandOptions::ResetOptionValues ()
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 @@ lldb::OptionDefinition
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 @@ CommandObjectDisassemble::Execute
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 @@ CommandObjectDisassemble::Execute
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 @@ CommandObjectDisassemble::Execute
}
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);
}
}
}

View File

@ -47,10 +47,12 @@ public:
bool show_mixed; // Show mixed source/assembly
bool show_bytes;
uint32_t num_lines_context;
uint32_t num_instructions;
bool raw;
std::string m_func_name;
lldb::addr_t m_start_addr;
lldb::addr_t m_end_addr;
bool m_at_pc;
static lldb::OptionDefinition g_option_table[];
};

View File

@ -61,6 +61,7 @@ Disassembler::Disassemble
const ArchSpec &arch,
const ExecutionContext &exe_ctx,
SymbolContextList &sc_list,
uint32_t num_instructions,
uint32_t num_mixed_context_lines,
bool show_bytes,
bool raw,
@ -71,13 +72,15 @@ Disassembler::Disassemble
const size_t count = sc_list.GetSize();
SymbolContext sc;
AddressRange range;
for (size_t i=0; i<count; ++i)
{
if (sc_list.GetContextAtIndex(i, sc) == false)
break;
if (sc.GetAddressRange(eSymbolContextFunction | eSymbolContextSymbol, range))
{
if (Disassemble (debugger, arch, exe_ctx, range, num_mixed_context_lines, show_bytes, raw, strm))
if (Disassemble (debugger, arch, exe_ctx, range, num_instructions,
num_mixed_context_lines, show_bytes, raw, strm))
{
++success_count;
strm.EOL();
@ -95,6 +98,7 @@ Disassembler::Disassemble
const ExecutionContext &exe_ctx,
const ConstString &name,
Module *module,
uint32_t num_instructions,
uint32_t num_mixed_context_lines,
bool show_bytes,
bool raw,
@ -134,7 +138,8 @@ Disassembler::Disassemble
return Disassemble (debugger,
arch,
exe_ctx,
sc_list,
sc_list,
num_instructions,
num_mixed_context_lines,
show_bytes,
raw,
@ -176,6 +181,7 @@ Disassembler::Disassemble
const ArchSpec &arch,
const ExecutionContext &exe_ctx,
const AddressRange &disasm_range,
uint32_t num_instructions,
uint32_t num_mixed_context_lines,
bool show_bytes,
bool raw,
@ -190,8 +196,6 @@ Disassembler::Disassemble
{
AddressRange range(disasm_range);
Process *process = exe_ctx.process;
// If we weren't passed in a section offset address range,
// try and resolve it to something
if (range.GetBaseAddress().IsSectionOffset() == false)
@ -217,117 +221,212 @@ Disassembler::Disassemble
}
else
{
// We got some things disassembled...
size_t num_instructions = disasm_ap->GetInstructionList().GetSize();
uint32_t offset = 0;
SymbolContext sc;
SymbolContext prev_sc;
AddressRange sc_range;
if (num_mixed_context_lines)
strm.IndentMore ();
return PrintInstructions (disasm_ap.get(),
data,
debugger,
arch,
exe_ctx,
disasm_range.GetBaseAddress(),
num_instructions,
num_mixed_context_lines,
show_bytes,
raw,
strm);
}
}
}
return false;
}
bool
Disassembler::Disassemble
(
Debugger &debugger,
const ArchSpec &arch,
const ExecutionContext &exe_ctx,
const Address &start_address,
uint32_t num_instructions,
uint32_t num_mixed_context_lines,
bool show_bytes,
bool raw,
Stream &strm
)
{
if (num_instructions > 0)
{
std::auto_ptr<Disassembler> disasm_ap (Disassembler::FindPlugin(arch));
Address addr = start_address;
Address addr(range.GetBaseAddress());
// We extract the section to make sure we don't transition out
// of the current section when disassembling
const Section *addr_section = addr.GetSection();
Module *range_module = range.GetBaseAddress().GetModule();
for (size_t i=0; i<num_instructions; ++i)
if (disasm_ap.get())
{
// If we weren't passed in a section offset address range,
// try and resolve it to something
if (addr.IsSectionOffset() == false)
{
if (exe_ctx.target)
{
Instruction *inst = disasm_ap->GetInstructionList().GetInstructionAtIndex (i).get();
if (inst)
if (exe_ctx.target->GetSectionLoadList().IsEmpty())
{
addr_t file_addr = addr.GetFileAddress();
if (addr_section == NULL || addr_section->ContainsFileAddress (file_addr) == false)
{
if (range_module)
range_module->ResolveFileAddress (file_addr, addr);
else if (exe_ctx.target)
exe_ctx.target->GetImages().ResolveFileAddress (file_addr, addr);
addr_section = addr.GetSection();
}
prev_sc = sc;
if (addr_section)
{
Module *module = addr_section->GetModule();
uint32_t resolved_mask = module->ResolveSymbolContextForAddress(addr, eSymbolContextEverything, sc);
if (resolved_mask)
{
if (!(prev_sc.function == sc.function || prev_sc.symbol == sc.symbol))
{
if (prev_sc.function || prev_sc.symbol)
strm.EOL();
strm << sc.module_sp->GetFileSpec().GetFilename();
if (sc.function)
strm << '`' << sc.function->GetMangled().GetName();
else if (sc.symbol)
strm << '`' << sc.symbol->GetMangled().GetName();
strm << ":\n";
}
if (num_mixed_context_lines && !sc_range.ContainsFileAddress (addr))
{
sc.GetAddressRange (eSymbolContextEverything, sc_range);
if (sc != prev_sc)
{
if (offset != 0)
strm.EOL();
sc.DumpStopContext(&strm, process, addr, false, true, false);
strm.EOL();
if (sc.comp_unit && sc.line_entry.IsValid())
{
debugger.GetSourceManager().DisplaySourceLinesWithLineNumbers (sc.line_entry.file,
sc.line_entry.line,
num_mixed_context_lines,
num_mixed_context_lines,
num_mixed_context_lines ? "->" : "",
&strm);
}
}
}
}
else
{
sc.Clear();
}
}
if (num_mixed_context_lines)
strm.IndentMore ();
strm.Indent();
size_t inst_byte_size = inst->GetByteSize();
inst->Dump(&strm, true, show_bytes ? &data : NULL, offset, &exe_ctx, raw);
strm.EOL();
offset += inst_byte_size;
addr.SetOffset (addr.GetOffset() + inst_byte_size);
if (num_mixed_context_lines)
strm.IndentLess ();
exe_ctx.target->GetImages().ResolveFileAddress (addr.GetOffset(), addr);
}
else
{
break;
exe_ctx.target->GetSectionLoadList().ResolveLoadAddress (addr.GetOffset(), addr);
}
}
if (num_mixed_context_lines)
strm.IndentLess ();
}
DataExtractor data;
size_t bytes_disassembled = disasm_ap->ParseInstructions (&exe_ctx, addr, num_instructions, data);
if (bytes_disassembled == 0)
{
return false;
}
else
{
return PrintInstructions (disasm_ap.get(),
data,
debugger,
arch,
exe_ctx,
addr,
num_instructions,
num_mixed_context_lines,
show_bytes,
raw,
strm);
}
}
return true;
}
return false;
}
bool
Disassembler::PrintInstructions
(
Disassembler *disasm_ptr,
DataExtractor &data,
Debugger &debugger,
const ArchSpec &arch,
const ExecutionContext &exe_ctx,
const Address &start_addr,
uint32_t num_instructions,
uint32_t num_mixed_context_lines,
bool show_bytes,
bool raw,
Stream &strm
)
{
// We got some things disassembled...
size_t num_instructions_found = disasm_ptr->GetInstructionList().GetSize();
if (num_instructions > 0 && num_instructions < num_instructions_found)
num_instructions_found = num_instructions;
uint32_t offset = 0;
SymbolContext sc;
SymbolContext prev_sc;
AddressRange sc_range;
Address addr = start_addr;
if (num_mixed_context_lines)
strm.IndentMore ();
// We extract the section to make sure we don't transition out
// of the current section when disassembling
const Section *addr_section = addr.GetSection();
Module *range_module = addr.GetModule();
for (size_t i=0; i<num_instructions_found; ++i)
{
Instruction *inst = disasm_ptr->GetInstructionList().GetInstructionAtIndex (i).get();
if (inst)
{
addr_t file_addr = addr.GetFileAddress();
if (addr_section == NULL || addr_section->ContainsFileAddress (file_addr) == false)
{
if (range_module)
range_module->ResolveFileAddress (file_addr, addr);
else if (exe_ctx.target)
exe_ctx.target->GetImages().ResolveFileAddress (file_addr, addr);
addr_section = addr.GetSection();
}
prev_sc = sc;
if (addr_section)
{
Module *module = addr_section->GetModule();
uint32_t resolved_mask = module->ResolveSymbolContextForAddress(addr, eSymbolContextEverything, sc);
if (resolved_mask)
{
if (!(prev_sc.function == sc.function || prev_sc.symbol == sc.symbol))
{
if (prev_sc.function || prev_sc.symbol)
strm.EOL();
strm << sc.module_sp->GetFileSpec().GetFilename();
if (sc.function)
strm << '`' << sc.function->GetMangled().GetName();
else if (sc.symbol)
strm << '`' << sc.symbol->GetMangled().GetName();
strm << ":\n";
}
if (num_mixed_context_lines && !sc_range.ContainsFileAddress (addr))
{
sc.GetAddressRange (eSymbolContextEverything, sc_range);
if (sc != prev_sc)
{
if (offset != 0)
strm.EOL();
sc.DumpStopContext(&strm, exe_ctx.process, addr, false, true, false);
strm.EOL();
if (sc.comp_unit && sc.line_entry.IsValid())
{
debugger.GetSourceManager().DisplaySourceLinesWithLineNumbers (sc.line_entry.file,
sc.line_entry.line,
num_mixed_context_lines,
num_mixed_context_lines,
num_mixed_context_lines ? "->" : "",
&strm);
}
}
}
}
else
{
sc.Clear();
}
}
if (num_mixed_context_lines)
strm.IndentMore ();
strm.Indent();
size_t inst_byte_size = inst->GetByteSize();
inst->Dump(&strm, true, show_bytes ? &data : NULL, offset, &exe_ctx, raw);
strm.EOL();
offset += inst_byte_size;
addr.SetOffset (addr.GetOffset() + inst_byte_size);
if (num_mixed_context_lines)
strm.IndentLess ();
}
else
{
break;
}
}
if (num_mixed_context_lines)
strm.IndentLess ();
return true;
}
bool
@ -336,6 +435,7 @@ Disassembler::Disassemble
Debugger &debugger,
const ArchSpec &arch,
const ExecutionContext &exe_ctx,
uint32_t num_instructions,
uint32_t num_mixed_context_lines,
bool show_bytes,
bool raw,
@ -363,7 +463,7 @@ Disassembler::Disassemble
range.SetByteSize (DEFAULT_DISASM_BYTE_SIZE);
}
return Disassemble(debugger, arch, exe_ctx, range, num_mixed_context_lines, show_bytes, raw, strm);
return Disassemble(debugger, arch, exe_ctx, range, num_instructions, num_mixed_context_lines, show_bytes, raw, strm);
}
Instruction::Instruction(const Address &addr) :
@ -443,12 +543,78 @@ Disassembler::ParseInstructions
data.SetData(data_sp);
data.SetByteOrder(target->GetArchitecture().GetByteOrder());
data.SetAddressByteSize(target->GetArchitecture().GetAddressByteSize());
return DecodeInstructions (range.GetBaseAddress(), data, 0, UINT32_MAX);
return DecodeInstructions (range.GetBaseAddress(), data, 0, UINT32_MAX, false);
}
return 0;
}
size_t
Disassembler::ParseInstructions
(
const ExecutionContext *exe_ctx,
const Address &start,
uint32_t num_instructions,
DataExtractor& data
)
{
Address addr = start;
if (num_instructions == 0)
return 0;
Target *target = exe_ctx->target;
// We'll guess at a size for the buffer, if we don't get all the instructions we want we can just re-fill & reuse it.
const addr_t byte_size = num_instructions * 2;
addr_t data_offset = 0;
addr_t next_instruction_offset = 0;
size_t buffer_size = byte_size;
uint32_t num_instructions_found = 0;
if (target == NULL || byte_size == 0 || !start.IsValid())
return 0;
DataBufferHeap *heap_buffer = new DataBufferHeap (byte_size, '\0');
DataBufferSP data_sp(heap_buffer);
data.SetData(data_sp);
data.SetByteOrder(target->GetArchitecture().GetByteOrder());
data.SetAddressByteSize(target->GetArchitecture().GetAddressByteSize());
Error error;
bool prefer_file_cache = true;
m_instruction_list.Clear();
while (num_instructions_found < num_instructions)
{
if (buffer_size < data_offset + byte_size)
{
buffer_size = data_offset + byte_size;
heap_buffer->SetByteSize (buffer_size);
data.SetData(data_sp); // Resizing might have changed the backing store location, so we have to reset
// the DataBufferSP in the extractor so it changes to pointing at the right thing.
}
const size_t bytes_read = target->ReadMemory (addr, prefer_file_cache, heap_buffer->GetBytes() + data_offset, byte_size, error);
size_t num_bytes_read = 0;
if (bytes_read == 0)
break;
num_bytes_read = DecodeInstructions (start, data, next_instruction_offset, num_instructions - num_instructions_found, true);
if (num_bytes_read == 0)
break;
num_instructions_found = m_instruction_list.GetSize();
// Prepare for the next round.
data_offset += bytes_read;
addr.Slide (bytes_read);
next_instruction_offset += num_bytes_read;
}
return m_instruction_list.GetSize();
}
//----------------------------------------------------------------------
// Disassembler copy constructor
//----------------------------------------------------------------------

View File

@ -739,7 +739,7 @@ ClangExpressionParser::DisassembleFunction (Stream &stream, ExecutionContext &ex
DataExtractor::TypeUInt8);
}
disassembler->DecodeInstructions (Address (NULL, func_remote_addr), extractor, 0, UINT32_MAX);
disassembler->DecodeInstructions (Address (NULL, func_remote_addr), extractor, 0, UINT32_MAX, false);
InstructionList &instruction_list = disassembler->GetInstructionList();

View File

@ -404,7 +404,8 @@ DisassemblerLLVM::DecodeInstructions
const Address &base_addr,
const DataExtractor& data,
uint32_t data_offset,
uint32_t num_instructions
uint32_t num_instructions,
bool append
)
{
if (m_disassembler == NULL)
@ -412,7 +413,8 @@ DisassemblerLLVM::DecodeInstructions
size_t total_inst_byte_size = 0;
m_instruction_list.Clear();
if (!append)
m_instruction_list.Clear();
while (data.ValidOffset(data_offset) && num_instructions)
{

View File

@ -78,7 +78,8 @@ public:
DecodeInstructions (const lldb_private::Address &base_addr,
const lldb_private::DataExtractor& data,
uint32_t data_offset,
uint32_t num_instructions);
uint32_t num_instructions,
bool append);
//------------------------------------------------------------------
// PluginInterface protocol

View File

@ -260,6 +260,7 @@ StackFrame::Disassemble ()
target.GetArchitecture(),
exe_ctx,
0,
0,
false,
false,
m_disassembly);

View File

@ -204,9 +204,9 @@ ThreadPlanAssemblyTracer::Log ()
m_process.GetAddressByteSize());
if (addr_valid)
m_disassembler->DecodeInstructions (pc_addr, extractor, 0, 1);
m_disassembler->DecodeInstructions (pc_addr, extractor, 0, 1, false);
else
m_disassembler->DecodeInstructions (Address (NULL, pc), extractor, 0, 1);
m_disassembler->DecodeInstructions (Address (NULL, pc), extractor, 0, 1, false);
InstructionList &instruction_list = m_disassembler->GetInstructionList();