xref: /freebsd/contrib/llvm-project/lldb/source/Plugins/Disassembler/LLVMC/DisassemblerLLVMC.cpp (revision cfd6422a5217410fbd66f7a7a8a64d9d85e61229)
1 //===-- DisassemblerLLVMC.cpp ---------------------------------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #include "DisassemblerLLVMC.h"
10 
11 #include "llvm-c/Disassembler.h"
12 #include "llvm/ADT/SmallString.h"
13 #include "llvm/MC/MCAsmInfo.h"
14 #include "llvm/MC/MCContext.h"
15 #include "llvm/MC/MCDisassembler/MCDisassembler.h"
16 #include "llvm/MC/MCDisassembler/MCExternalSymbolizer.h"
17 #include "llvm/MC/MCDisassembler/MCRelocationInfo.h"
18 #include "llvm/MC/MCInst.h"
19 #include "llvm/MC/MCInstPrinter.h"
20 #include "llvm/MC/MCInstrInfo.h"
21 #include "llvm/MC/MCRegisterInfo.h"
22 #include "llvm/MC/MCSubtargetInfo.h"
23 #include "llvm/MC/MCTargetOptions.h"
24 #include "llvm/Support/ErrorHandling.h"
25 #include "llvm/Support/ScopedPrinter.h"
26 #include "llvm/Support/TargetRegistry.h"
27 #include "llvm/Support/TargetSelect.h"
28 
29 #include "lldb/Core/Address.h"
30 #include "lldb/Core/Module.h"
31 #include "lldb/Symbol/SymbolContext.h"
32 #include "lldb/Target/ExecutionContext.h"
33 #include "lldb/Target/Process.h"
34 #include "lldb/Target/RegisterContext.h"
35 #include "lldb/Target/SectionLoadList.h"
36 #include "lldb/Target/StackFrame.h"
37 #include "lldb/Target/Target.h"
38 #include "lldb/Utility/DataExtractor.h"
39 #include "lldb/Utility/Log.h"
40 #include "lldb/Utility/RegularExpression.h"
41 #include "lldb/Utility/Stream.h"
42 
43 using namespace lldb;
44 using namespace lldb_private;
45 
46 LLDB_PLUGIN_DEFINE(DisassemblerLLVMC)
47 
48 class DisassemblerLLVMC::MCDisasmInstance {
49 public:
50   static std::unique_ptr<MCDisasmInstance>
51   Create(const char *triple, const char *cpu, const char *features_str,
52          unsigned flavor, DisassemblerLLVMC &owner);
53 
54   ~MCDisasmInstance() = default;
55 
56   uint64_t GetMCInst(const uint8_t *opcode_data, size_t opcode_data_len,
57                      lldb::addr_t pc, llvm::MCInst &mc_inst) const;
58   void PrintMCInst(llvm::MCInst &mc_inst, std::string &inst_string,
59                    std::string &comments_string);
60   void SetStyle(bool use_hex_immed, HexImmediateStyle hex_style);
61   bool CanBranch(llvm::MCInst &mc_inst) const;
62   bool HasDelaySlot(llvm::MCInst &mc_inst) const;
63   bool IsCall(llvm::MCInst &mc_inst) const;
64 
65 private:
66   MCDisasmInstance(std::unique_ptr<llvm::MCInstrInfo> &&instr_info_up,
67                    std::unique_ptr<llvm::MCRegisterInfo> &&reg_info_up,
68                    std::unique_ptr<llvm::MCSubtargetInfo> &&subtarget_info_up,
69                    std::unique_ptr<llvm::MCAsmInfo> &&asm_info_up,
70                    std::unique_ptr<llvm::MCContext> &&context_up,
71                    std::unique_ptr<llvm::MCDisassembler> &&disasm_up,
72                    std::unique_ptr<llvm::MCInstPrinter> &&instr_printer_up);
73 
74   std::unique_ptr<llvm::MCInstrInfo> m_instr_info_up;
75   std::unique_ptr<llvm::MCRegisterInfo> m_reg_info_up;
76   std::unique_ptr<llvm::MCSubtargetInfo> m_subtarget_info_up;
77   std::unique_ptr<llvm::MCAsmInfo> m_asm_info_up;
78   std::unique_ptr<llvm::MCContext> m_context_up;
79   std::unique_ptr<llvm::MCDisassembler> m_disasm_up;
80   std::unique_ptr<llvm::MCInstPrinter> m_instr_printer_up;
81 };
82 
83 class InstructionLLVMC : public lldb_private::Instruction {
84 public:
85   InstructionLLVMC(DisassemblerLLVMC &disasm,
86                    const lldb_private::Address &address,
87                    AddressClass addr_class)
88       : Instruction(address, addr_class),
89         m_disasm_wp(std::static_pointer_cast<DisassemblerLLVMC>(
90             disasm.shared_from_this())),
91         m_using_file_addr(false) {}
92 
93   ~InstructionLLVMC() override = default;
94 
95   bool DoesBranch() override {
96     VisitInstruction();
97     return m_does_branch;
98   }
99 
100   bool HasDelaySlot() override {
101     VisitInstruction();
102     return m_has_delay_slot;
103   }
104 
105   DisassemblerLLVMC::MCDisasmInstance *GetDisasmToUse(bool &is_alternate_isa) {
106     DisassemblerScope disasm(*this);
107     return GetDisasmToUse(is_alternate_isa, disasm);
108   }
109 
110   size_t Decode(const lldb_private::Disassembler &disassembler,
111                 const lldb_private::DataExtractor &data,
112                 lldb::offset_t data_offset) override {
113     // All we have to do is read the opcode which can be easy for some
114     // architectures
115     bool got_op = false;
116     DisassemblerScope disasm(*this);
117     if (disasm) {
118       const ArchSpec &arch = disasm->GetArchitecture();
119       const lldb::ByteOrder byte_order = data.GetByteOrder();
120 
121       const uint32_t min_op_byte_size = arch.GetMinimumOpcodeByteSize();
122       const uint32_t max_op_byte_size = arch.GetMaximumOpcodeByteSize();
123       if (min_op_byte_size == max_op_byte_size) {
124         // Fixed size instructions, just read that amount of data.
125         if (!data.ValidOffsetForDataOfSize(data_offset, min_op_byte_size))
126           return false;
127 
128         switch (min_op_byte_size) {
129         case 1:
130           m_opcode.SetOpcode8(data.GetU8(&data_offset), byte_order);
131           got_op = true;
132           break;
133 
134         case 2:
135           m_opcode.SetOpcode16(data.GetU16(&data_offset), byte_order);
136           got_op = true;
137           break;
138 
139         case 4:
140           m_opcode.SetOpcode32(data.GetU32(&data_offset), byte_order);
141           got_op = true;
142           break;
143 
144         case 8:
145           m_opcode.SetOpcode64(data.GetU64(&data_offset), byte_order);
146           got_op = true;
147           break;
148 
149         default:
150           m_opcode.SetOpcodeBytes(data.PeekData(data_offset, min_op_byte_size),
151                                   min_op_byte_size);
152           got_op = true;
153           break;
154         }
155       }
156       if (!got_op) {
157         bool is_alternate_isa = false;
158         DisassemblerLLVMC::MCDisasmInstance *mc_disasm_ptr =
159             GetDisasmToUse(is_alternate_isa, disasm);
160 
161         const llvm::Triple::ArchType machine = arch.GetMachine();
162         if (machine == llvm::Triple::arm || machine == llvm::Triple::thumb) {
163           if (machine == llvm::Triple::thumb || is_alternate_isa) {
164             uint32_t thumb_opcode = data.GetU16(&data_offset);
165             if ((thumb_opcode & 0xe000) != 0xe000 ||
166                 ((thumb_opcode & 0x1800u) == 0)) {
167               m_opcode.SetOpcode16(thumb_opcode, byte_order);
168               m_is_valid = true;
169             } else {
170               thumb_opcode <<= 16;
171               thumb_opcode |= data.GetU16(&data_offset);
172               m_opcode.SetOpcode16_2(thumb_opcode, byte_order);
173               m_is_valid = true;
174             }
175           } else {
176             m_opcode.SetOpcode32(data.GetU32(&data_offset), byte_order);
177             m_is_valid = true;
178           }
179         } else {
180           // The opcode isn't evenly sized, so we need to actually use the llvm
181           // disassembler to parse it and get the size.
182           uint8_t *opcode_data =
183               const_cast<uint8_t *>(data.PeekData(data_offset, 1));
184           const size_t opcode_data_len = data.BytesLeft(data_offset);
185           const addr_t pc = m_address.GetFileAddress();
186           llvm::MCInst inst;
187 
188           const size_t inst_size =
189               mc_disasm_ptr->GetMCInst(opcode_data, opcode_data_len, pc, inst);
190           if (inst_size == 0)
191             m_opcode.Clear();
192           else {
193             m_opcode.SetOpcodeBytes(opcode_data, inst_size);
194             m_is_valid = true;
195           }
196         }
197       }
198       return m_opcode.GetByteSize();
199     }
200     return 0;
201   }
202 
203   void AppendComment(std::string &description) {
204     if (m_comment.empty())
205       m_comment.swap(description);
206     else {
207       m_comment.append(", ");
208       m_comment.append(description);
209     }
210   }
211 
212   void CalculateMnemonicOperandsAndComment(
213       const lldb_private::ExecutionContext *exe_ctx) override {
214     DataExtractor data;
215     const AddressClass address_class = GetAddressClass();
216 
217     if (m_opcode.GetData(data)) {
218       std::string out_string;
219       std::string comment_string;
220 
221       DisassemblerScope disasm(*this, exe_ctx);
222       if (disasm) {
223         DisassemblerLLVMC::MCDisasmInstance *mc_disasm_ptr;
224 
225         if (address_class == AddressClass::eCodeAlternateISA)
226           mc_disasm_ptr = disasm->m_alternate_disasm_up.get();
227         else
228           mc_disasm_ptr = disasm->m_disasm_up.get();
229 
230         lldb::addr_t pc = m_address.GetFileAddress();
231         m_using_file_addr = true;
232 
233         const bool data_from_file = disasm->m_data_from_file;
234         bool use_hex_immediates = true;
235         Disassembler::HexImmediateStyle hex_style = Disassembler::eHexStyleC;
236 
237         if (exe_ctx) {
238           Target *target = exe_ctx->GetTargetPtr();
239           if (target) {
240             use_hex_immediates = target->GetUseHexImmediates();
241             hex_style = target->GetHexImmediateStyle();
242 
243             if (!data_from_file) {
244               const lldb::addr_t load_addr = m_address.GetLoadAddress(target);
245               if (load_addr != LLDB_INVALID_ADDRESS) {
246                 pc = load_addr;
247                 m_using_file_addr = false;
248               }
249             }
250           }
251         }
252 
253         const uint8_t *opcode_data = data.GetDataStart();
254         const size_t opcode_data_len = data.GetByteSize();
255         llvm::MCInst inst;
256         size_t inst_size =
257             mc_disasm_ptr->GetMCInst(opcode_data, opcode_data_len, pc, inst);
258 
259         if (inst_size > 0) {
260           mc_disasm_ptr->SetStyle(use_hex_immediates, hex_style);
261           mc_disasm_ptr->PrintMCInst(inst, out_string, comment_string);
262 
263           if (!comment_string.empty()) {
264             AppendComment(comment_string);
265           }
266         }
267 
268         if (inst_size == 0) {
269           m_comment.assign("unknown opcode");
270           inst_size = m_opcode.GetByteSize();
271           StreamString mnemonic_strm;
272           lldb::offset_t offset = 0;
273           lldb::ByteOrder byte_order = data.GetByteOrder();
274           switch (inst_size) {
275           case 1: {
276             const uint8_t uval8 = data.GetU8(&offset);
277             m_opcode.SetOpcode8(uval8, byte_order);
278             m_opcode_name.assign(".byte");
279             mnemonic_strm.Printf("0x%2.2x", uval8);
280           } break;
281           case 2: {
282             const uint16_t uval16 = data.GetU16(&offset);
283             m_opcode.SetOpcode16(uval16, byte_order);
284             m_opcode_name.assign(".short");
285             mnemonic_strm.Printf("0x%4.4x", uval16);
286           } break;
287           case 4: {
288             const uint32_t uval32 = data.GetU32(&offset);
289             m_opcode.SetOpcode32(uval32, byte_order);
290             m_opcode_name.assign(".long");
291             mnemonic_strm.Printf("0x%8.8x", uval32);
292           } break;
293           case 8: {
294             const uint64_t uval64 = data.GetU64(&offset);
295             m_opcode.SetOpcode64(uval64, byte_order);
296             m_opcode_name.assign(".quad");
297             mnemonic_strm.Printf("0x%16.16" PRIx64, uval64);
298           } break;
299           default:
300             if (inst_size == 0)
301               return;
302             else {
303               const uint8_t *bytes = data.PeekData(offset, inst_size);
304               if (bytes == nullptr)
305                 return;
306               m_opcode_name.assign(".byte");
307               m_opcode.SetOpcodeBytes(bytes, inst_size);
308               mnemonic_strm.Printf("0x%2.2x", bytes[0]);
309               for (uint32_t i = 1; i < inst_size; ++i)
310                 mnemonic_strm.Printf(" 0x%2.2x", bytes[i]);
311             }
312             break;
313           }
314           m_mnemonics = std::string(mnemonic_strm.GetString());
315           return;
316         }
317 
318         static RegularExpression s_regex(
319             llvm::StringRef("[ \t]*([^ ^\t]+)[ \t]*([^ ^\t].*)?"));
320 
321         llvm::SmallVector<llvm::StringRef, 4> matches;
322         if (s_regex.Execute(out_string, &matches)) {
323           m_opcode_name = matches[1].str();
324           m_mnemonics = matches[2].str();
325         }
326       }
327     }
328   }
329 
330   bool IsValid() const { return m_is_valid; }
331 
332   bool UsingFileAddress() const { return m_using_file_addr; }
333   size_t GetByteSize() const { return m_opcode.GetByteSize(); }
334 
335   /// Grants exclusive access to the disassembler and initializes it with the
336   /// given InstructionLLVMC and an optional ExecutionContext.
337   class DisassemblerScope {
338     std::shared_ptr<DisassemblerLLVMC> m_disasm;
339 
340   public:
341     explicit DisassemblerScope(
342         InstructionLLVMC &i,
343         const lldb_private::ExecutionContext *exe_ctx = nullptr)
344         : m_disasm(i.m_disasm_wp.lock()) {
345       m_disasm->m_mutex.lock();
346       m_disasm->m_inst = &i;
347       m_disasm->m_exe_ctx = exe_ctx;
348     }
349     ~DisassemblerScope() { m_disasm->m_mutex.unlock(); }
350 
351     /// Evaluates to true if this scope contains a valid disassembler.
352     operator bool() const { return static_cast<bool>(m_disasm); }
353 
354     std::shared_ptr<DisassemblerLLVMC> operator->() { return m_disasm; }
355   };
356 
357   static llvm::StringRef::const_iterator
358   ConsumeWhitespace(llvm::StringRef::const_iterator osi,
359                     llvm::StringRef::const_iterator ose) {
360     while (osi != ose) {
361       switch (*osi) {
362       default:
363         return osi;
364       case ' ':
365       case '\t':
366         break;
367       }
368       ++osi;
369     }
370 
371     return osi;
372   }
373 
374   static std::pair<bool, llvm::StringRef::const_iterator>
375   ConsumeChar(llvm::StringRef::const_iterator osi, const char c,
376               llvm::StringRef::const_iterator ose) {
377     bool found = false;
378 
379     osi = ConsumeWhitespace(osi, ose);
380     if (osi != ose && *osi == c) {
381       found = true;
382       ++osi;
383     }
384 
385     return std::make_pair(found, osi);
386   }
387 
388   static std::pair<Operand, llvm::StringRef::const_iterator>
389   ParseRegisterName(llvm::StringRef::const_iterator osi,
390                     llvm::StringRef::const_iterator ose) {
391     Operand ret;
392     ret.m_type = Operand::Type::Register;
393     std::string str;
394 
395     osi = ConsumeWhitespace(osi, ose);
396 
397     while (osi != ose) {
398       if (*osi >= '0' && *osi <= '9') {
399         if (str.empty()) {
400           return std::make_pair(Operand(), osi);
401         } else {
402           str.push_back(*osi);
403         }
404       } else if (*osi >= 'a' && *osi <= 'z') {
405         str.push_back(*osi);
406       } else {
407         switch (*osi) {
408         default:
409           if (str.empty()) {
410             return std::make_pair(Operand(), osi);
411           } else {
412             ret.m_register = ConstString(str);
413             return std::make_pair(ret, osi);
414           }
415         case '%':
416           if (!str.empty()) {
417             return std::make_pair(Operand(), osi);
418           }
419           break;
420         }
421       }
422       ++osi;
423     }
424 
425     ret.m_register = ConstString(str);
426     return std::make_pair(ret, osi);
427   }
428 
429   static std::pair<Operand, llvm::StringRef::const_iterator>
430   ParseImmediate(llvm::StringRef::const_iterator osi,
431                  llvm::StringRef::const_iterator ose) {
432     Operand ret;
433     ret.m_type = Operand::Type::Immediate;
434     std::string str;
435     bool is_hex = false;
436 
437     osi = ConsumeWhitespace(osi, ose);
438 
439     while (osi != ose) {
440       if (*osi >= '0' && *osi <= '9') {
441         str.push_back(*osi);
442       } else if (*osi >= 'a' && *osi <= 'f') {
443         if (is_hex) {
444           str.push_back(*osi);
445         } else {
446           return std::make_pair(Operand(), osi);
447         }
448       } else {
449         switch (*osi) {
450         default:
451           if (str.empty()) {
452             return std::make_pair(Operand(), osi);
453           } else {
454             ret.m_immediate = strtoull(str.c_str(), nullptr, 0);
455             return std::make_pair(ret, osi);
456           }
457         case 'x':
458           if (!str.compare("0")) {
459             is_hex = true;
460             str.push_back(*osi);
461           } else {
462             return std::make_pair(Operand(), osi);
463           }
464           break;
465         case '#':
466         case '$':
467           if (!str.empty()) {
468             return std::make_pair(Operand(), osi);
469           }
470           break;
471         case '-':
472           if (str.empty()) {
473             ret.m_negative = true;
474           } else {
475             return std::make_pair(Operand(), osi);
476           }
477         }
478       }
479       ++osi;
480     }
481 
482     ret.m_immediate = strtoull(str.c_str(), nullptr, 0);
483     return std::make_pair(ret, osi);
484   }
485 
486   // -0x5(%rax,%rax,2)
487   static std::pair<Operand, llvm::StringRef::const_iterator>
488   ParseIntelIndexedAccess(llvm::StringRef::const_iterator osi,
489                           llvm::StringRef::const_iterator ose) {
490     std::pair<Operand, llvm::StringRef::const_iterator> offset_and_iterator =
491         ParseImmediate(osi, ose);
492     if (offset_and_iterator.first.IsValid()) {
493       osi = offset_and_iterator.second;
494     }
495 
496     bool found = false;
497     std::tie(found, osi) = ConsumeChar(osi, '(', ose);
498     if (!found) {
499       return std::make_pair(Operand(), osi);
500     }
501 
502     std::pair<Operand, llvm::StringRef::const_iterator> base_and_iterator =
503         ParseRegisterName(osi, ose);
504     if (base_and_iterator.first.IsValid()) {
505       osi = base_and_iterator.second;
506     } else {
507       return std::make_pair(Operand(), osi);
508     }
509 
510     std::tie(found, osi) = ConsumeChar(osi, ',', ose);
511     if (!found) {
512       return std::make_pair(Operand(), osi);
513     }
514 
515     std::pair<Operand, llvm::StringRef::const_iterator> index_and_iterator =
516         ParseRegisterName(osi, ose);
517     if (index_and_iterator.first.IsValid()) {
518       osi = index_and_iterator.second;
519     } else {
520       return std::make_pair(Operand(), osi);
521     }
522 
523     std::tie(found, osi) = ConsumeChar(osi, ',', ose);
524     if (!found) {
525       return std::make_pair(Operand(), osi);
526     }
527 
528     std::pair<Operand, llvm::StringRef::const_iterator>
529         multiplier_and_iterator = ParseImmediate(osi, ose);
530     if (index_and_iterator.first.IsValid()) {
531       osi = index_and_iterator.second;
532     } else {
533       return std::make_pair(Operand(), osi);
534     }
535 
536     std::tie(found, osi) = ConsumeChar(osi, ')', ose);
537     if (!found) {
538       return std::make_pair(Operand(), osi);
539     }
540 
541     Operand product;
542     product.m_type = Operand::Type::Product;
543     product.m_children.push_back(index_and_iterator.first);
544     product.m_children.push_back(multiplier_and_iterator.first);
545 
546     Operand index;
547     index.m_type = Operand::Type::Sum;
548     index.m_children.push_back(base_and_iterator.first);
549     index.m_children.push_back(product);
550 
551     if (offset_and_iterator.first.IsValid()) {
552       Operand offset;
553       offset.m_type = Operand::Type::Sum;
554       offset.m_children.push_back(offset_and_iterator.first);
555       offset.m_children.push_back(index);
556 
557       Operand deref;
558       deref.m_type = Operand::Type::Dereference;
559       deref.m_children.push_back(offset);
560       return std::make_pair(deref, osi);
561     } else {
562       Operand deref;
563       deref.m_type = Operand::Type::Dereference;
564       deref.m_children.push_back(index);
565       return std::make_pair(deref, osi);
566     }
567   }
568 
569   // -0x10(%rbp)
570   static std::pair<Operand, llvm::StringRef::const_iterator>
571   ParseIntelDerefAccess(llvm::StringRef::const_iterator osi,
572                         llvm::StringRef::const_iterator ose) {
573     std::pair<Operand, llvm::StringRef::const_iterator> offset_and_iterator =
574         ParseImmediate(osi, ose);
575     if (offset_and_iterator.first.IsValid()) {
576       osi = offset_and_iterator.second;
577     }
578 
579     bool found = false;
580     std::tie(found, osi) = ConsumeChar(osi, '(', ose);
581     if (!found) {
582       return std::make_pair(Operand(), osi);
583     }
584 
585     std::pair<Operand, llvm::StringRef::const_iterator> base_and_iterator =
586         ParseRegisterName(osi, ose);
587     if (base_and_iterator.first.IsValid()) {
588       osi = base_and_iterator.second;
589     } else {
590       return std::make_pair(Operand(), osi);
591     }
592 
593     std::tie(found, osi) = ConsumeChar(osi, ')', ose);
594     if (!found) {
595       return std::make_pair(Operand(), osi);
596     }
597 
598     if (offset_and_iterator.first.IsValid()) {
599       Operand offset;
600       offset.m_type = Operand::Type::Sum;
601       offset.m_children.push_back(offset_and_iterator.first);
602       offset.m_children.push_back(base_and_iterator.first);
603 
604       Operand deref;
605       deref.m_type = Operand::Type::Dereference;
606       deref.m_children.push_back(offset);
607       return std::make_pair(deref, osi);
608     } else {
609       Operand deref;
610       deref.m_type = Operand::Type::Dereference;
611       deref.m_children.push_back(base_and_iterator.first);
612       return std::make_pair(deref, osi);
613     }
614   }
615 
616   // [sp, #8]!
617   static std::pair<Operand, llvm::StringRef::const_iterator>
618   ParseARMOffsetAccess(llvm::StringRef::const_iterator osi,
619                        llvm::StringRef::const_iterator ose) {
620     bool found = false;
621     std::tie(found, osi) = ConsumeChar(osi, '[', ose);
622     if (!found) {
623       return std::make_pair(Operand(), osi);
624     }
625 
626     std::pair<Operand, llvm::StringRef::const_iterator> base_and_iterator =
627         ParseRegisterName(osi, ose);
628     if (base_and_iterator.first.IsValid()) {
629       osi = base_and_iterator.second;
630     } else {
631       return std::make_pair(Operand(), osi);
632     }
633 
634     std::tie(found, osi) = ConsumeChar(osi, ',', ose);
635     if (!found) {
636       return std::make_pair(Operand(), osi);
637     }
638 
639     std::pair<Operand, llvm::StringRef::const_iterator> offset_and_iterator =
640         ParseImmediate(osi, ose);
641     if (offset_and_iterator.first.IsValid()) {
642       osi = offset_and_iterator.second;
643     }
644 
645     std::tie(found, osi) = ConsumeChar(osi, ']', ose);
646     if (!found) {
647       return std::make_pair(Operand(), osi);
648     }
649 
650     Operand offset;
651     offset.m_type = Operand::Type::Sum;
652     offset.m_children.push_back(offset_and_iterator.first);
653     offset.m_children.push_back(base_and_iterator.first);
654 
655     Operand deref;
656     deref.m_type = Operand::Type::Dereference;
657     deref.m_children.push_back(offset);
658     return std::make_pair(deref, osi);
659   }
660 
661   // [sp]
662   static std::pair<Operand, llvm::StringRef::const_iterator>
663   ParseARMDerefAccess(llvm::StringRef::const_iterator osi,
664                       llvm::StringRef::const_iterator ose) {
665     bool found = false;
666     std::tie(found, osi) = ConsumeChar(osi, '[', ose);
667     if (!found) {
668       return std::make_pair(Operand(), osi);
669     }
670 
671     std::pair<Operand, llvm::StringRef::const_iterator> base_and_iterator =
672         ParseRegisterName(osi, ose);
673     if (base_and_iterator.first.IsValid()) {
674       osi = base_and_iterator.second;
675     } else {
676       return std::make_pair(Operand(), osi);
677     }
678 
679     std::tie(found, osi) = ConsumeChar(osi, ']', ose);
680     if (!found) {
681       return std::make_pair(Operand(), osi);
682     }
683 
684     Operand deref;
685     deref.m_type = Operand::Type::Dereference;
686     deref.m_children.push_back(base_and_iterator.first);
687     return std::make_pair(deref, osi);
688   }
689 
690   static void DumpOperand(const Operand &op, Stream &s) {
691     switch (op.m_type) {
692     case Operand::Type::Dereference:
693       s.PutCString("*");
694       DumpOperand(op.m_children[0], s);
695       break;
696     case Operand::Type::Immediate:
697       if (op.m_negative) {
698         s.PutCString("-");
699       }
700       s.PutCString(llvm::to_string(op.m_immediate));
701       break;
702     case Operand::Type::Invalid:
703       s.PutCString("Invalid");
704       break;
705     case Operand::Type::Product:
706       s.PutCString("(");
707       DumpOperand(op.m_children[0], s);
708       s.PutCString("*");
709       DumpOperand(op.m_children[1], s);
710       s.PutCString(")");
711       break;
712     case Operand::Type::Register:
713       s.PutCString(op.m_register.GetStringRef());
714       break;
715     case Operand::Type::Sum:
716       s.PutCString("(");
717       DumpOperand(op.m_children[0], s);
718       s.PutCString("+");
719       DumpOperand(op.m_children[1], s);
720       s.PutCString(")");
721       break;
722     }
723   }
724 
725   bool ParseOperands(
726       llvm::SmallVectorImpl<Instruction::Operand> &operands) override {
727     const char *operands_string = GetOperands(nullptr);
728 
729     if (!operands_string) {
730       return false;
731     }
732 
733     llvm::StringRef operands_ref(operands_string);
734 
735     llvm::StringRef::const_iterator osi = operands_ref.begin();
736     llvm::StringRef::const_iterator ose = operands_ref.end();
737 
738     while (osi != ose) {
739       Operand operand;
740       llvm::StringRef::const_iterator iter;
741 
742       if ((std::tie(operand, iter) = ParseIntelIndexedAccess(osi, ose),
743            operand.IsValid()) ||
744           (std::tie(operand, iter) = ParseIntelDerefAccess(osi, ose),
745            operand.IsValid()) ||
746           (std::tie(operand, iter) = ParseARMOffsetAccess(osi, ose),
747            operand.IsValid()) ||
748           (std::tie(operand, iter) = ParseARMDerefAccess(osi, ose),
749            operand.IsValid()) ||
750           (std::tie(operand, iter) = ParseRegisterName(osi, ose),
751            operand.IsValid()) ||
752           (std::tie(operand, iter) = ParseImmediate(osi, ose),
753            operand.IsValid())) {
754         osi = iter;
755         operands.push_back(operand);
756       } else {
757         return false;
758       }
759 
760       std::pair<bool, llvm::StringRef::const_iterator> found_and_iter =
761           ConsumeChar(osi, ',', ose);
762       if (found_and_iter.first) {
763         osi = found_and_iter.second;
764       }
765 
766       osi = ConsumeWhitespace(osi, ose);
767     }
768 
769     DisassemblerSP disasm_sp = m_disasm_wp.lock();
770 
771     if (disasm_sp && operands.size() > 1) {
772       // TODO tie this into the MC Disassembler's notion of clobbers.
773       switch (disasm_sp->GetArchitecture().GetMachine()) {
774       default:
775         break;
776       case llvm::Triple::x86:
777       case llvm::Triple::x86_64:
778         operands[operands.size() - 1].m_clobbered = true;
779         break;
780       case llvm::Triple::arm:
781         operands[0].m_clobbered = true;
782         break;
783       }
784     }
785 
786     if (Log *log =
787             lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS)) {
788       StreamString ss;
789 
790       ss.Printf("[%s] expands to %zu operands:\n", operands_string,
791                 operands.size());
792       for (const Operand &operand : operands) {
793         ss.PutCString("  ");
794         DumpOperand(operand, ss);
795         ss.PutCString("\n");
796       }
797 
798       log->PutString(ss.GetString());
799     }
800 
801     return true;
802   }
803 
804   bool IsCall() override {
805     VisitInstruction();
806     return m_is_call;
807   }
808 
809 protected:
810   std::weak_ptr<DisassemblerLLVMC> m_disasm_wp;
811 
812   bool m_is_valid = false;
813   bool m_using_file_addr;
814   bool m_has_visited_instruction = false;
815 
816   // Be conservative. If we didn't understand the instruction, say it:
817   //   - Might branch
818   //   - Does not have a delay slot
819   //   - Is not a call
820   bool m_does_branch = true;
821   bool m_has_delay_slot = false;
822   bool m_is_call = false;
823 
824   void VisitInstruction() {
825     if (m_has_visited_instruction)
826       return;
827 
828     DisassemblerScope disasm(*this);
829     if (!disasm)
830       return;
831 
832     DataExtractor data;
833     if (!m_opcode.GetData(data))
834       return;
835 
836     bool is_alternate_isa;
837     lldb::addr_t pc = m_address.GetFileAddress();
838     DisassemblerLLVMC::MCDisasmInstance *mc_disasm_ptr =
839         GetDisasmToUse(is_alternate_isa, disasm);
840     const uint8_t *opcode_data = data.GetDataStart();
841     const size_t opcode_data_len = data.GetByteSize();
842     llvm::MCInst inst;
843     const size_t inst_size =
844         mc_disasm_ptr->GetMCInst(opcode_data, opcode_data_len, pc, inst);
845     if (inst_size == 0)
846       return;
847 
848     m_has_visited_instruction = true;
849     m_does_branch = mc_disasm_ptr->CanBranch(inst);
850     m_has_delay_slot = mc_disasm_ptr->HasDelaySlot(inst);
851     m_is_call = mc_disasm_ptr->IsCall(inst);
852   }
853 
854 private:
855   DisassemblerLLVMC::MCDisasmInstance *
856   GetDisasmToUse(bool &is_alternate_isa, DisassemblerScope &disasm) {
857     is_alternate_isa = false;
858     if (disasm) {
859       if (disasm->m_alternate_disasm_up) {
860         const AddressClass address_class = GetAddressClass();
861 
862         if (address_class == AddressClass::eCodeAlternateISA) {
863           is_alternate_isa = true;
864           return disasm->m_alternate_disasm_up.get();
865         }
866       }
867       return disasm->m_disasm_up.get();
868     }
869     return nullptr;
870   }
871 };
872 
873 std::unique_ptr<DisassemblerLLVMC::MCDisasmInstance>
874 DisassemblerLLVMC::MCDisasmInstance::Create(const char *triple, const char *cpu,
875                                             const char *features_str,
876                                             unsigned flavor,
877                                             DisassemblerLLVMC &owner) {
878   using Instance = std::unique_ptr<DisassemblerLLVMC::MCDisasmInstance>;
879 
880   std::string Status;
881   const llvm::Target *curr_target =
882       llvm::TargetRegistry::lookupTarget(triple, Status);
883   if (!curr_target)
884     return Instance();
885 
886   std::unique_ptr<llvm::MCInstrInfo> instr_info_up(
887       curr_target->createMCInstrInfo());
888   if (!instr_info_up)
889     return Instance();
890 
891   std::unique_ptr<llvm::MCRegisterInfo> reg_info_up(
892       curr_target->createMCRegInfo(triple));
893   if (!reg_info_up)
894     return Instance();
895 
896   std::unique_ptr<llvm::MCSubtargetInfo> subtarget_info_up(
897       curr_target->createMCSubtargetInfo(triple, cpu, features_str));
898   if (!subtarget_info_up)
899     return Instance();
900 
901   llvm::MCTargetOptions MCOptions;
902   std::unique_ptr<llvm::MCAsmInfo> asm_info_up(
903       curr_target->createMCAsmInfo(*reg_info_up, triple, MCOptions));
904   if (!asm_info_up)
905     return Instance();
906 
907   std::unique_ptr<llvm::MCContext> context_up(
908       new llvm::MCContext(asm_info_up.get(), reg_info_up.get(), nullptr));
909   if (!context_up)
910     return Instance();
911 
912   std::unique_ptr<llvm::MCDisassembler> disasm_up(
913       curr_target->createMCDisassembler(*subtarget_info_up, *context_up));
914   if (!disasm_up)
915     return Instance();
916 
917   std::unique_ptr<llvm::MCRelocationInfo> rel_info_up(
918       curr_target->createMCRelocationInfo(triple, *context_up));
919   if (!rel_info_up)
920     return Instance();
921 
922   std::unique_ptr<llvm::MCSymbolizer> symbolizer_up(
923       curr_target->createMCSymbolizer(
924           triple, nullptr, DisassemblerLLVMC::SymbolLookupCallback, &owner,
925           context_up.get(), std::move(rel_info_up)));
926   disasm_up->setSymbolizer(std::move(symbolizer_up));
927 
928   unsigned asm_printer_variant =
929       flavor == ~0U ? asm_info_up->getAssemblerDialect() : flavor;
930 
931   std::unique_ptr<llvm::MCInstPrinter> instr_printer_up(
932       curr_target->createMCInstPrinter(llvm::Triple{triple},
933                                        asm_printer_variant, *asm_info_up,
934                                        *instr_info_up, *reg_info_up));
935   if (!instr_printer_up)
936     return Instance();
937 
938   return Instance(
939       new MCDisasmInstance(std::move(instr_info_up), std::move(reg_info_up),
940                            std::move(subtarget_info_up), std::move(asm_info_up),
941                            std::move(context_up), std::move(disasm_up),
942                            std::move(instr_printer_up)));
943 }
944 
945 DisassemblerLLVMC::MCDisasmInstance::MCDisasmInstance(
946     std::unique_ptr<llvm::MCInstrInfo> &&instr_info_up,
947     std::unique_ptr<llvm::MCRegisterInfo> &&reg_info_up,
948     std::unique_ptr<llvm::MCSubtargetInfo> &&subtarget_info_up,
949     std::unique_ptr<llvm::MCAsmInfo> &&asm_info_up,
950     std::unique_ptr<llvm::MCContext> &&context_up,
951     std::unique_ptr<llvm::MCDisassembler> &&disasm_up,
952     std::unique_ptr<llvm::MCInstPrinter> &&instr_printer_up)
953     : m_instr_info_up(std::move(instr_info_up)),
954       m_reg_info_up(std::move(reg_info_up)),
955       m_subtarget_info_up(std::move(subtarget_info_up)),
956       m_asm_info_up(std::move(asm_info_up)),
957       m_context_up(std::move(context_up)), m_disasm_up(std::move(disasm_up)),
958       m_instr_printer_up(std::move(instr_printer_up)) {
959   assert(m_instr_info_up && m_reg_info_up && m_subtarget_info_up &&
960          m_asm_info_up && m_context_up && m_disasm_up && m_instr_printer_up);
961 }
962 
963 uint64_t DisassemblerLLVMC::MCDisasmInstance::GetMCInst(
964     const uint8_t *opcode_data, size_t opcode_data_len, lldb::addr_t pc,
965     llvm::MCInst &mc_inst) const {
966   llvm::ArrayRef<uint8_t> data(opcode_data, opcode_data_len);
967   llvm::MCDisassembler::DecodeStatus status;
968 
969   uint64_t new_inst_size;
970   status = m_disasm_up->getInstruction(mc_inst, new_inst_size, data, pc,
971                                        llvm::nulls());
972   if (status == llvm::MCDisassembler::Success)
973     return new_inst_size;
974   else
975     return 0;
976 }
977 
978 void DisassemblerLLVMC::MCDisasmInstance::PrintMCInst(
979     llvm::MCInst &mc_inst, std::string &inst_string,
980     std::string &comments_string) {
981   llvm::raw_string_ostream inst_stream(inst_string);
982   llvm::raw_string_ostream comments_stream(comments_string);
983 
984   m_instr_printer_up->setCommentStream(comments_stream);
985   m_instr_printer_up->printInst(&mc_inst, 0, llvm::StringRef(),
986                                 *m_subtarget_info_up, inst_stream);
987   m_instr_printer_up->setCommentStream(llvm::nulls());
988   comments_stream.flush();
989 
990   static std::string g_newlines("\r\n");
991 
992   for (size_t newline_pos = 0;
993        (newline_pos = comments_string.find_first_of(g_newlines, newline_pos)) !=
994        comments_string.npos;
995        /**/) {
996     comments_string.replace(comments_string.begin() + newline_pos,
997                             comments_string.begin() + newline_pos + 1, 1, ' ');
998   }
999 }
1000 
1001 void DisassemblerLLVMC::MCDisasmInstance::SetStyle(
1002     bool use_hex_immed, HexImmediateStyle hex_style) {
1003   m_instr_printer_up->setPrintImmHex(use_hex_immed);
1004   switch (hex_style) {
1005   case eHexStyleC:
1006     m_instr_printer_up->setPrintHexStyle(llvm::HexStyle::C);
1007     break;
1008   case eHexStyleAsm:
1009     m_instr_printer_up->setPrintHexStyle(llvm::HexStyle::Asm);
1010     break;
1011   }
1012 }
1013 
1014 bool DisassemblerLLVMC::MCDisasmInstance::CanBranch(
1015     llvm::MCInst &mc_inst) const {
1016   return m_instr_info_up->get(mc_inst.getOpcode())
1017       .mayAffectControlFlow(mc_inst, *m_reg_info_up);
1018 }
1019 
1020 bool DisassemblerLLVMC::MCDisasmInstance::HasDelaySlot(
1021     llvm::MCInst &mc_inst) const {
1022   return m_instr_info_up->get(mc_inst.getOpcode()).hasDelaySlot();
1023 }
1024 
1025 bool DisassemblerLLVMC::MCDisasmInstance::IsCall(llvm::MCInst &mc_inst) const {
1026   return m_instr_info_up->get(mc_inst.getOpcode()).isCall();
1027 }
1028 
1029 DisassemblerLLVMC::DisassemblerLLVMC(const ArchSpec &arch,
1030                                      const char *flavor_string)
1031     : Disassembler(arch, flavor_string), m_exe_ctx(nullptr), m_inst(nullptr),
1032       m_data_from_file(false) {
1033   if (!FlavorValidForArchSpec(arch, m_flavor.c_str())) {
1034     m_flavor.assign("default");
1035   }
1036 
1037   unsigned flavor = ~0U;
1038   llvm::Triple triple = arch.GetTriple();
1039 
1040   // So far the only supported flavor is "intel" on x86.  The base class will
1041   // set this correctly coming in.
1042   if (triple.getArch() == llvm::Triple::x86 ||
1043       triple.getArch() == llvm::Triple::x86_64) {
1044     if (m_flavor == "intel") {
1045       flavor = 1;
1046     } else if (m_flavor == "att") {
1047       flavor = 0;
1048     }
1049   }
1050 
1051   ArchSpec thumb_arch(arch);
1052   if (triple.getArch() == llvm::Triple::arm) {
1053     std::string thumb_arch_name(thumb_arch.GetTriple().getArchName().str());
1054     // Replace "arm" with "thumb" so we get all thumb variants correct
1055     if (thumb_arch_name.size() > 3) {
1056       thumb_arch_name.erase(0, 3);
1057       thumb_arch_name.insert(0, "thumb");
1058     } else {
1059       thumb_arch_name = "thumbv8.2a";
1060     }
1061     thumb_arch.GetTriple().setArchName(llvm::StringRef(thumb_arch_name));
1062   }
1063 
1064   // If no sub architecture specified then use the most recent arm architecture
1065   // so the disassembler will return all instruction. Without it we will see a
1066   // lot of unknow opcode in case the code uses instructions which are not
1067   // available in the oldest arm version (used when no sub architecture is
1068   // specified)
1069   if (triple.getArch() == llvm::Triple::arm &&
1070       triple.getSubArch() == llvm::Triple::NoSubArch)
1071     triple.setArchName("armv8.2a");
1072 
1073   std::string features_str = "";
1074   const char *triple_str = triple.getTriple().c_str();
1075 
1076   // ARM Cortex M0-M7 devices only execute thumb instructions
1077   if (arch.IsAlwaysThumbInstructions()) {
1078     triple_str = thumb_arch.GetTriple().getTriple().c_str();
1079     features_str += "+fp-armv8,";
1080   }
1081 
1082   const char *cpu = "";
1083 
1084   switch (arch.GetCore()) {
1085   case ArchSpec::eCore_mips32:
1086   case ArchSpec::eCore_mips32el:
1087     cpu = "mips32";
1088     break;
1089   case ArchSpec::eCore_mips32r2:
1090   case ArchSpec::eCore_mips32r2el:
1091     cpu = "mips32r2";
1092     break;
1093   case ArchSpec::eCore_mips32r3:
1094   case ArchSpec::eCore_mips32r3el:
1095     cpu = "mips32r3";
1096     break;
1097   case ArchSpec::eCore_mips32r5:
1098   case ArchSpec::eCore_mips32r5el:
1099     cpu = "mips32r5";
1100     break;
1101   case ArchSpec::eCore_mips32r6:
1102   case ArchSpec::eCore_mips32r6el:
1103     cpu = "mips32r6";
1104     break;
1105   case ArchSpec::eCore_mips64:
1106   case ArchSpec::eCore_mips64el:
1107     cpu = "mips64";
1108     break;
1109   case ArchSpec::eCore_mips64r2:
1110   case ArchSpec::eCore_mips64r2el:
1111     cpu = "mips64r2";
1112     break;
1113   case ArchSpec::eCore_mips64r3:
1114   case ArchSpec::eCore_mips64r3el:
1115     cpu = "mips64r3";
1116     break;
1117   case ArchSpec::eCore_mips64r5:
1118   case ArchSpec::eCore_mips64r5el:
1119     cpu = "mips64r5";
1120     break;
1121   case ArchSpec::eCore_mips64r6:
1122   case ArchSpec::eCore_mips64r6el:
1123     cpu = "mips64r6";
1124     break;
1125   default:
1126     cpu = "";
1127     break;
1128   }
1129 
1130   if (arch.IsMIPS()) {
1131     uint32_t arch_flags = arch.GetFlags();
1132     if (arch_flags & ArchSpec::eMIPSAse_msa)
1133       features_str += "+msa,";
1134     if (arch_flags & ArchSpec::eMIPSAse_dsp)
1135       features_str += "+dsp,";
1136     if (arch_flags & ArchSpec::eMIPSAse_dspr2)
1137       features_str += "+dspr2,";
1138   }
1139 
1140   // If any AArch64 variant, enable the ARMv8.5 ISA with SVE extensions so we
1141   // can disassemble newer instructions.
1142   if (triple.getArch() == llvm::Triple::aarch64 ||
1143       triple.getArch() == llvm::Triple::aarch64_32)
1144     features_str += "+v8.5a,+sve2";
1145 
1146   if ((triple.getArch() == llvm::Triple::aarch64 ||
1147        triple.getArch() == llvm::Triple::aarch64_32)
1148       && triple.getVendor() == llvm::Triple::Apple) {
1149     cpu = "apple-latest";
1150   }
1151 
1152   // We use m_disasm_up.get() to tell whether we are valid or not, so if this
1153   // isn't good for some reason, we won't be valid and FindPlugin will fail and
1154   // we won't get used.
1155   m_disasm_up = MCDisasmInstance::Create(triple_str, cpu, features_str.c_str(),
1156                                          flavor, *this);
1157 
1158   llvm::Triple::ArchType llvm_arch = triple.getArch();
1159 
1160   // For arm CPUs that can execute arm or thumb instructions, also create a
1161   // thumb instruction disassembler.
1162   if (llvm_arch == llvm::Triple::arm) {
1163     std::string thumb_triple(thumb_arch.GetTriple().getTriple());
1164     m_alternate_disasm_up =
1165         MCDisasmInstance::Create(thumb_triple.c_str(), "", features_str.c_str(),
1166                                  flavor, *this);
1167     if (!m_alternate_disasm_up)
1168       m_disasm_up.reset();
1169 
1170   } else if (arch.IsMIPS()) {
1171     /* Create alternate disassembler for MIPS16 and microMIPS */
1172     uint32_t arch_flags = arch.GetFlags();
1173     if (arch_flags & ArchSpec::eMIPSAse_mips16)
1174       features_str += "+mips16,";
1175     else if (arch_flags & ArchSpec::eMIPSAse_micromips)
1176       features_str += "+micromips,";
1177 
1178     m_alternate_disasm_up = MCDisasmInstance::Create(
1179         triple_str, cpu, features_str.c_str(), flavor, *this);
1180     if (!m_alternate_disasm_up)
1181       m_disasm_up.reset();
1182   }
1183 }
1184 
1185 DisassemblerLLVMC::~DisassemblerLLVMC() = default;
1186 
1187 Disassembler *DisassemblerLLVMC::CreateInstance(const ArchSpec &arch,
1188                                                 const char *flavor) {
1189   if (arch.GetTriple().getArch() != llvm::Triple::UnknownArch) {
1190     std::unique_ptr<DisassemblerLLVMC> disasm_up(
1191         new DisassemblerLLVMC(arch, flavor));
1192 
1193     if (disasm_up.get() && disasm_up->IsValid())
1194       return disasm_up.release();
1195   }
1196   return nullptr;
1197 }
1198 
1199 size_t DisassemblerLLVMC::DecodeInstructions(const Address &base_addr,
1200                                              const DataExtractor &data,
1201                                              lldb::offset_t data_offset,
1202                                              size_t num_instructions,
1203                                              bool append, bool data_from_file) {
1204   if (!append)
1205     m_instruction_list.Clear();
1206 
1207   if (!IsValid())
1208     return 0;
1209 
1210   m_data_from_file = data_from_file;
1211   uint32_t data_cursor = data_offset;
1212   const size_t data_byte_size = data.GetByteSize();
1213   uint32_t instructions_parsed = 0;
1214   Address inst_addr(base_addr);
1215 
1216   while (data_cursor < data_byte_size &&
1217          instructions_parsed < num_instructions) {
1218 
1219     AddressClass address_class = AddressClass::eCode;
1220 
1221     if (m_alternate_disasm_up)
1222       address_class = inst_addr.GetAddressClass();
1223 
1224     InstructionSP inst_sp(
1225         new InstructionLLVMC(*this, inst_addr, address_class));
1226 
1227     if (!inst_sp)
1228       break;
1229 
1230     uint32_t inst_size = inst_sp->Decode(*this, data, data_cursor);
1231 
1232     if (inst_size == 0)
1233       break;
1234 
1235     m_instruction_list.Append(inst_sp);
1236     data_cursor += inst_size;
1237     inst_addr.Slide(inst_size);
1238     instructions_parsed++;
1239   }
1240 
1241   return data_cursor - data_offset;
1242 }
1243 
1244 void DisassemblerLLVMC::Initialize() {
1245   PluginManager::RegisterPlugin(GetPluginNameStatic(),
1246                                 "Disassembler that uses LLVM MC to disassemble "
1247                                 "i386, x86_64, ARM, and ARM64.",
1248                                 CreateInstance);
1249 
1250   llvm::InitializeAllTargetInfos();
1251   llvm::InitializeAllTargetMCs();
1252   llvm::InitializeAllAsmParsers();
1253   llvm::InitializeAllDisassemblers();
1254 }
1255 
1256 void DisassemblerLLVMC::Terminate() {
1257   PluginManager::UnregisterPlugin(CreateInstance);
1258 }
1259 
1260 ConstString DisassemblerLLVMC::GetPluginNameStatic() {
1261   static ConstString g_name("llvm-mc");
1262   return g_name;
1263 }
1264 
1265 int DisassemblerLLVMC::OpInfoCallback(void *disassembler, uint64_t pc,
1266                                       uint64_t offset, uint64_t size,
1267                                       int tag_type, void *tag_bug) {
1268   return static_cast<DisassemblerLLVMC *>(disassembler)
1269       ->OpInfo(pc, offset, size, tag_type, tag_bug);
1270 }
1271 
1272 const char *DisassemblerLLVMC::SymbolLookupCallback(void *disassembler,
1273                                                     uint64_t value,
1274                                                     uint64_t *type, uint64_t pc,
1275                                                     const char **name) {
1276   return static_cast<DisassemblerLLVMC *>(disassembler)
1277       ->SymbolLookup(value, type, pc, name);
1278 }
1279 
1280 bool DisassemblerLLVMC::FlavorValidForArchSpec(
1281     const lldb_private::ArchSpec &arch, const char *flavor) {
1282   llvm::Triple triple = arch.GetTriple();
1283   if (flavor == nullptr || strcmp(flavor, "default") == 0)
1284     return true;
1285 
1286   if (triple.getArch() == llvm::Triple::x86 ||
1287       triple.getArch() == llvm::Triple::x86_64) {
1288     return strcmp(flavor, "intel") == 0 || strcmp(flavor, "att") == 0;
1289   } else
1290     return false;
1291 }
1292 
1293 bool DisassemblerLLVMC::IsValid() const { return m_disasm_up.operator bool(); }
1294 
1295 int DisassemblerLLVMC::OpInfo(uint64_t PC, uint64_t Offset, uint64_t Size,
1296                               int tag_type, void *tag_bug) {
1297   switch (tag_type) {
1298   default:
1299     break;
1300   case 1:
1301     memset(tag_bug, 0, sizeof(::LLVMOpInfo1));
1302     break;
1303   }
1304   return 0;
1305 }
1306 
1307 const char *DisassemblerLLVMC::SymbolLookup(uint64_t value, uint64_t *type_ptr,
1308                                             uint64_t pc, const char **name) {
1309   if (*type_ptr) {
1310     if (m_exe_ctx && m_inst) {
1311       // std::string remove_this_prior_to_checkin;
1312       Target *target = m_exe_ctx ? m_exe_ctx->GetTargetPtr() : nullptr;
1313       Address value_so_addr;
1314       Address pc_so_addr;
1315       if (m_inst->UsingFileAddress()) {
1316         ModuleSP module_sp(m_inst->GetAddress().GetModule());
1317         if (module_sp) {
1318           module_sp->ResolveFileAddress(value, value_so_addr);
1319           module_sp->ResolveFileAddress(pc, pc_so_addr);
1320         }
1321       } else if (target && !target->GetSectionLoadList().IsEmpty()) {
1322         target->GetSectionLoadList().ResolveLoadAddress(value, value_so_addr);
1323         target->GetSectionLoadList().ResolveLoadAddress(pc, pc_so_addr);
1324       }
1325 
1326       SymbolContext sym_ctx;
1327       const SymbolContextItem resolve_scope =
1328           eSymbolContextFunction | eSymbolContextSymbol;
1329       if (pc_so_addr.IsValid() && pc_so_addr.GetModule()) {
1330         pc_so_addr.GetModule()->ResolveSymbolContextForAddress(
1331             pc_so_addr, resolve_scope, sym_ctx);
1332       }
1333 
1334       if (value_so_addr.IsValid() && value_so_addr.GetSection()) {
1335         StreamString ss;
1336 
1337         bool format_omitting_current_func_name = false;
1338         if (sym_ctx.symbol || sym_ctx.function) {
1339           AddressRange range;
1340           if (sym_ctx.GetAddressRange(resolve_scope, 0, false, range) &&
1341               range.GetBaseAddress().IsValid() &&
1342               range.ContainsLoadAddress(value_so_addr, target)) {
1343             format_omitting_current_func_name = true;
1344           }
1345         }
1346 
1347         // If the "value" address (the target address we're symbolicating) is
1348         // inside the same SymbolContext as the current instruction pc
1349         // (pc_so_addr), don't print the full function name - just print it
1350         // with DumpStyleNoFunctionName style, e.g. "<+36>".
1351         if (format_omitting_current_func_name) {
1352           value_so_addr.Dump(&ss, target, Address::DumpStyleNoFunctionName,
1353                              Address::DumpStyleSectionNameOffset);
1354         } else {
1355           value_so_addr.Dump(
1356               &ss, target,
1357               Address::DumpStyleResolvedDescriptionNoFunctionArguments,
1358               Address::DumpStyleSectionNameOffset);
1359         }
1360 
1361         if (!ss.GetString().empty()) {
1362           // If Address::Dump returned a multi-line description, most commonly
1363           // seen when we have multiple levels of inlined functions at an
1364           // address, only show the first line.
1365           std::string str = std::string(ss.GetString());
1366           size_t first_eol_char = str.find_first_of("\r\n");
1367           if (first_eol_char != std::string::npos) {
1368             str.erase(first_eol_char);
1369           }
1370           m_inst->AppendComment(str);
1371         }
1372       }
1373     }
1374   }
1375 
1376   *type_ptr = LLVMDisassembler_ReferenceType_InOut_None;
1377   *name = nullptr;
1378   return nullptr;
1379 }
1380 
1381 // PluginInterface protocol
1382 ConstString DisassemblerLLVMC::GetPluginName() { return GetPluginNameStatic(); }
1383 
1384 uint32_t DisassemblerLLVMC::GetPluginVersion() { return 1; }
1385