diff options
| author | Dimitry Andric <dim@FreeBSD.org> | 2019-01-19 10:06:29 +0000 |
|---|---|---|
| committer | Dimitry Andric <dim@FreeBSD.org> | 2019-01-19 10:06:29 +0000 |
| commit | 94994d372d014ce4c8758b9605d63fae651bd8aa (patch) | |
| tree | 51c0b708bd59f205d6b35cb2a8c24d62f0c33d77 /source/Plugins/Disassembler/llvm/DisassemblerLLVMC.cpp | |
| parent | 39be7ce23363d12ae3e49aeb1fdb2bfeb892e836 (diff) | |
Notes
Diffstat (limited to 'source/Plugins/Disassembler/llvm/DisassemblerLLVMC.cpp')
| -rw-r--r-- | source/Plugins/Disassembler/llvm/DisassemblerLLVMC.cpp | 123 |
1 files changed, 65 insertions, 58 deletions
diff --git a/source/Plugins/Disassembler/llvm/DisassemblerLLVMC.cpp b/source/Plugins/Disassembler/llvm/DisassemblerLLVMC.cpp index 9b381dd3b96c..5df842250591 100644 --- a/source/Plugins/Disassembler/llvm/DisassemblerLLVMC.cpp +++ b/source/Plugins/Disassembler/llvm/DisassemblerLLVMC.cpp @@ -7,12 +7,8 @@ // //===----------------------------------------------------------------------===// -// C Includes -// C++ Includes -// Project includes #include "DisassemblerLLVMC.h" -// Other libraries and framework includes #include "llvm-c/Disassembler.h" #include "llvm/ADT/SmallString.h" #include "llvm/MC/MCAsmInfo.h" @@ -98,16 +94,15 @@ public: bool DoesBranch() override { if (m_does_branch == eLazyBoolCalculate) { - std::shared_ptr<DisassemblerLLVMC> disasm_sp(GetDisassembler()); - if (disasm_sp) { - disasm_sp->Lock(this, NULL); + DisassemblerScope disasm(*this); + if (disasm) { DataExtractor data; if (m_opcode.GetData(data)) { bool is_alternate_isa; lldb::addr_t pc = m_address.GetFileAddress(); DisassemblerLLVMC::MCDisasmInstance *mc_disasm_ptr = - GetDisasmToUse(is_alternate_isa); + GetDisasmToUse(is_alternate_isa, disasm); const uint8_t *opcode_data = data.GetDataStart(); const size_t opcode_data_len = data.GetByteSize(); llvm::MCInst inst; @@ -125,7 +120,6 @@ public: m_does_branch = eLazyBoolNo; } } - disasm_sp->Unlock(); } } return m_does_branch == eLazyBoolYes; @@ -133,16 +127,15 @@ public: bool HasDelaySlot() override { if (m_has_delay_slot == eLazyBoolCalculate) { - std::shared_ptr<DisassemblerLLVMC> disasm_sp(GetDisassembler()); - if (disasm_sp) { - disasm_sp->Lock(this, NULL); + DisassemblerScope disasm(*this); + if (disasm) { DataExtractor data; if (m_opcode.GetData(data)) { bool is_alternate_isa; lldb::addr_t pc = m_address.GetFileAddress(); DisassemblerLLVMC::MCDisasmInstance *mc_disasm_ptr = - GetDisasmToUse(is_alternate_isa); + GetDisasmToUse(is_alternate_isa, disasm); const uint8_t *opcode_data = data.GetDataStart(); const size_t opcode_data_len = data.GetByteSize(); llvm::MCInst inst; @@ -160,27 +153,14 @@ public: m_has_delay_slot = eLazyBoolNo; } } - disasm_sp->Unlock(); } } return m_has_delay_slot == eLazyBoolYes; } DisassemblerLLVMC::MCDisasmInstance *GetDisasmToUse(bool &is_alternate_isa) { - is_alternate_isa = false; - std::shared_ptr<DisassemblerLLVMC> disasm_sp(GetDisassembler()); - if (disasm_sp) { - if (disasm_sp->m_alternate_disasm_up) { - const AddressClass address_class = GetAddressClass(); - - if (address_class == AddressClass::eCodeAlternateISA) { - is_alternate_isa = true; - return disasm_sp->m_alternate_disasm_up.get(); - } - } - return disasm_sp->m_disasm_up.get(); - } - return nullptr; + DisassemblerScope disasm(*this); + return GetDisasmToUse(is_alternate_isa, disasm); } size_t Decode(const lldb_private::Disassembler &disassembler, @@ -189,9 +169,9 @@ public: // All we have to do is read the opcode which can be easy for some // architectures bool got_op = false; - std::shared_ptr<DisassemblerLLVMC> disasm_sp(GetDisassembler()); - if (disasm_sp) { - const ArchSpec &arch = disasm_sp->GetArchitecture(); + DisassemblerScope disasm(*this); + if (disasm) { + const ArchSpec &arch = disasm->GetArchitecture(); const lldb::ByteOrder byte_order = data.GetByteOrder(); const uint32_t min_op_byte_size = arch.GetMinimumOpcodeByteSize(); @@ -232,7 +212,7 @@ public: if (!got_op) { bool is_alternate_isa = false; DisassemblerLLVMC::MCDisasmInstance *mc_disasm_ptr = - GetDisasmToUse(is_alternate_isa); + GetDisasmToUse(is_alternate_isa, disasm); const llvm::Triple::ArchType machine = arch.GetMachine(); if (machine == llvm::Triple::arm || machine == llvm::Triple::thumb) { @@ -261,10 +241,8 @@ public: const addr_t pc = m_address.GetFileAddress(); llvm::MCInst inst; - disasm_sp->Lock(this, NULL); const size_t inst_size = mc_disasm_ptr->GetMCInst(opcode_data, opcode_data_len, pc, inst); - disasm_sp->Unlock(); if (inst_size == 0) m_opcode.Clear(); else { @@ -296,19 +274,19 @@ public: std::string out_string; std::string comment_string; - std::shared_ptr<DisassemblerLLVMC> disasm_sp(GetDisassembler()); - if (disasm_sp) { + DisassemblerScope disasm(*this, exe_ctx); + if (disasm) { DisassemblerLLVMC::MCDisasmInstance *mc_disasm_ptr; if (address_class == AddressClass::eCodeAlternateISA) - mc_disasm_ptr = disasm_sp->m_alternate_disasm_up.get(); + mc_disasm_ptr = disasm->m_alternate_disasm_up.get(); else - mc_disasm_ptr = disasm_sp->m_disasm_up.get(); + mc_disasm_ptr = disasm->m_disasm_up.get(); lldb::addr_t pc = m_address.GetFileAddress(); m_using_file_addr = true; - const bool data_from_file = disasm_sp->m_data_from_file; + const bool data_from_file = disasm->m_data_from_file; bool use_hex_immediates = true; Disassembler::HexImmediateStyle hex_style = Disassembler::eHexStyleC; @@ -328,8 +306,6 @@ public: } } - disasm_sp->Lock(this, exe_ctx); - const uint8_t *opcode_data = data.GetDataStart(); const size_t opcode_data_len = data.GetByteSize(); llvm::MCInst inst; @@ -345,8 +321,6 @@ public: } } - disasm_sp->Unlock(); - if (inst_size == 0) { m_comment.assign("unknown opcode"); inst_size = m_opcode.GetByteSize(); @@ -423,9 +397,27 @@ public: bool UsingFileAddress() const { return m_using_file_addr; } size_t GetByteSize() const { return m_opcode.GetByteSize(); } - std::shared_ptr<DisassemblerLLVMC> GetDisassembler() { - return m_disasm_wp.lock(); - } + /// Grants exclusive access to the disassembler and initializes it with the + /// given InstructionLLVMC and an optional ExecutionContext. + class DisassemblerScope { + std::shared_ptr<DisassemblerLLVMC> m_disasm; + + public: + explicit DisassemblerScope( + InstructionLLVMC &i, + const lldb_private::ExecutionContext *exe_ctx = nullptr) + : m_disasm(i.m_disasm_wp.lock()) { + m_disasm->m_mutex.lock(); + m_disasm->m_inst = &i; + m_disasm->m_exe_ctx = exe_ctx; + } + ~DisassemblerScope() { m_disasm->m_mutex.unlock(); } + + /// Evaluates to true if this scope contains a valid disassembler. + operator bool() const { return static_cast<bool>(m_disasm); } + + std::shared_ptr<DisassemblerLLVMC> operator->() { return m_disasm; } + }; static llvm::StringRef::const_iterator ConsumeWhitespace(llvm::StringRef::const_iterator osi, @@ -876,16 +868,15 @@ public: bool IsCall() override { if (m_is_call == eLazyBoolCalculate) { - std::shared_ptr<DisassemblerLLVMC> disasm_sp(GetDisassembler()); - if (disasm_sp) { - disasm_sp->Lock(this, NULL); + DisassemblerScope disasm(*this); + if (disasm) { DataExtractor data; if (m_opcode.GetData(data)) { bool is_alternate_isa; lldb::addr_t pc = m_address.GetFileAddress(); DisassemblerLLVMC::MCDisasmInstance *mc_disasm_ptr = - GetDisasmToUse(is_alternate_isa); + GetDisasmToUse(is_alternate_isa, disasm); const uint8_t *opcode_data = data.GetDataStart(); const size_t opcode_data_len = data.GetByteSize(); llvm::MCInst inst; @@ -900,7 +891,6 @@ public: m_is_call = eLazyBoolNo; } } - disasm_sp->Unlock(); } } return m_is_call == eLazyBoolYes; @@ -913,6 +903,24 @@ protected: LazyBool m_is_call; bool m_is_valid; bool m_using_file_addr; + +private: + DisassemblerLLVMC::MCDisasmInstance * + GetDisasmToUse(bool &is_alternate_isa, DisassemblerScope &disasm) { + is_alternate_isa = false; + if (disasm) { + if (disasm->m_alternate_disasm_up) { + const AddressClass address_class = GetAddressClass(); + + if (address_class == AddressClass::eCodeAlternateISA) { + is_alternate_isa = true; + return disasm->m_alternate_disasm_up.get(); + } + } + return disasm->m_disasm_up.get(); + } + return nullptr; + } }; std::unique_ptr<DisassemblerLLVMC::MCDisasmInstance> @@ -1114,11 +1122,13 @@ DisassemblerLLVMC::DisassemblerLLVMC(const ArchSpec &arch, triple.getSubArch() == llvm::Triple::NoSubArch) triple.setArchName("armv8.2a"); + std::string features_str = ""; const char *triple_str = triple.getTriple().c_str(); // ARM Cortex M0-M7 devices only execute thumb instructions if (arch.IsAlwaysThumbInstructions()) { triple_str = thumb_arch.GetTriple().getTriple().c_str(); + features_str += "+fp-armv8,"; } const char *cpu = ""; @@ -1169,7 +1179,6 @@ DisassemblerLLVMC::DisassemblerLLVMC(const ArchSpec &arch, break; } - std::string features_str = ""; if (triple.getArch() == llvm::Triple::mips || triple.getArch() == llvm::Triple::mipsel || triple.getArch() == llvm::Triple::mips64 || @@ -1201,7 +1210,8 @@ DisassemblerLLVMC::DisassemblerLLVMC(const ArchSpec &arch, if (llvm_arch == llvm::Triple::arm) { std::string thumb_triple(thumb_arch.GetTriple().getTriple()); m_alternate_disasm_up = - MCDisasmInstance::Create(thumb_triple.c_str(), "", "", flavor, *this); + MCDisasmInstance::Create(thumb_triple.c_str(), "", features_str.c_str(), + flavor, *this); if (!m_alternate_disasm_up) m_disasm_up.reset(); @@ -1326,10 +1336,7 @@ bool DisassemblerLLVMC::FlavorValidForArchSpec( if (triple.getArch() == llvm::Triple::x86 || triple.getArch() == llvm::Triple::x86_64) { - if (strcmp(flavor, "intel") == 0 || strcmp(flavor, "att") == 0) - return true; - else - return false; + return strcmp(flavor, "intel") == 0 || strcmp(flavor, "att") == 0; } else return false; } @@ -1368,7 +1375,7 @@ const char *DisassemblerLLVMC::SymbolLookup(uint64_t value, uint64_t *type_ptr, } SymbolContext sym_ctx; - const uint32_t resolve_scope = + const SymbolContextItem resolve_scope = eSymbolContextFunction | eSymbolContextSymbol; if (pc_so_addr.IsValid() && pc_so_addr.GetModule()) { pc_so_addr.GetModule()->ResolveSymbolContextForAddress( |
