]> CyberLeo.Net >> Repos - FreeBSD/releng/10.0.git/blob - contrib/llvm/tools/lldb/source/Plugins/Disassembler/llvm/DisassemblerLLVMC.cpp
- Copy stable/10 (r259064) to releng/10.0 as part of the
[FreeBSD/releng/10.0.git] / contrib / llvm / tools / lldb / source / Plugins / Disassembler / llvm / DisassemblerLLVMC.cpp
1 //===-- DisassemblerLLVMC.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 "DisassemblerLLVMC.h"
11
12 #include "llvm-c/Disassembler.h"
13 #include "llvm/MC/MCAsmInfo.h"
14 #include "llvm/MC/MCContext.h"
15 #include "llvm/MC/MCDisassembler.h"
16 #include "llvm/MC/MCInst.h"
17 #include "llvm/MC/MCInstPrinter.h"
18 #include "llvm/MC/MCInstrInfo.h"
19 #include "llvm/MC/MCRegisterInfo.h"
20 #include "llvm/MC/MCSubtargetInfo.h"
21 #include "llvm/Support/ErrorHandling.h"
22 #include "llvm/Support/MemoryObject.h"
23 #include "llvm/Support/TargetRegistry.h"
24 #include "llvm/Support/TargetSelect.h"
25 #include "llvm/ADT/SmallString.h"
26
27
28 #include "lldb/Core/Address.h"
29 #include "lldb/Core/DataExtractor.h"
30 #include "lldb/Core/Module.h"
31 #include "lldb/Core/Stream.h"
32 #include "lldb/Symbol/SymbolContext.h"
33 #include "lldb/Target/ExecutionContext.h"
34 #include "lldb/Target/Process.h"
35 #include "lldb/Target/RegisterContext.h"
36 #include "lldb/Target/Target.h"
37 #include "lldb/Target/StackFrame.h"
38
39 #include <regex.h>
40
41 using namespace lldb;
42 using namespace lldb_private;
43
44 class InstructionLLVMC : public lldb_private::Instruction
45 {
46 public:
47     InstructionLLVMC (DisassemblerLLVMC &disasm,
48                       const lldb_private::Address &address, 
49                       AddressClass addr_class) :
50         Instruction (address, addr_class),
51         m_disasm_sp (disasm.shared_from_this()),
52         m_does_branch (eLazyBoolCalculate),
53         m_is_valid (false),
54         m_using_file_addr (false)
55     {
56     }
57     
58     virtual
59     ~InstructionLLVMC ()
60     {
61     }
62     
63     virtual bool
64     DoesBranch ()
65     {
66         if (m_does_branch == eLazyBoolCalculate)
67         {
68             GetDisassemblerLLVMC().Lock(this, NULL);
69             DataExtractor data;
70             if (m_opcode.GetData(data))
71             {
72                 bool is_alternate_isa;
73                 lldb::addr_t pc = m_address.GetFileAddress();
74
75                 DisassemblerLLVMC::LLVMCDisassembler *mc_disasm_ptr = GetDisasmToUse (is_alternate_isa);
76                 const uint8_t *opcode_data = data.GetDataStart();
77                 const size_t opcode_data_len = data.GetByteSize();
78                 llvm::MCInst inst;
79                 const size_t inst_size = mc_disasm_ptr->GetMCInst (opcode_data,
80                                                                    opcode_data_len,
81                                                                    pc,
82                                                                    inst);
83                 // Be conservative, if we didn't understand the instruction, say it might branch...
84                 if (inst_size == 0)
85                     m_does_branch = eLazyBoolYes;
86                 else
87                 {
88                     const bool can_branch = mc_disasm_ptr->CanBranch(inst);
89                     if (can_branch)
90                         m_does_branch = eLazyBoolYes;
91                     else
92                         m_does_branch = eLazyBoolNo;
93                 }
94             }
95             GetDisassemblerLLVMC().Unlock();
96         }
97         return m_does_branch == eLazyBoolYes;
98     }
99     
100     DisassemblerLLVMC::LLVMCDisassembler *
101     GetDisasmToUse (bool &is_alternate_isa)
102     {
103         is_alternate_isa = false;
104         DisassemblerLLVMC &llvm_disasm = GetDisassemblerLLVMC();
105         if (llvm_disasm.m_alternate_disasm_ap.get() != NULL)
106         {
107             const AddressClass address_class = GetAddressClass ();
108         
109             if (address_class == eAddressClassCodeAlternateISA)
110             {
111                 is_alternate_isa = true;
112                 return llvm_disasm.m_alternate_disasm_ap.get();
113             }
114         }
115         return llvm_disasm.m_disasm_ap.get();
116     }
117     
118     virtual size_t
119     Decode (const lldb_private::Disassembler &disassembler,
120             const lldb_private::DataExtractor &data,
121             lldb::offset_t data_offset)
122     {
123         // All we have to do is read the opcode which can be easy for some
124         // architectures
125         bool got_op = false;
126         DisassemblerLLVMC &llvm_disasm = GetDisassemblerLLVMC();
127         const ArchSpec &arch = llvm_disasm.GetArchitecture();
128         
129         const uint32_t min_op_byte_size = arch.GetMinimumOpcodeByteSize();
130         const uint32_t max_op_byte_size = arch.GetMaximumOpcodeByteSize();
131         if (min_op_byte_size == max_op_byte_size)
132         {
133             // Fixed size instructions, just read that amount of data.
134             if (!data.ValidOffsetForDataOfSize(data_offset, min_op_byte_size))
135                 return false;
136             
137             switch (min_op_byte_size)
138             {
139                 case 1:
140                     m_opcode.SetOpcode8  (data.GetU8  (&data_offset));
141                     got_op = true;
142                     break;
143
144                 case 2:
145                     m_opcode.SetOpcode16 (data.GetU16 (&data_offset));
146                     got_op = true;
147                     break;
148
149                 case 4:
150                     m_opcode.SetOpcode32 (data.GetU32 (&data_offset));
151                     got_op = true;
152                     break;
153
154                 case 8:
155                     m_opcode.SetOpcode64 (data.GetU64 (&data_offset));
156                     got_op = true;
157                     break;
158
159                 default:
160                     m_opcode.SetOpcodeBytes(data.PeekData(data_offset, min_op_byte_size), min_op_byte_size);
161                     got_op = true;
162                     break;
163             }
164         }
165         if (!got_op)
166         {
167             bool is_alternate_isa = false;
168             DisassemblerLLVMC::LLVMCDisassembler *mc_disasm_ptr = GetDisasmToUse (is_alternate_isa);
169             
170             const llvm::Triple::ArchType machine = arch.GetMachine();
171             if (machine == llvm::Triple::arm || machine == llvm::Triple::thumb)
172             {
173                 if (machine == llvm::Triple::thumb || is_alternate_isa)
174                 {
175                     uint32_t thumb_opcode = data.GetU16(&data_offset);
176                     if ((thumb_opcode & 0xe000) != 0xe000 || ((thumb_opcode & 0x1800u) == 0))
177                     {
178                         m_opcode.SetOpcode16 (thumb_opcode);
179                         m_is_valid = true;
180                     }
181                     else
182                     {
183                         thumb_opcode <<= 16;
184                         thumb_opcode |= data.GetU16(&data_offset);
185                         m_opcode.SetOpcode16_2 (thumb_opcode);
186                         m_is_valid = true;
187                     }
188                 }
189                 else
190                 {
191                     m_opcode.SetOpcode32 (data.GetU32(&data_offset));
192                     m_is_valid = true;
193                 }
194             }
195             else
196             {
197                 // The opcode isn't evenly sized, so we need to actually use the llvm
198                 // disassembler to parse it and get the size.
199                 uint8_t *opcode_data = const_cast<uint8_t *>(data.PeekData (data_offset, 1));
200                 const size_t opcode_data_len = data.BytesLeft(data_offset);
201                 const addr_t pc = m_address.GetFileAddress();
202                 llvm::MCInst inst;
203                 
204                 llvm_disasm.Lock(this, NULL);
205                 const size_t inst_size = mc_disasm_ptr->GetMCInst(opcode_data,
206                                                                   opcode_data_len,
207                                                                   pc,
208                                                                   inst);
209                 llvm_disasm.Unlock();
210                 if (inst_size == 0)
211                     m_opcode.Clear();
212                 else
213                 {
214                     m_opcode.SetOpcodeBytes(opcode_data, inst_size);
215                     m_is_valid = true;
216                 }
217             }
218         }
219         return m_opcode.GetByteSize();
220     }
221     
222     void
223     AppendComment (std::string &description)
224     {
225         if (m_comment.empty())
226             m_comment.swap (description);
227         else
228         {
229             m_comment.append(", ");
230             m_comment.append(description);
231         }
232     }
233     
234     virtual void
235     CalculateMnemonicOperandsAndComment (const lldb_private::ExecutionContext *exe_ctx)
236     {
237         DataExtractor data;
238         const AddressClass address_class = GetAddressClass ();
239
240         if (m_opcode.GetData(data))
241         {
242             char out_string[512];
243             
244             DisassemblerLLVMC &llvm_disasm = GetDisassemblerLLVMC();
245
246             DisassemblerLLVMC::LLVMCDisassembler *mc_disasm_ptr;
247             
248             if (address_class == eAddressClassCodeAlternateISA)
249                 mc_disasm_ptr = llvm_disasm.m_alternate_disasm_ap.get();
250             else
251                 mc_disasm_ptr = llvm_disasm.m_disasm_ap.get();
252             
253             lldb::addr_t pc = m_address.GetFileAddress();
254             m_using_file_addr = true;
255             
256             const bool data_from_file = GetDisassemblerLLVMC().m_data_from_file;
257             bool use_hex_immediates = true;
258             Disassembler::HexImmediateStyle hex_style = Disassembler::eHexStyleC;
259
260             if (exe_ctx)
261             {
262                 Target *target = exe_ctx->GetTargetPtr();
263                 if (target)
264                 {
265                     use_hex_immediates = target->GetUseHexImmediates();
266                     hex_style = target->GetHexImmediateStyle();
267
268                     if (!data_from_file)
269                     {
270                         const lldb::addr_t load_addr = m_address.GetLoadAddress(target);
271                         if (load_addr != LLDB_INVALID_ADDRESS)
272                         {
273                             pc = load_addr;
274                             m_using_file_addr = false;
275                         }
276                     }
277                 }
278             }
279             
280             llvm_disasm.Lock(this, exe_ctx);
281             
282             const uint8_t *opcode_data = data.GetDataStart();
283             const size_t opcode_data_len = data.GetByteSize();
284             llvm::MCInst inst;
285             size_t inst_size = mc_disasm_ptr->GetMCInst (opcode_data,
286                                                          opcode_data_len,
287                                                          pc,
288                                                          inst);
289
290             if (inst_size > 0)
291             {
292                 mc_disasm_ptr->SetStyle(use_hex_immediates, hex_style);
293                 mc_disasm_ptr->PrintMCInst(inst, out_string, sizeof(out_string));
294             }
295
296             llvm_disasm.Unlock();
297             
298             if (inst_size == 0)
299             {
300                 m_comment.assign ("unknown opcode");
301                 inst_size = m_opcode.GetByteSize();
302                 StreamString mnemonic_strm;
303                 lldb::offset_t offset = 0;
304                 switch (inst_size)
305                 {
306                     case 1:
307                         {
308                             const uint8_t uval8 = data.GetU8 (&offset);
309                             m_opcode.SetOpcode8 (uval8);
310                             m_opcode_name.assign (".byte");
311                             mnemonic_strm.Printf("0x%2.2x", uval8);
312                         }
313                         break;
314                     case 2:
315                         {
316                             const uint16_t uval16 = data.GetU16(&offset);
317                             m_opcode.SetOpcode16(uval16);
318                             m_opcode_name.assign (".short");
319                             mnemonic_strm.Printf("0x%4.4x", uval16);
320                         }
321                         break;
322                     case 4:
323                         {
324                             const uint32_t uval32 = data.GetU32(&offset);
325                             m_opcode.SetOpcode32(uval32);
326                             m_opcode_name.assign (".long");
327                             mnemonic_strm.Printf("0x%8.8x", uval32);
328                         }
329                         break;
330                     case 8:
331                         {
332                             const uint64_t uval64 = data.GetU64(&offset);
333                             m_opcode.SetOpcode64(uval64);
334                             m_opcode_name.assign (".quad");
335                             mnemonic_strm.Printf("0x%16.16" PRIx64, uval64);
336                         }
337                         break;
338                     default:
339                         if (inst_size == 0)
340                             return;
341                         else
342                         {
343                             const uint8_t *bytes = data.PeekData(offset, inst_size);
344                             if (bytes == NULL)
345                                 return;
346                             m_opcode_name.assign (".byte");
347                             m_opcode.SetOpcodeBytes(bytes, inst_size);
348                             mnemonic_strm.Printf("0x%2.2x", bytes[0]);
349                             for (uint32_t i=1; i<inst_size; ++i)
350                                 mnemonic_strm.Printf(" 0x%2.2x", bytes[i]);
351                         }
352                         break;
353                 }
354                 m_mnemonics.swap(mnemonic_strm.GetString());
355                 return;
356             }
357             else
358             {
359                 if (m_does_branch == eLazyBoolCalculate)
360                 {
361                     const bool can_branch = mc_disasm_ptr->CanBranch(inst);
362                     if (can_branch)
363                         m_does_branch = eLazyBoolYes;
364                     else
365                         m_does_branch = eLazyBoolNo;
366
367                 }
368             }
369             
370             if (!s_regex_compiled)
371             {
372                 ::regcomp(&s_regex, "[ \t]*([^ ^\t]+)[ \t]*([^ ^\t].*)?", REG_EXTENDED);
373                 s_regex_compiled = true;
374             }
375             
376             ::regmatch_t matches[3];
377             
378             if (!::regexec(&s_regex, out_string, sizeof(matches) / sizeof(::regmatch_t), matches, 0))
379             {
380                 if (matches[1].rm_so != -1)
381                     m_opcode_name.assign(out_string + matches[1].rm_so, matches[1].rm_eo - matches[1].rm_so);
382                 if (matches[2].rm_so != -1)
383                     m_mnemonics.assign(out_string + matches[2].rm_so, matches[2].rm_eo - matches[2].rm_so);
384             }
385         }
386     }
387     
388     bool
389     IsValid () const
390     {
391         return m_is_valid;
392     }
393     
394     bool
395     UsingFileAddress() const
396     {
397         return m_using_file_addr;
398     }
399     size_t
400     GetByteSize () const
401     {
402         return m_opcode.GetByteSize();
403     }
404     
405     DisassemblerLLVMC &
406     GetDisassemblerLLVMC ()
407     {
408         return *(DisassemblerLLVMC *)m_disasm_sp.get();
409     }
410 protected:
411     
412     DisassemblerSP          m_disasm_sp; // for ownership
413     LazyBool                m_does_branch;
414     bool                    m_is_valid;
415     bool                    m_using_file_addr;
416     
417     static bool             s_regex_compiled;
418     static ::regex_t        s_regex;
419 };
420
421 bool InstructionLLVMC::s_regex_compiled = false;
422 ::regex_t InstructionLLVMC::s_regex;
423
424 DisassemblerLLVMC::LLVMCDisassembler::LLVMCDisassembler (const char *triple, unsigned flavor, DisassemblerLLVMC &owner):
425     m_is_valid(true)
426 {
427     std::string Error;
428     const llvm::Target *curr_target = llvm::TargetRegistry::lookupTarget(triple, Error);
429     if (!curr_target)
430     {
431         m_is_valid = false;
432         return;
433     }
434     
435     m_instr_info_ap.reset(curr_target->createMCInstrInfo());
436     m_reg_info_ap.reset (curr_target->createMCRegInfo(triple));
437     
438     std::string features_str;
439
440     m_subtarget_info_ap.reset(curr_target->createMCSubtargetInfo(triple, "",
441                                                                 features_str));
442     
443     m_asm_info_ap.reset(curr_target->createMCAsmInfo(triple));
444     
445     if (m_instr_info_ap.get() == NULL || m_reg_info_ap.get() == NULL || m_subtarget_info_ap.get() == NULL || m_asm_info_ap.get() == NULL)
446     {
447         m_is_valid = false;
448         return;
449     }
450     
451     m_context_ap.reset(new llvm::MCContext(*m_asm_info_ap.get(), *(m_reg_info_ap.get()), 0));
452     
453     m_disasm_ap.reset(curr_target->createMCDisassembler(*m_subtarget_info_ap.get()));
454     if (m_disasm_ap.get())
455     {
456         m_disasm_ap->setupForSymbolicDisassembly(NULL,
457                                                   DisassemblerLLVMC::SymbolLookupCallback,
458                                                   (void *) &owner,
459                                                   m_context_ap.get());
460         
461         unsigned asm_printer_variant;
462         if (flavor == ~0U)
463             asm_printer_variant = m_asm_info_ap->getAssemblerDialect();
464         else
465         {
466             asm_printer_variant = flavor;
467         }
468         
469         m_instr_printer_ap.reset(curr_target->createMCInstPrinter(asm_printer_variant,
470                                                                   *m_asm_info_ap.get(),
471                                                                   *m_instr_info_ap.get(),
472                                                                   *m_reg_info_ap.get(),
473                                                                   *m_subtarget_info_ap.get()));
474         if (m_instr_printer_ap.get() == NULL)
475         {
476             m_disasm_ap.reset();
477             m_is_valid = false;
478         }
479     }
480     else
481         m_is_valid = false;
482 }
483
484 DisassemblerLLVMC::LLVMCDisassembler::~LLVMCDisassembler()
485 {
486 }
487
488 namespace {
489     // This is the memory object we use in GetInstruction.
490     class LLDBDisasmMemoryObject : public llvm::MemoryObject {
491       const uint8_t *m_bytes;
492       uint64_t m_size;
493       uint64_t m_base_PC;
494     public:
495       LLDBDisasmMemoryObject(const uint8_t *bytes, uint64_t size, uint64_t basePC) :
496                          m_bytes(bytes), m_size(size), m_base_PC(basePC) {}
497      
498       uint64_t getBase() const { return m_base_PC; }
499       uint64_t getExtent() const { return m_size; }
500
501       int readByte(uint64_t addr, uint8_t *byte) const {
502         if (addr - m_base_PC >= m_size)
503           return -1;
504         *byte = m_bytes[addr - m_base_PC];
505         return 0;
506       }
507     };
508 } // End Anonymous Namespace
509
510 uint64_t
511 DisassemblerLLVMC::LLVMCDisassembler::GetMCInst (const uint8_t *opcode_data,
512                                                  size_t opcode_data_len,
513                                                  lldb::addr_t pc,
514                                                  llvm::MCInst &mc_inst)
515 {
516     LLDBDisasmMemoryObject memory_object (opcode_data, opcode_data_len, pc);
517     llvm::MCDisassembler::DecodeStatus status;
518
519     uint64_t new_inst_size;
520     status = m_disasm_ap->getInstruction(mc_inst,
521                                          new_inst_size,
522                                          memory_object,
523                                          pc,
524                                          llvm::nulls(),
525                                          llvm::nulls());
526     if (status == llvm::MCDisassembler::Success)
527         return new_inst_size;
528     else
529         return 0;
530 }
531
532 uint64_t
533 DisassemblerLLVMC::LLVMCDisassembler::PrintMCInst (llvm::MCInst &mc_inst,
534                                                    char *dst,
535                                                    size_t dst_len)
536 {
537     llvm::StringRef unused_annotations;
538     llvm::SmallString<64> inst_string;
539     llvm::raw_svector_ostream inst_stream(inst_string);
540     m_instr_printer_ap->printInst (&mc_inst, inst_stream, unused_annotations);
541     inst_stream.flush();
542     const size_t output_size = std::min(dst_len - 1, inst_string.size());
543     std::memcpy(dst, inst_string.data(), output_size);
544     dst[output_size] = '\0';
545     
546     return output_size;
547 }
548
549 void
550 DisassemblerLLVMC::LLVMCDisassembler::SetStyle (bool use_hex_immed, HexImmediateStyle hex_style)
551 {
552     m_instr_printer_ap->setPrintImmHex(use_hex_immed);
553     switch(hex_style)
554     {
555     case eHexStyleC:      m_instr_printer_ap->setPrintImmHex(llvm::HexStyle::C); break;
556     case eHexStyleAsm:    m_instr_printer_ap->setPrintImmHex(llvm::HexStyle::Asm); break;
557     }
558 }
559
560 bool
561 DisassemblerLLVMC::LLVMCDisassembler::CanBranch (llvm::MCInst &mc_inst)
562 {
563     return m_instr_info_ap->get(mc_inst.getOpcode()).mayAffectControlFlow(mc_inst, *m_reg_info_ap.get());
564 }
565
566 bool
567 DisassemblerLLVMC::FlavorValidForArchSpec (const lldb_private::ArchSpec &arch, const char *flavor)
568 {
569     llvm::Triple triple = arch.GetTriple();
570     if (flavor == NULL || strcmp (flavor, "default") == 0)
571         return true;
572     
573     if (triple.getArch() == llvm::Triple::x86 || triple.getArch() == llvm::Triple::x86_64)
574     {
575         if (strcmp (flavor, "intel") == 0 || strcmp (flavor, "att") == 0)
576             return true;
577         else
578             return false;
579     }
580     else
581         return false;
582 }
583     
584
585 Disassembler *
586 DisassemblerLLVMC::CreateInstance (const ArchSpec &arch, const char *flavor)
587 {
588     if (arch.GetTriple().getArch() != llvm::Triple::UnknownArch)
589     {
590         std::unique_ptr<DisassemblerLLVMC> disasm_ap (new DisassemblerLLVMC(arch, flavor));
591     
592         if (disasm_ap.get() && disasm_ap->IsValid())
593             return disasm_ap.release();
594     }
595     return NULL;
596 }
597
598 DisassemblerLLVMC::DisassemblerLLVMC (const ArchSpec &arch, const char *flavor_string) :
599     Disassembler(arch, flavor_string),
600     m_exe_ctx (NULL),
601     m_inst (NULL),
602     m_data_from_file (false)
603 {
604     if (!FlavorValidForArchSpec (arch, m_flavor.c_str()))
605     {
606         m_flavor.assign("default");
607     }
608     
609     const char *triple = arch.GetTriple().getTriple().c_str();
610     unsigned flavor = ~0U;
611     
612     // So far the only supported flavor is "intel" on x86.  The base class will set this
613     // correctly coming in.
614     if (arch.GetTriple().getArch() == llvm::Triple::x86
615         || arch.GetTriple().getArch() == llvm::Triple::x86_64)
616     {
617         if (m_flavor == "intel")
618         {
619             flavor = 1;
620         }
621         else if (m_flavor == "att")
622         {
623             flavor = 0;
624         }
625     }
626     
627     ArchSpec thumb_arch(arch);
628     if (arch.GetTriple().getArch() == llvm::Triple::arm)
629     {
630         std::string thumb_arch_name (thumb_arch.GetTriple().getArchName().str());
631         // Replace "arm" with "thumb" so we get all thumb variants correct
632         if (thumb_arch_name.size() > 3)
633         {
634             thumb_arch_name.erase(0,3);
635             thumb_arch_name.insert(0, "thumb");
636         }
637         else
638         {
639             thumb_arch_name = "thumbv7";
640         }
641         thumb_arch.GetTriple().setArchName(llvm::StringRef(thumb_arch_name.c_str()));
642     }
643     
644     // Cortex-M3 devices (e.g. armv7m) can only execute thumb (T2) instructions, 
645     // so hardcode the primary disassembler to thumb mode.
646     if (arch.GetTriple().getArch() == llvm::Triple::arm
647         && (arch.GetCore() == ArchSpec::Core::eCore_arm_armv7m || arch.GetCore() == ArchSpec::Core::eCore_arm_armv7em))
648     {
649         triple = thumb_arch.GetTriple().getTriple().c_str();
650     }
651
652     m_disasm_ap.reset (new LLVMCDisassembler(triple, flavor, *this));
653     if (!m_disasm_ap->IsValid())
654     {
655         // We use m_disasm_ap.get() to tell whether we are valid or not, so if this isn't good for some reason,
656         // we reset it, and then we won't be valid and FindPlugin will fail and we won't get used.
657         m_disasm_ap.reset();
658     }
659
660     // For arm CPUs that can execute arm or thumb instructions, also create a thumb instruction disassembler.
661     if (arch.GetTriple().getArch() == llvm::Triple::arm)
662     {
663         std::string thumb_triple(thumb_arch.GetTriple().getTriple());
664         m_alternate_disasm_ap.reset(new LLVMCDisassembler(thumb_triple.c_str(), flavor, *this));
665         if (!m_alternate_disasm_ap->IsValid())
666         {
667             m_disasm_ap.reset();
668             m_alternate_disasm_ap.reset();
669         }
670     }
671 }
672
673 DisassemblerLLVMC::~DisassemblerLLVMC()
674 {
675 }
676
677 size_t
678 DisassemblerLLVMC::DecodeInstructions (const Address &base_addr,
679                                        const DataExtractor& data,
680                                        lldb::offset_t data_offset,
681                                        size_t num_instructions,
682                                        bool append,
683                                        bool data_from_file)
684 {
685     if (!append)
686         m_instruction_list.Clear();
687     
688     if (!IsValid())
689         return 0;
690     
691     m_data_from_file = data_from_file;
692     uint32_t data_cursor = data_offset;
693     const size_t data_byte_size = data.GetByteSize();
694     uint32_t instructions_parsed = 0;
695     Address inst_addr(base_addr);
696     
697     while (data_cursor < data_byte_size && instructions_parsed < num_instructions)
698     {
699         
700         AddressClass address_class = eAddressClassCode;
701         
702         if (m_alternate_disasm_ap.get() != NULL)
703             address_class = inst_addr.GetAddressClass ();
704         
705         InstructionSP inst_sp(new InstructionLLVMC(*this,
706                                                    inst_addr, 
707                                                    address_class));
708         
709         if (!inst_sp)
710             break;
711         
712         uint32_t inst_size = inst_sp->Decode(*this, data, data_cursor);
713                 
714         if (inst_size == 0)
715             break;
716
717         m_instruction_list.Append(inst_sp);
718         data_cursor += inst_size;
719         inst_addr.Slide(inst_size);
720         instructions_parsed++;
721     }
722     
723     return data_cursor - data_offset;
724 }
725
726 void
727 DisassemblerLLVMC::Initialize()
728 {
729     PluginManager::RegisterPlugin (GetPluginNameStatic(),
730                                    "Disassembler that uses LLVM MC to disassemble i386, x86_64 and ARM.",
731                                    CreateInstance);
732     
733     llvm::InitializeAllTargetInfos();
734     llvm::InitializeAllTargetMCs();
735     llvm::InitializeAllAsmParsers();
736     llvm::InitializeAllDisassemblers();
737 }
738
739 void
740 DisassemblerLLVMC::Terminate()
741 {
742     PluginManager::UnregisterPlugin (CreateInstance);
743 }
744
745
746 ConstString
747 DisassemblerLLVMC::GetPluginNameStatic()
748 {
749     static ConstString g_name("llvm-mc");
750     return g_name;
751 }
752
753 int DisassemblerLLVMC::OpInfoCallback (void *disassembler,
754                                        uint64_t pc,
755                                        uint64_t offset,
756                                        uint64_t size,
757                                        int tag_type,
758                                        void *tag_bug)
759 {
760     return static_cast<DisassemblerLLVMC*>(disassembler)->OpInfo (pc,
761                                                                   offset,
762                                                                   size,
763                                                                   tag_type,
764                                                                   tag_bug);
765 }
766
767 const char *DisassemblerLLVMC::SymbolLookupCallback (void *disassembler,
768                                                      uint64_t value,
769                                                      uint64_t *type,
770                                                      uint64_t pc,
771                                                      const char **name)
772 {
773     return static_cast<DisassemblerLLVMC*>(disassembler)->SymbolLookup(value,
774                                                                        type,
775                                                                        pc,
776                                                                        name);
777 }
778
779 int DisassemblerLLVMC::OpInfo (uint64_t PC,
780                                uint64_t Offset,
781                                uint64_t Size,
782                                int tag_type,
783                                void *tag_bug)
784 {
785     switch (tag_type)
786     {
787     default:
788         break;
789     case 1:
790         bzero (tag_bug, sizeof(::LLVMOpInfo1));
791         break;
792     }
793     return 0;
794 }
795
796 const char *DisassemblerLLVMC::SymbolLookup (uint64_t value,
797                                              uint64_t *type_ptr,
798                                              uint64_t pc,
799                                              const char **name)
800 {
801     if (*type_ptr)
802     {
803         if (m_exe_ctx && m_inst)
804         {        
805             //std::string remove_this_prior_to_checkin;
806             Target *target = m_exe_ctx ? m_exe_ctx->GetTargetPtr() : NULL;
807             Address value_so_addr;
808             if (m_inst->UsingFileAddress())
809             {
810                 ModuleSP module_sp(m_inst->GetAddress().GetModule());
811                 if (module_sp)
812                     module_sp->ResolveFileAddress(value, value_so_addr);
813             }
814             else if (target && !target->GetSectionLoadList().IsEmpty())
815             {
816                 target->GetSectionLoadList().ResolveLoadAddress(value, value_so_addr);
817             }
818             
819             if (value_so_addr.IsValid() && value_so_addr.GetSection())
820             {
821                 StreamString ss;
822                 
823                 value_so_addr.Dump (&ss,
824                                     target,
825                                     Address::DumpStyleResolvedDescriptionNoModule,
826                                     Address::DumpStyleSectionNameOffset);
827                 
828                 if (!ss.GetString().empty())
829                 {
830                     m_inst->AppendComment(ss.GetString());
831                 }
832             }
833         }
834     }
835
836     *type_ptr = LLVMDisassembler_ReferenceType_InOut_None;
837     *name = NULL;
838     return NULL;
839 }
840
841 //------------------------------------------------------------------
842 // PluginInterface protocol
843 //------------------------------------------------------------------
844 ConstString
845 DisassemblerLLVMC::GetPluginName()
846 {
847     return GetPluginNameStatic();
848 }
849
850 uint32_t
851 DisassemblerLLVMC::GetPluginVersion()
852 {
853     return 1;
854 }
855