diff options
Diffstat (limited to 'lldb/source')
-rw-r--r-- | lldb/source/Commands/CommandObjectDisassemble.cpp | 207 | ||||
-rw-r--r-- | lldb/source/Commands/CommandObjectDisassemble.h | 2 | ||||
-rw-r--r-- | lldb/source/Core/Disassembler.cpp | 364 | ||||
-rw-r--r-- | lldb/source/Expression/ClangExpressionParser.cpp | 2 | ||||
-rw-r--r-- | lldb/source/Plugins/Disassembler/llvm/DisassemblerLLVM.cpp | 6 | ||||
-rw-r--r-- | lldb/source/Plugins/Disassembler/llvm/DisassemblerLLVM.h | 3 | ||||
-rw-r--r-- | lldb/source/Target/StackFrame.cpp | 1 | ||||
-rw-r--r-- | lldb/source/Target/ThreadPlanTracer.cpp | 4 |
8 files changed, 431 insertions, 158 deletions
diff --git a/lldb/source/Commands/CommandObjectDisassemble.cpp b/lldb/source/Commands/CommandObjectDisassemble.cpp index a4dd5ac3805..ecfd30f648e 100644 --- a/lldb/source/Commands/CommandObjectDisassemble.cpp +++ b/lldb/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 @@ 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,62 +261,133 @@ 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) + { + if (exe_ctx.frame == NULL) + { + result.AppendError ("Cannot disassemble around the current PC without a selected frame.\n"); + result.SetStatus (eReturnStatusFailed); + return false; + } + 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 { - range.GetBaseAddress().SetOffset (m_options.m_start_addr); - if (m_options.m_end_addr != LLDB_INVALID_ADDRESS) + start_addr.SetOffset (m_options.m_start_addr); + if (start_addr.IsValid()) { - if (m_options.m_end_addr < m_options.m_start_addr) + if (m_options.m_end_addr != LLDB_INVALID_ADDRESS) { - result.AppendErrorWithFormat ("End address before start address.\n"); + 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; + return false; } - range.SetByteSize (m_options.m_end_addr - m_options.m_start_addr); + } + + 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 - range.SetByteSize (DEFAULT_DISASM_BYTE_SIZE); - } + { + result.AppendErrorWithFormat ("Failed to disassemble memory at 0x%8.8llx.\n", m_options.m_start_addr); + result.SetStatus (eReturnStatusFailed); + } + } else { - // The default action is to disassemble the current frame function. - if (exe_ctx.frame) + AddressRange range; + if (start_addr.IsValid()) + { + range.GetBaseAddress() = start_addr; + range.SetByteSize (range_byte_size); + } + else { - 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(); + // 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 - range.GetBaseAddress() = exe_ctx.frame->GetFrameCodeAddress(); + { + 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.AppendError ("invalid frame"); - result.SetStatus (eReturnStatusFailed); - return false; + result.AppendErrorWithFormat ("Failed to disassemble memory at 0x%8.8llx.\n", m_options.m_start_addr); + result.SetStatus (eReturnStatusFailed); } } - 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); - } - else - { - result.AppendErrorWithFormat ("Failed to disassemble memory at 0x%8.8llx.\n", m_options.m_start_addr); - result.SetStatus (eReturnStatusFailed); - } } return result.Succeeded(); diff --git a/lldb/source/Commands/CommandObjectDisassemble.h b/lldb/source/Commands/CommandObjectDisassemble.h index 9b0e0ab2afe..a36ae88cb15 100644 --- a/lldb/source/Commands/CommandObjectDisassemble.h +++ b/lldb/source/Commands/CommandObjectDisassemble.h @@ -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[]; }; diff --git a/lldb/source/Core/Disassembler.cpp b/lldb/source/Core/Disassembler.cpp index fa7f4833d99..9625894386b 100644 --- a/lldb/source/Core/Disassembler.cpp +++ b/lldb/source/Core/Disassembler.cpp @@ -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,116 +221,211 @@ 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; + 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) + { + if (exe_ctx.target->GetSectionLoadList().IsEmpty()) + { + exe_ctx.target->GetImages().ResolveFileAddress (addr.GetOffset(), addr); + } + else + { + exe_ctx.target->GetSectionLoadList().ResolveLoadAddress (addr.GetOffset(), addr); + } + } + } - Address addr(range.GetBaseAddress()); + 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 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(); - // 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(); + 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; ++i) + 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) { - Instruction *inst = disasm_ap->GetInstructionList().GetInstructionAtIndex (i).get(); - if (inst) + if (!(prev_sc.function == sc.function || prev_sc.symbol == sc.symbol)) { - 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(); - } + if (prev_sc.function || prev_sc.symbol) + strm.EOL(); - prev_sc = sc; + 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 (addr_section) + if (num_mixed_context_lines && !sc_range.ContainsFileAddress (addr)) + { + sc.GetAddressRange (eSymbolContextEverything, sc_range); + + if (sc != prev_sc) { - 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 + 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()) { - sc.Clear(); + debugger.GetSourceManager().DisplaySourceLinesWithLineNumbers (sc.line_entry.file, + sc.line_entry.line, + num_mixed_context_lines, + num_mixed_context_lines, + num_mixed_context_lines ? "->" : "", + &strm); } } - 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 (); - + 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; } - return true; } - return false; + if (num_mixed_context_lines) + strm.IndentLess (); + + return true; } @@ -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 //---------------------------------------------------------------------- diff --git a/lldb/source/Expression/ClangExpressionParser.cpp b/lldb/source/Expression/ClangExpressionParser.cpp index 68301981576..e228cc5e080 100644 --- a/lldb/source/Expression/ClangExpressionParser.cpp +++ b/lldb/source/Expression/ClangExpressionParser.cpp @@ -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(); diff --git a/lldb/source/Plugins/Disassembler/llvm/DisassemblerLLVM.cpp b/lldb/source/Plugins/Disassembler/llvm/DisassemblerLLVM.cpp index 3b10a343209..ca51db346fc 100644 --- a/lldb/source/Plugins/Disassembler/llvm/DisassemblerLLVM.cpp +++ b/lldb/source/Plugins/Disassembler/llvm/DisassemblerLLVM.cpp @@ -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) { diff --git a/lldb/source/Plugins/Disassembler/llvm/DisassemblerLLVM.h b/lldb/source/Plugins/Disassembler/llvm/DisassemblerLLVM.h index 842c03d5dcd..012d4b685e8 100644 --- a/lldb/source/Plugins/Disassembler/llvm/DisassemblerLLVM.h +++ b/lldb/source/Plugins/Disassembler/llvm/DisassemblerLLVM.h @@ -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 diff --git a/lldb/source/Target/StackFrame.cpp b/lldb/source/Target/StackFrame.cpp index 60931fcfbb3..78ab910c79a 100644 --- a/lldb/source/Target/StackFrame.cpp +++ b/lldb/source/Target/StackFrame.cpp @@ -260,6 +260,7 @@ StackFrame::Disassemble () target.GetArchitecture(), exe_ctx, 0, + 0, false, false, m_disassembly); diff --git a/lldb/source/Target/ThreadPlanTracer.cpp b/lldb/source/Target/ThreadPlanTracer.cpp index a01550a5a39..b8b7627201a 100644 --- a/lldb/source/Target/ThreadPlanTracer.cpp +++ b/lldb/source/Target/ThreadPlanTracer.cpp @@ -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(); |