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
diff --git a/lldb/source/Core/Disassembler.cpp b/lldb/source/Core/Disassembler.cpp
index fa7f483..9625894 100644
--- a/lldb/source/Core/Disassembler.cpp
+++ b/lldb/source/Core/Disassembler.cpp
@@ -61,6 +61,7 @@
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 @@
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 @@
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 @@
return Disassemble (debugger,
arch,
exe_ctx,
- sc_list,
+ sc_list,
+ num_instructions,
num_mixed_context_lines,
show_bytes,
raw,
@@ -176,6 +181,7 @@
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 @@
{
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 @@
}
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 @@
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 @@
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 @@
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
//----------------------------------------------------------------------