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
 //----------------------------------------------------------------------