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