forked from OSchip/llvm-project
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:
parent
381e25b793
commit
37023b06bd
|
@ -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 ();
|
||||
|
|
|
@ -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>";
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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[];
|
||||
};
|
||||
|
||||
|
|
|
@ -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
|
||||
//----------------------------------------------------------------------
|
||||
|
|
|
@ -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();
|
||||
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -260,6 +260,7 @@ StackFrame::Disassemble ()
|
|||
target.GetArchitecture(),
|
||||
exe_ctx,
|
||||
0,
|
||||
0,
|
||||
false,
|
||||
false,
|
||||
m_disassembly);
|
||||
|
|
|
@ -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();
|
||||
|
||||
|
|
Loading…
Reference in New Issue