summaryrefslogtreecommitdiff
path: root/source/Plugins/Disassembler/llvm/DisassemblerLLVMC.cpp
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2019-01-19 10:06:29 +0000
committerDimitry Andric <dim@FreeBSD.org>2019-01-19 10:06:29 +0000
commit94994d372d014ce4c8758b9605d63fae651bd8aa (patch)
tree51c0b708bd59f205d6b35cb2a8c24d62f0c33d77 /source/Plugins/Disassembler/llvm/DisassemblerLLVMC.cpp
parent39be7ce23363d12ae3e49aeb1fdb2bfeb892e836 (diff)
Notes
Diffstat (limited to 'source/Plugins/Disassembler/llvm/DisassemblerLLVMC.cpp')
-rw-r--r--source/Plugins/Disassembler/llvm/DisassemblerLLVMC.cpp123
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(