diff options
| author | Jim Ingham <jingham@apple.com> | 2011-03-22 01:48:42 +0000 |
|---|---|---|
| committer | Jim Ingham <jingham@apple.com> | 2011-03-22 01:48:42 +0000 |
| commit | 37023b06bd64f8a497bcedb6401e003bb124d7fc (patch) | |
| tree | ce9005f3bfd126afd4c2afe57dbc19e927bc0bee /lldb/source/Core | |
| parent | 381e25b793e65ff4cb50dc5624e259ab7fe15683 (diff) | |
| download | bcm5719-llvm-37023b06bd64f8a497bcedb6401e003bb124d7fc.tar.gz bcm5719-llvm-37023b06bd64f8a497bcedb6401e003bb124d7fc.zip | |
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
Diffstat (limited to 'lldb/source/Core')
| -rw-r--r-- | lldb/source/Core/Disassembler.cpp | 364 |
1 files changed, 265 insertions, 99 deletions
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 //---------------------------------------------------------------------- |

