1 //===-- Disassembler.cpp ----------------------------------------*- C++ -*-===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 
10 #include "lldb/Core/Disassembler.h"
11 
12 // C Includes
13 // C++ Includes
14 // Other libraries and framework includes
15 // Project includes
16 #include "lldb/lldb-private.h"
17 #include "lldb/Core/Error.h"
18 #include "lldb/Core/DataBufferHeap.h"
19 #include "lldb/Core/DataExtractor.h"
20 #include "lldb/Core/Debugger.h"
21 #include "lldb/Core/EmulateInstruction.h"
22 #include "lldb/Core/Module.h"
23 #include "lldb/Core/PluginManager.h"
24 #include "lldb/Core/RegularExpression.h"
25 #include "lldb/Core/Timer.h"
26 #include "lldb/Interpreter/NamedOptionValue.h"
27 #include "lldb/Symbol/ClangNamespaceDecl.h"
28 #include "lldb/Symbol/ObjectFile.h"
29 #include "lldb/Target/ExecutionContext.h"
30 #include "lldb/Target/Process.h"
31 #include "lldb/Target/StackFrame.h"
32 #include "lldb/Target/Target.h"
33 
34 #define DEFAULT_DISASM_BYTE_SIZE 32
35 
36 using namespace lldb;
37 using namespace lldb_private;
38 
39 
40 DisassemblerSP
41 Disassembler::FindPlugin (const ArchSpec &arch, const char *plugin_name)
42 {
43     Timer scoped_timer (__PRETTY_FUNCTION__,
44                         "Disassembler::FindPlugin (arch = %s, plugin_name = %s)",
45                         arch.GetArchitectureName(),
46                         plugin_name);
47 
48     DisassemblerCreateInstance create_callback = NULL;
49 
50     if (plugin_name)
51     {
52         create_callback = PluginManager::GetDisassemblerCreateCallbackForPluginName (plugin_name);
53         if (create_callback)
54         {
55             DisassemblerSP disassembler_sp(create_callback(arch));
56 
57             if (disassembler_sp.get())
58                 return disassembler_sp;
59         }
60     }
61     else
62     {
63         for (uint32_t idx = 0; (create_callback = PluginManager::GetDisassemblerCreateCallbackAtIndex(idx)) != NULL; ++idx)
64         {
65             DisassemblerSP disassembler_sp(create_callback(arch));
66 
67             if (disassembler_sp.get())
68                 return disassembler_sp;
69         }
70     }
71     return DisassemblerSP();
72 }
73 
74 
75 static void
76 ResolveAddress (const ExecutionContext &exe_ctx,
77                 const Address &addr,
78                 Address &resolved_addr)
79 {
80     if (!addr.IsSectionOffset())
81     {
82         // If we weren't passed in a section offset address range,
83         // try and resolve it to something
84         Target *target = exe_ctx.GetTargetPtr();
85         if (target)
86         {
87             if (target->GetSectionLoadList().IsEmpty())
88             {
89                 target->GetImages().ResolveFileAddress (addr.GetOffset(), resolved_addr);
90             }
91             else
92             {
93                 target->GetSectionLoadList().ResolveLoadAddress (addr.GetOffset(), resolved_addr);
94             }
95             // We weren't able to resolve the address, just treat it as a
96             // raw address
97             if (resolved_addr.IsValid())
98                 return;
99         }
100     }
101     resolved_addr = addr;
102 }
103 
104 size_t
105 Disassembler::Disassemble
106 (
107     Debugger &debugger,
108     const ArchSpec &arch,
109     const char *plugin_name,
110     const ExecutionContext &exe_ctx,
111     SymbolContextList &sc_list,
112     uint32_t num_instructions,
113     uint32_t num_mixed_context_lines,
114     uint32_t options,
115     Stream &strm
116 )
117 {
118     size_t success_count = 0;
119     const size_t count = sc_list.GetSize();
120     SymbolContext sc;
121     AddressRange range;
122     const uint32_t scope = eSymbolContextBlock | eSymbolContextFunction | eSymbolContextSymbol;
123     const bool use_inline_block_range = true;
124     for (size_t i=0; i<count; ++i)
125     {
126         if (sc_list.GetContextAtIndex(i, sc) == false)
127             break;
128         for (uint32_t range_idx = 0; sc.GetAddressRange(scope, range_idx, use_inline_block_range, range); ++range_idx)
129         {
130             if (Disassemble (debugger,
131                              arch,
132                              plugin_name,
133                              exe_ctx,
134                              range,
135                              num_instructions,
136                              num_mixed_context_lines,
137                              options,
138                              strm))
139             {
140                 ++success_count;
141                 strm.EOL();
142             }
143         }
144     }
145     return success_count;
146 }
147 
148 bool
149 Disassembler::Disassemble
150 (
151     Debugger &debugger,
152     const ArchSpec &arch,
153     const char *plugin_name,
154     const ExecutionContext &exe_ctx,
155     const ConstString &name,
156     Module *module,
157     uint32_t num_instructions,
158     uint32_t num_mixed_context_lines,
159     uint32_t options,
160     Stream &strm
161 )
162 {
163     SymbolContextList sc_list;
164     if (name)
165     {
166         const bool include_symbols = true;
167         const bool include_inlines = true;
168         if (module)
169         {
170             module->FindFunctions (name,
171                                    NULL,
172                                    eFunctionNameTypeBase |
173                                    eFunctionNameTypeFull |
174                                    eFunctionNameTypeMethod |
175                                    eFunctionNameTypeSelector,
176                                    include_symbols,
177                                    include_inlines,
178                                    true,
179                                    sc_list);
180         }
181         else if (exe_ctx.GetTargetPtr())
182         {
183             exe_ctx.GetTargetPtr()->GetImages().FindFunctions (name,
184                                                                eFunctionNameTypeBase |
185                                                                eFunctionNameTypeFull |
186                                                                eFunctionNameTypeMethod |
187                                                                eFunctionNameTypeSelector,
188                                                                include_symbols,
189                                                                include_inlines,
190                                                                false,
191                                                                sc_list);
192         }
193     }
194 
195     if (sc_list.GetSize ())
196     {
197         return Disassemble (debugger,
198                             arch,
199                             plugin_name,
200                             exe_ctx,
201                             sc_list,
202                             num_instructions,
203                             num_mixed_context_lines,
204                             options,
205                             strm);
206     }
207     return false;
208 }
209 
210 
211 lldb::DisassemblerSP
212 Disassembler::DisassembleRange
213 (
214     const ArchSpec &arch,
215     const char *plugin_name,
216     const ExecutionContext &exe_ctx,
217     const AddressRange &range
218 )
219 {
220     lldb::DisassemblerSP disasm_sp;
221     if (range.GetByteSize() > 0 && range.GetBaseAddress().IsValid())
222     {
223         disasm_sp = Disassembler::FindPlugin(arch, plugin_name);
224 
225         if (disasm_sp)
226         {
227             size_t bytes_disassembled = disasm_sp->ParseInstructions (&exe_ctx, range, NULL);
228             if (bytes_disassembled == 0)
229                 disasm_sp.reset();
230         }
231     }
232     return disasm_sp;
233 }
234 
235 lldb::DisassemblerSP
236 Disassembler::DisassembleBytes
237 (
238     const ArchSpec &arch,
239     const char *plugin_name,
240     const Address &start,
241     const void *bytes,
242     size_t length,
243     uint32_t num_instructions
244 )
245 {
246     lldb::DisassemblerSP disasm_sp;
247 
248     if (bytes)
249     {
250         disasm_sp = Disassembler::FindPlugin(arch, plugin_name);
251 
252         if (disasm_sp)
253         {
254             DataExtractor data(bytes, length, arch.GetByteOrder(), arch.GetAddressByteSize());
255 
256             (void)disasm_sp->DecodeInstructions (start,
257                                                  data,
258                                                  0,
259                                                  num_instructions,
260                                                  false);
261         }
262     }
263 
264     return disasm_sp;
265 }
266 
267 
268 bool
269 Disassembler::Disassemble
270 (
271     Debugger &debugger,
272     const ArchSpec &arch,
273     const char *plugin_name,
274     const ExecutionContext &exe_ctx,
275     const AddressRange &disasm_range,
276     uint32_t num_instructions,
277     uint32_t num_mixed_context_lines,
278     uint32_t options,
279     Stream &strm
280 )
281 {
282     if (disasm_range.GetByteSize())
283     {
284         lldb::DisassemblerSP disasm_sp (Disassembler::FindPlugin(arch, plugin_name));
285 
286         if (disasm_sp.get())
287         {
288             AddressRange range;
289             ResolveAddress (exe_ctx, disasm_range.GetBaseAddress(), range.GetBaseAddress());
290             range.SetByteSize (disasm_range.GetByteSize());
291 
292             size_t bytes_disassembled = disasm_sp->ParseInstructions (&exe_ctx, range, &strm);
293             if (bytes_disassembled == 0)
294                 return false;
295 
296             return PrintInstructions (disasm_sp.get(),
297                                       debugger,
298                                       arch,
299                                       exe_ctx,
300                                       num_instructions,
301                                       num_mixed_context_lines,
302                                       options,
303                                       strm);
304         }
305     }
306     return false;
307 }
308 
309 bool
310 Disassembler::Disassemble
311 (
312     Debugger &debugger,
313     const ArchSpec &arch,
314     const char *plugin_name,
315     const ExecutionContext &exe_ctx,
316     const Address &start_address,
317     uint32_t num_instructions,
318     uint32_t num_mixed_context_lines,
319     uint32_t options,
320     Stream &strm
321 )
322 {
323     if (num_instructions > 0)
324     {
325         lldb::DisassemblerSP disasm_sp (Disassembler::FindPlugin(arch, plugin_name));
326         if (disasm_sp.get())
327         {
328             Address addr;
329             ResolveAddress (exe_ctx, start_address, addr);
330 
331             size_t bytes_disassembled = disasm_sp->ParseInstructions (&exe_ctx, addr, num_instructions);
332             if (bytes_disassembled == 0)
333                 return false;
334             return PrintInstructions (disasm_sp.get(),
335                                       debugger,
336                                       arch,
337                                       exe_ctx,
338                                       num_instructions,
339                                       num_mixed_context_lines,
340                                       options,
341                                       strm);
342         }
343     }
344     return false;
345 }
346 
347 bool
348 Disassembler::PrintInstructions
349 (
350     Disassembler *disasm_ptr,
351     Debugger &debugger,
352     const ArchSpec &arch,
353     const ExecutionContext &exe_ctx,
354     uint32_t num_instructions,
355     uint32_t num_mixed_context_lines,
356     uint32_t options,
357     Stream &strm
358 )
359 {
360     // We got some things disassembled...
361     size_t num_instructions_found = disasm_ptr->GetInstructionList().GetSize();
362 
363     if (num_instructions > 0 && num_instructions < num_instructions_found)
364         num_instructions_found = num_instructions;
365 
366     const uint32_t max_opcode_byte_size = disasm_ptr->GetInstructionList().GetMaxOpcocdeByteSize ();
367     uint32_t offset = 0;
368     SymbolContext sc;
369     SymbolContext prev_sc;
370     AddressRange sc_range;
371     const Address *pc_addr_ptr = NULL;
372     ExecutionContextScope *exe_scope = exe_ctx.GetBestExecutionContextScope();
373     StackFrame *frame = exe_ctx.GetFramePtr();
374 
375     if (frame)
376         pc_addr_ptr = &frame->GetFrameCodeAddress();
377     const uint32_t scope = eSymbolContextLineEntry | eSymbolContextFunction | eSymbolContextSymbol;
378     const bool use_inline_block_range = false;
379     for (size_t i=0; i<num_instructions_found; ++i)
380     {
381         Instruction *inst = disasm_ptr->GetInstructionList().GetInstructionAtIndex (i).get();
382         if (inst)
383         {
384             const Address &addr = inst->GetAddress();
385             const bool inst_is_at_pc = pc_addr_ptr && addr == *pc_addr_ptr;
386 
387             prev_sc = sc;
388 
389             ModuleSP module_sp (addr.GetModule());
390             if (module_sp)
391             {
392                 uint32_t resolved_mask = module_sp->ResolveSymbolContextForAddress(addr, eSymbolContextEverything, sc);
393                 if (resolved_mask)
394                 {
395                     if (num_mixed_context_lines)
396                     {
397                         if (!sc_range.ContainsFileAddress (addr))
398                         {
399                             sc.GetAddressRange (scope, 0, use_inline_block_range, sc_range);
400 
401                             if (sc != prev_sc)
402                             {
403                                 if (offset != 0)
404                                     strm.EOL();
405 
406                                 sc.DumpStopContext(&strm, exe_ctx.GetProcessPtr(), addr, false, true, false);
407                                 strm.EOL();
408 
409                                 if (sc.comp_unit && sc.line_entry.IsValid())
410                                 {
411                                     debugger.GetSourceManager().DisplaySourceLinesWithLineNumbers (sc.line_entry.file,
412                                                                                                    sc.line_entry.line,
413                                                                                                    num_mixed_context_lines,
414                                                                                                    num_mixed_context_lines,
415                                                                                                    ((inst_is_at_pc && (options & eOptionMarkPCSourceLine)) ? "->" : ""),
416                                                                                                    &strm);
417                                 }
418                             }
419                         }
420                     }
421                     else if ((sc.function || sc.symbol) && (sc.function != prev_sc.function || sc.symbol != prev_sc.symbol))
422                     {
423                         if (prev_sc.function || prev_sc.symbol)
424                             strm.EOL();
425 
426                         bool show_fullpaths = false;
427                         bool show_module = true;
428                         bool show_inlined_frames = true;
429                         sc.DumpStopContext (&strm,
430                                             exe_scope,
431                                             addr,
432                                             show_fullpaths,
433                                             show_module,
434                                             show_inlined_frames);
435 
436                         strm << ":\n";
437                     }
438                 }
439                 else
440                 {
441                     sc.Clear();
442                 }
443             }
444 
445             if ((options & eOptionMarkPCAddress) && pc_addr_ptr)
446             {
447                 strm.PutCString(inst_is_at_pc ? "-> " : "   ");
448             }
449             const bool show_bytes = (options & eOptionShowBytes) != 0;
450             inst->Dump(&strm, max_opcode_byte_size, true, show_bytes, &exe_ctx);
451             strm.EOL();
452         }
453         else
454         {
455             break;
456         }
457     }
458 
459     return true;
460 }
461 
462 
463 bool
464 Disassembler::Disassemble
465 (
466     Debugger &debugger,
467     const ArchSpec &arch,
468     const char *plugin_name,
469     const ExecutionContext &exe_ctx,
470     uint32_t num_instructions,
471     uint32_t num_mixed_context_lines,
472     uint32_t options,
473     Stream &strm
474 )
475 {
476     AddressRange range;
477     StackFrame *frame = exe_ctx.GetFramePtr();
478     if (frame)
479     {
480         SymbolContext sc(frame->GetSymbolContext(eSymbolContextFunction | eSymbolContextSymbol));
481         if (sc.function)
482         {
483             range = sc.function->GetAddressRange();
484         }
485         else if (sc.symbol && sc.symbol->ValueIsAddress())
486         {
487             range.GetBaseAddress() = sc.symbol->GetAddress();
488             range.SetByteSize (sc.symbol->GetByteSize());
489         }
490         else
491         {
492             range.GetBaseAddress() = frame->GetFrameCodeAddress();
493         }
494 
495         if (range.GetBaseAddress().IsValid() && range.GetByteSize() == 0)
496             range.SetByteSize (DEFAULT_DISASM_BYTE_SIZE);
497     }
498 
499     return Disassemble (debugger,
500                         arch,
501                         plugin_name,
502                         exe_ctx,
503                         range,
504                         num_instructions,
505                         num_mixed_context_lines,
506                         options,
507                         strm);
508 }
509 
510 Instruction::Instruction(const Address &address, AddressClass addr_class) :
511     m_address (address),
512     m_address_class (addr_class),
513     m_opcode(),
514     m_calculated_strings(false)
515 {
516 }
517 
518 Instruction::~Instruction()
519 {
520 }
521 
522 AddressClass
523 Instruction::GetAddressClass ()
524 {
525     if (m_address_class == eAddressClassInvalid)
526         m_address_class = m_address.GetAddressClass();
527     return m_address_class;
528 }
529 
530 void
531 Instruction::Dump (lldb_private::Stream *s,
532                    uint32_t max_opcode_byte_size,
533                    bool show_address,
534                    bool show_bytes,
535                    const ExecutionContext* exe_ctx)
536 {
537     const size_t opcode_column_width = 7;
538     const size_t operand_column_width = 25;
539 
540     CalculateMnemonicOperandsAndCommentIfNeeded (exe_ctx);
541 
542     StreamString ss;
543 
544     if (show_address)
545     {
546         m_address.Dump(&ss,
547                        exe_ctx ? exe_ctx->GetBestExecutionContextScope() : NULL,
548                        Address::DumpStyleLoadAddress,
549                        Address::DumpStyleModuleWithFileAddress,
550                        0);
551 
552         ss.PutCString(":  ");
553     }
554 
555     if (show_bytes)
556     {
557         if (m_opcode.GetType() == Opcode::eTypeBytes)
558         {
559             // x86_64 and i386 are the only ones that use bytes right now so
560             // pad out the byte dump to be able to always show 15 bytes (3 chars each)
561             // plus a space
562             if (max_opcode_byte_size > 0)
563                 m_opcode.Dump (&ss, max_opcode_byte_size * 3 + 1);
564             else
565                 m_opcode.Dump (&ss, 15 * 3 + 1);
566         }
567         else
568         {
569             // Else, we have ARM which can show up to a uint32_t 0x00000000 (10 spaces)
570             // plus two for padding...
571             if (max_opcode_byte_size > 0)
572                 m_opcode.Dump (&ss, max_opcode_byte_size * 3 + 1);
573             else
574                 m_opcode.Dump (&ss, 12);
575         }
576     }
577 
578     const size_t opcode_pos = ss.GetSize();
579 
580     ss.PutCString (m_opcode_name.c_str());
581     ss.FillLastLineToColumn (opcode_pos + opcode_column_width, ' ');
582     ss.PutCString (m_mnemocics.c_str());
583 
584     if (!m_comment.empty())
585     {
586         ss.FillLastLineToColumn (opcode_pos + opcode_column_width + operand_column_width, ' ');
587         ss.PutCString (" ; ");
588         ss.PutCString (m_comment.c_str());
589     }
590     s->Write (ss.GetData(), ss.GetSize());
591 }
592 
593 bool
594 Instruction::DumpEmulation (const ArchSpec &arch)
595 {
596 	std::auto_ptr<EmulateInstruction> insn_emulator_ap (EmulateInstruction::FindPlugin (arch, eInstructionTypeAny, NULL));
597 	if (insn_emulator_ap.get())
598 	{
599         insn_emulator_ap->SetInstruction (GetOpcode(), GetAddress(), NULL);
600         return insn_emulator_ap->EvaluateInstruction (0);
601 	}
602 
603     return false;
604 }
605 
606 OptionValueSP
607 Instruction::ReadArray (FILE *in_file, Stream *out_stream, OptionValue::Type data_type)
608 {
609     bool done = false;
610     char buffer[1024];
611 
612     OptionValueSP option_value_sp (new OptionValueArray (1u << data_type));
613 
614     int idx = 0;
615     while (!done)
616     {
617         if (!fgets (buffer, 1023, in_file))
618         {
619             out_stream->Printf ("Instruction::ReadArray:  Error reading file (fgets).\n");
620             option_value_sp.reset ();
621             return option_value_sp;
622         }
623 
624         std::string line (buffer);
625 
626         int len = line.size();
627         if (line[len-1] == '\n')
628         {
629             line[len-1] = '\0';
630             line.resize (len-1);
631         }
632 
633         if ((line.size() == 1) && line[0] == ']')
634         {
635             done = true;
636             line.clear();
637         }
638 
639         if (line.size() > 0)
640         {
641             std::string value;
642             RegularExpression reg_exp ("^[ \t]*([^ \t]+)[ \t]*$");
643             bool reg_exp_success = reg_exp.Execute (line.c_str(), 1);
644             if (reg_exp_success)
645                 reg_exp.GetMatchAtIndex (line.c_str(), 1, value);
646             else
647                 value = line;
648 
649             OptionValueSP data_value_sp;
650             switch (data_type)
651             {
652             case OptionValue::eTypeUInt64:
653                 data_value_sp.reset (new OptionValueUInt64 (0, 0));
654                 data_value_sp->SetValueFromCString (value.c_str());
655                 break;
656             // Other types can be added later as needed.
657             default:
658                 data_value_sp.reset (new OptionValueString (value.c_str(), ""));
659                 break;
660             }
661 
662             option_value_sp->GetAsArray()->InsertValue (idx, data_value_sp);
663             ++idx;
664         }
665     }
666 
667     return option_value_sp;
668 }
669 
670 OptionValueSP
671 Instruction::ReadDictionary (FILE *in_file, Stream *out_stream)
672 {
673     bool done = false;
674     char buffer[1024];
675 
676     OptionValueSP option_value_sp (new OptionValueDictionary());
677     static ConstString encoding_key ("data_encoding");
678     OptionValue::Type data_type = OptionValue::eTypeInvalid;
679 
680 
681     while (!done)
682     {
683         // Read the next line in the file
684         if (!fgets (buffer, 1023, in_file))
685         {
686             out_stream->Printf ("Instruction::ReadDictionary: Error reading file (fgets).\n");
687             option_value_sp.reset ();
688             return option_value_sp;
689         }
690 
691         // Check to see if the line contains the end-of-dictionary marker ("}")
692         std::string line (buffer);
693 
694         int len = line.size();
695         if (line[len-1] == '\n')
696         {
697             line[len-1] = '\0';
698             line.resize (len-1);
699         }
700 
701         if ((line.size() == 1) && (line[0] == '}'))
702         {
703             done = true;
704             line.clear();
705         }
706 
707         // Try to find a key-value pair in the current line and add it to the dictionary.
708         if (line.size() > 0)
709         {
710             RegularExpression reg_exp ("^[ \t]*([a-zA-Z_][a-zA-Z0-9_]*)[ \t]*=[ \t]*(.*)[ \t]*$");
711             bool reg_exp_success = reg_exp.Execute (line.c_str(), 2);
712             std::string key;
713             std::string value;
714             if (reg_exp_success)
715             {
716                 reg_exp.GetMatchAtIndex (line.c_str(), 1, key);
717                 reg_exp.GetMatchAtIndex (line.c_str(), 2, value);
718             }
719             else
720             {
721                 out_stream->Printf ("Instruction::ReadDictionary: Failure executing regular expression.\n");
722                 option_value_sp.reset();
723                 return option_value_sp;
724             }
725 
726             ConstString const_key (key.c_str());
727             // Check value to see if it's the start of an array or dictionary.
728 
729             lldb::OptionValueSP value_sp;
730             assert (value.empty() == false);
731             assert (key.empty() == false);
732 
733             if (value[0] == '{')
734             {
735                 assert (value.size() == 1);
736                 // value is a dictionary
737                 value_sp = ReadDictionary (in_file, out_stream);
738                 if (value_sp.get() == NULL)
739                 {
740                     option_value_sp.reset ();
741                     return option_value_sp;
742                 }
743             }
744             else if (value[0] == '[')
745             {
746                 assert (value.size() == 1);
747                 // value is an array
748                 value_sp = ReadArray (in_file, out_stream, data_type);
749                 if (value_sp.get() == NULL)
750                 {
751                     option_value_sp.reset ();
752                     return option_value_sp;
753                 }
754                 // We've used the data_type to read an array; re-set the type to Invalid
755                 data_type = OptionValue::eTypeInvalid;
756             }
757             else if ((value[0] == '0') && (value[1] == 'x'))
758             {
759                 value_sp.reset (new OptionValueUInt64 (0, 0));
760                 value_sp->SetValueFromCString (value.c_str());
761             }
762             else
763             {
764                 int len = value.size();
765                 if ((value[0] == '"') && (value[len-1] == '"'))
766                     value = value.substr (1, len-2);
767                 value_sp.reset (new OptionValueString (value.c_str(), ""));
768             }
769 
770 
771 
772             if (const_key == encoding_key)
773             {
774                 // A 'data_encoding=..." is NOT a normal key-value pair; it is meta-data indicating the
775                 // data type of an upcoming array (usually the next bit of data to be read in).
776                 if (strcmp (value.c_str(), "uint32_t") == 0)
777                     data_type = OptionValue::eTypeUInt64;
778             }
779             else
780                 option_value_sp->GetAsDictionary()->SetValueForKey (const_key, value_sp, false);
781         }
782     }
783 
784     return option_value_sp;
785 }
786 
787 bool
788 Instruction::TestEmulation (Stream *out_stream, const char *file_name)
789 {
790     if (!out_stream)
791         return false;
792 
793     if (!file_name)
794     {
795         out_stream->Printf ("Instruction::TestEmulation:  Missing file_name.");
796         return false;
797     }
798 
799     FILE *test_file = fopen (file_name, "r");
800     if (!test_file)
801     {
802         out_stream->Printf ("Instruction::TestEmulation: Attempt to open test file failed.");
803         return false;
804     }
805 
806     char buffer[256];
807     if (!fgets (buffer, 255, test_file))
808     {
809         out_stream->Printf ("Instruction::TestEmulation: Error reading first line of test file.\n");
810         fclose (test_file);
811         return false;
812     }
813 
814     if (strncmp (buffer, "InstructionEmulationState={", 27) != 0)
815     {
816         out_stream->Printf ("Instructin::TestEmulation: Test file does not contain emulation state dictionary\n");
817         fclose (test_file);
818         return false;
819     }
820 
821     // Read all the test information from the test file into an OptionValueDictionary.
822 
823     OptionValueSP data_dictionary_sp (ReadDictionary (test_file, out_stream));
824     if (data_dictionary_sp.get() == NULL)
825     {
826         out_stream->Printf ("Instruction::TestEmulation:  Error reading Dictionary Object.\n");
827         fclose (test_file);
828         return false;
829     }
830 
831     fclose (test_file);
832 
833     OptionValueDictionary *data_dictionary = data_dictionary_sp->GetAsDictionary();
834     static ConstString description_key ("assembly_string");
835     static ConstString triple_key ("triple");
836 
837     OptionValueSP value_sp = data_dictionary->GetValueForKey (description_key);
838 
839     if (value_sp.get() == NULL)
840     {
841         out_stream->Printf ("Instruction::TestEmulation:  Test file does not contain description string.\n");
842         return false;
843     }
844 
845     SetDescription (value_sp->GetStringValue());
846 
847 
848     value_sp = data_dictionary->GetValueForKey (triple_key);
849     if (value_sp.get() == NULL)
850     {
851         out_stream->Printf ("Instruction::TestEmulation: Test file does not contain triple.\n");
852         return false;
853     }
854 
855     ArchSpec arch;
856     arch.SetTriple (llvm::Triple (value_sp->GetStringValue()));
857 
858     bool success = false;
859     std::auto_ptr<EmulateInstruction> insn_emulator_ap (EmulateInstruction::FindPlugin (arch, eInstructionTypeAny, NULL));
860     if (insn_emulator_ap.get())
861         success = insn_emulator_ap->TestEmulation (out_stream, arch, data_dictionary);
862 
863     if (success)
864         out_stream->Printf ("Emulation test succeeded.");
865     else
866         out_stream->Printf ("Emulation test failed.");
867 
868     return success;
869 }
870 
871 bool
872 Instruction::Emulate (const ArchSpec &arch,
873                       uint32_t evaluate_options,
874                       void *baton,
875                       EmulateInstruction::ReadMemoryCallback read_mem_callback,
876                       EmulateInstruction::WriteMemoryCallback write_mem_callback,
877                       EmulateInstruction::ReadRegisterCallback read_reg_callback,
878                       EmulateInstruction::WriteRegisterCallback write_reg_callback)
879 {
880 	std::auto_ptr<EmulateInstruction> insn_emulator_ap (EmulateInstruction::FindPlugin (arch, eInstructionTypeAny, NULL));
881 	if (insn_emulator_ap.get())
882 	{
883 		insn_emulator_ap->SetBaton (baton);
884 		insn_emulator_ap->SetCallbacks (read_mem_callback, write_mem_callback, read_reg_callback, write_reg_callback);
885         insn_emulator_ap->SetInstruction (GetOpcode(), GetAddress(), NULL);
886         return insn_emulator_ap->EvaluateInstruction (evaluate_options);
887 	}
888 
889     return false;
890 }
891 
892 
893 uint32_t
894 Instruction::GetData (DataExtractor &data)
895 {
896     return m_opcode.GetData(data);
897 }
898 
899 InstructionList::InstructionList() :
900     m_instructions()
901 {
902 }
903 
904 InstructionList::~InstructionList()
905 {
906 }
907 
908 size_t
909 InstructionList::GetSize() const
910 {
911     return m_instructions.size();
912 }
913 
914 uint32_t
915 InstructionList::GetMaxOpcocdeByteSize () const
916 {
917     uint32_t max_inst_size = 0;
918     collection::const_iterator pos, end;
919     for (pos = m_instructions.begin(), end = m_instructions.end();
920          pos != end;
921          ++pos)
922     {
923         uint32_t inst_size = (*pos)->GetOpcode().GetByteSize();
924         if (max_inst_size < inst_size)
925             max_inst_size = inst_size;
926     }
927     return max_inst_size;
928 }
929 
930 
931 
932 InstructionSP
933 InstructionList::GetInstructionAtIndex (uint32_t idx) const
934 {
935     InstructionSP inst_sp;
936     if (idx < m_instructions.size())
937         inst_sp = m_instructions[idx];
938     return inst_sp;
939 }
940 
941 void
942 InstructionList::Dump (Stream *s,
943                        bool show_address,
944                        bool show_bytes,
945                        const ExecutionContext* exe_ctx)
946 {
947     const uint32_t max_opcode_byte_size = GetMaxOpcocdeByteSize();
948     collection::const_iterator pos, begin, end;
949     for (begin = m_instructions.begin(), end = m_instructions.end(), pos = begin;
950          pos != end;
951          ++pos)
952     {
953         if (pos != begin)
954             s->EOL();
955         (*pos)->Dump(s, max_opcode_byte_size, show_address, show_bytes, exe_ctx);
956     }
957 }
958 
959 
960 void
961 InstructionList::Clear()
962 {
963   m_instructions.clear();
964 }
965 
966 void
967 InstructionList::Append (lldb::InstructionSP &inst_sp)
968 {
969     if (inst_sp)
970         m_instructions.push_back(inst_sp);
971 }
972 
973 uint32_t
974 InstructionList::GetIndexOfNextBranchInstruction(uint32_t start) const
975 {
976     size_t num_instructions = m_instructions.size();
977 
978     uint32_t next_branch = UINT32_MAX;
979     for (size_t i = start; i < num_instructions; i++)
980     {
981         if (m_instructions[i]->DoesBranch())
982         {
983             next_branch = i;
984             break;
985         }
986     }
987     return next_branch;
988 }
989 
990 uint32_t
991 InstructionList::GetIndexOfInstructionAtLoadAddress (lldb::addr_t load_addr, Target &target)
992 {
993     Address address;
994     address.SetLoadAddress(load_addr, &target);
995     uint32_t num_instructions = m_instructions.size();
996     uint32_t index = UINT32_MAX;
997     for (int i = 0; i < num_instructions; i++)
998     {
999         if (m_instructions[i]->GetAddress() == address)
1000         {
1001             index = i;
1002             break;
1003         }
1004     }
1005     return index;
1006 }
1007 
1008 size_t
1009 Disassembler::ParseInstructions
1010 (
1011     const ExecutionContext *exe_ctx,
1012     const AddressRange &range,
1013     Stream *error_strm_ptr
1014 )
1015 {
1016     if (exe_ctx)
1017     {
1018         Target *target = exe_ctx->GetTargetPtr();
1019         const addr_t byte_size = range.GetByteSize();
1020         if (target == NULL || byte_size == 0 || !range.GetBaseAddress().IsValid())
1021             return 0;
1022 
1023         DataBufferHeap *heap_buffer = new DataBufferHeap (byte_size, '\0');
1024         DataBufferSP data_sp(heap_buffer);
1025 
1026         Error error;
1027         const bool prefer_file_cache = true;
1028         const size_t bytes_read = target->ReadMemory (range.GetBaseAddress(),
1029                                                       prefer_file_cache,
1030                                                       heap_buffer->GetBytes(),
1031                                                       heap_buffer->GetByteSize(),
1032                                                       error);
1033 
1034         if (bytes_read > 0)
1035         {
1036             if (bytes_read != heap_buffer->GetByteSize())
1037                 heap_buffer->SetByteSize (bytes_read);
1038             DataExtractor data (data_sp,
1039                                 m_arch.GetByteOrder(),
1040                                 m_arch.GetAddressByteSize());
1041             return DecodeInstructions (range.GetBaseAddress(), data, 0, UINT32_MAX, false);
1042         }
1043         else if (error_strm_ptr)
1044         {
1045             const char *error_cstr = error.AsCString();
1046             if (error_cstr)
1047             {
1048                 error_strm_ptr->Printf("error: %s\n", error_cstr);
1049             }
1050         }
1051     }
1052     else if (error_strm_ptr)
1053     {
1054         error_strm_ptr->PutCString("error: invalid execution context\n");
1055     }
1056     return 0;
1057 }
1058 
1059 size_t
1060 Disassembler::ParseInstructions
1061 (
1062     const ExecutionContext *exe_ctx,
1063     const Address &start,
1064     uint32_t num_instructions
1065 )
1066 {
1067     m_instruction_list.Clear();
1068 
1069     if (exe_ctx == NULL || num_instructions == 0 || !start.IsValid())
1070         return 0;
1071 
1072     Target *target = exe_ctx->GetTargetPtr();
1073     // Calculate the max buffer size we will need in order to disassemble
1074     const addr_t byte_size = num_instructions * m_arch.GetMaximumOpcodeByteSize();
1075 
1076     if (target == NULL || byte_size == 0)
1077         return 0;
1078 
1079     DataBufferHeap *heap_buffer = new DataBufferHeap (byte_size, '\0');
1080     DataBufferSP data_sp (heap_buffer);
1081 
1082     Error error;
1083     bool prefer_file_cache = true;
1084     const size_t bytes_read = target->ReadMemory (start,
1085                                                   prefer_file_cache,
1086                                                   heap_buffer->GetBytes(),
1087                                                   byte_size,
1088                                                   error);
1089 
1090     if (bytes_read == 0)
1091         return 0;
1092     DataExtractor data (data_sp,
1093                         m_arch.GetByteOrder(),
1094                         m_arch.GetAddressByteSize());
1095 
1096     const bool append_instructions = true;
1097     DecodeInstructions (start,
1098                         data,
1099                         0,
1100                         num_instructions,
1101                         append_instructions);
1102 
1103     return m_instruction_list.GetSize();
1104 }
1105 
1106 //----------------------------------------------------------------------
1107 // Disassembler copy constructor
1108 //----------------------------------------------------------------------
1109 Disassembler::Disassembler(const ArchSpec& arch) :
1110     m_arch (arch),
1111     m_instruction_list(),
1112     m_base_addr(LLDB_INVALID_ADDRESS)
1113 {
1114 
1115 }
1116 
1117 //----------------------------------------------------------------------
1118 // Destructor
1119 //----------------------------------------------------------------------
1120 Disassembler::~Disassembler()
1121 {
1122 }
1123 
1124 InstructionList &
1125 Disassembler::GetInstructionList ()
1126 {
1127     return m_instruction_list;
1128 }
1129 
1130 const InstructionList &
1131 Disassembler::GetInstructionList () const
1132 {
1133     return m_instruction_list;
1134 }
1135 
1136 //----------------------------------------------------------------------
1137 // Class PseudoInstruction
1138 //----------------------------------------------------------------------
1139 PseudoInstruction::PseudoInstruction () :
1140     Instruction (Address(), eAddressClassUnknown),
1141     m_description ()
1142 {
1143 }
1144 
1145 PseudoInstruction::~PseudoInstruction ()
1146 {
1147 }
1148 
1149 bool
1150 PseudoInstruction::DoesBranch () const
1151 {
1152     // This is NOT a valid question for a pseudo instruction.
1153     return false;
1154 }
1155 
1156 size_t
1157 PseudoInstruction::Decode (const lldb_private::Disassembler &disassembler,
1158                            const lldb_private::DataExtractor &data,
1159                            uint32_t data_offset)
1160 {
1161     return m_opcode.GetByteSize();
1162 }
1163 
1164 
1165 void
1166 PseudoInstruction::SetOpcode (size_t opcode_size, void *opcode_data)
1167 {
1168     if (!opcode_data)
1169         return;
1170 
1171     switch (opcode_size)
1172     {
1173         case 8:
1174         {
1175             uint8_t value8 = *((uint8_t *) opcode_data);
1176             m_opcode.SetOpcode8 (value8);
1177             break;
1178          }
1179         case 16:
1180         {
1181             uint16_t value16 = *((uint16_t *) opcode_data);
1182             m_opcode.SetOpcode16 (value16);
1183             break;
1184          }
1185         case 32:
1186         {
1187             uint32_t value32 = *((uint32_t *) opcode_data);
1188             m_opcode.SetOpcode32 (value32);
1189             break;
1190          }
1191         case 64:
1192         {
1193             uint64_t value64 = *((uint64_t *) opcode_data);
1194             m_opcode.SetOpcode64 (value64);
1195             break;
1196          }
1197         default:
1198             break;
1199     }
1200 }
1201 
1202 void
1203 PseudoInstruction::SetDescription (const char *description)
1204 {
1205     if (description && strlen (description) > 0)
1206         m_description = description;
1207 }
1208