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