diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2016-07-23 20:50:09 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2016-07-23 20:50:09 +0000 |
commit | f3fbd1c0586ff6ec7895991e6c28f61a503c36a8 (patch) | |
tree | 48d008fd3df8c0e73271a4b18474e0aac6dbfe33 /source/Plugins/Disassembler/llvm/DisassemblerLLVMC.cpp | |
parent | 2fc5d2d1dfaf623ce4e24cd8590565902f8c557c (diff) |
Notes
Diffstat (limited to 'source/Plugins/Disassembler/llvm/DisassemblerLLVMC.cpp')
-rw-r--r-- | source/Plugins/Disassembler/llvm/DisassemblerLLVMC.cpp | 542 |
1 files changed, 275 insertions, 267 deletions
diff --git a/source/Plugins/Disassembler/llvm/DisassemblerLLVMC.cpp b/source/Plugins/Disassembler/llvm/DisassemblerLLVMC.cpp index 6d124b689341f..4d24cf1ab6de3 100644 --- a/source/Plugins/Disassembler/llvm/DisassemblerLLVMC.cpp +++ b/source/Plugins/Disassembler/llvm/DisassemblerLLVMC.cpp @@ -11,20 +11,20 @@ // C++ Includes // Project includes #include "llvm-c/Disassembler.h" +#include "llvm/ADT/SmallString.h" #include "llvm/MC/MCAsmInfo.h" #include "llvm/MC/MCContext.h" -#include "llvm/MC/MCDisassembler.h" -#include "llvm/MC/MCExternalSymbolizer.h" +#include "llvm/MC/MCDisassembler/MCDisassembler.h" +#include "llvm/MC/MCDisassembler/MCExternalSymbolizer.h" +#include "llvm/MC/MCDisassembler/MCRelocationInfo.h" #include "llvm/MC/MCInst.h" #include "llvm/MC/MCInstPrinter.h" #include "llvm/MC/MCInstrInfo.h" #include "llvm/MC/MCRegisterInfo.h" -#include "llvm/MC/MCRelocationInfo.h" #include "llvm/MC/MCSubtargetInfo.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/TargetRegistry.h" #include "llvm/Support/TargetSelect.h" -#include "llvm/ADT/SmallString.h" // Other libraries and framework includes #include "DisassemblerLLVMC.h" @@ -53,7 +53,7 @@ public: const lldb_private::Address &address, AddressClass addr_class) : Instruction (address, addr_class), - m_disasm_sp (disasm.shared_from_this()), + m_disasm_wp (std::static_pointer_cast<DisassemblerLLVMC>(disasm.shared_from_this())), m_does_branch (eLazyBoolCalculate), m_has_delay_slot (eLazyBoolCalculate), m_is_valid (false), @@ -68,34 +68,38 @@ public: { if (m_does_branch == eLazyBoolCalculate) { - GetDisassemblerLLVMC().Lock(this, NULL); - DataExtractor data; - if (m_opcode.GetData(data)) + std::shared_ptr<DisassemblerLLVMC> disasm_sp(GetDisassembler()); + if (disasm_sp) { - bool is_alternate_isa; - lldb::addr_t pc = m_address.GetFileAddress(); - - DisassemblerLLVMC::LLVMCDisassembler *mc_disasm_ptr = GetDisasmToUse (is_alternate_isa); - const uint8_t *opcode_data = data.GetDataStart(); - const size_t opcode_data_len = data.GetByteSize(); - llvm::MCInst inst; - const size_t inst_size = mc_disasm_ptr->GetMCInst (opcode_data, - opcode_data_len, - pc, - inst); - // Be conservative, if we didn't understand the instruction, say it might branch... - if (inst_size == 0) - m_does_branch = eLazyBoolYes; - else + disasm_sp->Lock(this, NULL); + DataExtractor data; + if (m_opcode.GetData(data)) { - const bool can_branch = mc_disasm_ptr->CanBranch(inst); - if (can_branch) + bool is_alternate_isa; + lldb::addr_t pc = m_address.GetFileAddress(); + + DisassemblerLLVMC::LLVMCDisassembler *mc_disasm_ptr = GetDisasmToUse (is_alternate_isa); + const uint8_t *opcode_data = data.GetDataStart(); + const size_t opcode_data_len = data.GetByteSize(); + llvm::MCInst inst; + const size_t inst_size = mc_disasm_ptr->GetMCInst (opcode_data, + opcode_data_len, + pc, + inst); + // Be conservative, if we didn't understand the instruction, say it might branch... + if (inst_size == 0) m_does_branch = eLazyBoolYes; else - m_does_branch = eLazyBoolNo; + { + const bool can_branch = mc_disasm_ptr->CanBranch(inst); + if (can_branch) + m_does_branch = eLazyBoolYes; + else + m_does_branch = eLazyBoolNo; + } } + disasm_sp->Unlock(); } - GetDisassemblerLLVMC().Unlock(); } return m_does_branch == eLazyBoolYes; } @@ -105,34 +109,38 @@ public: { if (m_has_delay_slot == eLazyBoolCalculate) { - GetDisassemblerLLVMC().Lock(this, NULL); - DataExtractor data; - if (m_opcode.GetData(data)) + std::shared_ptr<DisassemblerLLVMC> disasm_sp(GetDisassembler()); + if (disasm_sp) { - bool is_alternate_isa; - lldb::addr_t pc = m_address.GetFileAddress(); - - DisassemblerLLVMC::LLVMCDisassembler *mc_disasm_ptr = GetDisasmToUse (is_alternate_isa); - const uint8_t *opcode_data = data.GetDataStart(); - const size_t opcode_data_len = data.GetByteSize(); - llvm::MCInst inst; - const size_t inst_size = mc_disasm_ptr->GetMCInst (opcode_data, - opcode_data_len, - pc, - inst); - // if we didn't understand the instruction, say it doesn't have a delay slot... - if (inst_size == 0) - m_has_delay_slot = eLazyBoolNo; - else + disasm_sp->Lock(this, NULL); + DataExtractor data; + if (m_opcode.GetData(data)) { - const bool has_delay_slot = mc_disasm_ptr->HasDelaySlot(inst); - if (has_delay_slot) - m_has_delay_slot = eLazyBoolYes; - else + bool is_alternate_isa; + lldb::addr_t pc = m_address.GetFileAddress(); + + DisassemblerLLVMC::LLVMCDisassembler *mc_disasm_ptr = GetDisasmToUse (is_alternate_isa); + const uint8_t *opcode_data = data.GetDataStart(); + const size_t opcode_data_len = data.GetByteSize(); + llvm::MCInst inst; + const size_t inst_size = mc_disasm_ptr->GetMCInst (opcode_data, + opcode_data_len, + pc, + inst); + // if we didn't understand the instruction, say it doesn't have a delay slot... + if (inst_size == 0) m_has_delay_slot = eLazyBoolNo; + else + { + const bool has_delay_slot = mc_disasm_ptr->HasDelaySlot(inst); + if (has_delay_slot) + m_has_delay_slot = eLazyBoolYes; + else + m_has_delay_slot = eLazyBoolNo; + } } + disasm_sp->Unlock(); } - GetDisassemblerLLVMC().Unlock(); } return m_has_delay_slot == eLazyBoolYes; } @@ -141,18 +149,22 @@ public: GetDisasmToUse (bool &is_alternate_isa) { is_alternate_isa = false; - DisassemblerLLVMC &llvm_disasm = GetDisassemblerLLVMC(); - if (llvm_disasm.m_alternate_disasm_ap.get() != NULL) + std::shared_ptr<DisassemblerLLVMC> disasm_sp(GetDisassembler()); + if (disasm_sp) { - const AddressClass address_class = GetAddressClass (); - - if (address_class == eAddressClassCodeAlternateISA) + if (disasm_sp->m_alternate_disasm_ap.get() != NULL) { - is_alternate_isa = true; - return llvm_disasm.m_alternate_disasm_ap.get(); + const AddressClass address_class = GetAddressClass (); + + if (address_class == eAddressClassCodeAlternateISA) + { + is_alternate_isa = true; + return disasm_sp->m_alternate_disasm_ap.get(); + } } + return disasm_sp->m_disasm_ap.get(); } - return llvm_disasm.m_disasm_ap.get(); + return nullptr; } size_t @@ -163,101 +175,105 @@ public: // All we have to do is read the opcode which can be easy for some // architectures bool got_op = false; - DisassemblerLLVMC &llvm_disasm = GetDisassemblerLLVMC(); - const ArchSpec &arch = llvm_disasm.GetArchitecture(); - const lldb::ByteOrder byte_order = data.GetByteOrder(); - - const uint32_t min_op_byte_size = arch.GetMinimumOpcodeByteSize(); - const uint32_t max_op_byte_size = arch.GetMaximumOpcodeByteSize(); - if (min_op_byte_size == max_op_byte_size) + std::shared_ptr<DisassemblerLLVMC> disasm_sp(GetDisassembler()); + if (disasm_sp) { - // Fixed size instructions, just read that amount of data. - if (!data.ValidOffsetForDataOfSize(data_offset, min_op_byte_size)) - return false; + const ArchSpec &arch = disasm_sp->GetArchitecture(); + const lldb::ByteOrder byte_order = data.GetByteOrder(); - switch (min_op_byte_size) + const uint32_t min_op_byte_size = arch.GetMinimumOpcodeByteSize(); + const uint32_t max_op_byte_size = arch.GetMaximumOpcodeByteSize(); + if (min_op_byte_size == max_op_byte_size) { - case 1: - m_opcode.SetOpcode8 (data.GetU8 (&data_offset), byte_order); - got_op = true; - break; - - case 2: - m_opcode.SetOpcode16 (data.GetU16 (&data_offset), byte_order); - got_op = true; - break; - - case 4: - m_opcode.SetOpcode32 (data.GetU32 (&data_offset), byte_order); - got_op = true; - break; - - case 8: - m_opcode.SetOpcode64 (data.GetU64 (&data_offset), byte_order); - got_op = true; - break; - - default: - m_opcode.SetOpcodeBytes(data.PeekData(data_offset, min_op_byte_size), min_op_byte_size); - got_op = true; - break; - } - } - if (!got_op) - { - bool is_alternate_isa = false; - DisassemblerLLVMC::LLVMCDisassembler *mc_disasm_ptr = GetDisasmToUse (is_alternate_isa); + // Fixed size instructions, just read that amount of data. + if (!data.ValidOffsetForDataOfSize(data_offset, min_op_byte_size)) + return false; + + switch (min_op_byte_size) + { + case 1: + m_opcode.SetOpcode8 (data.GetU8 (&data_offset), byte_order); + got_op = true; + break; + + case 2: + m_opcode.SetOpcode16 (data.GetU16 (&data_offset), byte_order); + got_op = true; + break; + + case 4: + m_opcode.SetOpcode32 (data.GetU32 (&data_offset), byte_order); + got_op = true; + break; + + case 8: + m_opcode.SetOpcode64 (data.GetU64 (&data_offset), byte_order); + got_op = true; + break; - const llvm::Triple::ArchType machine = arch.GetMachine(); - if (machine == llvm::Triple::arm || machine == llvm::Triple::thumb) + default: + m_opcode.SetOpcodeBytes(data.PeekData(data_offset, min_op_byte_size), min_op_byte_size); + got_op = true; + break; + } + } + if (!got_op) { - if (machine == llvm::Triple::thumb || is_alternate_isa) + bool is_alternate_isa = false; + DisassemblerLLVMC::LLVMCDisassembler *mc_disasm_ptr = GetDisasmToUse (is_alternate_isa); + + const llvm::Triple::ArchType machine = arch.GetMachine(); + if (machine == llvm::Triple::arm || machine == llvm::Triple::thumb) { - uint32_t thumb_opcode = data.GetU16(&data_offset); - if ((thumb_opcode & 0xe000) != 0xe000 || ((thumb_opcode & 0x1800u) == 0)) + if (machine == llvm::Triple::thumb || is_alternate_isa) { - m_opcode.SetOpcode16 (thumb_opcode, byte_order); - m_is_valid = true; + uint32_t thumb_opcode = data.GetU16(&data_offset); + if ((thumb_opcode & 0xe000) != 0xe000 || ((thumb_opcode & 0x1800u) == 0)) + { + m_opcode.SetOpcode16 (thumb_opcode, byte_order); + m_is_valid = true; + } + else + { + thumb_opcode <<= 16; + thumb_opcode |= data.GetU16(&data_offset); + m_opcode.SetOpcode16_2 (thumb_opcode, byte_order); + m_is_valid = true; + } } else { - thumb_opcode <<= 16; - thumb_opcode |= data.GetU16(&data_offset); - m_opcode.SetOpcode16_2 (thumb_opcode, byte_order); + m_opcode.SetOpcode32 (data.GetU32(&data_offset), byte_order); m_is_valid = true; } } else { - m_opcode.SetOpcode32 (data.GetU32(&data_offset), byte_order); - m_is_valid = true; - } - } - else - { - // The opcode isn't evenly sized, so we need to actually use the llvm - // disassembler to parse it and get the size. - uint8_t *opcode_data = const_cast<uint8_t *>(data.PeekData (data_offset, 1)); - const size_t opcode_data_len = data.BytesLeft(data_offset); - const addr_t pc = m_address.GetFileAddress(); - llvm::MCInst inst; - - llvm_disasm.Lock(this, NULL); - const size_t inst_size = mc_disasm_ptr->GetMCInst(opcode_data, - opcode_data_len, - pc, - inst); - llvm_disasm.Unlock(); - if (inst_size == 0) - m_opcode.Clear(); - else - { - m_opcode.SetOpcodeBytes(opcode_data, inst_size); - m_is_valid = true; + // The opcode isn't evenly sized, so we need to actually use the llvm + // disassembler to parse it and get the size. + uint8_t *opcode_data = const_cast<uint8_t *>(data.PeekData (data_offset, 1)); + const size_t opcode_data_len = data.BytesLeft(data_offset); + 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 + { + m_opcode.SetOpcodeBytes(opcode_data, inst_size); + m_is_valid = true; + } } } + return m_opcode.GetByteSize(); } - return m_opcode.GetByteSize(); + return 0; } void @@ -283,146 +299,148 @@ public: std::string out_string; std::string comment_string; - DisassemblerLLVMC &llvm_disasm = GetDisassemblerLLVMC(); - - DisassemblerLLVMC::LLVMCDisassembler *mc_disasm_ptr; + std::shared_ptr<DisassemblerLLVMC> disasm_sp(GetDisassembler()); + if (disasm_sp) + { + DisassemblerLLVMC::LLVMCDisassembler *mc_disasm_ptr; - if (address_class == eAddressClassCodeAlternateISA) - mc_disasm_ptr = llvm_disasm.m_alternate_disasm_ap.get(); - else - mc_disasm_ptr = llvm_disasm.m_disasm_ap.get(); + if (address_class == eAddressClassCodeAlternateISA) + mc_disasm_ptr = disasm_sp->m_alternate_disasm_ap.get(); + else + mc_disasm_ptr = disasm_sp->m_disasm_ap.get(); - lldb::addr_t pc = m_address.GetFileAddress(); - m_using_file_addr = true; + lldb::addr_t pc = m_address.GetFileAddress(); + m_using_file_addr = true; - const bool data_from_file = GetDisassemblerLLVMC().m_data_from_file; - bool use_hex_immediates = true; - Disassembler::HexImmediateStyle hex_style = Disassembler::eHexStyleC; + const bool data_from_file = disasm_sp->m_data_from_file; + bool use_hex_immediates = true; + Disassembler::HexImmediateStyle hex_style = Disassembler::eHexStyleC; - if (exe_ctx) - { - Target *target = exe_ctx->GetTargetPtr(); - if (target) + if (exe_ctx) { - use_hex_immediates = target->GetUseHexImmediates(); - hex_style = target->GetHexImmediateStyle(); - - if (!data_from_file) + Target *target = exe_ctx->GetTargetPtr(); + if (target) { - const lldb::addr_t load_addr = m_address.GetLoadAddress(target); - if (load_addr != LLDB_INVALID_ADDRESS) + use_hex_immediates = target->GetUseHexImmediates(); + hex_style = target->GetHexImmediateStyle(); + + if (!data_from_file) { - pc = load_addr; - m_using_file_addr = false; + const lldb::addr_t load_addr = m_address.GetLoadAddress(target); + if (load_addr != LLDB_INVALID_ADDRESS) + { + pc = load_addr; + m_using_file_addr = false; + } } } } - } - llvm_disasm.Lock(this, exe_ctx); + disasm_sp->Lock(this, exe_ctx); - const uint8_t *opcode_data = data.GetDataStart(); - const size_t opcode_data_len = data.GetByteSize(); - llvm::MCInst inst; - size_t inst_size = mc_disasm_ptr->GetMCInst (opcode_data, - opcode_data_len, - pc, - inst); + const uint8_t *opcode_data = data.GetDataStart(); + const size_t opcode_data_len = data.GetByteSize(); + llvm::MCInst inst; + size_t inst_size = mc_disasm_ptr->GetMCInst (opcode_data, + opcode_data_len, + pc, + inst); - if (inst_size > 0) - { - mc_disasm_ptr->SetStyle(use_hex_immediates, hex_style); - mc_disasm_ptr->PrintMCInst(inst, out_string, comment_string); - - if (!comment_string.empty()) + if (inst_size > 0) { - AppendComment(comment_string); + mc_disasm_ptr->SetStyle(use_hex_immediates, hex_style); + mc_disasm_ptr->PrintMCInst(inst, out_string, comment_string); + + if (!comment_string.empty()) + { + AppendComment(comment_string); + } } - } - llvm_disasm.Unlock(); + disasm_sp->Unlock(); - if (inst_size == 0) - { - m_comment.assign ("unknown opcode"); - inst_size = m_opcode.GetByteSize(); - StreamString mnemonic_strm; - lldb::offset_t offset = 0; - lldb::ByteOrder byte_order = data.GetByteOrder(); - switch (inst_size) + if (inst_size == 0) { - case 1: - { - const uint8_t uval8 = data.GetU8 (&offset); - m_opcode.SetOpcode8 (uval8, byte_order); - m_opcode_name.assign (".byte"); - mnemonic_strm.Printf("0x%2.2x", uval8); - } - break; - case 2: - { - const uint16_t uval16 = data.GetU16(&offset); - m_opcode.SetOpcode16(uval16, byte_order); - m_opcode_name.assign (".short"); - mnemonic_strm.Printf("0x%4.4x", uval16); - } - break; - case 4: - { - const uint32_t uval32 = data.GetU32(&offset); - m_opcode.SetOpcode32(uval32, byte_order); - m_opcode_name.assign (".long"); - mnemonic_strm.Printf("0x%8.8x", uval32); - } - break; - case 8: - { - const uint64_t uval64 = data.GetU64(&offset); - m_opcode.SetOpcode64(uval64, byte_order); - m_opcode_name.assign (".quad"); - mnemonic_strm.Printf("0x%16.16" PRIx64, uval64); - } - break; - default: - if (inst_size == 0) - return; - else - { - const uint8_t *bytes = data.PeekData(offset, inst_size); - if (bytes == NULL) + m_comment.assign ("unknown opcode"); + inst_size = m_opcode.GetByteSize(); + StreamString mnemonic_strm; + lldb::offset_t offset = 0; + lldb::ByteOrder byte_order = data.GetByteOrder(); + switch (inst_size) + { + case 1: + { + const uint8_t uval8 = data.GetU8 (&offset); + m_opcode.SetOpcode8 (uval8, byte_order); + m_opcode_name.assign (".byte"); + mnemonic_strm.Printf("0x%2.2x", uval8); + } + break; + case 2: + { + const uint16_t uval16 = data.GetU16(&offset); + m_opcode.SetOpcode16(uval16, byte_order); + m_opcode_name.assign (".short"); + mnemonic_strm.Printf("0x%4.4x", uval16); + } + break; + case 4: + { + const uint32_t uval32 = data.GetU32(&offset); + m_opcode.SetOpcode32(uval32, byte_order); + m_opcode_name.assign (".long"); + mnemonic_strm.Printf("0x%8.8x", uval32); + } + break; + case 8: + { + const uint64_t uval64 = data.GetU64(&offset); + m_opcode.SetOpcode64(uval64, byte_order); + m_opcode_name.assign (".quad"); + mnemonic_strm.Printf("0x%16.16" PRIx64, uval64); + } + break; + default: + if (inst_size == 0) return; - m_opcode_name.assign (".byte"); - m_opcode.SetOpcodeBytes(bytes, inst_size); - mnemonic_strm.Printf("0x%2.2x", bytes[0]); - for (uint32_t i=1; i<inst_size; ++i) - mnemonic_strm.Printf(" 0x%2.2x", bytes[i]); - } - break; + else + { + const uint8_t *bytes = data.PeekData(offset, inst_size); + if (bytes == NULL) + return; + m_opcode_name.assign (".byte"); + m_opcode.SetOpcodeBytes(bytes, inst_size); + mnemonic_strm.Printf("0x%2.2x", bytes[0]); + for (uint32_t i=1; i<inst_size; ++i) + mnemonic_strm.Printf(" 0x%2.2x", bytes[i]); + } + break; + } + m_mnemonics.swap(mnemonic_strm.GetString()); + return; } - m_mnemonics.swap(mnemonic_strm.GetString()); - return; - } - else - { - if (m_does_branch == eLazyBoolCalculate) + else { - const bool can_branch = mc_disasm_ptr->CanBranch(inst); - if (can_branch) - m_does_branch = eLazyBoolYes; - else - m_does_branch = eLazyBoolNo; + if (m_does_branch == eLazyBoolCalculate) + { + const bool can_branch = mc_disasm_ptr->CanBranch(inst); + if (can_branch) + m_does_branch = eLazyBoolYes; + else + m_does_branch = eLazyBoolNo; + } } - } - static RegularExpression s_regex("[ \t]*([^ ^\t]+)[ \t]*([^ ^\t].*)?"); + static RegularExpression s_regex("[ \t]*([^ ^\t]+)[ \t]*([^ ^\t].*)?"); - RegularExpression::Match matches(3); + RegularExpression::Match matches(3); - if (s_regex.Execute(out_string.c_str(), &matches)) - { - matches.GetMatchAtIndex(out_string.c_str(), 1, m_opcode_name); - matches.GetMatchAtIndex(out_string.c_str(), 2, m_mnemonics); + if (s_regex.Execute(out_string.c_str(), &matches)) + { + matches.GetMatchAtIndex(out_string.c_str(), 1, m_opcode_name); + matches.GetMatchAtIndex(out_string.c_str(), 2, m_mnemonics); + } } } } @@ -444,14 +462,14 @@ public: return m_opcode.GetByteSize(); } - DisassemblerLLVMC & - GetDisassemblerLLVMC () + std::shared_ptr<DisassemblerLLVMC> + GetDisassembler () { - return *(DisassemblerLLVMC *)m_disasm_sp.get(); + return m_disasm_wp.lock(); } protected: - DisassemblerSP m_disasm_sp; // for ownership + std::weak_ptr<DisassemblerLLVMC> m_disasm_wp; LazyBool m_does_branch; LazyBool m_has_delay_slot; bool m_is_valid; @@ -633,7 +651,7 @@ DisassemblerLLVMC::DisassemblerLLVMC (const ArchSpec &arch, const char *flavor_s } else { - thumb_arch_name = "thumbv7"; + thumb_arch_name = "thumbv8.2a"; } thumb_arch.GetTriple().setArchName(llvm::StringRef(thumb_arch_name.c_str())); } @@ -643,22 +661,12 @@ DisassemblerLLVMC::DisassemblerLLVMC (const ArchSpec &arch, const char *flavor_s // in case the code uses instructions which are not available in the oldest arm version // (used when no sub architecture is specified) if (triple.getArch() == llvm::Triple::arm && triple.getSubArch() == llvm::Triple::NoSubArch) - triple.setArchName("armv8.1a"); + triple.setArchName("armv8.2a"); const char *triple_str = triple.getTriple().c_str(); - // v. https://en.wikipedia.org/wiki/ARM_Cortex-M#Silicon_customization - // - // Cortex-M3 devices (e.g. armv7m) can only execute thumb (T2) instructions, - // so hardcode the primary disassembler to thumb mode. Same for Cortex-M4 (armv7em). - // - // Handle the Cortex-M0 (armv6m) the same; the ISA is a subset of the T and T32 - // instructions defined in ARMv7-A. - - if ((triple.getArch() == llvm::Triple::arm || triple.getArch() == llvm::Triple::thumb) - && (arch.GetCore() == ArchSpec::Core::eCore_arm_armv7m - || arch.GetCore() == ArchSpec::Core::eCore_arm_armv7em - || arch.GetCore() == ArchSpec::Core::eCore_arm_armv6m)) + // ARM Cortex M0-M7 devices only execute thumb instructions + if (arch.IsAlwaysThumbInstructions ()) { triple_str = thumb_arch.GetTriple().getTriple().c_str(); } |