1 //===-- Disassembler.cpp ----------------------------------------*- C++ -*-===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 
10 #include "lldb/Core/Disassembler.h"
11 
12 // C Includes
13 // C++ Includes
14 // Other libraries and framework includes
15 // Project includes
16 #include "lldb/lldb-private.h"
17 #include "lldb/Core/Error.h"
18 #include "lldb/Core/DataBufferHeap.h"
19 #include "lldb/Core/DataExtractor.h"
20 #include "lldb/Core/Debugger.h"
21 #include "lldb/Core/EmulateInstruction.h"
22 #include "lldb/Core/Module.h"
23 #include "lldb/Core/PluginManager.h"
24 #include "lldb/Core/Timer.h"
25 #include "lldb/Symbol/ObjectFile.h"
26 #include "lldb/Target/ExecutionContext.h"
27 #include "lldb/Target/Process.h"
28 #include "lldb/Target/StackFrame.h"
29 #include "lldb/Target/Target.h"
30 
31 #define DEFAULT_DISASM_BYTE_SIZE 32
32 
33 using namespace lldb;
34 using namespace lldb_private;
35 
36 
37 Disassembler*
38 Disassembler::FindPlugin (const ArchSpec &arch, const char *plugin_name)
39 {
40     Timer scoped_timer (__PRETTY_FUNCTION__,
41                         "Disassembler::FindPlugin (arch = %s, plugin_name = %s)",
42                         arch.GetArchitectureName(),
43                         plugin_name);
44 
45     std::auto_ptr<Disassembler> disassembler_ap;
46     DisassemblerCreateInstance create_callback = NULL;
47 
48     if (plugin_name)
49     {
50         create_callback = PluginManager::GetDisassemblerCreateCallbackForPluginName (plugin_name);
51         if (create_callback)
52         {
53             disassembler_ap.reset (create_callback(arch));
54 
55             if (disassembler_ap.get())
56                 return disassembler_ap.release();
57         }
58     }
59     else
60     {
61         for (uint32_t idx = 0; (create_callback = PluginManager::GetDisassemblerCreateCallbackAtIndex(idx)) != NULL; ++idx)
62         {
63             disassembler_ap.reset (create_callback(arch));
64 
65             if (disassembler_ap.get())
66                 return disassembler_ap.release();
67         }
68     }
69     return NULL;
70 }
71 
72 
73 static void
74 ResolveAddress (const ExecutionContext &exe_ctx,
75                 const Address &addr,
76                 Address &resolved_addr)
77 {
78     if (!addr.IsSectionOffset())
79     {
80         // If we weren't passed in a section offset address range,
81         // try and resolve it to something
82         if (exe_ctx.target)
83         {
84             if (exe_ctx.target->GetSectionLoadList().IsEmpty())
85             {
86                 exe_ctx.target->GetImages().ResolveFileAddress (addr.GetOffset(), resolved_addr);
87             }
88             else
89             {
90                 exe_ctx.target->GetSectionLoadList().ResolveLoadAddress (addr.GetOffset(), resolved_addr);
91             }
92             // We weren't able to resolve the address, just treat it as a
93             // raw address
94             if (resolved_addr.IsValid())
95                 return;
96         }
97     }
98     resolved_addr = addr;
99 }
100 
101 size_t
102 Disassembler::Disassemble
103 (
104     Debugger &debugger,
105     const ArchSpec &arch,
106     const char *plugin_name,
107     const ExecutionContext &exe_ctx,
108     SymbolContextList &sc_list,
109     uint32_t num_instructions,
110     uint32_t num_mixed_context_lines,
111     bool show_bytes,
112     bool raw,
113     Stream &strm
114 )
115 {
116     size_t success_count = 0;
117     const size_t count = sc_list.GetSize();
118     SymbolContext sc;
119     AddressRange range;
120 
121     for (size_t i=0; i<count; ++i)
122     {
123         if (sc_list.GetContextAtIndex(i, sc) == false)
124             break;
125         if (sc.GetAddressRange(eSymbolContextFunction | eSymbolContextSymbol, range))
126         {
127             if (Disassemble (debugger,
128                              arch,
129                              plugin_name,
130                              exe_ctx,
131                              range,
132                              num_instructions,
133                              num_mixed_context_lines,
134                              show_bytes,
135                              raw,
136                              strm))
137             {
138                 ++success_count;
139                 strm.EOL();
140             }
141         }
142     }
143     return success_count;
144 }
145 
146 bool
147 Disassembler::Disassemble
148 (
149     Debugger &debugger,
150     const ArchSpec &arch,
151     const char *plugin_name,
152     const ExecutionContext &exe_ctx,
153     const ConstString &name,
154     Module *module,
155     uint32_t num_instructions,
156     uint32_t num_mixed_context_lines,
157     bool show_bytes,
158     bool raw,
159     Stream &strm
160 )
161 {
162     SymbolContextList sc_list;
163     if (name)
164     {
165         const bool include_symbols = true;
166         if (module)
167         {
168             module->FindFunctions (name,
169                                    eFunctionNameTypeBase |
170                                    eFunctionNameTypeFull |
171                                    eFunctionNameTypeMethod |
172                                    eFunctionNameTypeSelector,
173                                    include_symbols,
174                                    true,
175                                    sc_list);
176         }
177         else if (exe_ctx.target)
178         {
179             exe_ctx.target->GetImages().FindFunctions (name,
180                                                        eFunctionNameTypeBase |
181                                                        eFunctionNameTypeFull |
182                                                        eFunctionNameTypeMethod |
183                                                        eFunctionNameTypeSelector,
184                                                        include_symbols,
185                                                        false,
186                                                        sc_list);
187         }
188     }
189 
190     if (sc_list.GetSize ())
191     {
192         return Disassemble (debugger,
193                             arch,
194                             plugin_name,
195                             exe_ctx,
196                             sc_list,
197                             num_instructions,
198                             num_mixed_context_lines,
199                             show_bytes,
200                             raw,
201                             strm);
202     }
203     return false;
204 }
205 
206 
207 lldb::DisassemblerSP
208 Disassembler::DisassembleRange
209 (
210     const ArchSpec &arch,
211     const char *plugin_name,
212     const ExecutionContext &exe_ctx,
213     const AddressRange &range
214 )
215 {
216     lldb::DisassemblerSP disasm_sp;
217     if (range.GetByteSize() > 0 && range.GetBaseAddress().IsValid())
218     {
219         disasm_sp.reset (Disassembler::FindPlugin(arch, plugin_name));
220 
221         if (disasm_sp)
222         {
223             size_t bytes_disassembled = disasm_sp->ParseInstructions (&exe_ctx, range);
224             if (bytes_disassembled == 0)
225                 disasm_sp.reset();
226         }
227     }
228     return disasm_sp;
229 }
230 
231 
232 bool
233 Disassembler::Disassemble
234 (
235     Debugger &debugger,
236     const ArchSpec &arch,
237     const char *plugin_name,
238     const ExecutionContext &exe_ctx,
239     const AddressRange &disasm_range,
240     uint32_t num_instructions,
241     uint32_t num_mixed_context_lines,
242     bool show_bytes,
243     bool raw,
244     Stream &strm
245 )
246 {
247     if (disasm_range.GetByteSize())
248     {
249         std::auto_ptr<Disassembler> disasm_ap (Disassembler::FindPlugin(arch, plugin_name));
250 
251         if (disasm_ap.get())
252         {
253             AddressRange range;
254             ResolveAddress (exe_ctx, disasm_range.GetBaseAddress(), range.GetBaseAddress());
255             range.SetByteSize (disasm_range.GetByteSize());
256 
257             size_t bytes_disassembled = disasm_ap->ParseInstructions (&exe_ctx, range);
258             if (bytes_disassembled == 0)
259                 return false;
260 
261             return PrintInstructions (disasm_ap.get(),
262                                       debugger,
263                                       arch,
264                                       exe_ctx,
265                                       num_instructions,
266                                       num_mixed_context_lines,
267                                       show_bytes,
268                                       raw,
269                                       strm);
270         }
271     }
272     return false;
273 }
274 
275 bool
276 Disassembler::Disassemble
277 (
278     Debugger &debugger,
279     const ArchSpec &arch,
280     const char *plugin_name,
281     const ExecutionContext &exe_ctx,
282     const Address &start_address,
283     uint32_t num_instructions,
284     uint32_t num_mixed_context_lines,
285     bool show_bytes,
286     bool raw,
287     Stream &strm
288 )
289 {
290     if (num_instructions > 0)
291     {
292         std::auto_ptr<Disassembler> disasm_ap (Disassembler::FindPlugin(arch, plugin_name));
293         if (disasm_ap.get())
294         {
295             Address addr;
296             ResolveAddress (exe_ctx, start_address, addr);
297 
298             size_t bytes_disassembled = disasm_ap->ParseInstructions (&exe_ctx, addr, num_instructions);
299             if (bytes_disassembled == 0)
300                 return false;
301             return PrintInstructions (disasm_ap.get(),
302                                       debugger,
303                                       arch,
304                                       exe_ctx,
305                                       num_instructions,
306                                       num_mixed_context_lines,
307                                       show_bytes,
308                                       raw,
309                                       strm);
310         }
311     }
312     return false;
313 }
314 
315 bool
316 Disassembler::PrintInstructions
317 (
318     Disassembler *disasm_ptr,
319     Debugger &debugger,
320     const ArchSpec &arch,
321     const ExecutionContext &exe_ctx,
322     uint32_t num_instructions,
323     uint32_t num_mixed_context_lines,
324     bool show_bytes,
325     bool raw,
326     Stream &strm
327 )
328 {
329     // We got some things disassembled...
330     size_t num_instructions_found = disasm_ptr->GetInstructionList().GetSize();
331 
332     if (num_instructions > 0 && num_instructions < num_instructions_found)
333         num_instructions_found = num_instructions;
334 
335     const uint32_t max_opcode_byte_size = disasm_ptr->GetInstructionList().GetMaxOpcocdeByteSize ();
336     uint32_t offset = 0;
337     SymbolContext sc;
338     SymbolContext prev_sc;
339     AddressRange sc_range;
340     Address *pc_addr_ptr = NULL;
341     if (exe_ctx.frame)
342         pc_addr_ptr = &exe_ctx.frame->GetFrameCodeAddress();
343 
344     for (size_t i=0; i<num_instructions_found; ++i)
345     {
346         Instruction *inst = disasm_ptr->GetInstructionList().GetInstructionAtIndex (i).get();
347         if (inst)
348         {
349             const Address &addr = inst->GetAddress();
350             const bool inst_is_at_pc = pc_addr_ptr && addr == *pc_addr_ptr;
351 
352             prev_sc = sc;
353 
354             Module *module = addr.GetModule();
355             if (module)
356             {
357                 uint32_t resolved_mask = module->ResolveSymbolContextForAddress(addr, eSymbolContextEverything, sc);
358                 if (resolved_mask)
359                 {
360                     if (num_mixed_context_lines)
361                     {
362                         if (!sc_range.ContainsFileAddress (addr))
363                         {
364                             sc.GetAddressRange (eSymbolContextEverything, sc_range);
365 
366                             if (sc != prev_sc)
367                             {
368                                 if (offset != 0)
369                                     strm.EOL();
370 
371                                 sc.DumpStopContext(&strm, exe_ctx.process, addr, false, true, false);
372                                 strm.EOL();
373 
374                                 if (sc.comp_unit && sc.line_entry.IsValid())
375                                 {
376                                     debugger.GetSourceManager().DisplaySourceLinesWithLineNumbers (sc.line_entry.file,
377                                                                                                    sc.line_entry.line,
378                                                                                                    num_mixed_context_lines,
379                                                                                                    num_mixed_context_lines,
380                                                                                                    num_mixed_context_lines ? "->" : "",
381                                                                                                    &strm);
382                                 }
383                             }
384                         }
385                     }
386                     else if (!(prev_sc.function == sc.function || prev_sc.symbol == sc.symbol))
387                     {
388                         if (prev_sc.function || prev_sc.symbol)
389                             strm.EOL();
390 
391                         strm << sc.module_sp->GetFileSpec().GetFilename();
392 
393                         if (sc.function)
394                             strm << '`' << sc.function->GetMangled().GetName();
395                         else if (sc.symbol)
396                             strm << '`' << sc.symbol->GetMangled().GetName();
397                         strm << ":\n";
398                     }
399                 }
400                 else
401                 {
402                     sc.Clear();
403                 }
404             }
405 
406             if (pc_addr_ptr)
407             {
408                 if (inst_is_at_pc)
409                     strm.PutCString("-> ");
410                 else
411                     strm.PutCString("   ");
412             }
413             inst->Dump(&strm, max_opcode_byte_size, true, show_bytes, &exe_ctx, raw);
414             strm.EOL();
415         }
416         else
417         {
418             break;
419         }
420     }
421 
422     return true;
423 }
424 
425 
426 bool
427 Disassembler::Disassemble
428 (
429     Debugger &debugger,
430     const ArchSpec &arch,
431     const char *plugin_name,
432     const ExecutionContext &exe_ctx,
433     uint32_t num_instructions,
434     uint32_t num_mixed_context_lines,
435     bool show_bytes,
436     bool raw,
437     Stream &strm
438 )
439 {
440     AddressRange range;
441     if (exe_ctx.frame)
442     {
443         SymbolContext sc(exe_ctx.frame->GetSymbolContext(eSymbolContextFunction | eSymbolContextSymbol));
444         if (sc.function)
445         {
446             range = sc.function->GetAddressRange();
447         }
448         else if (sc.symbol && sc.symbol->GetAddressRangePtr())
449         {
450             range = *sc.symbol->GetAddressRangePtr();
451         }
452         else
453         {
454             range.GetBaseAddress() = exe_ctx.frame->GetFrameCodeAddress();
455         }
456 
457         if (range.GetBaseAddress().IsValid() && range.GetByteSize() == 0)
458             range.SetByteSize (DEFAULT_DISASM_BYTE_SIZE);
459     }
460 
461     return Disassemble (debugger,
462                         arch,
463                         plugin_name,
464                         exe_ctx,
465                         range,
466                         num_instructions,
467                         num_mixed_context_lines,
468                         show_bytes,
469                         raw,
470                         strm);
471 }
472 
473 Instruction::Instruction(const Address &address, AddressClass addr_class) :
474     m_address (address),
475     m_address_class (addr_class),
476     m_opcode()
477 {
478 }
479 
480 Instruction::~Instruction()
481 {
482 }
483 
484 AddressClass
485 Instruction::GetAddressClass ()
486 {
487     if (m_address_class == eAddressClassInvalid)
488         m_address_class = m_address.GetAddressClass();
489     return m_address_class;
490 }
491 
492 bool
493 Instruction::DumpEmulation (const ArchSpec &arch)
494 {
495 	std::auto_ptr<EmulateInstruction> insn_emulator_ap (EmulateInstruction::FindPlugin (arch, NULL));
496 	if (insn_emulator_ap.get())
497 	{
498         insn_emulator_ap->SetInstruction (GetOpcode(), GetAddress());
499         return insn_emulator_ap->EvaluateInstruction ();
500 	}
501 
502     return false;
503 }
504 
505 bool
506 Instruction::Emulate (const ArchSpec &arch,
507                       bool auto_advance_pc,
508                       void *baton,
509                       EmulateInstruction::ReadMemory read_mem_callback,
510                       EmulateInstruction::WriteMemory write_mem_callback,
511                       EmulateInstruction::ReadRegister read_reg_callback,
512                       EmulateInstruction::WriteRegister write_reg_callback)
513 {
514 	std::auto_ptr<EmulateInstruction> insn_emulator_ap (EmulateInstruction::FindPlugin (arch, NULL));
515 	if (insn_emulator_ap.get())
516 	{
517 		insn_emulator_ap->SetBaton (baton);
518 		insn_emulator_ap->SetCallbacks (read_mem_callback, write_mem_callback, read_reg_callback, write_reg_callback);
519         insn_emulator_ap->SetInstruction (GetOpcode(), GetAddress());
520         insn_emulator_ap->SetAdvancePC (auto_advance_pc);
521         return insn_emulator_ap->EvaluateInstruction ();
522 	}
523 
524     return false;
525 }
526 
527 InstructionList::InstructionList() :
528     m_instructions()
529 {
530 }
531 
532 InstructionList::~InstructionList()
533 {
534 }
535 
536 size_t
537 InstructionList::GetSize() const
538 {
539     return m_instructions.size();
540 }
541 
542 uint32_t
543 InstructionList::GetMaxOpcocdeByteSize () const
544 {
545     uint32_t max_inst_size = 0;
546     collection::const_iterator pos, end;
547     for (pos = m_instructions.begin(), end = m_instructions.end();
548          pos != end;
549          ++pos)
550     {
551         uint32_t inst_size = (*pos)->GetOpcode().GetByteSize();
552         if (max_inst_size < inst_size)
553             max_inst_size = inst_size;
554     }
555     return max_inst_size;
556 }
557 
558 
559 
560 InstructionSP
561 InstructionList::GetInstructionAtIndex (uint32_t idx) const
562 {
563     InstructionSP inst_sp;
564     if (idx < m_instructions.size())
565         inst_sp = m_instructions[idx];
566     return inst_sp;
567 }
568 
569 void
570 InstructionList::Clear()
571 {
572   m_instructions.clear();
573 }
574 
575 void
576 InstructionList::Append (lldb::InstructionSP &inst_sp)
577 {
578     if (inst_sp)
579         m_instructions.push_back(inst_sp);
580 }
581 
582 
583 size_t
584 Disassembler::ParseInstructions
585 (
586     const ExecutionContext *exe_ctx,
587     const AddressRange &range
588 )
589 {
590     Target *target = exe_ctx->target;
591     const addr_t byte_size = range.GetByteSize();
592     if (target == NULL || byte_size == 0 || !range.GetBaseAddress().IsValid())
593         return 0;
594 
595     DataBufferHeap *heap_buffer = new DataBufferHeap (byte_size, '\0');
596     DataBufferSP data_sp(heap_buffer);
597 
598     Error error;
599     const bool prefer_file_cache = true;
600     const size_t bytes_read = target->ReadMemory (range.GetBaseAddress(),
601                                                   prefer_file_cache,
602                                                   heap_buffer->GetBytes(),
603                                                   heap_buffer->GetByteSize(),
604                                                   error);
605 
606     if (bytes_read > 0)
607     {
608         if (bytes_read != heap_buffer->GetByteSize())
609             heap_buffer->SetByteSize (bytes_read);
610         DataExtractor data (data_sp,
611                             m_arch.GetByteOrder(),
612                             m_arch.GetAddressByteSize());
613         return DecodeInstructions (range.GetBaseAddress(), data, 0, UINT32_MAX, false);
614     }
615 
616     return 0;
617 }
618 
619 size_t
620 Disassembler::ParseInstructions
621 (
622     const ExecutionContext *exe_ctx,
623     const Address &start,
624     uint32_t num_instructions
625 )
626 {
627     m_instruction_list.Clear();
628 
629     if (num_instructions == 0 || !start.IsValid())
630         return 0;
631 
632     Target *target = exe_ctx->target;
633     // Calculate the max buffer size we will need in order to disassemble
634     const addr_t byte_size = num_instructions * m_arch.GetMaximumOpcodeByteSize();
635 
636     if (target == NULL || byte_size == 0)
637         return 0;
638 
639     DataBufferHeap *heap_buffer = new DataBufferHeap (byte_size, '\0');
640     DataBufferSP data_sp (heap_buffer);
641 
642     Error error;
643     bool prefer_file_cache = true;
644     const size_t bytes_read = target->ReadMemory (start,
645                                                   prefer_file_cache,
646                                                   heap_buffer->GetBytes(),
647                                                   byte_size,
648                                                   error);
649 
650     if (bytes_read == 0)
651         return 0;
652     DataExtractor data (data_sp,
653                         m_arch.GetByteOrder(),
654                         m_arch.GetAddressByteSize());
655 
656     const bool append_instructions = true;
657     DecodeInstructions (start,
658                         data,
659                         0,
660                         num_instructions,
661                         append_instructions);
662 
663     return m_instruction_list.GetSize();
664 }
665 
666 //----------------------------------------------------------------------
667 // Disassembler copy constructor
668 //----------------------------------------------------------------------
669 Disassembler::Disassembler(const ArchSpec& arch) :
670     m_arch (arch),
671     m_instruction_list(),
672     m_base_addr(LLDB_INVALID_ADDRESS)
673 {
674 
675 }
676 
677 //----------------------------------------------------------------------
678 // Destructor
679 //----------------------------------------------------------------------
680 Disassembler::~Disassembler()
681 {
682 }
683 
684 InstructionList &
685 Disassembler::GetInstructionList ()
686 {
687     return m_instruction_list;
688 }
689 
690 const InstructionList &
691 Disassembler::GetInstructionList () const
692 {
693     return m_instruction_list;
694 }
695