1//===-- DisassemblerLLVMC.h -------------------------------------*- 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#ifndef liblldb_DisassemblerLLVMC_h_
11#define liblldb_DisassemblerLLVMC_h_
12
13#include <string>
14
15#include "llvm-c/Disassembler.h"
16
17// Opaque references to C++ Objects in LLVM's MC.
18namespace llvm
19{
20    class MCContext;
21    class MCInst;
22    class MCInstrInfo;
23    class MCRegisterInfo;
24    class MCDisassembler;
25    class MCInstPrinter;
26    class MCAsmInfo;
27    class MCSubtargetInfo;
28}
29
30#include "lldb/Core/Address.h"
31#include "lldb/Core/Disassembler.h"
32#include "lldb/Core/PluginManager.h"
33#include "lldb/Host/Mutex.h"
34
35class InstructionLLVMC;
36
37class DisassemblerLLVMC : public lldb_private::Disassembler
38{
39    // Since we need to make two actual MC Disassemblers for ARM (ARM & THUMB), and there's a bit of goo to set up and own
40    // in the MC disassembler world, I added this class to manage the actual disassemblers.
41    class LLVMCDisassembler
42    {
43    public:
44        LLVMCDisassembler (const char *triple, unsigned flavor, DisassemblerLLVMC &owner);
45
46        ~LLVMCDisassembler();
47
48        uint64_t GetMCInst (const uint8_t *opcode_data, size_t opcode_data_len, lldb::addr_t pc, llvm::MCInst &mc_inst);
49        uint64_t PrintMCInst (llvm::MCInst &mc_inst, char *output_buffer, size_t out_buffer_len);
50        void     SetStyle (bool use_hex_immed, HexImmediateStyle hex_style);
51        bool     CanBranch (llvm::MCInst &mc_inst);
52        bool     IsValid()
53        {
54            return m_is_valid;
55        }
56
57    private:
58        bool                                     m_is_valid;
59        std::unique_ptr<llvm::MCContext>         m_context_ap;
60        std::unique_ptr<llvm::MCAsmInfo>         m_asm_info_ap;
61        std::unique_ptr<llvm::MCSubtargetInfo>   m_subtarget_info_ap;
62        std::unique_ptr<llvm::MCInstrInfo>       m_instr_info_ap;
63        std::unique_ptr<llvm::MCRegisterInfo>    m_reg_info_ap;
64        std::unique_ptr<llvm::MCInstPrinter>     m_instr_printer_ap;
65        std::unique_ptr<llvm::MCDisassembler>    m_disasm_ap;
66    };
67
68public:
69    //------------------------------------------------------------------
70    // Static Functions
71    //------------------------------------------------------------------
72    static void
73    Initialize();
74
75    static void
76    Terminate();
77
78    static lldb_private::ConstString
79    GetPluginNameStatic();
80
81    static lldb_private::Disassembler *
82    CreateInstance(const lldb_private::ArchSpec &arch, const char *flavor);
83
84    DisassemblerLLVMC(const lldb_private::ArchSpec &arch, const char *flavor /* = NULL */);
85
86    virtual
87    ~DisassemblerLLVMC();
88
89    virtual size_t
90    DecodeInstructions (const lldb_private::Address &base_addr,
91                        const lldb_private::DataExtractor& data,
92                        lldb::offset_t data_offset,
93                        size_t num_instructions,
94                        bool append,
95                        bool data_from_file);
96
97    //------------------------------------------------------------------
98    // PluginInterface protocol
99    //------------------------------------------------------------------
100    virtual lldb_private::ConstString
101    GetPluginName();
102
103    virtual uint32_t
104    GetPluginVersion();
105
106protected:
107    friend class InstructionLLVMC;
108
109    virtual bool
110    FlavorValidForArchSpec (const lldb_private::ArchSpec &arch, const char *flavor);
111
112    bool
113    IsValid()
114    {
115        return (m_disasm_ap.get() != NULL && m_disasm_ap->IsValid());
116    }
117
118    int OpInfo(uint64_t PC,
119               uint64_t Offset,
120               uint64_t Size,
121               int TagType,
122               void *TagBug);
123
124    const char *SymbolLookup (uint64_t ReferenceValue,
125                              uint64_t *ReferenceType,
126                              uint64_t ReferencePC,
127                              const char **ReferenceName);
128
129    static int OpInfoCallback (void *DisInfo,
130                               uint64_t PC,
131                               uint64_t Offset,
132                               uint64_t Size,
133                               int TagType,
134                               void *TagBug);
135
136    static const char *SymbolLookupCallback(void *DisInfo,
137                                            uint64_t ReferenceValue,
138                                            uint64_t *ReferenceType,
139                                            uint64_t ReferencePC,
140                                            const char **ReferenceName);
141
142    void Lock(InstructionLLVMC *inst,
143              const lldb_private::ExecutionContext *exe_ctx)
144    {
145        m_mutex.Lock();
146        m_inst = inst;
147        m_exe_ctx = exe_ctx;
148    }
149
150    void Unlock()
151    {
152        m_inst = NULL;
153        m_exe_ctx = NULL;
154        m_mutex.Unlock();
155    }
156
157    const lldb_private::ExecutionContext *m_exe_ctx;
158    InstructionLLVMC *m_inst;
159    lldb_private::Mutex m_mutex;
160    bool m_data_from_file;
161
162    std::unique_ptr<LLVMCDisassembler> m_disasm_ap;
163    std::unique_ptr<LLVMCDisassembler> m_alternate_disasm_ap;
164};
165
166#endif  // liblldb_DisassemblerLLVM_h_
167