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