diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2017-01-02 19:26:05 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2017-01-02 19:26:05 +0000 |
commit | 14f1b3e8826ce43b978db93a62d1166055db5394 (patch) | |
tree | 0a00ad8d3498783fe0193f3b656bca17c4c8697d /source/Expression | |
parent | 4ee8c119c71a06dcad1e0fecc8c675e480e59337 (diff) | |
download | src-14f1b3e8826ce43b978db93a62d1166055db5394.tar.gz src-14f1b3e8826ce43b978db93a62d1166055db5394.zip |
Vendor import of lldb trunk r290819:vendor/lldb/lldb-trunk-r290819
Notes
Notes:
svn path=/vendor/lldb/dist/; revision=311128
svn path=/vendor/lldb/lldb-trunk-r290819/; revision=311129; tag=vendor/lldb/lldb-trunk-r290819
Diffstat (limited to 'source/Expression')
-rw-r--r-- | source/Expression/CMakeLists.txt | 7 | ||||
-rw-r--r-- | source/Expression/DWARFExpression.cpp | 6242 | ||||
-rw-r--r-- | source/Expression/DiagnosticManager.cpp | 100 | ||||
-rw-r--r-- | source/Expression/Expression.cpp | 27 | ||||
-rw-r--r-- | source/Expression/ExpressionSourceCode.cpp | 605 | ||||
-rw-r--r-- | source/Expression/ExpressionVariable.cpp | 122 | ||||
-rw-r--r-- | source/Expression/FunctionCaller.cpp | 633 | ||||
-rw-r--r-- | source/Expression/IRDynamicChecks.cpp | 933 | ||||
-rw-r--r-- | source/Expression/IRExecutionUnit.cpp | 2054 | ||||
-rw-r--r-- | source/Expression/IRInterpreter.cpp | 3190 | ||||
-rw-r--r-- | source/Expression/IRMemoryMap.cpp | 1432 | ||||
-rw-r--r-- | source/Expression/LLVMUserExpression.cpp | 571 | ||||
-rw-r--r-- | source/Expression/Materializer.cpp | 2293 | ||||
-rw-r--r-- | source/Expression/REPL.cpp | 1083 | ||||
-rw-r--r-- | source/Expression/UserExpression.cpp | 632 | ||||
-rw-r--r-- | source/Expression/UtilityFunction.cpp | 137 |
16 files changed, 9747 insertions, 10314 deletions
diff --git a/source/Expression/CMakeLists.txt b/source/Expression/CMakeLists.txt index 48e67888e436..f8faa6df0267 100644 --- a/source/Expression/CMakeLists.txt +++ b/source/Expression/CMakeLists.txt @@ -1,3 +1,7 @@ +if(NOT LLDB_BUILT_STANDALONE) + set(tablegen_deps intrinsics_gen) +endif() + add_lldb_library(lldbExpression DiagnosticManager.cpp DWARFExpression.cpp @@ -14,4 +18,7 @@ add_lldb_library(lldbExpression REPL.cpp UserExpression.cpp UtilityFunction.cpp + + DEPENDS + ${tablegen_deps} ) diff --git a/source/Expression/DWARFExpression.cpp b/source/Expression/DWARFExpression.cpp index b81d60e9b065..c8b0b5944e8b 100644 --- a/source/Expression/DWARFExpression.cpp +++ b/source/Expression/DWARFExpression.cpp @@ -16,13 +16,13 @@ #include <vector> #include "lldb/Core/DataEncoder.h" -#include "lldb/Core/dwarf.h" #include "lldb/Core/Log.h" #include "lldb/Core/RegisterValue.h" -#include "lldb/Core/StreamString.h" #include "lldb/Core/Scalar.h" -#include "lldb/Core/Value.h" +#include "lldb/Core/StreamString.h" #include "lldb/Core/VMRange.h" +#include "lldb/Core/Value.h" +#include "lldb/Core/dwarf.h" #include "Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.h" #include "Plugins/ExpressionParser/Clang/ClangExpressionVariable.h" @@ -30,6 +30,8 @@ #include "lldb/Host/Endian.h" #include "lldb/Host/Host.h" +#include "lldb/Symbol/Function.h" + #include "lldb/Target/ABI.h" #include "lldb/Target/ExecutionContext.h" #include "lldb/Target/Process.h" @@ -44,628 +46,670 @@ using namespace lldb; using namespace lldb_private; static lldb::addr_t -ReadAddressFromDebugAddrSection(const DWARFCompileUnit* dwarf_cu, uint32_t index) -{ - uint32_t index_size = dwarf_cu->GetAddressByteSize(); - dw_offset_t addr_base = dwarf_cu->GetAddrBase(); - lldb::offset_t offset = addr_base + index * index_size; - return dwarf_cu->GetSymbolFileDWARF()->get_debug_addr_data().GetMaxU64(&offset, index_size); +ReadAddressFromDebugAddrSection(const DWARFCompileUnit *dwarf_cu, + uint32_t index) { + uint32_t index_size = dwarf_cu->GetAddressByteSize(); + dw_offset_t addr_base = dwarf_cu->GetAddrBase(); + lldb::offset_t offset = addr_base + index * index_size; + return dwarf_cu->GetSymbolFileDWARF()->get_debug_addr_data().GetMaxU64( + &offset, index_size); } //---------------------------------------------------------------------- // DWARFExpression constructor //---------------------------------------------------------------------- -DWARFExpression::DWARFExpression(DWARFCompileUnit* dwarf_cu) : - m_module_wp(), - m_data(), - m_dwarf_cu(dwarf_cu), - m_reg_kind (eRegisterKindDWARF), - m_loclist_slide (LLDB_INVALID_ADDRESS) -{ -} - -DWARFExpression::DWARFExpression(const DWARFExpression& rhs) : - m_module_wp(rhs.m_module_wp), - m_data(rhs.m_data), - m_dwarf_cu(rhs.m_dwarf_cu), - m_reg_kind (rhs.m_reg_kind), - m_loclist_slide(rhs.m_loclist_slide) -{ -} +DWARFExpression::DWARFExpression(DWARFCompileUnit *dwarf_cu) + : m_module_wp(), m_data(), m_dwarf_cu(dwarf_cu), + m_reg_kind(eRegisterKindDWARF), m_loclist_slide(LLDB_INVALID_ADDRESS) {} +DWARFExpression::DWARFExpression(const DWARFExpression &rhs) + : m_module_wp(rhs.m_module_wp), m_data(rhs.m_data), + m_dwarf_cu(rhs.m_dwarf_cu), m_reg_kind(rhs.m_reg_kind), + m_loclist_slide(rhs.m_loclist_slide) {} DWARFExpression::DWARFExpression(lldb::ModuleSP module_sp, - const DataExtractor& data, - DWARFCompileUnit* dwarf_cu, + const DataExtractor &data, + DWARFCompileUnit *dwarf_cu, lldb::offset_t data_offset, - lldb::offset_t data_length) : - m_module_wp(), - m_data(data, data_offset, data_length), - m_dwarf_cu(dwarf_cu), - m_reg_kind (eRegisterKindDWARF), - m_loclist_slide(LLDB_INVALID_ADDRESS) -{ - if (module_sp) - m_module_wp = module_sp; + lldb::offset_t data_length) + : m_module_wp(), m_data(data, data_offset, data_length), + m_dwarf_cu(dwarf_cu), m_reg_kind(eRegisterKindDWARF), + m_loclist_slide(LLDB_INVALID_ADDRESS) { + if (module_sp) + m_module_wp = module_sp; } //---------------------------------------------------------------------- // Destructor //---------------------------------------------------------------------- -DWARFExpression::~DWARFExpression() -{ -} +DWARFExpression::~DWARFExpression() {} +bool DWARFExpression::IsValid() const { return m_data.GetByteSize() > 0; } -bool -DWARFExpression::IsValid() const -{ - return m_data.GetByteSize() > 0; +void DWARFExpression::SetOpcodeData(const DataExtractor &data) { + m_data = data; } -void -DWARFExpression::SetOpcodeData (const DataExtractor& data) -{ - m_data = data; +void DWARFExpression::CopyOpcodeData(lldb::ModuleSP module_sp, + const DataExtractor &data, + lldb::offset_t data_offset, + lldb::offset_t data_length) { + const uint8_t *bytes = data.PeekData(data_offset, data_length); + if (bytes) { + m_module_wp = module_sp; + m_data.SetData(DataBufferSP(new DataBufferHeap(bytes, data_length))); + m_data.SetByteOrder(data.GetByteOrder()); + m_data.SetAddressByteSize(data.GetAddressByteSize()); + } } -void -DWARFExpression::CopyOpcodeData (lldb::ModuleSP module_sp, const DataExtractor& data, lldb::offset_t data_offset, lldb::offset_t data_length) -{ - const uint8_t *bytes = data.PeekData(data_offset, data_length); - if (bytes) - { - m_module_wp = module_sp; - m_data.SetData(DataBufferSP(new DataBufferHeap(bytes, data_length))); - m_data.SetByteOrder(data.GetByteOrder()); - m_data.SetAddressByteSize(data.GetAddressByteSize()); - } +void DWARFExpression::CopyOpcodeData(const void *data, + lldb::offset_t data_length, + ByteOrder byte_order, + uint8_t addr_byte_size) { + if (data && data_length) { + m_data.SetData(DataBufferSP(new DataBufferHeap(data, data_length))); + m_data.SetByteOrder(byte_order); + m_data.SetAddressByteSize(addr_byte_size); + } } -void -DWARFExpression::CopyOpcodeData (const void *data, - lldb::offset_t data_length, - ByteOrder byte_order, - uint8_t addr_byte_size) -{ - if (data && data_length) - { - m_data.SetData(DataBufferSP(new DataBufferHeap(data, data_length))); - m_data.SetByteOrder(byte_order); - m_data.SetAddressByteSize(addr_byte_size); - } +void DWARFExpression::CopyOpcodeData(uint64_t const_value, + lldb::offset_t const_value_byte_size, + uint8_t addr_byte_size) { + if (const_value_byte_size) { + m_data.SetData( + DataBufferSP(new DataBufferHeap(&const_value, const_value_byte_size))); + m_data.SetByteOrder(endian::InlHostByteOrder()); + m_data.SetAddressByteSize(addr_byte_size); + } } -void -DWARFExpression::CopyOpcodeData (uint64_t const_value, - lldb::offset_t const_value_byte_size, - uint8_t addr_byte_size) -{ - if (const_value_byte_size) - { - m_data.SetData(DataBufferSP(new DataBufferHeap(&const_value, const_value_byte_size))); - m_data.SetByteOrder(endian::InlHostByteOrder()); - m_data.SetAddressByteSize(addr_byte_size); - } +void DWARFExpression::SetOpcodeData(lldb::ModuleSP module_sp, + const DataExtractor &data, + lldb::offset_t data_offset, + lldb::offset_t data_length) { + m_module_wp = module_sp; + m_data.SetData(data, data_offset, data_length); } -void -DWARFExpression::SetOpcodeData (lldb::ModuleSP module_sp, const DataExtractor& data, lldb::offset_t data_offset, lldb::offset_t data_length) -{ - m_module_wp = module_sp; - m_data.SetData(data, data_offset, data_length); -} +void DWARFExpression::DumpLocation(Stream *s, lldb::offset_t offset, + lldb::offset_t length, + lldb::DescriptionLevel level, + ABI *abi) const { + if (!m_data.ValidOffsetForDataOfSize(offset, length)) + return; + const lldb::offset_t start_offset = offset; + const lldb::offset_t end_offset = offset + length; + while (m_data.ValidOffset(offset) && offset < end_offset) { + const lldb::offset_t op_offset = offset; + const uint8_t op = m_data.GetU8(&offset); + + switch (level) { + default: + break; + + case lldb::eDescriptionLevelBrief: + if (offset > start_offset) + s->PutChar(' '); + break; + + case lldb::eDescriptionLevelFull: + case lldb::eDescriptionLevelVerbose: + if (offset > start_offset) + s->EOL(); + s->Indent(); + if (level == lldb::eDescriptionLevelFull) + break; + // Fall through for verbose and print offset and DW_OP prefix.. + s->Printf("0x%8.8" PRIx64 ": %s", op_offset, + op >= DW_OP_APPLE_uninit ? "DW_OP_APPLE_" : "DW_OP_"); + break; + } -void -DWARFExpression::DumpLocation (Stream *s, lldb::offset_t offset, lldb::offset_t length, lldb::DescriptionLevel level, ABI *abi) const -{ - if (!m_data.ValidOffsetForDataOfSize(offset, length)) - return; - const lldb::offset_t start_offset = offset; - const lldb::offset_t end_offset = offset + length; - while (m_data.ValidOffset(offset) && offset < end_offset) + switch (op) { + case DW_OP_addr: + *s << "DW_OP_addr(" << m_data.GetAddress(&offset) << ") "; + break; // 0x03 1 address + case DW_OP_deref: + *s << "DW_OP_deref"; + break; // 0x06 + case DW_OP_const1u: + s->Printf("DW_OP_const1u(0x%2.2x) ", m_data.GetU8(&offset)); + break; // 0x08 1 1-byte constant + case DW_OP_const1s: + s->Printf("DW_OP_const1s(0x%2.2x) ", m_data.GetU8(&offset)); + break; // 0x09 1 1-byte constant + case DW_OP_const2u: + s->Printf("DW_OP_const2u(0x%4.4x) ", m_data.GetU16(&offset)); + break; // 0x0a 1 2-byte constant + case DW_OP_const2s: + s->Printf("DW_OP_const2s(0x%4.4x) ", m_data.GetU16(&offset)); + break; // 0x0b 1 2-byte constant + case DW_OP_const4u: + s->Printf("DW_OP_const4u(0x%8.8x) ", m_data.GetU32(&offset)); + break; // 0x0c 1 4-byte constant + case DW_OP_const4s: + s->Printf("DW_OP_const4s(0x%8.8x) ", m_data.GetU32(&offset)); + break; // 0x0d 1 4-byte constant + case DW_OP_const8u: + s->Printf("DW_OP_const8u(0x%16.16" PRIx64 ") ", m_data.GetU64(&offset)); + break; // 0x0e 1 8-byte constant + case DW_OP_const8s: + s->Printf("DW_OP_const8s(0x%16.16" PRIx64 ") ", m_data.GetU64(&offset)); + break; // 0x0f 1 8-byte constant + case DW_OP_constu: + s->Printf("DW_OP_constu(0x%" PRIx64 ") ", m_data.GetULEB128(&offset)); + break; // 0x10 1 ULEB128 constant + case DW_OP_consts: + s->Printf("DW_OP_consts(0x%" PRId64 ") ", m_data.GetSLEB128(&offset)); + break; // 0x11 1 SLEB128 constant + case DW_OP_dup: + s->PutCString("DW_OP_dup"); + break; // 0x12 + case DW_OP_drop: + s->PutCString("DW_OP_drop"); + break; // 0x13 + case DW_OP_over: + s->PutCString("DW_OP_over"); + break; // 0x14 + case DW_OP_pick: + s->Printf("DW_OP_pick(0x%2.2x) ", m_data.GetU8(&offset)); + break; // 0x15 1 1-byte stack index + case DW_OP_swap: + s->PutCString("DW_OP_swap"); + break; // 0x16 + case DW_OP_rot: + s->PutCString("DW_OP_rot"); + break; // 0x17 + case DW_OP_xderef: + s->PutCString("DW_OP_xderef"); + break; // 0x18 + case DW_OP_abs: + s->PutCString("DW_OP_abs"); + break; // 0x19 + case DW_OP_and: + s->PutCString("DW_OP_and"); + break; // 0x1a + case DW_OP_div: + s->PutCString("DW_OP_div"); + break; // 0x1b + case DW_OP_minus: + s->PutCString("DW_OP_minus"); + break; // 0x1c + case DW_OP_mod: + s->PutCString("DW_OP_mod"); + break; // 0x1d + case DW_OP_mul: + s->PutCString("DW_OP_mul"); + break; // 0x1e + case DW_OP_neg: + s->PutCString("DW_OP_neg"); + break; // 0x1f + case DW_OP_not: + s->PutCString("DW_OP_not"); + break; // 0x20 + case DW_OP_or: + s->PutCString("DW_OP_or"); + break; // 0x21 + case DW_OP_plus: + s->PutCString("DW_OP_plus"); + break; // 0x22 + case DW_OP_plus_uconst: // 0x23 1 ULEB128 addend + s->Printf("DW_OP_plus_uconst(0x%" PRIx64 ") ", + m_data.GetULEB128(&offset)); + break; + + case DW_OP_shl: + s->PutCString("DW_OP_shl"); + break; // 0x24 + case DW_OP_shr: + s->PutCString("DW_OP_shr"); + break; // 0x25 + case DW_OP_shra: + s->PutCString("DW_OP_shra"); + break; // 0x26 + case DW_OP_xor: + s->PutCString("DW_OP_xor"); + break; // 0x27 + case DW_OP_skip: + s->Printf("DW_OP_skip(0x%4.4x)", m_data.GetU16(&offset)); + break; // 0x2f 1 signed 2-byte constant + case DW_OP_bra: + s->Printf("DW_OP_bra(0x%4.4x)", m_data.GetU16(&offset)); + break; // 0x28 1 signed 2-byte constant + case DW_OP_eq: + s->PutCString("DW_OP_eq"); + break; // 0x29 + case DW_OP_ge: + s->PutCString("DW_OP_ge"); + break; // 0x2a + case DW_OP_gt: + s->PutCString("DW_OP_gt"); + break; // 0x2b + case DW_OP_le: + s->PutCString("DW_OP_le"); + break; // 0x2c + case DW_OP_lt: + s->PutCString("DW_OP_lt"); + break; // 0x2d + case DW_OP_ne: + s->PutCString("DW_OP_ne"); + break; // 0x2e + + case DW_OP_lit0: // 0x30 + case DW_OP_lit1: // 0x31 + case DW_OP_lit2: // 0x32 + case DW_OP_lit3: // 0x33 + case DW_OP_lit4: // 0x34 + case DW_OP_lit5: // 0x35 + case DW_OP_lit6: // 0x36 + case DW_OP_lit7: // 0x37 + case DW_OP_lit8: // 0x38 + case DW_OP_lit9: // 0x39 + case DW_OP_lit10: // 0x3A + case DW_OP_lit11: // 0x3B + case DW_OP_lit12: // 0x3C + case DW_OP_lit13: // 0x3D + case DW_OP_lit14: // 0x3E + case DW_OP_lit15: // 0x3F + case DW_OP_lit16: // 0x40 + case DW_OP_lit17: // 0x41 + case DW_OP_lit18: // 0x42 + case DW_OP_lit19: // 0x43 + case DW_OP_lit20: // 0x44 + case DW_OP_lit21: // 0x45 + case DW_OP_lit22: // 0x46 + case DW_OP_lit23: // 0x47 + case DW_OP_lit24: // 0x48 + case DW_OP_lit25: // 0x49 + case DW_OP_lit26: // 0x4A + case DW_OP_lit27: // 0x4B + case DW_OP_lit28: // 0x4C + case DW_OP_lit29: // 0x4D + case DW_OP_lit30: // 0x4E + case DW_OP_lit31: + s->Printf("DW_OP_lit%i", op - DW_OP_lit0); + break; // 0x4f + + case DW_OP_reg0: // 0x50 + case DW_OP_reg1: // 0x51 + case DW_OP_reg2: // 0x52 + case DW_OP_reg3: // 0x53 + case DW_OP_reg4: // 0x54 + case DW_OP_reg5: // 0x55 + case DW_OP_reg6: // 0x56 + case DW_OP_reg7: // 0x57 + case DW_OP_reg8: // 0x58 + case DW_OP_reg9: // 0x59 + case DW_OP_reg10: // 0x5A + case DW_OP_reg11: // 0x5B + case DW_OP_reg12: // 0x5C + case DW_OP_reg13: // 0x5D + case DW_OP_reg14: // 0x5E + case DW_OP_reg15: // 0x5F + case DW_OP_reg16: // 0x60 + case DW_OP_reg17: // 0x61 + case DW_OP_reg18: // 0x62 + case DW_OP_reg19: // 0x63 + case DW_OP_reg20: // 0x64 + case DW_OP_reg21: // 0x65 + case DW_OP_reg22: // 0x66 + case DW_OP_reg23: // 0x67 + case DW_OP_reg24: // 0x68 + case DW_OP_reg25: // 0x69 + case DW_OP_reg26: // 0x6A + case DW_OP_reg27: // 0x6B + case DW_OP_reg28: // 0x6C + case DW_OP_reg29: // 0x6D + case DW_OP_reg30: // 0x6E + case DW_OP_reg31: // 0x6F { - const lldb::offset_t op_offset = offset; - const uint8_t op = m_data.GetU8(&offset); - - switch (level) - { - default: - break; - - case lldb::eDescriptionLevelBrief: - if (offset > start_offset) - s->PutChar(' '); + uint32_t reg_num = op - DW_OP_reg0; + if (abi) { + RegisterInfo reg_info; + if (abi->GetRegisterInfoByKind(m_reg_kind, reg_num, reg_info)) { + if (reg_info.name) { + s->PutCString(reg_info.name); break; - - case lldb::eDescriptionLevelFull: - case lldb::eDescriptionLevelVerbose: - if (offset > start_offset) - s->EOL(); - s->Indent(); - if (level == lldb::eDescriptionLevelFull) - break; - // Fall through for verbose and print offset and DW_OP prefix.. - s->Printf("0x%8.8" PRIx64 ": %s", op_offset, op >= DW_OP_APPLE_uninit ? "DW_OP_APPLE_" : "DW_OP_"); + } else if (reg_info.alt_name) { + s->PutCString(reg_info.alt_name); break; + } } + } + s->Printf("DW_OP_reg%u", reg_num); + break; + } break; + + case DW_OP_breg0: + case DW_OP_breg1: + case DW_OP_breg2: + case DW_OP_breg3: + case DW_OP_breg4: + case DW_OP_breg5: + case DW_OP_breg6: + case DW_OP_breg7: + case DW_OP_breg8: + case DW_OP_breg9: + case DW_OP_breg10: + case DW_OP_breg11: + case DW_OP_breg12: + case DW_OP_breg13: + case DW_OP_breg14: + case DW_OP_breg15: + case DW_OP_breg16: + case DW_OP_breg17: + case DW_OP_breg18: + case DW_OP_breg19: + case DW_OP_breg20: + case DW_OP_breg21: + case DW_OP_breg22: + case DW_OP_breg23: + case DW_OP_breg24: + case DW_OP_breg25: + case DW_OP_breg26: + case DW_OP_breg27: + case DW_OP_breg28: + case DW_OP_breg29: + case DW_OP_breg30: + case DW_OP_breg31: { + uint32_t reg_num = op - DW_OP_breg0; + int64_t reg_offset = m_data.GetSLEB128(&offset); + if (abi) { + RegisterInfo reg_info; + if (abi->GetRegisterInfoByKind(m_reg_kind, reg_num, reg_info)) { + if (reg_info.name) { + s->Printf("[%s%+" PRIi64 "]", reg_info.name, reg_offset); + break; + } else if (reg_info.alt_name) { + s->Printf("[%s%+" PRIi64 "]", reg_info.alt_name, reg_offset); + break; + } + } + } + s->Printf("DW_OP_breg%i(0x%" PRIx64 ")", reg_num, reg_offset); + } break; - switch (op) - { - case DW_OP_addr: *s << "DW_OP_addr(" << m_data.GetAddress(&offset) << ") "; break; // 0x03 1 address - case DW_OP_deref: *s << "DW_OP_deref"; break; // 0x06 - case DW_OP_const1u: s->Printf("DW_OP_const1u(0x%2.2x) ", m_data.GetU8(&offset)); break; // 0x08 1 1-byte constant - case DW_OP_const1s: s->Printf("DW_OP_const1s(0x%2.2x) ", m_data.GetU8(&offset)); break; // 0x09 1 1-byte constant - case DW_OP_const2u: s->Printf("DW_OP_const2u(0x%4.4x) ", m_data.GetU16(&offset)); break; // 0x0a 1 2-byte constant - case DW_OP_const2s: s->Printf("DW_OP_const2s(0x%4.4x) ", m_data.GetU16(&offset)); break; // 0x0b 1 2-byte constant - case DW_OP_const4u: s->Printf("DW_OP_const4u(0x%8.8x) ", m_data.GetU32(&offset)); break; // 0x0c 1 4-byte constant - case DW_OP_const4s: s->Printf("DW_OP_const4s(0x%8.8x) ", m_data.GetU32(&offset)); break; // 0x0d 1 4-byte constant - case DW_OP_const8u: s->Printf("DW_OP_const8u(0x%16.16" PRIx64 ") ", m_data.GetU64(&offset)); break; // 0x0e 1 8-byte constant - case DW_OP_const8s: s->Printf("DW_OP_const8s(0x%16.16" PRIx64 ") ", m_data.GetU64(&offset)); break; // 0x0f 1 8-byte constant - case DW_OP_constu: s->Printf("DW_OP_constu(0x%" PRIx64 ") ", m_data.GetULEB128(&offset)); break; // 0x10 1 ULEB128 constant - case DW_OP_consts: s->Printf("DW_OP_consts(0x%" PRId64 ") ", m_data.GetSLEB128(&offset)); break; // 0x11 1 SLEB128 constant - case DW_OP_dup: s->PutCString("DW_OP_dup"); break; // 0x12 - case DW_OP_drop: s->PutCString("DW_OP_drop"); break; // 0x13 - case DW_OP_over: s->PutCString("DW_OP_over"); break; // 0x14 - case DW_OP_pick: s->Printf("DW_OP_pick(0x%2.2x) ", m_data.GetU8(&offset)); break; // 0x15 1 1-byte stack index - case DW_OP_swap: s->PutCString("DW_OP_swap"); break; // 0x16 - case DW_OP_rot: s->PutCString("DW_OP_rot"); break; // 0x17 - case DW_OP_xderef: s->PutCString("DW_OP_xderef"); break; // 0x18 - case DW_OP_abs: s->PutCString("DW_OP_abs"); break; // 0x19 - case DW_OP_and: s->PutCString("DW_OP_and"); break; // 0x1a - case DW_OP_div: s->PutCString("DW_OP_div"); break; // 0x1b - case DW_OP_minus: s->PutCString("DW_OP_minus"); break; // 0x1c - case DW_OP_mod: s->PutCString("DW_OP_mod"); break; // 0x1d - case DW_OP_mul: s->PutCString("DW_OP_mul"); break; // 0x1e - case DW_OP_neg: s->PutCString("DW_OP_neg"); break; // 0x1f - case DW_OP_not: s->PutCString("DW_OP_not"); break; // 0x20 - case DW_OP_or: s->PutCString("DW_OP_or"); break; // 0x21 - case DW_OP_plus: s->PutCString("DW_OP_plus"); break; // 0x22 - case DW_OP_plus_uconst: // 0x23 1 ULEB128 addend - s->Printf("DW_OP_plus_uconst(0x%" PRIx64 ") ", m_data.GetULEB128(&offset)); - break; - - case DW_OP_shl: s->PutCString("DW_OP_shl"); break; // 0x24 - case DW_OP_shr: s->PutCString("DW_OP_shr"); break; // 0x25 - case DW_OP_shra: s->PutCString("DW_OP_shra"); break; // 0x26 - case DW_OP_xor: s->PutCString("DW_OP_xor"); break; // 0x27 - case DW_OP_skip: s->Printf("DW_OP_skip(0x%4.4x)", m_data.GetU16(&offset)); break; // 0x2f 1 signed 2-byte constant - case DW_OP_bra: s->Printf("DW_OP_bra(0x%4.4x)", m_data.GetU16(&offset)); break; // 0x28 1 signed 2-byte constant - case DW_OP_eq: s->PutCString("DW_OP_eq"); break; // 0x29 - case DW_OP_ge: s->PutCString("DW_OP_ge"); break; // 0x2a - case DW_OP_gt: s->PutCString("DW_OP_gt"); break; // 0x2b - case DW_OP_le: s->PutCString("DW_OP_le"); break; // 0x2c - case DW_OP_lt: s->PutCString("DW_OP_lt"); break; // 0x2d - case DW_OP_ne: s->PutCString("DW_OP_ne"); break; // 0x2e - - case DW_OP_lit0: // 0x30 - case DW_OP_lit1: // 0x31 - case DW_OP_lit2: // 0x32 - case DW_OP_lit3: // 0x33 - case DW_OP_lit4: // 0x34 - case DW_OP_lit5: // 0x35 - case DW_OP_lit6: // 0x36 - case DW_OP_lit7: // 0x37 - case DW_OP_lit8: // 0x38 - case DW_OP_lit9: // 0x39 - case DW_OP_lit10: // 0x3A - case DW_OP_lit11: // 0x3B - case DW_OP_lit12: // 0x3C - case DW_OP_lit13: // 0x3D - case DW_OP_lit14: // 0x3E - case DW_OP_lit15: // 0x3F - case DW_OP_lit16: // 0x40 - case DW_OP_lit17: // 0x41 - case DW_OP_lit18: // 0x42 - case DW_OP_lit19: // 0x43 - case DW_OP_lit20: // 0x44 - case DW_OP_lit21: // 0x45 - case DW_OP_lit22: // 0x46 - case DW_OP_lit23: // 0x47 - case DW_OP_lit24: // 0x48 - case DW_OP_lit25: // 0x49 - case DW_OP_lit26: // 0x4A - case DW_OP_lit27: // 0x4B - case DW_OP_lit28: // 0x4C - case DW_OP_lit29: // 0x4D - case DW_OP_lit30: // 0x4E - case DW_OP_lit31: s->Printf("DW_OP_lit%i", op - DW_OP_lit0); break; // 0x4f - - case DW_OP_reg0: // 0x50 - case DW_OP_reg1: // 0x51 - case DW_OP_reg2: // 0x52 - case DW_OP_reg3: // 0x53 - case DW_OP_reg4: // 0x54 - case DW_OP_reg5: // 0x55 - case DW_OP_reg6: // 0x56 - case DW_OP_reg7: // 0x57 - case DW_OP_reg8: // 0x58 - case DW_OP_reg9: // 0x59 - case DW_OP_reg10: // 0x5A - case DW_OP_reg11: // 0x5B - case DW_OP_reg12: // 0x5C - case DW_OP_reg13: // 0x5D - case DW_OP_reg14: // 0x5E - case DW_OP_reg15: // 0x5F - case DW_OP_reg16: // 0x60 - case DW_OP_reg17: // 0x61 - case DW_OP_reg18: // 0x62 - case DW_OP_reg19: // 0x63 - case DW_OP_reg20: // 0x64 - case DW_OP_reg21: // 0x65 - case DW_OP_reg22: // 0x66 - case DW_OP_reg23: // 0x67 - case DW_OP_reg24: // 0x68 - case DW_OP_reg25: // 0x69 - case DW_OP_reg26: // 0x6A - case DW_OP_reg27: // 0x6B - case DW_OP_reg28: // 0x6C - case DW_OP_reg29: // 0x6D - case DW_OP_reg30: // 0x6E - case DW_OP_reg31: // 0x6F - { - uint32_t reg_num = op - DW_OP_reg0; - if (abi) - { - RegisterInfo reg_info; - if (abi->GetRegisterInfoByKind(m_reg_kind, reg_num, reg_info)) - { - if (reg_info.name) - { - s->PutCString (reg_info.name); - break; - } - else if (reg_info.alt_name) - { - s->PutCString (reg_info.alt_name); - break; - } - } - } - s->Printf("DW_OP_reg%u", reg_num); break; - } - break; - - case DW_OP_breg0: - case DW_OP_breg1: - case DW_OP_breg2: - case DW_OP_breg3: - case DW_OP_breg4: - case DW_OP_breg5: - case DW_OP_breg6: - case DW_OP_breg7: - case DW_OP_breg8: - case DW_OP_breg9: - case DW_OP_breg10: - case DW_OP_breg11: - case DW_OP_breg12: - case DW_OP_breg13: - case DW_OP_breg14: - case DW_OP_breg15: - case DW_OP_breg16: - case DW_OP_breg17: - case DW_OP_breg18: - case DW_OP_breg19: - case DW_OP_breg20: - case DW_OP_breg21: - case DW_OP_breg22: - case DW_OP_breg23: - case DW_OP_breg24: - case DW_OP_breg25: - case DW_OP_breg26: - case DW_OP_breg27: - case DW_OP_breg28: - case DW_OP_breg29: - case DW_OP_breg30: - case DW_OP_breg31: - { - uint32_t reg_num = op - DW_OP_breg0; - int64_t reg_offset = m_data.GetSLEB128(&offset); - if (abi) - { - RegisterInfo reg_info; - if (abi->GetRegisterInfoByKind(m_reg_kind, reg_num, reg_info)) - { - if (reg_info.name) - { - s->Printf("[%s%+" PRIi64 "]", reg_info.name, reg_offset); - break; - } - else if (reg_info.alt_name) - { - s->Printf("[%s%+" PRIi64 "]", reg_info.alt_name, reg_offset); - break; - } - } - } - s->Printf("DW_OP_breg%i(0x%" PRIx64 ")", reg_num, reg_offset); - } - break; - - case DW_OP_regx: // 0x90 1 ULEB128 register - { - uint32_t reg_num = m_data.GetULEB128(&offset); - if (abi) - { - RegisterInfo reg_info; - if (abi->GetRegisterInfoByKind(m_reg_kind, reg_num, reg_info)) - { - if (reg_info.name) - { - s->PutCString (reg_info.name); - break; - } - else if (reg_info.alt_name) - { - s->PutCString (reg_info.alt_name); - break; - } - } - } - s->Printf("DW_OP_regx(%" PRIu32 ")", reg_num); break; - } - break; - case DW_OP_fbreg: // 0x91 1 SLEB128 offset - s->Printf("DW_OP_fbreg(%" PRIi64 ")",m_data.GetSLEB128(&offset)); - break; - case DW_OP_bregx: // 0x92 2 ULEB128 register followed by SLEB128 offset - { - uint32_t reg_num = m_data.GetULEB128(&offset); - int64_t reg_offset = m_data.GetSLEB128(&offset); - if (abi) - { - RegisterInfo reg_info; - if (abi->GetRegisterInfoByKind(m_reg_kind, reg_num, reg_info)) - { - if (reg_info.name) - { - s->Printf("[%s%+" PRIi64 "]", reg_info.name, reg_offset); - break; - } - else if (reg_info.alt_name) - { - s->Printf("[%s%+" PRIi64 "]", reg_info.alt_name, reg_offset); - break; - } - } - } - s->Printf("DW_OP_bregx(reg=%" PRIu32 ",offset=%" PRIi64 ")", reg_num, reg_offset); - } - break; - case DW_OP_piece: // 0x93 1 ULEB128 size of piece addressed - s->Printf("DW_OP_piece(0x%" PRIx64 ")", m_data.GetULEB128(&offset)); - break; - case DW_OP_deref_size: // 0x94 1 1-byte size of data retrieved - s->Printf("DW_OP_deref_size(0x%2.2x)", m_data.GetU8(&offset)); - break; - case DW_OP_xderef_size: // 0x95 1 1-byte size of data retrieved - s->Printf("DW_OP_xderef_size(0x%2.2x)", m_data.GetU8(&offset)); - break; - case DW_OP_nop: s->PutCString("DW_OP_nop"); break; // 0x96 - case DW_OP_push_object_address: s->PutCString("DW_OP_push_object_address"); break; // 0x97 DWARF3 - case DW_OP_call2: // 0x98 DWARF3 1 2-byte offset of DIE - s->Printf("DW_OP_call2(0x%4.4x)", m_data.GetU16(&offset)); - break; - case DW_OP_call4: // 0x99 DWARF3 1 4-byte offset of DIE - s->Printf("DW_OP_call4(0x%8.8x)", m_data.GetU32(&offset)); - break; - case DW_OP_call_ref: // 0x9a DWARF3 1 4- or 8-byte offset of DIE - s->Printf("DW_OP_call_ref(0x%8.8" PRIx64 ")", m_data.GetAddress(&offset)); - break; -// case DW_OP_call_frame_cfa: s << "call_frame_cfa"; break; // 0x9c DWARF3 -// case DW_OP_bit_piece: // 0x9d DWARF3 2 -// s->Printf("DW_OP_bit_piece(0x%x, 0x%x)", m_data.GetULEB128(&offset), m_data.GetULEB128(&offset)); -// break; -// case DW_OP_lo_user: s->PutCString("DW_OP_lo_user"); break; // 0xe0 -// case DW_OP_hi_user: s->PutCString("DW_OP_hi_user"); break; // 0xff -// case DW_OP_APPLE_extern: -// s->Printf("DW_OP_APPLE_extern(%" PRIu64 ")", m_data.GetULEB128(&offset)); -// break; -// case DW_OP_APPLE_array_ref: -// s->PutCString("DW_OP_APPLE_array_ref"); -// break; - case DW_OP_form_tls_address: - s->PutCString("DW_OP_form_tls_address"); // 0x9b - break; - case DW_OP_GNU_addr_index: // 0xfb - s->Printf("DW_OP_GNU_addr_index(0x%" PRIx64 ")", m_data.GetULEB128(&offset)); - break; - case DW_OP_GNU_const_index: // 0xfc - s->Printf("DW_OP_GNU_const_index(0x%" PRIx64 ")", m_data.GetULEB128(&offset)); - break; - case DW_OP_GNU_push_tls_address: - s->PutCString("DW_OP_GNU_push_tls_address"); // 0xe0 + case DW_OP_regx: // 0x90 1 ULEB128 register + { + uint32_t reg_num = m_data.GetULEB128(&offset); + if (abi) { + RegisterInfo reg_info; + if (abi->GetRegisterInfoByKind(m_reg_kind, reg_num, reg_info)) { + if (reg_info.name) { + s->PutCString(reg_info.name); break; - case DW_OP_APPLE_uninit: - s->PutCString("DW_OP_APPLE_uninit"); // 0xF0 + } else if (reg_info.alt_name) { + s->PutCString(reg_info.alt_name); break; -// case DW_OP_APPLE_assign: // 0xF1 - pops value off and assigns it to second item on stack (2nd item must have assignable context) -// s->PutCString("DW_OP_APPLE_assign"); -// break; -// case DW_OP_APPLE_address_of: // 0xF2 - gets the address of the top stack item (top item must be a variable, or have value_type that is an address already) -// s->PutCString("DW_OP_APPLE_address_of"); -// break; -// case DW_OP_APPLE_value_of: // 0xF3 - pops the value off the stack and pushes the value of that object (top item must be a variable, or expression local) -// s->PutCString("DW_OP_APPLE_value_of"); -// break; -// case DW_OP_APPLE_deref_type: // 0xF4 - gets the address of the top stack item (top item must be a variable, or a clang type) -// s->PutCString("DW_OP_APPLE_deref_type"); -// break; -// case DW_OP_APPLE_expr_local: // 0xF5 - ULEB128 expression local index -// s->Printf("DW_OP_APPLE_expr_local(%" PRIu64 ")", m_data.GetULEB128(&offset)); -// break; -// case DW_OP_APPLE_constf: // 0xF6 - 1 byte float size, followed by constant float data -// { -// uint8_t float_length = m_data.GetU8(&offset); -// s->Printf("DW_OP_APPLE_constf(<%u> ", float_length); -// m_data.Dump(s, offset, eFormatHex, float_length, 1, UINT32_MAX, DW_INVALID_ADDRESS, 0, 0); -// s->PutChar(')'); -// // Consume the float data -// m_data.GetData(&offset, float_length); -// } -// break; -// case DW_OP_APPLE_scalar_cast: -// s->Printf("DW_OP_APPLE_scalar_cast(%s)", Scalar::GetValueTypeAsCString ((Scalar::Type)m_data.GetU8(&offset))); -// break; -// case DW_OP_APPLE_clang_cast: -// { -// clang::Type *clang_type = (clang::Type *)m_data.GetMaxU64(&offset, sizeof(void*)); -// s->Printf("DW_OP_APPLE_clang_cast(%p)", clang_type); -// } -// break; -// case DW_OP_APPLE_clear: -// s->PutCString("DW_OP_APPLE_clear"); -// break; -// case DW_OP_APPLE_error: // 0xFF - Stops expression evaluation and returns an error (no args) -// s->PutCString("DW_OP_APPLE_error"); -// break; + } } + } + s->Printf("DW_OP_regx(%" PRIu32 ")", reg_num); + break; + } break; + case DW_OP_fbreg: // 0x91 1 SLEB128 offset + s->Printf("DW_OP_fbreg(%" PRIi64 ")", m_data.GetSLEB128(&offset)); + break; + case DW_OP_bregx: // 0x92 2 ULEB128 register followed by SLEB128 offset + { + uint32_t reg_num = m_data.GetULEB128(&offset); + int64_t reg_offset = m_data.GetSLEB128(&offset); + if (abi) { + RegisterInfo reg_info; + if (abi->GetRegisterInfoByKind(m_reg_kind, reg_num, reg_info)) { + if (reg_info.name) { + s->Printf("[%s%+" PRIi64 "]", reg_info.name, reg_offset); + break; + } else if (reg_info.alt_name) { + s->Printf("[%s%+" PRIi64 "]", reg_info.alt_name, reg_offset); + break; + } + } + } + s->Printf("DW_OP_bregx(reg=%" PRIu32 ",offset=%" PRIi64 ")", reg_num, + reg_offset); + } break; + case DW_OP_piece: // 0x93 1 ULEB128 size of piece addressed + s->Printf("DW_OP_piece(0x%" PRIx64 ")", m_data.GetULEB128(&offset)); + break; + case DW_OP_deref_size: // 0x94 1 1-byte size of data retrieved + s->Printf("DW_OP_deref_size(0x%2.2x)", m_data.GetU8(&offset)); + break; + case DW_OP_xderef_size: // 0x95 1 1-byte size of data retrieved + s->Printf("DW_OP_xderef_size(0x%2.2x)", m_data.GetU8(&offset)); + break; + case DW_OP_nop: + s->PutCString("DW_OP_nop"); + break; // 0x96 + case DW_OP_push_object_address: + s->PutCString("DW_OP_push_object_address"); + break; // 0x97 DWARF3 + case DW_OP_call2: // 0x98 DWARF3 1 2-byte offset of DIE + s->Printf("DW_OP_call2(0x%4.4x)", m_data.GetU16(&offset)); + break; + case DW_OP_call4: // 0x99 DWARF3 1 4-byte offset of DIE + s->Printf("DW_OP_call4(0x%8.8x)", m_data.GetU32(&offset)); + break; + case DW_OP_call_ref: // 0x9a DWARF3 1 4- or 8-byte offset of DIE + s->Printf("DW_OP_call_ref(0x%8.8" PRIx64 ")", m_data.GetAddress(&offset)); + break; + // case DW_OP_call_frame_cfa: s << "call_frame_cfa"; break; + // // 0x9c DWARF3 + // case DW_OP_bit_piece: // 0x9d DWARF3 2 + // s->Printf("DW_OP_bit_piece(0x%x, 0x%x)", + // m_data.GetULEB128(&offset), m_data.GetULEB128(&offset)); + // break; + // case DW_OP_lo_user: s->PutCString("DW_OP_lo_user"); break; + // // 0xe0 + // case DW_OP_hi_user: s->PutCString("DW_OP_hi_user"); break; + // // 0xff + // case DW_OP_APPLE_extern: + // s->Printf("DW_OP_APPLE_extern(%" PRIu64 ")", + // m_data.GetULEB128(&offset)); + // break; + // case DW_OP_APPLE_array_ref: + // s->PutCString("DW_OP_APPLE_array_ref"); + // break; + case DW_OP_form_tls_address: + s->PutCString("DW_OP_form_tls_address"); // 0x9b + break; + case DW_OP_GNU_addr_index: // 0xfb + s->Printf("DW_OP_GNU_addr_index(0x%" PRIx64 ")", + m_data.GetULEB128(&offset)); + break; + case DW_OP_GNU_const_index: // 0xfc + s->Printf("DW_OP_GNU_const_index(0x%" PRIx64 ")", + m_data.GetULEB128(&offset)); + break; + case DW_OP_GNU_push_tls_address: + s->PutCString("DW_OP_GNU_push_tls_address"); // 0xe0 + break; + case DW_OP_APPLE_uninit: + s->PutCString("DW_OP_APPLE_uninit"); // 0xF0 + break; + // case DW_OP_APPLE_assign: // 0xF1 - pops value off and + // assigns it to second item on stack (2nd item must have + // assignable context) + // s->PutCString("DW_OP_APPLE_assign"); + // break; + // case DW_OP_APPLE_address_of: // 0xF2 - gets the address of + // the top stack item (top item must be a variable, or have + // value_type that is an address already) + // s->PutCString("DW_OP_APPLE_address_of"); + // break; + // case DW_OP_APPLE_value_of: // 0xF3 - pops the value off the + // stack and pushes the value of that object (top item must be a + // variable, or expression local) + // s->PutCString("DW_OP_APPLE_value_of"); + // break; + // case DW_OP_APPLE_deref_type: // 0xF4 - gets the address of + // the top stack item (top item must be a variable, or a clang + // type) + // s->PutCString("DW_OP_APPLE_deref_type"); + // break; + // case DW_OP_APPLE_expr_local: // 0xF5 - ULEB128 expression + // local index + // s->Printf("DW_OP_APPLE_expr_local(%" PRIu64 ")", + // m_data.GetULEB128(&offset)); + // break; + // case DW_OP_APPLE_constf: // 0xF6 - 1 byte float size, + // followed by constant float data + // { + // uint8_t float_length = m_data.GetU8(&offset); + // s->Printf("DW_OP_APPLE_constf(<%u> ", float_length); + // m_data.Dump(s, offset, eFormatHex, float_length, 1, + // UINT32_MAX, DW_INVALID_ADDRESS, 0, 0); + // s->PutChar(')'); + // // Consume the float data + // m_data.GetData(&offset, float_length); + // } + // break; + // case DW_OP_APPLE_scalar_cast: + // s->Printf("DW_OP_APPLE_scalar_cast(%s)", + // Scalar::GetValueTypeAsCString + // ((Scalar::Type)m_data.GetU8(&offset))); + // break; + // case DW_OP_APPLE_clang_cast: + // { + // clang::Type *clang_type = (clang::Type + // *)m_data.GetMaxU64(&offset, sizeof(void*)); + // s->Printf("DW_OP_APPLE_clang_cast(%p)", clang_type); + // } + // break; + // case DW_OP_APPLE_clear: + // s->PutCString("DW_OP_APPLE_clear"); + // break; + // case DW_OP_APPLE_error: // 0xFF - Stops expression + // evaluation and returns an error (no args) + // s->PutCString("DW_OP_APPLE_error"); + // break; } + } } -void -DWARFExpression::SetLocationListSlide (addr_t slide) -{ - m_loclist_slide = slide; +void DWARFExpression::SetLocationListSlide(addr_t slide) { + m_loclist_slide = slide; } -int -DWARFExpression::GetRegisterKind () -{ - return m_reg_kind; -} +int DWARFExpression::GetRegisterKind() { return m_reg_kind; } -void -DWARFExpression::SetRegisterKind (RegisterKind reg_kind) -{ - m_reg_kind = reg_kind; +void DWARFExpression::SetRegisterKind(RegisterKind reg_kind) { + m_reg_kind = reg_kind; } -bool -DWARFExpression::IsLocationList() const -{ - return m_loclist_slide != LLDB_INVALID_ADDRESS; +bool DWARFExpression::IsLocationList() const { + return m_loclist_slide != LLDB_INVALID_ADDRESS; } -void -DWARFExpression::GetDescription (Stream *s, lldb::DescriptionLevel level, addr_t location_list_base_addr, ABI *abi) const -{ - if (IsLocationList()) - { - // We have a location list - lldb::offset_t offset = 0; - uint32_t count = 0; - addr_t curr_base_addr = location_list_base_addr; - while (m_data.ValidOffset(offset)) - { - addr_t begin_addr_offset = LLDB_INVALID_ADDRESS; - addr_t end_addr_offset = LLDB_INVALID_ADDRESS; - if (!AddressRangeForLocationListEntry(m_dwarf_cu, m_data, &offset, begin_addr_offset, end_addr_offset)) - break; - - if (begin_addr_offset == 0 && end_addr_offset == 0) - break; - - if (begin_addr_offset < end_addr_offset) - { - if (count > 0) - s->PutCString(", "); - VMRange addr_range(curr_base_addr + begin_addr_offset, curr_base_addr + end_addr_offset); - addr_range.Dump(s, 0, 8); - s->PutChar('{'); - lldb::offset_t location_length = m_data.GetU16(&offset); - DumpLocation (s, offset, location_length, level, abi); - s->PutChar('}'); - offset += location_length; - } - else - { - if ((m_data.GetAddressByteSize() == 4 && (begin_addr_offset == UINT32_MAX)) || - (m_data.GetAddressByteSize() == 8 && (begin_addr_offset == UINT64_MAX))) - { - curr_base_addr = end_addr_offset + location_list_base_addr; - // We have a new base address - if (count > 0) - s->PutCString(", "); - *s << "base_addr = " << end_addr_offset; - } - } - - count++; +void DWARFExpression::GetDescription(Stream *s, lldb::DescriptionLevel level, + addr_t location_list_base_addr, + ABI *abi) const { + if (IsLocationList()) { + // We have a location list + lldb::offset_t offset = 0; + uint32_t count = 0; + addr_t curr_base_addr = location_list_base_addr; + while (m_data.ValidOffset(offset)) { + addr_t begin_addr_offset = LLDB_INVALID_ADDRESS; + addr_t end_addr_offset = LLDB_INVALID_ADDRESS; + if (!AddressRangeForLocationListEntry(m_dwarf_cu, m_data, &offset, + begin_addr_offset, end_addr_offset)) + break; + + if (begin_addr_offset == 0 && end_addr_offset == 0) + break; + + if (begin_addr_offset < end_addr_offset) { + if (count > 0) + s->PutCString(", "); + VMRange addr_range(curr_base_addr + begin_addr_offset, + curr_base_addr + end_addr_offset); + addr_range.Dump(s, 0, 8); + s->PutChar('{'); + lldb::offset_t location_length = m_data.GetU16(&offset); + DumpLocation(s, offset, location_length, level, abi); + s->PutChar('}'); + offset += location_length; + } else { + if ((m_data.GetAddressByteSize() == 4 && + (begin_addr_offset == UINT32_MAX)) || + (m_data.GetAddressByteSize() == 8 && + (begin_addr_offset == UINT64_MAX))) { + curr_base_addr = end_addr_offset + location_list_base_addr; + // We have a new base address + if (count > 0) + s->PutCString(", "); + *s << "base_addr = " << end_addr_offset; } + } + + count++; } - else - { - // We have a normal location that contains DW_OP location opcodes - DumpLocation (s, 0, m_data.GetByteSize(), level, abi); - } + } else { + // We have a normal location that contains DW_OP location opcodes + DumpLocation(s, 0, m_data.GetByteSize(), level, abi); + } } -static bool -ReadRegisterValueAsScalar -( - RegisterContext *reg_ctx, - lldb::RegisterKind reg_kind, - uint32_t reg_num, - Error *error_ptr, - Value &value -) -{ - if (reg_ctx == NULL) - { - if (error_ptr) - error_ptr->SetErrorStringWithFormat("No register context in frame.\n"); - } - else - { - uint32_t native_reg = reg_ctx->ConvertRegisterKindToRegisterNumber(reg_kind, reg_num); - if (native_reg == LLDB_INVALID_REGNUM) - { - if (error_ptr) - error_ptr->SetErrorStringWithFormat("Unable to convert register kind=%u reg_num=%u to a native register number.\n", reg_kind, reg_num); - } - else - { - const RegisterInfo *reg_info = reg_ctx->GetRegisterInfoAtIndex(native_reg); - RegisterValue reg_value; - if (reg_ctx->ReadRegister (reg_info, reg_value)) - { - if (reg_value.GetScalarValue(value.GetScalar())) - { - value.SetValueType (Value::eValueTypeScalar); - value.SetContext (Value::eContextTypeRegisterInfo, - const_cast<RegisterInfo *>(reg_info)); - if (error_ptr) - error_ptr->Clear(); - return true; - } - else - { - // If we get this error, then we need to implement a value - // buffer in the dwarf expression evaluation function... - if (error_ptr) - error_ptr->SetErrorStringWithFormat ("register %s can't be converted to a scalar value", - reg_info->name); - } - } - else - { - if (error_ptr) - error_ptr->SetErrorStringWithFormat("register %s is not available", reg_info->name); - } +static bool ReadRegisterValueAsScalar(RegisterContext *reg_ctx, + lldb::RegisterKind reg_kind, + uint32_t reg_num, Error *error_ptr, + Value &value) { + if (reg_ctx == NULL) { + if (error_ptr) + error_ptr->SetErrorStringWithFormat("No register context in frame.\n"); + } else { + uint32_t native_reg = + reg_ctx->ConvertRegisterKindToRegisterNumber(reg_kind, reg_num); + if (native_reg == LLDB_INVALID_REGNUM) { + if (error_ptr) + error_ptr->SetErrorStringWithFormat("Unable to convert register " + "kind=%u reg_num=%u to a native " + "register number.\n", + reg_kind, reg_num); + } else { + const RegisterInfo *reg_info = + reg_ctx->GetRegisterInfoAtIndex(native_reg); + RegisterValue reg_value; + if (reg_ctx->ReadRegister(reg_info, reg_value)) { + if (reg_value.GetScalarValue(value.GetScalar())) { + value.SetValueType(Value::eValueTypeScalar); + value.SetContext(Value::eContextTypeRegisterInfo, + const_cast<RegisterInfo *>(reg_info)); + if (error_ptr) + error_ptr->Clear(); + return true; + } else { + // If we get this error, then we need to implement a value + // buffer in the dwarf expression evaluation function... + if (error_ptr) + error_ptr->SetErrorStringWithFormat( + "register %s can't be converted to a scalar value", + reg_info->name); } + } else { + if (error_ptr) + error_ptr->SetErrorStringWithFormat("register %s is not available", + reg_info->name); + } } - return false; + } + return false; } -//bool -//DWARFExpression::LocationListContainsLoadAddress (Process* process, const Address &addr) const +// bool +// DWARFExpression::LocationListContainsLoadAddress (Process* process, const +// Address &addr) const //{ -// return LocationListContainsLoadAddress(process, addr.GetLoadAddress(process)); +// return LocationListContainsLoadAddress(process, +// addr.GetLoadAddress(process)); //} // -//bool -//DWARFExpression::LocationListContainsLoadAddress (Process* process, addr_t load_addr) const +// bool +// DWARFExpression::LocationListContainsLoadAddress (Process* process, addr_t +// load_addr) const //{ // if (load_addr == LLDB_INVALID_ADDRESS) // return false; @@ -701,2638 +745,2650 @@ ReadRegisterValueAsScalar // return false; //} -static offset_t -GetOpcodeDataSize (const DataExtractor &data, const lldb::offset_t data_offset, const uint8_t op) -{ - lldb::offset_t offset = data_offset; - switch (op) - { - case DW_OP_addr: - case DW_OP_call_ref: // 0x9a 1 address sized offset of DIE (DWARF3) - return data.GetAddressByteSize(); - - // Opcodes with no arguments - case DW_OP_deref: // 0x06 - case DW_OP_dup: // 0x12 - case DW_OP_drop: // 0x13 - case DW_OP_over: // 0x14 - case DW_OP_swap: // 0x16 - case DW_OP_rot: // 0x17 - case DW_OP_xderef: // 0x18 - case DW_OP_abs: // 0x19 - case DW_OP_and: // 0x1a - case DW_OP_div: // 0x1b - case DW_OP_minus: // 0x1c - case DW_OP_mod: // 0x1d - case DW_OP_mul: // 0x1e - case DW_OP_neg: // 0x1f - case DW_OP_not: // 0x20 - case DW_OP_or: // 0x21 - case DW_OP_plus: // 0x22 - case DW_OP_shl: // 0x24 - case DW_OP_shr: // 0x25 - case DW_OP_shra: // 0x26 - case DW_OP_xor: // 0x27 - case DW_OP_eq: // 0x29 - case DW_OP_ge: // 0x2a - case DW_OP_gt: // 0x2b - case DW_OP_le: // 0x2c - case DW_OP_lt: // 0x2d - case DW_OP_ne: // 0x2e - case DW_OP_lit0: // 0x30 - case DW_OP_lit1: // 0x31 - case DW_OP_lit2: // 0x32 - case DW_OP_lit3: // 0x33 - case DW_OP_lit4: // 0x34 - case DW_OP_lit5: // 0x35 - case DW_OP_lit6: // 0x36 - case DW_OP_lit7: // 0x37 - case DW_OP_lit8: // 0x38 - case DW_OP_lit9: // 0x39 - case DW_OP_lit10: // 0x3A - case DW_OP_lit11: // 0x3B - case DW_OP_lit12: // 0x3C - case DW_OP_lit13: // 0x3D - case DW_OP_lit14: // 0x3E - case DW_OP_lit15: // 0x3F - case DW_OP_lit16: // 0x40 - case DW_OP_lit17: // 0x41 - case DW_OP_lit18: // 0x42 - case DW_OP_lit19: // 0x43 - case DW_OP_lit20: // 0x44 - case DW_OP_lit21: // 0x45 - case DW_OP_lit22: // 0x46 - case DW_OP_lit23: // 0x47 - case DW_OP_lit24: // 0x48 - case DW_OP_lit25: // 0x49 - case DW_OP_lit26: // 0x4A - case DW_OP_lit27: // 0x4B - case DW_OP_lit28: // 0x4C - case DW_OP_lit29: // 0x4D - case DW_OP_lit30: // 0x4E - case DW_OP_lit31: // 0x4f - case DW_OP_reg0: // 0x50 - case DW_OP_reg1: // 0x51 - case DW_OP_reg2: // 0x52 - case DW_OP_reg3: // 0x53 - case DW_OP_reg4: // 0x54 - case DW_OP_reg5: // 0x55 - case DW_OP_reg6: // 0x56 - case DW_OP_reg7: // 0x57 - case DW_OP_reg8: // 0x58 - case DW_OP_reg9: // 0x59 - case DW_OP_reg10: // 0x5A - case DW_OP_reg11: // 0x5B - case DW_OP_reg12: // 0x5C - case DW_OP_reg13: // 0x5D - case DW_OP_reg14: // 0x5E - case DW_OP_reg15: // 0x5F - case DW_OP_reg16: // 0x60 - case DW_OP_reg17: // 0x61 - case DW_OP_reg18: // 0x62 - case DW_OP_reg19: // 0x63 - case DW_OP_reg20: // 0x64 - case DW_OP_reg21: // 0x65 - case DW_OP_reg22: // 0x66 - case DW_OP_reg23: // 0x67 - case DW_OP_reg24: // 0x68 - case DW_OP_reg25: // 0x69 - case DW_OP_reg26: // 0x6A - case DW_OP_reg27: // 0x6B - case DW_OP_reg28: // 0x6C - case DW_OP_reg29: // 0x6D - case DW_OP_reg30: // 0x6E - case DW_OP_reg31: // 0x6F - case DW_OP_nop: // 0x96 - case DW_OP_push_object_address: // 0x97 DWARF3 - case DW_OP_form_tls_address: // 0x9b DWARF3 - case DW_OP_call_frame_cfa: // 0x9c DWARF3 - case DW_OP_stack_value: // 0x9f DWARF4 - case DW_OP_GNU_push_tls_address: // 0xe0 GNU extension - return 0; - - // Opcodes with a single 1 byte arguments - case DW_OP_const1u: // 0x08 1 1-byte constant - case DW_OP_const1s: // 0x09 1 1-byte constant - case DW_OP_pick: // 0x15 1 1-byte stack index - case DW_OP_deref_size: // 0x94 1 1-byte size of data retrieved - case DW_OP_xderef_size: // 0x95 1 1-byte size of data retrieved - return 1; - - // Opcodes with a single 2 byte arguments - case DW_OP_const2u: // 0x0a 1 2-byte constant - case DW_OP_const2s: // 0x0b 1 2-byte constant - case DW_OP_skip: // 0x2f 1 signed 2-byte constant - case DW_OP_bra: // 0x28 1 signed 2-byte constant - case DW_OP_call2: // 0x98 1 2-byte offset of DIE (DWARF3) - return 2; - - // Opcodes with a single 4 byte arguments - case DW_OP_const4u: // 0x0c 1 4-byte constant - case DW_OP_const4s: // 0x0d 1 4-byte constant - case DW_OP_call4: // 0x99 1 4-byte offset of DIE (DWARF3) - return 4; - - // Opcodes with a single 8 byte arguments - case DW_OP_const8u: // 0x0e 1 8-byte constant - case DW_OP_const8s: // 0x0f 1 8-byte constant - return 8; - - // All opcodes that have a single ULEB (signed or unsigned) argument - case DW_OP_constu: // 0x10 1 ULEB128 constant - case DW_OP_consts: // 0x11 1 SLEB128 constant - case DW_OP_plus_uconst: // 0x23 1 ULEB128 addend - case DW_OP_breg0: // 0x70 1 ULEB128 register - case DW_OP_breg1: // 0x71 1 ULEB128 register - case DW_OP_breg2: // 0x72 1 ULEB128 register - case DW_OP_breg3: // 0x73 1 ULEB128 register - case DW_OP_breg4: // 0x74 1 ULEB128 register - case DW_OP_breg5: // 0x75 1 ULEB128 register - case DW_OP_breg6: // 0x76 1 ULEB128 register - case DW_OP_breg7: // 0x77 1 ULEB128 register - case DW_OP_breg8: // 0x78 1 ULEB128 register - case DW_OP_breg9: // 0x79 1 ULEB128 register - case DW_OP_breg10: // 0x7a 1 ULEB128 register - case DW_OP_breg11: // 0x7b 1 ULEB128 register - case DW_OP_breg12: // 0x7c 1 ULEB128 register - case DW_OP_breg13: // 0x7d 1 ULEB128 register - case DW_OP_breg14: // 0x7e 1 ULEB128 register - case DW_OP_breg15: // 0x7f 1 ULEB128 register - case DW_OP_breg16: // 0x80 1 ULEB128 register - case DW_OP_breg17: // 0x81 1 ULEB128 register - case DW_OP_breg18: // 0x82 1 ULEB128 register - case DW_OP_breg19: // 0x83 1 ULEB128 register - case DW_OP_breg20: // 0x84 1 ULEB128 register - case DW_OP_breg21: // 0x85 1 ULEB128 register - case DW_OP_breg22: // 0x86 1 ULEB128 register - case DW_OP_breg23: // 0x87 1 ULEB128 register - case DW_OP_breg24: // 0x88 1 ULEB128 register - case DW_OP_breg25: // 0x89 1 ULEB128 register - case DW_OP_breg26: // 0x8a 1 ULEB128 register - case DW_OP_breg27: // 0x8b 1 ULEB128 register - case DW_OP_breg28: // 0x8c 1 ULEB128 register - case DW_OP_breg29: // 0x8d 1 ULEB128 register - case DW_OP_breg30: // 0x8e 1 ULEB128 register - case DW_OP_breg31: // 0x8f 1 ULEB128 register - case DW_OP_regx: // 0x90 1 ULEB128 register - case DW_OP_fbreg: // 0x91 1 SLEB128 offset - case DW_OP_piece: // 0x93 1 ULEB128 size of piece addressed - case DW_OP_GNU_addr_index: // 0xfb 1 ULEB128 index - case DW_OP_GNU_const_index: // 0xfc 1 ULEB128 index - data.Skip_LEB128(&offset); - return offset - data_offset; - - // All opcodes that have a 2 ULEB (signed or unsigned) arguments - case DW_OP_bregx: // 0x92 2 ULEB128 register followed by SLEB128 offset - case DW_OP_bit_piece: // 0x9d ULEB128 bit size, ULEB128 bit offset (DWARF3); - data.Skip_LEB128(&offset); - data.Skip_LEB128(&offset); - return offset - data_offset; - - case DW_OP_implicit_value: // 0x9e ULEB128 size followed by block of that size (DWARF4) - { - uint64_t block_len = data.Skip_LEB128(&offset); - offset += block_len; - return offset - data_offset; - } - - default: - break; - } - return LLDB_INVALID_OFFSET; +static offset_t GetOpcodeDataSize(const DataExtractor &data, + const lldb::offset_t data_offset, + const uint8_t op) { + lldb::offset_t offset = data_offset; + switch (op) { + case DW_OP_addr: + case DW_OP_call_ref: // 0x9a 1 address sized offset of DIE (DWARF3) + return data.GetAddressByteSize(); + + // Opcodes with no arguments + case DW_OP_deref: // 0x06 + case DW_OP_dup: // 0x12 + case DW_OP_drop: // 0x13 + case DW_OP_over: // 0x14 + case DW_OP_swap: // 0x16 + case DW_OP_rot: // 0x17 + case DW_OP_xderef: // 0x18 + case DW_OP_abs: // 0x19 + case DW_OP_and: // 0x1a + case DW_OP_div: // 0x1b + case DW_OP_minus: // 0x1c + case DW_OP_mod: // 0x1d + case DW_OP_mul: // 0x1e + case DW_OP_neg: // 0x1f + case DW_OP_not: // 0x20 + case DW_OP_or: // 0x21 + case DW_OP_plus: // 0x22 + case DW_OP_shl: // 0x24 + case DW_OP_shr: // 0x25 + case DW_OP_shra: // 0x26 + case DW_OP_xor: // 0x27 + case DW_OP_eq: // 0x29 + case DW_OP_ge: // 0x2a + case DW_OP_gt: // 0x2b + case DW_OP_le: // 0x2c + case DW_OP_lt: // 0x2d + case DW_OP_ne: // 0x2e + case DW_OP_lit0: // 0x30 + case DW_OP_lit1: // 0x31 + case DW_OP_lit2: // 0x32 + case DW_OP_lit3: // 0x33 + case DW_OP_lit4: // 0x34 + case DW_OP_lit5: // 0x35 + case DW_OP_lit6: // 0x36 + case DW_OP_lit7: // 0x37 + case DW_OP_lit8: // 0x38 + case DW_OP_lit9: // 0x39 + case DW_OP_lit10: // 0x3A + case DW_OP_lit11: // 0x3B + case DW_OP_lit12: // 0x3C + case DW_OP_lit13: // 0x3D + case DW_OP_lit14: // 0x3E + case DW_OP_lit15: // 0x3F + case DW_OP_lit16: // 0x40 + case DW_OP_lit17: // 0x41 + case DW_OP_lit18: // 0x42 + case DW_OP_lit19: // 0x43 + case DW_OP_lit20: // 0x44 + case DW_OP_lit21: // 0x45 + case DW_OP_lit22: // 0x46 + case DW_OP_lit23: // 0x47 + case DW_OP_lit24: // 0x48 + case DW_OP_lit25: // 0x49 + case DW_OP_lit26: // 0x4A + case DW_OP_lit27: // 0x4B + case DW_OP_lit28: // 0x4C + case DW_OP_lit29: // 0x4D + case DW_OP_lit30: // 0x4E + case DW_OP_lit31: // 0x4f + case DW_OP_reg0: // 0x50 + case DW_OP_reg1: // 0x51 + case DW_OP_reg2: // 0x52 + case DW_OP_reg3: // 0x53 + case DW_OP_reg4: // 0x54 + case DW_OP_reg5: // 0x55 + case DW_OP_reg6: // 0x56 + case DW_OP_reg7: // 0x57 + case DW_OP_reg8: // 0x58 + case DW_OP_reg9: // 0x59 + case DW_OP_reg10: // 0x5A + case DW_OP_reg11: // 0x5B + case DW_OP_reg12: // 0x5C + case DW_OP_reg13: // 0x5D + case DW_OP_reg14: // 0x5E + case DW_OP_reg15: // 0x5F + case DW_OP_reg16: // 0x60 + case DW_OP_reg17: // 0x61 + case DW_OP_reg18: // 0x62 + case DW_OP_reg19: // 0x63 + case DW_OP_reg20: // 0x64 + case DW_OP_reg21: // 0x65 + case DW_OP_reg22: // 0x66 + case DW_OP_reg23: // 0x67 + case DW_OP_reg24: // 0x68 + case DW_OP_reg25: // 0x69 + case DW_OP_reg26: // 0x6A + case DW_OP_reg27: // 0x6B + case DW_OP_reg28: // 0x6C + case DW_OP_reg29: // 0x6D + case DW_OP_reg30: // 0x6E + case DW_OP_reg31: // 0x6F + case DW_OP_nop: // 0x96 + case DW_OP_push_object_address: // 0x97 DWARF3 + case DW_OP_form_tls_address: // 0x9b DWARF3 + case DW_OP_call_frame_cfa: // 0x9c DWARF3 + case DW_OP_stack_value: // 0x9f DWARF4 + case DW_OP_GNU_push_tls_address: // 0xe0 GNU extension + return 0; + + // Opcodes with a single 1 byte arguments + case DW_OP_const1u: // 0x08 1 1-byte constant + case DW_OP_const1s: // 0x09 1 1-byte constant + case DW_OP_pick: // 0x15 1 1-byte stack index + case DW_OP_deref_size: // 0x94 1 1-byte size of data retrieved + case DW_OP_xderef_size: // 0x95 1 1-byte size of data retrieved + return 1; + + // Opcodes with a single 2 byte arguments + case DW_OP_const2u: // 0x0a 1 2-byte constant + case DW_OP_const2s: // 0x0b 1 2-byte constant + case DW_OP_skip: // 0x2f 1 signed 2-byte constant + case DW_OP_bra: // 0x28 1 signed 2-byte constant + case DW_OP_call2: // 0x98 1 2-byte offset of DIE (DWARF3) + return 2; + + // Opcodes with a single 4 byte arguments + case DW_OP_const4u: // 0x0c 1 4-byte constant + case DW_OP_const4s: // 0x0d 1 4-byte constant + case DW_OP_call4: // 0x99 1 4-byte offset of DIE (DWARF3) + return 4; + + // Opcodes with a single 8 byte arguments + case DW_OP_const8u: // 0x0e 1 8-byte constant + case DW_OP_const8s: // 0x0f 1 8-byte constant + return 8; + + // All opcodes that have a single ULEB (signed or unsigned) argument + case DW_OP_constu: // 0x10 1 ULEB128 constant + case DW_OP_consts: // 0x11 1 SLEB128 constant + case DW_OP_plus_uconst: // 0x23 1 ULEB128 addend + case DW_OP_breg0: // 0x70 1 ULEB128 register + case DW_OP_breg1: // 0x71 1 ULEB128 register + case DW_OP_breg2: // 0x72 1 ULEB128 register + case DW_OP_breg3: // 0x73 1 ULEB128 register + case DW_OP_breg4: // 0x74 1 ULEB128 register + case DW_OP_breg5: // 0x75 1 ULEB128 register + case DW_OP_breg6: // 0x76 1 ULEB128 register + case DW_OP_breg7: // 0x77 1 ULEB128 register + case DW_OP_breg8: // 0x78 1 ULEB128 register + case DW_OP_breg9: // 0x79 1 ULEB128 register + case DW_OP_breg10: // 0x7a 1 ULEB128 register + case DW_OP_breg11: // 0x7b 1 ULEB128 register + case DW_OP_breg12: // 0x7c 1 ULEB128 register + case DW_OP_breg13: // 0x7d 1 ULEB128 register + case DW_OP_breg14: // 0x7e 1 ULEB128 register + case DW_OP_breg15: // 0x7f 1 ULEB128 register + case DW_OP_breg16: // 0x80 1 ULEB128 register + case DW_OP_breg17: // 0x81 1 ULEB128 register + case DW_OP_breg18: // 0x82 1 ULEB128 register + case DW_OP_breg19: // 0x83 1 ULEB128 register + case DW_OP_breg20: // 0x84 1 ULEB128 register + case DW_OP_breg21: // 0x85 1 ULEB128 register + case DW_OP_breg22: // 0x86 1 ULEB128 register + case DW_OP_breg23: // 0x87 1 ULEB128 register + case DW_OP_breg24: // 0x88 1 ULEB128 register + case DW_OP_breg25: // 0x89 1 ULEB128 register + case DW_OP_breg26: // 0x8a 1 ULEB128 register + case DW_OP_breg27: // 0x8b 1 ULEB128 register + case DW_OP_breg28: // 0x8c 1 ULEB128 register + case DW_OP_breg29: // 0x8d 1 ULEB128 register + case DW_OP_breg30: // 0x8e 1 ULEB128 register + case DW_OP_breg31: // 0x8f 1 ULEB128 register + case DW_OP_regx: // 0x90 1 ULEB128 register + case DW_OP_fbreg: // 0x91 1 SLEB128 offset + case DW_OP_piece: // 0x93 1 ULEB128 size of piece addressed + case DW_OP_GNU_addr_index: // 0xfb 1 ULEB128 index + case DW_OP_GNU_const_index: // 0xfc 1 ULEB128 index + data.Skip_LEB128(&offset); + return offset - data_offset; + + // All opcodes that have a 2 ULEB (signed or unsigned) arguments + case DW_OP_bregx: // 0x92 2 ULEB128 register followed by SLEB128 offset + case DW_OP_bit_piece: // 0x9d ULEB128 bit size, ULEB128 bit offset (DWARF3); + data.Skip_LEB128(&offset); + data.Skip_LEB128(&offset); + return offset - data_offset; + + case DW_OP_implicit_value: // 0x9e ULEB128 size followed by block of that size + // (DWARF4) + { + uint64_t block_len = data.Skip_LEB128(&offset); + offset += block_len; + return offset - data_offset; + } + + default: + break; + } + return LLDB_INVALID_OFFSET; } -lldb::addr_t -DWARFExpression::GetLocation_DW_OP_addr (uint32_t op_addr_idx, bool &error) const -{ - error = false; - if (IsLocationList()) - return LLDB_INVALID_ADDRESS; - lldb::offset_t offset = 0; - uint32_t curr_op_addr_idx = 0; - while (m_data.ValidOffset(offset)) - { - const uint8_t op = m_data.GetU8(&offset); - - if (op == DW_OP_addr) - { - const lldb::addr_t op_file_addr = m_data.GetAddress(&offset); - if (curr_op_addr_idx == op_addr_idx) - return op_file_addr; - else - ++curr_op_addr_idx; +lldb::addr_t DWARFExpression::GetLocation_DW_OP_addr(uint32_t op_addr_idx, + bool &error) const { + error = false; + if (IsLocationList()) + return LLDB_INVALID_ADDRESS; + lldb::offset_t offset = 0; + uint32_t curr_op_addr_idx = 0; + while (m_data.ValidOffset(offset)) { + const uint8_t op = m_data.GetU8(&offset); + + if (op == DW_OP_addr) { + const lldb::addr_t op_file_addr = m_data.GetAddress(&offset); + if (curr_op_addr_idx == op_addr_idx) + return op_file_addr; + else + ++curr_op_addr_idx; + } else if (op == DW_OP_GNU_addr_index) { + uint64_t index = m_data.GetULEB128(&offset); + if (curr_op_addr_idx == op_addr_idx) { + if (!m_dwarf_cu) { + error = true; + break; } - else if (op == DW_OP_GNU_addr_index) - { - uint64_t index = m_data.GetULEB128(&offset); - if (curr_op_addr_idx == op_addr_idx) - { - if (!m_dwarf_cu) - { - error = true; - break; - } - return ReadAddressFromDebugAddrSection(m_dwarf_cu, index); - } - else - ++curr_op_addr_idx; - } - else - { - const offset_t op_arg_size = GetOpcodeDataSize (m_data, offset, op); - if (op_arg_size == LLDB_INVALID_OFFSET) - { - error = true; - break; - } - offset += op_arg_size; - } + return ReadAddressFromDebugAddrSection(m_dwarf_cu, index); + } else + ++curr_op_addr_idx; + } else { + const offset_t op_arg_size = GetOpcodeDataSize(m_data, offset, op); + if (op_arg_size == LLDB_INVALID_OFFSET) { + error = true; + break; + } + offset += op_arg_size; } - return LLDB_INVALID_ADDRESS; + } + return LLDB_INVALID_ADDRESS; } -bool -DWARFExpression::Update_DW_OP_addr (lldb::addr_t file_addr) -{ - if (IsLocationList()) +bool DWARFExpression::Update_DW_OP_addr(lldb::addr_t file_addr) { + if (IsLocationList()) + return false; + lldb::offset_t offset = 0; + while (m_data.ValidOffset(offset)) { + const uint8_t op = m_data.GetU8(&offset); + + if (op == DW_OP_addr) { + const uint32_t addr_byte_size = m_data.GetAddressByteSize(); + // We have to make a copy of the data as we don't know if this + // data is from a read only memory mapped buffer, so we duplicate + // all of the data first, then modify it, and if all goes well, + // we then replace the data for this expression + + // So first we copy the data into a heap buffer + std::unique_ptr<DataBufferHeap> head_data_ap( + new DataBufferHeap(m_data.GetDataStart(), m_data.GetByteSize())); + + // Make en encoder so we can write the address into the buffer using + // the correct byte order (endianness) + DataEncoder encoder(head_data_ap->GetBytes(), head_data_ap->GetByteSize(), + m_data.GetByteOrder(), addr_byte_size); + + // Replace the address in the new buffer + if (encoder.PutMaxU64(offset, addr_byte_size, file_addr) == UINT32_MAX) return false; - lldb::offset_t offset = 0; - while (m_data.ValidOffset(offset)) - { - const uint8_t op = m_data.GetU8(&offset); - - if (op == DW_OP_addr) - { - const uint32_t addr_byte_size = m_data.GetAddressByteSize(); - // We have to make a copy of the data as we don't know if this - // data is from a read only memory mapped buffer, so we duplicate - // all of the data first, then modify it, and if all goes well, - // we then replace the data for this expression - - // So first we copy the data into a heap buffer - std::unique_ptr<DataBufferHeap> head_data_ap (new DataBufferHeap (m_data.GetDataStart(), - m_data.GetByteSize())); - - // Make en encoder so we can write the address into the buffer using - // the correct byte order (endianness) - DataEncoder encoder (head_data_ap->GetBytes(), - head_data_ap->GetByteSize(), - m_data.GetByteOrder(), - addr_byte_size); - - // Replace the address in the new buffer - if (encoder.PutMaxU64 (offset, addr_byte_size, file_addr) == UINT32_MAX) - return false; - // All went well, so now we can reset the data using a shared - // pointer to the heap data so "m_data" will now correctly - // manage the heap data. - m_data.SetData (DataBufferSP (head_data_ap.release())); - return true; - } - else - { - const offset_t op_arg_size = GetOpcodeDataSize (m_data, offset, op); - if (op_arg_size == LLDB_INVALID_OFFSET) - break; - offset += op_arg_size; - } + // All went well, so now we can reset the data using a shared + // pointer to the heap data so "m_data" will now correctly + // manage the heap data. + m_data.SetData(DataBufferSP(head_data_ap.release())); + return true; + } else { + const offset_t op_arg_size = GetOpcodeDataSize(m_data, offset, op); + if (op_arg_size == LLDB_INVALID_OFFSET) + break; + offset += op_arg_size; } + } + return false; +} + +bool DWARFExpression::ContainsThreadLocalStorage() const { + // We are assuming for now that any thread local variable will not + // have a location list. This has been true for all thread local + // variables we have seen so far produced by any compiler. + if (IsLocationList()) return false; + lldb::offset_t offset = 0; + while (m_data.ValidOffset(offset)) { + const uint8_t op = m_data.GetU8(&offset); + + if (op == DW_OP_form_tls_address || op == DW_OP_GNU_push_tls_address) + return true; + const offset_t op_arg_size = GetOpcodeDataSize(m_data, offset, op); + if (op_arg_size == LLDB_INVALID_OFFSET) + return false; + else + offset += op_arg_size; + } + return false; } +bool DWARFExpression::LinkThreadLocalStorage( + lldb::ModuleSP new_module_sp, + std::function<lldb::addr_t(lldb::addr_t file_addr)> const + &link_address_callback) { + // We are assuming for now that any thread local variable will not + // have a location list. This has been true for all thread local + // variables we have seen so far produced by any compiler. + if (IsLocationList()) + return false; -bool -DWARFExpression::ContainsThreadLocalStorage() const -{ - // We are assuming for now that any thread local variable will not - // have a location list. This has been true for all thread local - // variables we have seen so far produced by any compiler. - if (IsLocationList()) - return false; - lldb::offset_t offset = 0; - while (m_data.ValidOffset(offset)) - { - const uint8_t op = m_data.GetU8(&offset); + const uint32_t addr_byte_size = m_data.GetAddressByteSize(); + // We have to make a copy of the data as we don't know if this + // data is from a read only memory mapped buffer, so we duplicate + // all of the data first, then modify it, and if all goes well, + // we then replace the data for this expression + + // So first we copy the data into a heap buffer + std::shared_ptr<DataBufferHeap> heap_data_sp( + new DataBufferHeap(m_data.GetDataStart(), m_data.GetByteSize())); + + // Make en encoder so we can write the address into the buffer using + // the correct byte order (endianness) + DataEncoder encoder(heap_data_sp->GetBytes(), heap_data_sp->GetByteSize(), + m_data.GetByteOrder(), addr_byte_size); + + lldb::offset_t offset = 0; + lldb::offset_t const_offset = 0; + lldb::addr_t const_value = 0; + size_t const_byte_size = 0; + while (m_data.ValidOffset(offset)) { + const uint8_t op = m_data.GetU8(&offset); + + bool decoded_data = false; + switch (op) { + case DW_OP_const4u: + // Remember the const offset in case we later have a + // DW_OP_form_tls_address + // or DW_OP_GNU_push_tls_address + const_offset = offset; + const_value = m_data.GetU32(&offset); + decoded_data = true; + const_byte_size = 4; + break; + + case DW_OP_const8u: + // Remember the const offset in case we later have a + // DW_OP_form_tls_address + // or DW_OP_GNU_push_tls_address + const_offset = offset; + const_value = m_data.GetU64(&offset); + decoded_data = true; + const_byte_size = 8; + break; + + case DW_OP_form_tls_address: + case DW_OP_GNU_push_tls_address: + // DW_OP_form_tls_address and DW_OP_GNU_push_tls_address must be preceded + // by + // a file address on the stack. We assume that DW_OP_const4u or + // DW_OP_const8u + // is used for these values, and we check that the last opcode we got + // before + // either of these was DW_OP_const4u or DW_OP_const8u. If so, then we can + // link + // the value accodingly. For Darwin, the value in the DW_OP_const4u or + // DW_OP_const8u is the file address of a structure that contains a + // function + // pointer, the pthread key and the offset into the data pointed to by the + // pthread key. So we must link this address and also set the module of + // this + // expression to the new_module_sp so we can resolve the file address + // correctly + if (const_byte_size > 0) { + lldb::addr_t linked_file_addr = link_address_callback(const_value); + if (linked_file_addr == LLDB_INVALID_ADDRESS) + return false; + // Replace the address in the new buffer + if (encoder.PutMaxU64(const_offset, const_byte_size, + linked_file_addr) == UINT32_MAX) + return false; + } + break; + + default: + const_offset = 0; + const_value = 0; + const_byte_size = 0; + break; + } - if (op == DW_OP_form_tls_address || op == DW_OP_GNU_push_tls_address) - return true; - const offset_t op_arg_size = GetOpcodeDataSize(m_data, offset, op); - if (op_arg_size == LLDB_INVALID_OFFSET) - return false; - else - offset += op_arg_size; + if (!decoded_data) { + const offset_t op_arg_size = GetOpcodeDataSize(m_data, offset, op); + if (op_arg_size == LLDB_INVALID_OFFSET) + return false; + else + offset += op_arg_size; } - return false; + } + + // If we linked the TLS address correctly, update the module so that when the + // expression + // is evaluated it can resolve the file address to a load address and read the + // TLS data + m_module_wp = new_module_sp; + m_data.SetData(heap_data_sp); + return true; } -bool -DWARFExpression::LinkThreadLocalStorage( - lldb::ModuleSP new_module_sp, std::function<lldb::addr_t(lldb::addr_t file_addr)> const &link_address_callback) -{ - // We are assuming for now that any thread local variable will not - // have a location list. This has been true for all thread local - // variables we have seen so far produced by any compiler. - if (IsLocationList()) - return false; - const uint32_t addr_byte_size = m_data.GetAddressByteSize(); - // We have to make a copy of the data as we don't know if this - // data is from a read only memory mapped buffer, so we duplicate - // all of the data first, then modify it, and if all goes well, - // we then replace the data for this expression +bool DWARFExpression::LocationListContainsAddress( + lldb::addr_t loclist_base_addr, lldb::addr_t addr) const { + if (addr == LLDB_INVALID_ADDRESS) + return false; - // So first we copy the data into a heap buffer - std::shared_ptr<DataBufferHeap> heap_data_sp(new DataBufferHeap(m_data.GetDataStart(), m_data.GetByteSize())); + if (IsLocationList()) { + lldb::offset_t offset = 0; - // Make en encoder so we can write the address into the buffer using - // the correct byte order (endianness) - DataEncoder encoder(heap_data_sp->GetBytes(), heap_data_sp->GetByteSize(), m_data.GetByteOrder(), addr_byte_size); + if (loclist_base_addr == LLDB_INVALID_ADDRESS) + return false; - lldb::offset_t offset = 0; - lldb::offset_t const_offset = 0; - lldb::addr_t const_value = 0; - size_t const_byte_size = 0; - while (m_data.ValidOffset(offset)) - { - const uint8_t op = m_data.GetU8(&offset); - - bool decoded_data = false; - switch (op) - { - case DW_OP_const4u: - // Remember the const offset in case we later have a DW_OP_form_tls_address - // or DW_OP_GNU_push_tls_address - const_offset = offset; - const_value = m_data.GetU32(&offset); - decoded_data = true; - const_byte_size = 4; - break; + while (m_data.ValidOffset(offset)) { + // We need to figure out what the value is for the location. + addr_t lo_pc = LLDB_INVALID_ADDRESS; + addr_t hi_pc = LLDB_INVALID_ADDRESS; + if (!AddressRangeForLocationListEntry(m_dwarf_cu, m_data, &offset, lo_pc, + hi_pc)) + break; - case DW_OP_const8u: - // Remember the const offset in case we later have a DW_OP_form_tls_address - // or DW_OP_GNU_push_tls_address - const_offset = offset; - const_value = m_data.GetU64(&offset); - decoded_data = true; - const_byte_size = 8; - break; + if (lo_pc == 0 && hi_pc == 0) + break; - case DW_OP_form_tls_address: - case DW_OP_GNU_push_tls_address: - // DW_OP_form_tls_address and DW_OP_GNU_push_tls_address must be preceded by - // a file address on the stack. We assume that DW_OP_const4u or DW_OP_const8u - // is used for these values, and we check that the last opcode we got before - // either of these was DW_OP_const4u or DW_OP_const8u. If so, then we can link - // the value accodingly. For Darwin, the value in the DW_OP_const4u or - // DW_OP_const8u is the file address of a structure that contains a function - // pointer, the pthread key and the offset into the data pointed to by the - // pthread key. So we must link this address and also set the module of this - // expression to the new_module_sp so we can resolve the file address correctly - if (const_byte_size > 0) - { - lldb::addr_t linked_file_addr = link_address_callback(const_value); - if (linked_file_addr == LLDB_INVALID_ADDRESS) - return false; - // Replace the address in the new buffer - if (encoder.PutMaxU64(const_offset, const_byte_size, linked_file_addr) == UINT32_MAX) - return false; - } - break; + lo_pc += loclist_base_addr - m_loclist_slide; + hi_pc += loclist_base_addr - m_loclist_slide; - default: - const_offset = 0; - const_value = 0; - const_byte_size = 0; - break; - } + if (lo_pc <= addr && addr < hi_pc) + return true; - if (!decoded_data) - { - const offset_t op_arg_size = GetOpcodeDataSize(m_data, offset, op); - if (op_arg_size == LLDB_INVALID_OFFSET) - return false; - else - offset += op_arg_size; - } + offset += m_data.GetU16(&offset); } - - // If we linked the TLS address correctly, update the module so that when the expression - // is evaluated it can resolve the file address to a load address and read the TLS data - m_module_wp = new_module_sp; - m_data.SetData(heap_data_sp); - return true; + } + return false; } -bool -DWARFExpression::LocationListContainsAddress(lldb::addr_t loclist_base_addr, lldb::addr_t addr) const -{ - if (addr == LLDB_INVALID_ADDRESS) - return false; - - if (IsLocationList()) - { - lldb::offset_t offset = 0; - - if (loclist_base_addr == LLDB_INVALID_ADDRESS) - return false; +bool DWARFExpression::GetLocation(addr_t base_addr, addr_t pc, + lldb::offset_t &offset, + lldb::offset_t &length) { + offset = 0; + if (!IsLocationList()) { + length = m_data.GetByteSize(); + return true; + } - while (m_data.ValidOffset(offset)) - { - // We need to figure out what the value is for the location. - addr_t lo_pc = LLDB_INVALID_ADDRESS; - addr_t hi_pc = LLDB_INVALID_ADDRESS; - if (!AddressRangeForLocationListEntry(m_dwarf_cu, m_data, &offset, lo_pc, hi_pc)) - break; + if (base_addr != LLDB_INVALID_ADDRESS && pc != LLDB_INVALID_ADDRESS) { + addr_t curr_base_addr = base_addr; - if (lo_pc == 0 && hi_pc == 0) - break; + while (m_data.ValidOffset(offset)) { + // We need to figure out what the value is for the location. + addr_t lo_pc = LLDB_INVALID_ADDRESS; + addr_t hi_pc = LLDB_INVALID_ADDRESS; + if (!AddressRangeForLocationListEntry(m_dwarf_cu, m_data, &offset, lo_pc, + hi_pc)) + break; - lo_pc += loclist_base_addr - m_loclist_slide; - hi_pc += loclist_base_addr - m_loclist_slide; + if (lo_pc == 0 && hi_pc == 0) + break; - if (lo_pc <= addr && addr < hi_pc) - return true; + lo_pc += curr_base_addr - m_loclist_slide; + hi_pc += curr_base_addr - m_loclist_slide; - offset += m_data.GetU16(&offset); - } - } - return false; -} + length = m_data.GetU16(&offset); -bool -DWARFExpression::GetLocation (addr_t base_addr, addr_t pc, lldb::offset_t &offset, lldb::offset_t &length) -{ - offset = 0; - if (!IsLocationList()) - { - length = m_data.GetByteSize(); + if (length > 0 && lo_pc <= pc && pc < hi_pc) return true; - } - - if (base_addr != LLDB_INVALID_ADDRESS && pc != LLDB_INVALID_ADDRESS) - { - addr_t curr_base_addr = base_addr; - - while (m_data.ValidOffset(offset)) - { - // We need to figure out what the value is for the location. - addr_t lo_pc = LLDB_INVALID_ADDRESS; - addr_t hi_pc = LLDB_INVALID_ADDRESS; - if (!AddressRangeForLocationListEntry(m_dwarf_cu, m_data, &offset, lo_pc, hi_pc)) - break; - - if (lo_pc == 0 && hi_pc == 0) - break; - lo_pc += curr_base_addr - m_loclist_slide; - hi_pc += curr_base_addr - m_loclist_slide; - - length = m_data.GetU16(&offset); - - if (length > 0 && lo_pc <= pc && pc < hi_pc) - return true; - - offset += length; - } + offset += length; } - offset = LLDB_INVALID_OFFSET; - length = 0; - return false; + } + offset = LLDB_INVALID_OFFSET; + length = 0; + return false; } -bool -DWARFExpression::DumpLocationForAddress (Stream *s, - lldb::DescriptionLevel level, - addr_t base_addr, - addr_t address, - ABI *abi) -{ - lldb::offset_t offset = 0; - lldb::offset_t length = 0; - - if (GetLocation (base_addr, address, offset, length)) - { - if (length > 0) - { - DumpLocation(s, offset, length, level, abi); - return true; - } +bool DWARFExpression::DumpLocationForAddress(Stream *s, + lldb::DescriptionLevel level, + addr_t base_addr, addr_t address, + ABI *abi) { + lldb::offset_t offset = 0; + lldb::offset_t length = 0; + + if (GetLocation(base_addr, address, offset, length)) { + if (length > 0) { + DumpLocation(s, offset, length, level, abi); + return true; } - return false; + } + return false; } -bool -DWARFExpression::Evaluate -( - ExecutionContextScope *exe_scope, - ClangExpressionVariableList *expr_locals, - ClangExpressionDeclMap *decl_map, - lldb::addr_t loclist_base_load_addr, - const Value* initial_value_ptr, - const Value* object_address_ptr, - Value& result, - Error *error_ptr -) const -{ - ExecutionContext exe_ctx (exe_scope); - return Evaluate(&exe_ctx, - expr_locals, - decl_map, - nullptr, - loclist_base_load_addr, - initial_value_ptr, - object_address_ptr, - result, - error_ptr); +bool DWARFExpression::Evaluate(ExecutionContextScope *exe_scope, + ClangExpressionVariableList *expr_locals, + ClangExpressionDeclMap *decl_map, + lldb::addr_t loclist_base_load_addr, + const Value *initial_value_ptr, + const Value *object_address_ptr, Value &result, + Error *error_ptr) const { + ExecutionContext exe_ctx(exe_scope); + return Evaluate(&exe_ctx, expr_locals, decl_map, nullptr, + loclist_base_load_addr, initial_value_ptr, object_address_ptr, + result, error_ptr); } -bool -DWARFExpression::Evaluate -( - ExecutionContext *exe_ctx, - ClangExpressionVariableList *expr_locals, - ClangExpressionDeclMap *decl_map, - RegisterContext *reg_ctx, - lldb::addr_t loclist_base_load_addr, - const Value* initial_value_ptr, - const Value* object_address_ptr, - Value& result, - Error *error_ptr -) const -{ - ModuleSP module_sp = m_module_wp.lock(); - - if (IsLocationList()) - { - lldb::offset_t offset = 0; - addr_t pc; - StackFrame *frame = NULL; - if (reg_ctx) - pc = reg_ctx->GetPC(); - else - { - frame = exe_ctx->GetFramePtr(); - if (!frame) - return false; - RegisterContextSP reg_ctx_sp = frame->GetRegisterContext(); - if (!reg_ctx_sp) - return false; - pc = reg_ctx_sp->GetPC(); - } - - if (loclist_base_load_addr != LLDB_INVALID_ADDRESS) - { - if (pc == LLDB_INVALID_ADDRESS) - { - if (error_ptr) - error_ptr->SetErrorString("Invalid PC in frame."); - return false; - } +bool DWARFExpression::Evaluate( + ExecutionContext *exe_ctx, ClangExpressionVariableList *expr_locals, + ClangExpressionDeclMap *decl_map, RegisterContext *reg_ctx, + lldb::addr_t loclist_base_load_addr, const Value *initial_value_ptr, + const Value *object_address_ptr, Value &result, Error *error_ptr) const { + ModuleSP module_sp = m_module_wp.lock(); - addr_t curr_loclist_base_load_addr = loclist_base_load_addr; - - while (m_data.ValidOffset(offset)) - { - // We need to figure out what the value is for the location. - addr_t lo_pc = LLDB_INVALID_ADDRESS; - addr_t hi_pc = LLDB_INVALID_ADDRESS; - if (!AddressRangeForLocationListEntry(m_dwarf_cu, m_data, &offset, lo_pc, hi_pc)) - break; - - if (lo_pc == 0 && hi_pc == 0) - break; - - lo_pc += curr_loclist_base_load_addr - m_loclist_slide; - hi_pc += curr_loclist_base_load_addr - m_loclist_slide; - - uint16_t length = m_data.GetU16(&offset); - - if (length > 0 && lo_pc <= pc && pc < hi_pc) - { - return DWARFExpression::Evaluate (exe_ctx, - expr_locals, - decl_map, - reg_ctx, - module_sp, - m_data, - m_dwarf_cu, - offset, - length, - m_reg_kind, - initial_value_ptr, - object_address_ptr, - result, - error_ptr); - } - offset += length; - } - } - if (error_ptr) - error_ptr->SetErrorString ("variable not available"); + if (IsLocationList()) { + lldb::offset_t offset = 0; + addr_t pc; + StackFrame *frame = NULL; + if (reg_ctx) + pc = reg_ctx->GetPC(); + else { + frame = exe_ctx->GetFramePtr(); + if (!frame) + return false; + RegisterContextSP reg_ctx_sp = frame->GetRegisterContext(); + if (!reg_ctx_sp) return false; + pc = reg_ctx_sp->GetPC(); } - // Not a location list, just a single expression. - return DWARFExpression::Evaluate (exe_ctx, - expr_locals, - decl_map, - reg_ctx, - module_sp, - m_data, - m_dwarf_cu, - 0, - m_data.GetByteSize(), - m_reg_kind, - initial_value_ptr, - object_address_ptr, - result, - error_ptr); -} - - - -bool -DWARFExpression::Evaluate -( - ExecutionContext *exe_ctx, - ClangExpressionVariableList *expr_locals, - ClangExpressionDeclMap *decl_map, - RegisterContext *reg_ctx, - lldb::ModuleSP module_sp, - const DataExtractor& opcodes, - DWARFCompileUnit* dwarf_cu, - const lldb::offset_t opcodes_offset, - const lldb::offset_t opcodes_length, - const lldb::RegisterKind reg_kind, - const Value* initial_value_ptr, - const Value* object_address_ptr, - Value& result, - Error *error_ptr -) -{ - - if (opcodes_length == 0) - { + if (loclist_base_load_addr != LLDB_INVALID_ADDRESS) { + if (pc == LLDB_INVALID_ADDRESS) { if (error_ptr) - error_ptr->SetErrorString ("no location, value may have been optimized out"); + error_ptr->SetErrorString("Invalid PC in frame."); return false; - } - std::vector<Value> stack; - - Process *process = NULL; - StackFrame *frame = NULL; - - if (exe_ctx) - { - process = exe_ctx->GetProcessPtr(); - frame = exe_ctx->GetFramePtr(); - } - if (reg_ctx == NULL && frame) - reg_ctx = frame->GetRegisterContext().get(); + } - if (initial_value_ptr) - stack.push_back(*initial_value_ptr); + addr_t curr_loclist_base_load_addr = loclist_base_load_addr; - lldb::offset_t offset = opcodes_offset; - const lldb::offset_t end_offset = opcodes_offset + opcodes_length; - Value tmp; - uint32_t reg_num; + while (m_data.ValidOffset(offset)) { + // We need to figure out what the value is for the location. + addr_t lo_pc = LLDB_INVALID_ADDRESS; + addr_t hi_pc = LLDB_INVALID_ADDRESS; + if (!AddressRangeForLocationListEntry(m_dwarf_cu, m_data, &offset, + lo_pc, hi_pc)) + break; - /// Insertion point for evaluating multi-piece expression. - uint64_t op_piece_offset = 0; - Value pieces; // Used for DW_OP_piece + if (lo_pc == 0 && hi_pc == 0) + break; - // Make sure all of the data is available in opcodes. - if (!opcodes.ValidOffsetForDataOfSize(opcodes_offset, opcodes_length)) - { - if (error_ptr) - error_ptr->SetErrorString ("invalid offset and/or length for opcodes buffer."); - return false; - } - Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS)); + lo_pc += curr_loclist_base_load_addr - m_loclist_slide; + hi_pc += curr_loclist_base_load_addr - m_loclist_slide; + uint16_t length = m_data.GetU16(&offset); - while (opcodes.ValidOffset(offset) && offset < end_offset) - { - const lldb::offset_t op_offset = offset; - const uint8_t op = opcodes.GetU8(&offset); - - if (log && log->GetVerbose()) - { - size_t count = stack.size(); - log->Printf("Stack before operation has %" PRIu64 " values:", (uint64_t)count); - for (size_t i=0; i<count; ++i) - { - StreamString new_value; - new_value.Printf("[%" PRIu64 "]", (uint64_t)i); - stack[i].Dump(&new_value); - log->Printf(" %s", new_value.GetData()); - } - log->Printf("0x%8.8" PRIx64 ": %s", op_offset, DW_OP_value_to_name(op)); + if (length > 0 && lo_pc <= pc && pc < hi_pc) { + return DWARFExpression::Evaluate( + exe_ctx, expr_locals, decl_map, reg_ctx, module_sp, m_data, + m_dwarf_cu, offset, length, m_reg_kind, initial_value_ptr, + object_address_ptr, result, error_ptr); } - switch (op) - { - //---------------------------------------------------------------------- - // The DW_OP_addr operation has a single operand that encodes a machine - // address and whose size is the size of an address on the target machine. - //---------------------------------------------------------------------- - case DW_OP_addr: - stack.push_back(Scalar(opcodes.GetAddress(&offset))); - stack.back().SetValueType (Value::eValueTypeFileAddress); - break; - - //---------------------------------------------------------------------- - // The DW_OP_addr_sect_offset4 is used for any location expressions in - // shared libraries that have a location like: - // DW_OP_addr(0x1000) - // If this address resides in a shared library, then this virtual - // address won't make sense when it is evaluated in the context of a - // running process where shared libraries have been slid. To account for - // this, this new address type where we can store the section pointer - // and a 4 byte offset. - //---------------------------------------------------------------------- -// case DW_OP_addr_sect_offset4: -// { -// result_type = eResultTypeFileAddress; -// lldb::Section *sect = (lldb::Section *)opcodes.GetMaxU64(&offset, sizeof(void *)); -// lldb::addr_t sect_offset = opcodes.GetU32(&offset); -// -// Address so_addr (sect, sect_offset); -// lldb::addr_t load_addr = so_addr.GetLoadAddress(); -// if (load_addr != LLDB_INVALID_ADDRESS) -// { -// // We successfully resolve a file address to a load -// // address. -// stack.push_back(load_addr); -// break; -// } -// else -// { -// // We were able -// if (error_ptr) -// error_ptr->SetErrorStringWithFormat ("Section %s in %s is not currently loaded.\n", sect->GetName().AsCString(), sect->GetModule()->GetFileSpec().GetFilename().AsCString()); -// return false; -// } -// } -// break; - - //---------------------------------------------------------------------- - // OPCODE: DW_OP_deref - // OPERANDS: none - // DESCRIPTION: Pops the top stack entry and treats it as an address. - // The value retrieved from that address is pushed. The size of the - // data retrieved from the dereferenced address is the size of an - // address on the target machine. - //---------------------------------------------------------------------- - case DW_OP_deref: - { - if (stack.empty()) - { - if (error_ptr) - error_ptr->SetErrorString("Expression stack empty for DW_OP_deref."); - return false; - } - Value::ValueType value_type = stack.back().GetValueType(); - switch (value_type) - { - case Value::eValueTypeHostAddress: - { - void *src = (void *)stack.back().GetScalar().ULongLong(); - intptr_t ptr; - ::memcpy (&ptr, src, sizeof(void *)); - stack.back().GetScalar() = ptr; - stack.back().ClearContext(); - } - break; - case Value::eValueTypeLoadAddress: - if (exe_ctx) - { - if (process) - { - lldb::addr_t pointer_addr = stack.back().GetScalar().ULongLong(LLDB_INVALID_ADDRESS); - Error error; - lldb::addr_t pointer_value = process->ReadPointerFromMemory(pointer_addr, error); - if (pointer_value != LLDB_INVALID_ADDRESS) - { - stack.back().GetScalar() = pointer_value; - stack.back().ClearContext(); - } - else - { - if (error_ptr) - error_ptr->SetErrorStringWithFormat ("Failed to dereference pointer from 0x%" PRIx64 " for DW_OP_deref: %s\n", - pointer_addr, - error.AsCString()); - return false; - } - } - else - { - if (error_ptr) - error_ptr->SetErrorStringWithFormat ("NULL process for DW_OP_deref.\n"); - return false; - } - } - else - { - if (error_ptr) - error_ptr->SetErrorStringWithFormat ("NULL execution context for DW_OP_deref.\n"); - return false; - } - break; - - default: - break; - } - - } - break; - - //---------------------------------------------------------------------- - // OPCODE: DW_OP_deref_size - // OPERANDS: 1 - // 1 - uint8_t that specifies the size of the data to dereference. - // DESCRIPTION: Behaves like the DW_OP_deref operation: it pops the top - // stack entry and treats it as an address. The value retrieved from that - // address is pushed. In the DW_OP_deref_size operation, however, the - // size in bytes of the data retrieved from the dereferenced address is - // specified by the single operand. This operand is a 1-byte unsigned - // integral constant whose value may not be larger than the size of an - // address on the target machine. The data retrieved is zero extended - // to the size of an address on the target machine before being pushed - // on the expression stack. - //---------------------------------------------------------------------- - case DW_OP_deref_size: - { - if (stack.empty()) - { - if (error_ptr) - error_ptr->SetErrorString("Expression stack empty for DW_OP_deref_size."); - return false; - } - uint8_t size = opcodes.GetU8(&offset); - Value::ValueType value_type = stack.back().GetValueType(); - switch (value_type) - { - case Value::eValueTypeHostAddress: - { - void *src = (void *)stack.back().GetScalar().ULongLong(); - intptr_t ptr; - ::memcpy (&ptr, src, sizeof(void *)); - // I can't decide whether the size operand should apply to the bytes in their - // lldb-host endianness or the target endianness.. I doubt this'll ever come up - // but I'll opt for assuming big endian regardless. - switch (size) - { - case 1: ptr = ptr & 0xff; break; - case 2: ptr = ptr & 0xffff; break; - case 3: ptr = ptr & 0xffffff; break; - case 4: ptr = ptr & 0xffffffff; break; - // the casts are added to work around the case where intptr_t is a 32 bit quantity; - // presumably we won't hit the 5..7 cases if (void*) is 32-bits in this program. - case 5: ptr = (intptr_t) ptr & 0xffffffffffULL; break; - case 6: ptr = (intptr_t) ptr & 0xffffffffffffULL; break; - case 7: ptr = (intptr_t) ptr & 0xffffffffffffffULL; break; - default: break; - } - stack.back().GetScalar() = ptr; - stack.back().ClearContext(); - } - break; - case Value::eValueTypeLoadAddress: - if (exe_ctx) - { - if (process) - { - lldb::addr_t pointer_addr = stack.back().GetScalar().ULongLong(LLDB_INVALID_ADDRESS); - uint8_t addr_bytes[sizeof(lldb::addr_t)]; - Error error; - if (process->ReadMemory(pointer_addr, &addr_bytes, size, error) == size) - { - DataExtractor addr_data(addr_bytes, sizeof(addr_bytes), process->GetByteOrder(), size); - lldb::offset_t addr_data_offset = 0; - switch (size) - { - case 1: stack.back().GetScalar() = addr_data.GetU8(&addr_data_offset); break; - case 2: stack.back().GetScalar() = addr_data.GetU16(&addr_data_offset); break; - case 4: stack.back().GetScalar() = addr_data.GetU32(&addr_data_offset); break; - case 8: stack.back().GetScalar() = addr_data.GetU64(&addr_data_offset); break; - default: stack.back().GetScalar() = addr_data.GetPointer(&addr_data_offset); - } - stack.back().ClearContext(); - } - else - { - if (error_ptr) - error_ptr->SetErrorStringWithFormat ("Failed to dereference pointer from 0x%" PRIx64 " for DW_OP_deref: %s\n", - pointer_addr, - error.AsCString()); - return false; - } - } - else - { - if (error_ptr) - error_ptr->SetErrorStringWithFormat ("NULL process for DW_OP_deref.\n"); - return false; - } - } - else - { - if (error_ptr) - error_ptr->SetErrorStringWithFormat ("NULL execution context for DW_OP_deref.\n"); - return false; - } - break; - - default: - break; - } + offset += length; + } + } + if (error_ptr) + error_ptr->SetErrorString("variable not available"); + return false; + } - } - break; + // Not a location list, just a single expression. + return DWARFExpression::Evaluate( + exe_ctx, expr_locals, decl_map, reg_ctx, module_sp, m_data, m_dwarf_cu, 0, + m_data.GetByteSize(), m_reg_kind, initial_value_ptr, object_address_ptr, + result, error_ptr); +} - //---------------------------------------------------------------------- - // OPCODE: DW_OP_xderef_size - // OPERANDS: 1 - // 1 - uint8_t that specifies the size of the data to dereference. - // DESCRIPTION: Behaves like the DW_OP_xderef operation: the entry at - // the top of the stack is treated as an address. The second stack - // entry is treated as an "address space identifier" for those - // architectures that support multiple address spaces. The top two - // stack elements are popped, a data item is retrieved through an - // implementation-defined address calculation and pushed as the new - // stack top. In the DW_OP_xderef_size operation, however, the size in - // bytes of the data retrieved from the dereferenced address is - // specified by the single operand. This operand is a 1-byte unsigned - // integral constant whose value may not be larger than the size of an - // address on the target machine. The data retrieved is zero extended - // to the size of an address on the target machine before being pushed - // on the expression stack. - //---------------------------------------------------------------------- - case DW_OP_xderef_size: +bool DWARFExpression::Evaluate( + ExecutionContext *exe_ctx, ClangExpressionVariableList *expr_locals, + ClangExpressionDeclMap *decl_map, RegisterContext *reg_ctx, + lldb::ModuleSP module_sp, const DataExtractor &opcodes, + DWARFCompileUnit *dwarf_cu, const lldb::offset_t opcodes_offset, + const lldb::offset_t opcodes_length, const lldb::RegisterKind reg_kind, + const Value *initial_value_ptr, const Value *object_address_ptr, + Value &result, Error *error_ptr) { + + if (opcodes_length == 0) { + if (error_ptr) + error_ptr->SetErrorString( + "no location, value may have been optimized out"); + return false; + } + std::vector<Value> stack; + + Process *process = NULL; + StackFrame *frame = NULL; + + if (exe_ctx) { + process = exe_ctx->GetProcessPtr(); + frame = exe_ctx->GetFramePtr(); + } + if (reg_ctx == NULL && frame) + reg_ctx = frame->GetRegisterContext().get(); + + if (initial_value_ptr) + stack.push_back(*initial_value_ptr); + + lldb::offset_t offset = opcodes_offset; + const lldb::offset_t end_offset = opcodes_offset + opcodes_length; + Value tmp; + uint32_t reg_num; + + /// Insertion point for evaluating multi-piece expression. + uint64_t op_piece_offset = 0; + Value pieces; // Used for DW_OP_piece + + // Make sure all of the data is available in opcodes. + if (!opcodes.ValidOffsetForDataOfSize(opcodes_offset, opcodes_length)) { + if (error_ptr) + error_ptr->SetErrorString( + "invalid offset and/or length for opcodes buffer."); + return false; + } + Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS)); + + while (opcodes.ValidOffset(offset) && offset < end_offset) { + const lldb::offset_t op_offset = offset; + const uint8_t op = opcodes.GetU8(&offset); + + if (log && log->GetVerbose()) { + size_t count = stack.size(); + log->Printf("Stack before operation has %" PRIu64 " values:", + (uint64_t)count); + for (size_t i = 0; i < count; ++i) { + StreamString new_value; + new_value.Printf("[%" PRIu64 "]", (uint64_t)i); + stack[i].Dump(&new_value); + log->Printf(" %s", new_value.GetData()); + } + log->Printf("0x%8.8" PRIx64 ": %s", op_offset, DW_OP_value_to_name(op)); + } + switch (op) { + //---------------------------------------------------------------------- + // The DW_OP_addr operation has a single operand that encodes a machine + // address and whose size is the size of an address on the target machine. + //---------------------------------------------------------------------- + case DW_OP_addr: + stack.push_back(Scalar(opcodes.GetAddress(&offset))); + stack.back().SetValueType(Value::eValueTypeFileAddress); + break; + + //---------------------------------------------------------------------- + // The DW_OP_addr_sect_offset4 is used for any location expressions in + // shared libraries that have a location like: + // DW_OP_addr(0x1000) + // If this address resides in a shared library, then this virtual + // address won't make sense when it is evaluated in the context of a + // running process where shared libraries have been slid. To account for + // this, this new address type where we can store the section pointer + // and a 4 byte offset. + //---------------------------------------------------------------------- + // case DW_OP_addr_sect_offset4: + // { + // result_type = eResultTypeFileAddress; + // lldb::Section *sect = (lldb::Section + // *)opcodes.GetMaxU64(&offset, sizeof(void *)); + // lldb::addr_t sect_offset = opcodes.GetU32(&offset); + // + // Address so_addr (sect, sect_offset); + // lldb::addr_t load_addr = so_addr.GetLoadAddress(); + // if (load_addr != LLDB_INVALID_ADDRESS) + // { + // // We successfully resolve a file address to a load + // // address. + // stack.push_back(load_addr); + // break; + // } + // else + // { + // // We were able + // if (error_ptr) + // error_ptr->SetErrorStringWithFormat ("Section %s in + // %s is not currently loaded.\n", + // sect->GetName().AsCString(), + // sect->GetModule()->GetFileSpec().GetFilename().AsCString()); + // return false; + // } + // } + // break; + + //---------------------------------------------------------------------- + // OPCODE: DW_OP_deref + // OPERANDS: none + // DESCRIPTION: Pops the top stack entry and treats it as an address. + // The value retrieved from that address is pushed. The size of the + // data retrieved from the dereferenced address is the size of an + // address on the target machine. + //---------------------------------------------------------------------- + case DW_OP_deref: { + if (stack.empty()) { + if (error_ptr) + error_ptr->SetErrorString("Expression stack empty for DW_OP_deref."); + return false; + } + Value::ValueType value_type = stack.back().GetValueType(); + switch (value_type) { + case Value::eValueTypeHostAddress: { + void *src = (void *)stack.back().GetScalar().ULongLong(); + intptr_t ptr; + ::memcpy(&ptr, src, sizeof(void *)); + stack.back().GetScalar() = ptr; + stack.back().ClearContext(); + } break; + case Value::eValueTypeLoadAddress: + if (exe_ctx) { + if (process) { + lldb::addr_t pointer_addr = + stack.back().GetScalar().ULongLong(LLDB_INVALID_ADDRESS); + Error error; + lldb::addr_t pointer_value = + process->ReadPointerFromMemory(pointer_addr, error); + if (pointer_value != LLDB_INVALID_ADDRESS) { + stack.back().GetScalar() = pointer_value; + stack.back().ClearContext(); + } else { + if (error_ptr) + error_ptr->SetErrorStringWithFormat( + "Failed to dereference pointer from 0x%" PRIx64 + " for DW_OP_deref: %s\n", + pointer_addr, error.AsCString()); + return false; + } + } else { if (error_ptr) - error_ptr->SetErrorString("Unimplemented opcode: DW_OP_xderef_size."); + error_ptr->SetErrorStringWithFormat( + "NULL process for DW_OP_deref.\n"); return false; - //---------------------------------------------------------------------- - // OPCODE: DW_OP_xderef - // OPERANDS: none - // DESCRIPTION: Provides an extended dereference mechanism. The entry at - // the top of the stack is treated as an address. The second stack entry - // is treated as an "address space identifier" for those architectures - // that support multiple address spaces. The top two stack elements are - // popped, a data item is retrieved through an implementation-defined - // address calculation and pushed as the new stack top. The size of the - // data retrieved from the dereferenced address is the size of an address - // on the target machine. - //---------------------------------------------------------------------- - case DW_OP_xderef: + } + } else { + if (error_ptr) + error_ptr->SetErrorStringWithFormat( + "NULL execution context for DW_OP_deref.\n"); + return false; + } + break; + + default: + break; + } + + } break; + + //---------------------------------------------------------------------- + // OPCODE: DW_OP_deref_size + // OPERANDS: 1 + // 1 - uint8_t that specifies the size of the data to dereference. + // DESCRIPTION: Behaves like the DW_OP_deref operation: it pops the top + // stack entry and treats it as an address. The value retrieved from that + // address is pushed. In the DW_OP_deref_size operation, however, the + // size in bytes of the data retrieved from the dereferenced address is + // specified by the single operand. This operand is a 1-byte unsigned + // integral constant whose value may not be larger than the size of an + // address on the target machine. The data retrieved is zero extended + // to the size of an address on the target machine before being pushed + // on the expression stack. + //---------------------------------------------------------------------- + case DW_OP_deref_size: { + if (stack.empty()) { + if (error_ptr) + error_ptr->SetErrorString( + "Expression stack empty for DW_OP_deref_size."); + return false; + } + uint8_t size = opcodes.GetU8(&offset); + Value::ValueType value_type = stack.back().GetValueType(); + switch (value_type) { + case Value::eValueTypeHostAddress: { + void *src = (void *)stack.back().GetScalar().ULongLong(); + intptr_t ptr; + ::memcpy(&ptr, src, sizeof(void *)); + // I can't decide whether the size operand should apply to the bytes in + // their + // lldb-host endianness or the target endianness.. I doubt this'll ever + // come up + // but I'll opt for assuming big endian regardless. + switch (size) { + case 1: + ptr = ptr & 0xff; + break; + case 2: + ptr = ptr & 0xffff; + break; + case 3: + ptr = ptr & 0xffffff; + break; + case 4: + ptr = ptr & 0xffffffff; + break; + // the casts are added to work around the case where intptr_t is a 32 + // bit quantity; + // presumably we won't hit the 5..7 cases if (void*) is 32-bits in this + // program. + case 5: + ptr = (intptr_t)ptr & 0xffffffffffULL; + break; + case 6: + ptr = (intptr_t)ptr & 0xffffffffffffULL; + break; + case 7: + ptr = (intptr_t)ptr & 0xffffffffffffffULL; + break; + default: + break; + } + stack.back().GetScalar() = ptr; + stack.back().ClearContext(); + } break; + case Value::eValueTypeLoadAddress: + if (exe_ctx) { + if (process) { + lldb::addr_t pointer_addr = + stack.back().GetScalar().ULongLong(LLDB_INVALID_ADDRESS); + uint8_t addr_bytes[sizeof(lldb::addr_t)]; + Error error; + if (process->ReadMemory(pointer_addr, &addr_bytes, size, error) == + size) { + DataExtractor addr_data(addr_bytes, sizeof(addr_bytes), + process->GetByteOrder(), size); + lldb::offset_t addr_data_offset = 0; + switch (size) { + case 1: + stack.back().GetScalar() = addr_data.GetU8(&addr_data_offset); + break; + case 2: + stack.back().GetScalar() = addr_data.GetU16(&addr_data_offset); + break; + case 4: + stack.back().GetScalar() = addr_data.GetU32(&addr_data_offset); + break; + case 8: + stack.back().GetScalar() = addr_data.GetU64(&addr_data_offset); + break; + default: + stack.back().GetScalar() = + addr_data.GetPointer(&addr_data_offset); + } + stack.back().ClearContext(); + } else { + if (error_ptr) + error_ptr->SetErrorStringWithFormat( + "Failed to dereference pointer from 0x%" PRIx64 + " for DW_OP_deref: %s\n", + pointer_addr, error.AsCString()); + return false; + } + } else { if (error_ptr) - error_ptr->SetErrorString("Unimplemented opcode: DW_OP_xderef."); + error_ptr->SetErrorStringWithFormat( + "NULL process for DW_OP_deref.\n"); return false; - - //---------------------------------------------------------------------- - // All DW_OP_constXXX opcodes have a single operand as noted below: - // - // Opcode Operand 1 - // --------------- ---------------------------------------------------- - // DW_OP_const1u 1-byte unsigned integer constant - // DW_OP_const1s 1-byte signed integer constant - // DW_OP_const2u 2-byte unsigned integer constant - // DW_OP_const2s 2-byte signed integer constant - // DW_OP_const4u 4-byte unsigned integer constant - // DW_OP_const4s 4-byte signed integer constant - // DW_OP_const8u 8-byte unsigned integer constant - // DW_OP_const8s 8-byte signed integer constant - // DW_OP_constu unsigned LEB128 integer constant - // DW_OP_consts signed LEB128 integer constant - //---------------------------------------------------------------------- - case DW_OP_const1u : stack.push_back(Scalar(( uint8_t)opcodes.GetU8 (&offset))); break; - case DW_OP_const1s : stack.push_back(Scalar(( int8_t)opcodes.GetU8 (&offset))); break; - case DW_OP_const2u : stack.push_back(Scalar((uint16_t)opcodes.GetU16 (&offset))); break; - case DW_OP_const2s : stack.push_back(Scalar(( int16_t)opcodes.GetU16 (&offset))); break; - case DW_OP_const4u : stack.push_back(Scalar((uint32_t)opcodes.GetU32 (&offset))); break; - case DW_OP_const4s : stack.push_back(Scalar(( int32_t)opcodes.GetU32 (&offset))); break; - case DW_OP_const8u : stack.push_back(Scalar((uint64_t)opcodes.GetU64 (&offset))); break; - case DW_OP_const8s : stack.push_back(Scalar(( int64_t)opcodes.GetU64 (&offset))); break; - case DW_OP_constu : stack.push_back(Scalar(opcodes.GetULEB128 (&offset))); break; - case DW_OP_consts : stack.push_back(Scalar(opcodes.GetSLEB128 (&offset))); break; - - //---------------------------------------------------------------------- - // OPCODE: DW_OP_dup - // OPERANDS: none - // DESCRIPTION: duplicates the value at the top of the stack - //---------------------------------------------------------------------- - case DW_OP_dup: - if (stack.empty()) - { - if (error_ptr) - error_ptr->SetErrorString("Expression stack empty for DW_OP_dup."); - return false; - } - else - stack.push_back(stack.back()); - break; - - //---------------------------------------------------------------------- - // OPCODE: DW_OP_drop - // OPERANDS: none - // DESCRIPTION: pops the value at the top of the stack - //---------------------------------------------------------------------- - case DW_OP_drop: - if (stack.empty()) - { - if (error_ptr) - error_ptr->SetErrorString("Expression stack empty for DW_OP_drop."); - return false; - } - else - stack.pop_back(); - break; - - //---------------------------------------------------------------------- - // OPCODE: DW_OP_over - // OPERANDS: none - // DESCRIPTION: Duplicates the entry currently second in the stack at - // the top of the stack. - //---------------------------------------------------------------------- - case DW_OP_over: - if (stack.size() < 2) - { - if (error_ptr) - error_ptr->SetErrorString("Expression stack needs at least 2 items for DW_OP_over."); - return false; - } - else - stack.push_back(stack[stack.size() - 2]); - break; - - - //---------------------------------------------------------------------- - // OPCODE: DW_OP_pick - // OPERANDS: uint8_t index into the current stack - // DESCRIPTION: The stack entry with the specified index (0 through 255, - // inclusive) is pushed on the stack - //---------------------------------------------------------------------- - case DW_OP_pick: - { - uint8_t pick_idx = opcodes.GetU8(&offset); - if (pick_idx < stack.size()) - stack.push_back(stack[pick_idx]); - else - { - if (error_ptr) - error_ptr->SetErrorStringWithFormat("Index %u out of range for DW_OP_pick.\n", pick_idx); - return false; - } - } - break; - - //---------------------------------------------------------------------- - // OPCODE: DW_OP_swap - // OPERANDS: none - // DESCRIPTION: swaps the top two stack entries. The entry at the top - // of the stack becomes the second stack entry, and the second entry - // becomes the top of the stack - //---------------------------------------------------------------------- - case DW_OP_swap: - if (stack.size() < 2) - { - if (error_ptr) - error_ptr->SetErrorString("Expression stack needs at least 2 items for DW_OP_swap."); - return false; - } - else - { - tmp = stack.back(); - stack.back() = stack[stack.size() - 2]; - stack[stack.size() - 2] = tmp; - } - break; - - //---------------------------------------------------------------------- - // OPCODE: DW_OP_rot - // OPERANDS: none - // DESCRIPTION: Rotates the first three stack entries. The entry at - // the top of the stack becomes the third stack entry, the second - // entry becomes the top of the stack, and the third entry becomes - // the second entry. - //---------------------------------------------------------------------- - case DW_OP_rot: - if (stack.size() < 3) - { - if (error_ptr) - error_ptr->SetErrorString("Expression stack needs at least 3 items for DW_OP_rot."); - return false; - } - else - { - size_t last_idx = stack.size() - 1; - Value old_top = stack[last_idx]; - stack[last_idx] = stack[last_idx - 1]; - stack[last_idx - 1] = stack[last_idx - 2]; - stack[last_idx - 2] = old_top; - } - break; - - //---------------------------------------------------------------------- - // OPCODE: DW_OP_abs - // OPERANDS: none - // DESCRIPTION: pops the top stack entry, interprets it as a signed - // value and pushes its absolute value. If the absolute value can not be - // represented, the result is undefined. - //---------------------------------------------------------------------- - case DW_OP_abs: - if (stack.empty()) - { - if (error_ptr) - error_ptr->SetErrorString("Expression stack needs at least 1 item for DW_OP_abs."); - return false; - } - else if (stack.back().ResolveValue(exe_ctx).AbsoluteValue() == false) - { - if (error_ptr) - error_ptr->SetErrorString("Failed to take the absolute value of the first stack item."); - return false; - } - break; - - //---------------------------------------------------------------------- - // OPCODE: DW_OP_and - // OPERANDS: none - // DESCRIPTION: pops the top two stack values, performs a bitwise and - // operation on the two, and pushes the result. - //---------------------------------------------------------------------- - case DW_OP_and: - if (stack.size() < 2) - { - if (error_ptr) - error_ptr->SetErrorString("Expression stack needs at least 2 items for DW_OP_and."); - return false; - } - else - { - tmp = stack.back(); - stack.pop_back(); - stack.back().ResolveValue(exe_ctx) = stack.back().ResolveValue(exe_ctx) & tmp.ResolveValue(exe_ctx); - } - break; - - //---------------------------------------------------------------------- - // OPCODE: DW_OP_div - // OPERANDS: none - // DESCRIPTION: pops the top two stack values, divides the former second - // entry by the former top of the stack using signed division, and - // pushes the result. - //---------------------------------------------------------------------- - case DW_OP_div: - if (stack.size() < 2) - { - if (error_ptr) - error_ptr->SetErrorString("Expression stack needs at least 2 items for DW_OP_div."); - return false; - } - else - { - tmp = stack.back(); - if (tmp.ResolveValue(exe_ctx).IsZero()) - { - if (error_ptr) - error_ptr->SetErrorString("Divide by zero."); - return false; - } - else - { - stack.pop_back(); - stack.back() = stack.back().ResolveValue(exe_ctx) / tmp.ResolveValue(exe_ctx); - if (!stack.back().ResolveValue(exe_ctx).IsValid()) - { - if (error_ptr) - error_ptr->SetErrorString("Divide failed."); - return false; - } - } - } - break; - - //---------------------------------------------------------------------- - // OPCODE: DW_OP_minus - // OPERANDS: none - // DESCRIPTION: pops the top two stack values, subtracts the former top - // of the stack from the former second entry, and pushes the result. - //---------------------------------------------------------------------- - case DW_OP_minus: - if (stack.size() < 2) - { - if (error_ptr) - error_ptr->SetErrorString("Expression stack needs at least 2 items for DW_OP_minus."); - return false; - } - else - { - tmp = stack.back(); - stack.pop_back(); - stack.back().ResolveValue(exe_ctx) = stack.back().ResolveValue(exe_ctx) - tmp.ResolveValue(exe_ctx); - } - break; - - //---------------------------------------------------------------------- - // OPCODE: DW_OP_mod - // OPERANDS: none - // DESCRIPTION: pops the top two stack values and pushes the result of - // the calculation: former second stack entry modulo the former top of - // the stack. - //---------------------------------------------------------------------- - case DW_OP_mod: - if (stack.size() < 2) - { - if (error_ptr) - error_ptr->SetErrorString("Expression stack needs at least 2 items for DW_OP_mod."); - return false; - } - else - { - tmp = stack.back(); - stack.pop_back(); - stack.back().ResolveValue(exe_ctx) = stack.back().ResolveValue(exe_ctx) % tmp.ResolveValue(exe_ctx); - } - break; - - - //---------------------------------------------------------------------- - // OPCODE: DW_OP_mul - // OPERANDS: none - // DESCRIPTION: pops the top two stack entries, multiplies them - // together, and pushes the result. - //---------------------------------------------------------------------- - case DW_OP_mul: - if (stack.size() < 2) - { - if (error_ptr) - error_ptr->SetErrorString("Expression stack needs at least 2 items for DW_OP_mul."); - return false; - } - else - { - tmp = stack.back(); - stack.pop_back(); - stack.back().ResolveValue(exe_ctx) = stack.back().ResolveValue(exe_ctx) * tmp.ResolveValue(exe_ctx); - } - break; - - //---------------------------------------------------------------------- - // OPCODE: DW_OP_neg - // OPERANDS: none - // DESCRIPTION: pops the top stack entry, and pushes its negation. - //---------------------------------------------------------------------- - case DW_OP_neg: - if (stack.empty()) - { - if (error_ptr) - error_ptr->SetErrorString("Expression stack needs at least 1 item for DW_OP_neg."); - return false; - } - else - { - if (stack.back().ResolveValue(exe_ctx).UnaryNegate() == false) - { - if (error_ptr) - error_ptr->SetErrorString("Unary negate failed."); - return false; - } - } - break; - - //---------------------------------------------------------------------- - // OPCODE: DW_OP_not - // OPERANDS: none - // DESCRIPTION: pops the top stack entry, and pushes its bitwise - // complement - //---------------------------------------------------------------------- - case DW_OP_not: - if (stack.empty()) - { - if (error_ptr) - error_ptr->SetErrorString("Expression stack needs at least 1 item for DW_OP_not."); - return false; - } - else - { - if (stack.back().ResolveValue(exe_ctx).OnesComplement() == false) - { - if (error_ptr) - error_ptr->SetErrorString("Logical NOT failed."); - return false; - } - } - break; - - //---------------------------------------------------------------------- - // OPCODE: DW_OP_or - // OPERANDS: none - // DESCRIPTION: pops the top two stack entries, performs a bitwise or - // operation on the two, and pushes the result. - //---------------------------------------------------------------------- - case DW_OP_or: - if (stack.size() < 2) - { - if (error_ptr) - error_ptr->SetErrorString("Expression stack needs at least 2 items for DW_OP_or."); - return false; - } - else - { - tmp = stack.back(); - stack.pop_back(); - stack.back().ResolveValue(exe_ctx) = stack.back().ResolveValue(exe_ctx) | tmp.ResolveValue(exe_ctx); - } - break; - - //---------------------------------------------------------------------- - // OPCODE: DW_OP_plus - // OPERANDS: none - // DESCRIPTION: pops the top two stack entries, adds them together, and - // pushes the result. - //---------------------------------------------------------------------- - case DW_OP_plus: - if (stack.size() < 2) - { - if (error_ptr) - error_ptr->SetErrorString("Expression stack needs at least 2 items for DW_OP_plus."); - return false; - } - else - { - tmp = stack.back(); - stack.pop_back(); - stack.back().GetScalar() += tmp.GetScalar(); - } - break; - - //---------------------------------------------------------------------- - // OPCODE: DW_OP_plus_uconst - // OPERANDS: none - // DESCRIPTION: pops the top stack entry, adds it to the unsigned LEB128 - // constant operand and pushes the result. - //---------------------------------------------------------------------- - case DW_OP_plus_uconst: - if (stack.empty()) - { - if (error_ptr) - error_ptr->SetErrorString("Expression stack needs at least 1 item for DW_OP_plus_uconst."); - return false; - } - else - { - const uint64_t uconst_value = opcodes.GetULEB128(&offset); - // Implicit conversion from a UINT to a Scalar... - stack.back().GetScalar() += uconst_value; - if (!stack.back().GetScalar().IsValid()) - { - if (error_ptr) - error_ptr->SetErrorString("DW_OP_plus_uconst failed."); - return false; - } - } - break; - - //---------------------------------------------------------------------- - // OPCODE: DW_OP_shl - // OPERANDS: none - // DESCRIPTION: pops the top two stack entries, shifts the former - // second entry left by the number of bits specified by the former top - // of the stack, and pushes the result. - //---------------------------------------------------------------------- - case DW_OP_shl: - if (stack.size() < 2) - { - if (error_ptr) - error_ptr->SetErrorString("Expression stack needs at least 2 items for DW_OP_shl."); - return false; - } - else - { - tmp = stack.back(); - stack.pop_back(); - stack.back().ResolveValue(exe_ctx) <<= tmp.ResolveValue(exe_ctx); - } - break; - - //---------------------------------------------------------------------- - // OPCODE: DW_OP_shr - // OPERANDS: none - // DESCRIPTION: pops the top two stack entries, shifts the former second - // entry right logically (filling with zero bits) by the number of bits - // specified by the former top of the stack, and pushes the result. - //---------------------------------------------------------------------- - case DW_OP_shr: - if (stack.size() < 2) - { - if (error_ptr) - error_ptr->SetErrorString("Expression stack needs at least 2 items for DW_OP_shr."); - return false; - } - else - { - tmp = stack.back(); - stack.pop_back(); - if (stack.back().ResolveValue(exe_ctx).ShiftRightLogical(tmp.ResolveValue(exe_ctx)) == false) - { - if (error_ptr) - error_ptr->SetErrorString("DW_OP_shr failed."); - return false; - } - } - break; - - //---------------------------------------------------------------------- - // OPCODE: DW_OP_shra - // OPERANDS: none - // DESCRIPTION: pops the top two stack entries, shifts the former second - // entry right arithmetically (divide the magnitude by 2, keep the same - // sign for the result) by the number of bits specified by the former - // top of the stack, and pushes the result. - //---------------------------------------------------------------------- - case DW_OP_shra: - if (stack.size() < 2) - { - if (error_ptr) - error_ptr->SetErrorString("Expression stack needs at least 2 items for DW_OP_shra."); - return false; - } - else - { - tmp = stack.back(); - stack.pop_back(); - stack.back().ResolveValue(exe_ctx) >>= tmp.ResolveValue(exe_ctx); - } - break; - - //---------------------------------------------------------------------- - // OPCODE: DW_OP_xor - // OPERANDS: none - // DESCRIPTION: pops the top two stack entries, performs the bitwise - // exclusive-or operation on the two, and pushes the result. - //---------------------------------------------------------------------- - case DW_OP_xor: - if (stack.size() < 2) - { - if (error_ptr) - error_ptr->SetErrorString("Expression stack needs at least 2 items for DW_OP_xor."); - return false; - } - else - { - tmp = stack.back(); - stack.pop_back(); - stack.back().ResolveValue(exe_ctx) = stack.back().ResolveValue(exe_ctx) ^ tmp.ResolveValue(exe_ctx); - } - break; - - - //---------------------------------------------------------------------- - // OPCODE: DW_OP_skip - // OPERANDS: int16_t - // DESCRIPTION: An unconditional branch. Its single operand is a 2-byte - // signed integer constant. The 2-byte constant is the number of bytes - // of the DWARF expression to skip forward or backward from the current - // operation, beginning after the 2-byte constant. - //---------------------------------------------------------------------- - case DW_OP_skip: - { - int16_t skip_offset = (int16_t)opcodes.GetU16(&offset); - lldb::offset_t new_offset = offset + skip_offset; - if (new_offset >= opcodes_offset && new_offset < end_offset) - offset = new_offset; - else - { - if (error_ptr) - error_ptr->SetErrorString("Invalid opcode offset in DW_OP_skip."); - return false; - } - } - break; - - //---------------------------------------------------------------------- - // OPCODE: DW_OP_bra - // OPERANDS: int16_t - // DESCRIPTION: A conditional branch. Its single operand is a 2-byte - // signed integer constant. This operation pops the top of stack. If - // the value popped is not the constant 0, the 2-byte constant operand - // is the number of bytes of the DWARF expression to skip forward or - // backward from the current operation, beginning after the 2-byte - // constant. - //---------------------------------------------------------------------- - case DW_OP_bra: - if (stack.empty()) - { - if (error_ptr) - error_ptr->SetErrorString("Expression stack needs at least 1 item for DW_OP_bra."); - return false; - } - else - { - tmp = stack.back(); - stack.pop_back(); - int16_t bra_offset = (int16_t)opcodes.GetU16(&offset); - Scalar zero(0); - if (tmp.ResolveValue(exe_ctx) != zero) - { - lldb::offset_t new_offset = offset + bra_offset; - if (new_offset >= opcodes_offset && new_offset < end_offset) - offset = new_offset; - else - { - if (error_ptr) - error_ptr->SetErrorString("Invalid opcode offset in DW_OP_bra."); - return false; - } - } - } - break; - - //---------------------------------------------------------------------- - // OPCODE: DW_OP_eq - // OPERANDS: none - // DESCRIPTION: pops the top two stack values, compares using the - // equals (==) operator. - // STACK RESULT: push the constant value 1 onto the stack if the result - // of the operation is true or the constant value 0 if the result of the - // operation is false. - //---------------------------------------------------------------------- - case DW_OP_eq: - if (stack.size() < 2) - { - if (error_ptr) - error_ptr->SetErrorString("Expression stack needs at least 2 items for DW_OP_eq."); - return false; - } - else - { - tmp = stack.back(); - stack.pop_back(); - stack.back().ResolveValue(exe_ctx) = stack.back().ResolveValue(exe_ctx) == tmp.ResolveValue(exe_ctx); - } - break; - - //---------------------------------------------------------------------- - // OPCODE: DW_OP_ge - // OPERANDS: none - // DESCRIPTION: pops the top two stack values, compares using the - // greater than or equal to (>=) operator. - // STACK RESULT: push the constant value 1 onto the stack if the result - // of the operation is true or the constant value 0 if the result of the - // operation is false. - //---------------------------------------------------------------------- - case DW_OP_ge: - if (stack.size() < 2) - { - if (error_ptr) - error_ptr->SetErrorString("Expression stack needs at least 2 items for DW_OP_ge."); - return false; - } - else - { - tmp = stack.back(); - stack.pop_back(); - stack.back().ResolveValue(exe_ctx) = stack.back().ResolveValue(exe_ctx) >= tmp.ResolveValue(exe_ctx); - } - break; - - //---------------------------------------------------------------------- - // OPCODE: DW_OP_gt - // OPERANDS: none - // DESCRIPTION: pops the top two stack values, compares using the - // greater than (>) operator. - // STACK RESULT: push the constant value 1 onto the stack if the result - // of the operation is true or the constant value 0 if the result of the - // operation is false. - //---------------------------------------------------------------------- - case DW_OP_gt: - if (stack.size() < 2) - { - if (error_ptr) - error_ptr->SetErrorString("Expression stack needs at least 2 items for DW_OP_gt."); - return false; - } - else - { - tmp = stack.back(); - stack.pop_back(); - stack.back().ResolveValue(exe_ctx) = stack.back().ResolveValue(exe_ctx) > tmp.ResolveValue(exe_ctx); - } - break; - - //---------------------------------------------------------------------- - // OPCODE: DW_OP_le - // OPERANDS: none - // DESCRIPTION: pops the top two stack values, compares using the - // less than or equal to (<=) operator. - // STACK RESULT: push the constant value 1 onto the stack if the result - // of the operation is true or the constant value 0 if the result of the - // operation is false. - //---------------------------------------------------------------------- - case DW_OP_le: - if (stack.size() < 2) - { - if (error_ptr) - error_ptr->SetErrorString("Expression stack needs at least 2 items for DW_OP_le."); - return false; - } - else - { - tmp = stack.back(); - stack.pop_back(); - stack.back().ResolveValue(exe_ctx) = stack.back().ResolveValue(exe_ctx) <= tmp.ResolveValue(exe_ctx); - } - break; - - //---------------------------------------------------------------------- - // OPCODE: DW_OP_lt - // OPERANDS: none - // DESCRIPTION: pops the top two stack values, compares using the - // less than (<) operator. - // STACK RESULT: push the constant value 1 onto the stack if the result - // of the operation is true or the constant value 0 if the result of the - // operation is false. - //---------------------------------------------------------------------- - case DW_OP_lt: - if (stack.size() < 2) - { - if (error_ptr) - error_ptr->SetErrorString("Expression stack needs at least 2 items for DW_OP_lt."); - return false; - } - else - { - tmp = stack.back(); - stack.pop_back(); - stack.back().ResolveValue(exe_ctx) = stack.back().ResolveValue(exe_ctx) < tmp.ResolveValue(exe_ctx); - } - break; - - //---------------------------------------------------------------------- - // OPCODE: DW_OP_ne - // OPERANDS: none - // DESCRIPTION: pops the top two stack values, compares using the - // not equal (!=) operator. - // STACK RESULT: push the constant value 1 onto the stack if the result - // of the operation is true or the constant value 0 if the result of the - // operation is false. - //---------------------------------------------------------------------- - case DW_OP_ne: - if (stack.size() < 2) - { - if (error_ptr) - error_ptr->SetErrorString("Expression stack needs at least 2 items for DW_OP_ne."); - return false; - } - else - { - tmp = stack.back(); - stack.pop_back(); - stack.back().ResolveValue(exe_ctx) = stack.back().ResolveValue(exe_ctx) != tmp.ResolveValue(exe_ctx); - } - break; - - //---------------------------------------------------------------------- - // OPCODE: DW_OP_litn - // OPERANDS: none - // DESCRIPTION: encode the unsigned literal values from 0 through 31. - // STACK RESULT: push the unsigned literal constant value onto the top - // of the stack. - //---------------------------------------------------------------------- - case DW_OP_lit0: - case DW_OP_lit1: - case DW_OP_lit2: - case DW_OP_lit3: - case DW_OP_lit4: - case DW_OP_lit5: - case DW_OP_lit6: - case DW_OP_lit7: - case DW_OP_lit8: - case DW_OP_lit9: - case DW_OP_lit10: - case DW_OP_lit11: - case DW_OP_lit12: - case DW_OP_lit13: - case DW_OP_lit14: - case DW_OP_lit15: - case DW_OP_lit16: - case DW_OP_lit17: - case DW_OP_lit18: - case DW_OP_lit19: - case DW_OP_lit20: - case DW_OP_lit21: - case DW_OP_lit22: - case DW_OP_lit23: - case DW_OP_lit24: - case DW_OP_lit25: - case DW_OP_lit26: - case DW_OP_lit27: - case DW_OP_lit28: - case DW_OP_lit29: - case DW_OP_lit30: - case DW_OP_lit31: - stack.push_back(Scalar(op - DW_OP_lit0)); - break; - - //---------------------------------------------------------------------- - // OPCODE: DW_OP_regN - // OPERANDS: none - // DESCRIPTION: Push the value in register n on the top of the stack. - //---------------------------------------------------------------------- - case DW_OP_reg0: - case DW_OP_reg1: - case DW_OP_reg2: - case DW_OP_reg3: - case DW_OP_reg4: - case DW_OP_reg5: - case DW_OP_reg6: - case DW_OP_reg7: - case DW_OP_reg8: - case DW_OP_reg9: - case DW_OP_reg10: - case DW_OP_reg11: - case DW_OP_reg12: - case DW_OP_reg13: - case DW_OP_reg14: - case DW_OP_reg15: - case DW_OP_reg16: - case DW_OP_reg17: - case DW_OP_reg18: - case DW_OP_reg19: - case DW_OP_reg20: - case DW_OP_reg21: - case DW_OP_reg22: - case DW_OP_reg23: - case DW_OP_reg24: - case DW_OP_reg25: - case DW_OP_reg26: - case DW_OP_reg27: - case DW_OP_reg28: - case DW_OP_reg29: - case DW_OP_reg30: - case DW_OP_reg31: - { - reg_num = op - DW_OP_reg0; - - if (ReadRegisterValueAsScalar (reg_ctx, reg_kind, reg_num, error_ptr, tmp)) - stack.push_back(tmp); - else - return false; - } - break; - //---------------------------------------------------------------------- - // OPCODE: DW_OP_regx - // OPERANDS: - // ULEB128 literal operand that encodes the register. - // DESCRIPTION: Push the value in register on the top of the stack. - //---------------------------------------------------------------------- - case DW_OP_regx: - { - reg_num = opcodes.GetULEB128(&offset); - if (ReadRegisterValueAsScalar (reg_ctx, reg_kind, reg_num, error_ptr, tmp)) - stack.push_back(tmp); - else - return false; - } - break; - - //---------------------------------------------------------------------- - // OPCODE: DW_OP_bregN - // OPERANDS: - // SLEB128 offset from register N - // DESCRIPTION: Value is in memory at the address specified by register - // N plus an offset. - //---------------------------------------------------------------------- - case DW_OP_breg0: - case DW_OP_breg1: - case DW_OP_breg2: - case DW_OP_breg3: - case DW_OP_breg4: - case DW_OP_breg5: - case DW_OP_breg6: - case DW_OP_breg7: - case DW_OP_breg8: - case DW_OP_breg9: - case DW_OP_breg10: - case DW_OP_breg11: - case DW_OP_breg12: - case DW_OP_breg13: - case DW_OP_breg14: - case DW_OP_breg15: - case DW_OP_breg16: - case DW_OP_breg17: - case DW_OP_breg18: - case DW_OP_breg19: - case DW_OP_breg20: - case DW_OP_breg21: - case DW_OP_breg22: - case DW_OP_breg23: - case DW_OP_breg24: - case DW_OP_breg25: - case DW_OP_breg26: - case DW_OP_breg27: - case DW_OP_breg28: - case DW_OP_breg29: - case DW_OP_breg30: - case DW_OP_breg31: - { - reg_num = op - DW_OP_breg0; - - if (ReadRegisterValueAsScalar (reg_ctx, reg_kind, reg_num, error_ptr, tmp)) - { - int64_t breg_offset = opcodes.GetSLEB128(&offset); - tmp.ResolveValue(exe_ctx) += (uint64_t)breg_offset; - tmp.ClearContext(); - stack.push_back(tmp); - stack.back().SetValueType (Value::eValueTypeLoadAddress); - } - else - return false; - } - break; - //---------------------------------------------------------------------- - // OPCODE: DW_OP_bregx - // OPERANDS: 2 - // ULEB128 literal operand that encodes the register. - // SLEB128 offset from register N - // DESCRIPTION: Value is in memory at the address specified by register - // N plus an offset. - //---------------------------------------------------------------------- - case DW_OP_bregx: - { - reg_num = opcodes.GetULEB128(&offset); - - if (ReadRegisterValueAsScalar (reg_ctx, reg_kind, reg_num, error_ptr, tmp)) - { - int64_t breg_offset = opcodes.GetSLEB128(&offset); - tmp.ResolveValue(exe_ctx) += (uint64_t)breg_offset; - tmp.ClearContext(); - stack.push_back(tmp); - stack.back().SetValueType (Value::eValueTypeLoadAddress); - } - else - return false; - } - break; - - case DW_OP_fbreg: - if (exe_ctx) - { - if (frame) - { - Scalar value; - if (frame->GetFrameBaseValue(value, error_ptr)) - { - int64_t fbreg_offset = opcodes.GetSLEB128(&offset); - value += fbreg_offset; - stack.push_back(value); - stack.back().SetValueType (Value::eValueTypeLoadAddress); - } - else - return false; - } - else - { - if (error_ptr) - error_ptr->SetErrorString ("Invalid stack frame in context for DW_OP_fbreg opcode."); - return false; + } + } else { + if (error_ptr) + error_ptr->SetErrorStringWithFormat( + "NULL execution context for DW_OP_deref.\n"); + return false; + } + break; + + default: + break; + } + + } break; + + //---------------------------------------------------------------------- + // OPCODE: DW_OP_xderef_size + // OPERANDS: 1 + // 1 - uint8_t that specifies the size of the data to dereference. + // DESCRIPTION: Behaves like the DW_OP_xderef operation: the entry at + // the top of the stack is treated as an address. The second stack + // entry is treated as an "address space identifier" for those + // architectures that support multiple address spaces. The top two + // stack elements are popped, a data item is retrieved through an + // implementation-defined address calculation and pushed as the new + // stack top. In the DW_OP_xderef_size operation, however, the size in + // bytes of the data retrieved from the dereferenced address is + // specified by the single operand. This operand is a 1-byte unsigned + // integral constant whose value may not be larger than the size of an + // address on the target machine. The data retrieved is zero extended + // to the size of an address on the target machine before being pushed + // on the expression stack. + //---------------------------------------------------------------------- + case DW_OP_xderef_size: + if (error_ptr) + error_ptr->SetErrorString("Unimplemented opcode: DW_OP_xderef_size."); + return false; + //---------------------------------------------------------------------- + // OPCODE: DW_OP_xderef + // OPERANDS: none + // DESCRIPTION: Provides an extended dereference mechanism. The entry at + // the top of the stack is treated as an address. The second stack entry + // is treated as an "address space identifier" for those architectures + // that support multiple address spaces. The top two stack elements are + // popped, a data item is retrieved through an implementation-defined + // address calculation and pushed as the new stack top. The size of the + // data retrieved from the dereferenced address is the size of an address + // on the target machine. + //---------------------------------------------------------------------- + case DW_OP_xderef: + if (error_ptr) + error_ptr->SetErrorString("Unimplemented opcode: DW_OP_xderef."); + return false; + + //---------------------------------------------------------------------- + // All DW_OP_constXXX opcodes have a single operand as noted below: + // + // Opcode Operand 1 + // --------------- ---------------------------------------------------- + // DW_OP_const1u 1-byte unsigned integer constant + // DW_OP_const1s 1-byte signed integer constant + // DW_OP_const2u 2-byte unsigned integer constant + // DW_OP_const2s 2-byte signed integer constant + // DW_OP_const4u 4-byte unsigned integer constant + // DW_OP_const4s 4-byte signed integer constant + // DW_OP_const8u 8-byte unsigned integer constant + // DW_OP_const8s 8-byte signed integer constant + // DW_OP_constu unsigned LEB128 integer constant + // DW_OP_consts signed LEB128 integer constant + //---------------------------------------------------------------------- + case DW_OP_const1u: + stack.push_back(Scalar((uint8_t)opcodes.GetU8(&offset))); + break; + case DW_OP_const1s: + stack.push_back(Scalar((int8_t)opcodes.GetU8(&offset))); + break; + case DW_OP_const2u: + stack.push_back(Scalar((uint16_t)opcodes.GetU16(&offset))); + break; + case DW_OP_const2s: + stack.push_back(Scalar((int16_t)opcodes.GetU16(&offset))); + break; + case DW_OP_const4u: + stack.push_back(Scalar((uint32_t)opcodes.GetU32(&offset))); + break; + case DW_OP_const4s: + stack.push_back(Scalar((int32_t)opcodes.GetU32(&offset))); + break; + case DW_OP_const8u: + stack.push_back(Scalar((uint64_t)opcodes.GetU64(&offset))); + break; + case DW_OP_const8s: + stack.push_back(Scalar((int64_t)opcodes.GetU64(&offset))); + break; + case DW_OP_constu: + stack.push_back(Scalar(opcodes.GetULEB128(&offset))); + break; + case DW_OP_consts: + stack.push_back(Scalar(opcodes.GetSLEB128(&offset))); + break; + + //---------------------------------------------------------------------- + // OPCODE: DW_OP_dup + // OPERANDS: none + // DESCRIPTION: duplicates the value at the top of the stack + //---------------------------------------------------------------------- + case DW_OP_dup: + if (stack.empty()) { + if (error_ptr) + error_ptr->SetErrorString("Expression stack empty for DW_OP_dup."); + return false; + } else + stack.push_back(stack.back()); + break; + + //---------------------------------------------------------------------- + // OPCODE: DW_OP_drop + // OPERANDS: none + // DESCRIPTION: pops the value at the top of the stack + //---------------------------------------------------------------------- + case DW_OP_drop: + if (stack.empty()) { + if (error_ptr) + error_ptr->SetErrorString("Expression stack empty for DW_OP_drop."); + return false; + } else + stack.pop_back(); + break; + + //---------------------------------------------------------------------- + // OPCODE: DW_OP_over + // OPERANDS: none + // DESCRIPTION: Duplicates the entry currently second in the stack at + // the top of the stack. + //---------------------------------------------------------------------- + case DW_OP_over: + if (stack.size() < 2) { + if (error_ptr) + error_ptr->SetErrorString( + "Expression stack needs at least 2 items for DW_OP_over."); + return false; + } else + stack.push_back(stack[stack.size() - 2]); + break; + + //---------------------------------------------------------------------- + // OPCODE: DW_OP_pick + // OPERANDS: uint8_t index into the current stack + // DESCRIPTION: The stack entry with the specified index (0 through 255, + // inclusive) is pushed on the stack + //---------------------------------------------------------------------- + case DW_OP_pick: { + uint8_t pick_idx = opcodes.GetU8(&offset); + if (pick_idx < stack.size()) + stack.push_back(stack[pick_idx]); + else { + if (error_ptr) + error_ptr->SetErrorStringWithFormat( + "Index %u out of range for DW_OP_pick.\n", pick_idx); + return false; + } + } break; + + //---------------------------------------------------------------------- + // OPCODE: DW_OP_swap + // OPERANDS: none + // DESCRIPTION: swaps the top two stack entries. The entry at the top + // of the stack becomes the second stack entry, and the second entry + // becomes the top of the stack + //---------------------------------------------------------------------- + case DW_OP_swap: + if (stack.size() < 2) { + if (error_ptr) + error_ptr->SetErrorString( + "Expression stack needs at least 2 items for DW_OP_swap."); + return false; + } else { + tmp = stack.back(); + stack.back() = stack[stack.size() - 2]; + stack[stack.size() - 2] = tmp; + } + break; + + //---------------------------------------------------------------------- + // OPCODE: DW_OP_rot + // OPERANDS: none + // DESCRIPTION: Rotates the first three stack entries. The entry at + // the top of the stack becomes the third stack entry, the second + // entry becomes the top of the stack, and the third entry becomes + // the second entry. + //---------------------------------------------------------------------- + case DW_OP_rot: + if (stack.size() < 3) { + if (error_ptr) + error_ptr->SetErrorString( + "Expression stack needs at least 3 items for DW_OP_rot."); + return false; + } else { + size_t last_idx = stack.size() - 1; + Value old_top = stack[last_idx]; + stack[last_idx] = stack[last_idx - 1]; + stack[last_idx - 1] = stack[last_idx - 2]; + stack[last_idx - 2] = old_top; + } + break; + + //---------------------------------------------------------------------- + // OPCODE: DW_OP_abs + // OPERANDS: none + // DESCRIPTION: pops the top stack entry, interprets it as a signed + // value and pushes its absolute value. If the absolute value can not be + // represented, the result is undefined. + //---------------------------------------------------------------------- + case DW_OP_abs: + if (stack.empty()) { + if (error_ptr) + error_ptr->SetErrorString( + "Expression stack needs at least 1 item for DW_OP_abs."); + return false; + } else if (stack.back().ResolveValue(exe_ctx).AbsoluteValue() == false) { + if (error_ptr) + error_ptr->SetErrorString( + "Failed to take the absolute value of the first stack item."); + return false; + } + break; + + //---------------------------------------------------------------------- + // OPCODE: DW_OP_and + // OPERANDS: none + // DESCRIPTION: pops the top two stack values, performs a bitwise and + // operation on the two, and pushes the result. + //---------------------------------------------------------------------- + case DW_OP_and: + if (stack.size() < 2) { + if (error_ptr) + error_ptr->SetErrorString( + "Expression stack needs at least 2 items for DW_OP_and."); + return false; + } else { + tmp = stack.back(); + stack.pop_back(); + stack.back().ResolveValue(exe_ctx) = + stack.back().ResolveValue(exe_ctx) & tmp.ResolveValue(exe_ctx); + } + break; + + //---------------------------------------------------------------------- + // OPCODE: DW_OP_div + // OPERANDS: none + // DESCRIPTION: pops the top two stack values, divides the former second + // entry by the former top of the stack using signed division, and + // pushes the result. + //---------------------------------------------------------------------- + case DW_OP_div: + if (stack.size() < 2) { + if (error_ptr) + error_ptr->SetErrorString( + "Expression stack needs at least 2 items for DW_OP_div."); + return false; + } else { + tmp = stack.back(); + if (tmp.ResolveValue(exe_ctx).IsZero()) { + if (error_ptr) + error_ptr->SetErrorString("Divide by zero."); + return false; + } else { + stack.pop_back(); + stack.back() = + stack.back().ResolveValue(exe_ctx) / tmp.ResolveValue(exe_ctx); + if (!stack.back().ResolveValue(exe_ctx).IsValid()) { + if (error_ptr) + error_ptr->SetErrorString("Divide failed."); + return false; + } + } + } + break; + + //---------------------------------------------------------------------- + // OPCODE: DW_OP_minus + // OPERANDS: none + // DESCRIPTION: pops the top two stack values, subtracts the former top + // of the stack from the former second entry, and pushes the result. + //---------------------------------------------------------------------- + case DW_OP_minus: + if (stack.size() < 2) { + if (error_ptr) + error_ptr->SetErrorString( + "Expression stack needs at least 2 items for DW_OP_minus."); + return false; + } else { + tmp = stack.back(); + stack.pop_back(); + stack.back().ResolveValue(exe_ctx) = + stack.back().ResolveValue(exe_ctx) - tmp.ResolveValue(exe_ctx); + } + break; + + //---------------------------------------------------------------------- + // OPCODE: DW_OP_mod + // OPERANDS: none + // DESCRIPTION: pops the top two stack values and pushes the result of + // the calculation: former second stack entry modulo the former top of + // the stack. + //---------------------------------------------------------------------- + case DW_OP_mod: + if (stack.size() < 2) { + if (error_ptr) + error_ptr->SetErrorString( + "Expression stack needs at least 2 items for DW_OP_mod."); + return false; + } else { + tmp = stack.back(); + stack.pop_back(); + stack.back().ResolveValue(exe_ctx) = + stack.back().ResolveValue(exe_ctx) % tmp.ResolveValue(exe_ctx); + } + break; + + //---------------------------------------------------------------------- + // OPCODE: DW_OP_mul + // OPERANDS: none + // DESCRIPTION: pops the top two stack entries, multiplies them + // together, and pushes the result. + //---------------------------------------------------------------------- + case DW_OP_mul: + if (stack.size() < 2) { + if (error_ptr) + error_ptr->SetErrorString( + "Expression stack needs at least 2 items for DW_OP_mul."); + return false; + } else { + tmp = stack.back(); + stack.pop_back(); + stack.back().ResolveValue(exe_ctx) = + stack.back().ResolveValue(exe_ctx) * tmp.ResolveValue(exe_ctx); + } + break; + + //---------------------------------------------------------------------- + // OPCODE: DW_OP_neg + // OPERANDS: none + // DESCRIPTION: pops the top stack entry, and pushes its negation. + //---------------------------------------------------------------------- + case DW_OP_neg: + if (stack.empty()) { + if (error_ptr) + error_ptr->SetErrorString( + "Expression stack needs at least 1 item for DW_OP_neg."); + return false; + } else { + if (stack.back().ResolveValue(exe_ctx).UnaryNegate() == false) { + if (error_ptr) + error_ptr->SetErrorString("Unary negate failed."); + return false; + } + } + break; + + //---------------------------------------------------------------------- + // OPCODE: DW_OP_not + // OPERANDS: none + // DESCRIPTION: pops the top stack entry, and pushes its bitwise + // complement + //---------------------------------------------------------------------- + case DW_OP_not: + if (stack.empty()) { + if (error_ptr) + error_ptr->SetErrorString( + "Expression stack needs at least 1 item for DW_OP_not."); + return false; + } else { + if (stack.back().ResolveValue(exe_ctx).OnesComplement() == false) { + if (error_ptr) + error_ptr->SetErrorString("Logical NOT failed."); + return false; + } + } + break; + + //---------------------------------------------------------------------- + // OPCODE: DW_OP_or + // OPERANDS: none + // DESCRIPTION: pops the top two stack entries, performs a bitwise or + // operation on the two, and pushes the result. + //---------------------------------------------------------------------- + case DW_OP_or: + if (stack.size() < 2) { + if (error_ptr) + error_ptr->SetErrorString( + "Expression stack needs at least 2 items for DW_OP_or."); + return false; + } else { + tmp = stack.back(); + stack.pop_back(); + stack.back().ResolveValue(exe_ctx) = + stack.back().ResolveValue(exe_ctx) | tmp.ResolveValue(exe_ctx); + } + break; + + //---------------------------------------------------------------------- + // OPCODE: DW_OP_plus + // OPERANDS: none + // DESCRIPTION: pops the top two stack entries, adds them together, and + // pushes the result. + //---------------------------------------------------------------------- + case DW_OP_plus: + if (stack.size() < 2) { + if (error_ptr) + error_ptr->SetErrorString( + "Expression stack needs at least 2 items for DW_OP_plus."); + return false; + } else { + tmp = stack.back(); + stack.pop_back(); + stack.back().GetScalar() += tmp.GetScalar(); + } + break; + + //---------------------------------------------------------------------- + // OPCODE: DW_OP_plus_uconst + // OPERANDS: none + // DESCRIPTION: pops the top stack entry, adds it to the unsigned LEB128 + // constant operand and pushes the result. + //---------------------------------------------------------------------- + case DW_OP_plus_uconst: + if (stack.empty()) { + if (error_ptr) + error_ptr->SetErrorString( + "Expression stack needs at least 1 item for DW_OP_plus_uconst."); + return false; + } else { + const uint64_t uconst_value = opcodes.GetULEB128(&offset); + // Implicit conversion from a UINT to a Scalar... + stack.back().GetScalar() += uconst_value; + if (!stack.back().GetScalar().IsValid()) { + if (error_ptr) + error_ptr->SetErrorString("DW_OP_plus_uconst failed."); + return false; + } + } + break; + + //---------------------------------------------------------------------- + // OPCODE: DW_OP_shl + // OPERANDS: none + // DESCRIPTION: pops the top two stack entries, shifts the former + // second entry left by the number of bits specified by the former top + // of the stack, and pushes the result. + //---------------------------------------------------------------------- + case DW_OP_shl: + if (stack.size() < 2) { + if (error_ptr) + error_ptr->SetErrorString( + "Expression stack needs at least 2 items for DW_OP_shl."); + return false; + } else { + tmp = stack.back(); + stack.pop_back(); + stack.back().ResolveValue(exe_ctx) <<= tmp.ResolveValue(exe_ctx); + } + break; + + //---------------------------------------------------------------------- + // OPCODE: DW_OP_shr + // OPERANDS: none + // DESCRIPTION: pops the top two stack entries, shifts the former second + // entry right logically (filling with zero bits) by the number of bits + // specified by the former top of the stack, and pushes the result. + //---------------------------------------------------------------------- + case DW_OP_shr: + if (stack.size() < 2) { + if (error_ptr) + error_ptr->SetErrorString( + "Expression stack needs at least 2 items for DW_OP_shr."); + return false; + } else { + tmp = stack.back(); + stack.pop_back(); + if (stack.back().ResolveValue(exe_ctx).ShiftRightLogical( + tmp.ResolveValue(exe_ctx)) == false) { + if (error_ptr) + error_ptr->SetErrorString("DW_OP_shr failed."); + return false; + } + } + break; + + //---------------------------------------------------------------------- + // OPCODE: DW_OP_shra + // OPERANDS: none + // DESCRIPTION: pops the top two stack entries, shifts the former second + // entry right arithmetically (divide the magnitude by 2, keep the same + // sign for the result) by the number of bits specified by the former + // top of the stack, and pushes the result. + //---------------------------------------------------------------------- + case DW_OP_shra: + if (stack.size() < 2) { + if (error_ptr) + error_ptr->SetErrorString( + "Expression stack needs at least 2 items for DW_OP_shra."); + return false; + } else { + tmp = stack.back(); + stack.pop_back(); + stack.back().ResolveValue(exe_ctx) >>= tmp.ResolveValue(exe_ctx); + } + break; + + //---------------------------------------------------------------------- + // OPCODE: DW_OP_xor + // OPERANDS: none + // DESCRIPTION: pops the top two stack entries, performs the bitwise + // exclusive-or operation on the two, and pushes the result. + //---------------------------------------------------------------------- + case DW_OP_xor: + if (stack.size() < 2) { + if (error_ptr) + error_ptr->SetErrorString( + "Expression stack needs at least 2 items for DW_OP_xor."); + return false; + } else { + tmp = stack.back(); + stack.pop_back(); + stack.back().ResolveValue(exe_ctx) = + stack.back().ResolveValue(exe_ctx) ^ tmp.ResolveValue(exe_ctx); + } + break; + + //---------------------------------------------------------------------- + // OPCODE: DW_OP_skip + // OPERANDS: int16_t + // DESCRIPTION: An unconditional branch. Its single operand is a 2-byte + // signed integer constant. The 2-byte constant is the number of bytes + // of the DWARF expression to skip forward or backward from the current + // operation, beginning after the 2-byte constant. + //---------------------------------------------------------------------- + case DW_OP_skip: { + int16_t skip_offset = (int16_t)opcodes.GetU16(&offset); + lldb::offset_t new_offset = offset + skip_offset; + if (new_offset >= opcodes_offset && new_offset < end_offset) + offset = new_offset; + else { + if (error_ptr) + error_ptr->SetErrorString("Invalid opcode offset in DW_OP_skip."); + return false; + } + } break; + + //---------------------------------------------------------------------- + // OPCODE: DW_OP_bra + // OPERANDS: int16_t + // DESCRIPTION: A conditional branch. Its single operand is a 2-byte + // signed integer constant. This operation pops the top of stack. If + // the value popped is not the constant 0, the 2-byte constant operand + // is the number of bytes of the DWARF expression to skip forward or + // backward from the current operation, beginning after the 2-byte + // constant. + //---------------------------------------------------------------------- + case DW_OP_bra: + if (stack.empty()) { + if (error_ptr) + error_ptr->SetErrorString( + "Expression stack needs at least 1 item for DW_OP_bra."); + return false; + } else { + tmp = stack.back(); + stack.pop_back(); + int16_t bra_offset = (int16_t)opcodes.GetU16(&offset); + Scalar zero(0); + if (tmp.ResolveValue(exe_ctx) != zero) { + lldb::offset_t new_offset = offset + bra_offset; + if (new_offset >= opcodes_offset && new_offset < end_offset) + offset = new_offset; + else { + if (error_ptr) + error_ptr->SetErrorString("Invalid opcode offset in DW_OP_bra."); + return false; + } + } + } + break; + + //---------------------------------------------------------------------- + // OPCODE: DW_OP_eq + // OPERANDS: none + // DESCRIPTION: pops the top two stack values, compares using the + // equals (==) operator. + // STACK RESULT: push the constant value 1 onto the stack if the result + // of the operation is true or the constant value 0 if the result of the + // operation is false. + //---------------------------------------------------------------------- + case DW_OP_eq: + if (stack.size() < 2) { + if (error_ptr) + error_ptr->SetErrorString( + "Expression stack needs at least 2 items for DW_OP_eq."); + return false; + } else { + tmp = stack.back(); + stack.pop_back(); + stack.back().ResolveValue(exe_ctx) = + stack.back().ResolveValue(exe_ctx) == tmp.ResolveValue(exe_ctx); + } + break; + + //---------------------------------------------------------------------- + // OPCODE: DW_OP_ge + // OPERANDS: none + // DESCRIPTION: pops the top two stack values, compares using the + // greater than or equal to (>=) operator. + // STACK RESULT: push the constant value 1 onto the stack if the result + // of the operation is true or the constant value 0 if the result of the + // operation is false. + //---------------------------------------------------------------------- + case DW_OP_ge: + if (stack.size() < 2) { + if (error_ptr) + error_ptr->SetErrorString( + "Expression stack needs at least 2 items for DW_OP_ge."); + return false; + } else { + tmp = stack.back(); + stack.pop_back(); + stack.back().ResolveValue(exe_ctx) = + stack.back().ResolveValue(exe_ctx) >= tmp.ResolveValue(exe_ctx); + } + break; + + //---------------------------------------------------------------------- + // OPCODE: DW_OP_gt + // OPERANDS: none + // DESCRIPTION: pops the top two stack values, compares using the + // greater than (>) operator. + // STACK RESULT: push the constant value 1 onto the stack if the result + // of the operation is true or the constant value 0 if the result of the + // operation is false. + //---------------------------------------------------------------------- + case DW_OP_gt: + if (stack.size() < 2) { + if (error_ptr) + error_ptr->SetErrorString( + "Expression stack needs at least 2 items for DW_OP_gt."); + return false; + } else { + tmp = stack.back(); + stack.pop_back(); + stack.back().ResolveValue(exe_ctx) = + stack.back().ResolveValue(exe_ctx) > tmp.ResolveValue(exe_ctx); + } + break; + + //---------------------------------------------------------------------- + // OPCODE: DW_OP_le + // OPERANDS: none + // DESCRIPTION: pops the top two stack values, compares using the + // less than or equal to (<=) operator. + // STACK RESULT: push the constant value 1 onto the stack if the result + // of the operation is true or the constant value 0 if the result of the + // operation is false. + //---------------------------------------------------------------------- + case DW_OP_le: + if (stack.size() < 2) { + if (error_ptr) + error_ptr->SetErrorString( + "Expression stack needs at least 2 items for DW_OP_le."); + return false; + } else { + tmp = stack.back(); + stack.pop_back(); + stack.back().ResolveValue(exe_ctx) = + stack.back().ResolveValue(exe_ctx) <= tmp.ResolveValue(exe_ctx); + } + break; + + //---------------------------------------------------------------------- + // OPCODE: DW_OP_lt + // OPERANDS: none + // DESCRIPTION: pops the top two stack values, compares using the + // less than (<) operator. + // STACK RESULT: push the constant value 1 onto the stack if the result + // of the operation is true or the constant value 0 if the result of the + // operation is false. + //---------------------------------------------------------------------- + case DW_OP_lt: + if (stack.size() < 2) { + if (error_ptr) + error_ptr->SetErrorString( + "Expression stack needs at least 2 items for DW_OP_lt."); + return false; + } else { + tmp = stack.back(); + stack.pop_back(); + stack.back().ResolveValue(exe_ctx) = + stack.back().ResolveValue(exe_ctx) < tmp.ResolveValue(exe_ctx); + } + break; + + //---------------------------------------------------------------------- + // OPCODE: DW_OP_ne + // OPERANDS: none + // DESCRIPTION: pops the top two stack values, compares using the + // not equal (!=) operator. + // STACK RESULT: push the constant value 1 onto the stack if the result + // of the operation is true or the constant value 0 if the result of the + // operation is false. + //---------------------------------------------------------------------- + case DW_OP_ne: + if (stack.size() < 2) { + if (error_ptr) + error_ptr->SetErrorString( + "Expression stack needs at least 2 items for DW_OP_ne."); + return false; + } else { + tmp = stack.back(); + stack.pop_back(); + stack.back().ResolveValue(exe_ctx) = + stack.back().ResolveValue(exe_ctx) != tmp.ResolveValue(exe_ctx); + } + break; + + //---------------------------------------------------------------------- + // OPCODE: DW_OP_litn + // OPERANDS: none + // DESCRIPTION: encode the unsigned literal values from 0 through 31. + // STACK RESULT: push the unsigned literal constant value onto the top + // of the stack. + //---------------------------------------------------------------------- + case DW_OP_lit0: + case DW_OP_lit1: + case DW_OP_lit2: + case DW_OP_lit3: + case DW_OP_lit4: + case DW_OP_lit5: + case DW_OP_lit6: + case DW_OP_lit7: + case DW_OP_lit8: + case DW_OP_lit9: + case DW_OP_lit10: + case DW_OP_lit11: + case DW_OP_lit12: + case DW_OP_lit13: + case DW_OP_lit14: + case DW_OP_lit15: + case DW_OP_lit16: + case DW_OP_lit17: + case DW_OP_lit18: + case DW_OP_lit19: + case DW_OP_lit20: + case DW_OP_lit21: + case DW_OP_lit22: + case DW_OP_lit23: + case DW_OP_lit24: + case DW_OP_lit25: + case DW_OP_lit26: + case DW_OP_lit27: + case DW_OP_lit28: + case DW_OP_lit29: + case DW_OP_lit30: + case DW_OP_lit31: + stack.push_back(Scalar(op - DW_OP_lit0)); + break; + + //---------------------------------------------------------------------- + // OPCODE: DW_OP_regN + // OPERANDS: none + // DESCRIPTION: Push the value in register n on the top of the stack. + //---------------------------------------------------------------------- + case DW_OP_reg0: + case DW_OP_reg1: + case DW_OP_reg2: + case DW_OP_reg3: + case DW_OP_reg4: + case DW_OP_reg5: + case DW_OP_reg6: + case DW_OP_reg7: + case DW_OP_reg8: + case DW_OP_reg9: + case DW_OP_reg10: + case DW_OP_reg11: + case DW_OP_reg12: + case DW_OP_reg13: + case DW_OP_reg14: + case DW_OP_reg15: + case DW_OP_reg16: + case DW_OP_reg17: + case DW_OP_reg18: + case DW_OP_reg19: + case DW_OP_reg20: + case DW_OP_reg21: + case DW_OP_reg22: + case DW_OP_reg23: + case DW_OP_reg24: + case DW_OP_reg25: + case DW_OP_reg26: + case DW_OP_reg27: + case DW_OP_reg28: + case DW_OP_reg29: + case DW_OP_reg30: + case DW_OP_reg31: { + reg_num = op - DW_OP_reg0; + + if (ReadRegisterValueAsScalar(reg_ctx, reg_kind, reg_num, error_ptr, tmp)) + stack.push_back(tmp); + else + return false; + } break; + //---------------------------------------------------------------------- + // OPCODE: DW_OP_regx + // OPERANDS: + // ULEB128 literal operand that encodes the register. + // DESCRIPTION: Push the value in register on the top of the stack. + //---------------------------------------------------------------------- + case DW_OP_regx: { + reg_num = opcodes.GetULEB128(&offset); + if (ReadRegisterValueAsScalar(reg_ctx, reg_kind, reg_num, error_ptr, tmp)) + stack.push_back(tmp); + else + return false; + } break; + + //---------------------------------------------------------------------- + // OPCODE: DW_OP_bregN + // OPERANDS: + // SLEB128 offset from register N + // DESCRIPTION: Value is in memory at the address specified by register + // N plus an offset. + //---------------------------------------------------------------------- + case DW_OP_breg0: + case DW_OP_breg1: + case DW_OP_breg2: + case DW_OP_breg3: + case DW_OP_breg4: + case DW_OP_breg5: + case DW_OP_breg6: + case DW_OP_breg7: + case DW_OP_breg8: + case DW_OP_breg9: + case DW_OP_breg10: + case DW_OP_breg11: + case DW_OP_breg12: + case DW_OP_breg13: + case DW_OP_breg14: + case DW_OP_breg15: + case DW_OP_breg16: + case DW_OP_breg17: + case DW_OP_breg18: + case DW_OP_breg19: + case DW_OP_breg20: + case DW_OP_breg21: + case DW_OP_breg22: + case DW_OP_breg23: + case DW_OP_breg24: + case DW_OP_breg25: + case DW_OP_breg26: + case DW_OP_breg27: + case DW_OP_breg28: + case DW_OP_breg29: + case DW_OP_breg30: + case DW_OP_breg31: { + reg_num = op - DW_OP_breg0; + + if (ReadRegisterValueAsScalar(reg_ctx, reg_kind, reg_num, error_ptr, + tmp)) { + int64_t breg_offset = opcodes.GetSLEB128(&offset); + tmp.ResolveValue(exe_ctx) += (uint64_t)breg_offset; + tmp.ClearContext(); + stack.push_back(tmp); + stack.back().SetValueType(Value::eValueTypeLoadAddress); + } else + return false; + } break; + //---------------------------------------------------------------------- + // OPCODE: DW_OP_bregx + // OPERANDS: 2 + // ULEB128 literal operand that encodes the register. + // SLEB128 offset from register N + // DESCRIPTION: Value is in memory at the address specified by register + // N plus an offset. + //---------------------------------------------------------------------- + case DW_OP_bregx: { + reg_num = opcodes.GetULEB128(&offset); + + if (ReadRegisterValueAsScalar(reg_ctx, reg_kind, reg_num, error_ptr, + tmp)) { + int64_t breg_offset = opcodes.GetSLEB128(&offset); + tmp.ResolveValue(exe_ctx) += (uint64_t)breg_offset; + tmp.ClearContext(); + stack.push_back(tmp); + stack.back().SetValueType(Value::eValueTypeLoadAddress); + } else + return false; + } break; + + case DW_OP_fbreg: + if (exe_ctx) { + if (frame) { + Scalar value; + if (frame->GetFrameBaseValue(value, error_ptr)) { + int64_t fbreg_offset = opcodes.GetSLEB128(&offset); + value += fbreg_offset; + stack.push_back(value); + stack.back().SetValueType(Value::eValueTypeLoadAddress); + } else + return false; + } else { + if (error_ptr) + error_ptr->SetErrorString( + "Invalid stack frame in context for DW_OP_fbreg opcode."); + return false; + } + } else { + if (error_ptr) + error_ptr->SetErrorStringWithFormat( + "NULL execution context for DW_OP_fbreg.\n"); + return false; + } + + break; + + //---------------------------------------------------------------------- + // OPCODE: DW_OP_nop + // OPERANDS: none + // DESCRIPTION: A place holder. It has no effect on the location stack + // or any of its values. + //---------------------------------------------------------------------- + case DW_OP_nop: + break; + + //---------------------------------------------------------------------- + // OPCODE: DW_OP_piece + // OPERANDS: 1 + // ULEB128: byte size of the piece + // DESCRIPTION: The operand describes the size in bytes of the piece of + // the object referenced by the DWARF expression whose result is at the + // top of the stack. If the piece is located in a register, but does not + // occupy the entire register, the placement of the piece within that + // register is defined by the ABI. + // + // Many compilers store a single variable in sets of registers, or store + // a variable partially in memory and partially in registers. + // DW_OP_piece provides a way of describing how large a part of a + // variable a particular DWARF expression refers to. + //---------------------------------------------------------------------- + case DW_OP_piece: { + const uint64_t piece_byte_size = opcodes.GetULEB128(&offset); + + if (piece_byte_size > 0) { + Value curr_piece; + + if (stack.empty()) { + // In a multi-piece expression, this means that the current piece is + // not available. + // Fill with zeros for now by resizing the data and appending it + curr_piece.ResizeData(piece_byte_size); + ::memset(curr_piece.GetBuffer().GetBytes(), 0, piece_byte_size); + pieces.AppendDataToHostBuffer(curr_piece); + } else { + Error error; + // Extract the current piece into "curr_piece" + Value curr_piece_source_value(stack.back()); + stack.pop_back(); + + const Value::ValueType curr_piece_source_value_type = + curr_piece_source_value.GetValueType(); + switch (curr_piece_source_value_type) { + case Value::eValueTypeLoadAddress: + if (process) { + if (curr_piece.ResizeData(piece_byte_size) == piece_byte_size) { + lldb::addr_t load_addr = + curr_piece_source_value.GetScalar().ULongLong( + LLDB_INVALID_ADDRESS); + if (process->ReadMemory( + load_addr, curr_piece.GetBuffer().GetBytes(), + piece_byte_size, error) != piece_byte_size) { + if (error_ptr) + error_ptr->SetErrorStringWithFormat( + "failed to read memory DW_OP_piece(%" PRIu64 + ") from 0x%" PRIx64, + piece_byte_size, load_addr); + return false; } - } - else - { + } else { if (error_ptr) - error_ptr->SetErrorStringWithFormat ("NULL execution context for DW_OP_fbreg.\n"); + error_ptr->SetErrorStringWithFormat( + "failed to resize the piece memory buffer for " + "DW_OP_piece(%" PRIu64 ")", + piece_byte_size); return false; - } - - break; - - //---------------------------------------------------------------------- - // OPCODE: DW_OP_nop - // OPERANDS: none - // DESCRIPTION: A place holder. It has no effect on the location stack - // or any of its values. - //---------------------------------------------------------------------- - case DW_OP_nop: - break; - - //---------------------------------------------------------------------- - // OPCODE: DW_OP_piece - // OPERANDS: 1 - // ULEB128: byte size of the piece - // DESCRIPTION: The operand describes the size in bytes of the piece of - // the object referenced by the DWARF expression whose result is at the - // top of the stack. If the piece is located in a register, but does not - // occupy the entire register, the placement of the piece within that - // register is defined by the ABI. - // - // Many compilers store a single variable in sets of registers, or store - // a variable partially in memory and partially in registers. - // DW_OP_piece provides a way of describing how large a part of a - // variable a particular DWARF expression refers to. - //---------------------------------------------------------------------- - case DW_OP_piece: - { - const uint64_t piece_byte_size = opcodes.GetULEB128(&offset); - - if (piece_byte_size > 0) - { - Value curr_piece; - - if (stack.empty()) - { - // In a multi-piece expression, this means that the current piece is not available. - // Fill with zeros for now by resizing the data and appending it - curr_piece.ResizeData(piece_byte_size); - ::memset (curr_piece.GetBuffer().GetBytes(), 0, piece_byte_size); - pieces.AppendDataToHostBuffer(curr_piece); - } - else - { - Error error; - // Extract the current piece into "curr_piece" - Value curr_piece_source_value(stack.back()); - stack.pop_back(); - - const Value::ValueType curr_piece_source_value_type = curr_piece_source_value.GetValueType(); - switch (curr_piece_source_value_type) - { - case Value::eValueTypeLoadAddress: - if (process) - { - if (curr_piece.ResizeData(piece_byte_size) == piece_byte_size) - { - lldb::addr_t load_addr = curr_piece_source_value.GetScalar().ULongLong(LLDB_INVALID_ADDRESS); - if (process->ReadMemory(load_addr, curr_piece.GetBuffer().GetBytes(), piece_byte_size, error) != piece_byte_size) - { - if (error_ptr) - error_ptr->SetErrorStringWithFormat ("failed to read memory DW_OP_piece(%" PRIu64 ") from 0x%" PRIx64, - piece_byte_size, - load_addr); - return false; - } - } - else - { - if (error_ptr) - error_ptr->SetErrorStringWithFormat ("failed to resize the piece memory buffer for DW_OP_piece(%" PRIu64 ")", piece_byte_size); - return false; - } - } - break; - - case Value::eValueTypeFileAddress: - case Value::eValueTypeHostAddress: - if (error_ptr) - { - lldb::addr_t addr = curr_piece_source_value.GetScalar().ULongLong(LLDB_INVALID_ADDRESS); - error_ptr->SetErrorStringWithFormat ("failed to read memory DW_OP_piece(%" PRIu64 ") from %s address 0x%" PRIx64, - piece_byte_size, - curr_piece_source_value.GetValueType() == Value::eValueTypeFileAddress ? "file" : "host", - addr); - } - return false; - - case Value::eValueTypeScalar: - { - uint32_t bit_size = piece_byte_size * 8; - uint32_t bit_offset = 0; - if (!curr_piece_source_value.GetScalar().ExtractBitfield (bit_size, bit_offset)) - { - if (error_ptr) - error_ptr->SetErrorStringWithFormat("unable to extract %" PRIu64 " bytes from a %" PRIu64 " byte scalar value.", piece_byte_size, (uint64_t)curr_piece_source_value.GetScalar().GetByteSize()); - return false; - } - curr_piece = curr_piece_source_value; - } - break; - - case Value::eValueTypeVector: - { - if (curr_piece_source_value.GetVector().length >= piece_byte_size) - curr_piece_source_value.GetVector().length = piece_byte_size; - else - { - if (error_ptr) - error_ptr->SetErrorStringWithFormat("unable to extract %" PRIu64 " bytes from a %" PRIu64 " byte vector value.", piece_byte_size, (uint64_t)curr_piece_source_value.GetVector().length); - return false; - } - } - break; - - } - - // Check if this is the first piece? - if (op_piece_offset == 0) - { - // This is the first piece, we should push it back onto the stack so subsequent - // pieces will be able to access this piece and add to it - if (pieces.AppendDataToHostBuffer(curr_piece) == 0) - { - if (error_ptr) - error_ptr->SetErrorString("failed to append piece data"); - return false; - } - } - else - { - // If this is the second or later piece there should be a value on the stack - if (pieces.GetBuffer().GetByteSize() != op_piece_offset) - { - if (error_ptr) - error_ptr->SetErrorStringWithFormat ("DW_OP_piece for offset %" PRIu64 " but top of stack is of size %" PRIu64, - op_piece_offset, - pieces.GetBuffer().GetByteSize()); - return false; - } - - if (pieces.AppendDataToHostBuffer(curr_piece) == 0) - { - if (error_ptr) - error_ptr->SetErrorString("failed to append piece data"); - return false; - } - } - op_piece_offset += piece_byte_size; - } - } + } } break; - case DW_OP_bit_piece: // 0x9d ULEB128 bit size, ULEB128 bit offset (DWARF3); - if (stack.size() < 1) - { - if (error_ptr) - error_ptr->SetErrorString("Expression stack needs at least 1 item for DW_OP_bit_piece."); - return false; + case Value::eValueTypeFileAddress: + case Value::eValueTypeHostAddress: + if (error_ptr) { + lldb::addr_t addr = curr_piece_source_value.GetScalar().ULongLong( + LLDB_INVALID_ADDRESS); + error_ptr->SetErrorStringWithFormat( + "failed to read memory DW_OP_piece(%" PRIu64 + ") from %s address 0x%" PRIx64, + piece_byte_size, curr_piece_source_value.GetValueType() == + Value::eValueTypeFileAddress + ? "file" + : "host", + addr); } - else - { - const uint64_t piece_bit_size = opcodes.GetULEB128(&offset); - const uint64_t piece_bit_offset = opcodes.GetULEB128(&offset); - switch (stack.back().GetValueType()) - { - case Value::eValueTypeScalar: - { - if (!stack.back().GetScalar().ExtractBitfield (piece_bit_size, piece_bit_offset)) - { - if (error_ptr) - error_ptr->SetErrorStringWithFormat("unable to extract %" PRIu64 " bit value with %" PRIu64 " bit offset from a %" PRIu64 " bit scalar value.", - piece_bit_size, - piece_bit_offset, - (uint64_t)(stack.back().GetScalar().GetByteSize()*8)); - return false; - } - } - break; - - case Value::eValueTypeFileAddress: - case Value::eValueTypeLoadAddress: - case Value::eValueTypeHostAddress: - if (error_ptr) - { - error_ptr->SetErrorStringWithFormat ("unable to extract DW_OP_bit_piece(bit_size = %" PRIu64 ", bit_offset = %" PRIu64 ") from an addresss value.", - piece_bit_size, - piece_bit_offset); - } - return false; - - case Value::eValueTypeVector: - if (error_ptr) - { - error_ptr->SetErrorStringWithFormat ("unable to extract DW_OP_bit_piece(bit_size = %" PRIu64 ", bit_offset = %" PRIu64 ") from a vector value.", - piece_bit_size, - piece_bit_offset); - } - return false; - } - } - break; + return false; - //---------------------------------------------------------------------- - // OPCODE: DW_OP_push_object_address - // OPERANDS: none - // DESCRIPTION: Pushes the address of the object currently being - // evaluated as part of evaluation of a user presented expression. - // This object may correspond to an independent variable described by - // its own DIE or it may be a component of an array, structure, or class - // whose address has been dynamically determined by an earlier step - // during user expression evaluation. - //---------------------------------------------------------------------- - case DW_OP_push_object_address: - if (object_address_ptr) - stack.push_back(*object_address_ptr); - else - { - if (error_ptr) - error_ptr->SetErrorString ("DW_OP_push_object_address used without specifying an object address"); - return false; - } - break; + case Value::eValueTypeScalar: { + uint32_t bit_size = piece_byte_size * 8; + uint32_t bit_offset = 0; + if (!curr_piece_source_value.GetScalar().ExtractBitfield( + bit_size, bit_offset)) { + if (error_ptr) + error_ptr->SetErrorStringWithFormat( + "unable to extract %" PRIu64 " bytes from a %" PRIu64 + " byte scalar value.", + piece_byte_size, + (uint64_t)curr_piece_source_value.GetScalar() + .GetByteSize()); + return false; + } + curr_piece = curr_piece_source_value; + } break; + + case Value::eValueTypeVector: { + if (curr_piece_source_value.GetVector().length >= piece_byte_size) + curr_piece_source_value.GetVector().length = piece_byte_size; + else { + if (error_ptr) + error_ptr->SetErrorStringWithFormat( + "unable to extract %" PRIu64 " bytes from a %" PRIu64 + " byte vector value.", + piece_byte_size, + (uint64_t)curr_piece_source_value.GetVector().length); + return false; + } + } break; + } + + // Check if this is the first piece? + if (op_piece_offset == 0) { + // This is the first piece, we should push it back onto the stack so + // subsequent + // pieces will be able to access this piece and add to it + if (pieces.AppendDataToHostBuffer(curr_piece) == 0) { + if (error_ptr) + error_ptr->SetErrorString("failed to append piece data"); + return false; + } + } else { + // If this is the second or later piece there should be a value on + // the stack + if (pieces.GetBuffer().GetByteSize() != op_piece_offset) { + if (error_ptr) + error_ptr->SetErrorStringWithFormat( + "DW_OP_piece for offset %" PRIu64 + " but top of stack is of size %" PRIu64, + op_piece_offset, pieces.GetBuffer().GetByteSize()); + return false; + } + + if (pieces.AppendDataToHostBuffer(curr_piece) == 0) { + if (error_ptr) + error_ptr->SetErrorString("failed to append piece data"); + return false; + } + } + op_piece_offset += piece_byte_size; + } + } + } break; - //---------------------------------------------------------------------- - // OPCODE: DW_OP_call2 - // OPERANDS: - // uint16_t compile unit relative offset of a DIE - // DESCRIPTION: Performs subroutine calls during evaluation - // of a DWARF expression. The operand is the 2-byte unsigned offset - // of a debugging information entry in the current compilation unit. - // - // Operand interpretation is exactly like that for DW_FORM_ref2. - // - // This operation transfers control of DWARF expression evaluation - // to the DW_AT_location attribute of the referenced DIE. If there is - // no such attribute, then there is no effect. Execution of the DWARF - // expression of a DW_AT_location attribute may add to and/or remove from - // values on the stack. Execution returns to the point following the call - // when the end of the attribute is reached. Values on the stack at the - // time of the call may be used as parameters by the called expression - // and values left on the stack by the called expression may be used as - // return values by prior agreement between the calling and called - // expressions. - //---------------------------------------------------------------------- - case DW_OP_call2: - if (error_ptr) - error_ptr->SetErrorString ("Unimplemented opcode DW_OP_call2."); - return false; - //---------------------------------------------------------------------- - // OPCODE: DW_OP_call4 - // OPERANDS: 1 - // uint32_t compile unit relative offset of a DIE - // DESCRIPTION: Performs a subroutine call during evaluation of a DWARF - // expression. For DW_OP_call4, the operand is a 4-byte unsigned offset - // of a debugging information entry in the current compilation unit. - // - // Operand interpretation DW_OP_call4 is exactly like that for - // DW_FORM_ref4. - // - // This operation transfers control of DWARF expression evaluation - // to the DW_AT_location attribute of the referenced DIE. If there is - // no such attribute, then there is no effect. Execution of the DWARF - // expression of a DW_AT_location attribute may add to and/or remove from - // values on the stack. Execution returns to the point following the call - // when the end of the attribute is reached. Values on the stack at the - // time of the call may be used as parameters by the called expression - // and values left on the stack by the called expression may be used as - // return values by prior agreement between the calling and called - // expressions. - //---------------------------------------------------------------------- - case DW_OP_call4: + case DW_OP_bit_piece: // 0x9d ULEB128 bit size, ULEB128 bit offset (DWARF3); + if (stack.size() < 1) { + if (error_ptr) + error_ptr->SetErrorString( + "Expression stack needs at least 1 item for DW_OP_bit_piece."); + return false; + } else { + const uint64_t piece_bit_size = opcodes.GetULEB128(&offset); + const uint64_t piece_bit_offset = opcodes.GetULEB128(&offset); + switch (stack.back().GetValueType()) { + case Value::eValueTypeScalar: { + if (!stack.back().GetScalar().ExtractBitfield(piece_bit_size, + piece_bit_offset)) { if (error_ptr) - error_ptr->SetErrorString ("Unimplemented opcode DW_OP_call4."); + error_ptr->SetErrorStringWithFormat( + "unable to extract %" PRIu64 " bit value with %" PRIu64 + " bit offset from a %" PRIu64 " bit scalar value.", + piece_bit_size, piece_bit_offset, + (uint64_t)(stack.back().GetScalar().GetByteSize() * 8)); return false; + } + } break; + + case Value::eValueTypeFileAddress: + case Value::eValueTypeLoadAddress: + case Value::eValueTypeHostAddress: + if (error_ptr) { + error_ptr->SetErrorStringWithFormat( + "unable to extract DW_OP_bit_piece(bit_size = %" PRIu64 + ", bit_offset = %" PRIu64 ") from an addresss value.", + piece_bit_size, piece_bit_offset); + } + return false; + + case Value::eValueTypeVector: + if (error_ptr) { + error_ptr->SetErrorStringWithFormat( + "unable to extract DW_OP_bit_piece(bit_size = %" PRIu64 + ", bit_offset = %" PRIu64 ") from a vector value.", + piece_bit_size, piece_bit_offset); + } + return false; + } + } + break; + + //---------------------------------------------------------------------- + // OPCODE: DW_OP_push_object_address + // OPERANDS: none + // DESCRIPTION: Pushes the address of the object currently being + // evaluated as part of evaluation of a user presented expression. + // This object may correspond to an independent variable described by + // its own DIE or it may be a component of an array, structure, or class + // whose address has been dynamically determined by an earlier step + // during user expression evaluation. + //---------------------------------------------------------------------- + case DW_OP_push_object_address: + if (object_address_ptr) + stack.push_back(*object_address_ptr); + else { + if (error_ptr) + error_ptr->SetErrorString("DW_OP_push_object_address used without " + "specifying an object address"); + return false; + } + break; + + //---------------------------------------------------------------------- + // OPCODE: DW_OP_call2 + // OPERANDS: + // uint16_t compile unit relative offset of a DIE + // DESCRIPTION: Performs subroutine calls during evaluation + // of a DWARF expression. The operand is the 2-byte unsigned offset + // of a debugging information entry in the current compilation unit. + // + // Operand interpretation is exactly like that for DW_FORM_ref2. + // + // This operation transfers control of DWARF expression evaluation + // to the DW_AT_location attribute of the referenced DIE. If there is + // no such attribute, then there is no effect. Execution of the DWARF + // expression of a DW_AT_location attribute may add to and/or remove from + // values on the stack. Execution returns to the point following the call + // when the end of the attribute is reached. Values on the stack at the + // time of the call may be used as parameters by the called expression + // and values left on the stack by the called expression may be used as + // return values by prior agreement between the calling and called + // expressions. + //---------------------------------------------------------------------- + case DW_OP_call2: + if (error_ptr) + error_ptr->SetErrorString("Unimplemented opcode DW_OP_call2."); + return false; + //---------------------------------------------------------------------- + // OPCODE: DW_OP_call4 + // OPERANDS: 1 + // uint32_t compile unit relative offset of a DIE + // DESCRIPTION: Performs a subroutine call during evaluation of a DWARF + // expression. For DW_OP_call4, the operand is a 4-byte unsigned offset + // of a debugging information entry in the current compilation unit. + // + // Operand interpretation DW_OP_call4 is exactly like that for + // DW_FORM_ref4. + // + // This operation transfers control of DWARF expression evaluation + // to the DW_AT_location attribute of the referenced DIE. If there is + // no such attribute, then there is no effect. Execution of the DWARF + // expression of a DW_AT_location attribute may add to and/or remove from + // values on the stack. Execution returns to the point following the call + // when the end of the attribute is reached. Values on the stack at the + // time of the call may be used as parameters by the called expression + // and values left on the stack by the called expression may be used as + // return values by prior agreement between the calling and called + // expressions. + //---------------------------------------------------------------------- + case DW_OP_call4: + if (error_ptr) + error_ptr->SetErrorString("Unimplemented opcode DW_OP_call4."); + return false; + + //---------------------------------------------------------------------- + // OPCODE: DW_OP_stack_value + // OPERANDS: None + // DESCRIPTION: Specifies that the object does not exist in memory but + // rather is a constant value. The value from the top of the stack is + // the value to be used. This is the actual object value and not the + // location. + //---------------------------------------------------------------------- + case DW_OP_stack_value: + stack.back().SetValueType(Value::eValueTypeScalar); + break; + + //---------------------------------------------------------------------- + // OPCODE: DW_OP_call_frame_cfa + // OPERANDS: None + // DESCRIPTION: Specifies a DWARF expression that pushes the value of + // the canonical frame address consistent with the call frame information + // located in .debug_frame (or in the FDEs of the eh_frame section). + //---------------------------------------------------------------------- + case DW_OP_call_frame_cfa: + if (frame) { + // Note that we don't have to parse FDEs because this DWARF expression + // is commonly evaluated with a valid stack frame. + StackID id = frame->GetStackID(); + addr_t cfa = id.GetCallFrameAddress(); + if (cfa != LLDB_INVALID_ADDRESS) { + stack.push_back(Scalar(cfa)); + stack.back().SetValueType(Value::eValueTypeLoadAddress); + } else if (error_ptr) + error_ptr->SetErrorString("Stack frame does not include a canonical " + "frame address for DW_OP_call_frame_cfa " + "opcode."); + } else { + if (error_ptr) + error_ptr->SetErrorString("Invalid stack frame in context for " + "DW_OP_call_frame_cfa opcode."); + return false; + } + break; + + //---------------------------------------------------------------------- + // OPCODE: DW_OP_form_tls_address (or the old pre-DWARFv3 vendor extension + // opcode, DW_OP_GNU_push_tls_address) + // OPERANDS: none + // DESCRIPTION: Pops a TLS offset from the stack, converts it to + // an address in the current thread's thread-local storage block, + // and pushes it on the stack. + //---------------------------------------------------------------------- + case DW_OP_form_tls_address: + case DW_OP_GNU_push_tls_address: { + if (stack.size() < 1) { + if (error_ptr) { + if (op == DW_OP_form_tls_address) + error_ptr->SetErrorString( + "DW_OP_form_tls_address needs an argument."); + else + error_ptr->SetErrorString( + "DW_OP_GNU_push_tls_address needs an argument."); + } + return false; + } - //---------------------------------------------------------------------- - // OPCODE: DW_OP_stack_value - // OPERANDS: None - // DESCRIPTION: Specifies that the object does not exist in memory but - // rather is a constant value. The value from the top of the stack is - // the value to be used. This is the actual object value and not the - // location. - //---------------------------------------------------------------------- - case DW_OP_stack_value: - stack.back().SetValueType(Value::eValueTypeScalar); - break; + if (!exe_ctx || !module_sp) { + if (error_ptr) + error_ptr->SetErrorString("No context to evaluate TLS within."); + return false; + } - //---------------------------------------------------------------------- - // OPCODE: DW_OP_call_frame_cfa - // OPERANDS: None - // DESCRIPTION: Specifies a DWARF expression that pushes the value of - // the canonical frame address consistent with the call frame information - // located in .debug_frame (or in the FDEs of the eh_frame section). - //---------------------------------------------------------------------- - case DW_OP_call_frame_cfa: - if (frame) - { - // Note that we don't have to parse FDEs because this DWARF expression - // is commonly evaluated with a valid stack frame. - StackID id = frame->GetStackID(); - addr_t cfa = id.GetCallFrameAddress(); - if (cfa != LLDB_INVALID_ADDRESS) - { - stack.push_back(Scalar(cfa)); - stack.back().SetValueType (Value::eValueTypeLoadAddress); - } - else - if (error_ptr) - error_ptr->SetErrorString ("Stack frame does not include a canonical frame address for DW_OP_call_frame_cfa opcode."); - } - else - { - if (error_ptr) - error_ptr->SetErrorString ("Invalid stack frame in context for DW_OP_call_frame_cfa opcode."); - return false; - } - break; + Thread *thread = exe_ctx->GetThreadPtr(); + if (!thread) { + if (error_ptr) + error_ptr->SetErrorString("No thread to evaluate TLS within."); + return false; + } - //---------------------------------------------------------------------- - // OPCODE: DW_OP_form_tls_address (or the old pre-DWARFv3 vendor extension opcode, DW_OP_GNU_push_tls_address) - // OPERANDS: none - // DESCRIPTION: Pops a TLS offset from the stack, converts it to - // an address in the current thread's thread-local storage block, - // and pushes it on the stack. - //---------------------------------------------------------------------- - case DW_OP_form_tls_address: - case DW_OP_GNU_push_tls_address: - { - if (stack.size() < 1) - { - if (error_ptr) - { - if (op == DW_OP_form_tls_address) - error_ptr->SetErrorString("DW_OP_form_tls_address needs an argument."); - else - error_ptr->SetErrorString("DW_OP_GNU_push_tls_address needs an argument."); - } - return false; - } + // Lookup the TLS block address for this thread and module. + const addr_t tls_file_addr = + stack.back().GetScalar().ULongLong(LLDB_INVALID_ADDRESS); + const addr_t tls_load_addr = + thread->GetThreadLocalData(module_sp, tls_file_addr); - if (!exe_ctx || !module_sp) - { - if (error_ptr) - error_ptr->SetErrorString("No context to evaluate TLS within."); - return false; - } + if (tls_load_addr == LLDB_INVALID_ADDRESS) { + if (error_ptr) + error_ptr->SetErrorString( + "No TLS data currently exists for this thread."); + return false; + } + + stack.back().GetScalar() = tls_load_addr; + stack.back().SetValueType(Value::eValueTypeLoadAddress); + } break; + + //---------------------------------------------------------------------- + // OPCODE: DW_OP_GNU_addr_index + // OPERANDS: 1 + // ULEB128: index to the .debug_addr section + // DESCRIPTION: Pushes an address to the stack from the .debug_addr + // section with the base address specified by the DW_AT_addr_base + // attribute and the 0 based index is the ULEB128 encoded index. + //---------------------------------------------------------------------- + case DW_OP_GNU_addr_index: { + if (!dwarf_cu) { + if (error_ptr) + error_ptr->SetErrorString("DW_OP_GNU_addr_index found without a " + "compile unit being specified"); + return false; + } + uint64_t index = opcodes.GetULEB128(&offset); + uint32_t index_size = dwarf_cu->GetAddressByteSize(); + dw_offset_t addr_base = dwarf_cu->GetAddrBase(); + lldb::offset_t offset = addr_base + index * index_size; + uint64_t value = + dwarf_cu->GetSymbolFileDWARF()->get_debug_addr_data().GetMaxU64( + &offset, index_size); + stack.push_back(Scalar(value)); + stack.back().SetValueType(Value::eValueTypeFileAddress); + } break; + + //---------------------------------------------------------------------- + // OPCODE: DW_OP_GNU_const_index + // OPERANDS: 1 + // ULEB128: index to the .debug_addr section + // DESCRIPTION: Pushes an constant with the size of a machine address to + // the stack from the .debug_addr section with the base address specified + // by the DW_AT_addr_base attribute and the 0 based index is the ULEB128 + // encoded index. + //---------------------------------------------------------------------- + case DW_OP_GNU_const_index: { + if (!dwarf_cu) { + if (error_ptr) + error_ptr->SetErrorString("DW_OP_GNU_const_index found without a " + "compile unit being specified"); + return false; + } + uint64_t index = opcodes.GetULEB128(&offset); + uint32_t index_size = dwarf_cu->GetAddressByteSize(); + dw_offset_t addr_base = dwarf_cu->GetAddrBase(); + lldb::offset_t offset = addr_base + index * index_size; + const DWARFDataExtractor &debug_addr = + dwarf_cu->GetSymbolFileDWARF()->get_debug_addr_data(); + switch (index_size) { + case 4: + stack.push_back(Scalar(debug_addr.GetU32(&offset))); + break; + case 8: + stack.push_back(Scalar(debug_addr.GetU64(&offset))); + break; + default: + assert(false && "Unhandled index size"); + return false; + } + } break; + + default: + if (log) + log->Printf("Unhandled opcode %s in DWARFExpression.", + DW_OP_value_to_name(op)); + break; + } + } + + if (stack.empty()) { + // Nothing on the stack, check if we created a piece value from DW_OP_piece + // or DW_OP_bit_piece opcodes + if (pieces.GetBuffer().GetByteSize()) { + result = pieces; + } else { + if (error_ptr) + error_ptr->SetErrorString("Stack empty after evaluation."); + return false; + } + } else { + if (log && log->GetVerbose()) { + size_t count = stack.size(); + log->Printf("Stack after operation has %" PRIu64 " values:", + (uint64_t)count); + for (size_t i = 0; i < count; ++i) { + StreamString new_value; + new_value.Printf("[%" PRIu64 "]", (uint64_t)i); + stack[i].Dump(&new_value); + log->Printf(" %s", new_value.GetData()); + } + } + result = stack.back(); + } + return true; // Return true on success +} - Thread *thread = exe_ctx->GetThreadPtr(); - if (!thread) - { - if (error_ptr) - error_ptr->SetErrorString("No thread to evaluate TLS within."); - return false; - } +size_t DWARFExpression::LocationListSize(const DWARFCompileUnit *dwarf_cu, + const DataExtractor &debug_loc_data, + lldb::offset_t offset) { + const lldb::offset_t debug_loc_offset = offset; + while (debug_loc_data.ValidOffset(offset)) { + lldb::addr_t start_addr = LLDB_INVALID_ADDRESS; + lldb::addr_t end_addr = LLDB_INVALID_ADDRESS; + if (!AddressRangeForLocationListEntry(dwarf_cu, debug_loc_data, &offset, + start_addr, end_addr)) + break; + + if (start_addr == 0 && end_addr == 0) + break; + + uint16_t loc_length = debug_loc_data.GetU16(&offset); + offset += loc_length; + } + + if (offset > debug_loc_offset) + return offset - debug_loc_offset; + return 0; +} - // Lookup the TLS block address for this thread and module. - const addr_t tls_file_addr = stack.back().GetScalar().ULongLong(LLDB_INVALID_ADDRESS); - const addr_t tls_load_addr = thread->GetThreadLocalData(module_sp, tls_file_addr); +bool DWARFExpression::AddressRangeForLocationListEntry( + const DWARFCompileUnit *dwarf_cu, const DataExtractor &debug_loc_data, + lldb::offset_t *offset_ptr, lldb::addr_t &low_pc, lldb::addr_t &high_pc) { + if (!debug_loc_data.ValidOffset(*offset_ptr)) + return false; - if (tls_load_addr == LLDB_INVALID_ADDRESS) - { - if (error_ptr) - error_ptr->SetErrorString ("No TLS data currently exists for this thread."); - return false; - } + switch (dwarf_cu->GetSymbolFileDWARF()->GetLocationListFormat()) { + case NonLocationList: + return false; + case RegularLocationList: + low_pc = debug_loc_data.GetAddress(offset_ptr); + high_pc = debug_loc_data.GetAddress(offset_ptr); + return true; + case SplitDwarfLocationList: + switch (debug_loc_data.GetU8(offset_ptr)) { + case DW_LLE_end_of_list: + return false; + case DW_LLE_startx_endx: { + uint64_t index = debug_loc_data.GetULEB128(offset_ptr); + low_pc = ReadAddressFromDebugAddrSection(dwarf_cu, index); + index = debug_loc_data.GetULEB128(offset_ptr); + high_pc = ReadAddressFromDebugAddrSection(dwarf_cu, index); + return true; + } + case DW_LLE_startx_length: { + uint64_t index = debug_loc_data.GetULEB128(offset_ptr); + low_pc = ReadAddressFromDebugAddrSection(dwarf_cu, index); + uint32_t length = debug_loc_data.GetU32(offset_ptr); + high_pc = low_pc + length; + return true; + } + default: + // Not supported entry type + return false; + } + } + assert(false && "Not supported location list type"); + return false; +} - stack.back().GetScalar() = tls_load_addr; - stack.back().SetValueType (Value::eValueTypeLoadAddress); - } - break; +static bool print_dwarf_exp_op(Stream &s, const DataExtractor &data, + lldb::offset_t *offset_ptr, int address_size, + int dwarf_ref_size) { + uint8_t opcode = data.GetU8(offset_ptr); + DRC_class opcode_class; + uint64_t uint; + int64_t sint; - //---------------------------------------------------------------------- - // OPCODE: DW_OP_GNU_addr_index - // OPERANDS: 1 - // ULEB128: index to the .debug_addr section - // DESCRIPTION: Pushes an address to the stack from the .debug_addr - // section with the base address specified by the DW_AT_addr_base - // attribute and the 0 based index is the ULEB128 encoded index. - //---------------------------------------------------------------------- - case DW_OP_GNU_addr_index: - { - if (!dwarf_cu) - { - if (error_ptr) - error_ptr->SetErrorString ("DW_OP_GNU_addr_index found without a compile unit being specified"); - return false; - } - uint64_t index = opcodes.GetULEB128(&offset); - uint32_t index_size = dwarf_cu->GetAddressByteSize(); - dw_offset_t addr_base = dwarf_cu->GetAddrBase(); - lldb::offset_t offset = addr_base + index * index_size; - uint64_t value = dwarf_cu->GetSymbolFileDWARF()->get_debug_addr_data().GetMaxU64(&offset, index_size); - stack.push_back(Scalar(value)); - stack.back().SetValueType(Value::eValueTypeFileAddress); - } - break; + int size; - //---------------------------------------------------------------------- - // OPCODE: DW_OP_GNU_const_index - // OPERANDS: 1 - // ULEB128: index to the .debug_addr section - // DESCRIPTION: Pushes an constant with the size of a machine address to - // the stack from the .debug_addr section with the base address specified - // by the DW_AT_addr_base attribute and the 0 based index is the ULEB128 - // encoded index. - //---------------------------------------------------------------------- - case DW_OP_GNU_const_index: - { - if (!dwarf_cu) - { - if (error_ptr) - error_ptr->SetErrorString ("DW_OP_GNU_const_index found without a compile unit being specified"); - return false; - } - uint64_t index = opcodes.GetULEB128(&offset); - uint32_t index_size = dwarf_cu->GetAddressByteSize(); - dw_offset_t addr_base = dwarf_cu->GetAddrBase(); - lldb::offset_t offset = addr_base + index * index_size; - const DWARFDataExtractor& debug_addr = dwarf_cu->GetSymbolFileDWARF()->get_debug_addr_data(); - switch (index_size) - { - case 4: - stack.push_back(Scalar(debug_addr.GetU32(&offset))); - break; - case 8: - stack.push_back(Scalar(debug_addr.GetU64(&offset))); - break; - default: - assert(false && "Unhandled index size"); - return false; - } - } - break; + opcode_class = DW_OP_value_to_class(opcode) & (~DRC_DWARFv3); - default: - if (log) - log->Printf("Unhandled opcode %s in DWARFExpression.", DW_OP_value_to_name(op)); - break; - } - } + s.Printf("%s ", DW_OP_value_to_name(opcode)); - if (stack.empty()) - { - // Nothing on the stack, check if we created a piece value from DW_OP_piece or DW_OP_bit_piece opcodes - if (pieces.GetBuffer().GetByteSize()) - { - result = pieces; - } - else - { - if (error_ptr) - error_ptr->SetErrorString ("Stack empty after evaluation."); - return false; - } - } - else - { - if (log && log->GetVerbose()) - { - size_t count = stack.size(); - log->Printf("Stack after operation has %" PRIu64 " values:", (uint64_t)count); - for (size_t i=0; i<count; ++i) - { - StreamString new_value; - new_value.Printf("[%" PRIu64 "]", (uint64_t)i); - stack[i].Dump(&new_value); - log->Printf(" %s", new_value.GetData()); - } - } - result = stack.back(); - } - return true; // Return true on success + /* Does this take zero parameters? If so we can shortcut this function. */ + if (opcode_class == DRC_ZEROOPERANDS) + return true; + + if (opcode_class == DRC_TWOOPERANDS && opcode == DW_OP_bregx) { + uint = data.GetULEB128(offset_ptr); + sint = data.GetSLEB128(offset_ptr); + s.Printf("%" PRIu64 " %" PRIi64, uint, sint); + return true; + } + if (opcode_class != DRC_ONEOPERAND) { + s.Printf("UNKNOWN OP %u", opcode); + return false; + } + + switch (opcode) { + case DW_OP_addr: + size = address_size; + break; + case DW_OP_const1u: + size = 1; + break; + case DW_OP_const1s: + size = -1; + break; + case DW_OP_const2u: + size = 2; + break; + case DW_OP_const2s: + size = -2; + break; + case DW_OP_const4u: + size = 4; + break; + case DW_OP_const4s: + size = -4; + break; + case DW_OP_const8u: + size = 8; + break; + case DW_OP_const8s: + size = -8; + break; + case DW_OP_constu: + size = 128; + break; + case DW_OP_consts: + size = -128; + break; + case DW_OP_fbreg: + size = -128; + break; + case DW_OP_breg0: + case DW_OP_breg1: + case DW_OP_breg2: + case DW_OP_breg3: + case DW_OP_breg4: + case DW_OP_breg5: + case DW_OP_breg6: + case DW_OP_breg7: + case DW_OP_breg8: + case DW_OP_breg9: + case DW_OP_breg10: + case DW_OP_breg11: + case DW_OP_breg12: + case DW_OP_breg13: + case DW_OP_breg14: + case DW_OP_breg15: + case DW_OP_breg16: + case DW_OP_breg17: + case DW_OP_breg18: + case DW_OP_breg19: + case DW_OP_breg20: + case DW_OP_breg21: + case DW_OP_breg22: + case DW_OP_breg23: + case DW_OP_breg24: + case DW_OP_breg25: + case DW_OP_breg26: + case DW_OP_breg27: + case DW_OP_breg28: + case DW_OP_breg29: + case DW_OP_breg30: + case DW_OP_breg31: + size = -128; + break; + case DW_OP_pick: + case DW_OP_deref_size: + case DW_OP_xderef_size: + size = 1; + break; + case DW_OP_skip: + case DW_OP_bra: + size = -2; + break; + case DW_OP_call2: + size = 2; + break; + case DW_OP_call4: + size = 4; + break; + case DW_OP_call_ref: + size = dwarf_ref_size; + break; + case DW_OP_piece: + case DW_OP_plus_uconst: + case DW_OP_regx: + case DW_OP_GNU_addr_index: + case DW_OP_GNU_const_index: + size = 128; + break; + default: + s.Printf("UNKNOWN ONE-OPERAND OPCODE, #%u", opcode); + return true; + } + + switch (size) { + case -1: + sint = (int8_t)data.GetU8(offset_ptr); + s.Printf("%+" PRIi64, sint); + break; + case -2: + sint = (int16_t)data.GetU16(offset_ptr); + s.Printf("%+" PRIi64, sint); + break; + case -4: + sint = (int32_t)data.GetU32(offset_ptr); + s.Printf("%+" PRIi64, sint); + break; + case -8: + sint = (int64_t)data.GetU64(offset_ptr); + s.Printf("%+" PRIi64, sint); + break; + case -128: + sint = data.GetSLEB128(offset_ptr); + s.Printf("%+" PRIi64, sint); + break; + case 1: + uint = data.GetU8(offset_ptr); + s.Printf("0x%2.2" PRIx64, uint); + break; + case 2: + uint = data.GetU16(offset_ptr); + s.Printf("0x%4.4" PRIx64, uint); + break; + case 4: + uint = data.GetU32(offset_ptr); + s.Printf("0x%8.8" PRIx64, uint); + break; + case 8: + uint = data.GetU64(offset_ptr); + s.Printf("0x%16.16" PRIx64, uint); + break; + case 128: + uint = data.GetULEB128(offset_ptr); + s.Printf("0x%" PRIx64, uint); + break; + } + + return false; } -size_t -DWARFExpression::LocationListSize(const DWARFCompileUnit* dwarf_cu, - const DataExtractor& debug_loc_data, - lldb::offset_t offset) -{ - const lldb::offset_t debug_loc_offset = offset; - while (debug_loc_data.ValidOffset(offset)) - { - lldb::addr_t start_addr = LLDB_INVALID_ADDRESS; - lldb::addr_t end_addr = LLDB_INVALID_ADDRESS; - if (!AddressRangeForLocationListEntry(dwarf_cu, debug_loc_data, &offset, start_addr, end_addr)) - break; +bool DWARFExpression::PrintDWARFExpression(Stream &s, const DataExtractor &data, + int address_size, int dwarf_ref_size, + bool location_expression) { + int op_count = 0; + lldb::offset_t offset = 0; + while (data.ValidOffset(offset)) { + if (location_expression && op_count > 0) + return false; + if (op_count > 0) + s.PutCString(", "); + if (!print_dwarf_exp_op(s, data, &offset, address_size, dwarf_ref_size)) + return false; + op_count++; + } + + return true; +} - if (start_addr == 0 && end_addr == 0) - break; +void DWARFExpression::PrintDWARFLocationList( + Stream &s, const DWARFCompileUnit *cu, const DataExtractor &debug_loc_data, + lldb::offset_t offset) { + uint64_t start_addr, end_addr; + uint32_t addr_size = DWARFCompileUnit::GetAddressByteSize(cu); + s.SetAddressByteSize(DWARFCompileUnit::GetAddressByteSize(cu)); + dw_addr_t base_addr = cu ? cu->GetBaseAddress() : 0; + while (debug_loc_data.ValidOffset(offset)) { + start_addr = debug_loc_data.GetMaxU64(&offset, addr_size); + end_addr = debug_loc_data.GetMaxU64(&offset, addr_size); + + if (start_addr == 0 && end_addr == 0) + break; + + s.PutCString("\n "); + s.Indent(); + if (cu) + s.AddressRange(start_addr + base_addr, end_addr + base_addr, + cu->GetAddressByteSize(), NULL, ": "); + uint32_t loc_length = debug_loc_data.GetU16(&offset); + + DataExtractor locationData(debug_loc_data, offset, loc_length); + PrintDWARFExpression(s, locationData, addr_size, 4, false); + offset += loc_length; + } +} - uint16_t loc_length = debug_loc_data.GetU16(&offset); - offset += loc_length; - } +bool DWARFExpression::GetOpAndEndOffsets(StackFrame &frame, + lldb::offset_t &op_offset, + lldb::offset_t &end_offset) { + SymbolContext sc = frame.GetSymbolContext(eSymbolContextFunction); + if (!sc.function) { + return false; + } - if (offset > debug_loc_offset) - return offset - debug_loc_offset; - return 0; -} + addr_t loclist_base_file_addr = + sc.function->GetAddressRange().GetBaseAddress().GetFileAddress(); + if (loclist_base_file_addr == LLDB_INVALID_ADDRESS) { + return false; + } -bool -DWARFExpression::AddressRangeForLocationListEntry(const DWARFCompileUnit* dwarf_cu, - const DataExtractor& debug_loc_data, - lldb::offset_t* offset_ptr, - lldb::addr_t& low_pc, - lldb::addr_t& high_pc) -{ - if (!debug_loc_data.ValidOffset(*offset_ptr)) - return false; + addr_t pc_file_addr = frame.GetFrameCodeAddress().GetFileAddress(); + lldb::offset_t opcodes_offset, opcodes_length; + if (!GetLocation(loclist_base_file_addr, pc_file_addr, opcodes_offset, + opcodes_length)) { + return false; + } - switch (dwarf_cu->GetSymbolFileDWARF()->GetLocationListFormat()) - { - case NonLocationList: - return false; - case RegularLocationList: - low_pc = debug_loc_data.GetAddress(offset_ptr); - high_pc = debug_loc_data.GetAddress(offset_ptr); - return true; - case SplitDwarfLocationList: - switch (debug_loc_data.GetU8(offset_ptr)) - { - case DW_LLE_end_of_list_entry: - return false; - case DW_LLE_start_end_entry: - { - uint64_t index = debug_loc_data.GetULEB128(offset_ptr); - low_pc = ReadAddressFromDebugAddrSection(dwarf_cu, index); - index = debug_loc_data.GetULEB128(offset_ptr); - high_pc = ReadAddressFromDebugAddrSection(dwarf_cu, index); - return true; - } - case DW_LLE_start_length_entry: - { - uint64_t index = debug_loc_data.GetULEB128(offset_ptr); - low_pc = ReadAddressFromDebugAddrSection(dwarf_cu, index); - uint32_t length = debug_loc_data.GetU32(offset_ptr); - high_pc = low_pc + length; - return true; - } - default: - // Not supported entry type - return false; - } - } - assert (false && "Not supported location list type"); + if (opcodes_length == 0) { return false; + } + + op_offset = opcodes_offset; + end_offset = opcodes_offset + opcodes_length; + return true; } -static bool -print_dwarf_exp_op (Stream &s, - const DataExtractor& data, - lldb::offset_t *offset_ptr, - int address_size, - int dwarf_ref_size) -{ - uint8_t opcode = data.GetU8(offset_ptr); - DRC_class opcode_class; - uint64_t uint; - int64_t sint; +bool DWARFExpression::MatchesOperand(StackFrame &frame, + const Instruction::Operand &operand) { + using namespace OperandMatchers; - int size; + lldb::offset_t op_offset; + lldb::offset_t end_offset; + if (!GetOpAndEndOffsets(frame, op_offset, end_offset)) { + return false; + } - opcode_class = DW_OP_value_to_class (opcode) & (~DRC_DWARFv3); + if (!m_data.ValidOffset(op_offset) || op_offset >= end_offset) { + return false; + } - s.Printf("%s ", DW_OP_value_to_name (opcode)); + RegisterContextSP reg_ctx_sp = frame.GetRegisterContext(); + if (!reg_ctx_sp) { + return false; + } - /* Does this take zero parameters? If so we can shortcut this function. */ - if (opcode_class == DRC_ZEROOPERANDS) - return true; + DataExtractor opcodes = m_data; + uint8_t opcode = opcodes.GetU8(&op_offset); - if (opcode_class == DRC_TWOOPERANDS && opcode == DW_OP_bregx) - { - uint = data.GetULEB128(offset_ptr); - sint = data.GetSLEB128(offset_ptr); - s.Printf("%" PRIu64 " %" PRIi64, uint, sint); - return true; - } - if (opcode_class != DRC_ONEOPERAND) - { - s.Printf("UNKNOWN OP %u", opcode); - return false; - } + if (opcode == DW_OP_fbreg) { + int64_t offset = opcodes.GetSLEB128(&op_offset); - switch (opcode) - { - case DW_OP_addr: size = address_size; break; - case DW_OP_const1u: size = 1; break; - case DW_OP_const1s: size = -1; break; - case DW_OP_const2u: size = 2; break; - case DW_OP_const2s: size = -2; break; - case DW_OP_const4u: size = 4; break; - case DW_OP_const4s: size = -4; break; - case DW_OP_const8u: size = 8; break; - case DW_OP_const8s: size = -8; break; - case DW_OP_constu: size = 128; break; - case DW_OP_consts: size = -128; break; - case DW_OP_fbreg: size = -128; break; - case DW_OP_breg0: - case DW_OP_breg1: - case DW_OP_breg2: - case DW_OP_breg3: - case DW_OP_breg4: - case DW_OP_breg5: - case DW_OP_breg6: - case DW_OP_breg7: - case DW_OP_breg8: - case DW_OP_breg9: - case DW_OP_breg10: - case DW_OP_breg11: - case DW_OP_breg12: - case DW_OP_breg13: - case DW_OP_breg14: - case DW_OP_breg15: - case DW_OP_breg16: - case DW_OP_breg17: - case DW_OP_breg18: - case DW_OP_breg19: - case DW_OP_breg20: - case DW_OP_breg21: - case DW_OP_breg22: - case DW_OP_breg23: - case DW_OP_breg24: - case DW_OP_breg25: - case DW_OP_breg26: - case DW_OP_breg27: - case DW_OP_breg28: - case DW_OP_breg29: - case DW_OP_breg30: - case DW_OP_breg31: - size = -128; break; - case DW_OP_pick: - case DW_OP_deref_size: - case DW_OP_xderef_size: - size = 1; break; - case DW_OP_skip: - case DW_OP_bra: - size = -2; break; - case DW_OP_call2: - size = 2; break; - case DW_OP_call4: - size = 4; break; - case DW_OP_call_ref: - size = dwarf_ref_size; break; - case DW_OP_piece: - case DW_OP_plus_uconst: - case DW_OP_regx: - case DW_OP_GNU_addr_index: - case DW_OP_GNU_const_index: - size = 128; break; - default: - s.Printf("UNKNOWN ONE-OPERAND OPCODE, #%u", opcode); - return true; + DWARFExpression *fb_expr = frame.GetFrameBaseExpression(nullptr); + if (!fb_expr) { + return false; } - switch (size) - { - case -1: sint = (int8_t) data.GetU8(offset_ptr); s.Printf("%+" PRIi64, sint); break; - case -2: sint = (int16_t) data.GetU16(offset_ptr); s.Printf("%+" PRIi64, sint); break; - case -4: sint = (int32_t) data.GetU32(offset_ptr); s.Printf("%+" PRIi64, sint); break; - case -8: sint = (int64_t) data.GetU64(offset_ptr); s.Printf("%+" PRIi64, sint); break; - case -128: sint = data.GetSLEB128(offset_ptr); s.Printf("%+" PRIi64, sint); break; - case 1: uint = data.GetU8(offset_ptr); s.Printf("0x%2.2" PRIx64, uint); break; - case 2: uint = data.GetU16(offset_ptr); s.Printf("0x%4.4" PRIx64, uint); break; - case 4: uint = data.GetU32(offset_ptr); s.Printf("0x%8.8" PRIx64, uint); break; - case 8: uint = data.GetU64(offset_ptr); s.Printf("0x%16.16" PRIx64, uint); break; - case 128: uint = data.GetULEB128(offset_ptr); s.Printf("0x%" PRIx64, uint); break; + auto recurse = [&frame, fb_expr](const Instruction::Operand &child) { + return fb_expr->MatchesOperand(frame, child); + }; + + if (!offset && + MatchUnaryOp(MatchOpType(Instruction::Operand::Type::Dereference), + recurse)(operand)) { + return true; } + return MatchUnaryOp( + MatchOpType(Instruction::Operand::Type::Dereference), + MatchBinaryOp(MatchOpType(Instruction::Operand::Type::Sum), + MatchImmOp(offset), recurse))(operand); + } + + bool dereference = false; + const RegisterInfo *reg = nullptr; + int64_t offset = 0; + + if (opcode >= DW_OP_reg0 && opcode <= DW_OP_reg31) { + reg = reg_ctx_sp->GetRegisterInfo(m_reg_kind, opcode - DW_OP_reg0); + } else if (opcode >= DW_OP_breg0 && opcode <= DW_OP_breg31) { + offset = opcodes.GetSLEB128(&op_offset); + reg = reg_ctx_sp->GetRegisterInfo(m_reg_kind, opcode - DW_OP_breg0); + } else if (opcode == DW_OP_regx) { + uint32_t reg_num = static_cast<uint32_t>(opcodes.GetULEB128(&op_offset)); + reg = reg_ctx_sp->GetRegisterInfo(m_reg_kind, reg_num); + } else if (opcode == DW_OP_bregx) { + uint32_t reg_num = static_cast<uint32_t>(opcodes.GetULEB128(&op_offset)); + offset = opcodes.GetSLEB128(&op_offset); + reg = reg_ctx_sp->GetRegisterInfo(m_reg_kind, reg_num); + } else { return false; -} + } -bool -DWARFExpression::PrintDWARFExpression(Stream &s, - const DataExtractor& data, - int address_size, - int dwarf_ref_size, - bool location_expression) -{ - int op_count = 0; - lldb::offset_t offset = 0; - while (data.ValidOffset(offset)) - { - if (location_expression && op_count > 0) - return false; - if (op_count > 0) - s.PutCString(", "); - if (!print_dwarf_exp_op (s, data, &offset, address_size, dwarf_ref_size)) - return false; - op_count++; + if (!reg) { + return false; + } + + if (dereference) { + if (!offset && + MatchUnaryOp(MatchOpType(Instruction::Operand::Type::Dereference), + MatchRegOp(*reg))(operand)) { + return true; } - return true; + return MatchUnaryOp( + MatchOpType(Instruction::Operand::Type::Dereference), + MatchBinaryOp(MatchOpType(Instruction::Operand::Type::Sum), + MatchRegOp(*reg), + MatchImmOp(offset)))(operand); + } else { + return MatchRegOp(*reg)(operand); + } } -void -DWARFExpression::PrintDWARFLocationList(Stream &s, - const DWARFCompileUnit* cu, - const DataExtractor& debug_loc_data, - lldb::offset_t offset) -{ - uint64_t start_addr, end_addr; - uint32_t addr_size = DWARFCompileUnit::GetAddressByteSize(cu); - s.SetAddressByteSize(DWARFCompileUnit::GetAddressByteSize(cu)); - dw_addr_t base_addr = cu ? cu->GetBaseAddress() : 0; - while (debug_loc_data.ValidOffset(offset)) - { - start_addr = debug_loc_data.GetMaxU64(&offset,addr_size); - end_addr = debug_loc_data.GetMaxU64(&offset,addr_size); - - if (start_addr == 0 && end_addr == 0) - break; - - s.PutCString("\n "); - s.Indent(); - if (cu) - s.AddressRange (start_addr + base_addr, - end_addr + base_addr, - cu->GetAddressByteSize(), - NULL, - ": "); - uint32_t loc_length = debug_loc_data.GetU16(&offset); - - DataExtractor locationData(debug_loc_data, offset, loc_length); - PrintDWARFExpression (s, locationData, addr_size, 4, false); - offset += loc_length; - } -} diff --git a/source/Expression/DiagnosticManager.cpp b/source/Expression/DiagnosticManager.cpp index 5156ee38a67b..ad06600e098a 100644 --- a/source/Expression/DiagnosticManager.cpp +++ b/source/Expression/DiagnosticManager.cpp @@ -16,76 +16,66 @@ using namespace lldb_private; -void -DiagnosticManager::Dump(Log *log) -{ - if (!log) - return; +void DiagnosticManager::Dump(Log *log) { + if (!log) + return; - std::string str = GetString(); + std::string str = GetString(); - // GetString() puts a separator after each diagnostic. - // We want to remove the last '\n' because log->PutCString will add one for us. + // GetString() puts a separator after each diagnostic. + // We want to remove the last '\n' because log->PutCString will add one for + // us. - if (str.size() && str.back() == '\n') - { - str.pop_back(); - } + if (str.size() && str.back() == '\n') { + str.pop_back(); + } - log->PutCString(str.c_str()); + log->PutCString(str.c_str()); } -static const char * -StringForSeverity(DiagnosticSeverity severity) -{ - switch (severity) - { - // this should be exhaustive - case lldb_private::eDiagnosticSeverityError: - return "error: "; - case lldb_private::eDiagnosticSeverityWarning: - return "warning: "; - case lldb_private::eDiagnosticSeverityRemark: - return ""; - } - llvm_unreachable("switch needs another case for DiagnosticSeverity enum"); +static const char *StringForSeverity(DiagnosticSeverity severity) { + switch (severity) { + // this should be exhaustive + case lldb_private::eDiagnosticSeverityError: + return "error: "; + case lldb_private::eDiagnosticSeverityWarning: + return "warning: "; + case lldb_private::eDiagnosticSeverityRemark: + return ""; + } + llvm_unreachable("switch needs another case for DiagnosticSeverity enum"); } -std::string -DiagnosticManager::GetString(char separator) -{ - std::string ret; +std::string DiagnosticManager::GetString(char separator) { + std::string ret; - for (const Diagnostic *diagnostic : Diagnostics()) - { - ret.append(StringForSeverity(diagnostic->GetSeverity())); - ret.append(diagnostic->GetMessage()); - ret.push_back(separator); - } + for (const Diagnostic *diagnostic : Diagnostics()) { + ret.append(StringForSeverity(diagnostic->GetSeverity())); + ret.append(diagnostic->GetMessage()); + ret.push_back(separator); + } - return ret; + return ret; } -size_t -DiagnosticManager::Printf(DiagnosticSeverity severity, const char *format, ...) -{ - StreamString ss; +size_t DiagnosticManager::Printf(DiagnosticSeverity severity, + const char *format, ...) { + StreamString ss; - va_list args; - va_start(args, format); - size_t result = ss.PrintfVarArg(format, args); - va_end(args); + va_list args; + va_start(args, format); + size_t result = ss.PrintfVarArg(format, args); + va_end(args); - AddDiagnostic(ss.GetData(), severity, eDiagnosticOriginLLDB); + AddDiagnostic(ss.GetString(), severity, eDiagnosticOriginLLDB); - return result; + return result; } -size_t -DiagnosticManager::PutCString(DiagnosticSeverity severity, const char *cstr) -{ - if (!cstr) - return 0; - AddDiagnostic(cstr, severity, eDiagnosticOriginLLDB); - return strlen(cstr); +size_t DiagnosticManager::PutString(DiagnosticSeverity severity, + llvm::StringRef str) { + if (str.empty()) + return 0; + AddDiagnostic(str, severity, eDiagnosticOriginLLDB); + return str.size(); } diff --git a/source/Expression/Expression.cpp b/source/Expression/Expression.cpp index e5dd9c03db7d..285079a85b43 100644 --- a/source/Expression/Expression.cpp +++ b/source/Expression/Expression.cpp @@ -1,4 +1,4 @@ -//===-- Expression.h ---------------------------------------*- C++ -*-===// +//===-- Expression.cpp ------------------------------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -13,20 +13,17 @@ using namespace lldb_private; -Expression::Expression (Target &target) : - m_target_wp (target.shared_from_this()), - m_jit_start_addr (LLDB_INVALID_ADDRESS), - m_jit_end_addr (LLDB_INVALID_ADDRESS) -{ - // Can't make any kind of expression without a target. - assert (m_target_wp.lock()); +Expression::Expression(Target &target) + : m_target_wp(target.shared_from_this()), + m_jit_start_addr(LLDB_INVALID_ADDRESS), + m_jit_end_addr(LLDB_INVALID_ADDRESS) { + // Can't make any kind of expression without a target. + assert(m_target_wp.lock()); } -Expression::Expression (ExecutionContextScope &exe_scope) : - m_target_wp (exe_scope.CalculateTarget()), - m_jit_start_addr (LLDB_INVALID_ADDRESS), - m_jit_end_addr (LLDB_INVALID_ADDRESS) -{ - assert (m_target_wp.lock()); +Expression::Expression(ExecutionContextScope &exe_scope) + : m_target_wp(exe_scope.CalculateTarget()), + m_jit_start_addr(LLDB_INVALID_ADDRESS), + m_jit_end_addr(LLDB_INVALID_ADDRESS) { + assert(m_target_wp.lock()); } - diff --git a/source/Expression/ExpressionSourceCode.cpp b/source/Expression/ExpressionSourceCode.cpp index 2d41d1a8b449..90a9ff2ffa06 100644 --- a/source/Expression/ExpressionSourceCode.cpp +++ b/source/Expression/ExpressionSourceCode.cpp @@ -9,12 +9,12 @@ #include "lldb/Expression/ExpressionSourceCode.h" -#include "lldb/Core/StreamString.h" #include "Plugins/ExpressionParser/Clang/ClangModulesDeclVendor.h" #include "Plugins/ExpressionParser/Clang/ClangPersistentVariables.h" +#include "lldb/Core/StreamString.h" +#include "lldb/Symbol/Block.h" #include "lldb/Symbol/CompileUnit.h" #include "lldb/Symbol/DebugMacros.h" -#include "lldb/Symbol/Block.h" #include "lldb/Symbol/TypeSystem.h" #include "lldb/Symbol/VariableList.h" #include "lldb/Target/ExecutionContext.h" @@ -25,8 +25,7 @@ using namespace lldb_private; -const char * -ExpressionSourceCode::g_expression_prefix = R"( +const char *ExpressionSourceCode::g_expression_prefix = R"( #ifndef NULL #define NULL (__null) #endif @@ -62,366 +61,324 @@ extern "C" )"; static const char *c_start_marker = " /*LLDB_BODY_START*/\n "; -static const char *c_end_marker = ";\n /*LLDB_BODY_END*/\n"; +static const char *c_end_marker = ";\n /*LLDB_BODY_END*/\n"; namespace { -class AddMacroState -{ - enum State - { - CURRENT_FILE_NOT_YET_PUSHED, - CURRENT_FILE_PUSHED, - CURRENT_FILE_POPPED - }; +class AddMacroState { + enum State { + CURRENT_FILE_NOT_YET_PUSHED, + CURRENT_FILE_PUSHED, + CURRENT_FILE_POPPED + }; public: - AddMacroState(const FileSpec ¤t_file, const uint32_t current_file_line) - : m_state(CURRENT_FILE_NOT_YET_PUSHED), - m_current_file(current_file), - m_current_file_line(current_file_line) - { } - - void - StartFile(const FileSpec &file) - { - m_file_stack.push_back(file); - if (file == m_current_file) - m_state = CURRENT_FILE_PUSHED; - } + AddMacroState(const FileSpec ¤t_file, const uint32_t current_file_line) + : m_state(CURRENT_FILE_NOT_YET_PUSHED), m_current_file(current_file), + m_current_file_line(current_file_line) {} - void - EndFile() - { - if (m_file_stack.size() == 0) - return; + void StartFile(const FileSpec &file) { + m_file_stack.push_back(file); + if (file == m_current_file) + m_state = CURRENT_FILE_PUSHED; + } - FileSpec old_top = m_file_stack.back(); - m_file_stack.pop_back(); - if (old_top == m_current_file) - m_state = CURRENT_FILE_POPPED; - } + void EndFile() { + if (m_file_stack.size() == 0) + return; - // An entry is valid if it occurs before the current line in - // the current file. - bool - IsValidEntry(uint32_t line) - { - switch (m_state) - { - case CURRENT_FILE_NOT_YET_PUSHED: - return true; - case CURRENT_FILE_PUSHED: - // If we are in file included in the current file, - // the entry should be added. - if (m_file_stack.back() != m_current_file) - return true; - - if (line >= m_current_file_line) - return false; - else - return true; - default: - return false; - } + FileSpec old_top = m_file_stack.back(); + m_file_stack.pop_back(); + if (old_top == m_current_file) + m_state = CURRENT_FILE_POPPED; + } + + // An entry is valid if it occurs before the current line in + // the current file. + bool IsValidEntry(uint32_t line) { + switch (m_state) { + case CURRENT_FILE_NOT_YET_PUSHED: + return true; + case CURRENT_FILE_PUSHED: + // If we are in file included in the current file, + // the entry should be added. + if (m_file_stack.back() != m_current_file) + return true; + + if (line >= m_current_file_line) + return false; + else + return true; + default: + return false; } + } private: - std::vector<FileSpec> m_file_stack; - State m_state; - FileSpec m_current_file; - uint32_t m_current_file_line; + std::vector<FileSpec> m_file_stack; + State m_state; + FileSpec m_current_file; + uint32_t m_current_file_line; }; } // anonymous namespace -static void -AddMacros(const DebugMacros *dm, CompileUnit *comp_unit, AddMacroState &state, StreamString &stream) -{ - if (dm == nullptr) - return; +static void AddMacros(const DebugMacros *dm, CompileUnit *comp_unit, + AddMacroState &state, StreamString &stream) { + if (dm == nullptr) + return; - for (size_t i = 0; i < dm->GetNumMacroEntries(); i++) - { - const DebugMacroEntry &entry = dm->GetMacroEntryAtIndex(i); - uint32_t line; - - switch (entry.GetType()) - { - case DebugMacroEntry::DEFINE: - if (state.IsValidEntry(entry.GetLineNumber())) - stream.Printf("#define %s\n", entry.GetMacroString().AsCString()); - else - return; - break; - case DebugMacroEntry::UNDEF: - if (state.IsValidEntry(entry.GetLineNumber())) - stream.Printf("#undef %s\n", entry.GetMacroString().AsCString()); - else - return; - break; - case DebugMacroEntry::START_FILE: - line = entry.GetLineNumber(); - if (state.IsValidEntry(line)) - state.StartFile(entry.GetFileSpec(comp_unit)); - else - return; - break; - case DebugMacroEntry::END_FILE: - state.EndFile(); - break; - case DebugMacroEntry::INDIRECT: - AddMacros(entry.GetIndirectDebugMacros(), comp_unit, state, stream); - break; - default: - // This is an unknown/invalid entry. Ignore. - break; - } + for (size_t i = 0; i < dm->GetNumMacroEntries(); i++) { + const DebugMacroEntry &entry = dm->GetMacroEntryAtIndex(i); + uint32_t line; + + switch (entry.GetType()) { + case DebugMacroEntry::DEFINE: + if (state.IsValidEntry(entry.GetLineNumber())) + stream.Printf("#define %s\n", entry.GetMacroString().AsCString()); + else + return; + break; + case DebugMacroEntry::UNDEF: + if (state.IsValidEntry(entry.GetLineNumber())) + stream.Printf("#undef %s\n", entry.GetMacroString().AsCString()); + else + return; + break; + case DebugMacroEntry::START_FILE: + line = entry.GetLineNumber(); + if (state.IsValidEntry(line)) + state.StartFile(entry.GetFileSpec(comp_unit)); + else + return; + break; + case DebugMacroEntry::END_FILE: + state.EndFile(); + break; + case DebugMacroEntry::INDIRECT: + AddMacros(entry.GetIndirectDebugMacros(), comp_unit, state, stream); + break; + default: + // This is an unknown/invalid entry. Ignore. + break; } + } } -static void -AddLocalVariableDecls(const lldb::VariableListSP &var_list_sp, StreamString &stream) -{ - for (size_t i = 0; i < var_list_sp->GetSize(); i++) - { - lldb::VariableSP var_sp = var_list_sp->GetVariableAtIndex(i); +static void AddLocalVariableDecls(const lldb::VariableListSP &var_list_sp, + StreamString &stream) { + for (size_t i = 0; i < var_list_sp->GetSize(); i++) { + lldb::VariableSP var_sp = var_list_sp->GetVariableAtIndex(i); - ConstString var_name = var_sp->GetName(); - if (!var_name || var_name == ConstString("this") || var_name == ConstString(".block_descriptor")) - continue; + ConstString var_name = var_sp->GetName(); + if (!var_name || var_name == ConstString("this") || + var_name == ConstString(".block_descriptor")) + continue; - stream.Printf("using $__lldb_local_vars::%s;\n", var_name.AsCString()); - } + stream.Printf("using $__lldb_local_vars::%s;\n", var_name.AsCString()); + } } -bool ExpressionSourceCode::GetText (std::string &text, lldb::LanguageType wrapping_language, bool static_method, ExecutionContext &exe_ctx) const -{ - const char *target_specific_defines = "typedef signed char BOOL;\n"; - std::string module_macros; - - Target *target = exe_ctx.GetTargetPtr(); - if (target) - { - if (target->GetArchitecture().GetMachine() == llvm::Triple::aarch64) - { - target_specific_defines = "typedef bool BOOL;\n"; - } - if (target->GetArchitecture().GetMachine() == llvm::Triple::x86_64) - { - if (lldb::PlatformSP platform_sp = target->GetPlatform()) - { - static ConstString g_platform_ios_simulator ("ios-simulator"); - if (platform_sp->GetPluginName() == g_platform_ios_simulator) - { - target_specific_defines = "typedef bool BOOL;\n"; - } - } +bool ExpressionSourceCode::GetText(std::string &text, + lldb::LanguageType wrapping_language, + bool static_method, + ExecutionContext &exe_ctx) const { + const char *target_specific_defines = "typedef signed char BOOL;\n"; + std::string module_macros; + + Target *target = exe_ctx.GetTargetPtr(); + if (target) { + if (target->GetArchitecture().GetMachine() == llvm::Triple::aarch64) { + target_specific_defines = "typedef bool BOOL;\n"; + } + if (target->GetArchitecture().GetMachine() == llvm::Triple::x86_64) { + if (lldb::PlatformSP platform_sp = target->GetPlatform()) { + static ConstString g_platform_ios_simulator("ios-simulator"); + if (platform_sp->GetPluginName() == g_platform_ios_simulator) { + target_specific_defines = "typedef bool BOOL;\n"; } - - if (ClangModulesDeclVendor *decl_vendor = target->GetClangModulesDeclVendor()) - { - ClangPersistentVariables *persistent_vars = llvm::cast<ClangPersistentVariables>(target->GetPersistentExpressionStateForLanguage(lldb::eLanguageTypeC)); - const ClangModulesDeclVendor::ModuleVector &hand_imported_modules = persistent_vars->GetHandLoadedClangModules(); - ClangModulesDeclVendor::ModuleVector modules_for_macros; - - for (ClangModulesDeclVendor::ModuleID module : hand_imported_modules) - { - modules_for_macros.push_back(module); - } - - if (target->GetEnableAutoImportClangModules()) - { - if (StackFrame *frame = exe_ctx.GetFramePtr()) - { - if (Block *block = frame->GetFrameBlock()) - { - SymbolContext sc; - - block->CalculateSymbolContext(&sc); - - if (sc.comp_unit) - { - StreamString error_stream; - - decl_vendor->AddModulesForCompileUnit(*sc.comp_unit, modules_for_macros, error_stream); - } - } - } + } + } + + if (ClangModulesDeclVendor *decl_vendor = + target->GetClangModulesDeclVendor()) { + ClangPersistentVariables *persistent_vars = + llvm::cast<ClangPersistentVariables>( + target->GetPersistentExpressionStateForLanguage( + lldb::eLanguageTypeC)); + const ClangModulesDeclVendor::ModuleVector &hand_imported_modules = + persistent_vars->GetHandLoadedClangModules(); + ClangModulesDeclVendor::ModuleVector modules_for_macros; + + for (ClangModulesDeclVendor::ModuleID module : hand_imported_modules) { + modules_for_macros.push_back(module); + } + + if (target->GetEnableAutoImportClangModules()) { + if (StackFrame *frame = exe_ctx.GetFramePtr()) { + if (Block *block = frame->GetFrameBlock()) { + SymbolContext sc; + + block->CalculateSymbolContext(&sc); + + if (sc.comp_unit) { + StreamString error_stream; + + decl_vendor->AddModulesForCompileUnit( + *sc.comp_unit, modules_for_macros, error_stream); } - - decl_vendor->ForEachMacro(modules_for_macros, [&module_macros] (const std::string &expansion) -> bool { - module_macros.append(expansion); - module_macros.append("\n"); - return false; - }); + } } + } + decl_vendor->ForEachMacro( + modules_for_macros, + [&module_macros](const std::string &expansion) -> bool { + module_macros.append(expansion); + module_macros.append("\n"); + return false; + }); } + } - StreamString debug_macros_stream; - StreamString lldb_local_var_decls; - if (StackFrame *frame = exe_ctx.GetFramePtr()) - { - const SymbolContext &sc = frame->GetSymbolContext( - lldb:: eSymbolContextCompUnit | lldb::eSymbolContextLineEntry); - - if (sc.comp_unit && sc.line_entry.IsValid()) - { - DebugMacros *dm = sc.comp_unit->GetDebugMacros(); - if (dm) - { - AddMacroState state(sc.line_entry.file, sc.line_entry.line); - AddMacros(dm, sc.comp_unit, state, debug_macros_stream); - } - } + StreamString debug_macros_stream; + StreamString lldb_local_var_decls; + if (StackFrame *frame = exe_ctx.GetFramePtr()) { + const SymbolContext &sc = frame->GetSymbolContext( + lldb::eSymbolContextCompUnit | lldb::eSymbolContextLineEntry); - ConstString object_name; - if (Language::LanguageIsCPlusPlus(frame->GetLanguage())) - { - if (target->GetInjectLocalVariables(&exe_ctx)) - { - lldb::VariableListSP var_list_sp = frame->GetInScopeVariableList(false, true); - AddLocalVariableDecls(var_list_sp, lldb_local_var_decls); - } - } + if (sc.comp_unit && sc.line_entry.IsValid()) { + DebugMacros *dm = sc.comp_unit->GetDebugMacros(); + if (dm) { + AddMacroState state(sc.line_entry.file, sc.line_entry.line); + AddMacros(dm, sc.comp_unit, state, debug_macros_stream); + } } - if (m_wrap) - { - switch (wrapping_language) - { - default: - return false; - case lldb::eLanguageTypeC: - case lldb::eLanguageTypeC_plus_plus: - case lldb::eLanguageTypeObjC: - break; - } - - StreamString wrap_stream; - - wrap_stream.Printf("%s\n%s\n%s\n%s\n%s\n", - module_macros.c_str(), - debug_macros_stream.GetData(), - g_expression_prefix, - target_specific_defines, - m_prefix.c_str()); - - // First construct a tagged form of the user expression so we can find it later: - std::string tagged_body; - switch (wrapping_language) - { - default: - tagged_body = m_body; - break; - case lldb::eLanguageTypeC: - case lldb::eLanguageTypeC_plus_plus: - case lldb::eLanguageTypeObjC: - tagged_body.append(c_start_marker); - tagged_body.append(m_body); - tagged_body.append(c_end_marker); - break; - - } - switch (wrapping_language) - { - default: - break; - case lldb::eLanguageTypeC: - wrap_stream.Printf("void \n" - "%s(void *$__lldb_arg) \n" - "{ \n" - " %s; \n" - "%s" - "} \n", - m_name.c_str(), - lldb_local_var_decls.GetData(), - tagged_body.c_str()); - break; - case lldb::eLanguageTypeC_plus_plus: - wrap_stream.Printf("void \n" - "$__lldb_class::%s(void *$__lldb_arg) \n" - "{ \n" - " %s; \n" - "%s" - "} \n", - m_name.c_str(), - lldb_local_var_decls.GetData(), - tagged_body.c_str()); - break; - case lldb::eLanguageTypeObjC: - if (static_method) - { - wrap_stream.Printf("@interface $__lldb_objc_class ($__lldb_category) \n" - "+(void)%s:(void *)$__lldb_arg; \n" - "@end \n" - "@implementation $__lldb_objc_class ($__lldb_category) \n" - "+(void)%s:(void *)$__lldb_arg \n" - "{ \n" - "%s" - "} \n" - "@end \n", - m_name.c_str(), - m_name.c_str(), - tagged_body.c_str()); - } - else - { - wrap_stream.Printf("@interface $__lldb_objc_class ($__lldb_category) \n" - "-(void)%s:(void *)$__lldb_arg; \n" - "@end \n" - "@implementation $__lldb_objc_class ($__lldb_category) \n" - "-(void)%s:(void *)$__lldb_arg \n" - "{ \n" - "%s" - "} \n" - "@end \n", - m_name.c_str(), - m_name.c_str(), - tagged_body.c_str()); - } - break; - } - - text = wrap_stream.GetString(); + ConstString object_name; + if (Language::LanguageIsCPlusPlus(frame->GetLanguage())) { + if (target->GetInjectLocalVariables(&exe_ctx)) { + lldb::VariableListSP var_list_sp = + frame->GetInScopeVariableList(false, true); + AddLocalVariableDecls(var_list_sp, lldb_local_var_decls); + } } - else - { - text.append(m_body); + } + + if (m_wrap) { + switch (wrapping_language) { + default: + return false; + case lldb::eLanguageTypeC: + case lldb::eLanguageTypeC_plus_plus: + case lldb::eLanguageTypeObjC: + break; } - return true; -} + StreamString wrap_stream; -bool -ExpressionSourceCode::GetOriginalBodyBounds(std::string transformed_text, - lldb::LanguageType wrapping_language, - size_t &start_loc, - size_t &end_loc) -{ - const char *start_marker; - const char *end_marker; - - switch (wrapping_language) - { + wrap_stream.Printf("%s\n%s\n%s\n%s\n%s\n", module_macros.c_str(), + debug_macros_stream.GetData(), g_expression_prefix, + target_specific_defines, m_prefix.c_str()); + + // First construct a tagged form of the user expression so we can find it + // later: + std::string tagged_body; + switch (wrapping_language) { default: - return false; + tagged_body = m_body; + break; case lldb::eLanguageTypeC: case lldb::eLanguageTypeC_plus_plus: case lldb::eLanguageTypeObjC: - start_marker = c_start_marker; - end_marker = c_end_marker; - break; + tagged_body.append(c_start_marker); + tagged_body.append(m_body); + tagged_body.append(c_end_marker); + break; } - - start_loc = transformed_text.find(start_marker); - if (start_loc == std::string::npos) - return false; - start_loc += strlen(start_marker); - end_loc = transformed_text.find(end_marker); - if (end_loc == std::string::npos) - return false; - return true; + switch (wrapping_language) { + default: + break; + case lldb::eLanguageTypeC: + wrap_stream.Printf("void \n" + "%s(void *$__lldb_arg) \n" + "{ \n" + " %s; \n" + "%s" + "} \n", + m_name.c_str(), lldb_local_var_decls.GetData(), + tagged_body.c_str()); + break; + case lldb::eLanguageTypeC_plus_plus: + wrap_stream.Printf("void \n" + "$__lldb_class::%s(void *$__lldb_arg) \n" + "{ \n" + " %s; \n" + "%s" + "} \n", + m_name.c_str(), lldb_local_var_decls.GetData(), + tagged_body.c_str()); + break; + case lldb::eLanguageTypeObjC: + if (static_method) { + wrap_stream.Printf( + "@interface $__lldb_objc_class ($__lldb_category) \n" + "+(void)%s:(void *)$__lldb_arg; \n" + "@end \n" + "@implementation $__lldb_objc_class ($__lldb_category) \n" + "+(void)%s:(void *)$__lldb_arg \n" + "{ \n" + "%s" + "} \n" + "@end \n", + m_name.c_str(), m_name.c_str(), tagged_body.c_str()); + } else { + wrap_stream.Printf( + "@interface $__lldb_objc_class ($__lldb_category) \n" + "-(void)%s:(void *)$__lldb_arg; \n" + "@end \n" + "@implementation $__lldb_objc_class ($__lldb_category) \n" + "-(void)%s:(void *)$__lldb_arg \n" + "{ \n" + "%s" + "} \n" + "@end \n", + m_name.c_str(), m_name.c_str(), tagged_body.c_str()); + } + break; + } + + text = wrap_stream.GetString(); + } else { + text.append(m_body); + } + + return true; } +bool ExpressionSourceCode::GetOriginalBodyBounds( + std::string transformed_text, lldb::LanguageType wrapping_language, + size_t &start_loc, size_t &end_loc) { + const char *start_marker; + const char *end_marker; + + switch (wrapping_language) { + default: + return false; + case lldb::eLanguageTypeC: + case lldb::eLanguageTypeC_plus_plus: + case lldb::eLanguageTypeObjC: + start_marker = c_start_marker; + end_marker = c_end_marker; + break; + } + + start_loc = transformed_text.find(start_marker); + if (start_loc == std::string::npos) + return false; + start_loc += strlen(start_marker); + end_loc = transformed_text.find(end_marker); + if (end_loc == std::string::npos) + return false; + return true; +} diff --git a/source/Expression/ExpressionVariable.cpp b/source/Expression/ExpressionVariable.cpp index 5567ee286aa9..00e689622949 100644 --- a/source/Expression/ExpressionVariable.cpp +++ b/source/Expression/ExpressionVariable.cpp @@ -7,84 +7,76 @@ // //===----------------------------------------------------------------------===// -#include "lldb/Core/Log.h" #include "lldb/Expression/ExpressionVariable.h" +#include "lldb/Core/Log.h" #include "lldb/Expression/IRExecutionUnit.h" using namespace lldb_private; -ExpressionVariable::~ExpressionVariable() -{ -} +ExpressionVariable::~ExpressionVariable() {} -uint8_t * -ExpressionVariable::GetValueBytes() -{ - const size_t byte_size = m_frozen_sp->GetByteSize(); - if (byte_size > 0) - { - if (m_frozen_sp->GetDataExtractor().GetByteSize() < byte_size) - { - m_frozen_sp->GetValue().ResizeData(byte_size); - m_frozen_sp->GetValue().GetData (m_frozen_sp->GetDataExtractor()); - } - return const_cast<uint8_t *>(m_frozen_sp->GetDataExtractor().GetDataStart()); +uint8_t *ExpressionVariable::GetValueBytes() { + const size_t byte_size = m_frozen_sp->GetByteSize(); + if (byte_size > 0) { + if (m_frozen_sp->GetDataExtractor().GetByteSize() < byte_size) { + m_frozen_sp->GetValue().ResizeData(byte_size); + m_frozen_sp->GetValue().GetData(m_frozen_sp->GetDataExtractor()); } - return NULL; + return const_cast<uint8_t *>( + m_frozen_sp->GetDataExtractor().GetDataStart()); + } + return NULL; } -PersistentExpressionState::~PersistentExpressionState () -{ -} +PersistentExpressionState::~PersistentExpressionState() {} + +lldb::addr_t PersistentExpressionState::LookupSymbol(const ConstString &name) { + SymbolMap::iterator si = m_symbol_map.find(name.GetCString()); -lldb::addr_t -PersistentExpressionState::LookupSymbol (const ConstString &name) -{ - SymbolMap::iterator si = m_symbol_map.find(name.GetCString()); - - if (si != m_symbol_map.end()) - return si->second; - else - return LLDB_INVALID_ADDRESS; + if (si != m_symbol_map.end()) + return si->second; + else + return LLDB_INVALID_ADDRESS; } +void PersistentExpressionState::RegisterExecutionUnit( + lldb::IRExecutionUnitSP &execution_unit_sp) { + Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS)); -void -PersistentExpressionState::RegisterExecutionUnit (lldb::IRExecutionUnitSP &execution_unit_sp) -{ - Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); - - m_execution_units.insert(execution_unit_sp); - - if (log) - log->Printf ("Registering JITted Functions:\n"); - - for (const IRExecutionUnit::JittedFunction &jitted_function : execution_unit_sp->GetJittedFunctions()) - { - if (jitted_function.m_external && - jitted_function.m_name != execution_unit_sp->GetFunctionName() && - jitted_function.m_remote_addr != LLDB_INVALID_ADDRESS) - { - m_symbol_map[jitted_function.m_name.GetCString()] = jitted_function.m_remote_addr; - if (log) - log->Printf (" Function: %s at 0x%" PRIx64 ".", jitted_function.m_name.GetCString(), jitted_function.m_remote_addr); - } + m_execution_units.insert(execution_unit_sp); + + if (log) + log->Printf("Registering JITted Functions:\n"); + + for (const IRExecutionUnit::JittedFunction &jitted_function : + execution_unit_sp->GetJittedFunctions()) { + if (jitted_function.m_external && + jitted_function.m_name != execution_unit_sp->GetFunctionName() && + jitted_function.m_remote_addr != LLDB_INVALID_ADDRESS) { + m_symbol_map[jitted_function.m_name.GetCString()] = + jitted_function.m_remote_addr; + if (log) + log->Printf(" Function: %s at 0x%" PRIx64 ".", + jitted_function.m_name.GetCString(), + jitted_function.m_remote_addr); } - - if (log) - log->Printf ("Registering JIIted Symbols:\n"); - - for (const IRExecutionUnit::JittedGlobalVariable &global_var : execution_unit_sp->GetJittedGlobalVariables()) - { - if (global_var.m_remote_addr != LLDB_INVALID_ADDRESS) - { - // Demangle the name before inserting it, so that lookups by the ConstStr of the demangled name - // will find the mangled one (needed for looking up metadata pointers.) - Mangled mangler(global_var.m_name); - mangler.GetDemangledName(lldb::eLanguageTypeUnknown); - m_symbol_map[global_var.m_name.GetCString()] = global_var.m_remote_addr; - if (log) - log->Printf (" Symbol: %s at 0x%" PRIx64 ".", global_var.m_name.GetCString(), global_var.m_remote_addr); - } + } + + if (log) + log->Printf("Registering JIIted Symbols:\n"); + + for (const IRExecutionUnit::JittedGlobalVariable &global_var : + execution_unit_sp->GetJittedGlobalVariables()) { + if (global_var.m_remote_addr != LLDB_INVALID_ADDRESS) { + // Demangle the name before inserting it, so that lookups by the ConstStr + // of the demangled name + // will find the mangled one (needed for looking up metadata pointers.) + Mangled mangler(global_var.m_name); + mangler.GetDemangledName(lldb::eLanguageTypeUnknown); + m_symbol_map[global_var.m_name.GetCString()] = global_var.m_remote_addr; + if (log) + log->Printf(" Symbol: %s at 0x%" PRIx64 ".", + global_var.m_name.GetCString(), global_var.m_remote_addr); } + } } diff --git a/source/Expression/FunctionCaller.cpp b/source/Expression/FunctionCaller.cpp index 3a4f1fe33add..f218ccb047a7 100644 --- a/source/Expression/FunctionCaller.cpp +++ b/source/Expression/FunctionCaller.cpp @@ -1,4 +1,4 @@ -//===-- FunctionCaller.cpp ---------------------------------------*- C++ -*-===// +//===-- FunctionCaller.cpp ---------------------------------------*- C++-*-===// // // The LLVM Compiler Infrastructure // @@ -7,7 +7,6 @@ // //===----------------------------------------------------------------------===// - // C Includes // C++ Includes // Other libraries and framework includes @@ -38,364 +37,358 @@ using namespace lldb_private; //---------------------------------------------------------------------- // FunctionCaller constructor //---------------------------------------------------------------------- -FunctionCaller::FunctionCaller -( - ExecutionContextScope &exe_scope, - const CompilerType &return_type, - const Address& functionAddress, - const ValueList &arg_value_list, - const char *name -) : - Expression (exe_scope), - m_execution_unit_sp(), - m_parser(), - m_jit_module_wp(), - m_name (name ? name : "<unknown>"), - m_function_ptr (NULL), - m_function_addr (functionAddress), - m_function_return_type(return_type), - m_wrapper_function_name ("__lldb_caller_function"), - m_wrapper_struct_name ("__lldb_caller_struct"), - m_wrapper_args_addrs (), - m_arg_values (arg_value_list), - m_compiled (false), - m_JITted (false) -{ - m_jit_process_wp = lldb::ProcessWP(exe_scope.CalculateProcess()); - // Can't make a FunctionCaller without a process. - assert (m_jit_process_wp.lock()); +FunctionCaller::FunctionCaller(ExecutionContextScope &exe_scope, + const CompilerType &return_type, + const Address &functionAddress, + const ValueList &arg_value_list, + const char *name) + : Expression(exe_scope), m_execution_unit_sp(), m_parser(), + m_jit_module_wp(), m_name(name ? name : "<unknown>"), + m_function_ptr(NULL), m_function_addr(functionAddress), + m_function_return_type(return_type), + m_wrapper_function_name("__lldb_caller_function"), + m_wrapper_struct_name("__lldb_caller_struct"), m_wrapper_args_addrs(), + m_arg_values(arg_value_list), m_compiled(false), m_JITted(false) { + m_jit_process_wp = lldb::ProcessWP(exe_scope.CalculateProcess()); + // Can't make a FunctionCaller without a process. + assert(m_jit_process_wp.lock()); } //---------------------------------------------------------------------- // Destructor //---------------------------------------------------------------------- -FunctionCaller::~FunctionCaller() -{ - lldb::ProcessSP process_sp (m_jit_process_wp.lock()); - if (process_sp) - { - lldb::ModuleSP jit_module_sp (m_jit_module_wp.lock()); - if (jit_module_sp) - process_sp->GetTarget().GetImages().Remove(jit_module_sp); - } +FunctionCaller::~FunctionCaller() { + lldb::ProcessSP process_sp(m_jit_process_wp.lock()); + if (process_sp) { + lldb::ModuleSP jit_module_sp(m_jit_module_wp.lock()); + if (jit_module_sp) + process_sp->GetTarget().GetImages().Remove(jit_module_sp); + } } -bool -FunctionCaller::WriteFunctionWrapper(ExecutionContext &exe_ctx, DiagnosticManager &diagnostic_manager) -{ - Process *process = exe_ctx.GetProcessPtr(); - - if (!process) - return false; - - lldb::ProcessSP jit_process_sp(m_jit_process_wp.lock()); - - if (process != jit_process_sp.get()) - return false; - - if (!m_compiled) - return false; - - if (m_JITted) - return true; - - bool can_interpret = false; // should stay that way - - Error jit_error (m_parser->PrepareForExecution (m_jit_start_addr, - m_jit_end_addr, - m_execution_unit_sp, - exe_ctx, - can_interpret, - eExecutionPolicyAlways)); - - if (!jit_error.Success()) - return false; - - if (m_parser->GetGenerateDebugInfo()) - { - lldb::ModuleSP jit_module_sp ( m_execution_unit_sp->GetJITModule()); - - if (jit_module_sp) - { - ConstString const_func_name(FunctionName()); - FileSpec jit_file; - jit_file.GetFilename() = const_func_name; - jit_module_sp->SetFileSpecAndObjectName (jit_file, ConstString()); - m_jit_module_wp = jit_module_sp; - process->GetTarget().GetImages().Append(jit_module_sp); - } - } - if (process && m_jit_start_addr) - m_jit_process_wp = process->shared_from_this(); - - m_JITted = true; +bool FunctionCaller::WriteFunctionWrapper( + ExecutionContext &exe_ctx, DiagnosticManager &diagnostic_manager) { + Process *process = exe_ctx.GetProcessPtr(); + + if (!process) + return false; + + lldb::ProcessSP jit_process_sp(m_jit_process_wp.lock()); + + if (process != jit_process_sp.get()) + return false; + if (!m_compiled) + return false; + + if (m_JITted) return true; + + bool can_interpret = false; // should stay that way + + Error jit_error(m_parser->PrepareForExecution( + m_jit_start_addr, m_jit_end_addr, m_execution_unit_sp, exe_ctx, + can_interpret, eExecutionPolicyAlways)); + + if (!jit_error.Success()) + return false; + + if (m_parser->GetGenerateDebugInfo()) { + lldb::ModuleSP jit_module_sp(m_execution_unit_sp->GetJITModule()); + + if (jit_module_sp) { + ConstString const_func_name(FunctionName()); + FileSpec jit_file; + jit_file.GetFilename() = const_func_name; + jit_module_sp->SetFileSpecAndObjectName(jit_file, ConstString()); + m_jit_module_wp = jit_module_sp; + process->GetTarget().GetImages().Append(jit_module_sp); + } + } + if (process && m_jit_start_addr) + m_jit_process_wp = process->shared_from_this(); + + m_JITted = true; + + return true; } -bool -FunctionCaller::WriteFunctionArguments(ExecutionContext &exe_ctx, lldb::addr_t &args_addr_ref, - DiagnosticManager &diagnostic_manager) -{ - return WriteFunctionArguments(exe_ctx, args_addr_ref, m_arg_values, diagnostic_manager); +bool FunctionCaller::WriteFunctionArguments( + ExecutionContext &exe_ctx, lldb::addr_t &args_addr_ref, + DiagnosticManager &diagnostic_manager) { + return WriteFunctionArguments(exe_ctx, args_addr_ref, m_arg_values, + diagnostic_manager); } -// FIXME: Assure that the ValueList we were passed in is consistent with the one that defined this function. - -bool -FunctionCaller::WriteFunctionArguments(ExecutionContext &exe_ctx, lldb::addr_t &args_addr_ref, ValueList &arg_values, - DiagnosticManager &diagnostic_manager) -{ - // All the information to reconstruct the struct is provided by the - // StructExtractor. - if (!m_struct_valid) - { - diagnostic_manager.PutCString( - eDiagnosticSeverityError, - "Argument information was not correctly parsed, so the function cannot be called."); - return false; - } +// FIXME: Assure that the ValueList we were passed in is consistent with the one +// that defined this function. + +bool FunctionCaller::WriteFunctionArguments( + ExecutionContext &exe_ctx, lldb::addr_t &args_addr_ref, + ValueList &arg_values, DiagnosticManager &diagnostic_manager) { + // All the information to reconstruct the struct is provided by the + // StructExtractor. + if (!m_struct_valid) { + diagnostic_manager.PutString(eDiagnosticSeverityError, + "Argument information was not correctly " + "parsed, so the function cannot be called."); + return false; + } - Error error; - lldb::ExpressionResults return_value = lldb::eExpressionSetupError; + Error error; + lldb::ExpressionResults return_value = lldb::eExpressionSetupError; - Process *process = exe_ctx.GetProcessPtr(); + Process *process = exe_ctx.GetProcessPtr(); - if (process == NULL) - return return_value; + if (process == NULL) + return return_value; - lldb::ProcessSP jit_process_sp(m_jit_process_wp.lock()); - - if (process != jit_process_sp.get()) - return false; - + lldb::ProcessSP jit_process_sp(m_jit_process_wp.lock()); + + if (process != jit_process_sp.get()) + return false; + + if (args_addr_ref == LLDB_INVALID_ADDRESS) { + args_addr_ref = process->AllocateMemory( + m_struct_size, lldb::ePermissionsReadable | lldb::ePermissionsWritable, + error); if (args_addr_ref == LLDB_INVALID_ADDRESS) - { - args_addr_ref = process->AllocateMemory(m_struct_size, lldb::ePermissionsReadable|lldb::ePermissionsWritable, error); - if (args_addr_ref == LLDB_INVALID_ADDRESS) - return false; - m_wrapper_args_addrs.push_back (args_addr_ref); - } - else - { - // Make sure this is an address that we've already handed out. - if (find (m_wrapper_args_addrs.begin(), m_wrapper_args_addrs.end(), args_addr_ref) == m_wrapper_args_addrs.end()) - { - return false; - } + return false; + m_wrapper_args_addrs.push_back(args_addr_ref); + } else { + // Make sure this is an address that we've already handed out. + if (find(m_wrapper_args_addrs.begin(), m_wrapper_args_addrs.end(), + args_addr_ref) == m_wrapper_args_addrs.end()) { + return false; } + } - // TODO: verify fun_addr needs to be a callable address - Scalar fun_addr (m_function_addr.GetCallableLoadAddress(exe_ctx.GetTargetPtr())); - uint64_t first_offset = m_member_offsets[0]; - process->WriteScalarToMemory(args_addr_ref + first_offset, fun_addr, process->GetAddressByteSize(), error); + // TODO: verify fun_addr needs to be a callable address + Scalar fun_addr( + m_function_addr.GetCallableLoadAddress(exe_ctx.GetTargetPtr())); + uint64_t first_offset = m_member_offsets[0]; + process->WriteScalarToMemory(args_addr_ref + first_offset, fun_addr, + process->GetAddressByteSize(), error); - // FIXME: We will need to extend this for Variadic functions. + // FIXME: We will need to extend this for Variadic functions. - Error value_error; + Error value_error; - size_t num_args = arg_values.GetSize(); - if (num_args != m_arg_values.GetSize()) - { - diagnostic_manager.Printf(eDiagnosticSeverityError, - "Wrong number of arguments - was: %" PRIu64 " should be: %" PRIu64 "", - (uint64_t)num_args, (uint64_t)m_arg_values.GetSize()); - return false; - } + size_t num_args = arg_values.GetSize(); + if (num_args != m_arg_values.GetSize()) { + diagnostic_manager.Printf( + eDiagnosticSeverityError, + "Wrong number of arguments - was: %" PRIu64 " should be: %" PRIu64 "", + (uint64_t)num_args, (uint64_t)m_arg_values.GetSize()); + return false; + } - for (size_t i = 0; i < num_args; i++) - { - // FIXME: We should sanity check sizes. - - uint64_t offset = m_member_offsets[i+1]; // Clang sizes are in bytes. - Value *arg_value = arg_values.GetValueAtIndex(i); - - // FIXME: For now just do scalars: - - // Special case: if it's a pointer, don't do anything (the ABI supports passing cstrings) - - if (arg_value->GetValueType() == Value::eValueTypeHostAddress && - arg_value->GetContextType() == Value::eContextTypeInvalid && - arg_value->GetCompilerType().IsPointerType()) - continue; - - const Scalar &arg_scalar = arg_value->ResolveValue(&exe_ctx); - - if (!process->WriteScalarToMemory(args_addr_ref + offset, arg_scalar, arg_scalar.GetByteSize(), error)) - return false; - } + for (size_t i = 0; i < num_args; i++) { + // FIXME: We should sanity check sizes. - return true; -} + uint64_t offset = m_member_offsets[i + 1]; // Clang sizes are in bytes. + Value *arg_value = arg_values.GetValueAtIndex(i); -bool -FunctionCaller::InsertFunction(ExecutionContext &exe_ctx, lldb::addr_t &args_addr_ref, - DiagnosticManager &diagnostic_manager) -{ - if (CompileFunction(exe_ctx.GetThreadSP(), diagnostic_manager) != 0) - return false; - if (!WriteFunctionWrapper(exe_ctx, diagnostic_manager)) - return false; - if (!WriteFunctionArguments(exe_ctx, args_addr_ref, diagnostic_manager)) - return false; - - Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_STEP)); - if (log) - log->Printf ("Call Address: 0x%" PRIx64 " Struct Address: 0x%" PRIx64 ".\n", m_jit_start_addr, args_addr_ref); - - return true; + // FIXME: For now just do scalars: + + // Special case: if it's a pointer, don't do anything (the ABI supports + // passing cstrings) + + if (arg_value->GetValueType() == Value::eValueTypeHostAddress && + arg_value->GetContextType() == Value::eContextTypeInvalid && + arg_value->GetCompilerType().IsPointerType()) + continue; + + const Scalar &arg_scalar = arg_value->ResolveValue(&exe_ctx); + + if (!process->WriteScalarToMemory(args_addr_ref + offset, arg_scalar, + arg_scalar.GetByteSize(), error)) + return false; + } + + return true; } -lldb::ThreadPlanSP -FunctionCaller::GetThreadPlanToCallFunction(ExecutionContext &exe_ctx, lldb::addr_t args_addr, - const EvaluateExpressionOptions &options, - DiagnosticManager &diagnostic_manager) -{ - Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_EXPRESSIONS | LIBLLDB_LOG_STEP)); - - if (log) - log->Printf("-- [FunctionCaller::GetThreadPlanToCallFunction] Creating thread plan to call function \"%s\" --", m_name.c_str()); - - // FIXME: Use the errors Stream for better error reporting. - Thread *thread = exe_ctx.GetThreadPtr(); - if (thread == NULL) - { - diagnostic_manager.PutCString(eDiagnosticSeverityError, "Can't call a function without a valid thread."); - return NULL; - } +bool FunctionCaller::InsertFunction(ExecutionContext &exe_ctx, + lldb::addr_t &args_addr_ref, + DiagnosticManager &diagnostic_manager) { + if (CompileFunction(exe_ctx.GetThreadSP(), diagnostic_manager) != 0) + return false; + if (!WriteFunctionWrapper(exe_ctx, diagnostic_manager)) + return false; + if (!WriteFunctionArguments(exe_ctx, args_addr_ref, diagnostic_manager)) + return false; + + Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_STEP)); + if (log) + log->Printf("Call Address: 0x%" PRIx64 " Struct Address: 0x%" PRIx64 ".\n", + m_jit_start_addr, args_addr_ref); + + return true; +} - // Okay, now run the function: - - Address wrapper_address (m_jit_start_addr); - - lldb::addr_t args = { args_addr }; - - lldb::ThreadPlanSP new_plan_sp (new ThreadPlanCallFunction (*thread, - wrapper_address, - CompilerType(), - args, - options)); - new_plan_sp->SetIsMasterPlan(true); - new_plan_sp->SetOkayToDiscard (false); - return new_plan_sp; +lldb::ThreadPlanSP FunctionCaller::GetThreadPlanToCallFunction( + ExecutionContext &exe_ctx, lldb::addr_t args_addr, + const EvaluateExpressionOptions &options, + DiagnosticManager &diagnostic_manager) { + Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_EXPRESSIONS | + LIBLLDB_LOG_STEP)); + + if (log) + log->Printf("-- [FunctionCaller::GetThreadPlanToCallFunction] Creating " + "thread plan to call function \"%s\" --", + m_name.c_str()); + + // FIXME: Use the errors Stream for better error reporting. + Thread *thread = exe_ctx.GetThreadPtr(); + if (thread == NULL) { + diagnostic_manager.PutString( + eDiagnosticSeverityError, + "Can't call a function without a valid thread."); + return NULL; + } + + // Okay, now run the function: + + Address wrapper_address(m_jit_start_addr); + + lldb::addr_t args = {args_addr}; + + lldb::ThreadPlanSP new_plan_sp(new ThreadPlanCallFunction( + *thread, wrapper_address, CompilerType(), args, options)); + new_plan_sp->SetIsMasterPlan(true); + new_plan_sp->SetOkayToDiscard(false); + return new_plan_sp; } -bool -FunctionCaller::FetchFunctionResults (ExecutionContext &exe_ctx, lldb::addr_t args_addr, Value &ret_value) -{ - // Read the return value - it is the last field in the struct: - // FIXME: How does clang tell us there's no return value? We need to handle that case. - // FIXME: Create our ThreadPlanCallFunction with the return CompilerType, and then use GetReturnValueObject - // to fetch the value. That way we can fetch any values we need. - - Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_EXPRESSIONS | LIBLLDB_LOG_STEP)); - - if (log) - log->Printf("-- [FunctionCaller::FetchFunctionResults] Fetching function results for \"%s\"--", m_name.c_str()); - - Process *process = exe_ctx.GetProcessPtr(); - - if (process == NULL) - return false; - - lldb::ProcessSP jit_process_sp(m_jit_process_wp.lock()); - - if (process != jit_process_sp.get()) - return false; - - Error error; - ret_value.GetScalar() = process->ReadUnsignedIntegerFromMemory (args_addr + m_return_offset, m_return_size, 0, error); - - if (error.Fail()) - return false; - - ret_value.SetCompilerType(m_function_return_type); - ret_value.SetValueType(Value::eValueTypeScalar); - return true; +bool FunctionCaller::FetchFunctionResults(ExecutionContext &exe_ctx, + lldb::addr_t args_addr, + Value &ret_value) { + // Read the return value - it is the last field in the struct: + // FIXME: How does clang tell us there's no return value? We need to handle + // that case. + // FIXME: Create our ThreadPlanCallFunction with the return CompilerType, and + // then use GetReturnValueObject + // to fetch the value. That way we can fetch any values we need. + + Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_EXPRESSIONS | + LIBLLDB_LOG_STEP)); + + if (log) + log->Printf("-- [FunctionCaller::FetchFunctionResults] Fetching function " + "results for \"%s\"--", + m_name.c_str()); + + Process *process = exe_ctx.GetProcessPtr(); + + if (process == NULL) + return false; + + lldb::ProcessSP jit_process_sp(m_jit_process_wp.lock()); + + if (process != jit_process_sp.get()) + return false; + + Error error; + ret_value.GetScalar() = process->ReadUnsignedIntegerFromMemory( + args_addr + m_return_offset, m_return_size, 0, error); + + if (error.Fail()) + return false; + + ret_value.SetCompilerType(m_function_return_type); + ret_value.SetValueType(Value::eValueTypeScalar); + return true; } -void -FunctionCaller::DeallocateFunctionResults (ExecutionContext &exe_ctx, lldb::addr_t args_addr) -{ - std::list<lldb::addr_t>::iterator pos; - pos = std::find(m_wrapper_args_addrs.begin(), m_wrapper_args_addrs.end(), args_addr); - if (pos != m_wrapper_args_addrs.end()) - m_wrapper_args_addrs.erase(pos); - - exe_ctx.GetProcessRef().DeallocateMemory(args_addr); +void FunctionCaller::DeallocateFunctionResults(ExecutionContext &exe_ctx, + lldb::addr_t args_addr) { + std::list<lldb::addr_t>::iterator pos; + pos = std::find(m_wrapper_args_addrs.begin(), m_wrapper_args_addrs.end(), + args_addr); + if (pos != m_wrapper_args_addrs.end()) + m_wrapper_args_addrs.erase(pos); + + exe_ctx.GetProcessRef().DeallocateMemory(args_addr); } -lldb::ExpressionResults -FunctionCaller::ExecuteFunction(ExecutionContext &exe_ctx, lldb::addr_t *args_addr_ptr, - const EvaluateExpressionOptions &options, DiagnosticManager &diagnostic_manager, - Value &results) -{ - lldb::ExpressionResults return_value = lldb::eExpressionSetupError; - - // FunctionCaller::ExecuteFunction execution is always just to get the result. Do make sure we ignore - // breakpoints, unwind on error, and don't try to debug it. - EvaluateExpressionOptions real_options = options; - real_options.SetDebug(false); - real_options.SetUnwindOnError(true); - real_options.SetIgnoreBreakpoints(true); - - lldb::addr_t args_addr; - - if (args_addr_ptr != NULL) - args_addr = *args_addr_ptr; - else - args_addr = LLDB_INVALID_ADDRESS; - - if (CompileFunction(exe_ctx.GetThreadSP(), diagnostic_manager) != 0) - return lldb::eExpressionSetupError; - - if (args_addr == LLDB_INVALID_ADDRESS) - { - if (!InsertFunction(exe_ctx, args_addr, diagnostic_manager)) - return lldb::eExpressionSetupError; +lldb::ExpressionResults FunctionCaller::ExecuteFunction( + ExecutionContext &exe_ctx, lldb::addr_t *args_addr_ptr, + const EvaluateExpressionOptions &options, + DiagnosticManager &diagnostic_manager, Value &results) { + lldb::ExpressionResults return_value = lldb::eExpressionSetupError; + + // FunctionCaller::ExecuteFunction execution is always just to get the result. + // Do make sure we ignore + // breakpoints, unwind on error, and don't try to debug it. + EvaluateExpressionOptions real_options = options; + real_options.SetDebug(false); + real_options.SetUnwindOnError(true); + real_options.SetIgnoreBreakpoints(true); + + lldb::addr_t args_addr; + + if (args_addr_ptr != NULL) + args_addr = *args_addr_ptr; + else + args_addr = LLDB_INVALID_ADDRESS; + + if (CompileFunction(exe_ctx.GetThreadSP(), diagnostic_manager) != 0) + return lldb::eExpressionSetupError; + + if (args_addr == LLDB_INVALID_ADDRESS) { + if (!InsertFunction(exe_ctx, args_addr, diagnostic_manager)) + return lldb::eExpressionSetupError; + } + + Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_EXPRESSIONS | + LIBLLDB_LOG_STEP)); + + if (log) + log->Printf( + "== [FunctionCaller::ExecuteFunction] Executing function \"%s\" ==", + m_name.c_str()); + + lldb::ThreadPlanSP call_plan_sp = GetThreadPlanToCallFunction( + exe_ctx, args_addr, real_options, diagnostic_manager); + if (!call_plan_sp) + return lldb::eExpressionSetupError; + + // We need to make sure we record the fact that we are running an expression + // here + // otherwise this fact will fail to be recorded when fetching an Objective-C + // object description + if (exe_ctx.GetProcessPtr()) + exe_ctx.GetProcessPtr()->SetRunningUserExpression(true); + + return_value = exe_ctx.GetProcessRef().RunThreadPlan( + exe_ctx, call_plan_sp, real_options, diagnostic_manager); + + if (log) { + if (return_value != lldb::eExpressionCompleted) { + log->Printf("== [FunctionCaller::ExecuteFunction] Execution of \"%s\" " + "completed abnormally ==", + m_name.c_str()); + } else { + log->Printf("== [FunctionCaller::ExecuteFunction] Execution of \"%s\" " + "completed normally ==", + m_name.c_str()); } + } - Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_EXPRESSIONS | LIBLLDB_LOG_STEP)); + if (exe_ctx.GetProcessPtr()) + exe_ctx.GetProcessPtr()->SetRunningUserExpression(false); - if (log) - log->Printf("== [FunctionCaller::ExecuteFunction] Executing function \"%s\" ==", m_name.c_str()); + if (args_addr_ptr != NULL) + *args_addr_ptr = args_addr; - lldb::ThreadPlanSP call_plan_sp = GetThreadPlanToCallFunction(exe_ctx, args_addr, real_options, diagnostic_manager); - if (!call_plan_sp) - return lldb::eExpressionSetupError; + if (return_value != lldb::eExpressionCompleted) + return return_value; - // We need to make sure we record the fact that we are running an expression here - // otherwise this fact will fail to be recorded when fetching an Objective-C object description - if (exe_ctx.GetProcessPtr()) - exe_ctx.GetProcessPtr()->SetRunningUserExpression(true); + FetchFunctionResults(exe_ctx, args_addr, results); - return_value = exe_ctx.GetProcessRef().RunThreadPlan(exe_ctx, call_plan_sp, real_options, diagnostic_manager); + if (args_addr_ptr == NULL) + DeallocateFunctionResults(exe_ctx, args_addr); - if (log) - { - if (return_value != lldb::eExpressionCompleted) - { - log->Printf("== [FunctionCaller::ExecuteFunction] Execution of \"%s\" completed abnormally ==", m_name.c_str()); - } - else - { - log->Printf("== [FunctionCaller::ExecuteFunction] Execution of \"%s\" completed normally ==", m_name.c_str()); - } - } - - if (exe_ctx.GetProcessPtr()) - exe_ctx.GetProcessPtr()->SetRunningUserExpression(false); - - if (args_addr_ptr != NULL) - *args_addr_ptr = args_addr; - - if (return_value != lldb::eExpressionCompleted) - return return_value; - - FetchFunctionResults(exe_ctx, args_addr, results); - - if (args_addr_ptr == NULL) - DeallocateFunctionResults(exe_ctx, args_addr); - - return lldb::eExpressionCompleted; + return lldb::eExpressionCompleted; } diff --git a/source/Expression/IRDynamicChecks.cpp b/source/Expression/IRDynamicChecks.cpp index 62bcfe0d14b8..b337ea2cb275 100644 --- a/source/Expression/IRDynamicChecks.cpp +++ b/source/Expression/IRDynamicChecks.cpp @@ -10,13 +10,13 @@ // C Includes // C++ Includes // Other libraries and framework includes -#include "llvm/Support/raw_ostream.h" #include "llvm/IR/Constants.h" #include "llvm/IR/DataLayout.h" #include "llvm/IR/Function.h" #include "llvm/IR/Instructions.h" #include "llvm/IR/Module.h" #include "llvm/IR/Value.h" +#include "llvm/Support/raw_ostream.h" // Project includes #include "lldb/Expression/IRDynamicChecks.h" @@ -39,76 +39,72 @@ static char ID; #define VALID_OBJC_OBJECT_CHECK_NAME "$__lldb_objc_object_check" static const char g_valid_pointer_check_text[] = -"extern \"C\" void\n" -"_$__lldb_valid_pointer_check (unsigned char *$__lldb_arg_ptr)\n" -"{\n" -" unsigned char $__lldb_local_val = *$__lldb_arg_ptr;\n" -"}"; + "extern \"C\" void\n" + "_$__lldb_valid_pointer_check (unsigned char *$__lldb_arg_ptr)\n" + "{\n" + " unsigned char $__lldb_local_val = *$__lldb_arg_ptr;\n" + "}"; DynamicCheckerFunctions::DynamicCheckerFunctions() = default; DynamicCheckerFunctions::~DynamicCheckerFunctions() = default; -bool -DynamicCheckerFunctions::Install(DiagnosticManager &diagnostic_manager, ExecutionContext &exe_ctx) -{ - Error error; - m_valid_pointer_check.reset(exe_ctx.GetTargetRef().GetUtilityFunctionForLanguage(g_valid_pointer_check_text, - lldb::eLanguageTypeC, - VALID_POINTER_CHECK_NAME, - error)); - if (error.Fail()) - return false; +bool DynamicCheckerFunctions::Install(DiagnosticManager &diagnostic_manager, + ExecutionContext &exe_ctx) { + Error error; + m_valid_pointer_check.reset( + exe_ctx.GetTargetRef().GetUtilityFunctionForLanguage( + g_valid_pointer_check_text, lldb::eLanguageTypeC, + VALID_POINTER_CHECK_NAME, error)); + if (error.Fail()) + return false; - if (!m_valid_pointer_check->Install(diagnostic_manager, exe_ctx)) - return false; + if (!m_valid_pointer_check->Install(diagnostic_manager, exe_ctx)) + return false; - Process *process = exe_ctx.GetProcessPtr(); + Process *process = exe_ctx.GetProcessPtr(); - if (process) - { - ObjCLanguageRuntime *objc_language_runtime = process->GetObjCLanguageRuntime(); + if (process) { + ObjCLanguageRuntime *objc_language_runtime = + process->GetObjCLanguageRuntime(); - if (objc_language_runtime) - { - m_objc_object_check.reset(objc_language_runtime->CreateObjectChecker(VALID_OBJC_OBJECT_CHECK_NAME)); + if (objc_language_runtime) { + m_objc_object_check.reset(objc_language_runtime->CreateObjectChecker( + VALID_OBJC_OBJECT_CHECK_NAME)); - if (!m_objc_object_check->Install(diagnostic_manager, exe_ctx)) - return false; - } + if (!m_objc_object_check->Install(diagnostic_manager, exe_ctx)) + return false; } + } - return true; + return true; } -bool -DynamicCheckerFunctions::DoCheckersExplainStop (lldb::addr_t addr, Stream &message) -{ - // FIXME: We have to get the checkers to know why they scotched the call in more detail, - // so we can print a better message here. - if (m_valid_pointer_check && m_valid_pointer_check->ContainsAddress(addr)) - { - message.Printf ("Attempted to dereference an invalid pointer."); - return true; - } - else if (m_objc_object_check && m_objc_object_check->ContainsAddress(addr)) - { - message.Printf ("Attempted to dereference an invalid ObjC Object or send it an unrecognized selector"); - return true; - } - return false; +bool DynamicCheckerFunctions::DoCheckersExplainStop(lldb::addr_t addr, + Stream &message) { + // FIXME: We have to get the checkers to know why they scotched the call in + // more detail, + // so we can print a better message here. + if (m_valid_pointer_check && m_valid_pointer_check->ContainsAddress(addr)) { + message.Printf("Attempted to dereference an invalid pointer."); + return true; + } else if (m_objc_object_check && + m_objc_object_check->ContainsAddress(addr)) { + message.Printf("Attempted to dereference an invalid ObjC Object or send it " + "an unrecognized selector"); + return true; + } + return false; } -static std::string -PrintValue(llvm::Value *V, bool truncate = false) -{ - std::string s; - raw_string_ostream rso(s); - V->print(rso); - rso.flush(); - if (truncate) - s.resize(s.length() - 1); - return s; +static std::string PrintValue(llvm::Value *V, bool truncate = false) { + std::string s; + raw_string_ostream rso(s); + V->print(rso); + rso.flush(); + if (truncate) + s.resize(s.length() - 1); + return s; } //---------------------------------------------------------------------- @@ -141,537 +137,476 @@ PrintValue(llvm::Value *V, bool truncate = false) //---------------------------------------------------------------------- class Instrumenter { public: - //------------------------------------------------------------------ - /// Constructor - /// - /// @param[in] module - /// The module being instrumented. - //------------------------------------------------------------------ - Instrumenter (llvm::Module &module, - DynamicCheckerFunctions &checker_functions) : - m_module(module), - m_checker_functions(checker_functions), - m_i8ptr_ty(nullptr), - m_intptr_ty(nullptr) - { - } - - virtual ~Instrumenter() = default; - - //------------------------------------------------------------------ - /// Inspect a function to find instructions to instrument - /// - /// @param[in] function - /// The function to inspect. - /// - /// @return - /// True on success; false on error. - //------------------------------------------------------------------ - bool Inspect (llvm::Function &function) - { - return InspectFunction(function); + //------------------------------------------------------------------ + /// Constructor + /// + /// @param[in] module + /// The module being instrumented. + //------------------------------------------------------------------ + Instrumenter(llvm::Module &module, DynamicCheckerFunctions &checker_functions) + : m_module(module), m_checker_functions(checker_functions), + m_i8ptr_ty(nullptr), m_intptr_ty(nullptr) {} + + virtual ~Instrumenter() = default; + + //------------------------------------------------------------------ + /// Inspect a function to find instructions to instrument + /// + /// @param[in] function + /// The function to inspect. + /// + /// @return + /// True on success; false on error. + //------------------------------------------------------------------ + bool Inspect(llvm::Function &function) { return InspectFunction(function); } + + //------------------------------------------------------------------ + /// Instrument all the instructions found by Inspect() + /// + /// @return + /// True on success; false on error. + //------------------------------------------------------------------ + bool Instrument() { + for (InstIterator ii = m_to_instrument.begin(), + last_ii = m_to_instrument.end(); + ii != last_ii; ++ii) { + if (!InstrumentInstruction(*ii)) + return false; } - //------------------------------------------------------------------ - /// Instrument all the instructions found by Inspect() - /// - /// @return - /// True on success; false on error. - //------------------------------------------------------------------ - bool Instrument () - { - for (InstIterator ii = m_to_instrument.begin(), last_ii = m_to_instrument.end(); - ii != last_ii; - ++ii) - { - if (!InstrumentInstruction(*ii)) - return false; - } - - return true; - } + return true; + } protected: - //------------------------------------------------------------------ - /// Add instrumentation to a single instruction - /// - /// @param[in] inst - /// The instruction to be instrumented. - /// - /// @return - /// True on success; false otherwise. - //------------------------------------------------------------------ - virtual bool InstrumentInstruction(llvm::Instruction *inst) = 0; - - //------------------------------------------------------------------ - /// Register a single instruction to be instrumented - /// - /// @param[in] inst - /// The instruction to be instrumented. - //------------------------------------------------------------------ - void RegisterInstruction(llvm::Instruction &i) - { - m_to_instrument.push_back(&i); + //------------------------------------------------------------------ + /// Add instrumentation to a single instruction + /// + /// @param[in] inst + /// The instruction to be instrumented. + /// + /// @return + /// True on success; false otherwise. + //------------------------------------------------------------------ + virtual bool InstrumentInstruction(llvm::Instruction *inst) = 0; + + //------------------------------------------------------------------ + /// Register a single instruction to be instrumented + /// + /// @param[in] inst + /// The instruction to be instrumented. + //------------------------------------------------------------------ + void RegisterInstruction(llvm::Instruction &i) { + m_to_instrument.push_back(&i); + } + + //------------------------------------------------------------------ + /// Determine whether a single instruction is interesting to + /// instrument, and, if so, call RegisterInstruction + /// + /// @param[in] i + /// The instruction to be inspected. + /// + /// @return + /// False if there was an error scanning; true otherwise. + //------------------------------------------------------------------ + virtual bool InspectInstruction(llvm::Instruction &i) { return true; } + + //------------------------------------------------------------------ + /// Scan a basic block to see if any instructions are interesting + /// + /// @param[in] bb + /// The basic block to be inspected. + /// + /// @return + /// False if there was an error scanning; true otherwise. + //------------------------------------------------------------------ + virtual bool InspectBasicBlock(llvm::BasicBlock &bb) { + for (llvm::BasicBlock::iterator ii = bb.begin(), last_ii = bb.end(); + ii != last_ii; ++ii) { + if (!InspectInstruction(*ii)) + return false; } - //------------------------------------------------------------------ - /// Determine whether a single instruction is interesting to - /// instrument, and, if so, call RegisterInstruction - /// - /// @param[in] i - /// The instruction to be inspected. - /// - /// @return - /// False if there was an error scanning; true otherwise. - //------------------------------------------------------------------ - virtual bool InspectInstruction(llvm::Instruction &i) - { - return true; + return true; + } + + //------------------------------------------------------------------ + /// Scan a function to see if any instructions are interesting + /// + /// @param[in] f + /// The function to be inspected. + /// + /// @return + /// False if there was an error scanning; true otherwise. + //------------------------------------------------------------------ + virtual bool InspectFunction(llvm::Function &f) { + for (llvm::Function::iterator bbi = f.begin(), last_bbi = f.end(); + bbi != last_bbi; ++bbi) { + if (!InspectBasicBlock(*bbi)) + return false; } - //------------------------------------------------------------------ - /// Scan a basic block to see if any instructions are interesting - /// - /// @param[in] bb - /// The basic block to be inspected. - /// - /// @return - /// False if there was an error scanning; true otherwise. - //------------------------------------------------------------------ - virtual bool InspectBasicBlock(llvm::BasicBlock &bb) - { - for (llvm::BasicBlock::iterator ii = bb.begin(), last_ii = bb.end(); - ii != last_ii; - ++ii) - { - if (!InspectInstruction(*ii)) - return false; - } - - return true; + return true; + } + + //------------------------------------------------------------------ + /// Build a function pointer for a function with signature + /// void (*)(uint8_t*) with a given address + /// + /// @param[in] start_address + /// The address of the function. + /// + /// @return + /// The function pointer, for use in a CallInst. + //------------------------------------------------------------------ + llvm::Value *BuildPointerValidatorFunc(lldb::addr_t start_address) { + llvm::Type *param_array[1]; + + param_array[0] = const_cast<llvm::PointerType *>(GetI8PtrTy()); + + ArrayRef<llvm::Type *> params(param_array, 1); + + FunctionType *fun_ty = FunctionType::get( + llvm::Type::getVoidTy(m_module.getContext()), params, true); + PointerType *fun_ptr_ty = PointerType::getUnqual(fun_ty); + Constant *fun_addr_int = + ConstantInt::get(GetIntptrTy(), start_address, false); + return ConstantExpr::getIntToPtr(fun_addr_int, fun_ptr_ty); + } + + //------------------------------------------------------------------ + /// Build a function pointer for a function with signature + /// void (*)(uint8_t*, uint8_t*) with a given address + /// + /// @param[in] start_address + /// The address of the function. + /// + /// @return + /// The function pointer, for use in a CallInst. + //------------------------------------------------------------------ + llvm::Value *BuildObjectCheckerFunc(lldb::addr_t start_address) { + llvm::Type *param_array[2]; + + param_array[0] = const_cast<llvm::PointerType *>(GetI8PtrTy()); + param_array[1] = const_cast<llvm::PointerType *>(GetI8PtrTy()); + + ArrayRef<llvm::Type *> params(param_array, 2); + + FunctionType *fun_ty = FunctionType::get( + llvm::Type::getVoidTy(m_module.getContext()), params, true); + PointerType *fun_ptr_ty = PointerType::getUnqual(fun_ty); + Constant *fun_addr_int = + ConstantInt::get(GetIntptrTy(), start_address, false); + return ConstantExpr::getIntToPtr(fun_addr_int, fun_ptr_ty); + } + + PointerType *GetI8PtrTy() { + if (!m_i8ptr_ty) + m_i8ptr_ty = llvm::Type::getInt8PtrTy(m_module.getContext()); + + return m_i8ptr_ty; + } + + IntegerType *GetIntptrTy() { + if (!m_intptr_ty) { + llvm::DataLayout data_layout(&m_module); + + m_intptr_ty = llvm::Type::getIntNTy(m_module.getContext(), + data_layout.getPointerSizeInBits()); } - //------------------------------------------------------------------ - /// Scan a function to see if any instructions are interesting - /// - /// @param[in] f - /// The function to be inspected. - /// - /// @return - /// False if there was an error scanning; true otherwise. - //------------------------------------------------------------------ - virtual bool InspectFunction(llvm::Function &f) - { - for (llvm::Function::iterator bbi = f.begin(), last_bbi = f.end(); - bbi != last_bbi; - ++bbi) - { - if (!InspectBasicBlock(*bbi)) - return false; - } + return m_intptr_ty; + } - return true; - } + typedef std::vector<llvm::Instruction *> InstVector; + typedef InstVector::iterator InstIterator; - //------------------------------------------------------------------ - /// Build a function pointer for a function with signature - /// void (*)(uint8_t*) with a given address - /// - /// @param[in] start_address - /// The address of the function. - /// - /// @return - /// The function pointer, for use in a CallInst. - //------------------------------------------------------------------ - llvm::Value *BuildPointerValidatorFunc(lldb::addr_t start_address) - { - llvm::Type *param_array[1]; - - param_array[0] = const_cast<llvm::PointerType*>(GetI8PtrTy()); - - ArrayRef<llvm::Type*> params(param_array, 1); - - FunctionType *fun_ty = FunctionType::get(llvm::Type::getVoidTy(m_module.getContext()), params, true); - PointerType *fun_ptr_ty = PointerType::getUnqual(fun_ty); - Constant *fun_addr_int = ConstantInt::get(GetIntptrTy(), start_address, false); - return ConstantExpr::getIntToPtr(fun_addr_int, fun_ptr_ty); - } + InstVector m_to_instrument; ///< List of instructions the inspector found + llvm::Module &m_module; ///< The module which is being instrumented + DynamicCheckerFunctions + &m_checker_functions; ///< The dynamic checker functions for the process - //------------------------------------------------------------------ - /// Build a function pointer for a function with signature - /// void (*)(uint8_t*, uint8_t*) with a given address - /// - /// @param[in] start_address - /// The address of the function. - /// - /// @return - /// The function pointer, for use in a CallInst. - //------------------------------------------------------------------ - llvm::Value *BuildObjectCheckerFunc(lldb::addr_t start_address) - { - llvm::Type *param_array[2]; - - param_array[0] = const_cast<llvm::PointerType*>(GetI8PtrTy()); - param_array[1] = const_cast<llvm::PointerType*>(GetI8PtrTy()); - - ArrayRef<llvm::Type*> params(param_array, 2); - - FunctionType *fun_ty = FunctionType::get(llvm::Type::getVoidTy(m_module.getContext()), params, true); - PointerType *fun_ptr_ty = PointerType::getUnqual(fun_ty); - Constant *fun_addr_int = ConstantInt::get(GetIntptrTy(), start_address, false); - return ConstantExpr::getIntToPtr(fun_addr_int, fun_ptr_ty); - } +private: + PointerType *m_i8ptr_ty; + IntegerType *m_intptr_ty; +}; - PointerType *GetI8PtrTy() - { - if (!m_i8ptr_ty) - m_i8ptr_ty = llvm::Type::getInt8PtrTy(m_module.getContext()); +class ValidPointerChecker : public Instrumenter { +public: + ValidPointerChecker(llvm::Module &module, + DynamicCheckerFunctions &checker_functions) + : Instrumenter(module, checker_functions), + m_valid_pointer_check_func(nullptr) {} - return m_i8ptr_ty; - } + ~ValidPointerChecker() override = default; - IntegerType *GetIntptrTy() - { - if (!m_intptr_ty) - { - llvm::DataLayout data_layout(&m_module); +protected: + bool InstrumentInstruction(llvm::Instruction *inst) override { + Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS)); - m_intptr_ty = llvm::Type::getIntNTy(m_module.getContext(), data_layout.getPointerSizeInBits()); - } + if (log) + log->Printf("Instrumenting load/store instruction: %s\n", + PrintValue(inst).c_str()); - return m_intptr_ty; - } + if (!m_valid_pointer_check_func) + m_valid_pointer_check_func = BuildPointerValidatorFunc( + m_checker_functions.m_valid_pointer_check->StartAddress()); - typedef std::vector <llvm::Instruction *> InstVector; - typedef InstVector::iterator InstIterator; + llvm::Value *dereferenced_ptr = nullptr; - InstVector m_to_instrument; ///< List of instructions the inspector found - llvm::Module &m_module; ///< The module which is being instrumented - DynamicCheckerFunctions &m_checker_functions; ///< The dynamic checker functions for the process + if (llvm::LoadInst *li = dyn_cast<llvm::LoadInst>(inst)) + dereferenced_ptr = li->getPointerOperand(); + else if (llvm::StoreInst *si = dyn_cast<llvm::StoreInst>(inst)) + dereferenced_ptr = si->getPointerOperand(); + else + return false; -private: - PointerType *m_i8ptr_ty; - IntegerType *m_intptr_ty; -}; + // Insert an instruction to cast the loaded value to int8_t* -class ValidPointerChecker : public Instrumenter -{ -public: - ValidPointerChecker (llvm::Module &module, - DynamicCheckerFunctions &checker_functions) : - Instrumenter(module, checker_functions), - m_valid_pointer_check_func(nullptr) - { - } + BitCastInst *bit_cast = + new BitCastInst(dereferenced_ptr, GetI8PtrTy(), "", inst); - ~ValidPointerChecker() override = default; + // Insert an instruction to call the helper with the result -protected: - bool InstrumentInstruction(llvm::Instruction *inst) override - { - Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); + llvm::Value *arg_array[1]; - if (log) - log->Printf("Instrumenting load/store instruction: %s\n", - PrintValue(inst).c_str()); + arg_array[0] = bit_cast; - if (!m_valid_pointer_check_func) - m_valid_pointer_check_func = BuildPointerValidatorFunc(m_checker_functions.m_valid_pointer_check->StartAddress()); + llvm::ArrayRef<llvm::Value *> args(arg_array, 1); - llvm::Value *dereferenced_ptr = nullptr; + CallInst::Create(m_valid_pointer_check_func, args, "", inst); - if (llvm::LoadInst *li = dyn_cast<llvm::LoadInst> (inst)) - dereferenced_ptr = li->getPointerOperand(); - else if (llvm::StoreInst *si = dyn_cast<llvm::StoreInst> (inst)) - dereferenced_ptr = si->getPointerOperand(); - else - return false; + return true; + } - // Insert an instruction to cast the loaded value to int8_t* + bool InspectInstruction(llvm::Instruction &i) override { + if (dyn_cast<llvm::LoadInst>(&i) || dyn_cast<llvm::StoreInst>(&i)) + RegisterInstruction(i); - BitCastInst *bit_cast = new BitCastInst(dereferenced_ptr, - GetI8PtrTy(), - "", - inst); + return true; + } - // Insert an instruction to call the helper with the result +private: + llvm::Value *m_valid_pointer_check_func; +}; - llvm::Value *arg_array[1]; +class ObjcObjectChecker : public Instrumenter { +public: + ObjcObjectChecker(llvm::Module &module, + DynamicCheckerFunctions &checker_functions) + : Instrumenter(module, checker_functions), + m_objc_object_check_func(nullptr) {} - arg_array[0] = bit_cast; + ~ObjcObjectChecker() override = default; - llvm::ArrayRef<llvm::Value *> args(arg_array, 1); + enum msgSend_type { + eMsgSend = 0, + eMsgSendSuper, + eMsgSendSuper_stret, + eMsgSend_fpret, + eMsgSend_stret + }; - CallInst::Create(m_valid_pointer_check_func, - args, - "", - inst); + std::map<llvm::Instruction *, msgSend_type> msgSend_types; - return true; +protected: + bool InstrumentInstruction(llvm::Instruction *inst) override { + CallInst *call_inst = dyn_cast<CallInst>(inst); + + if (!call_inst) + return false; // call_inst really shouldn't be nullptr, because otherwise + // InspectInstruction wouldn't have registered it + + if (!m_objc_object_check_func) + m_objc_object_check_func = BuildObjectCheckerFunc( + m_checker_functions.m_objc_object_check->StartAddress()); + + // id objc_msgSend(id theReceiver, SEL theSelector, ...) + + llvm::Value *target_object; + llvm::Value *selector; + + switch (msgSend_types[inst]) { + case eMsgSend: + case eMsgSend_fpret: + target_object = call_inst->getArgOperand(0); + selector = call_inst->getArgOperand(1); + break; + case eMsgSend_stret: + target_object = call_inst->getArgOperand(1); + selector = call_inst->getArgOperand(2); + break; + case eMsgSendSuper: + case eMsgSendSuper_stret: + return true; } - bool InspectInstruction(llvm::Instruction &i) override - { - if (dyn_cast<llvm::LoadInst> (&i) || - dyn_cast<llvm::StoreInst> (&i)) - RegisterInstruction(i); + // These objects should always be valid according to Sean Calannan + assert(target_object); + assert(selector); - return true; - } + // Insert an instruction to cast the receiver id to int8_t* -private: - llvm::Value *m_valid_pointer_check_func; -}; + BitCastInst *bit_cast = + new BitCastInst(target_object, GetI8PtrTy(), "", inst); -class ObjcObjectChecker : public Instrumenter -{ -public: - ObjcObjectChecker(llvm::Module &module, - DynamicCheckerFunctions &checker_functions) : - Instrumenter(module, checker_functions), - m_objc_object_check_func(nullptr) - { - } + // Insert an instruction to call the helper with the result - ~ObjcObjectChecker() override = default; + llvm::Value *arg_array[2]; - enum msgSend_type - { - eMsgSend = 0, - eMsgSendSuper, - eMsgSendSuper_stret, - eMsgSend_fpret, - eMsgSend_stret - }; + arg_array[0] = bit_cast; + arg_array[1] = selector; - std::map <llvm::Instruction *, msgSend_type> msgSend_types; + ArrayRef<llvm::Value *> args(arg_array, 2); -protected: - bool InstrumentInstruction(llvm::Instruction *inst) override - { - CallInst *call_inst = dyn_cast<CallInst>(inst); + CallInst::Create(m_objc_object_check_func, args, "", inst); - if (!call_inst) - return false; // call_inst really shouldn't be nullptr, because otherwise InspectInstruction wouldn't have registered it + return true; + } - if (!m_objc_object_check_func) - m_objc_object_check_func = BuildObjectCheckerFunc(m_checker_functions.m_objc_object_check->StartAddress()); + static llvm::Function *GetFunction(llvm::Value *value) { + if (llvm::Function *function = llvm::dyn_cast<llvm::Function>(value)) { + return function; + } - // id objc_msgSend(id theReceiver, SEL theSelector, ...) + if (llvm::ConstantExpr *const_expr = + llvm::dyn_cast<llvm::ConstantExpr>(value)) { + switch (const_expr->getOpcode()) { + default: + return nullptr; + case llvm::Instruction::BitCast: + return GetFunction(const_expr->getOperand(0)); + } + } - llvm::Value *target_object; - llvm::Value *selector; + return nullptr; + } - switch (msgSend_types[inst]) - { - case eMsgSend: - case eMsgSend_fpret: - target_object = call_inst->getArgOperand(0); - selector = call_inst->getArgOperand(1); - break; - case eMsgSend_stret: - target_object = call_inst->getArgOperand(1); - selector = call_inst->getArgOperand(2); - break; - case eMsgSendSuper: - case eMsgSendSuper_stret: - return true; - } + static llvm::Function *GetCalledFunction(llvm::CallInst *inst) { + return GetFunction(inst->getCalledValue()); + } - // These objects should always be valid according to Sean Calannan - assert (target_object); - assert (selector); + bool InspectInstruction(llvm::Instruction &i) override { + Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS)); - // Insert an instruction to cast the receiver id to int8_t* + CallInst *call_inst = dyn_cast<CallInst>(&i); - BitCastInst *bit_cast = new BitCastInst(target_object, - GetI8PtrTy(), - "", - inst); + if (call_inst) { + const llvm::Function *called_function = GetCalledFunction(call_inst); - // Insert an instruction to call the helper with the result + if (!called_function) + return true; - llvm::Value *arg_array[2]; + std::string name_str = called_function->getName().str(); + const char *name_cstr = name_str.c_str(); - arg_array[0] = bit_cast; - arg_array[1] = selector; + if (log) + log->Printf("Found call to %s: %s\n", name_cstr, + PrintValue(call_inst).c_str()); - ArrayRef<llvm::Value*> args(arg_array, 2); + if (name_str.find("objc_msgSend") == std::string::npos) + return true; - CallInst::Create(m_objc_object_check_func, - args, - "", - inst); + if (!strcmp(name_cstr, "objc_msgSend")) { + RegisterInstruction(i); + msgSend_types[&i] = eMsgSend; + return true; + } + if (!strcmp(name_cstr, "objc_msgSend_stret")) { + RegisterInstruction(i); + msgSend_types[&i] = eMsgSend_stret; return true; - } - - static llvm::Function *GetFunction(llvm::Value *value) - { - if (llvm::Function *function = llvm::dyn_cast<llvm::Function>(value)) - { - return function; - } - - if (llvm::ConstantExpr *const_expr = llvm::dyn_cast<llvm::ConstantExpr>(value)) - { - switch (const_expr->getOpcode()) - { - default: - return nullptr; - case llvm::Instruction::BitCast: - return GetFunction(const_expr->getOperand(0)); - } - } - - return nullptr; - } - - static llvm::Function *GetCalledFunction(llvm::CallInst *inst) - { - return GetFunction(inst->getCalledValue()); - } + } - bool InspectInstruction(llvm::Instruction &i) override - { - Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); - - CallInst *call_inst = dyn_cast<CallInst>(&i); - - if (call_inst) - { - const llvm::Function *called_function = GetCalledFunction(call_inst); - - if (!called_function) - return true; - - std::string name_str = called_function->getName().str(); - const char* name_cstr = name_str.c_str(); - - if (log) - log->Printf("Found call to %s: %s\n", name_cstr, PrintValue(call_inst).c_str()); - - if (name_str.find("objc_msgSend") == std::string::npos) - return true; - - if (!strcmp(name_cstr, "objc_msgSend")) - { - RegisterInstruction(i); - msgSend_types[&i] = eMsgSend; - return true; - } - - if (!strcmp(name_cstr, "objc_msgSend_stret")) - { - RegisterInstruction(i); - msgSend_types[&i] = eMsgSend_stret; - return true; - } - - if (!strcmp(name_cstr, "objc_msgSend_fpret")) - { - RegisterInstruction(i); - msgSend_types[&i] = eMsgSend_fpret; - return true; - } - - if (!strcmp(name_cstr, "objc_msgSendSuper")) - { - RegisterInstruction(i); - msgSend_types[&i] = eMsgSendSuper; - return true; - } - - if (!strcmp(name_cstr, "objc_msgSendSuper_stret")) - { - RegisterInstruction(i); - msgSend_types[&i] = eMsgSendSuper_stret; - return true; - } - - if (log) - log->Printf("Function name '%s' contains 'objc_msgSend' but is not handled", name_str.c_str()); - - return true; - } + if (!strcmp(name_cstr, "objc_msgSend_fpret")) { + RegisterInstruction(i); + msgSend_types[&i] = eMsgSend_fpret; + return true; + } + if (!strcmp(name_cstr, "objc_msgSendSuper")) { + RegisterInstruction(i); + msgSend_types[&i] = eMsgSendSuper; return true; + } + + if (!strcmp(name_cstr, "objc_msgSendSuper_stret")) { + RegisterInstruction(i); + msgSend_types[&i] = eMsgSendSuper_stret; + return true; + } + + if (log) + log->Printf( + "Function name '%s' contains 'objc_msgSend' but is not handled", + name_str.c_str()); + + return true; } + return true; + } + private: - llvm::Value *m_objc_object_check_func; + llvm::Value *m_objc_object_check_func; }; IRDynamicChecks::IRDynamicChecks(DynamicCheckerFunctions &checker_functions, - const char *func_name) : - ModulePass(ID), - m_func_name(func_name), - m_checker_functions(checker_functions) -{ -} + const char *func_name) + : ModulePass(ID), m_func_name(func_name), + m_checker_functions(checker_functions) {} IRDynamicChecks::~IRDynamicChecks() = default; -bool -IRDynamicChecks::runOnModule(llvm::Module &M) -{ - Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); +bool IRDynamicChecks::runOnModule(llvm::Module &M) { + Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS)); - llvm::Function* function = M.getFunction(StringRef(m_func_name.c_str())); + llvm::Function *function = M.getFunction(StringRef(m_func_name)); - if (!function) - { - if (log) - log->Printf("Couldn't find %s() in the module", m_func_name.c_str()); + if (!function) { + if (log) + log->Printf("Couldn't find %s() in the module", m_func_name.c_str()); - return false; - } + return false; + } - if (m_checker_functions.m_valid_pointer_check) - { - ValidPointerChecker vpc(M, m_checker_functions); + if (m_checker_functions.m_valid_pointer_check) { + ValidPointerChecker vpc(M, m_checker_functions); - if (!vpc.Inspect(*function)) - return false; + if (!vpc.Inspect(*function)) + return false; - if (!vpc.Instrument()) - return false; - } + if (!vpc.Instrument()) + return false; + } - if (m_checker_functions.m_objc_object_check) - { - ObjcObjectChecker ooc(M, m_checker_functions); + if (m_checker_functions.m_objc_object_check) { + ObjcObjectChecker ooc(M, m_checker_functions); - if (!ooc.Inspect(*function)) - return false; + if (!ooc.Inspect(*function)) + return false; - if (!ooc.Instrument()) - return false; - } + if (!ooc.Instrument()) + return false; + } - if (log && log->GetVerbose()) - { - std::string s; - raw_string_ostream oss(s); + if (log && log->GetVerbose()) { + std::string s; + raw_string_ostream oss(s); - M.print(oss, nullptr); + M.print(oss, nullptr); - oss.flush(); + oss.flush(); - log->Printf ("Module after dynamic checks: \n%s", s.c_str()); - } + log->Printf("Module after dynamic checks: \n%s", s.c_str()); + } - return true; + return true; } -void -IRDynamicChecks::assignPassManager(PMStack &PMS, - PassManagerType T) -{ -} +void IRDynamicChecks::assignPassManager(PMStack &PMS, PassManagerType T) {} -PassManagerType -IRDynamicChecks::getPotentialPassManagerType() const -{ - return PMT_ModulePassManager; +PassManagerType IRDynamicChecks::getPotentialPassManagerType() const { + return PMT_ModulePassManager; } diff --git a/source/Expression/IRExecutionUnit.cpp b/source/Expression/IRExecutionUnit.cpp index 103d76328c3a..f18d96bd9e23 100644 --- a/source/Expression/IRExecutionUnit.cpp +++ b/source/Expression/IRExecutionUnit.cpp @@ -8,6 +8,7 @@ //===----------------------------------------------------------------------===// #include "llvm/ExecutionEngine/ExecutionEngine.h" +#include "llvm/ExecutionEngine/ObjectCache.h" #include "llvm/IR/Constants.h" #include "llvm/IR/LLVMContext.h" #include "llvm/IR/Module.h" @@ -21,575 +22,575 @@ #include "lldb/Core/Log.h" #include "lldb/Core/Module.h" #include "lldb/Core/Section.h" +#include "lldb/Expression/IRExecutionUnit.h" #include "lldb/Symbol/CompileUnit.h" #include "lldb/Symbol/SymbolContext.h" -#include "lldb/Symbol/SymbolVendor.h" #include "lldb/Symbol/SymbolFile.h" -#include "lldb/Expression/IRExecutionUnit.h" +#include "lldb/Symbol/SymbolVendor.h" #include "lldb/Target/ExecutionContext.h" -#include "lldb/Target/Target.h" #include "lldb/Target/ObjCLanguageRuntime.h" +#include "lldb/Target/Target.h" #include "lldb/Utility/LLDBAssert.h" #include "lldb/../../source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.h" using namespace lldb_private; -IRExecutionUnit::IRExecutionUnit (std::unique_ptr<llvm::LLVMContext> &context_ap, - std::unique_ptr<llvm::Module> &module_ap, - ConstString &name, - const lldb::TargetSP &target_sp, - const SymbolContext &sym_ctx, - std::vector<std::string> &cpu_features) : - IRMemoryMap(target_sp), - m_context_ap(context_ap.release()), - m_module_ap(module_ap.release()), - m_module(m_module_ap.get()), - m_cpu_features(cpu_features), - m_name(name), - m_sym_ctx(sym_ctx), - m_did_jit(false), - m_function_load_addr(LLDB_INVALID_ADDRESS), - m_function_end_load_addr(LLDB_INVALID_ADDRESS), - m_reported_allocations(false) -{ -} - -lldb::addr_t -IRExecutionUnit::WriteNow (const uint8_t *bytes, - size_t size, - Error &error) -{ - const bool zero_memory = false; - lldb::addr_t allocation_process_addr = Malloc (size, - 8, - lldb::ePermissionsWritable | lldb::ePermissionsReadable, - eAllocationPolicyMirror, - zero_memory, - error); - - if (!error.Success()) - return LLDB_INVALID_ADDRESS; +IRExecutionUnit::IRExecutionUnit(std::unique_ptr<llvm::LLVMContext> &context_ap, + std::unique_ptr<llvm::Module> &module_ap, + ConstString &name, + const lldb::TargetSP &target_sp, + const SymbolContext &sym_ctx, + std::vector<std::string> &cpu_features) + : IRMemoryMap(target_sp), m_context_ap(context_ap.release()), + m_module_ap(module_ap.release()), m_module(m_module_ap.get()), + m_cpu_features(cpu_features), m_name(name), m_sym_ctx(sym_ctx), + m_did_jit(false), m_function_load_addr(LLDB_INVALID_ADDRESS), + m_function_end_load_addr(LLDB_INVALID_ADDRESS), + m_reported_allocations(false) {} + +lldb::addr_t IRExecutionUnit::WriteNow(const uint8_t *bytes, size_t size, + Error &error) { + const bool zero_memory = false; + lldb::addr_t allocation_process_addr = + Malloc(size, 8, lldb::ePermissionsWritable | lldb::ePermissionsReadable, + eAllocationPolicyMirror, zero_memory, error); + + if (!error.Success()) + return LLDB_INVALID_ADDRESS; - WriteMemory(allocation_process_addr, bytes, size, error); + WriteMemory(allocation_process_addr, bytes, size, error); - if (!error.Success()) - { - Error err; - Free (allocation_process_addr, err); + if (!error.Success()) { + Error err; + Free(allocation_process_addr, err); - return LLDB_INVALID_ADDRESS; - } + return LLDB_INVALID_ADDRESS; + } - if (Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)) - { - DataBufferHeap my_buffer(size, 0); - Error err; - ReadMemory(my_buffer.GetBytes(), allocation_process_addr, size, err); + if (Log *log = + lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS)) { + DataBufferHeap my_buffer(size, 0); + Error err; + ReadMemory(my_buffer.GetBytes(), allocation_process_addr, size, err); - if (err.Success()) - { - DataExtractor my_extractor(my_buffer.GetBytes(), my_buffer.GetByteSize(), lldb::eByteOrderBig, 8); - my_extractor.PutToLog(log, 0, my_buffer.GetByteSize(), allocation_process_addr, 16, DataExtractor::TypeUInt8); - } + if (err.Success()) { + DataExtractor my_extractor(my_buffer.GetBytes(), my_buffer.GetByteSize(), + lldb::eByteOrderBig, 8); + my_extractor.PutToLog(log, 0, my_buffer.GetByteSize(), + allocation_process_addr, 16, + DataExtractor::TypeUInt8); } + } - return allocation_process_addr; + return allocation_process_addr; } -void -IRExecutionUnit::FreeNow (lldb::addr_t allocation) -{ - if (allocation == LLDB_INVALID_ADDRESS) - return; +void IRExecutionUnit::FreeNow(lldb::addr_t allocation) { + if (allocation == LLDB_INVALID_ADDRESS) + return; - Error err; + Error err; - Free(allocation, err); + Free(allocation, err); } -Error -IRExecutionUnit::DisassembleFunction (Stream &stream, - lldb::ProcessSP &process_wp) -{ - Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); +Error IRExecutionUnit::DisassembleFunction(Stream &stream, + lldb::ProcessSP &process_wp) { + Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS)); - ExecutionContext exe_ctx(process_wp); + ExecutionContext exe_ctx(process_wp); - Error ret; + Error ret; - ret.Clear(); + ret.Clear(); - lldb::addr_t func_local_addr = LLDB_INVALID_ADDRESS; - lldb::addr_t func_remote_addr = LLDB_INVALID_ADDRESS; + lldb::addr_t func_local_addr = LLDB_INVALID_ADDRESS; + lldb::addr_t func_remote_addr = LLDB_INVALID_ADDRESS; - for (JittedFunction &function : m_jitted_functions) - { - if (function.m_name == m_name) - { - func_local_addr = function.m_local_addr; - func_remote_addr = function.m_remote_addr; - } + for (JittedFunction &function : m_jitted_functions) { + if (function.m_name == m_name) { + func_local_addr = function.m_local_addr; + func_remote_addr = function.m_remote_addr; } + } - if (func_local_addr == LLDB_INVALID_ADDRESS) - { - ret.SetErrorToGenericError(); - ret.SetErrorStringWithFormat("Couldn't find function %s for disassembly", m_name.AsCString()); - return ret; - } + if (func_local_addr == LLDB_INVALID_ADDRESS) { + ret.SetErrorToGenericError(); + ret.SetErrorStringWithFormat("Couldn't find function %s for disassembly", + m_name.AsCString()); + return ret; + } - if (log) - log->Printf("Found function, has local address 0x%" PRIx64 " and remote address 0x%" PRIx64, (uint64_t)func_local_addr, (uint64_t)func_remote_addr); + if (log) + log->Printf("Found function, has local address 0x%" PRIx64 + " and remote address 0x%" PRIx64, + (uint64_t)func_local_addr, (uint64_t)func_remote_addr); - std::pair <lldb::addr_t, lldb::addr_t> func_range; + std::pair<lldb::addr_t, lldb::addr_t> func_range; - func_range = GetRemoteRangeForLocal(func_local_addr); + func_range = GetRemoteRangeForLocal(func_local_addr); - if (func_range.first == 0 && func_range.second == 0) - { - ret.SetErrorToGenericError(); - ret.SetErrorStringWithFormat("Couldn't find code range for function %s", m_name.AsCString()); - return ret; - } + if (func_range.first == 0 && func_range.second == 0) { + ret.SetErrorToGenericError(); + ret.SetErrorStringWithFormat("Couldn't find code range for function %s", + m_name.AsCString()); + return ret; + } - if (log) - log->Printf("Function's code range is [0x%" PRIx64 "+0x%" PRIx64 "]", func_range.first, func_range.second); - - Target *target = exe_ctx.GetTargetPtr(); - if (!target) - { - ret.SetErrorToGenericError(); - ret.SetErrorString("Couldn't find the target"); - return ret; - } + if (log) + log->Printf("Function's code range is [0x%" PRIx64 "+0x%" PRIx64 "]", + func_range.first, func_range.second); - lldb::DataBufferSP buffer_sp(new DataBufferHeap(func_range.second, 0)); + Target *target = exe_ctx.GetTargetPtr(); + if (!target) { + ret.SetErrorToGenericError(); + ret.SetErrorString("Couldn't find the target"); + return ret; + } - Process *process = exe_ctx.GetProcessPtr(); - Error err; - process->ReadMemory(func_remote_addr, buffer_sp->GetBytes(), buffer_sp->GetByteSize(), err); + lldb::DataBufferSP buffer_sp(new DataBufferHeap(func_range.second, 0)); - if (!err.Success()) - { - ret.SetErrorToGenericError(); - ret.SetErrorStringWithFormat("Couldn't read from process: %s", err.AsCString("unknown error")); - return ret; - } + Process *process = exe_ctx.GetProcessPtr(); + Error err; + process->ReadMemory(func_remote_addr, buffer_sp->GetBytes(), + buffer_sp->GetByteSize(), err); - ArchSpec arch(target->GetArchitecture()); + if (!err.Success()) { + ret.SetErrorToGenericError(); + ret.SetErrorStringWithFormat("Couldn't read from process: %s", + err.AsCString("unknown error")); + return ret; + } - const char *plugin_name = NULL; - const char *flavor_string = NULL; - lldb::DisassemblerSP disassembler_sp = Disassembler::FindPlugin(arch, flavor_string, plugin_name); + ArchSpec arch(target->GetArchitecture()); - if (!disassembler_sp) - { - ret.SetErrorToGenericError(); - ret.SetErrorStringWithFormat("Unable to find disassembler plug-in for %s architecture.", arch.GetArchitectureName()); - return ret; - } + const char *plugin_name = NULL; + const char *flavor_string = NULL; + lldb::DisassemblerSP disassembler_sp = + Disassembler::FindPlugin(arch, flavor_string, plugin_name); - if (!process) - { - ret.SetErrorToGenericError(); - ret.SetErrorString("Couldn't find the process"); - return ret; - } + if (!disassembler_sp) { + ret.SetErrorToGenericError(); + ret.SetErrorStringWithFormat( + "Unable to find disassembler plug-in for %s architecture.", + arch.GetArchitectureName()); + return ret; + } - DataExtractor extractor(buffer_sp, - process->GetByteOrder(), - target->GetArchitecture().GetAddressByteSize()); + if (!process) { + ret.SetErrorToGenericError(); + ret.SetErrorString("Couldn't find the process"); + return ret; + } - if (log) - { - log->Printf("Function data has contents:"); - extractor.PutToLog (log, - 0, - extractor.GetByteSize(), - func_remote_addr, - 16, - DataExtractor::TypeUInt8); - } + DataExtractor extractor(buffer_sp, process->GetByteOrder(), + target->GetArchitecture().GetAddressByteSize()); - disassembler_sp->DecodeInstructions (Address (func_remote_addr), extractor, 0, UINT32_MAX, false, false); + if (log) { + log->Printf("Function data has contents:"); + extractor.PutToLog(log, 0, extractor.GetByteSize(), func_remote_addr, 16, + DataExtractor::TypeUInt8); + } - InstructionList &instruction_list = disassembler_sp->GetInstructionList(); - instruction_list.Dump(&stream, true, true, &exe_ctx); - return ret; + disassembler_sp->DecodeInstructions(Address(func_remote_addr), extractor, 0, + UINT32_MAX, false, false); + + InstructionList &instruction_list = disassembler_sp->GetInstructionList(); + instruction_list.Dump(&stream, true, true, &exe_ctx); + return ret; } -static void ReportInlineAsmError(const llvm::SMDiagnostic &diagnostic, void *Context, unsigned LocCookie) -{ - Error *err = static_cast<Error*>(Context); +static void ReportInlineAsmError(const llvm::SMDiagnostic &diagnostic, + void *Context, unsigned LocCookie) { + Error *err = static_cast<Error *>(Context); - if (err && err->Success()) - { - err->SetErrorToGenericError(); - err->SetErrorStringWithFormat("Inline assembly error: %s", diagnostic.getMessage().str().c_str()); - } + if (err && err->Success()) { + err->SetErrorToGenericError(); + err->SetErrorStringWithFormat("Inline assembly error: %s", + diagnostic.getMessage().str().c_str()); + } } -void -IRExecutionUnit::ReportSymbolLookupError(const ConstString &name) -{ - m_failed_lookups.push_back(name); +void IRExecutionUnit::ReportSymbolLookupError(const ConstString &name) { + m_failed_lookups.push_back(name); } -void -IRExecutionUnit::GetRunnableInfo(Error &error, - lldb::addr_t &func_addr, - lldb::addr_t &func_end) -{ - lldb::ProcessSP process_sp(GetProcessWP().lock()); +void IRExecutionUnit::GetRunnableInfo(Error &error, lldb::addr_t &func_addr, + lldb::addr_t &func_end) { + lldb::ProcessSP process_sp(GetProcessWP().lock()); - static std::recursive_mutex s_runnable_info_mutex; + static std::recursive_mutex s_runnable_info_mutex; - func_addr = LLDB_INVALID_ADDRESS; - func_end = LLDB_INVALID_ADDRESS; - - if (!process_sp) - { - error.SetErrorToGenericError(); - error.SetErrorString("Couldn't write the JIT compiled code into the process because the process is invalid"); - return; - } + func_addr = LLDB_INVALID_ADDRESS; + func_end = LLDB_INVALID_ADDRESS; - if (m_did_jit) - { - func_addr = m_function_load_addr; - func_end = m_function_end_load_addr; + if (!process_sp) { + error.SetErrorToGenericError(); + error.SetErrorString("Couldn't write the JIT compiled code into the " + "process because the process is invalid"); + return; + } - return; - }; + if (m_did_jit) { + func_addr = m_function_load_addr; + func_end = m_function_end_load_addr; - std::lock_guard<std::recursive_mutex> guard(s_runnable_info_mutex); + return; + }; - m_did_jit = true; + std::lock_guard<std::recursive_mutex> guard(s_runnable_info_mutex); - Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); + m_did_jit = true; - std::string error_string; + Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS)); - if (log) - { - std::string s; - llvm::raw_string_ostream oss(s); + std::string error_string; - m_module->print(oss, NULL); + if (log) { + std::string s; + llvm::raw_string_ostream oss(s); - oss.flush(); + m_module->print(oss, NULL); - log->Printf ("Module being sent to JIT: \n%s", s.c_str()); - } + oss.flush(); - llvm::Triple triple(m_module->getTargetTriple()); - llvm::Reloc::Model relocModel; - llvm::CodeModel::Model codeModel; + log->Printf("Module being sent to JIT: \n%s", s.c_str()); + } - if (triple.isOSBinFormatELF()) - { - relocModel = llvm::Reloc::Static; - } - else - { - relocModel = llvm::Reloc::PIC_; - } + llvm::Triple triple(m_module->getTargetTriple()); + llvm::Reloc::Model relocModel; + llvm::CodeModel::Model codeModel; - // This will be small for 32-bit and large for 64-bit. - codeModel = llvm::CodeModel::JITDefault; + if (triple.isOSBinFormatELF()) { + relocModel = llvm::Reloc::Static; + } else { + relocModel = llvm::Reloc::PIC_; + } - m_module_ap->getContext().setInlineAsmDiagnosticHandler(ReportInlineAsmError, &error); + // This will be small for 32-bit and large for 64-bit. + codeModel = llvm::CodeModel::JITDefault; - llvm::EngineBuilder builder(std::move(m_module_ap)); + m_module_ap->getContext().setInlineAsmDiagnosticHandler(ReportInlineAsmError, + &error); - builder.setEngineKind(llvm::EngineKind::JIT) - .setErrorStr(&error_string) - .setRelocationModel(relocModel) - .setMCJITMemoryManager(std::unique_ptr<MemoryManager>(new MemoryManager(*this))) - .setCodeModel(codeModel) - .setOptLevel(llvm::CodeGenOpt::Less); + llvm::EngineBuilder builder(std::move(m_module_ap)); - llvm::StringRef mArch; - llvm::StringRef mCPU; - llvm::SmallVector<std::string, 0> mAttrs; + builder.setEngineKind(llvm::EngineKind::JIT) + .setErrorStr(&error_string) + .setRelocationModel(relocModel) + .setMCJITMemoryManager( + std::unique_ptr<MemoryManager>(new MemoryManager(*this))) + .setCodeModel(codeModel) + .setOptLevel(llvm::CodeGenOpt::Less) + .setUseOrcMCJITReplacement(true); - for (std::string &feature : m_cpu_features) - mAttrs.push_back(feature); + llvm::StringRef mArch; + llvm::StringRef mCPU; + llvm::SmallVector<std::string, 0> mAttrs; - llvm::TargetMachine *target_machine = builder.selectTarget(triple, - mArch, - mCPU, - mAttrs); + for (std::string &feature : m_cpu_features) + mAttrs.push_back(feature); - m_execution_engine_ap.reset(builder.create(target_machine)); + llvm::TargetMachine *target_machine = + builder.selectTarget(triple, mArch, mCPU, mAttrs); - m_strip_underscore = (m_execution_engine_ap->getDataLayout().getGlobalPrefix() == '_'); + m_execution_engine_ap.reset(builder.create(target_machine)); - if (!m_execution_engine_ap.get()) - { - error.SetErrorToGenericError(); - error.SetErrorStringWithFormat("Couldn't JIT the function: %s", error_string.c_str()); - return; - } + m_strip_underscore = + (m_execution_engine_ap->getDataLayout().getGlobalPrefix() == '_'); - // Make sure we see all sections, including ones that don't have relocations... - m_execution_engine_ap->setProcessAllSections(true); - - m_execution_engine_ap->DisableLazyCompilation(); - - for (llvm::Function &function : *m_module) - { - if (function.isDeclaration() || function.hasPrivateLinkage()) - continue; - - const bool external = function.hasExternalLinkage() || function.hasLinkOnceODRLinkage(); - - void *fun_ptr = m_execution_engine_ap->getPointerToFunction(&function); - - if (!error.Success()) - { - // We got an error through our callback! - return; - } - - if (!fun_ptr) - { - error.SetErrorToGenericError(); - error.SetErrorStringWithFormat("'%s' was in the JITted module but wasn't lowered", function.getName().str().c_str()); - return; - } - m_jitted_functions.push_back (JittedFunction(function.getName().str().c_str(), external, (lldb::addr_t)fun_ptr)); + if (!m_execution_engine_ap.get()) { + error.SetErrorToGenericError(); + error.SetErrorStringWithFormat("Couldn't JIT the function: %s", + error_string.c_str()); + return; + } + + class ObjectDumper : public llvm::ObjectCache { + public: + void notifyObjectCompiled(const llvm::Module *module, + llvm::MemoryBufferRef object) override { + int fd = 0; + llvm::SmallVector<char, 256> result_path; + std::string object_name_model = + "jit-object-" + module->getModuleIdentifier() + "-%%%.o"; + (void)llvm::sys::fs::createUniqueFile(object_name_model, fd, result_path); + llvm::raw_fd_ostream fds(fd, true); + fds.write(object.getBufferStart(), object.getBufferSize()); } - CommitAllocations(process_sp); - ReportAllocations(*m_execution_engine_ap); - - // We have to do this after calling ReportAllocations because for the MCJIT, getGlobalValueAddress - // will cause the JIT to perform all relocations. That can only be done once, and has to happen - // after we do the remapping from local -> remote. - // That means we don't know the local address of the Variables, but we don't need that for anything, - // so that's okay. - - std::function<void (llvm::GlobalValue &)> RegisterOneValue = [this] (llvm::GlobalValue &val) { - if (val.hasExternalLinkage() && !val.isDeclaration()) - { - uint64_t var_ptr_addr = m_execution_engine_ap->getGlobalValueAddress(val.getName().str()); - - lldb::addr_t remote_addr = GetRemoteAddressForLocal(var_ptr_addr); - - // This is a really unfortunae API that sometimes returns local addresses and sometimes returns remote addresses, based on whether - // the variable was relocated during ReportAllocations or not. - - if (remote_addr == LLDB_INVALID_ADDRESS) - { - remote_addr = var_ptr_addr; - } - - if (var_ptr_addr != 0) - m_jitted_global_variables.push_back (JittedGlobalVariable (val.getName().str().c_str(), LLDB_INVALID_ADDRESS, remote_addr)); - } - }; - - for (llvm::GlobalVariable &global_var : m_module->getGlobalList()) - { - RegisterOneValue(global_var); + std::unique_ptr<llvm::MemoryBuffer> + getObject(const llvm::Module *module) override { + // Return nothing - we're just abusing the object-cache mechanism to dump + // objects. + return nullptr; } - - for (llvm::GlobalAlias &global_alias : m_module->getAliasList()) - { - RegisterOneValue(global_alias); - } - - WriteData(process_sp); + }; - if (m_failed_lookups.size()) - { - StreamString ss; + if (process_sp->GetTarget().GetEnableSaveObjects()) { + m_object_cache_ap = llvm::make_unique<ObjectDumper>(); + m_execution_engine_ap->setObjectCache(m_object_cache_ap.get()); + } - ss.PutCString("Couldn't lookup symbols:\n"); + // Make sure we see all sections, including ones that don't have + // relocations... + m_execution_engine_ap->setProcessAllSections(true); - bool emitNewLine = false; + m_execution_engine_ap->DisableLazyCompilation(); - for (const ConstString &failed_lookup : m_failed_lookups) - { - if (emitNewLine) - ss.PutCString("\n"); - emitNewLine = true; - ss.PutCString(" "); - ss.PutCString(Mangled(failed_lookup).GetDemangledName(lldb::eLanguageTypeObjC_plus_plus).AsCString()); - } + for (llvm::Function &function : *m_module) { + if (function.isDeclaration() || function.hasPrivateLinkage()) + continue; - m_failed_lookups.clear(); + const bool external = + function.hasExternalLinkage() || function.hasLinkOnceODRLinkage(); - error.SetErrorString(ss.GetData()); + void *fun_ptr = m_execution_engine_ap->getPointerToFunction(&function); - return; + if (!error.Success()) { + // We got an error through our callback! + return; } - m_function_load_addr = LLDB_INVALID_ADDRESS; - m_function_end_load_addr = LLDB_INVALID_ADDRESS; - - for (JittedFunction &jitted_function : m_jitted_functions) - { - jitted_function.m_remote_addr = GetRemoteAddressForLocal (jitted_function.m_local_addr); - - if (!m_name.IsEmpty() && jitted_function.m_name == m_name) - { - AddrRange func_range = GetRemoteRangeForLocal(jitted_function.m_local_addr); - m_function_end_load_addr = func_range.first + func_range.second; - m_function_load_addr = jitted_function.m_remote_addr; - } + if (!fun_ptr) { + error.SetErrorToGenericError(); + error.SetErrorStringWithFormat( + "'%s' was in the JITted module but wasn't lowered", + function.getName().str().c_str()); + return; } + m_jitted_functions.push_back(JittedFunction( + function.getName().str().c_str(), external, (lldb::addr_t)fun_ptr)); + } + + CommitAllocations(process_sp); + ReportAllocations(*m_execution_engine_ap); + + // We have to do this after calling ReportAllocations because for the MCJIT, + // getGlobalValueAddress + // will cause the JIT to perform all relocations. That can only be done once, + // and has to happen + // after we do the remapping from local -> remote. + // That means we don't know the local address of the Variables, but we don't + // need that for anything, + // so that's okay. + + std::function<void(llvm::GlobalValue &)> RegisterOneValue = [this]( + llvm::GlobalValue &val) { + if (val.hasExternalLinkage() && !val.isDeclaration()) { + uint64_t var_ptr_addr = + m_execution_engine_ap->getGlobalValueAddress(val.getName().str()); + + lldb::addr_t remote_addr = GetRemoteAddressForLocal(var_ptr_addr); + + // This is a really unfortunae API that sometimes returns local addresses + // and sometimes returns remote addresses, based on whether + // the variable was relocated during ReportAllocations or not. + + if (remote_addr == LLDB_INVALID_ADDRESS) { + remote_addr = var_ptr_addr; + } + + if (var_ptr_addr != 0) + m_jitted_global_variables.push_back(JittedGlobalVariable( + val.getName().str().c_str(), LLDB_INVALID_ADDRESS, remote_addr)); + } + }; - if (log) - { - log->Printf("Code can be run in the target."); - - StreamString disassembly_stream; + for (llvm::GlobalVariable &global_var : m_module->getGlobalList()) { + RegisterOneValue(global_var); + } - Error err = DisassembleFunction(disassembly_stream, process_sp); + for (llvm::GlobalAlias &global_alias : m_module->getAliasList()) { + RegisterOneValue(global_alias); + } - if (!err.Success()) - { - log->Printf("Couldn't disassemble function : %s", err.AsCString("unknown error")); - } - else - { - log->Printf("Function disassembly:\n%s", disassembly_stream.GetData()); - } + WriteData(process_sp); - log->Printf("Sections: "); - for (AllocationRecord &record : m_records) - { - if (record.m_process_address != LLDB_INVALID_ADDRESS) - { - record.dump(log); + if (m_failed_lookups.size()) { + StreamString ss; - DataBufferHeap my_buffer(record.m_size, 0); - Error err; - ReadMemory(my_buffer.GetBytes(), record.m_process_address, record.m_size, err); + ss.PutCString("Couldn't lookup symbols:\n"); - if (err.Success()) - { - DataExtractor my_extractor(my_buffer.GetBytes(), my_buffer.GetByteSize(), lldb::eByteOrderBig, 8); - my_extractor.PutToLog(log, 0, my_buffer.GetByteSize(), record.m_process_address, 16, DataExtractor::TypeUInt8); - } - } - else - { - record.dump(log); + bool emitNewLine = false; - DataExtractor my_extractor ((const void*)record.m_host_address, record.m_size, lldb::eByteOrderBig, 8); - my_extractor.PutToLog(log, 0, record.m_size, record.m_host_address, 16, DataExtractor::TypeUInt8); - } - } + for (const ConstString &failed_lookup : m_failed_lookups) { + if (emitNewLine) + ss.PutCString("\n"); + emitNewLine = true; + ss.PutCString(" "); + ss.PutCString(Mangled(failed_lookup) + .GetDemangledName(lldb::eLanguageTypeObjC_plus_plus) + .AsCString()); } - func_addr = m_function_load_addr; - func_end = m_function_end_load_addr; + m_failed_lookups.clear(); - return; -} + error.SetErrorString(ss.GetString()); -IRExecutionUnit::~IRExecutionUnit () -{ - m_module_ap.reset(); - m_execution_engine_ap.reset(); - m_context_ap.reset(); -} + return; + } -IRExecutionUnit::MemoryManager::MemoryManager (IRExecutionUnit &parent) : - m_default_mm_ap (new llvm::SectionMemoryManager()), - m_parent (parent) -{ -} + m_function_load_addr = LLDB_INVALID_ADDRESS; + m_function_end_load_addr = LLDB_INVALID_ADDRESS; -IRExecutionUnit::MemoryManager::~MemoryManager () -{ -} + for (JittedFunction &jitted_function : m_jitted_functions) { + jitted_function.m_remote_addr = + GetRemoteAddressForLocal(jitted_function.m_local_addr); -lldb::SectionType -IRExecutionUnit::GetSectionTypeFromSectionName (const llvm::StringRef &name, IRExecutionUnit::AllocationKind alloc_kind) -{ - lldb::SectionType sect_type = lldb::eSectionTypeCode; - switch (alloc_kind) - { - case AllocationKind::Stub: sect_type = lldb::eSectionTypeCode; break; - case AllocationKind::Code: sect_type = lldb::eSectionTypeCode; break; - case AllocationKind::Data: sect_type = lldb::eSectionTypeData; break; - case AllocationKind::Global:sect_type = lldb::eSectionTypeData; break; - case AllocationKind::Bytes: sect_type = lldb::eSectionTypeOther; break; + if (!m_name.IsEmpty() && jitted_function.m_name == m_name) { + AddrRange func_range = + GetRemoteRangeForLocal(jitted_function.m_local_addr); + m_function_end_load_addr = func_range.first + func_range.second; + m_function_load_addr = jitted_function.m_remote_addr; } + } - if (!name.empty()) - { - if (name.equals("__text") || name.equals(".text")) - sect_type = lldb::eSectionTypeCode; - else if (name.equals("__data") || name.equals(".data")) - sect_type = lldb::eSectionTypeCode; - else if (name.startswith("__debug_") || name.startswith(".debug_")) - { - const uint32_t name_idx = name[0] == '_' ? 8 : 7; - llvm::StringRef dwarf_name(name.substr(name_idx)); - switch (dwarf_name[0]) - { - case 'a': - if (dwarf_name.equals("abbrev")) - sect_type = lldb::eSectionTypeDWARFDebugAbbrev; - else if (dwarf_name.equals("aranges")) - sect_type = lldb::eSectionTypeDWARFDebugAranges; - else if (dwarf_name.equals("addr")) - sect_type = lldb::eSectionTypeDWARFDebugAddr; - break; + if (log) { + log->Printf("Code can be run in the target."); - case 'f': - if (dwarf_name.equals("frame")) - sect_type = lldb::eSectionTypeDWARFDebugFrame; - break; + StreamString disassembly_stream; - case 'i': - if (dwarf_name.equals("info")) - sect_type = lldb::eSectionTypeDWARFDebugInfo; - break; + Error err = DisassembleFunction(disassembly_stream, process_sp); - case 'l': - if (dwarf_name.equals("line")) - sect_type = lldb::eSectionTypeDWARFDebugLine; - else if (dwarf_name.equals("loc")) - sect_type = lldb::eSectionTypeDWARFDebugLoc; - break; + if (!err.Success()) { + log->Printf("Couldn't disassemble function : %s", + err.AsCString("unknown error")); + } else { + log->Printf("Function disassembly:\n%s", disassembly_stream.GetData()); + } - case 'm': - if (dwarf_name.equals("macinfo")) - sect_type = lldb::eSectionTypeDWARFDebugMacInfo; - break; + log->Printf("Sections: "); + for (AllocationRecord &record : m_records) { + if (record.m_process_address != LLDB_INVALID_ADDRESS) { + record.dump(log); - case 'p': - if (dwarf_name.equals("pubnames")) - sect_type = lldb::eSectionTypeDWARFDebugPubNames; - else if (dwarf_name.equals("pubtypes")) - sect_type = lldb::eSectionTypeDWARFDebugPubTypes; - break; + DataBufferHeap my_buffer(record.m_size, 0); + Error err; + ReadMemory(my_buffer.GetBytes(), record.m_process_address, + record.m_size, err); + + if (err.Success()) { + DataExtractor my_extractor(my_buffer.GetBytes(), + my_buffer.GetByteSize(), + lldb::eByteOrderBig, 8); + my_extractor.PutToLog(log, 0, my_buffer.GetByteSize(), + record.m_process_address, 16, + DataExtractor::TypeUInt8); + } + } else { + record.dump(log); + + DataExtractor my_extractor((const void *)record.m_host_address, + record.m_size, lldb::eByteOrderBig, 8); + my_extractor.PutToLog(log, 0, record.m_size, record.m_host_address, 16, + DataExtractor::TypeUInt8); + } + } + } - case 's': - if (dwarf_name.equals("str")) - sect_type = lldb::eSectionTypeDWARFDebugStr; - else if (dwarf_name.equals("str_offsets")) - sect_type = lldb::eSectionTypeDWARFDebugStrOffsets; - break; + func_addr = m_function_load_addr; + func_end = m_function_end_load_addr; - case 'r': - if (dwarf_name.equals("ranges")) - sect_type = lldb::eSectionTypeDWARFDebugRanges; - break; + return; +} - default: - break; - } - } - else if (name.startswith("__apple_") || name.startswith(".apple_")) - { +IRExecutionUnit::~IRExecutionUnit() { + m_module_ap.reset(); + m_execution_engine_ap.reset(); + m_context_ap.reset(); +} + +IRExecutionUnit::MemoryManager::MemoryManager(IRExecutionUnit &parent) + : m_default_mm_ap(new llvm::SectionMemoryManager()), m_parent(parent) {} + +IRExecutionUnit::MemoryManager::~MemoryManager() {} + +lldb::SectionType IRExecutionUnit::GetSectionTypeFromSectionName( + const llvm::StringRef &name, IRExecutionUnit::AllocationKind alloc_kind) { + lldb::SectionType sect_type = lldb::eSectionTypeCode; + switch (alloc_kind) { + case AllocationKind::Stub: + sect_type = lldb::eSectionTypeCode; + break; + case AllocationKind::Code: + sect_type = lldb::eSectionTypeCode; + break; + case AllocationKind::Data: + sect_type = lldb::eSectionTypeData; + break; + case AllocationKind::Global: + sect_type = lldb::eSectionTypeData; + break; + case AllocationKind::Bytes: + sect_type = lldb::eSectionTypeOther; + break; + } + + if (!name.empty()) { + if (name.equals("__text") || name.equals(".text")) + sect_type = lldb::eSectionTypeCode; + else if (name.equals("__data") || name.equals(".data")) + sect_type = lldb::eSectionTypeCode; + else if (name.startswith("__debug_") || name.startswith(".debug_")) { + const uint32_t name_idx = name[0] == '_' ? 8 : 7; + llvm::StringRef dwarf_name(name.substr(name_idx)); + switch (dwarf_name[0]) { + case 'a': + if (dwarf_name.equals("abbrev")) + sect_type = lldb::eSectionTypeDWARFDebugAbbrev; + else if (dwarf_name.equals("aranges")) + sect_type = lldb::eSectionTypeDWARFDebugAranges; + else if (dwarf_name.equals("addr")) + sect_type = lldb::eSectionTypeDWARFDebugAddr; + break; + + case 'f': + if (dwarf_name.equals("frame")) + sect_type = lldb::eSectionTypeDWARFDebugFrame; + break; + + case 'i': + if (dwarf_name.equals("info")) + sect_type = lldb::eSectionTypeDWARFDebugInfo; + break; + + case 'l': + if (dwarf_name.equals("line")) + sect_type = lldb::eSectionTypeDWARFDebugLine; + else if (dwarf_name.equals("loc")) + sect_type = lldb::eSectionTypeDWARFDebugLoc; + break; + + case 'm': + if (dwarf_name.equals("macinfo")) + sect_type = lldb::eSectionTypeDWARFDebugMacInfo; + break; + + case 'p': + if (dwarf_name.equals("pubnames")) + sect_type = lldb::eSectionTypeDWARFDebugPubNames; + else if (dwarf_name.equals("pubtypes")) + sect_type = lldb::eSectionTypeDWARFDebugPubTypes; + break; + + case 's': + if (dwarf_name.equals("str")) + sect_type = lldb::eSectionTypeDWARFDebugStr; + else if (dwarf_name.equals("str_offsets")) + sect_type = lldb::eSectionTypeDWARFDebugStrOffsets; + break; + + case 'r': + if (dwarf_name.equals("ranges")) + sect_type = lldb::eSectionTypeDWARFDebugRanges; + break; + + default: + break; + } + } else if (name.startswith("__apple_") || name.startswith(".apple_")) { #if 0 const uint32_t name_idx = name[0] == '_' ? 8 : 7; llvm::StringRef apple_name(name.substr(name_idx)); @@ -613,776 +614,657 @@ IRExecutionUnit::GetSectionTypeFromSectionName (const llvm::StringRef &name, IRE break; } #else - sect_type = lldb::eSectionTypeInvalid; + sect_type = lldb::eSectionTypeInvalid; #endif - } - else if (name.equals("__objc_imageinfo")) - sect_type = lldb::eSectionTypeOther; - } - return sect_type; + } else if (name.equals("__objc_imageinfo")) + sect_type = lldb::eSectionTypeOther; + } + return sect_type; } -uint8_t * -IRExecutionUnit::MemoryManager::allocateCodeSection(uintptr_t Size, - unsigned Alignment, - unsigned SectionID, - llvm::StringRef SectionName) -{ - Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); +uint8_t *IRExecutionUnit::MemoryManager::allocateCodeSection( + uintptr_t Size, unsigned Alignment, unsigned SectionID, + llvm::StringRef SectionName) { + Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS)); - uint8_t *return_value = m_default_mm_ap->allocateCodeSection(Size, Alignment, SectionID, SectionName); + uint8_t *return_value = m_default_mm_ap->allocateCodeSection( + Size, Alignment, SectionID, SectionName); - m_parent.m_records.push_back(AllocationRecord((uintptr_t)return_value, - lldb::ePermissionsReadable | lldb::ePermissionsExecutable, - GetSectionTypeFromSectionName (SectionName, AllocationKind::Code), - Size, - Alignment, - SectionID, - SectionName.str().c_str())); + m_parent.m_records.push_back(AllocationRecord( + (uintptr_t)return_value, + lldb::ePermissionsReadable | lldb::ePermissionsExecutable, + GetSectionTypeFromSectionName(SectionName, AllocationKind::Code), Size, + Alignment, SectionID, SectionName.str().c_str())); - if (log) - { - log->Printf("IRExecutionUnit::allocateCodeSection(Size=0x%" PRIx64 ", Alignment=%u, SectionID=%u) = %p", - (uint64_t)Size, Alignment, SectionID, (void *)return_value); - } - - if (m_parent.m_reported_allocations) - { - Error err; - lldb::ProcessSP process_sp = m_parent.GetBestExecutionContextScope()->CalculateProcess(); - - m_parent.CommitOneAllocation(process_sp, err, m_parent.m_records.back()); - } + if (log) { + log->Printf("IRExecutionUnit::allocateCodeSection(Size=0x%" PRIx64 + ", Alignment=%u, SectionID=%u) = %p", + (uint64_t)Size, Alignment, SectionID, (void *)return_value); + } + + if (m_parent.m_reported_allocations) { + Error err; + lldb::ProcessSP process_sp = + m_parent.GetBestExecutionContextScope()->CalculateProcess(); + + m_parent.CommitOneAllocation(process_sp, err, m_parent.m_records.back()); + } - return return_value; + return return_value; } -uint8_t * -IRExecutionUnit::MemoryManager::allocateDataSection(uintptr_t Size, - unsigned Alignment, - unsigned SectionID, - llvm::StringRef SectionName, - bool IsReadOnly) -{ - Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); - - uint8_t *return_value = m_default_mm_ap->allocateDataSection(Size, Alignment, SectionID, SectionName, IsReadOnly); - - uint32_t permissions = lldb::ePermissionsReadable; - if (!IsReadOnly) - permissions |= lldb::ePermissionsWritable; - m_parent.m_records.push_back(AllocationRecord((uintptr_t)return_value, - permissions, - GetSectionTypeFromSectionName (SectionName, AllocationKind::Data), - Size, - Alignment, - SectionID, - SectionName.str().c_str())); - if (log) - { - log->Printf("IRExecutionUnit::allocateDataSection(Size=0x%" PRIx64 ", Alignment=%u, SectionID=%u) = %p", - (uint64_t)Size, Alignment, SectionID, (void *)return_value); - } - - if (m_parent.m_reported_allocations) - { - Error err; - lldb::ProcessSP process_sp = m_parent.GetBestExecutionContextScope()->CalculateProcess(); - - m_parent.CommitOneAllocation(process_sp, err, m_parent.m_records.back()); - } +uint8_t *IRExecutionUnit::MemoryManager::allocateDataSection( + uintptr_t Size, unsigned Alignment, unsigned SectionID, + llvm::StringRef SectionName, bool IsReadOnly) { + Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS)); + + uint8_t *return_value = m_default_mm_ap->allocateDataSection( + Size, Alignment, SectionID, SectionName, IsReadOnly); + + uint32_t permissions = lldb::ePermissionsReadable; + if (!IsReadOnly) + permissions |= lldb::ePermissionsWritable; + m_parent.m_records.push_back(AllocationRecord( + (uintptr_t)return_value, permissions, + GetSectionTypeFromSectionName(SectionName, AllocationKind::Data), Size, + Alignment, SectionID, SectionName.str().c_str())); + if (log) { + log->Printf("IRExecutionUnit::allocateDataSection(Size=0x%" PRIx64 + ", Alignment=%u, SectionID=%u) = %p", + (uint64_t)Size, Alignment, SectionID, (void *)return_value); + } + + if (m_parent.m_reported_allocations) { + Error err; + lldb::ProcessSP process_sp = + m_parent.GetBestExecutionContextScope()->CalculateProcess(); + + m_parent.CommitOneAllocation(process_sp, err, m_parent.m_records.back()); + } - return return_value; + return return_value; } static ConstString FindBestAlternateMangledName(const ConstString &demangled, const lldb::LanguageType &lang_type, - const SymbolContext &sym_ctx) -{ - CPlusPlusLanguage::MethodName cpp_name(demangled); - std::string scope_qualified_name = cpp_name.GetScopeQualifiedName(); - - if (!scope_qualified_name.size()) - return ConstString(); - - if (!sym_ctx.module_sp) - return ConstString(); - - SymbolVendor *sym_vendor = sym_ctx.module_sp->GetSymbolVendor(); - if (!sym_vendor) - return ConstString(); - - lldb_private::SymbolFile *sym_file = sym_vendor->GetSymbolFile(); - if (!sym_file) - return ConstString(); - - std::vector<ConstString> alternates; - sym_file->GetMangledNamesForFunction(scope_qualified_name, alternates); - - std::vector<ConstString> param_and_qual_matches; - std::vector<ConstString> param_matches; - for (size_t i = 0; i < alternates.size(); i++) - { - ConstString alternate_mangled_name = alternates[i]; - Mangled mangled(alternate_mangled_name, true); - ConstString demangled = mangled.GetDemangledName(lang_type); - - CPlusPlusLanguage::MethodName alternate_cpp_name(demangled); - if (!cpp_name.IsValid()) - continue; - - if (alternate_cpp_name.GetArguments() == cpp_name.GetArguments()) - { - if (alternate_cpp_name.GetQualifiers() == cpp_name.GetQualifiers()) - param_and_qual_matches.push_back(alternate_mangled_name); - else - param_matches.push_back(alternate_mangled_name); - } + const SymbolContext &sym_ctx) { + CPlusPlusLanguage::MethodName cpp_name(demangled); + std::string scope_qualified_name = cpp_name.GetScopeQualifiedName(); + + if (!scope_qualified_name.size()) + return ConstString(); + + if (!sym_ctx.module_sp) + return ConstString(); + + SymbolVendor *sym_vendor = sym_ctx.module_sp->GetSymbolVendor(); + if (!sym_vendor) + return ConstString(); + + lldb_private::SymbolFile *sym_file = sym_vendor->GetSymbolFile(); + if (!sym_file) + return ConstString(); + + std::vector<ConstString> alternates; + sym_file->GetMangledNamesForFunction(scope_qualified_name, alternates); + + std::vector<ConstString> param_and_qual_matches; + std::vector<ConstString> param_matches; + for (size_t i = 0; i < alternates.size(); i++) { + ConstString alternate_mangled_name = alternates[i]; + Mangled mangled(alternate_mangled_name, true); + ConstString demangled = mangled.GetDemangledName(lang_type); + + CPlusPlusLanguage::MethodName alternate_cpp_name(demangled); + if (!cpp_name.IsValid()) + continue; + + if (alternate_cpp_name.GetArguments() == cpp_name.GetArguments()) { + if (alternate_cpp_name.GetQualifiers() == cpp_name.GetQualifiers()) + param_and_qual_matches.push_back(alternate_mangled_name); + else + param_matches.push_back(alternate_mangled_name); } - - if (param_and_qual_matches.size()) - return param_and_qual_matches[0]; // It is assumed that there will be only one! - else if (param_matches.size()) - return param_matches[0]; // Return one of them as a best match - else - return ConstString(); + } + + if (param_and_qual_matches.size()) + return param_and_qual_matches[0]; // It is assumed that there will be only + // one! + else if (param_matches.size()) + return param_matches[0]; // Return one of them as a best match + else + return ConstString(); } -struct IRExecutionUnit::SearchSpec -{ - ConstString name; - uint32_t mask; +struct IRExecutionUnit::SearchSpec { + ConstString name; + uint32_t mask; - SearchSpec(ConstString n, uint32_t m = lldb::eFunctionNameTypeFull) : - name(n), - mask(m) - { - } + SearchSpec(ConstString n, uint32_t m = lldb::eFunctionNameTypeFull) + : name(n), mask(m) {} }; -void -IRExecutionUnit::CollectCandidateCNames(std::vector<IRExecutionUnit::SearchSpec> &C_specs, const ConstString &name) -{ - if (m_strip_underscore && name.AsCString()[0] == '_') - C_specs.insert(C_specs.begin(), ConstString(&name.AsCString()[1])); - C_specs.push_back(SearchSpec(name)); +void IRExecutionUnit::CollectCandidateCNames( + std::vector<IRExecutionUnit::SearchSpec> &C_specs, + const ConstString &name) { + if (m_strip_underscore && name.AsCString()[0] == '_') + C_specs.insert(C_specs.begin(), ConstString(&name.AsCString()[1])); + C_specs.push_back(SearchSpec(name)); } -void -IRExecutionUnit::CollectCandidateCPlusPlusNames(std::vector<IRExecutionUnit::SearchSpec> &CPP_specs, const std::vector<SearchSpec> &C_specs, const SymbolContext &sc) -{ - for (const SearchSpec &C_spec : C_specs) - { - const ConstString &name = C_spec.name; - - if (CPlusPlusLanguage::IsCPPMangledName(name.GetCString())) - { - Mangled mangled(name, true); - ConstString demangled = mangled.GetDemangledName(lldb::eLanguageTypeC_plus_plus); - - if (demangled) - { - ConstString best_alternate_mangled_name = FindBestAlternateMangledName(demangled, lldb::eLanguageTypeC_plus_plus, sc); - - if (best_alternate_mangled_name) - { - CPP_specs.push_back(best_alternate_mangled_name); - } +void IRExecutionUnit::CollectCandidateCPlusPlusNames( + std::vector<IRExecutionUnit::SearchSpec> &CPP_specs, + const std::vector<SearchSpec> &C_specs, const SymbolContext &sc) { + for (const SearchSpec &C_spec : C_specs) { + const ConstString &name = C_spec.name; - CPP_specs.push_back(SearchSpec(demangled, lldb::eFunctionNameTypeFull)); - } - } + if (CPlusPlusLanguage::IsCPPMangledName(name.GetCString())) { + Mangled mangled(name, true); + ConstString demangled = + mangled.GetDemangledName(lldb::eLanguageTypeC_plus_plus); - // Maybe we're looking for a const symbol but the debug info told us it was const... - if (!strncmp(name.GetCString(), "_ZN", 3) && - strncmp(name.GetCString(), "_ZNK", 4)) - { - std::string fixed_scratch("_ZNK"); - fixed_scratch.append(name.GetCString() + 3); - CPP_specs.push_back(ConstString(fixed_scratch.c_str())); - } + if (demangled) { + ConstString best_alternate_mangled_name = FindBestAlternateMangledName( + demangled, lldb::eLanguageTypeC_plus_plus, sc); - // Maybe we're looking for a static symbol but we thought it was global... - if (!strncmp(name.GetCString(), "_Z", 2) && - strncmp(name.GetCString(), "_ZL", 3)) - { - std::string fixed_scratch("_ZL"); - fixed_scratch.append(name.GetCString() + 2); - CPP_specs.push_back(ConstString(fixed_scratch.c_str())); + if (best_alternate_mangled_name) { + CPP_specs.push_back(best_alternate_mangled_name); } + CPP_specs.push_back(SearchSpec(demangled, lldb::eFunctionNameTypeFull)); + } } + + std::set<ConstString> alternates; + CPlusPlusLanguage::FindAlternateFunctionManglings(name, alternates); + CPP_specs.insert(CPP_specs.end(), alternates.begin(), alternates.end()); + } } -void -IRExecutionUnit::CollectFallbackNames(std::vector<SearchSpec> &fallback_specs, - const std::vector<SearchSpec> &C_specs) -{ - // As a last-ditch fallback, try the base name for C++ names. It's terrible, - // but the DWARF doesn't always encode "extern C" correctly. - - for (const SearchSpec &C_spec : C_specs) - { - const ConstString &name = C_spec.name; - - if (CPlusPlusLanguage::IsCPPMangledName(name.GetCString())) - { - Mangled mangled_name(name); - ConstString demangled_name = mangled_name.GetDemangledName(lldb::eLanguageTypeC_plus_plus); - if (!demangled_name.IsEmpty()) - { - const char *demangled_cstr = demangled_name.AsCString(); - const char *lparen_loc = strchr(demangled_cstr, '('); - if (lparen_loc) - { - llvm::StringRef base_name(demangled_cstr, lparen_loc-demangled_cstr); - fallback_specs.push_back(ConstString(base_name)); - } - } +void IRExecutionUnit::CollectFallbackNames( + std::vector<SearchSpec> &fallback_specs, + const std::vector<SearchSpec> &C_specs) { + // As a last-ditch fallback, try the base name for C++ names. It's terrible, + // but the DWARF doesn't always encode "extern C" correctly. + + for (const SearchSpec &C_spec : C_specs) { + const ConstString &name = C_spec.name; + + if (CPlusPlusLanguage::IsCPPMangledName(name.GetCString())) { + Mangled mangled_name(name); + ConstString demangled_name = + mangled_name.GetDemangledName(lldb::eLanguageTypeC_plus_plus); + if (!demangled_name.IsEmpty()) { + const char *demangled_cstr = demangled_name.AsCString(); + const char *lparen_loc = strchr(demangled_cstr, '('); + if (lparen_loc) { + llvm::StringRef base_name(demangled_cstr, + lparen_loc - demangled_cstr); + fallback_specs.push_back(ConstString(base_name)); } + } } + } } +lldb::addr_t IRExecutionUnit::FindInSymbols( + const std::vector<IRExecutionUnit::SearchSpec> &specs, + const lldb_private::SymbolContext &sc) { + Target *target = sc.target_sp.get(); -lldb::addr_t -IRExecutionUnit::FindInSymbols(const std::vector<IRExecutionUnit::SearchSpec> &specs, const lldb_private::SymbolContext &sc) -{ - Target *target = sc.target_sp.get(); - - if (!target) - { - // we shouldn't be doing any symbol lookup at all without a target - return LLDB_INVALID_ADDRESS; - } + if (!target) { + // we shouldn't be doing any symbol lookup at all without a target + return LLDB_INVALID_ADDRESS; + } - for (const SearchSpec &spec : specs) - { - SymbolContextList sc_list; + for (const SearchSpec &spec : specs) { + SymbolContextList sc_list; - lldb::addr_t best_internal_load_address = LLDB_INVALID_ADDRESS; + lldb::addr_t best_internal_load_address = LLDB_INVALID_ADDRESS; - std::function<bool (lldb::addr_t &, SymbolContextList &, const lldb_private::SymbolContext &)> get_external_load_address = - [&best_internal_load_address, target](lldb::addr_t &load_address, - SymbolContextList &sc_list, - const lldb_private::SymbolContext &sc) -> lldb::addr_t - { - load_address = LLDB_INVALID_ADDRESS; + std::function<bool(lldb::addr_t &, SymbolContextList &, + const lldb_private::SymbolContext &)> + get_external_load_address = [&best_internal_load_address, target]( + lldb::addr_t &load_address, SymbolContextList &sc_list, + const lldb_private::SymbolContext &sc) -> lldb::addr_t { + load_address = LLDB_INVALID_ADDRESS; - for (size_t si = 0, se = sc_list.GetSize(); si < se; ++si) - { - SymbolContext candidate_sc; - - sc_list.GetContextAtIndex(si, candidate_sc); - - const bool is_external = (candidate_sc.function) || - (candidate_sc.symbol && candidate_sc.symbol->IsExternal()); - if (candidate_sc.symbol) - { - load_address = candidate_sc.symbol->ResolveCallableAddress(*target); - - if (load_address == LLDB_INVALID_ADDRESS) - { - if (target->GetProcessSP()) - load_address = candidate_sc.symbol->GetAddress().GetLoadAddress(target); - else - load_address = candidate_sc.symbol->GetAddress().GetFileAddress(); - } - } + for (size_t si = 0, se = sc_list.GetSize(); si < se; ++si) { + SymbolContext candidate_sc; - if (load_address == LLDB_INVALID_ADDRESS && candidate_sc.function) - { - if (target->GetProcessSP()) - load_address = candidate_sc.function->GetAddressRange().GetBaseAddress().GetLoadAddress(target); - else - load_address = candidate_sc.function->GetAddressRange().GetBaseAddress().GetFileAddress(); - } + sc_list.GetContextAtIndex(si, candidate_sc); - if (load_address != LLDB_INVALID_ADDRESS) - { - if (is_external) - { - return true; - } - else if (best_internal_load_address == LLDB_INVALID_ADDRESS) - { - best_internal_load_address = load_address; - load_address = LLDB_INVALID_ADDRESS; - } - } - } + const bool is_external = + (candidate_sc.function) || + (candidate_sc.symbol && candidate_sc.symbol->IsExternal()); + if (candidate_sc.symbol) { + load_address = candidate_sc.symbol->ResolveCallableAddress(*target); - return false; - }; - - if (sc.module_sp) - { - sc.module_sp->FindFunctions(spec.name, - NULL, - spec.mask, - true, // include_symbols - false, // include_inlines - true, // append - sc_list); + if (load_address == LLDB_INVALID_ADDRESS) { + if (target->GetProcessSP()) + load_address = + candidate_sc.symbol->GetAddress().GetLoadAddress(target); + else + load_address = candidate_sc.symbol->GetAddress().GetFileAddress(); + } } - lldb::addr_t load_address = LLDB_INVALID_ADDRESS; - - if (get_external_load_address(load_address, sc_list, sc)) - { - return load_address; - } - else - { - sc_list.Clear(); + if (load_address == LLDB_INVALID_ADDRESS && candidate_sc.function) { + if (target->GetProcessSP()) + load_address = candidate_sc.function->GetAddressRange() + .GetBaseAddress() + .GetLoadAddress(target); + else + load_address = candidate_sc.function->GetAddressRange() + .GetBaseAddress() + .GetFileAddress(); } - if (sc_list.GetSize() == 0 && sc.target_sp) - { - sc.target_sp->GetImages().FindFunctions(spec.name, - spec.mask, - true, // include_symbols - false, // include_inlines - true, // append - sc_list); + if (load_address != LLDB_INVALID_ADDRESS) { + if (is_external) { + return true; + } else if (best_internal_load_address == LLDB_INVALID_ADDRESS) { + best_internal_load_address = load_address; + load_address = LLDB_INVALID_ADDRESS; + } } + } - if (get_external_load_address(load_address, sc_list, sc)) - { - return load_address; - } - else - { - sc_list.Clear(); - } + return false; + }; - if (sc_list.GetSize() == 0 && sc.target_sp) - { - sc.target_sp->GetImages().FindSymbolsWithNameAndType(spec.name, lldb::eSymbolTypeAny, sc_list); - } + if (sc.module_sp) { + sc.module_sp->FindFunctions(spec.name, NULL, spec.mask, + true, // include_symbols + false, // include_inlines + true, // append + sc_list); + } - if (get_external_load_address(load_address, sc_list, sc)) - { - return load_address; - } - // if there are any searches we try after this, add an sc_list.Clear() in an "else" clause here + lldb::addr_t load_address = LLDB_INVALID_ADDRESS; - if (best_internal_load_address != LLDB_INVALID_ADDRESS) - { - return best_internal_load_address; - } + if (get_external_load_address(load_address, sc_list, sc)) { + return load_address; + } else { + sc_list.Clear(); } - return LLDB_INVALID_ADDRESS; -} + if (sc_list.GetSize() == 0 && sc.target_sp) { + sc.target_sp->GetImages().FindFunctions(spec.name, spec.mask, + true, // include_symbols + false, // include_inlines + true, // append + sc_list); + } -lldb::addr_t -IRExecutionUnit::FindInRuntimes(const std::vector<SearchSpec> &specs, const lldb_private::SymbolContext &sc) -{ - lldb::TargetSP target_sp = sc.target_sp; + if (get_external_load_address(load_address, sc_list, sc)) { + return load_address; + } else { + sc_list.Clear(); + } - if (!target_sp) - { - return LLDB_INVALID_ADDRESS; + if (sc_list.GetSize() == 0 && sc.target_sp) { + sc.target_sp->GetImages().FindSymbolsWithNameAndType( + spec.name, lldb::eSymbolTypeAny, sc_list); } - lldb::ProcessSP process_sp = sc.target_sp->GetProcessSP(); + if (get_external_load_address(load_address, sc_list, sc)) { + return load_address; + } + // if there are any searches we try after this, add an sc_list.Clear() in an + // "else" clause here - if (!process_sp) - { - return LLDB_INVALID_ADDRESS; + if (best_internal_load_address != LLDB_INVALID_ADDRESS) { + return best_internal_load_address; } + } - ObjCLanguageRuntime *runtime = process_sp->GetObjCLanguageRuntime(); + return LLDB_INVALID_ADDRESS; +} - if (runtime) - { - for (const SearchSpec &spec : specs) - { - lldb::addr_t symbol_load_addr = runtime->LookupRuntimeSymbol(spec.name); +lldb::addr_t +IRExecutionUnit::FindInRuntimes(const std::vector<SearchSpec> &specs, + const lldb_private::SymbolContext &sc) { + lldb::TargetSP target_sp = sc.target_sp; - if (symbol_load_addr != LLDB_INVALID_ADDRESS) - return symbol_load_addr; - } - } + if (!target_sp) { + return LLDB_INVALID_ADDRESS; + } + + lldb::ProcessSP process_sp = sc.target_sp->GetProcessSP(); + if (!process_sp) { return LLDB_INVALID_ADDRESS; -} + } -lldb::addr_t -IRExecutionUnit::FindInUserDefinedSymbols(const std::vector<SearchSpec> &specs, const lldb_private::SymbolContext &sc) -{ - lldb::TargetSP target_sp = sc.target_sp; - - for (const SearchSpec &spec : specs) - { - lldb::addr_t symbol_load_addr = target_sp->GetPersistentSymbol(spec.name); - - if (symbol_load_addr != LLDB_INVALID_ADDRESS) - return symbol_load_addr; + ObjCLanguageRuntime *runtime = process_sp->GetObjCLanguageRuntime(); + + if (runtime) { + for (const SearchSpec &spec : specs) { + lldb::addr_t symbol_load_addr = runtime->LookupRuntimeSymbol(spec.name); + + if (symbol_load_addr != LLDB_INVALID_ADDRESS) + return symbol_load_addr; } - - return LLDB_INVALID_ADDRESS; + } + + return LLDB_INVALID_ADDRESS; +} + +lldb::addr_t IRExecutionUnit::FindInUserDefinedSymbols( + const std::vector<SearchSpec> &specs, + const lldb_private::SymbolContext &sc) { + lldb::TargetSP target_sp = sc.target_sp; + + for (const SearchSpec &spec : specs) { + lldb::addr_t symbol_load_addr = target_sp->GetPersistentSymbol(spec.name); + + if (symbol_load_addr != LLDB_INVALID_ADDRESS) + return symbol_load_addr; + } + + return LLDB_INVALID_ADDRESS; } lldb::addr_t -IRExecutionUnit::FindSymbol(const lldb_private::ConstString &name) -{ - std::vector<SearchSpec> candidate_C_names; - std::vector<SearchSpec> candidate_CPlusPlus_names; +IRExecutionUnit::FindSymbol(const lldb_private::ConstString &name) { + std::vector<SearchSpec> candidate_C_names; + std::vector<SearchSpec> candidate_CPlusPlus_names; - CollectCandidateCNames(candidate_C_names, name); + CollectCandidateCNames(candidate_C_names, name); - lldb::addr_t ret = FindInSymbols(candidate_C_names, m_sym_ctx); - if (ret == LLDB_INVALID_ADDRESS) - ret = FindInRuntimes(candidate_C_names, m_sym_ctx); + lldb::addr_t ret = FindInSymbols(candidate_C_names, m_sym_ctx); + if (ret == LLDB_INVALID_ADDRESS) + ret = FindInRuntimes(candidate_C_names, m_sym_ctx); - if (ret == LLDB_INVALID_ADDRESS) - ret = FindInUserDefinedSymbols(candidate_C_names, m_sym_ctx); + if (ret == LLDB_INVALID_ADDRESS) + ret = FindInUserDefinedSymbols(candidate_C_names, m_sym_ctx); - if (ret == LLDB_INVALID_ADDRESS) - { - CollectCandidateCPlusPlusNames(candidate_CPlusPlus_names, candidate_C_names, m_sym_ctx); - ret = FindInSymbols(candidate_CPlusPlus_names, m_sym_ctx); - } - - if (ret == LLDB_INVALID_ADDRESS) - { - std::vector<SearchSpec> candidate_fallback_names; + if (ret == LLDB_INVALID_ADDRESS) { + CollectCandidateCPlusPlusNames(candidate_CPlusPlus_names, candidate_C_names, + m_sym_ctx); + ret = FindInSymbols(candidate_CPlusPlus_names, m_sym_ctx); + } - CollectFallbackNames(candidate_fallback_names, candidate_C_names); - ret = FindInSymbols(candidate_fallback_names, m_sym_ctx); - } + if (ret == LLDB_INVALID_ADDRESS) { + std::vector<SearchSpec> candidate_fallback_names; - return ret; + CollectFallbackNames(candidate_fallback_names, candidate_C_names); + ret = FindInSymbols(candidate_fallback_names, m_sym_ctx); + } + + return ret; } -void -IRExecutionUnit::GetStaticInitializers(std::vector <lldb::addr_t> &static_initializers) -{ - if (llvm::GlobalVariable *global_ctors = m_module->getNamedGlobal("llvm.global_ctors")) - { - if (llvm::ConstantArray *ctor_array = llvm::dyn_cast<llvm::ConstantArray>(global_ctors->getInitializer())) - { - for (llvm::Use &ctor_use : ctor_array->operands()) - { - if (llvm::ConstantStruct *ctor_struct = llvm::dyn_cast<llvm::ConstantStruct>(ctor_use)) - { - lldbassert(ctor_struct->getNumOperands() == 3); // this is standardized - if (llvm::Function *ctor_function = llvm::dyn_cast<llvm::Function>(ctor_struct->getOperand(1))) - { - ctor_function->dump(); - - ConstString ctor_function_name_cs(ctor_function->getName().str()); - - for (JittedFunction &jitted_function : m_jitted_functions) - { - if (ctor_function_name_cs == jitted_function.m_name) - { - if (jitted_function.m_remote_addr != LLDB_INVALID_ADDRESS) - { - static_initializers.push_back(jitted_function.m_remote_addr); - } - break; - } - } - } +void IRExecutionUnit::GetStaticInitializers( + std::vector<lldb::addr_t> &static_initializers) { + if (llvm::GlobalVariable *global_ctors = + m_module->getNamedGlobal("llvm.global_ctors")) { + if (llvm::ConstantArray *ctor_array = llvm::dyn_cast<llvm::ConstantArray>( + global_ctors->getInitializer())) { + for (llvm::Use &ctor_use : ctor_array->operands()) { + if (llvm::ConstantStruct *ctor_struct = + llvm::dyn_cast<llvm::ConstantStruct>(ctor_use)) { + lldbassert(ctor_struct->getNumOperands() == + 3); // this is standardized + if (llvm::Function *ctor_function = + llvm::dyn_cast<llvm::Function>(ctor_struct->getOperand(1))) { + ConstString ctor_function_name_cs(ctor_function->getName().str()); + + for (JittedFunction &jitted_function : m_jitted_functions) { + if (ctor_function_name_cs == jitted_function.m_name) { + if (jitted_function.m_remote_addr != LLDB_INVALID_ADDRESS) { + static_initializers.push_back(jitted_function.m_remote_addr); } + break; + } } + } } + } } + } } uint64_t -IRExecutionUnit::MemoryManager::getSymbolAddress(const std::string &Name) -{ - Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); +IRExecutionUnit::MemoryManager::getSymbolAddress(const std::string &Name) { + Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS)); - ConstString name_cs(Name.c_str()); + ConstString name_cs(Name.c_str()); - lldb::addr_t ret = m_parent.FindSymbol(name_cs); + lldb::addr_t ret = m_parent.FindSymbol(name_cs); - if (ret == LLDB_INVALID_ADDRESS) - { - if (log) - log->Printf("IRExecutionUnit::getSymbolAddress(Name=\"%s\") = <not found>", - Name.c_str()); + if (ret == LLDB_INVALID_ADDRESS) { + if (log) + log->Printf( + "IRExecutionUnit::getSymbolAddress(Name=\"%s\") = <not found>", + Name.c_str()); - m_parent.ReportSymbolLookupError(name_cs); - return 0xbad0bad0; - } - else - { - if (log) - log->Printf("IRExecutionUnit::getSymbolAddress(Name=\"%s\") = %" PRIx64, - Name.c_str(), - ret); - return ret; - } + m_parent.ReportSymbolLookupError(name_cs); + return 0xbad0bad0; + } else { + if (log) + log->Printf("IRExecutionUnit::getSymbolAddress(Name=\"%s\") = %" PRIx64, + Name.c_str(), ret); + return ret; + } } -void * -IRExecutionUnit::MemoryManager::getPointerToNamedFunction(const std::string &Name, - bool AbortOnFailure) { - assert (sizeof(void *) == 8); +void *IRExecutionUnit::MemoryManager::getPointerToNamedFunction( + const std::string &Name, bool AbortOnFailure) { + assert(sizeof(void *) == 8); - return (void*)getSymbolAddress(Name); + return (void *)getSymbolAddress(Name); } lldb::addr_t -IRExecutionUnit::GetRemoteAddressForLocal (lldb::addr_t local_address) -{ - Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); +IRExecutionUnit::GetRemoteAddressForLocal(lldb::addr_t local_address) { + Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS)); - for (AllocationRecord &record : m_records) - { - if (local_address >= record.m_host_address && - local_address < record.m_host_address + record.m_size) - { - if (record.m_process_address == LLDB_INVALID_ADDRESS) - return LLDB_INVALID_ADDRESS; + for (AllocationRecord &record : m_records) { + if (local_address >= record.m_host_address && + local_address < record.m_host_address + record.m_size) { + if (record.m_process_address == LLDB_INVALID_ADDRESS) + return LLDB_INVALID_ADDRESS; - lldb::addr_t ret = record.m_process_address + (local_address - record.m_host_address); + lldb::addr_t ret = + record.m_process_address + (local_address - record.m_host_address); - if (log) - { - log->Printf("IRExecutionUnit::GetRemoteAddressForLocal() found 0x%" PRIx64 " in [0x%" PRIx64 "..0x%" PRIx64 "], and returned 0x%" PRIx64 " from [0x%" PRIx64 "..0x%" PRIx64 "].", - local_address, - (uint64_t)record.m_host_address, - (uint64_t)record.m_host_address + (uint64_t)record.m_size, - ret, - record.m_process_address, - record.m_process_address + record.m_size); - } + if (log) { + log->Printf( + "IRExecutionUnit::GetRemoteAddressForLocal() found 0x%" PRIx64 + " in [0x%" PRIx64 "..0x%" PRIx64 "], and returned 0x%" PRIx64 + " from [0x%" PRIx64 "..0x%" PRIx64 "].", + local_address, (uint64_t)record.m_host_address, + (uint64_t)record.m_host_address + (uint64_t)record.m_size, ret, + record.m_process_address, record.m_process_address + record.m_size); + } - return ret; - } + return ret; } + } - return LLDB_INVALID_ADDRESS; + return LLDB_INVALID_ADDRESS; } IRExecutionUnit::AddrRange -IRExecutionUnit::GetRemoteRangeForLocal (lldb::addr_t local_address) -{ - for (AllocationRecord &record : m_records) - { - if (local_address >= record.m_host_address && - local_address < record.m_host_address + record.m_size) - { - if (record.m_process_address == LLDB_INVALID_ADDRESS) - return AddrRange(0, 0); - - return AddrRange(record.m_process_address, record.m_size); - } +IRExecutionUnit::GetRemoteRangeForLocal(lldb::addr_t local_address) { + for (AllocationRecord &record : m_records) { + if (local_address >= record.m_host_address && + local_address < record.m_host_address + record.m_size) { + if (record.m_process_address == LLDB_INVALID_ADDRESS) + return AddrRange(0, 0); + + return AddrRange(record.m_process_address, record.m_size); } + } - return AddrRange (0, 0); + return AddrRange(0, 0); } -bool -IRExecutionUnit::CommitOneAllocation (lldb::ProcessSP &process_sp, - Error &error, - AllocationRecord &record) -{ - if (record.m_process_address != LLDB_INVALID_ADDRESS) - { - return true; - } - - switch (record.m_sect_type) - { - case lldb::eSectionTypeInvalid: - case lldb::eSectionTypeDWARFDebugAbbrev: - case lldb::eSectionTypeDWARFDebugAddr: - case lldb::eSectionTypeDWARFDebugAranges: - case lldb::eSectionTypeDWARFDebugFrame: - case lldb::eSectionTypeDWARFDebugInfo: - case lldb::eSectionTypeDWARFDebugLine: - case lldb::eSectionTypeDWARFDebugLoc: - case lldb::eSectionTypeDWARFDebugMacInfo: - case lldb::eSectionTypeDWARFDebugPubNames: - case lldb::eSectionTypeDWARFDebugPubTypes: - case lldb::eSectionTypeDWARFDebugRanges: - case lldb::eSectionTypeDWARFDebugStr: - case lldb::eSectionTypeDWARFDebugStrOffsets: - case lldb::eSectionTypeDWARFAppleNames: - case lldb::eSectionTypeDWARFAppleTypes: - case lldb::eSectionTypeDWARFAppleNamespaces: - case lldb::eSectionTypeDWARFAppleObjC: - error.Clear(); - break; - default: - const bool zero_memory = false; - record.m_process_address = Malloc (record.m_size, - record.m_alignment, - record.m_permissions, - eAllocationPolicyProcessOnly, - zero_memory, - error); - break; - } - - return error.Success(); +bool IRExecutionUnit::CommitOneAllocation(lldb::ProcessSP &process_sp, + Error &error, + AllocationRecord &record) { + if (record.m_process_address != LLDB_INVALID_ADDRESS) { + return true; + } + + switch (record.m_sect_type) { + case lldb::eSectionTypeInvalid: + case lldb::eSectionTypeDWARFDebugAbbrev: + case lldb::eSectionTypeDWARFDebugAddr: + case lldb::eSectionTypeDWARFDebugAranges: + case lldb::eSectionTypeDWARFDebugFrame: + case lldb::eSectionTypeDWARFDebugInfo: + case lldb::eSectionTypeDWARFDebugLine: + case lldb::eSectionTypeDWARFDebugLoc: + case lldb::eSectionTypeDWARFDebugMacInfo: + case lldb::eSectionTypeDWARFDebugPubNames: + case lldb::eSectionTypeDWARFDebugPubTypes: + case lldb::eSectionTypeDWARFDebugRanges: + case lldb::eSectionTypeDWARFDebugStr: + case lldb::eSectionTypeDWARFDebugStrOffsets: + case lldb::eSectionTypeDWARFAppleNames: + case lldb::eSectionTypeDWARFAppleTypes: + case lldb::eSectionTypeDWARFAppleNamespaces: + case lldb::eSectionTypeDWARFAppleObjC: + error.Clear(); + break; + default: + const bool zero_memory = false; + record.m_process_address = + Malloc(record.m_size, record.m_alignment, record.m_permissions, + eAllocationPolicyProcessOnly, zero_memory, error); + break; + } + + return error.Success(); } -bool -IRExecutionUnit::CommitAllocations (lldb::ProcessSP &process_sp) -{ - bool ret = true; +bool IRExecutionUnit::CommitAllocations(lldb::ProcessSP &process_sp) { + bool ret = true; - lldb_private::Error err; + lldb_private::Error err; - for (AllocationRecord &record : m_records) - { - ret = CommitOneAllocation(process_sp, err, record); - - if (!ret) - { - break; - } - } + for (AllocationRecord &record : m_records) { + ret = CommitOneAllocation(process_sp, err, record); - if (!ret) - { - for (AllocationRecord &record : m_records) - { - if (record.m_process_address != LLDB_INVALID_ADDRESS) - { - Free(record.m_process_address, err); - record.m_process_address = LLDB_INVALID_ADDRESS; - } - } + if (!ret) { + break; + } + } + + if (!ret) { + for (AllocationRecord &record : m_records) { + if (record.m_process_address != LLDB_INVALID_ADDRESS) { + Free(record.m_process_address, err); + record.m_process_address = LLDB_INVALID_ADDRESS; + } } + } - return ret; + return ret; } -void -IRExecutionUnit::ReportAllocations (llvm::ExecutionEngine &engine) -{ - m_reported_allocations = true; - - for (AllocationRecord &record : m_records) - { - if (record.m_process_address == LLDB_INVALID_ADDRESS) - continue; +void IRExecutionUnit::ReportAllocations(llvm::ExecutionEngine &engine) { + m_reported_allocations = true; - if (record.m_section_id == eSectionIDInvalid) - continue; + for (AllocationRecord &record : m_records) { + if (record.m_process_address == LLDB_INVALID_ADDRESS) + continue; - engine.mapSectionAddress((void*)record.m_host_address, record.m_process_address); - } + if (record.m_section_id == eSectionIDInvalid) + continue; - // Trigger re-application of relocations. - engine.finalizeObject(); -} + engine.mapSectionAddress((void *)record.m_host_address, + record.m_process_address); + } -bool -IRExecutionUnit::WriteData (lldb::ProcessSP &process_sp) -{ - bool wrote_something = false; - for (AllocationRecord &record : m_records) - { - if (record.m_process_address != LLDB_INVALID_ADDRESS) - { - lldb_private::Error err; - WriteMemory (record.m_process_address, (uint8_t*)record.m_host_address, record.m_size, err); - if (err.Success()) - wrote_something = true; - } - } - return wrote_something; + // Trigger re-application of relocations. + engine.finalizeObject(); } -void -IRExecutionUnit::AllocationRecord::dump (Log *log) -{ - if (!log) - return; - - log->Printf("[0x%llx+0x%llx]->0x%llx (alignment %d, section ID %d, name %s)", - (unsigned long long)m_host_address, - (unsigned long long)m_size, - (unsigned long long)m_process_address, - (unsigned)m_alignment, - (unsigned)m_section_id, - m_name.c_str()); +bool IRExecutionUnit::WriteData(lldb::ProcessSP &process_sp) { + bool wrote_something = false; + for (AllocationRecord &record : m_records) { + if (record.m_process_address != LLDB_INVALID_ADDRESS) { + lldb_private::Error err; + WriteMemory(record.m_process_address, (uint8_t *)record.m_host_address, + record.m_size, err); + if (err.Success()) + wrote_something = true; + } + } + return wrote_something; } +void IRExecutionUnit::AllocationRecord::dump(Log *log) { + if (!log) + return; -lldb::ByteOrder -IRExecutionUnit::GetByteOrder () const -{ - ExecutionContext exe_ctx (GetBestExecutionContextScope()); - return exe_ctx.GetByteOrder(); + log->Printf("[0x%llx+0x%llx]->0x%llx (alignment %d, section ID %d, name %s)", + (unsigned long long)m_host_address, (unsigned long long)m_size, + (unsigned long long)m_process_address, (unsigned)m_alignment, + (unsigned)m_section_id, m_name.c_str()); } -uint32_t -IRExecutionUnit::GetAddressByteSize () const -{ - ExecutionContext exe_ctx (GetBestExecutionContextScope()); - return exe_ctx.GetAddressByteSize(); +lldb::ByteOrder IRExecutionUnit::GetByteOrder() const { + ExecutionContext exe_ctx(GetBestExecutionContextScope()); + return exe_ctx.GetByteOrder(); } -void -IRExecutionUnit::PopulateSymtab (lldb_private::ObjectFile *obj_file, - lldb_private::Symtab &symtab) -{ - // No symbols yet... +uint32_t IRExecutionUnit::GetAddressByteSize() const { + ExecutionContext exe_ctx(GetBestExecutionContextScope()); + return exe_ctx.GetAddressByteSize(); } +void IRExecutionUnit::PopulateSymtab(lldb_private::ObjectFile *obj_file, + lldb_private::Symtab &symtab) { + // No symbols yet... +} -void -IRExecutionUnit::PopulateSectionList (lldb_private::ObjectFile *obj_file, - lldb_private::SectionList §ion_list) -{ - for (AllocationRecord &record : m_records) - { - if (record.m_size > 0) - { - lldb::SectionSP section_sp (new lldb_private::Section (obj_file->GetModule(), - obj_file, - record.m_section_id, - ConstString(record.m_name), - record.m_sect_type, - record.m_process_address, - record.m_size, - record.m_host_address, // file_offset (which is the host address for the data) - record.m_size, // file_size - 0, - record.m_permissions)); // flags - section_list.AddSection (section_sp); - } +void IRExecutionUnit::PopulateSectionList( + lldb_private::ObjectFile *obj_file, + lldb_private::SectionList §ion_list) { + for (AllocationRecord &record : m_records) { + if (record.m_size > 0) { + lldb::SectionSP section_sp(new lldb_private::Section( + obj_file->GetModule(), obj_file, record.m_section_id, + ConstString(record.m_name), record.m_sect_type, + record.m_process_address, record.m_size, + record.m_host_address, // file_offset (which is the host address for + // the data) + record.m_size, // file_size + 0, + record.m_permissions)); // flags + section_list.AddSection(section_sp); } + } } -bool -IRExecutionUnit::GetArchitecture (lldb_private::ArchSpec &arch) -{ - ExecutionContext exe_ctx (GetBestExecutionContextScope()); - Target *target = exe_ctx.GetTargetPtr(); - if (target) - arch = target->GetArchitecture(); - else - arch.Clear(); - return arch.IsValid(); +bool IRExecutionUnit::GetArchitecture(lldb_private::ArchSpec &arch) { + ExecutionContext exe_ctx(GetBestExecutionContextScope()); + Target *target = exe_ctx.GetTargetPtr(); + if (target) + arch = target->GetArchitecture(); + else + arch.Clear(); + return arch.IsValid(); } -lldb::ModuleSP -IRExecutionUnit::GetJITModule () -{ - ExecutionContext exe_ctx (GetBestExecutionContextScope()); - Target *target = exe_ctx.GetTargetPtr(); - if (target) - { - lldb::ModuleSP jit_module_sp = lldb_private::Module::CreateJITModule (std::static_pointer_cast<lldb_private::ObjectFileJITDelegate>(shared_from_this())); - if (jit_module_sp) - { - bool changed = false; - jit_module_sp->SetLoadAddress(*target, 0, true, changed); - } - return jit_module_sp; +lldb::ModuleSP IRExecutionUnit::GetJITModule() { + ExecutionContext exe_ctx(GetBestExecutionContextScope()); + Target *target = exe_ctx.GetTargetPtr(); + if (target) { + lldb::ModuleSP jit_module_sp = lldb_private::Module::CreateJITModule( + std::static_pointer_cast<lldb_private::ObjectFileJITDelegate>( + shared_from_this())); + if (jit_module_sp) { + bool changed = false; + jit_module_sp->SetLoadAddress(*target, 0, true, changed); } - return lldb::ModuleSP(); + return jit_module_sp; + } + return lldb::ModuleSP(); } diff --git a/source/Expression/IRInterpreter.cpp b/source/Expression/IRInterpreter.cpp index 0285248314b6..ef96b85971be 100644 --- a/source/Expression/IRInterpreter.cpp +++ b/source/Expression/IRInterpreter.cpp @@ -43,1801 +43,1665 @@ using namespace llvm; -static std::string -PrintValue(const Value *value, bool truncate = false) -{ - std::string s; - raw_string_ostream rso(s); - value->print(rso); - rso.flush(); - if (truncate) - s.resize(s.length() - 1); - - size_t offset; - while ((offset = s.find('\n')) != s.npos) - s.erase(offset, 1); - while (s[0] == ' ' || s[0] == '\t') - s.erase(0, 1); - - return s; +static std::string PrintValue(const Value *value, bool truncate = false) { + std::string s; + raw_string_ostream rso(s); + value->print(rso); + rso.flush(); + if (truncate) + s.resize(s.length() - 1); + + size_t offset; + while ((offset = s.find('\n')) != s.npos) + s.erase(offset, 1); + while (s[0] == ' ' || s[0] == '\t') + s.erase(0, 1); + + return s; } -static std::string -PrintType(const Type *type, bool truncate = false) -{ - std::string s; - raw_string_ostream rso(s); - type->print(rso); - rso.flush(); - if (truncate) - s.resize(s.length() - 1); - return s; +static std::string PrintType(const Type *type, bool truncate = false) { + std::string s; + raw_string_ostream rso(s); + type->print(rso); + rso.flush(); + if (truncate) + s.resize(s.length() - 1); + return s; } -static bool -CanIgnoreCall (const CallInst *call) -{ - const llvm::Function *called_function = call->getCalledFunction(); +static bool CanIgnoreCall(const CallInst *call) { + const llvm::Function *called_function = call->getCalledFunction(); - if (!called_function) - return false; + if (!called_function) + return false; - if (called_function->isIntrinsic()) - { - switch (called_function->getIntrinsicID()) - { - default: - break; - case llvm::Intrinsic::dbg_declare: - case llvm::Intrinsic::dbg_value: - return true; - } + if (called_function->isIntrinsic()) { + switch (called_function->getIntrinsicID()) { + default: + break; + case llvm::Intrinsic::dbg_declare: + case llvm::Intrinsic::dbg_value: + return true; } + } - return false; + return false; } -class InterpreterStackFrame -{ +class InterpreterStackFrame { public: - typedef std::map <const Value*, lldb::addr_t> ValueMap; - - ValueMap m_values; - DataLayout &m_target_data; - lldb_private::IRExecutionUnit &m_execution_unit; - const BasicBlock *m_bb; - const BasicBlock *m_prev_bb; - BasicBlock::const_iterator m_ii; - BasicBlock::const_iterator m_ie; - - lldb::addr_t m_frame_process_address; - size_t m_frame_size; - lldb::addr_t m_stack_pointer; - - lldb::ByteOrder m_byte_order; - size_t m_addr_byte_size; - - InterpreterStackFrame (DataLayout &target_data, - lldb_private::IRExecutionUnit &execution_unit, - lldb::addr_t stack_frame_bottom, - lldb::addr_t stack_frame_top) : - m_target_data (target_data), - m_execution_unit (execution_unit), - m_bb (nullptr), - m_prev_bb (nullptr) - { - m_byte_order = (target_data.isLittleEndian() ? lldb::eByteOrderLittle : lldb::eByteOrderBig); - m_addr_byte_size = (target_data.getPointerSize(0)); - - m_frame_process_address = stack_frame_bottom; - m_frame_size = stack_frame_top - stack_frame_bottom; - m_stack_pointer = stack_frame_top; + typedef std::map<const Value *, lldb::addr_t> ValueMap; + + ValueMap m_values; + DataLayout &m_target_data; + lldb_private::IRExecutionUnit &m_execution_unit; + const BasicBlock *m_bb; + const BasicBlock *m_prev_bb; + BasicBlock::const_iterator m_ii; + BasicBlock::const_iterator m_ie; + + lldb::addr_t m_frame_process_address; + size_t m_frame_size; + lldb::addr_t m_stack_pointer; + + lldb::ByteOrder m_byte_order; + size_t m_addr_byte_size; + + InterpreterStackFrame(DataLayout &target_data, + lldb_private::IRExecutionUnit &execution_unit, + lldb::addr_t stack_frame_bottom, + lldb::addr_t stack_frame_top) + : m_target_data(target_data), m_execution_unit(execution_unit), + m_bb(nullptr), m_prev_bb(nullptr) { + m_byte_order = (target_data.isLittleEndian() ? lldb::eByteOrderLittle + : lldb::eByteOrderBig); + m_addr_byte_size = (target_data.getPointerSize(0)); + + m_frame_process_address = stack_frame_bottom; + m_frame_size = stack_frame_top - stack_frame_bottom; + m_stack_pointer = stack_frame_top; + } + + ~InterpreterStackFrame() {} + + void Jump(const BasicBlock *bb) { + m_prev_bb = m_bb; + m_bb = bb; + m_ii = m_bb->begin(); + m_ie = m_bb->end(); + } + + std::string SummarizeValue(const Value *value) { + lldb_private::StreamString ss; + + ss.Printf("%s", PrintValue(value).c_str()); + + ValueMap::iterator i = m_values.find(value); + + if (i != m_values.end()) { + lldb::addr_t addr = i->second; + + ss.Printf(" 0x%llx", (unsigned long long)addr); } - ~InterpreterStackFrame () - { + return ss.GetString(); + } + + bool AssignToMatchType(lldb_private::Scalar &scalar, uint64_t u64value, + Type *type) { + size_t type_size = m_target_data.getTypeStoreSize(type); + + switch (type_size) { + case 1: + scalar = (uint8_t)u64value; + break; + case 2: + scalar = (uint16_t)u64value; + break; + case 4: + scalar = (uint32_t)u64value; + break; + case 8: + scalar = (uint64_t)u64value; + break; + default: + return false; } - void Jump (const BasicBlock *bb) - { - m_prev_bb = m_bb; - m_bb = bb; - m_ii = m_bb->begin(); - m_ie = m_bb->end(); - } + return true; + } + + bool EvaluateValue(lldb_private::Scalar &scalar, const Value *value, + Module &module) { + const Constant *constant = dyn_cast<Constant>(value); - std::string SummarizeValue (const Value *value) - { - lldb_private::StreamString ss; + if (constant) { + APInt value_apint; - ss.Printf("%s", PrintValue(value).c_str()); + if (!ResolveConstantValue(value_apint, constant)) + return false; - ValueMap::iterator i = m_values.find(value); + return AssignToMatchType(scalar, value_apint.getLimitedValue(), + value->getType()); + } else { + lldb::addr_t process_address = ResolveValue(value, module); + size_t value_size = m_target_data.getTypeStoreSize(value->getType()); - if (i != m_values.end()) - { - lldb::addr_t addr = i->second; + lldb_private::DataExtractor value_extractor; + lldb_private::Error extract_error; - ss.Printf(" 0x%llx", (unsigned long long)addr); - } + m_execution_unit.GetMemoryData(value_extractor, process_address, + value_size, extract_error); - return ss.GetString(); + if (!extract_error.Success()) + return false; + + lldb::offset_t offset = 0; + if (value_size == 1 || value_size == 2 || value_size == 4 || + value_size == 8) { + uint64_t u64value = value_extractor.GetMaxU64(&offset, value_size); + return AssignToMatchType(scalar, u64value, value->getType()); + } } - bool AssignToMatchType (lldb_private::Scalar &scalar, uint64_t u64value, Type *type) - { - size_t type_size = m_target_data.getTypeStoreSize(type); + return false; + } - switch (type_size) - { - case 1: - scalar = (uint8_t)u64value; - break; - case 2: - scalar = (uint16_t)u64value; - break; - case 4: - scalar = (uint32_t)u64value; - break; - case 8: - scalar = (uint64_t)u64value; - break; + bool AssignValue(const Value *value, lldb_private::Scalar &scalar, + Module &module) { + lldb::addr_t process_address = ResolveValue(value, module); + + if (process_address == LLDB_INVALID_ADDRESS) + return false; + + lldb_private::Scalar cast_scalar; + + if (!AssignToMatchType(cast_scalar, scalar.ULongLong(), value->getType())) + return false; + + size_t value_byte_size = m_target_data.getTypeStoreSize(value->getType()); + + lldb_private::DataBufferHeap buf(value_byte_size, 0); + + lldb_private::Error get_data_error; + + if (!cast_scalar.GetAsMemoryData(buf.GetBytes(), buf.GetByteSize(), + m_byte_order, get_data_error)) + return false; + + lldb_private::Error write_error; + + m_execution_unit.WriteMemory(process_address, buf.GetBytes(), + buf.GetByteSize(), write_error); + + return write_error.Success(); + } + + bool ResolveConstantValue(APInt &value, const Constant *constant) { + switch (constant->getValueID()) { + default: + break; + case Value::FunctionVal: + if (const Function *constant_func = dyn_cast<Function>(constant)) { + lldb_private::ConstString name(constant_func->getName()); + lldb::addr_t addr = m_execution_unit.FindSymbol(name); + if (addr == LLDB_INVALID_ADDRESS) + return false; + value = APInt(m_target_data.getPointerSizeInBits(), addr); + return true; + } + break; + case Value::ConstantIntVal: + if (const ConstantInt *constant_int = dyn_cast<ConstantInt>(constant)) { + value = constant_int->getValue(); + return true; + } + break; + case Value::ConstantFPVal: + if (const ConstantFP *constant_fp = dyn_cast<ConstantFP>(constant)) { + value = constant_fp->getValueAPF().bitcastToAPInt(); + return true; + } + break; + case Value::ConstantExprVal: + if (const ConstantExpr *constant_expr = + dyn_cast<ConstantExpr>(constant)) { + switch (constant_expr->getOpcode()) { default: + return false; + case Instruction::IntToPtr: + case Instruction::PtrToInt: + case Instruction::BitCast: + return ResolveConstantValue(value, constant_expr->getOperand(0)); + case Instruction::GetElementPtr: { + ConstantExpr::const_op_iterator op_cursor = constant_expr->op_begin(); + ConstantExpr::const_op_iterator op_end = constant_expr->op_end(); + + Constant *base = dyn_cast<Constant>(*op_cursor); + + if (!base) return false; - } - return true; - } + if (!ResolveConstantValue(value, base)) + return false; - bool EvaluateValue (lldb_private::Scalar &scalar, const Value *value, Module &module) - { - const Constant *constant = dyn_cast<Constant>(value); + op_cursor++; - if (constant) - { - APInt value_apint; + if (op_cursor == op_end) + return true; // no offset to apply! + + SmallVector<Value *, 8> indices(op_cursor, op_end); + + Type *src_elem_ty = + cast<GEPOperator>(constant_expr)->getSourceElementType(); + uint64_t offset = + m_target_data.getIndexedOffsetInType(src_elem_ty, indices); - if (!ResolveConstantValue(value_apint, constant)) - return false; + const bool is_signed = true; + value += APInt(value.getBitWidth(), offset, is_signed); - return AssignToMatchType(scalar, value_apint.getLimitedValue(), value->getType()); + return true; } - else - { - lldb::addr_t process_address = ResolveValue(value, module); - size_t value_size = m_target_data.getTypeStoreSize(value->getType()); + } + } + break; + case Value::ConstantPointerNullVal: + if (isa<ConstantPointerNull>(constant)) { + value = APInt(m_target_data.getPointerSizeInBits(), 0); + return true; + } + break; + } + return false; + } - lldb_private::DataExtractor value_extractor; - lldb_private::Error extract_error; + bool MakeArgument(const Argument *value, uint64_t address) { + lldb::addr_t data_address = Malloc(value->getType()); - m_execution_unit.GetMemoryData(value_extractor, process_address, value_size, extract_error); + if (data_address == LLDB_INVALID_ADDRESS) + return false; - if (!extract_error.Success()) - return false; + lldb_private::Error write_error; - lldb::offset_t offset = 0; - if (value_size == 1 || value_size == 2 || value_size == 4 || value_size == 8) - { - uint64_t u64value = value_extractor.GetMaxU64(&offset, value_size); - return AssignToMatchType(scalar, u64value, value->getType()); - } - } + m_execution_unit.WritePointerToMemory(data_address, address, write_error); - return false; + if (!write_error.Success()) { + lldb_private::Error free_error; + m_execution_unit.Free(data_address, free_error); + return false; } - bool AssignValue (const Value *value, lldb_private::Scalar &scalar, Module &module) - { - lldb::addr_t process_address = ResolveValue (value, module); + m_values[value] = data_address; - if (process_address == LLDB_INVALID_ADDRESS) - return false; + lldb_private::Log *log( + lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS)); - lldb_private::Scalar cast_scalar; + if (log) { + log->Printf("Made an allocation for argument %s", + PrintValue(value).c_str()); + log->Printf(" Data region : %llx", (unsigned long long)address); + log->Printf(" Ref region : %llx", (unsigned long long)data_address); + } - if (!AssignToMatchType(cast_scalar, scalar.ULongLong(), value->getType())) - return false; + return true; + } - size_t value_byte_size = m_target_data.getTypeStoreSize(value->getType()); + bool ResolveConstant(lldb::addr_t process_address, const Constant *constant) { + APInt resolved_value; - lldb_private::DataBufferHeap buf(value_byte_size, 0); + if (!ResolveConstantValue(resolved_value, constant)) + return false; - lldb_private::Error get_data_error; + size_t constant_size = m_target_data.getTypeStoreSize(constant->getType()); + lldb_private::DataBufferHeap buf(constant_size, 0); - if (!cast_scalar.GetAsMemoryData(buf.GetBytes(), buf.GetByteSize(), m_byte_order, get_data_error)) - return false; + lldb_private::Error get_data_error; + + lldb_private::Scalar resolved_scalar( + resolved_value.zextOrTrunc(llvm::NextPowerOf2(constant_size) * 8)); + if (!resolved_scalar.GetAsMemoryData(buf.GetBytes(), buf.GetByteSize(), + m_byte_order, get_data_error)) + return false; + + lldb_private::Error write_error; + + m_execution_unit.WriteMemory(process_address, buf.GetBytes(), + buf.GetByteSize(), write_error); + + return write_error.Success(); + } - lldb_private::Error write_error; + lldb::addr_t Malloc(size_t size, uint8_t byte_alignment) { + lldb::addr_t ret = m_stack_pointer; - m_execution_unit.WriteMemory(process_address, buf.GetBytes(), buf.GetByteSize(), write_error); + ret -= size; + ret -= (ret % byte_alignment); - return write_error.Success(); + if (ret < m_frame_process_address) + return LLDB_INVALID_ADDRESS; + + m_stack_pointer = ret; + return ret; + } + + lldb::addr_t MallocPointer() { + return Malloc(m_target_data.getPointerSize(), + m_target_data.getPointerPrefAlignment()); + } + + lldb::addr_t Malloc(llvm::Type *type) { + lldb_private::Error alloc_error; + + return Malloc(m_target_data.getTypeAllocSize(type), + m_target_data.getPrefTypeAlignment(type)); + } + + std::string PrintData(lldb::addr_t addr, llvm::Type *type) { + size_t length = m_target_data.getTypeStoreSize(type); + + lldb_private::DataBufferHeap buf(length, 0); + + lldb_private::Error read_error; + + m_execution_unit.ReadMemory(buf.GetBytes(), addr, length, read_error); + + if (!read_error.Success()) + return std::string("<couldn't read data>"); + + lldb_private::StreamString ss; + + for (size_t i = 0; i < length; i++) { + if ((!(i & 0xf)) && i) + ss.Printf("%02hhx - ", buf.GetBytes()[i]); + else + ss.Printf("%02hhx ", buf.GetBytes()[i]); } - bool ResolveConstantValue (APInt &value, const Constant *constant) - { - switch (constant->getValueID()) - { - default: - break; - case Value::FunctionVal: - if (const Function *constant_func = dyn_cast<Function>(constant)) - { - lldb_private::ConstString name(constant_func->getName()); - lldb::addr_t addr = m_execution_unit.FindSymbol(name); - if (addr == LLDB_INVALID_ADDRESS) - return false; - value = APInt(m_target_data.getPointerSizeInBits(), addr); - return true; - } - break; - case Value::ConstantIntVal: - if (const ConstantInt *constant_int = dyn_cast<ConstantInt>(constant)) - { - value = constant_int->getValue(); - return true; - } - break; - case Value::ConstantFPVal: - if (const ConstantFP *constant_fp = dyn_cast<ConstantFP>(constant)) - { - value = constant_fp->getValueAPF().bitcastToAPInt(); - return true; - } - break; - case Value::ConstantExprVal: - if (const ConstantExpr *constant_expr = dyn_cast<ConstantExpr>(constant)) - { - switch (constant_expr->getOpcode()) - { - default: - return false; - case Instruction::IntToPtr: - case Instruction::PtrToInt: - case Instruction::BitCast: - return ResolveConstantValue(value, constant_expr->getOperand(0)); - case Instruction::GetElementPtr: - { - ConstantExpr::const_op_iterator op_cursor = constant_expr->op_begin(); - ConstantExpr::const_op_iterator op_end = constant_expr->op_end(); - - Constant *base = dyn_cast<Constant>(*op_cursor); - - if (!base) - return false; - - if (!ResolveConstantValue(value, base)) - return false; - - op_cursor++; - - if (op_cursor == op_end) - return true; // no offset to apply! - - SmallVector <Value *, 8> indices (op_cursor, op_end); - - Type *src_elem_ty = cast<GEPOperator>(constant_expr)->getSourceElementType(); - uint64_t offset = m_target_data.getIndexedOffsetInType(src_elem_ty, indices); - - const bool is_signed = true; - value += APInt(value.getBitWidth(), offset, is_signed); - - return true; - } - } - } - break; - case Value::ConstantPointerNullVal: - if (isa<ConstantPointerNull>(constant)) - { - value = APInt(m_target_data.getPointerSizeInBits(), 0); - return true; - } - break; - } - return false; + return ss.GetString(); + } + + lldb::addr_t ResolveValue(const Value *value, Module &module) { + ValueMap::iterator i = m_values.find(value); + + if (i != m_values.end()) + return i->second; + + // Fall back and allocate space [allocation type Alloca] + + lldb::addr_t data_address = Malloc(value->getType()); + + if (const Constant *constant = dyn_cast<Constant>(value)) { + if (!ResolveConstant(data_address, constant)) { + lldb_private::Error free_error; + m_execution_unit.Free(data_address, free_error); + return LLDB_INVALID_ADDRESS; + } } - bool MakeArgument(const Argument *value, uint64_t address) - { - lldb::addr_t data_address = Malloc(value->getType()); + m_values[value] = data_address; + return data_address; + } +}; - if (data_address == LLDB_INVALID_ADDRESS) - return false; +static const char *unsupported_opcode_error = + "Interpreter doesn't handle one of the expression's opcodes"; +static const char *unsupported_operand_error = + "Interpreter doesn't handle one of the expression's operands"; +// static const char *interpreter_initialization_error = "Interpreter couldn't +// be initialized"; +static const char *interpreter_internal_error = + "Interpreter encountered an internal error"; +static const char *bad_value_error = + "Interpreter couldn't resolve a value during execution"; +static const char *memory_allocation_error = + "Interpreter couldn't allocate memory"; +static const char *memory_write_error = "Interpreter couldn't write to memory"; +static const char *memory_read_error = "Interpreter couldn't read from memory"; +static const char *infinite_loop_error = "Interpreter ran for too many cycles"; +// static const char *bad_result_error = "Result of expression +// is in bad memory"; +static const char *too_many_functions_error = + "Interpreter doesn't handle modules with multiple function bodies."; + +static bool CanResolveConstant(llvm::Constant *constant) { + switch (constant->getValueID()) { + default: + return false; + case Value::ConstantIntVal: + case Value::ConstantFPVal: + case Value::FunctionVal: + return true; + case Value::ConstantExprVal: + if (const ConstantExpr *constant_expr = dyn_cast<ConstantExpr>(constant)) { + switch (constant_expr->getOpcode()) { + default: + return false; + case Instruction::IntToPtr: + case Instruction::PtrToInt: + case Instruction::BitCast: + return CanResolveConstant(constant_expr->getOperand(0)); + case Instruction::GetElementPtr: { + ConstantExpr::const_op_iterator op_cursor = constant_expr->op_begin(); + Constant *base = dyn_cast<Constant>(*op_cursor); + if (!base) + return false; + + return CanResolveConstant(base); + } + } + } else { + return false; + } + case Value::ConstantPointerNullVal: + return true; + } +} - lldb_private::Error write_error; +bool IRInterpreter::CanInterpret(llvm::Module &module, llvm::Function &function, + lldb_private::Error &error, + const bool support_function_calls) { + lldb_private::Log *log( + lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS)); - m_execution_unit.WritePointerToMemory(data_address, address, write_error); + bool saw_function_with_body = false; - if (!write_error.Success()) - { - lldb_private::Error free_error; - m_execution_unit.Free(data_address, free_error); - return false; + for (Module::iterator fi = module.begin(), fe = module.end(); fi != fe; + ++fi) { + if (fi->begin() != fi->end()) { + if (saw_function_with_body) { + if (log) + log->Printf("More than one function in the module has a body"); + error.SetErrorToGenericError(); + error.SetErrorString(too_many_functions_error); + return false; + } + saw_function_with_body = true; + } + } + + for (Function::iterator bbi = function.begin(), bbe = function.end(); + bbi != bbe; ++bbi) { + for (BasicBlock::iterator ii = bbi->begin(), ie = bbi->end(); ii != ie; + ++ii) { + switch (ii->getOpcode()) { + default: { + if (log) + log->Printf("Unsupported instruction: %s", PrintValue(&*ii).c_str()); + error.SetErrorToGenericError(); + error.SetErrorString(unsupported_opcode_error); + return false; + } + case Instruction::Add: + case Instruction::Alloca: + case Instruction::BitCast: + case Instruction::Br: + case Instruction::PHI: + break; + case Instruction::Call: { + CallInst *call_inst = dyn_cast<CallInst>(ii); + + if (!call_inst) { + error.SetErrorToGenericError(); + error.SetErrorString(interpreter_internal_error); + return false; } - m_values[value] = data_address; + if (!CanIgnoreCall(call_inst) && !support_function_calls) { + if (log) + log->Printf("Unsupported instruction: %s", + PrintValue(&*ii).c_str()); + error.SetErrorToGenericError(); + error.SetErrorString(unsupported_opcode_error); + return false; + } + } break; + case Instruction::GetElementPtr: + break; + case Instruction::ICmp: { + ICmpInst *icmp_inst = dyn_cast<ICmpInst>(ii); + + if (!icmp_inst) { + error.SetErrorToGenericError(); + error.SetErrorString(interpreter_internal_error); + return false; + } - lldb_private::Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); + switch (icmp_inst->getPredicate()) { + default: { + if (log) + log->Printf("Unsupported ICmp predicate: %s", + PrintValue(&*ii).c_str()); - if (log) - { - log->Printf("Made an allocation for argument %s", PrintValue(value).c_str()); - log->Printf(" Data region : %llx", (unsigned long long)address); - log->Printf(" Ref region : %llx", (unsigned long long)data_address); + error.SetErrorToGenericError(); + error.SetErrorString(unsupported_opcode_error); + return false; + } + case CmpInst::ICMP_EQ: + case CmpInst::ICMP_NE: + case CmpInst::ICMP_UGT: + case CmpInst::ICMP_UGE: + case CmpInst::ICMP_ULT: + case CmpInst::ICMP_ULE: + case CmpInst::ICMP_SGT: + case CmpInst::ICMP_SGE: + case CmpInst::ICMP_SLT: + case CmpInst::ICMP_SLE: + break; + } + } break; + case Instruction::And: + case Instruction::AShr: + case Instruction::IntToPtr: + case Instruction::PtrToInt: + case Instruction::Load: + case Instruction::LShr: + case Instruction::Mul: + case Instruction::Or: + case Instruction::Ret: + case Instruction::SDiv: + case Instruction::SExt: + case Instruction::Shl: + case Instruction::SRem: + case Instruction::Store: + case Instruction::Sub: + case Instruction::Trunc: + case Instruction::UDiv: + case Instruction::URem: + case Instruction::Xor: + case Instruction::ZExt: + break; + } + + for (int oi = 0, oe = ii->getNumOperands(); oi != oe; ++oi) { + Value *operand = ii->getOperand(oi); + Type *operand_type = operand->getType(); + + switch (operand_type->getTypeID()) { + default: + break; + case Type::VectorTyID: { + if (log) + log->Printf("Unsupported operand type: %s", + PrintType(operand_type).c_str()); + error.SetErrorString(unsupported_operand_error); + return false; + } } - return true; + if (Constant *constant = llvm::dyn_cast<Constant>(operand)) { + if (!CanResolveConstant(constant)) { + if (log) + log->Printf("Unsupported constant: %s", + PrintValue(constant).c_str()); + error.SetErrorString(unsupported_operand_error); + return false; + } + } + } } + } - bool ResolveConstant (lldb::addr_t process_address, const Constant *constant) - { - APInt resolved_value; + return true; +} - if (!ResolveConstantValue(resolved_value, constant)) - return false; +bool IRInterpreter::Interpret(llvm::Module &module, llvm::Function &function, + llvm::ArrayRef<lldb::addr_t> args, + lldb_private::IRExecutionUnit &execution_unit, + lldb_private::Error &error, + lldb::addr_t stack_frame_bottom, + lldb::addr_t stack_frame_top, + lldb_private::ExecutionContext &exe_ctx) { + lldb_private::Log *log( + lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS)); + + if (log) { + std::string s; + raw_string_ostream oss(s); - size_t constant_size = m_target_data.getTypeStoreSize(constant->getType()); - lldb_private::DataBufferHeap buf(constant_size, 0); + module.print(oss, NULL); - lldb_private::Error get_data_error; + oss.flush(); - lldb_private::Scalar resolved_scalar(resolved_value.zextOrTrunc(llvm::NextPowerOf2(constant_size) * 8)); - if (!resolved_scalar.GetAsMemoryData(buf.GetBytes(), buf.GetByteSize(), m_byte_order, get_data_error)) - return false; + log->Printf("Module as passed in to IRInterpreter::Interpret: \n\"%s\"", + s.c_str()); + } + + DataLayout data_layout(&module); + + InterpreterStackFrame frame(data_layout, execution_unit, stack_frame_bottom, + stack_frame_top); - lldb_private::Error write_error; + if (frame.m_frame_process_address == LLDB_INVALID_ADDRESS) { + error.SetErrorString("Couldn't allocate stack frame"); + } - m_execution_unit.WriteMemory(process_address, buf.GetBytes(), buf.GetByteSize(), write_error); + int arg_index = 0; - return write_error.Success(); + for (llvm::Function::arg_iterator ai = function.arg_begin(), + ae = function.arg_end(); + ai != ae; ++ai, ++arg_index) { + if (args.size() <= static_cast<size_t>(arg_index)) { + error.SetErrorString("Not enough arguments passed in to function"); + return false; } - lldb::addr_t Malloc (size_t size, uint8_t byte_alignment) - { - lldb::addr_t ret = m_stack_pointer; + lldb::addr_t ptr = args[arg_index]; - ret -= size; - ret -= (ret % byte_alignment); + frame.MakeArgument(&*ai, ptr); + } - if (ret < m_frame_process_address) - return LLDB_INVALID_ADDRESS; + uint32_t num_insts = 0; - m_stack_pointer = ret; - return ret; - } + frame.Jump(&function.front()); - lldb::addr_t MallocPointer () - { - return Malloc(m_target_data.getPointerSize(), m_target_data.getPointerPrefAlignment()); - } + while (frame.m_ii != frame.m_ie && (++num_insts < 4096)) { + const Instruction *inst = &*frame.m_ii; - lldb::addr_t Malloc (llvm::Type *type) - { - lldb_private::Error alloc_error; + if (log) + log->Printf("Interpreting %s", PrintValue(inst).c_str()); - return Malloc(m_target_data.getTypeAllocSize(type), m_target_data.getPrefTypeAlignment(type)); - } + switch (inst->getOpcode()) { + default: + break; + + case Instruction::Add: + case Instruction::Sub: + case Instruction::Mul: + case Instruction::SDiv: + case Instruction::UDiv: + case Instruction::SRem: + case Instruction::URem: + case Instruction::Shl: + case Instruction::LShr: + case Instruction::AShr: + case Instruction::And: + case Instruction::Or: + case Instruction::Xor: { + const BinaryOperator *bin_op = dyn_cast<BinaryOperator>(inst); + + if (!bin_op) { + if (log) + log->Printf( + "getOpcode() returns %s, but instruction is not a BinaryOperator", + inst->getOpcodeName()); + error.SetErrorToGenericError(); + error.SetErrorString(interpreter_internal_error); + return false; + } - std::string PrintData (lldb::addr_t addr, llvm::Type *type) - { - size_t length = m_target_data.getTypeStoreSize(type); + Value *lhs = inst->getOperand(0); + Value *rhs = inst->getOperand(1); - lldb_private::DataBufferHeap buf(length, 0); + lldb_private::Scalar L; + lldb_private::Scalar R; - lldb_private::Error read_error; + if (!frame.EvaluateValue(L, lhs, module)) { + if (log) + log->Printf("Couldn't evaluate %s", PrintValue(lhs).c_str()); + error.SetErrorToGenericError(); + error.SetErrorString(bad_value_error); + return false; + } - m_execution_unit.ReadMemory(buf.GetBytes(), addr, length, read_error); + if (!frame.EvaluateValue(R, rhs, module)) { + if (log) + log->Printf("Couldn't evaluate %s", PrintValue(rhs).c_str()); + error.SetErrorToGenericError(); + error.SetErrorString(bad_value_error); + return false; + } + + lldb_private::Scalar result; + + switch (inst->getOpcode()) { + default: + break; + case Instruction::Add: + result = L + R; + break; + case Instruction::Mul: + result = L * R; + break; + case Instruction::Sub: + result = L - R; + break; + case Instruction::SDiv: + L.MakeSigned(); + R.MakeSigned(); + result = L / R; + break; + case Instruction::UDiv: + L.MakeUnsigned(); + R.MakeUnsigned(); + result = L / R; + break; + case Instruction::SRem: + L.MakeSigned(); + R.MakeSigned(); + result = L % R; + break; + case Instruction::URem: + L.MakeUnsigned(); + R.MakeUnsigned(); + result = L % R; + break; + case Instruction::Shl: + result = L << R; + break; + case Instruction::AShr: + result = L >> R; + break; + case Instruction::LShr: + result = L; + result.ShiftRightLogical(R); + break; + case Instruction::And: + result = L & R; + break; + case Instruction::Or: + result = L | R; + break; + case Instruction::Xor: + result = L ^ R; + break; + } + + frame.AssignValue(inst, result, module); + + if (log) { + log->Printf("Interpreted a %s", inst->getOpcodeName()); + log->Printf(" L : %s", frame.SummarizeValue(lhs).c_str()); + log->Printf(" R : %s", frame.SummarizeValue(rhs).c_str()); + log->Printf(" = : %s", frame.SummarizeValue(inst).c_str()); + } + } break; + case Instruction::Alloca: { + const AllocaInst *alloca_inst = dyn_cast<AllocaInst>(inst); + + if (!alloca_inst) { + if (log) + log->Printf("getOpcode() returns Alloca, but instruction is not an " + "AllocaInst"); + error.SetErrorToGenericError(); + error.SetErrorString(interpreter_internal_error); + return false; + } - if (!read_error.Success()) - return std::string("<couldn't read data>"); + if (alloca_inst->isArrayAllocation()) { + if (log) + log->Printf( + "AllocaInsts are not handled if isArrayAllocation() is true"); + error.SetErrorToGenericError(); + error.SetErrorString(unsupported_opcode_error); + return false; + } - lldb_private::StreamString ss; + // The semantics of Alloca are: + // Create a region R of virtual memory of type T, backed by a data + // buffer + // Create a region P of virtual memory of type T*, backed by a data + // buffer + // Write the virtual address of R into P - for (size_t i = 0; i < length; i++) - { - if ((!(i & 0xf)) && i) - ss.Printf("%02hhx - ", buf.GetBytes()[i]); - else - ss.Printf("%02hhx ", buf.GetBytes()[i]); - } + Type *T = alloca_inst->getAllocatedType(); + Type *Tptr = alloca_inst->getType(); - return ss.GetString(); - } + lldb::addr_t R = frame.Malloc(T); - lldb::addr_t ResolveValue (const Value *value, Module &module) - { - ValueMap::iterator i = m_values.find(value); + if (R == LLDB_INVALID_ADDRESS) { + if (log) + log->Printf("Couldn't allocate memory for an AllocaInst"); + error.SetErrorToGenericError(); + error.SetErrorString(memory_allocation_error); + return false; + } - if (i != m_values.end()) - return i->second; + lldb::addr_t P = frame.Malloc(Tptr); - // Fall back and allocate space [allocation type Alloca] + if (P == LLDB_INVALID_ADDRESS) { + if (log) + log->Printf("Couldn't allocate the result pointer for an AllocaInst"); + error.SetErrorToGenericError(); + error.SetErrorString(memory_allocation_error); + return false; + } - lldb::addr_t data_address = Malloc(value->getType()); + lldb_private::Error write_error; - if (const Constant *constant = dyn_cast<Constant>(value)) - { - if (!ResolveConstant (data_address, constant)) - { - lldb_private::Error free_error; - m_execution_unit.Free(data_address, free_error); - return LLDB_INVALID_ADDRESS; - } - } + execution_unit.WritePointerToMemory(P, R, write_error); - m_values[value] = data_address; - return data_address; - } -}; + if (!write_error.Success()) { + if (log) + log->Printf("Couldn't write the result pointer for an AllocaInst"); + error.SetErrorToGenericError(); + error.SetErrorString(memory_write_error); + lldb_private::Error free_error; + execution_unit.Free(P, free_error); + execution_unit.Free(R, free_error); + return false; + } -static const char *unsupported_opcode_error = "Interpreter doesn't handle one of the expression's opcodes"; -static const char *unsupported_operand_error = "Interpreter doesn't handle one of the expression's operands"; -//static const char *interpreter_initialization_error = "Interpreter couldn't be initialized"; -static const char *interpreter_internal_error = "Interpreter encountered an internal error"; -static const char *bad_value_error = "Interpreter couldn't resolve a value during execution"; -static const char *memory_allocation_error = "Interpreter couldn't allocate memory"; -static const char *memory_write_error = "Interpreter couldn't write to memory"; -static const char *memory_read_error = "Interpreter couldn't read from memory"; -static const char *infinite_loop_error = "Interpreter ran for too many cycles"; -//static const char *bad_result_error = "Result of expression is in bad memory"; -static const char *too_many_functions_error = "Interpreter doesn't handle modules with multiple function bodies."; - -static bool -CanResolveConstant (llvm::Constant *constant) -{ - switch (constant->getValueID()) - { - default: + frame.m_values[alloca_inst] = P; + + if (log) { + log->Printf("Interpreted an AllocaInst"); + log->Printf(" R : 0x%" PRIx64, R); + log->Printf(" P : 0x%" PRIx64, P); + } + } break; + case Instruction::BitCast: + case Instruction::ZExt: { + const CastInst *cast_inst = dyn_cast<CastInst>(inst); + + if (!cast_inst) { + if (log) + log->Printf( + "getOpcode() returns %s, but instruction is not a BitCastInst", + cast_inst->getOpcodeName()); + error.SetErrorToGenericError(); + error.SetErrorString(interpreter_internal_error); return false; - case Value::ConstantIntVal: - case Value::ConstantFPVal: - case Value::FunctionVal: - return true; - case Value::ConstantExprVal: - if (const ConstantExpr *constant_expr = dyn_cast<ConstantExpr>(constant)) - { - switch (constant_expr->getOpcode()) - { - default: - return false; - case Instruction::IntToPtr: - case Instruction::PtrToInt: - case Instruction::BitCast: - return CanResolveConstant(constant_expr->getOperand(0)); - case Instruction::GetElementPtr: - { - ConstantExpr::const_op_iterator op_cursor = constant_expr->op_begin(); - Constant *base = dyn_cast<Constant>(*op_cursor); - if (!base) - return false; - - return CanResolveConstant(base); - } - } - } else { - return false; - } - case Value::ConstantPointerNullVal: - return true; - } -} + } -bool -IRInterpreter::CanInterpret (llvm::Module &module, - llvm::Function &function, - lldb_private::Error &error, - const bool support_function_calls) -{ - lldb_private::Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); - - bool saw_function_with_body = false; - - for (Module::iterator fi = module.begin(), fe = module.end(); - fi != fe; - ++fi) - { - if (fi->begin() != fi->end()) - { - if (saw_function_with_body) - { - if (log) - log->Printf("More than one function in the module has a body"); - error.SetErrorToGenericError(); - error.SetErrorString(too_many_functions_error); - return false; - } - saw_function_with_body = true; + Value *source = cast_inst->getOperand(0); + + lldb_private::Scalar S; + + if (!frame.EvaluateValue(S, source, module)) { + if (log) + log->Printf("Couldn't evaluate %s", PrintValue(source).c_str()); + error.SetErrorToGenericError(); + error.SetErrorString(bad_value_error); + return false; + } + + frame.AssignValue(inst, S, module); + } break; + case Instruction::SExt: { + const CastInst *cast_inst = dyn_cast<CastInst>(inst); + + if (!cast_inst) { + if (log) + log->Printf( + "getOpcode() returns %s, but instruction is not a BitCastInst", + cast_inst->getOpcodeName()); + error.SetErrorToGenericError(); + error.SetErrorString(interpreter_internal_error); + return false; + } + + Value *source = cast_inst->getOperand(0); + + lldb_private::Scalar S; + + if (!frame.EvaluateValue(S, source, module)) { + if (log) + log->Printf("Couldn't evaluate %s", PrintValue(source).c_str()); + error.SetErrorToGenericError(); + error.SetErrorString(bad_value_error); + return false; + } + + S.MakeSigned(); + + lldb_private::Scalar S_signextend(S.SLongLong()); + + frame.AssignValue(inst, S_signextend, module); + } break; + case Instruction::Br: { + const BranchInst *br_inst = dyn_cast<BranchInst>(inst); + + if (!br_inst) { + if (log) + log->Printf( + "getOpcode() returns Br, but instruction is not a BranchInst"); + error.SetErrorToGenericError(); + error.SetErrorString(interpreter_internal_error); + return false; + } + + if (br_inst->isConditional()) { + Value *condition = br_inst->getCondition(); + + lldb_private::Scalar C; + + if (!frame.EvaluateValue(C, condition, module)) { + if (log) + log->Printf("Couldn't evaluate %s", PrintValue(condition).c_str()); + error.SetErrorToGenericError(); + error.SetErrorString(bad_value_error); + return false; } - } - for (Function::iterator bbi = function.begin(), bbe = function.end(); - bbi != bbe; - ++bbi) - { - for (BasicBlock::iterator ii = bbi->begin(), ie = bbi->end(); - ii != ie; - ++ii) - { - switch (ii->getOpcode()) - { - default: - { - if (log) - log->Printf("Unsupported instruction: %s", PrintValue(&*ii).c_str()); - error.SetErrorToGenericError(); - error.SetErrorString(unsupported_opcode_error); - return false; - } - case Instruction::Add: - case Instruction::Alloca: - case Instruction::BitCast: - case Instruction::Br: - case Instruction::PHI: - break; - case Instruction::Call: - { - CallInst *call_inst = dyn_cast<CallInst>(ii); - - if (!call_inst) - { - error.SetErrorToGenericError(); - error.SetErrorString(interpreter_internal_error); - return false; - } - - if (!CanIgnoreCall(call_inst) && !support_function_calls) - { - if (log) - log->Printf("Unsupported instruction: %s", PrintValue(&*ii).c_str()); - error.SetErrorToGenericError(); - error.SetErrorString(unsupported_opcode_error); - return false; - } - } - break; - case Instruction::GetElementPtr: - break; - case Instruction::ICmp: - { - ICmpInst *icmp_inst = dyn_cast<ICmpInst>(ii); - - if (!icmp_inst) - { - error.SetErrorToGenericError(); - error.SetErrorString(interpreter_internal_error); - return false; - } - - switch (icmp_inst->getPredicate()) - { - default: - { - if (log) - log->Printf("Unsupported ICmp predicate: %s", PrintValue(&*ii).c_str()); - - error.SetErrorToGenericError(); - error.SetErrorString(unsupported_opcode_error); - return false; - } - case CmpInst::ICMP_EQ: - case CmpInst::ICMP_NE: - case CmpInst::ICMP_UGT: - case CmpInst::ICMP_UGE: - case CmpInst::ICMP_ULT: - case CmpInst::ICMP_ULE: - case CmpInst::ICMP_SGT: - case CmpInst::ICMP_SGE: - case CmpInst::ICMP_SLT: - case CmpInst::ICMP_SLE: - break; - } - } - break; - case Instruction::And: - case Instruction::AShr: - case Instruction::IntToPtr: - case Instruction::PtrToInt: - case Instruction::Load: - case Instruction::LShr: - case Instruction::Mul: - case Instruction::Or: - case Instruction::Ret: - case Instruction::SDiv: - case Instruction::SExt: - case Instruction::Shl: - case Instruction::SRem: - case Instruction::Store: - case Instruction::Sub: - case Instruction::Trunc: - case Instruction::UDiv: - case Instruction::URem: - case Instruction::Xor: - case Instruction::ZExt: - break; - } + if (!C.IsZero()) + frame.Jump(br_inst->getSuccessor(0)); + else + frame.Jump(br_inst->getSuccessor(1)); - for (int oi = 0, oe = ii->getNumOperands(); - oi != oe; - ++oi) - { - Value *operand = ii->getOperand(oi); - Type *operand_type = operand->getType(); - - switch (operand_type->getTypeID()) - { - default: - break; - case Type::VectorTyID: - { - if (log) - log->Printf("Unsupported operand type: %s", PrintType(operand_type).c_str()); - error.SetErrorString(unsupported_operand_error); - return false; - } - } - - if (Constant *constant = llvm::dyn_cast<Constant>(operand)) - { - if (!CanResolveConstant(constant)) - { - if (log) - log->Printf("Unsupported constant: %s", PrintValue(constant).c_str()); - error.SetErrorString(unsupported_operand_error); - return false; - } - } - } + if (log) { + log->Printf("Interpreted a BrInst with a condition"); + log->Printf(" cond : %s", frame.SummarizeValue(condition).c_str()); } + } else { + frame.Jump(br_inst->getSuccessor(0)); + if (log) { + log->Printf("Interpreted a BrInst with no condition"); + } + } } + continue; + case Instruction::PHI: { + const PHINode *phi_inst = dyn_cast<PHINode>(inst); - return true; -} + if (!phi_inst) { + if (log) + log->Printf( + "getOpcode() returns PHI, but instruction is not a PHINode"); + error.SetErrorToGenericError(); + error.SetErrorString(interpreter_internal_error); + return false; + } + if (!frame.m_prev_bb) { + if (log) + log->Printf("Encountered PHI node without having jumped from another " + "basic block"); + error.SetErrorToGenericError(); + error.SetErrorString(interpreter_internal_error); + return false; + } -bool -IRInterpreter::Interpret (llvm::Module &module, - llvm::Function &function, - llvm::ArrayRef<lldb::addr_t> args, - lldb_private::IRExecutionUnit &execution_unit, - lldb_private::Error &error, - lldb::addr_t stack_frame_bottom, - lldb::addr_t stack_frame_top, - lldb_private::ExecutionContext &exe_ctx) -{ - lldb_private::Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); + Value *value = phi_inst->getIncomingValueForBlock(frame.m_prev_bb); + lldb_private::Scalar result; + if (!frame.EvaluateValue(result, value, module)) { + if (log) + log->Printf("Couldn't evaluate %s", PrintValue(value).c_str()); + error.SetErrorToGenericError(); + error.SetErrorString(bad_value_error); + return false; + } + frame.AssignValue(inst, result, module); + + if (log) { + log->Printf("Interpreted a %s", inst->getOpcodeName()); + log->Printf(" Incoming value : %s", + frame.SummarizeValue(value).c_str()); + } + } break; + case Instruction::GetElementPtr: { + const GetElementPtrInst *gep_inst = dyn_cast<GetElementPtrInst>(inst); + + if (!gep_inst) { + if (log) + log->Printf("getOpcode() returns GetElementPtr, but instruction is " + "not a GetElementPtrInst"); + error.SetErrorToGenericError(); + error.SetErrorString(interpreter_internal_error); + return false; + } - if (log) - { - std::string s; - raw_string_ostream oss(s); + const Value *pointer_operand = gep_inst->getPointerOperand(); + Type *src_elem_ty = gep_inst->getSourceElementType(); - module.print(oss, NULL); + lldb_private::Scalar P; - oss.flush(); + if (!frame.EvaluateValue(P, pointer_operand, module)) { + if (log) + log->Printf("Couldn't evaluate %s", + PrintValue(pointer_operand).c_str()); + error.SetErrorToGenericError(); + error.SetErrorString(bad_value_error); + return false; + } - log->Printf("Module as passed in to IRInterpreter::Interpret: \n\"%s\"", s.c_str()); - } + typedef SmallVector<Value *, 8> IndexVector; + typedef IndexVector::iterator IndexIterator; - DataLayout data_layout(&module); + SmallVector<Value *, 8> indices(gep_inst->idx_begin(), + gep_inst->idx_end()); - InterpreterStackFrame frame(data_layout, execution_unit, stack_frame_bottom, stack_frame_top); + SmallVector<Value *, 8> const_indices; - if (frame.m_frame_process_address == LLDB_INVALID_ADDRESS) - { - error.SetErrorString("Couldn't allocate stack frame"); - } + for (IndexIterator ii = indices.begin(), ie = indices.end(); ii != ie; + ++ii) { + ConstantInt *constant_index = dyn_cast<ConstantInt>(*ii); - int arg_index = 0; + if (!constant_index) { + lldb_private::Scalar I; - for (llvm::Function::arg_iterator ai = function.arg_begin(), ae = function.arg_end(); - ai != ae; - ++ai, ++arg_index) - { - if (args.size() <= static_cast<size_t>(arg_index)) - { - error.SetErrorString ("Not enough arguments passed in to function"); + if (!frame.EvaluateValue(I, *ii, module)) { + if (log) + log->Printf("Couldn't evaluate %s", PrintValue(*ii).c_str()); + error.SetErrorToGenericError(); + error.SetErrorString(bad_value_error); return false; + } + + if (log) + log->Printf("Evaluated constant index %s as %llu", + PrintValue(*ii).c_str(), + I.ULongLong(LLDB_INVALID_ADDRESS)); + + constant_index = cast<ConstantInt>(ConstantInt::get( + (*ii)->getType(), I.ULongLong(LLDB_INVALID_ADDRESS))); } - lldb::addr_t ptr = args[arg_index]; + const_indices.push_back(constant_index); + } + + uint64_t offset = + data_layout.getIndexedOffsetInType(src_elem_ty, const_indices); + + lldb_private::Scalar Poffset = P + offset; + + frame.AssignValue(inst, Poffset, module); + + if (log) { + log->Printf("Interpreted a GetElementPtrInst"); + log->Printf(" P : %s", + frame.SummarizeValue(pointer_operand).c_str()); + log->Printf(" Poffset : %s", frame.SummarizeValue(inst).c_str()); + } + } break; + case Instruction::ICmp: { + const ICmpInst *icmp_inst = dyn_cast<ICmpInst>(inst); + + if (!icmp_inst) { + if (log) + log->Printf( + "getOpcode() returns ICmp, but instruction is not an ICmpInst"); + error.SetErrorToGenericError(); + error.SetErrorString(interpreter_internal_error); + return false; + } + + CmpInst::Predicate predicate = icmp_inst->getPredicate(); + + Value *lhs = inst->getOperand(0); + Value *rhs = inst->getOperand(1); + + lldb_private::Scalar L; + lldb_private::Scalar R; + + if (!frame.EvaluateValue(L, lhs, module)) { + if (log) + log->Printf("Couldn't evaluate %s", PrintValue(lhs).c_str()); + error.SetErrorToGenericError(); + error.SetErrorString(bad_value_error); + return false; + } + + if (!frame.EvaluateValue(R, rhs, module)) { + if (log) + log->Printf("Couldn't evaluate %s", PrintValue(rhs).c_str()); + error.SetErrorToGenericError(); + error.SetErrorString(bad_value_error); + return false; + } + + lldb_private::Scalar result; + + switch (predicate) { + default: + return false; + case CmpInst::ICMP_EQ: + result = (L == R); + break; + case CmpInst::ICMP_NE: + result = (L != R); + break; + case CmpInst::ICMP_UGT: + L.MakeUnsigned(); + R.MakeUnsigned(); + result = (L > R); + break; + case CmpInst::ICMP_UGE: + L.MakeUnsigned(); + R.MakeUnsigned(); + result = (L >= R); + break; + case CmpInst::ICMP_ULT: + L.MakeUnsigned(); + R.MakeUnsigned(); + result = (L < R); + break; + case CmpInst::ICMP_ULE: + L.MakeUnsigned(); + R.MakeUnsigned(); + result = (L <= R); + break; + case CmpInst::ICMP_SGT: + L.MakeSigned(); + R.MakeSigned(); + result = (L > R); + break; + case CmpInst::ICMP_SGE: + L.MakeSigned(); + R.MakeSigned(); + result = (L >= R); + break; + case CmpInst::ICMP_SLT: + L.MakeSigned(); + R.MakeSigned(); + result = (L < R); + break; + case CmpInst::ICMP_SLE: + L.MakeSigned(); + R.MakeSigned(); + result = (L <= R); + break; + } + + frame.AssignValue(inst, result, module); + + if (log) { + log->Printf("Interpreted an ICmpInst"); + log->Printf(" L : %s", frame.SummarizeValue(lhs).c_str()); + log->Printf(" R : %s", frame.SummarizeValue(rhs).c_str()); + log->Printf(" = : %s", frame.SummarizeValue(inst).c_str()); + } + } break; + case Instruction::IntToPtr: { + const IntToPtrInst *int_to_ptr_inst = dyn_cast<IntToPtrInst>(inst); + + if (!int_to_ptr_inst) { + if (log) + log->Printf("getOpcode() returns IntToPtr, but instruction is not an " + "IntToPtrInst"); + error.SetErrorToGenericError(); + error.SetErrorString(interpreter_internal_error); + return false; + } + + Value *src_operand = int_to_ptr_inst->getOperand(0); + + lldb_private::Scalar I; + + if (!frame.EvaluateValue(I, src_operand, module)) { + if (log) + log->Printf("Couldn't evaluate %s", PrintValue(src_operand).c_str()); + error.SetErrorToGenericError(); + error.SetErrorString(bad_value_error); + return false; + } + + frame.AssignValue(inst, I, module); + + if (log) { + log->Printf("Interpreted an IntToPtr"); + log->Printf(" Src : %s", frame.SummarizeValue(src_operand).c_str()); + log->Printf(" = : %s", frame.SummarizeValue(inst).c_str()); + } + } break; + case Instruction::PtrToInt: { + const PtrToIntInst *ptr_to_int_inst = dyn_cast<PtrToIntInst>(inst); + + if (!ptr_to_int_inst) { + if (log) + log->Printf("getOpcode() returns PtrToInt, but instruction is not an " + "PtrToIntInst"); + error.SetErrorToGenericError(); + error.SetErrorString(interpreter_internal_error); + return false; + } + + Value *src_operand = ptr_to_int_inst->getOperand(0); + + lldb_private::Scalar I; + + if (!frame.EvaluateValue(I, src_operand, module)) { + if (log) + log->Printf("Couldn't evaluate %s", PrintValue(src_operand).c_str()); + error.SetErrorToGenericError(); + error.SetErrorString(bad_value_error); + return false; + } + + frame.AssignValue(inst, I, module); + + if (log) { + log->Printf("Interpreted a PtrToInt"); + log->Printf(" Src : %s", frame.SummarizeValue(src_operand).c_str()); + log->Printf(" = : %s", frame.SummarizeValue(inst).c_str()); + } + } break; + case Instruction::Trunc: { + const TruncInst *trunc_inst = dyn_cast<TruncInst>(inst); + + if (!trunc_inst) { + if (log) + log->Printf( + "getOpcode() returns Trunc, but instruction is not a TruncInst"); + error.SetErrorToGenericError(); + error.SetErrorString(interpreter_internal_error); + return false; + } + + Value *src_operand = trunc_inst->getOperand(0); + + lldb_private::Scalar I; + + if (!frame.EvaluateValue(I, src_operand, module)) { + if (log) + log->Printf("Couldn't evaluate %s", PrintValue(src_operand).c_str()); + error.SetErrorToGenericError(); + error.SetErrorString(bad_value_error); + return false; + } + + frame.AssignValue(inst, I, module); + + if (log) { + log->Printf("Interpreted a Trunc"); + log->Printf(" Src : %s", frame.SummarizeValue(src_operand).c_str()); + log->Printf(" = : %s", frame.SummarizeValue(inst).c_str()); + } + } break; + case Instruction::Load: { + const LoadInst *load_inst = dyn_cast<LoadInst>(inst); + + if (!load_inst) { + if (log) + log->Printf( + "getOpcode() returns Load, but instruction is not a LoadInst"); + error.SetErrorToGenericError(); + error.SetErrorString(interpreter_internal_error); + return false; + } + + // The semantics of Load are: + // Create a region D that will contain the loaded data + // Resolve the region P containing a pointer + // Dereference P to get the region R that the data should be loaded from + // Transfer a unit of type type(D) from R to D - frame.MakeArgument(&*ai, ptr); + const Value *pointer_operand = load_inst->getPointerOperand(); + + Type *pointer_ty = pointer_operand->getType(); + PointerType *pointer_ptr_ty = dyn_cast<PointerType>(pointer_ty); + if (!pointer_ptr_ty) { + if (log) + log->Printf("getPointerOperand()->getType() is not a PointerType"); + error.SetErrorToGenericError(); + error.SetErrorString(interpreter_internal_error); + return false; + } + Type *target_ty = pointer_ptr_ty->getElementType(); + + lldb::addr_t D = frame.ResolveValue(load_inst, module); + lldb::addr_t P = frame.ResolveValue(pointer_operand, module); + + if (D == LLDB_INVALID_ADDRESS) { + if (log) + log->Printf("LoadInst's value doesn't resolve to anything"); + error.SetErrorToGenericError(); + error.SetErrorString(bad_value_error); + return false; + } + + if (P == LLDB_INVALID_ADDRESS) { + if (log) + log->Printf("LoadInst's pointer doesn't resolve to anything"); + error.SetErrorToGenericError(); + error.SetErrorString(bad_value_error); + return false; + } + + lldb::addr_t R; + lldb_private::Error read_error; + execution_unit.ReadPointerFromMemory(&R, P, read_error); + + if (!read_error.Success()) { + if (log) + log->Printf("Couldn't read the address to be loaded for a LoadInst"); + error.SetErrorToGenericError(); + error.SetErrorString(memory_read_error); + return false; + } + + size_t target_size = data_layout.getTypeStoreSize(target_ty); + lldb_private::DataBufferHeap buffer(target_size, 0); + + read_error.Clear(); + execution_unit.ReadMemory(buffer.GetBytes(), R, buffer.GetByteSize(), + read_error); + if (!read_error.Success()) { + if (log) + log->Printf("Couldn't read from a region on behalf of a LoadInst"); + error.SetErrorToGenericError(); + error.SetErrorString(memory_read_error); + return false; + } + + lldb_private::Error write_error; + execution_unit.WriteMemory(D, buffer.GetBytes(), buffer.GetByteSize(), + write_error); + if (!write_error.Success()) { + if (log) + log->Printf("Couldn't write to a region on behalf of a LoadInst"); + error.SetErrorToGenericError(); + error.SetErrorString(memory_read_error); + return false; + } + + if (log) { + log->Printf("Interpreted a LoadInst"); + log->Printf(" P : 0x%" PRIx64, P); + log->Printf(" R : 0x%" PRIx64, R); + log->Printf(" D : 0x%" PRIx64, D); + } + } break; + case Instruction::Ret: { + return true; } + case Instruction::Store: { + const StoreInst *store_inst = dyn_cast<StoreInst>(inst); - uint32_t num_insts = 0; + if (!store_inst) { + if (log) + log->Printf( + "getOpcode() returns Store, but instruction is not a StoreInst"); + error.SetErrorToGenericError(); + error.SetErrorString(interpreter_internal_error); + return false; + } - frame.Jump(&function.front()); + // The semantics of Store are: + // Resolve the region D containing the data to be stored + // Resolve the region P containing a pointer + // Dereference P to get the region R that the data should be stored in + // Transfer a unit of type type(D) from D to R + + const Value *value_operand = store_inst->getValueOperand(); + const Value *pointer_operand = store_inst->getPointerOperand(); + + Type *pointer_ty = pointer_operand->getType(); + PointerType *pointer_ptr_ty = dyn_cast<PointerType>(pointer_ty); + if (!pointer_ptr_ty) + return false; + Type *target_ty = pointer_ptr_ty->getElementType(); - while (frame.m_ii != frame.m_ie && (++num_insts < 4096)) - { - const Instruction *inst = &*frame.m_ii; + lldb::addr_t D = frame.ResolveValue(value_operand, module); + lldb::addr_t P = frame.ResolveValue(pointer_operand, module); + if (D == LLDB_INVALID_ADDRESS) { if (log) - log->Printf("Interpreting %s", PrintValue(inst).c_str()); + log->Printf("StoreInst's value doesn't resolve to anything"); + error.SetErrorToGenericError(); + error.SetErrorString(bad_value_error); + return false; + } - switch (inst->getOpcode()) - { - default: - break; - - case Instruction::Add: - case Instruction::Sub: - case Instruction::Mul: - case Instruction::SDiv: - case Instruction::UDiv: - case Instruction::SRem: - case Instruction::URem: - case Instruction::Shl: - case Instruction::LShr: - case Instruction::AShr: - case Instruction::And: - case Instruction::Or: - case Instruction::Xor: - { - const BinaryOperator *bin_op = dyn_cast<BinaryOperator>(inst); - - if (!bin_op) - { - if (log) - log->Printf("getOpcode() returns %s, but instruction is not a BinaryOperator", inst->getOpcodeName()); - error.SetErrorToGenericError(); - error.SetErrorString(interpreter_internal_error); - return false; - } - - Value *lhs = inst->getOperand(0); - Value *rhs = inst->getOperand(1); - - lldb_private::Scalar L; - lldb_private::Scalar R; - - if (!frame.EvaluateValue(L, lhs, module)) - { - if (log) - log->Printf("Couldn't evaluate %s", PrintValue(lhs).c_str()); - error.SetErrorToGenericError(); - error.SetErrorString(bad_value_error); - return false; - } - - if (!frame.EvaluateValue(R, rhs, module)) - { - if (log) - log->Printf("Couldn't evaluate %s", PrintValue(rhs).c_str()); - error.SetErrorToGenericError(); - error.SetErrorString(bad_value_error); - return false; - } - - lldb_private::Scalar result; - - switch (inst->getOpcode()) - { - default: - break; - case Instruction::Add: - result = L + R; - break; - case Instruction::Mul: - result = L * R; - break; - case Instruction::Sub: - result = L - R; - break; - case Instruction::SDiv: - L.MakeSigned(); - R.MakeSigned(); - result = L / R; - break; - case Instruction::UDiv: - L.MakeUnsigned(); - R.MakeUnsigned(); - result = L / R; - break; - case Instruction::SRem: - L.MakeSigned(); - R.MakeSigned(); - result = L % R; - break; - case Instruction::URem: - L.MakeUnsigned(); - R.MakeUnsigned(); - result = L % R; - break; - case Instruction::Shl: - result = L << R; - break; - case Instruction::AShr: - result = L >> R; - break; - case Instruction::LShr: - result = L; - result.ShiftRightLogical(R); - break; - case Instruction::And: - result = L & R; - break; - case Instruction::Or: - result = L | R; - break; - case Instruction::Xor: - result = L ^ R; - break; - } - - frame.AssignValue(inst, result, module); - - if (log) - { - log->Printf("Interpreted a %s", inst->getOpcodeName()); - log->Printf(" L : %s", frame.SummarizeValue(lhs).c_str()); - log->Printf(" R : %s", frame.SummarizeValue(rhs).c_str()); - log->Printf(" = : %s", frame.SummarizeValue(inst).c_str()); - } - } - break; - case Instruction::Alloca: - { - const AllocaInst *alloca_inst = dyn_cast<AllocaInst>(inst); - - if (!alloca_inst) - { - if (log) - log->Printf("getOpcode() returns Alloca, but instruction is not an AllocaInst"); - error.SetErrorToGenericError(); - error.SetErrorString(interpreter_internal_error); - return false; - } - - if (alloca_inst->isArrayAllocation()) - { - if (log) - log->Printf("AllocaInsts are not handled if isArrayAllocation() is true"); - error.SetErrorToGenericError(); - error.SetErrorString(unsupported_opcode_error); - return false; - } - - // The semantics of Alloca are: - // Create a region R of virtual memory of type T, backed by a data buffer - // Create a region P of virtual memory of type T*, backed by a data buffer - // Write the virtual address of R into P - - Type *T = alloca_inst->getAllocatedType(); - Type *Tptr = alloca_inst->getType(); - - lldb::addr_t R = frame.Malloc(T); - - if (R == LLDB_INVALID_ADDRESS) - { - if (log) - log->Printf("Couldn't allocate memory for an AllocaInst"); - error.SetErrorToGenericError(); - error.SetErrorString(memory_allocation_error); - return false; - } - - lldb::addr_t P = frame.Malloc(Tptr); - - if (P == LLDB_INVALID_ADDRESS) - { - if (log) - log->Printf("Couldn't allocate the result pointer for an AllocaInst"); - error.SetErrorToGenericError(); - error.SetErrorString(memory_allocation_error); - return false; - } - - lldb_private::Error write_error; - - execution_unit.WritePointerToMemory(P, R, write_error); - - if (!write_error.Success()) - { - if (log) - log->Printf("Couldn't write the result pointer for an AllocaInst"); - error.SetErrorToGenericError(); - error.SetErrorString(memory_write_error); - lldb_private::Error free_error; - execution_unit.Free(P, free_error); - execution_unit.Free(R, free_error); - return false; - } - - frame.m_values[alloca_inst] = P; - - if (log) - { - log->Printf("Interpreted an AllocaInst"); - log->Printf(" R : 0x%" PRIx64, R); - log->Printf(" P : 0x%" PRIx64, P); - } - } - break; - case Instruction::BitCast: - case Instruction::ZExt: - { - const CastInst *cast_inst = dyn_cast<CastInst>(inst); - - if (!cast_inst) - { - if (log) - log->Printf("getOpcode() returns %s, but instruction is not a BitCastInst", cast_inst->getOpcodeName()); - error.SetErrorToGenericError(); - error.SetErrorString(interpreter_internal_error); - return false; - } - - Value *source = cast_inst->getOperand(0); - - lldb_private::Scalar S; - - if (!frame.EvaluateValue(S, source, module)) - { - if (log) - log->Printf("Couldn't evaluate %s", PrintValue(source).c_str()); - error.SetErrorToGenericError(); - error.SetErrorString(bad_value_error); - return false; - } - - frame.AssignValue(inst, S, module); - } - break; - case Instruction::SExt: - { - const CastInst *cast_inst = dyn_cast<CastInst>(inst); - - if (!cast_inst) - { - if (log) - log->Printf("getOpcode() returns %s, but instruction is not a BitCastInst", cast_inst->getOpcodeName()); - error.SetErrorToGenericError(); - error.SetErrorString(interpreter_internal_error); - return false; - } - - Value *source = cast_inst->getOperand(0); - - lldb_private::Scalar S; - - if (!frame.EvaluateValue(S, source, module)) - { - if (log) - log->Printf("Couldn't evaluate %s", PrintValue(source).c_str()); - error.SetErrorToGenericError(); - error.SetErrorString(bad_value_error); - return false; - } - - S.MakeSigned(); - - lldb_private::Scalar S_signextend(S.SLongLong()); - - frame.AssignValue(inst, S_signextend, module); - } - break; - case Instruction::Br: - { - const BranchInst *br_inst = dyn_cast<BranchInst>(inst); - - if (!br_inst) - { - if (log) - log->Printf("getOpcode() returns Br, but instruction is not a BranchInst"); - error.SetErrorToGenericError(); - error.SetErrorString(interpreter_internal_error); - return false; - } - - if (br_inst->isConditional()) - { - Value *condition = br_inst->getCondition(); - - lldb_private::Scalar C; - - if (!frame.EvaluateValue(C, condition, module)) - { - if (log) - log->Printf("Couldn't evaluate %s", PrintValue(condition).c_str()); - error.SetErrorToGenericError(); - error.SetErrorString(bad_value_error); - return false; - } - - if (!C.IsZero()) - frame.Jump(br_inst->getSuccessor(0)); - else - frame.Jump(br_inst->getSuccessor(1)); - - if (log) - { - log->Printf("Interpreted a BrInst with a condition"); - log->Printf(" cond : %s", frame.SummarizeValue(condition).c_str()); - } - } - else - { - frame.Jump(br_inst->getSuccessor(0)); - - if (log) - { - log->Printf("Interpreted a BrInst with no condition"); - } - } - } - continue; - case Instruction::PHI: - { - const PHINode *phi_inst = dyn_cast<PHINode>(inst); - - if (!phi_inst) - { - if (log) - log->Printf("getOpcode() returns PHI, but instruction is not a PHINode"); - error.SetErrorToGenericError(); - error.SetErrorString(interpreter_internal_error); - return false; - } - if (!frame.m_prev_bb) - { - if (log) - log->Printf("Encountered PHI node without having jumped from another basic block"); - error.SetErrorToGenericError(); - error.SetErrorString(interpreter_internal_error); - return false; - } - - Value* value = phi_inst->getIncomingValueForBlock(frame.m_prev_bb); - lldb_private::Scalar result; - if (!frame.EvaluateValue(result, value, module)) - { - if (log) - log->Printf("Couldn't evaluate %s", PrintValue(value).c_str()); - error.SetErrorToGenericError(); - error.SetErrorString(bad_value_error); - return false; - } - frame.AssignValue(inst, result, module); - - if (log) - { - log->Printf("Interpreted a %s", inst->getOpcodeName()); - log->Printf(" Incoming value : %s", frame.SummarizeValue(value).c_str()); - } - } - break; - case Instruction::GetElementPtr: - { - const GetElementPtrInst *gep_inst = dyn_cast<GetElementPtrInst>(inst); - - if (!gep_inst) - { - if (log) - log->Printf("getOpcode() returns GetElementPtr, but instruction is not a GetElementPtrInst"); - error.SetErrorToGenericError(); - error.SetErrorString(interpreter_internal_error); - return false; - } - - const Value *pointer_operand = gep_inst->getPointerOperand(); - Type *src_elem_ty = gep_inst->getSourceElementType(); - - lldb_private::Scalar P; - - if (!frame.EvaluateValue(P, pointer_operand, module)) - { - if (log) - log->Printf("Couldn't evaluate %s", PrintValue(pointer_operand).c_str()); - error.SetErrorToGenericError(); - error.SetErrorString(bad_value_error); - return false; - } - - typedef SmallVector <Value *, 8> IndexVector; - typedef IndexVector::iterator IndexIterator; - - SmallVector <Value *, 8> indices (gep_inst->idx_begin(), - gep_inst->idx_end()); - - SmallVector <Value *, 8> const_indices; - - for (IndexIterator ii = indices.begin(), ie = indices.end(); - ii != ie; - ++ii) - { - ConstantInt *constant_index = dyn_cast<ConstantInt>(*ii); - - if (!constant_index) - { - lldb_private::Scalar I; - - if (!frame.EvaluateValue(I, *ii, module)) - { - if (log) - log->Printf("Couldn't evaluate %s", PrintValue(*ii).c_str()); - error.SetErrorToGenericError(); - error.SetErrorString(bad_value_error); - return false; - } - - if (log) - log->Printf("Evaluated constant index %s as %llu", PrintValue(*ii).c_str(), I.ULongLong(LLDB_INVALID_ADDRESS)); - - constant_index = cast<ConstantInt>(ConstantInt::get((*ii)->getType(), I.ULongLong(LLDB_INVALID_ADDRESS))); - } - - const_indices.push_back(constant_index); - } - - uint64_t offset = data_layout.getIndexedOffsetInType(src_elem_ty, const_indices); - - lldb_private::Scalar Poffset = P + offset; - - frame.AssignValue(inst, Poffset, module); - - if (log) - { - log->Printf("Interpreted a GetElementPtrInst"); - log->Printf(" P : %s", frame.SummarizeValue(pointer_operand).c_str()); - log->Printf(" Poffset : %s", frame.SummarizeValue(inst).c_str()); - } - } - break; - case Instruction::ICmp: - { - const ICmpInst *icmp_inst = dyn_cast<ICmpInst>(inst); - - if (!icmp_inst) - { - if (log) - log->Printf("getOpcode() returns ICmp, but instruction is not an ICmpInst"); - error.SetErrorToGenericError(); - error.SetErrorString(interpreter_internal_error); - return false; - } - - CmpInst::Predicate predicate = icmp_inst->getPredicate(); - - Value *lhs = inst->getOperand(0); - Value *rhs = inst->getOperand(1); - - lldb_private::Scalar L; - lldb_private::Scalar R; - - if (!frame.EvaluateValue(L, lhs, module)) - { - if (log) - log->Printf("Couldn't evaluate %s", PrintValue(lhs).c_str()); - error.SetErrorToGenericError(); - error.SetErrorString(bad_value_error); - return false; - } - - if (!frame.EvaluateValue(R, rhs, module)) - { - if (log) - log->Printf("Couldn't evaluate %s", PrintValue(rhs).c_str()); - error.SetErrorToGenericError(); - error.SetErrorString(bad_value_error); - return false; - } - - lldb_private::Scalar result; - - switch (predicate) - { - default: - return false; - case CmpInst::ICMP_EQ: - result = (L == R); - break; - case CmpInst::ICMP_NE: - result = (L != R); - break; - case CmpInst::ICMP_UGT: - L.MakeUnsigned(); - R.MakeUnsigned(); - result = (L > R); - break; - case CmpInst::ICMP_UGE: - L.MakeUnsigned(); - R.MakeUnsigned(); - result = (L >= R); - break; - case CmpInst::ICMP_ULT: - L.MakeUnsigned(); - R.MakeUnsigned(); - result = (L < R); - break; - case CmpInst::ICMP_ULE: - L.MakeUnsigned(); - R.MakeUnsigned(); - result = (L <= R); - break; - case CmpInst::ICMP_SGT: - L.MakeSigned(); - R.MakeSigned(); - result = (L > R); - break; - case CmpInst::ICMP_SGE: - L.MakeSigned(); - R.MakeSigned(); - result = (L >= R); - break; - case CmpInst::ICMP_SLT: - L.MakeSigned(); - R.MakeSigned(); - result = (L < R); - break; - case CmpInst::ICMP_SLE: - L.MakeSigned(); - R.MakeSigned(); - result = (L <= R); - break; - } - - frame.AssignValue(inst, result, module); - - if (log) - { - log->Printf("Interpreted an ICmpInst"); - log->Printf(" L : %s", frame.SummarizeValue(lhs).c_str()); - log->Printf(" R : %s", frame.SummarizeValue(rhs).c_str()); - log->Printf(" = : %s", frame.SummarizeValue(inst).c_str()); - } - } - break; - case Instruction::IntToPtr: - { - const IntToPtrInst *int_to_ptr_inst = dyn_cast<IntToPtrInst>(inst); - - if (!int_to_ptr_inst) - { - if (log) - log->Printf("getOpcode() returns IntToPtr, but instruction is not an IntToPtrInst"); - error.SetErrorToGenericError(); - error.SetErrorString(interpreter_internal_error); - return false; - } - - Value *src_operand = int_to_ptr_inst->getOperand(0); - - lldb_private::Scalar I; - - if (!frame.EvaluateValue(I, src_operand, module)) - { - if (log) - log->Printf("Couldn't evaluate %s", PrintValue(src_operand).c_str()); - error.SetErrorToGenericError(); - error.SetErrorString(bad_value_error); - return false; - } - - frame.AssignValue(inst, I, module); - - if (log) - { - log->Printf("Interpreted an IntToPtr"); - log->Printf(" Src : %s", frame.SummarizeValue(src_operand).c_str()); - log->Printf(" = : %s", frame.SummarizeValue(inst).c_str()); - } - } - break; - case Instruction::PtrToInt: - { - const PtrToIntInst *ptr_to_int_inst = dyn_cast<PtrToIntInst>(inst); - - if (!ptr_to_int_inst) - { - if (log) - log->Printf("getOpcode() returns PtrToInt, but instruction is not an PtrToIntInst"); - error.SetErrorToGenericError(); - error.SetErrorString(interpreter_internal_error); - return false; - } - - Value *src_operand = ptr_to_int_inst->getOperand(0); - - lldb_private::Scalar I; - - if (!frame.EvaluateValue(I, src_operand, module)) - { - if (log) - log->Printf("Couldn't evaluate %s", PrintValue(src_operand).c_str()); - error.SetErrorToGenericError(); - error.SetErrorString(bad_value_error); - return false; - } - - frame.AssignValue(inst, I, module); - - if (log) - { - log->Printf("Interpreted a PtrToInt"); - log->Printf(" Src : %s", frame.SummarizeValue(src_operand).c_str()); - log->Printf(" = : %s", frame.SummarizeValue(inst).c_str()); - } - } - break; - case Instruction::Trunc: - { - const TruncInst *trunc_inst = dyn_cast<TruncInst>(inst); - - if (!trunc_inst) - { - if (log) - log->Printf("getOpcode() returns Trunc, but instruction is not a TruncInst"); - error.SetErrorToGenericError(); - error.SetErrorString(interpreter_internal_error); - return false; - } - - Value *src_operand = trunc_inst->getOperand(0); - - lldb_private::Scalar I; - - if (!frame.EvaluateValue(I, src_operand, module)) - { - if (log) - log->Printf("Couldn't evaluate %s", PrintValue(src_operand).c_str()); - error.SetErrorToGenericError(); - error.SetErrorString(bad_value_error); - return false; - } - - frame.AssignValue(inst, I, module); - - if (log) - { - log->Printf("Interpreted a Trunc"); - log->Printf(" Src : %s", frame.SummarizeValue(src_operand).c_str()); - log->Printf(" = : %s", frame.SummarizeValue(inst).c_str()); - } - } - break; - case Instruction::Load: - { - const LoadInst *load_inst = dyn_cast<LoadInst>(inst); - - if (!load_inst) - { - if (log) - log->Printf("getOpcode() returns Load, but instruction is not a LoadInst"); - error.SetErrorToGenericError(); - error.SetErrorString(interpreter_internal_error); - return false; - } - - // The semantics of Load are: - // Create a region D that will contain the loaded data - // Resolve the region P containing a pointer - // Dereference P to get the region R that the data should be loaded from - // Transfer a unit of type type(D) from R to D - - const Value *pointer_operand = load_inst->getPointerOperand(); - - Type *pointer_ty = pointer_operand->getType(); - PointerType *pointer_ptr_ty = dyn_cast<PointerType>(pointer_ty); - if (!pointer_ptr_ty) - { - if (log) - log->Printf("getPointerOperand()->getType() is not a PointerType"); - error.SetErrorToGenericError(); - error.SetErrorString(interpreter_internal_error); - return false; - } - Type *target_ty = pointer_ptr_ty->getElementType(); - - lldb::addr_t D = frame.ResolveValue(load_inst, module); - lldb::addr_t P = frame.ResolveValue(pointer_operand, module); - - if (D == LLDB_INVALID_ADDRESS) - { - if (log) - log->Printf("LoadInst's value doesn't resolve to anything"); - error.SetErrorToGenericError(); - error.SetErrorString(bad_value_error); - return false; - } - - if (P == LLDB_INVALID_ADDRESS) - { - if (log) - log->Printf("LoadInst's pointer doesn't resolve to anything"); - error.SetErrorToGenericError(); - error.SetErrorString(bad_value_error); - return false; - } - - lldb::addr_t R; - lldb_private::Error read_error; - execution_unit.ReadPointerFromMemory(&R, P, read_error); - - if (!read_error.Success()) - { - if (log) - log->Printf("Couldn't read the address to be loaded for a LoadInst"); - error.SetErrorToGenericError(); - error.SetErrorString(memory_read_error); - return false; - } - - size_t target_size = data_layout.getTypeStoreSize(target_ty); - lldb_private::DataBufferHeap buffer(target_size, 0); - - read_error.Clear(); - execution_unit.ReadMemory(buffer.GetBytes(), R, buffer.GetByteSize(), read_error); - if (!read_error.Success()) - { - if (log) - log->Printf("Couldn't read from a region on behalf of a LoadInst"); - error.SetErrorToGenericError(); - error.SetErrorString(memory_read_error); - return false; - } - - lldb_private::Error write_error; - execution_unit.WriteMemory(D, buffer.GetBytes(), buffer.GetByteSize(), write_error); - if (!write_error.Success()) - { - if (log) - log->Printf("Couldn't write to a region on behalf of a LoadInst"); - error.SetErrorToGenericError(); - error.SetErrorString(memory_read_error); - return false; - } - - if (log) - { - log->Printf("Interpreted a LoadInst"); - log->Printf(" P : 0x%" PRIx64, P); - log->Printf(" R : 0x%" PRIx64, R); - log->Printf(" D : 0x%" PRIx64, D); - } - } - break; - case Instruction::Ret: - { - return true; - } - case Instruction::Store: - { - const StoreInst *store_inst = dyn_cast<StoreInst>(inst); - - if (!store_inst) - { - if (log) - log->Printf("getOpcode() returns Store, but instruction is not a StoreInst"); - error.SetErrorToGenericError(); - error.SetErrorString(interpreter_internal_error); - return false; - } - - // The semantics of Store are: - // Resolve the region D containing the data to be stored - // Resolve the region P containing a pointer - // Dereference P to get the region R that the data should be stored in - // Transfer a unit of type type(D) from D to R - - const Value *value_operand = store_inst->getValueOperand(); - const Value *pointer_operand = store_inst->getPointerOperand(); - - Type *pointer_ty = pointer_operand->getType(); - PointerType *pointer_ptr_ty = dyn_cast<PointerType>(pointer_ty); - if (!pointer_ptr_ty) - return false; - Type *target_ty = pointer_ptr_ty->getElementType(); - - lldb::addr_t D = frame.ResolveValue(value_operand, module); - lldb::addr_t P = frame.ResolveValue(pointer_operand, module); - - if (D == LLDB_INVALID_ADDRESS) - { - if (log) - log->Printf("StoreInst's value doesn't resolve to anything"); - error.SetErrorToGenericError(); - error.SetErrorString(bad_value_error); - return false; - } - - if (P == LLDB_INVALID_ADDRESS) - { - if (log) - log->Printf("StoreInst's pointer doesn't resolve to anything"); - error.SetErrorToGenericError(); - error.SetErrorString(bad_value_error); - return false; - } - - lldb::addr_t R; - lldb_private::Error read_error; - execution_unit.ReadPointerFromMemory(&R, P, read_error); - - if (!read_error.Success()) - { - if (log) - log->Printf("Couldn't read the address to be loaded for a LoadInst"); - error.SetErrorToGenericError(); - error.SetErrorString(memory_read_error); - return false; - } - - size_t target_size = data_layout.getTypeStoreSize(target_ty); - lldb_private::DataBufferHeap buffer(target_size, 0); - - read_error.Clear(); - execution_unit.ReadMemory(buffer.GetBytes(), D, buffer.GetByteSize(), read_error); - if (!read_error.Success()) - { - if (log) - log->Printf("Couldn't read from a region on behalf of a StoreInst"); - error.SetErrorToGenericError(); - error.SetErrorString(memory_read_error); - return false; - } - - lldb_private::Error write_error; - execution_unit.WriteMemory(R, buffer.GetBytes(), buffer.GetByteSize(), write_error); - if (!write_error.Success()) - { - if (log) - log->Printf("Couldn't write to a region on behalf of a StoreInst"); - error.SetErrorToGenericError(); - error.SetErrorString(memory_write_error); - return false; - } - - if (log) - { - log->Printf("Interpreted a StoreInst"); - log->Printf(" D : 0x%" PRIx64, D); - log->Printf(" P : 0x%" PRIx64, P); - log->Printf(" R : 0x%" PRIx64, R); - } - } - break; - case Instruction::Call: - { - const CallInst *call_inst = dyn_cast<CallInst>(inst); - - if (!call_inst) - { - if (log) - log->Printf("getOpcode() returns %s, but instruction is not a CallInst", inst->getOpcodeName()); - error.SetErrorToGenericError(); - error.SetErrorString(interpreter_internal_error); - return false; - } - - if (CanIgnoreCall(call_inst)) - break; - - // Get the return type - llvm::Type *returnType = call_inst->getType(); - if (returnType == nullptr) - { - error.SetErrorToGenericError(); - error.SetErrorString("unable to access return type"); - return false; - } - - // Work with void, integer and pointer return types - if (!returnType->isVoidTy() && - !returnType->isIntegerTy() && - !returnType->isPointerTy()) - { - error.SetErrorToGenericError(); - error.SetErrorString("return type is not supported"); - return false; - } - - // Check we can actually get a thread - if (exe_ctx.GetThreadPtr() == nullptr) - { - error.SetErrorToGenericError(); - error.SetErrorStringWithFormat("unable to acquire thread"); - return false; - } - - // Make sure we have a valid process - if (!exe_ctx.GetProcessPtr()) - { - error.SetErrorToGenericError(); - error.SetErrorStringWithFormat("unable to get the process"); - return false; - } - - // Find the address of the callee function - lldb_private::Scalar I; - const llvm::Value *val = call_inst->getCalledValue(); - - if (!frame.EvaluateValue(I, val, module)) - { - error.SetErrorToGenericError(); - error.SetErrorString("unable to get address of function"); - return false; - } - lldb_private::Address funcAddr(I.ULongLong(LLDB_INVALID_ADDRESS)); - - lldb_private::DiagnosticManager diagnostics; - lldb_private::EvaluateExpressionOptions options; - - // We generally receive a function pointer which we must dereference - llvm::Type* prototype = val->getType(); - if (!prototype->isPointerTy()) - { - error.SetErrorToGenericError(); - error.SetErrorString("call need function pointer"); - return false; - } - - // Dereference the function pointer - prototype = prototype->getPointerElementType(); - if (!(prototype->isFunctionTy() || prototype->isFunctionVarArg())) - { - error.SetErrorToGenericError(); - error.SetErrorString("call need function pointer"); - return false; - } - - // Find number of arguments - const int numArgs = call_inst->getNumArgOperands(); - - // We work with a fixed array of 16 arguments which is our upper limit - static lldb_private::ABI::CallArgument rawArgs[16]; - if (numArgs >= 16) - { - error.SetErrorToGenericError(); - error.SetErrorStringWithFormat("function takes too many arguments"); - return false; - } - - // Push all function arguments to the argument list that will - // be passed to the call function thread plan - for (int i = 0; i < numArgs; i++) - { - // Get details of this argument - llvm::Value *arg_op = call_inst->getArgOperand(i); - llvm::Type *arg_ty = arg_op->getType(); - - // Ensure that this argument is an supported type - if (!arg_ty->isIntegerTy() && !arg_ty->isPointerTy()) - { - error.SetErrorToGenericError(); - error.SetErrorStringWithFormat("argument %d must be integer type", i); - return false; - } - - // Extract the arguments value - lldb_private::Scalar tmp_op = 0; - if (!frame.EvaluateValue(tmp_op, arg_op, module)) - { - error.SetErrorToGenericError(); - error.SetErrorStringWithFormat("unable to evaluate argument %d", i); - return false; - } - - // Check if this is a string literal or constant string pointer - if (arg_ty->isPointerTy()) - { - // Pointer to just one type - assert(arg_ty->getNumContainedTypes() == 1); - - lldb::addr_t addr = tmp_op.ULongLong(); - size_t dataSize = 0; - - if (execution_unit.GetAllocSize(addr, dataSize)) - { - // Create the required buffer - rawArgs[i].size = dataSize; - rawArgs[i].data_ap.reset(new uint8_t[dataSize + 1]); - - // Read string from host memory - execution_unit.ReadMemory(rawArgs[i].data_ap.get(), addr, dataSize, error); - if (error.Fail()) - { - assert(!"we have failed to read the string from memory"); - return false; - } - // Add null terminator - rawArgs[i].data_ap[dataSize] = '\0'; - rawArgs[i].type = lldb_private::ABI::CallArgument::HostPointer; - } - else - { - assert(!"unable to locate host data for transfer to device"); - return false; - } - } - else /* if ( arg_ty->isPointerTy() ) */ - { - rawArgs[i].type = lldb_private::ABI::CallArgument::TargetValue; - // Get argument size in bytes - rawArgs[i].size = arg_ty->getIntegerBitWidth() / 8; - // Push value into argument list for thread plan - rawArgs[i].value = tmp_op.ULongLong(); - } - - } - - // Pack the arguments into an llvm::array - llvm::ArrayRef<lldb_private::ABI::CallArgument> args(rawArgs, numArgs); - - // Setup a thread plan to call the target function - lldb::ThreadPlanSP call_plan_sp(new lldb_private::ThreadPlanCallFunctionUsingABI( - exe_ctx.GetThreadRef(), funcAddr, *prototype, *returnType, args, options)); - - // Check if the plan is valid - lldb_private::StreamString ss; - if (!call_plan_sp || !call_plan_sp->ValidatePlan(&ss)) - { - error.SetErrorToGenericError(); - error.SetErrorStringWithFormat("unable to make ThreadPlanCallFunctionUsingABI for 0x%llx", - I.ULongLong()); - return false; - } - - exe_ctx.GetProcessPtr()->SetRunningUserExpression(true); - - // Execute the actual function call thread plan - lldb::ExpressionResults res = - exe_ctx.GetProcessRef().RunThreadPlan(exe_ctx, call_plan_sp, options, diagnostics); - - // Check that the thread plan completed successfully - if (res != lldb::ExpressionResults::eExpressionCompleted) - { - error.SetErrorToGenericError(); - error.SetErrorStringWithFormat("ThreadPlanCallFunctionUsingABI failed"); - return false; - } - - exe_ctx.GetProcessPtr()->SetRunningUserExpression(false); - - // Void return type - if (returnType->isVoidTy()) - { - // Cant assign to void types, so we leave the frame untouched - } - else - // Integer or pointer return type - if (returnType->isIntegerTy() || returnType->isPointerTy()) - { - // Get the encapsulated return value - lldb::ValueObjectSP retVal = call_plan_sp.get()->GetReturnValueObject(); - - lldb_private::Scalar returnVal = -1; - lldb_private::ValueObject *vobj = retVal.get(); - - // Check if the return value is valid - if (vobj == nullptr || retVal.empty()) - { - error.SetErrorToGenericError(); - error.SetErrorStringWithFormat("unable to get the return value"); - return false; - } - - // Extract the return value as a integer - lldb_private::Value & value = vobj->GetValue(); - returnVal = value.GetScalar(); - - // Push the return value as the result - frame.AssignValue(inst, returnVal, module); - } + if (P == LLDB_INVALID_ADDRESS) { + if (log) + log->Printf("StoreInst's pointer doesn't resolve to anything"); + error.SetErrorToGenericError(); + error.SetErrorString(bad_value_error); + return false; + } + + lldb::addr_t R; + lldb_private::Error read_error; + execution_unit.ReadPointerFromMemory(&R, P, read_error); + + if (!read_error.Success()) { + if (log) + log->Printf("Couldn't read the address to be loaded for a LoadInst"); + error.SetErrorToGenericError(); + error.SetErrorString(memory_read_error); + return false; + } + + size_t target_size = data_layout.getTypeStoreSize(target_ty); + lldb_private::DataBufferHeap buffer(target_size, 0); + + read_error.Clear(); + execution_unit.ReadMemory(buffer.GetBytes(), D, buffer.GetByteSize(), + read_error); + if (!read_error.Success()) { + if (log) + log->Printf("Couldn't read from a region on behalf of a StoreInst"); + error.SetErrorToGenericError(); + error.SetErrorString(memory_read_error); + return false; + } + + lldb_private::Error write_error; + execution_unit.WriteMemory(R, buffer.GetBytes(), buffer.GetByteSize(), + write_error); + if (!write_error.Success()) { + if (log) + log->Printf("Couldn't write to a region on behalf of a StoreInst"); + error.SetErrorToGenericError(); + error.SetErrorString(memory_write_error); + return false; + } + + if (log) { + log->Printf("Interpreted a StoreInst"); + log->Printf(" D : 0x%" PRIx64, D); + log->Printf(" P : 0x%" PRIx64, P); + log->Printf(" R : 0x%" PRIx64, R); + } + } break; + case Instruction::Call: { + const CallInst *call_inst = dyn_cast<CallInst>(inst); + + if (!call_inst) { + if (log) + log->Printf( + "getOpcode() returns %s, but instruction is not a CallInst", + inst->getOpcodeName()); + error.SetErrorToGenericError(); + error.SetErrorString(interpreter_internal_error); + return false; + } + + if (CanIgnoreCall(call_inst)) + break; + + // Get the return type + llvm::Type *returnType = call_inst->getType(); + if (returnType == nullptr) { + error.SetErrorToGenericError(); + error.SetErrorString("unable to access return type"); + return false; + } + + // Work with void, integer and pointer return types + if (!returnType->isVoidTy() && !returnType->isIntegerTy() && + !returnType->isPointerTy()) { + error.SetErrorToGenericError(); + error.SetErrorString("return type is not supported"); + return false; + } + + // Check we can actually get a thread + if (exe_ctx.GetThreadPtr() == nullptr) { + error.SetErrorToGenericError(); + error.SetErrorStringWithFormat("unable to acquire thread"); + return false; + } + + // Make sure we have a valid process + if (!exe_ctx.GetProcessPtr()) { + error.SetErrorToGenericError(); + error.SetErrorStringWithFormat("unable to get the process"); + return false; + } + + // Find the address of the callee function + lldb_private::Scalar I; + const llvm::Value *val = call_inst->getCalledValue(); + + if (!frame.EvaluateValue(I, val, module)) { + error.SetErrorToGenericError(); + error.SetErrorString("unable to get address of function"); + return false; + } + lldb_private::Address funcAddr(I.ULongLong(LLDB_INVALID_ADDRESS)); + + lldb_private::DiagnosticManager diagnostics; + lldb_private::EvaluateExpressionOptions options; + + // We generally receive a function pointer which we must dereference + llvm::Type *prototype = val->getType(); + if (!prototype->isPointerTy()) { + error.SetErrorToGenericError(); + error.SetErrorString("call need function pointer"); + return false; + } + + // Dereference the function pointer + prototype = prototype->getPointerElementType(); + if (!(prototype->isFunctionTy() || prototype->isFunctionVarArg())) { + error.SetErrorToGenericError(); + error.SetErrorString("call need function pointer"); + return false; + } + + // Find number of arguments + const int numArgs = call_inst->getNumArgOperands(); + + // We work with a fixed array of 16 arguments which is our upper limit + static lldb_private::ABI::CallArgument rawArgs[16]; + if (numArgs >= 16) { + error.SetErrorToGenericError(); + error.SetErrorStringWithFormat("function takes too many arguments"); + return false; + } + + // Push all function arguments to the argument list that will + // be passed to the call function thread plan + for (int i = 0; i < numArgs; i++) { + // Get details of this argument + llvm::Value *arg_op = call_inst->getArgOperand(i); + llvm::Type *arg_ty = arg_op->getType(); + + // Ensure that this argument is an supported type + if (!arg_ty->isIntegerTy() && !arg_ty->isPointerTy()) { + error.SetErrorToGenericError(); + error.SetErrorStringWithFormat("argument %d must be integer type", i); + return false; + } + + // Extract the arguments value + lldb_private::Scalar tmp_op = 0; + if (!frame.EvaluateValue(tmp_op, arg_op, module)) { + error.SetErrorToGenericError(); + error.SetErrorStringWithFormat("unable to evaluate argument %d", i); + return false; + } + + // Check if this is a string literal or constant string pointer + if (arg_ty->isPointerTy()) { + // Pointer to just one type + assert(arg_ty->getNumContainedTypes() == 1); + + lldb::addr_t addr = tmp_op.ULongLong(); + size_t dataSize = 0; + + if (execution_unit.GetAllocSize(addr, dataSize)) { + // Create the required buffer + rawArgs[i].size = dataSize; + rawArgs[i].data_ap.reset(new uint8_t[dataSize + 1]); + + // Read string from host memory + execution_unit.ReadMemory(rawArgs[i].data_ap.get(), addr, dataSize, + error); + if (error.Fail()) { + assert(!"we have failed to read the string from memory"); + return false; } - break; + // Add null terminator + rawArgs[i].data_ap[dataSize] = '\0'; + rawArgs[i].type = lldb_private::ABI::CallArgument::HostPointer; + } else { + assert(!"unable to locate host data for transfer to device"); + return false; + } + } else /* if ( arg_ty->isPointerTy() ) */ + { + rawArgs[i].type = lldb_private::ABI::CallArgument::TargetValue; + // Get argument size in bytes + rawArgs[i].size = arg_ty->getIntegerBitWidth() / 8; + // Push value into argument list for thread plan + rawArgs[i].value = tmp_op.ULongLong(); } + } - ++frame.m_ii; - } + // Pack the arguments into an llvm::array + llvm::ArrayRef<lldb_private::ABI::CallArgument> args(rawArgs, numArgs); + + // Setup a thread plan to call the target function + lldb::ThreadPlanSP call_plan_sp( + new lldb_private::ThreadPlanCallFunctionUsingABI( + exe_ctx.GetThreadRef(), funcAddr, *prototype, *returnType, args, + options)); + + // Check if the plan is valid + lldb_private::StreamString ss; + if (!call_plan_sp || !call_plan_sp->ValidatePlan(&ss)) { + error.SetErrorToGenericError(); + error.SetErrorStringWithFormat( + "unable to make ThreadPlanCallFunctionUsingABI for 0x%llx", + I.ULongLong()); + return false; + } + + exe_ctx.GetProcessPtr()->SetRunningUserExpression(true); - if (num_insts >= 4096) - { + // Execute the actual function call thread plan + lldb::ExpressionResults res = exe_ctx.GetProcessRef().RunThreadPlan( + exe_ctx, call_plan_sp, options, diagnostics); + + // Check that the thread plan completed successfully + if (res != lldb::ExpressionResults::eExpressionCompleted) { error.SetErrorToGenericError(); - error.SetErrorString(infinite_loop_error); + error.SetErrorStringWithFormat("ThreadPlanCallFunctionUsingABI failed"); return false; + } + + exe_ctx.GetProcessPtr()->SetRunningUserExpression(false); + + // Void return type + if (returnType->isVoidTy()) { + // Cant assign to void types, so we leave the frame untouched + } else + // Integer or pointer return type + if (returnType->isIntegerTy() || returnType->isPointerTy()) { + // Get the encapsulated return value + lldb::ValueObjectSP retVal = call_plan_sp.get()->GetReturnValueObject(); + + lldb_private::Scalar returnVal = -1; + lldb_private::ValueObject *vobj = retVal.get(); + + // Check if the return value is valid + if (vobj == nullptr || retVal.empty()) { + error.SetErrorToGenericError(); + error.SetErrorStringWithFormat("unable to get the return value"); + return false; + } + + // Extract the return value as a integer + lldb_private::Value &value = vobj->GetValue(); + returnVal = value.GetScalar(); + + // Push the return value as the result + frame.AssignValue(inst, returnVal, module); + } + } break; } + ++frame.m_ii; + } + + if (num_insts >= 4096) { + error.SetErrorToGenericError(); + error.SetErrorString(infinite_loop_error); return false; + } + + return false; } diff --git a/source/Expression/IRMemoryMap.cpp b/source/Expression/IRMemoryMap.cpp index aa165722c437..008838d5aab3 100644 --- a/source/Expression/IRMemoryMap.cpp +++ b/source/Expression/IRMemoryMap.cpp @@ -7,12 +7,12 @@ // //===----------------------------------------------------------------------===// +#include "lldb/Expression/IRMemoryMap.h" #include "lldb/Core/DataBufferHeap.h" #include "lldb/Core/DataExtractor.h" #include "lldb/Core/Error.h" #include "lldb/Core/Log.h" #include "lldb/Core/Scalar.h" -#include "lldb/Expression/IRMemoryMap.h" #include "lldb/Target/MemoryRegionInfo.h" #include "lldb/Target/Process.h" #include "lldb/Target/Target.h" @@ -20,223 +20,204 @@ using namespace lldb_private; -IRMemoryMap::IRMemoryMap (lldb::TargetSP target_sp) : - m_target_wp(target_sp) -{ - if (target_sp) - m_process_wp = target_sp->GetProcessSP(); +IRMemoryMap::IRMemoryMap(lldb::TargetSP target_sp) : m_target_wp(target_sp) { + if (target_sp) + m_process_wp = target_sp->GetProcessSP(); } -IRMemoryMap::~IRMemoryMap () -{ - lldb::ProcessSP process_sp = m_process_wp.lock(); +IRMemoryMap::~IRMemoryMap() { + lldb::ProcessSP process_sp = m_process_wp.lock(); - if (process_sp) - { - AllocationMap::iterator iter; - - Error err; - - while ((iter = m_allocations.begin()) != m_allocations.end()) - { - err.Clear(); - if (iter->second.m_leak) - m_allocations.erase(iter); - else - Free(iter->first, err); - } - } -} + if (process_sp) { + AllocationMap::iterator iter; -lldb::addr_t -IRMemoryMap::FindSpace (size_t size) -{ - // The FindSpace algorithm's job is to find a region of memory that the - // underlying process is unlikely to be using. - // - // The memory returned by this function will never be written to. The only - // point is that it should not shadow process memory if possible, so that - // expressions processing real values from the process do not use the - // wrong data. - // - // If the process can in fact allocate memory (CanJIT() lets us know this) - // then this can be accomplished just be allocating memory in the inferior. - // Then no guessing is required. + Error err; - lldb::TargetSP target_sp = m_target_wp.lock(); - lldb::ProcessSP process_sp = m_process_wp.lock(); - - const bool process_is_alive = process_sp && process_sp->IsAlive(); + while ((iter = m_allocations.begin()) != m_allocations.end()) { + err.Clear(); + if (iter->second.m_leak) + m_allocations.erase(iter); + else + Free(iter->first, err); + } + } +} - lldb::addr_t ret = LLDB_INVALID_ADDRESS; - if (size == 0) - return ret; +lldb::addr_t IRMemoryMap::FindSpace(size_t size) { + // The FindSpace algorithm's job is to find a region of memory that the + // underlying process is unlikely to be using. + // + // The memory returned by this function will never be written to. The only + // point is that it should not shadow process memory if possible, so that + // expressions processing real values from the process do not use the + // wrong data. + // + // If the process can in fact allocate memory (CanJIT() lets us know this) + // then this can be accomplished just be allocating memory in the inferior. + // Then no guessing is required. + + lldb::TargetSP target_sp = m_target_wp.lock(); + lldb::ProcessSP process_sp = m_process_wp.lock(); + + const bool process_is_alive = process_sp && process_sp->IsAlive(); + + lldb::addr_t ret = LLDB_INVALID_ADDRESS; + if (size == 0) + return ret; - if (process_is_alive && process_sp->CanJIT()) - { - Error alloc_error; + if (process_is_alive && process_sp->CanJIT()) { + Error alloc_error; - ret = process_sp->AllocateMemory(size, lldb::ePermissionsReadable | lldb::ePermissionsWritable, alloc_error); + ret = process_sp->AllocateMemory(size, lldb::ePermissionsReadable | + lldb::ePermissionsWritable, + alloc_error); - if (!alloc_error.Success()) - return LLDB_INVALID_ADDRESS; - else - return ret; - } - - // At this point we know that we need to hunt. - // - // First, go to the end of the existing allocations we've made if there are - // any allocations. Otherwise start at the beginning of memory. - - if (m_allocations.empty()) - { - ret = 0x0; - } + if (!alloc_error.Success()) + return LLDB_INVALID_ADDRESS; else - { - auto back = m_allocations.rbegin(); - lldb::addr_t addr = back->first; - size_t alloc_size = back->second.m_size; - ret = llvm::alignTo(addr+alloc_size, 4096); - } - - // Now, if it's possible to use the GetMemoryRegionInfo API to detect mapped - // regions, walk forward through memory until a region is found that - // has adequate space for our allocation. - if (process_is_alive) - { - const uint64_t end_of_memory = process_sp->GetAddressByteSize() == 8 ? - 0xffffffffffffffffull : 0xffffffffull; - - lldbassert(process_sp->GetAddressByteSize() == 4 || end_of_memory != 0xffffffffull); - - MemoryRegionInfo region_info; - Error err = process_sp->GetMemoryRegionInfo(ret, region_info); - if (err.Success()) - { - while (true) - { - if (region_info.GetReadable() != MemoryRegionInfo::OptionalBool::eNo || - region_info.GetWritable() != MemoryRegionInfo::OptionalBool::eNo || - region_info.GetExecutable() != MemoryRegionInfo::OptionalBool::eNo) - { - if (region_info.GetRange().GetRangeEnd() - 1 >= end_of_memory) - { - ret = LLDB_INVALID_ADDRESS; - break; - } - else - { - ret = region_info.GetRange().GetRangeEnd(); - } - } - else if (ret + size < region_info.GetRange().GetRangeEnd()) - { - return ret; - } - else - { - // ret stays the same. We just need to walk a bit further. - } - - err = process_sp->GetMemoryRegionInfo(region_info.GetRange().GetRangeEnd(), region_info); - if (err.Fail()) - { - lldbassert(!"GetMemoryRegionInfo() succeeded, then failed"); - ret = LLDB_INVALID_ADDRESS; - break; - } - } + return ret; + } + + // At this point we know that we need to hunt. + // + // First, go to the end of the existing allocations we've made if there are + // any allocations. Otherwise start at the beginning of memory. + + if (m_allocations.empty()) { + ret = 0x0; + } else { + auto back = m_allocations.rbegin(); + lldb::addr_t addr = back->first; + size_t alloc_size = back->second.m_size; + ret = llvm::alignTo(addr + alloc_size, 4096); + } + + // Now, if it's possible to use the GetMemoryRegionInfo API to detect mapped + // regions, walk forward through memory until a region is found that + // has adequate space for our allocation. + if (process_is_alive) { + const uint64_t end_of_memory = process_sp->GetAddressByteSize() == 8 + ? 0xffffffffffffffffull + : 0xffffffffull; + + lldbassert(process_sp->GetAddressByteSize() == 4 || + end_of_memory != 0xffffffffull); + + MemoryRegionInfo region_info; + Error err = process_sp->GetMemoryRegionInfo(ret, region_info); + if (err.Success()) { + while (true) { + if (region_info.GetReadable() != MemoryRegionInfo::OptionalBool::eNo || + region_info.GetWritable() != MemoryRegionInfo::OptionalBool::eNo || + region_info.GetExecutable() != + MemoryRegionInfo::OptionalBool::eNo) { + if (region_info.GetRange().GetRangeEnd() - 1 >= end_of_memory) { + ret = LLDB_INVALID_ADDRESS; + break; + } else { + ret = region_info.GetRange().GetRangeEnd(); + } + } else if (ret + size < region_info.GetRange().GetRangeEnd()) { + return ret; + } else { + // ret stays the same. We just need to walk a bit further. } - } - - // We've tried our algorithm, and it didn't work. Now we have to reset back - // to the end of the allocations we've already reported, or use a 'sensible' - // default if this is our first allocation. - - if (m_allocations.empty()) - { - uint32_t address_byte_size = GetAddressByteSize(); - if (address_byte_size != UINT32_MAX) - { - switch (address_byte_size) - { - case 8: - ret = 0xffffffff00000000ull; - break; - case 4: - ret = 0xee000000ull; - break; - default: - break; - } + + err = process_sp->GetMemoryRegionInfo( + region_info.GetRange().GetRangeEnd(), region_info); + if (err.Fail()) { + lldbassert(!"GetMemoryRegionInfo() succeeded, then failed"); + ret = LLDB_INVALID_ADDRESS; + break; } + } } - else - { - auto back = m_allocations.rbegin(); - lldb::addr_t addr = back->first; - size_t alloc_size = back->second.m_size; - ret = llvm::alignTo(addr+alloc_size, 4096); + } + + // We've tried our algorithm, and it didn't work. Now we have to reset back + // to the end of the allocations we've already reported, or use a 'sensible' + // default if this is our first allocation. + + if (m_allocations.empty()) { + uint32_t address_byte_size = GetAddressByteSize(); + if (address_byte_size != UINT32_MAX) { + switch (address_byte_size) { + case 8: + ret = 0xffffffff00000000ull; + break; + case 4: + ret = 0xee000000ull; + break; + default: + break; + } } + } else { + auto back = m_allocations.rbegin(); + lldb::addr_t addr = back->first; + size_t alloc_size = back->second.m_size; + ret = llvm::alignTo(addr + alloc_size, 4096); + } - return ret; + return ret; } IRMemoryMap::AllocationMap::iterator -IRMemoryMap::FindAllocation (lldb::addr_t addr, size_t size) -{ - if (addr == LLDB_INVALID_ADDRESS) - return m_allocations.end(); - - AllocationMap::iterator iter = m_allocations.lower_bound (addr); - - if (iter == m_allocations.end() || - iter->first > addr) - { - if (iter == m_allocations.begin()) - return m_allocations.end(); - iter--; - } +IRMemoryMap::FindAllocation(lldb::addr_t addr, size_t size) { + if (addr == LLDB_INVALID_ADDRESS) + return m_allocations.end(); - if (iter->first <= addr && iter->first + iter->second.m_size >= addr + size) - return iter; + AllocationMap::iterator iter = m_allocations.lower_bound(addr); - return m_allocations.end(); -} + if (iter == m_allocations.end() || iter->first > addr) { + if (iter == m_allocations.begin()) + return m_allocations.end(); + iter--; + } -bool -IRMemoryMap::IntersectsAllocation (lldb::addr_t addr, size_t size) const -{ - if (addr == LLDB_INVALID_ADDRESS) - return false; - - AllocationMap::const_iterator iter = m_allocations.lower_bound (addr); - - // Since we only know that the returned interval begins at a location greater than or - // equal to where the given interval begins, it's possible that the given interval - // intersects either the returned interval or the previous interval. Thus, we need to - // check both. Note that we only need to check these two intervals. Since all intervals - // are disjoint it is not possible that an adjacent interval does not intersect, but a - // non-adjacent interval does intersect. - if (iter != m_allocations.end()) { - if (AllocationsIntersect(addr, size, iter->second.m_process_start, iter->second.m_size)) - return true; - } + if (iter->first <= addr && iter->first + iter->second.m_size >= addr + size) + return iter; - if (iter != m_allocations.begin()) { - --iter; - if (AllocationsIntersect(addr, size, iter->second.m_process_start, iter->second.m_size)) - return true; - } + return m_allocations.end(); +} +bool IRMemoryMap::IntersectsAllocation(lldb::addr_t addr, size_t size) const { + if (addr == LLDB_INVALID_ADDRESS) return false; + + AllocationMap::const_iterator iter = m_allocations.lower_bound(addr); + + // Since we only know that the returned interval begins at a location greater + // than or + // equal to where the given interval begins, it's possible that the given + // interval + // intersects either the returned interval or the previous interval. Thus, we + // need to + // check both. Note that we only need to check these two intervals. Since all + // intervals + // are disjoint it is not possible that an adjacent interval does not + // intersect, but a + // non-adjacent interval does intersect. + if (iter != m_allocations.end()) { + if (AllocationsIntersect(addr, size, iter->second.m_process_start, + iter->second.m_size)) + return true; + } + + if (iter != m_allocations.begin()) { + --iter; + if (AllocationsIntersect(addr, size, iter->second.m_process_start, + iter->second.m_size)) + return true; + } + + return false; } -bool -IRMemoryMap::AllocationsIntersect(lldb::addr_t addr1, size_t size1, lldb::addr_t addr2, size_t size2) { - // Given two half open intervals [A, B) and [X, Y), the only 6 permutations that satisfy +bool IRMemoryMap::AllocationsIntersect(lldb::addr_t addr1, size_t size1, + lldb::addr_t addr2, size_t size2) { + // Given two half open intervals [A, B) and [X, Y), the only 6 permutations + // that satisfy // A<B and X<Y are the following: // A B X Y // A X B Y (intersects) @@ -249,666 +230,615 @@ IRMemoryMap::AllocationsIntersect(lldb::addr_t addr1, size_t size1, lldb::addr_t return (addr2 < (addr1 + size1)) && (addr1 < (addr2 + size2)); } -lldb::ByteOrder -IRMemoryMap::GetByteOrder() -{ - lldb::ProcessSP process_sp = m_process_wp.lock(); +lldb::ByteOrder IRMemoryMap::GetByteOrder() { + lldb::ProcessSP process_sp = m_process_wp.lock(); - if (process_sp) - return process_sp->GetByteOrder(); + if (process_sp) + return process_sp->GetByteOrder(); - lldb::TargetSP target_sp = m_target_wp.lock(); + lldb::TargetSP target_sp = m_target_wp.lock(); - if (target_sp) - return target_sp->GetArchitecture().GetByteOrder(); + if (target_sp) + return target_sp->GetArchitecture().GetByteOrder(); - return lldb::eByteOrderInvalid; + return lldb::eByteOrderInvalid; } -uint32_t -IRMemoryMap::GetAddressByteSize() -{ - lldb::ProcessSP process_sp = m_process_wp.lock(); +uint32_t IRMemoryMap::GetAddressByteSize() { + lldb::ProcessSP process_sp = m_process_wp.lock(); - if (process_sp) - return process_sp->GetAddressByteSize(); + if (process_sp) + return process_sp->GetAddressByteSize(); - lldb::TargetSP target_sp = m_target_wp.lock(); + lldb::TargetSP target_sp = m_target_wp.lock(); - if (target_sp) - return target_sp->GetArchitecture().GetAddressByteSize(); + if (target_sp) + return target_sp->GetArchitecture().GetAddressByteSize(); - return UINT32_MAX; + return UINT32_MAX; } -ExecutionContextScope * -IRMemoryMap::GetBestExecutionContextScope() const -{ - lldb::ProcessSP process_sp = m_process_wp.lock(); +ExecutionContextScope *IRMemoryMap::GetBestExecutionContextScope() const { + lldb::ProcessSP process_sp = m_process_wp.lock(); - if (process_sp) - return process_sp.get(); + if (process_sp) + return process_sp.get(); - lldb::TargetSP target_sp = m_target_wp.lock(); + lldb::TargetSP target_sp = m_target_wp.lock(); - if (target_sp) - return target_sp.get(); + if (target_sp) + return target_sp.get(); - return NULL; + return NULL; } -IRMemoryMap::Allocation::Allocation (lldb::addr_t process_alloc, - lldb::addr_t process_start, - size_t size, - uint32_t permissions, - uint8_t alignment, - AllocationPolicy policy) : - m_process_alloc (process_alloc), - m_process_start (process_start), - m_size (size), - m_permissions (permissions), - m_alignment (alignment), - m_policy (policy), - m_leak (false) -{ - switch (policy) - { - default: - assert (0 && "We cannot reach this!"); - case eAllocationPolicyHostOnly: - m_data.SetByteSize(size); - memset(m_data.GetBytes(), 0, size); - break; - case eAllocationPolicyProcessOnly: - break; - case eAllocationPolicyMirror: - m_data.SetByteSize(size); - memset(m_data.GetBytes(), 0, size); - break; - } +IRMemoryMap::Allocation::Allocation(lldb::addr_t process_alloc, + lldb::addr_t process_start, size_t size, + uint32_t permissions, uint8_t alignment, + AllocationPolicy policy) + : m_process_alloc(process_alloc), m_process_start(process_start), + m_size(size), m_permissions(permissions), m_alignment(alignment), + m_policy(policy), m_leak(false) { + switch (policy) { + default: + assert(0 && "We cannot reach this!"); + case eAllocationPolicyHostOnly: + m_data.SetByteSize(size); + memset(m_data.GetBytes(), 0, size); + break; + case eAllocationPolicyProcessOnly: + break; + case eAllocationPolicyMirror: + m_data.SetByteSize(size); + memset(m_data.GetBytes(), 0, size); + break; + } } -lldb::addr_t -IRMemoryMap::Malloc (size_t size, uint8_t alignment, uint32_t permissions, AllocationPolicy policy, bool zero_memory, Error &error) -{ - lldb_private::Log *log (lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); - error.Clear(); - - lldb::ProcessSP process_sp; - lldb::addr_t allocation_address = LLDB_INVALID_ADDRESS; - lldb::addr_t aligned_address = LLDB_INVALID_ADDRESS; - - size_t alignment_mask = alignment - 1; - size_t allocation_size; - - if (size == 0) - allocation_size = alignment; - else - allocation_size = (size & alignment_mask) ? ((size + alignment) & (~alignment_mask)) : size; - - switch (policy) - { - default: +lldb::addr_t IRMemoryMap::Malloc(size_t size, uint8_t alignment, + uint32_t permissions, AllocationPolicy policy, + bool zero_memory, Error &error) { + lldb_private::Log *log( + lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS)); + error.Clear(); + + lldb::ProcessSP process_sp; + lldb::addr_t allocation_address = LLDB_INVALID_ADDRESS; + lldb::addr_t aligned_address = LLDB_INVALID_ADDRESS; + + size_t alignment_mask = alignment - 1; + size_t allocation_size; + + if (size == 0) + allocation_size = alignment; + else + allocation_size = (size & alignment_mask) + ? ((size + alignment) & (~alignment_mask)) + : size; + + switch (policy) { + default: + error.SetErrorToGenericError(); + error.SetErrorString("Couldn't malloc: invalid allocation policy"); + return LLDB_INVALID_ADDRESS; + case eAllocationPolicyHostOnly: + allocation_address = FindSpace(allocation_size); + if (allocation_address == LLDB_INVALID_ADDRESS) { + error.SetErrorToGenericError(); + error.SetErrorString("Couldn't malloc: address space is full"); + return LLDB_INVALID_ADDRESS; + } + break; + case eAllocationPolicyMirror: + process_sp = m_process_wp.lock(); + if (log) + log->Printf("IRMemoryMap::%s process_sp=0x%" PRIx64 + ", process_sp->CanJIT()=%s, process_sp->IsAlive()=%s", + __FUNCTION__, (lldb::addr_t)process_sp.get(), + process_sp && process_sp->CanJIT() ? "true" : "false", + process_sp && process_sp->IsAlive() ? "true" : "false"); + if (process_sp && process_sp->CanJIT() && process_sp->IsAlive()) { + if (!zero_memory) + allocation_address = + process_sp->AllocateMemory(allocation_size, permissions, error); + else + allocation_address = + process_sp->CallocateMemory(allocation_size, permissions, error); + + if (!error.Success()) + return LLDB_INVALID_ADDRESS; + } else { + if (log) + log->Printf("IRMemoryMap::%s switching to eAllocationPolicyHostOnly " + "due to failed condition (see previous expr log message)", + __FUNCTION__); + policy = eAllocationPolicyHostOnly; + allocation_address = FindSpace(allocation_size); + if (allocation_address == LLDB_INVALID_ADDRESS) { error.SetErrorToGenericError(); - error.SetErrorString("Couldn't malloc: invalid allocation policy"); + error.SetErrorString("Couldn't malloc: address space is full"); return LLDB_INVALID_ADDRESS; - case eAllocationPolicyHostOnly: - allocation_address = FindSpace(allocation_size); - if (allocation_address == LLDB_INVALID_ADDRESS) - { - error.SetErrorToGenericError(); - error.SetErrorString("Couldn't malloc: address space is full"); - return LLDB_INVALID_ADDRESS; - } - break; - case eAllocationPolicyMirror: - process_sp = m_process_wp.lock(); - if (log) - log->Printf ("IRMemoryMap::%s process_sp=0x%" PRIx64 ", process_sp->CanJIT()=%s, process_sp->IsAlive()=%s", __FUNCTION__, (lldb::addr_t) process_sp.get (), process_sp && process_sp->CanJIT () ? "true" : "false", process_sp && process_sp->IsAlive () ? "true" : "false"); - if (process_sp && process_sp->CanJIT() && process_sp->IsAlive()) - { - if (!zero_memory) - allocation_address = process_sp->AllocateMemory(allocation_size, permissions, error); - else - allocation_address = process_sp->CallocateMemory(allocation_size, permissions, error); - - if (!error.Success()) - return LLDB_INVALID_ADDRESS; - } - else - { - if (log) - log->Printf ("IRMemoryMap::%s switching to eAllocationPolicyHostOnly due to failed condition (see previous expr log message)", __FUNCTION__); - policy = eAllocationPolicyHostOnly; - allocation_address = FindSpace(allocation_size); - if (allocation_address == LLDB_INVALID_ADDRESS) - { - error.SetErrorToGenericError(); - error.SetErrorString("Couldn't malloc: address space is full"); - return LLDB_INVALID_ADDRESS; - } - } - break; - case eAllocationPolicyProcessOnly: - process_sp = m_process_wp.lock(); - if (process_sp) - { - if (process_sp->CanJIT() && process_sp->IsAlive()) - { - if (!zero_memory) - allocation_address = process_sp->AllocateMemory(allocation_size, permissions, error); - else - allocation_address = process_sp->CallocateMemory(allocation_size, permissions, error); - - if (!error.Success()) - return LLDB_INVALID_ADDRESS; - } - else - { - error.SetErrorToGenericError(); - error.SetErrorString("Couldn't malloc: process doesn't support allocating memory"); - return LLDB_INVALID_ADDRESS; - } - } + } + } + break; + case eAllocationPolicyProcessOnly: + process_sp = m_process_wp.lock(); + if (process_sp) { + if (process_sp->CanJIT() && process_sp->IsAlive()) { + if (!zero_memory) + allocation_address = + process_sp->AllocateMemory(allocation_size, permissions, error); else - { - error.SetErrorToGenericError(); - error.SetErrorString("Couldn't malloc: process doesn't exist, and this memory must be in the process"); - return LLDB_INVALID_ADDRESS; - } - break; - } + allocation_address = + process_sp->CallocateMemory(allocation_size, permissions, error); + if (!error.Success()) + return LLDB_INVALID_ADDRESS; + } else { + error.SetErrorToGenericError(); + error.SetErrorString( + "Couldn't malloc: process doesn't support allocating memory"); + return LLDB_INVALID_ADDRESS; + } + } else { + error.SetErrorToGenericError(); + error.SetErrorString("Couldn't malloc: process doesn't exist, and this " + "memory must be in the process"); + return LLDB_INVALID_ADDRESS; + } + break; + } - lldb::addr_t mask = alignment - 1; - aligned_address = (allocation_address + mask) & (~mask); + lldb::addr_t mask = alignment - 1; + aligned_address = (allocation_address + mask) & (~mask); - m_allocations[aligned_address] = Allocation(allocation_address, - aligned_address, - allocation_size, - permissions, - alignment, - policy); + m_allocations[aligned_address] = + Allocation(allocation_address, aligned_address, allocation_size, + permissions, alignment, policy); - if (zero_memory) - { - Error write_error; - std::vector<uint8_t> zero_buf(size, 0); - WriteMemory(aligned_address, zero_buf.data(), size, write_error); - } + if (zero_memory) { + Error write_error; + std::vector<uint8_t> zero_buf(size, 0); + WriteMemory(aligned_address, zero_buf.data(), size, write_error); + } - if (log) - { - const char * policy_string; + if (log) { + const char *policy_string; - switch (policy) - { - default: - policy_string = "<invalid policy>"; - break; - case eAllocationPolicyHostOnly: - policy_string = "eAllocationPolicyHostOnly"; - break; - case eAllocationPolicyProcessOnly: - policy_string = "eAllocationPolicyProcessOnly"; - break; - case eAllocationPolicyMirror: - policy_string = "eAllocationPolicyMirror"; - break; - } - - log->Printf("IRMemoryMap::Malloc (%" PRIu64 ", 0x%" PRIx64 ", 0x%" PRIx64 ", %s) -> 0x%" PRIx64, - (uint64_t)allocation_size, - (uint64_t)alignment, - (uint64_t)permissions, - policy_string, - aligned_address); + switch (policy) { + default: + policy_string = "<invalid policy>"; + break; + case eAllocationPolicyHostOnly: + policy_string = "eAllocationPolicyHostOnly"; + break; + case eAllocationPolicyProcessOnly: + policy_string = "eAllocationPolicyProcessOnly"; + break; + case eAllocationPolicyMirror: + policy_string = "eAllocationPolicyMirror"; + break; } - return aligned_address; + log->Printf("IRMemoryMap::Malloc (%" PRIu64 ", 0x%" PRIx64 ", 0x%" PRIx64 + ", %s) -> 0x%" PRIx64, + (uint64_t)allocation_size, (uint64_t)alignment, + (uint64_t)permissions, policy_string, aligned_address); + } + + return aligned_address; } -void -IRMemoryMap::Leak (lldb::addr_t process_address, Error &error) -{ - error.Clear(); +void IRMemoryMap::Leak(lldb::addr_t process_address, Error &error) { + error.Clear(); - AllocationMap::iterator iter = m_allocations.find(process_address); + AllocationMap::iterator iter = m_allocations.find(process_address); - if (iter == m_allocations.end()) - { - error.SetErrorToGenericError(); - error.SetErrorString("Couldn't leak: allocation doesn't exist"); - return; - } + if (iter == m_allocations.end()) { + error.SetErrorToGenericError(); + error.SetErrorString("Couldn't leak: allocation doesn't exist"); + return; + } - Allocation &allocation = iter->second; + Allocation &allocation = iter->second; - allocation.m_leak = true; + allocation.m_leak = true; } -void -IRMemoryMap::Free (lldb::addr_t process_address, Error &error) -{ - error.Clear(); +void IRMemoryMap::Free(lldb::addr_t process_address, Error &error) { + error.Clear(); - AllocationMap::iterator iter = m_allocations.find(process_address); + AllocationMap::iterator iter = m_allocations.find(process_address); - if (iter == m_allocations.end()) - { - error.SetErrorToGenericError(); - error.SetErrorString("Couldn't free: allocation doesn't exist"); - return; - } - - Allocation &allocation = iter->second; + if (iter == m_allocations.end()) { + error.SetErrorToGenericError(); + error.SetErrorString("Couldn't free: allocation doesn't exist"); + return; + } - switch (allocation.m_policy) - { - default: - case eAllocationPolicyHostOnly: - { - lldb::ProcessSP process_sp = m_process_wp.lock(); - if (process_sp) - { - if (process_sp->CanJIT() && process_sp->IsAlive()) - process_sp->DeallocateMemory(allocation.m_process_alloc); // FindSpace allocated this for real - } + Allocation &allocation = iter->second; - break; - } - case eAllocationPolicyMirror: - case eAllocationPolicyProcessOnly: - { - lldb::ProcessSP process_sp = m_process_wp.lock(); - if (process_sp) - process_sp->DeallocateMemory(allocation.m_process_alloc); - } - } - - if (lldb_private::Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)) - { - log->Printf("IRMemoryMap::Free (0x%" PRIx64 ") freed [0x%" PRIx64 "..0x%" PRIx64 ")", - (uint64_t)process_address, - iter->second.m_process_start, - iter->second.m_process_start + iter->second.m_size); + switch (allocation.m_policy) { + default: + case eAllocationPolicyHostOnly: { + lldb::ProcessSP process_sp = m_process_wp.lock(); + if (process_sp) { + if (process_sp->CanJIT() && process_sp->IsAlive()) + process_sp->DeallocateMemory( + allocation.m_process_alloc); // FindSpace allocated this for real } - m_allocations.erase(iter); + break; + } + case eAllocationPolicyMirror: + case eAllocationPolicyProcessOnly: { + lldb::ProcessSP process_sp = m_process_wp.lock(); + if (process_sp) + process_sp->DeallocateMemory(allocation.m_process_alloc); + } + } + + if (lldb_private::Log *log = + lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS)) { + log->Printf("IRMemoryMap::Free (0x%" PRIx64 ") freed [0x%" PRIx64 + "..0x%" PRIx64 ")", + (uint64_t)process_address, iter->second.m_process_start, + iter->second.m_process_start + iter->second.m_size); + } + + m_allocations.erase(iter); } -bool -IRMemoryMap::GetAllocSize(lldb::addr_t address, size_t &size) -{ - AllocationMap::iterator iter = FindAllocation(address, size); - if (iter == m_allocations.end()) - return false; - - Allocation &al = iter->second; +bool IRMemoryMap::GetAllocSize(lldb::addr_t address, size_t &size) { + AllocationMap::iterator iter = FindAllocation(address, size); + if (iter == m_allocations.end()) + return false; - if (address > (al.m_process_start + al.m_size)) - { - size = 0; - return false; - } + Allocation &al = iter->second; - if (address > al.m_process_start) - { - int dif = address - al.m_process_start; - size = al.m_size - dif; - return true; - } + if (address > (al.m_process_start + al.m_size)) { + size = 0; + return false; + } - size = al.m_size; + if (address > al.m_process_start) { + int dif = address - al.m_process_start; + size = al.m_size - dif; return true; -} + } -void -IRMemoryMap::WriteMemory (lldb::addr_t process_address, const uint8_t *bytes, size_t size, Error &error) -{ - error.Clear(); + size = al.m_size; + return true; +} - AllocationMap::iterator iter = FindAllocation(process_address, size); +void IRMemoryMap::WriteMemory(lldb::addr_t process_address, + const uint8_t *bytes, size_t size, Error &error) { + error.Clear(); - if (iter == m_allocations.end()) - { - lldb::ProcessSP process_sp = m_process_wp.lock(); + AllocationMap::iterator iter = FindAllocation(process_address, size); - if (process_sp) - { - process_sp->WriteMemory(process_address, bytes, size, error); - return; - } + if (iter == m_allocations.end()) { + lldb::ProcessSP process_sp = m_process_wp.lock(); - error.SetErrorToGenericError(); - error.SetErrorString("Couldn't write: no allocation contains the target range and the process doesn't exist"); - return; + if (process_sp) { + process_sp->WriteMemory(process_address, bytes, size, error); + return; } - Allocation &allocation = iter->second; + error.SetErrorToGenericError(); + error.SetErrorString("Couldn't write: no allocation contains the target " + "range and the process doesn't exist"); + return; + } - uint64_t offset = process_address - allocation.m_process_start; + Allocation &allocation = iter->second; - lldb::ProcessSP process_sp; + uint64_t offset = process_address - allocation.m_process_start; - switch (allocation.m_policy) - { - default: - error.SetErrorToGenericError(); - error.SetErrorString("Couldn't write: invalid allocation policy"); + lldb::ProcessSP process_sp; + + switch (allocation.m_policy) { + default: + error.SetErrorToGenericError(); + error.SetErrorString("Couldn't write: invalid allocation policy"); + return; + case eAllocationPolicyHostOnly: + if (!allocation.m_data.GetByteSize()) { + error.SetErrorToGenericError(); + error.SetErrorString("Couldn't write: data buffer is empty"); + return; + } + ::memcpy(allocation.m_data.GetBytes() + offset, bytes, size); + break; + case eAllocationPolicyMirror: + if (!allocation.m_data.GetByteSize()) { + error.SetErrorToGenericError(); + error.SetErrorString("Couldn't write: data buffer is empty"); + return; + } + ::memcpy(allocation.m_data.GetBytes() + offset, bytes, size); + process_sp = m_process_wp.lock(); + if (process_sp) { + process_sp->WriteMemory(process_address, bytes, size, error); + if (!error.Success()) return; - case eAllocationPolicyHostOnly: - if (!allocation.m_data.GetByteSize()) - { - error.SetErrorToGenericError(); - error.SetErrorString("Couldn't write: data buffer is empty"); - return; - } - ::memcpy (allocation.m_data.GetBytes() + offset, bytes, size); - break; - case eAllocationPolicyMirror: - if (!allocation.m_data.GetByteSize()) - { - error.SetErrorToGenericError(); - error.SetErrorString("Couldn't write: data buffer is empty"); - return; - } - ::memcpy (allocation.m_data.GetBytes() + offset, bytes, size); - process_sp = m_process_wp.lock(); - if (process_sp) - { - process_sp->WriteMemory(process_address, bytes, size, error); - if (!error.Success()) - return; - } - break; - case eAllocationPolicyProcessOnly: - process_sp = m_process_wp.lock(); - if (process_sp) - { - process_sp->WriteMemory(process_address, bytes, size, error); - if (!error.Success()) - return; - } - break; } - - if (lldb_private::Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)) - { - log->Printf("IRMemoryMap::WriteMemory (0x%" PRIx64 ", 0x%" PRIx64 ", 0x%" PRId64 ") went to [0x%" PRIx64 "..0x%" PRIx64 ")", - (uint64_t)process_address, - (uint64_t)bytes, - (uint64_t)size, - (uint64_t)allocation.m_process_start, - (uint64_t)allocation.m_process_start + (uint64_t)allocation.m_size); + break; + case eAllocationPolicyProcessOnly: + process_sp = m_process_wp.lock(); + if (process_sp) { + process_sp->WriteMemory(process_address, bytes, size, error); + if (!error.Success()) + return; } + break; + } + + if (lldb_private::Log *log = + lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS)) { + log->Printf("IRMemoryMap::WriteMemory (0x%" PRIx64 ", 0x%" PRIx64 + ", 0x%" PRId64 ") went to [0x%" PRIx64 "..0x%" PRIx64 ")", + (uint64_t)process_address, (uint64_t)bytes, (uint64_t)size, + (uint64_t)allocation.m_process_start, + (uint64_t)allocation.m_process_start + + (uint64_t)allocation.m_size); + } } -void -IRMemoryMap::WriteScalarToMemory (lldb::addr_t process_address, Scalar &scalar, size_t size, Error &error) -{ - error.Clear(); - - if (size == UINT32_MAX) - size = scalar.GetByteSize(); - - if (size > 0) - { - uint8_t buf[32]; - const size_t mem_size = scalar.GetAsMemoryData (buf, size, GetByteOrder(), error); - if (mem_size > 0) - { - return WriteMemory(process_address, buf, mem_size, error); - } - else - { - error.SetErrorToGenericError(); - error.SetErrorString ("Couldn't write scalar: failed to get scalar as memory data"); - } - } - else - { - error.SetErrorToGenericError(); - error.SetErrorString ("Couldn't write scalar: its size was zero"); - } - return; +void IRMemoryMap::WriteScalarToMemory(lldb::addr_t process_address, + Scalar &scalar, size_t size, + Error &error) { + error.Clear(); + + if (size == UINT32_MAX) + size = scalar.GetByteSize(); + + if (size > 0) { + uint8_t buf[32]; + const size_t mem_size = + scalar.GetAsMemoryData(buf, size, GetByteOrder(), error); + if (mem_size > 0) { + return WriteMemory(process_address, buf, mem_size, error); + } else { + error.SetErrorToGenericError(); + error.SetErrorString( + "Couldn't write scalar: failed to get scalar as memory data"); + } + } else { + error.SetErrorToGenericError(); + error.SetErrorString("Couldn't write scalar: its size was zero"); + } + return; } -void -IRMemoryMap::WritePointerToMemory (lldb::addr_t process_address, lldb::addr_t address, Error &error) -{ - error.Clear(); +void IRMemoryMap::WritePointerToMemory(lldb::addr_t process_address, + lldb::addr_t address, Error &error) { + error.Clear(); - Scalar scalar(address); + Scalar scalar(address); - WriteScalarToMemory(process_address, scalar, GetAddressByteSize(), error); + WriteScalarToMemory(process_address, scalar, GetAddressByteSize(), error); } -void -IRMemoryMap::ReadMemory (uint8_t *bytes, lldb::addr_t process_address, size_t size, Error &error) -{ - error.Clear(); +void IRMemoryMap::ReadMemory(uint8_t *bytes, lldb::addr_t process_address, + size_t size, Error &error) { + error.Clear(); - AllocationMap::iterator iter = FindAllocation(process_address, size); - - if (iter == m_allocations.end()) - { - lldb::ProcessSP process_sp = m_process_wp.lock(); + AllocationMap::iterator iter = FindAllocation(process_address, size); - if (process_sp) - { - process_sp->ReadMemory(process_address, bytes, size, error); - return; - } + if (iter == m_allocations.end()) { + lldb::ProcessSP process_sp = m_process_wp.lock(); - lldb::TargetSP target_sp = m_target_wp.lock(); + if (process_sp) { + process_sp->ReadMemory(process_address, bytes, size, error); + return; + } - if (target_sp) - { - Address absolute_address(process_address); - target_sp->ReadMemory(absolute_address, false, bytes, size, error); - return; - } + lldb::TargetSP target_sp = m_target_wp.lock(); - error.SetErrorToGenericError(); - error.SetErrorString("Couldn't read: no allocation contains the target range, and neither the process nor the target exist"); - return; + if (target_sp) { + Address absolute_address(process_address); + target_sp->ReadMemory(absolute_address, false, bytes, size, error); + return; } - Allocation &allocation = iter->second; + error.SetErrorToGenericError(); + error.SetErrorString("Couldn't read: no allocation contains the target " + "range, and neither the process nor the target exist"); + return; + } - uint64_t offset = process_address - allocation.m_process_start; + Allocation &allocation = iter->second; - if (offset > allocation.m_size) - { - error.SetErrorToGenericError(); - error.SetErrorString("Couldn't read: data is not in the allocation"); - return; - } + uint64_t offset = process_address - allocation.m_process_start; - lldb::ProcessSP process_sp; + if (offset > allocation.m_size) { + error.SetErrorToGenericError(); + error.SetErrorString("Couldn't read: data is not in the allocation"); + return; + } - switch (allocation.m_policy) - { - default: + lldb::ProcessSP process_sp; + + switch (allocation.m_policy) { + default: + error.SetErrorToGenericError(); + error.SetErrorString("Couldn't read: invalid allocation policy"); + return; + case eAllocationPolicyHostOnly: + if (!allocation.m_data.GetByteSize()) { + error.SetErrorToGenericError(); + error.SetErrorString("Couldn't read: data buffer is empty"); + return; + } + if (allocation.m_data.GetByteSize() < offset + size) { + error.SetErrorToGenericError(); + error.SetErrorString("Couldn't read: not enough underlying data"); + return; + } + + ::memcpy(bytes, allocation.m_data.GetBytes() + offset, size); + break; + case eAllocationPolicyMirror: + process_sp = m_process_wp.lock(); + if (process_sp) { + process_sp->ReadMemory(process_address, bytes, size, error); + if (!error.Success()) + return; + } else { + if (!allocation.m_data.GetByteSize()) { error.SetErrorToGenericError(); - error.SetErrorString("Couldn't read: invalid allocation policy"); + error.SetErrorString("Couldn't read: data buffer is empty"); + return; + } + ::memcpy(bytes, allocation.m_data.GetBytes() + offset, size); + } + break; + case eAllocationPolicyProcessOnly: + process_sp = m_process_wp.lock(); + if (process_sp) { + process_sp->ReadMemory(process_address, bytes, size, error); + if (!error.Success()) return; - case eAllocationPolicyHostOnly: - if (!allocation.m_data.GetByteSize()) - { - error.SetErrorToGenericError(); - error.SetErrorString("Couldn't read: data buffer is empty"); - return; - } - if (allocation.m_data.GetByteSize() < offset + size) - { - error.SetErrorToGenericError(); - error.SetErrorString("Couldn't read: not enough underlying data"); - return; - } - - ::memcpy (bytes, allocation.m_data.GetBytes() + offset, size); - break; - case eAllocationPolicyMirror: - process_sp = m_process_wp.lock(); - if (process_sp) - { - process_sp->ReadMemory(process_address, bytes, size, error); - if (!error.Success()) - return; - } - else - { - if (!allocation.m_data.GetByteSize()) - { - error.SetErrorToGenericError(); - error.SetErrorString("Couldn't read: data buffer is empty"); - return; - } - ::memcpy (bytes, allocation.m_data.GetBytes() + offset, size); - } - break; - case eAllocationPolicyProcessOnly: - process_sp = m_process_wp.lock(); - if (process_sp) - { - process_sp->ReadMemory(process_address, bytes, size, error); - if (!error.Success()) - return; - } - break; - } - - if (lldb_private::Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)) - { - log->Printf("IRMemoryMap::ReadMemory (0x%" PRIx64 ", 0x%" PRIx64 ", 0x%" PRId64 ") came from [0x%" PRIx64 "..0x%" PRIx64 ")", - (uint64_t)process_address, - (uint64_t)bytes, - (uint64_t)size, - (uint64_t)allocation.m_process_start, - (uint64_t)allocation.m_process_start + (uint64_t)allocation.m_size); } + break; + } + + if (lldb_private::Log *log = + lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS)) { + log->Printf("IRMemoryMap::ReadMemory (0x%" PRIx64 ", 0x%" PRIx64 + ", 0x%" PRId64 ") came from [0x%" PRIx64 "..0x%" PRIx64 ")", + (uint64_t)process_address, (uint64_t)bytes, (uint64_t)size, + (uint64_t)allocation.m_process_start, + (uint64_t)allocation.m_process_start + + (uint64_t)allocation.m_size); + } } -void -IRMemoryMap::ReadScalarFromMemory (Scalar &scalar, lldb::addr_t process_address, size_t size, Error &error) -{ - error.Clear(); +void IRMemoryMap::ReadScalarFromMemory(Scalar &scalar, + lldb::addr_t process_address, + size_t size, Error &error) { + error.Clear(); - if (size > 0) - { - DataBufferHeap buf(size, 0); - ReadMemory(buf.GetBytes(), process_address, size, error); + if (size > 0) { + DataBufferHeap buf(size, 0); + ReadMemory(buf.GetBytes(), process_address, size, error); - if (!error.Success()) - return; - - DataExtractor extractor(buf.GetBytes(), buf.GetByteSize(), GetByteOrder(), GetAddressByteSize()); - - lldb::offset_t offset = 0; - - switch (size) - { - default: - error.SetErrorToGenericError(); - error.SetErrorStringWithFormat("Couldn't read scalar: unsupported size %" PRIu64, (uint64_t)size); - return; - case 1: scalar = extractor.GetU8(&offset); break; - case 2: scalar = extractor.GetU16(&offset); break; - case 4: scalar = extractor.GetU32(&offset); break; - case 8: scalar = extractor.GetU64(&offset); break; - } - } - else - { - error.SetErrorToGenericError(); - error.SetErrorString ("Couldn't read scalar: its size was zero"); - } - return; -} + if (!error.Success()) + return; -void -IRMemoryMap::ReadPointerFromMemory (lldb::addr_t *address, lldb::addr_t process_address, Error &error) -{ - error.Clear(); + DataExtractor extractor(buf.GetBytes(), buf.GetByteSize(), GetByteOrder(), + GetAddressByteSize()); - Scalar pointer_scalar; - ReadScalarFromMemory(pointer_scalar, process_address, GetAddressByteSize(), error); + lldb::offset_t offset = 0; - if (!error.Success()) - return; + switch (size) { + default: + error.SetErrorToGenericError(); + error.SetErrorStringWithFormat( + "Couldn't read scalar: unsupported size %" PRIu64, (uint64_t)size); + return; + case 1: + scalar = extractor.GetU8(&offset); + break; + case 2: + scalar = extractor.GetU16(&offset); + break; + case 4: + scalar = extractor.GetU32(&offset); + break; + case 8: + scalar = extractor.GetU64(&offset); + break; + } + } else { + error.SetErrorToGenericError(); + error.SetErrorString("Couldn't read scalar: its size was zero"); + } + return; +} + +void IRMemoryMap::ReadPointerFromMemory(lldb::addr_t *address, + lldb::addr_t process_address, + Error &error) { + error.Clear(); - *address = pointer_scalar.ULongLong(); + Scalar pointer_scalar; + ReadScalarFromMemory(pointer_scalar, process_address, GetAddressByteSize(), + error); + if (!error.Success()) return; -} -void -IRMemoryMap::GetMemoryData (DataExtractor &extractor, lldb::addr_t process_address, size_t size, Error &error) -{ - error.Clear(); + *address = pointer_scalar.ULongLong(); - if (size > 0) - { - AllocationMap::iterator iter = FindAllocation(process_address, size); + return; +} - if (iter == m_allocations.end()) - { - error.SetErrorToGenericError(); - error.SetErrorStringWithFormat("Couldn't find an allocation containing [0x%" PRIx64 "..0x%" PRIx64 ")", process_address, process_address + size); - return; - } +void IRMemoryMap::GetMemoryData(DataExtractor &extractor, + lldb::addr_t process_address, size_t size, + Error &error) { + error.Clear(); - Allocation &allocation = iter->second; - - switch (allocation.m_policy) - { - default: - error.SetErrorToGenericError(); - error.SetErrorString("Couldn't get memory data: invalid allocation policy"); - return; - case eAllocationPolicyProcessOnly: - error.SetErrorToGenericError(); - error.SetErrorString("Couldn't get memory data: memory is only in the target"); - return; - case eAllocationPolicyMirror: - { - lldb::ProcessSP process_sp = m_process_wp.lock(); - - if (!allocation.m_data.GetByteSize()) - { - error.SetErrorToGenericError(); - error.SetErrorString("Couldn't get memory data: data buffer is empty"); - return; - } - if (process_sp) - { - process_sp->ReadMemory(allocation.m_process_start, allocation.m_data.GetBytes(), allocation.m_data.GetByteSize(), error); - if (!error.Success()) - return; - uint64_t offset = process_address - allocation.m_process_start; - extractor = DataExtractor(allocation.m_data.GetBytes() + offset, size, GetByteOrder(), GetAddressByteSize()); - return; - } - } - break; - case eAllocationPolicyHostOnly: - if (!allocation.m_data.GetByteSize()) - { - error.SetErrorToGenericError(); - error.SetErrorString("Couldn't get memory data: data buffer is empty"); - return; - } - uint64_t offset = process_address - allocation.m_process_start; - extractor = DataExtractor(allocation.m_data.GetBytes() + offset, size, GetByteOrder(), GetAddressByteSize()); - return; - } + if (size > 0) { + AllocationMap::iterator iter = FindAllocation(process_address, size); + + if (iter == m_allocations.end()) { + error.SetErrorToGenericError(); + error.SetErrorStringWithFormat( + "Couldn't find an allocation containing [0x%" PRIx64 "..0x%" PRIx64 + ")", + process_address, process_address + size); + return; } - else - { + + Allocation &allocation = iter->second; + + switch (allocation.m_policy) { + default: + error.SetErrorToGenericError(); + error.SetErrorString( + "Couldn't get memory data: invalid allocation policy"); + return; + case eAllocationPolicyProcessOnly: + error.SetErrorToGenericError(); + error.SetErrorString( + "Couldn't get memory data: memory is only in the target"); + return; + case eAllocationPolicyMirror: { + lldb::ProcessSP process_sp = m_process_wp.lock(); + + if (!allocation.m_data.GetByteSize()) { error.SetErrorToGenericError(); - error.SetErrorString ("Couldn't get memory data: its size was zero"); + error.SetErrorString("Couldn't get memory data: data buffer is empty"); return; - } + } + if (process_sp) { + process_sp->ReadMemory(allocation.m_process_start, + allocation.m_data.GetBytes(), + allocation.m_data.GetByteSize(), error); + if (!error.Success()) + return; + uint64_t offset = process_address - allocation.m_process_start; + extractor = DataExtractor(allocation.m_data.GetBytes() + offset, size, + GetByteOrder(), GetAddressByteSize()); + return; + } + } break; + case eAllocationPolicyHostOnly: + if (!allocation.m_data.GetByteSize()) { + error.SetErrorToGenericError(); + error.SetErrorString("Couldn't get memory data: data buffer is empty"); + return; + } + uint64_t offset = process_address - allocation.m_process_start; + extractor = DataExtractor(allocation.m_data.GetBytes() + offset, size, + GetByteOrder(), GetAddressByteSize()); + return; + } + } else { + error.SetErrorToGenericError(); + error.SetErrorString("Couldn't get memory data: its size was zero"); + return; + } } diff --git a/source/Expression/LLVMUserExpression.cpp b/source/Expression/LLVMUserExpression.cpp index 0b969806280e..c5df7812ba43 100644 --- a/source/Expression/LLVMUserExpression.cpp +++ b/source/Expression/LLVMUserExpression.cpp @@ -41,341 +41,336 @@ using namespace lldb_private; -LLVMUserExpression::LLVMUserExpression(ExecutionContextScope &exe_scope, - const char *expr, - const char *expr_prefix, - lldb::LanguageType language, - ResultType desired_type, +LLVMUserExpression::LLVMUserExpression(ExecutionContextScope &exe_scope, + llvm::StringRef expr, + llvm::StringRef prefix, + lldb::LanguageType language, + ResultType desired_type, const EvaluateExpressionOptions &options) - : UserExpression(exe_scope, expr, expr_prefix, language, desired_type, options), + : UserExpression(exe_scope, expr, prefix, language, desired_type, options), m_stack_frame_bottom(LLDB_INVALID_ADDRESS), - m_stack_frame_top(LLDB_INVALID_ADDRESS), - m_transformed_text(), - m_execution_unit_sp(), - m_materializer_ap(), - m_jit_module_wp(), - m_enforce_valid_object(true), - m_in_cplusplus_method(false), - m_in_objectivec_method(false), - m_in_static_method(false), - m_needs_object_ptr(false), - m_target(NULL), - m_can_interpret(false), - m_materialized_address(LLDB_INVALID_ADDRESS) -{ + m_stack_frame_top(LLDB_INVALID_ADDRESS), m_transformed_text(), + m_execution_unit_sp(), m_materializer_ap(), m_jit_module_wp(), + m_enforce_valid_object(true), m_in_cplusplus_method(false), + m_in_objectivec_method(false), m_in_static_method(false), + m_needs_object_ptr(false), m_target(NULL), m_can_interpret(false), + m_materialized_address(LLDB_INVALID_ADDRESS) {} + +LLVMUserExpression::~LLVMUserExpression() { + if (m_target) { + lldb::ModuleSP jit_module_sp(m_jit_module_wp.lock()); + if (jit_module_sp) + m_target->GetImages().Remove(jit_module_sp); + } } -LLVMUserExpression::~LLVMUserExpression() -{ - if (m_target) - { - lldb::ModuleSP jit_module_sp(m_jit_module_wp.lock()); - if (jit_module_sp) - m_target->GetImages().Remove(jit_module_sp); +lldb::ExpressionResults +LLVMUserExpression::DoExecute(DiagnosticManager &diagnostic_manager, + ExecutionContext &exe_ctx, + const EvaluateExpressionOptions &options, + lldb::UserExpressionSP &shared_ptr_to_me, + lldb::ExpressionVariableSP &result) { + // The expression log is quite verbose, and if you're just tracking the + // execution of the + // expression, it's quite convenient to have these logs come out with the STEP + // log as well. + Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_EXPRESSIONS | + LIBLLDB_LOG_STEP)); + + if (m_jit_start_addr != LLDB_INVALID_ADDRESS || m_can_interpret) { + lldb::addr_t struct_address = LLDB_INVALID_ADDRESS; + + if (!PrepareToExecuteJITExpression(diagnostic_manager, exe_ctx, + struct_address)) { + diagnostic_manager.Printf( + eDiagnosticSeverityError, + "errored out in %s, couldn't PrepareToExecuteJITExpression", + __FUNCTION__); + return lldb::eExpressionSetupError; } -} -lldb::ExpressionResults -LLVMUserExpression::DoExecute(DiagnosticManager &diagnostic_manager, ExecutionContext &exe_ctx, - const EvaluateExpressionOptions &options, lldb::UserExpressionSP &shared_ptr_to_me, - lldb::ExpressionVariableSP &result) -{ - // The expression log is quite verbose, and if you're just tracking the execution of the - // expression, it's quite convenient to have these logs come out with the STEP log as well. - Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_EXPRESSIONS | LIBLLDB_LOG_STEP)); - - if (m_jit_start_addr != LLDB_INVALID_ADDRESS || m_can_interpret) - { - lldb::addr_t struct_address = LLDB_INVALID_ADDRESS; - - if (!PrepareToExecuteJITExpression(diagnostic_manager, exe_ctx, struct_address)) - { - diagnostic_manager.Printf(eDiagnosticSeverityError, - "errored out in %s, couldn't PrepareToExecuteJITExpression", __FUNCTION__); - return lldb::eExpressionSetupError; - } + lldb::addr_t function_stack_bottom = LLDB_INVALID_ADDRESS; + lldb::addr_t function_stack_top = LLDB_INVALID_ADDRESS; - lldb::addr_t function_stack_bottom = LLDB_INVALID_ADDRESS; - lldb::addr_t function_stack_top = LLDB_INVALID_ADDRESS; + if (m_can_interpret) { + llvm::Module *module = m_execution_unit_sp->GetModule(); + llvm::Function *function = m_execution_unit_sp->GetFunction(); - if (m_can_interpret) - { - llvm::Module *module = m_execution_unit_sp->GetModule(); - llvm::Function *function = m_execution_unit_sp->GetFunction(); + if (!module || !function) { + diagnostic_manager.PutString( + eDiagnosticSeverityError, + "supposed to interpret, but nothing is there"); + return lldb::eExpressionSetupError; + } - if (!module || !function) - { - diagnostic_manager.PutCString(eDiagnosticSeverityError, "supposed to interpret, but nothing is there"); - return lldb::eExpressionSetupError; - } + Error interpreter_error; - Error interpreter_error; + std::vector<lldb::addr_t> args; - std::vector<lldb::addr_t> args; + if (!AddArguments(exe_ctx, args, struct_address, diagnostic_manager)) { + diagnostic_manager.Printf(eDiagnosticSeverityError, + "errored out in %s, couldn't AddArguments", + __FUNCTION__); + return lldb::eExpressionSetupError; + } - if (!AddArguments(exe_ctx, args, struct_address, diagnostic_manager)) - { - diagnostic_manager.Printf(eDiagnosticSeverityError, "errored out in %s, couldn't AddArguments", - __FUNCTION__); - return lldb::eExpressionSetupError; - } + function_stack_bottom = m_stack_frame_bottom; + function_stack_top = m_stack_frame_top; - function_stack_bottom = m_stack_frame_bottom; - function_stack_top = m_stack_frame_top; + IRInterpreter::Interpret(*module, *function, args, + *m_execution_unit_sp.get(), interpreter_error, + function_stack_bottom, function_stack_top, + exe_ctx); - IRInterpreter::Interpret(*module, *function, args, *m_execution_unit_sp.get(), interpreter_error, - function_stack_bottom, function_stack_top, exe_ctx); + if (!interpreter_error.Success()) { + diagnostic_manager.Printf(eDiagnosticSeverityError, + "supposed to interpret, but failed: %s", + interpreter_error.AsCString()); + return lldb::eExpressionDiscarded; + } + } else { + if (!exe_ctx.HasThreadScope()) { + diagnostic_manager.Printf(eDiagnosticSeverityError, + "%s called with no thread selected", + __FUNCTION__); + return lldb::eExpressionSetupError; + } - if (!interpreter_error.Success()) - { - diagnostic_manager.Printf(eDiagnosticSeverityError, "supposed to interpret, but failed: %s", - interpreter_error.AsCString()); - return lldb::eExpressionDiscarded; - } - } - else - { - if (!exe_ctx.HasThreadScope()) - { - diagnostic_manager.Printf(eDiagnosticSeverityError, "%s called with no thread selected", __FUNCTION__); - return lldb::eExpressionSetupError; - } - - Address wrapper_address(m_jit_start_addr); - - std::vector<lldb::addr_t> args; - - if (!AddArguments(exe_ctx, args, struct_address, diagnostic_manager)) - { - diagnostic_manager.Printf(eDiagnosticSeverityError, "errored out in %s, couldn't AddArguments", - __FUNCTION__); - return lldb::eExpressionSetupError; - } - - lldb::ThreadPlanSP call_plan_sp(new ThreadPlanCallUserExpression(exe_ctx.GetThreadRef(), wrapper_address, - args, options, shared_ptr_to_me)); - - StreamString ss; - if (!call_plan_sp || !call_plan_sp->ValidatePlan(&ss)) - { - diagnostic_manager.PutCString(eDiagnosticSeverityError, ss.GetData()); - return lldb::eExpressionSetupError; - } - - ThreadPlanCallUserExpression *user_expression_plan = - static_cast<ThreadPlanCallUserExpression *>(call_plan_sp.get()); - - lldb::addr_t function_stack_pointer = user_expression_plan->GetFunctionStackPointer(); - - function_stack_bottom = function_stack_pointer - HostInfo::GetPageSize(); - function_stack_top = function_stack_pointer; - - if (log) - log->Printf("-- [UserExpression::Execute] Execution of expression begins --"); - - if (exe_ctx.GetProcessPtr()) - exe_ctx.GetProcessPtr()->SetRunningUserExpression(true); - - lldb::ExpressionResults execution_result = - exe_ctx.GetProcessRef().RunThreadPlan(exe_ctx, call_plan_sp, options, diagnostic_manager); - - if (exe_ctx.GetProcessPtr()) - exe_ctx.GetProcessPtr()->SetRunningUserExpression(false); - - if (log) - log->Printf("-- [UserExpression::Execute] Execution of expression completed --"); - - if (execution_result == lldb::eExpressionInterrupted || execution_result == lldb::eExpressionHitBreakpoint) - { - const char *error_desc = NULL; - - if (call_plan_sp) - { - lldb::StopInfoSP real_stop_info_sp = call_plan_sp->GetRealStopInfo(); - if (real_stop_info_sp) - error_desc = real_stop_info_sp->GetDescription(); - } - if (error_desc) - diagnostic_manager.Printf(eDiagnosticSeverityError, "Execution was interrupted, reason: %s.", - error_desc); - else - diagnostic_manager.PutCString(eDiagnosticSeverityError, "Execution was interrupted."); - - if ((execution_result == lldb::eExpressionInterrupted && options.DoesUnwindOnError()) || - (execution_result == lldb::eExpressionHitBreakpoint && options.DoesIgnoreBreakpoints())) - diagnostic_manager.AppendMessageToDiagnostic( - "The process has been returned to the state before expression evaluation."); - else - { - if (execution_result == lldb::eExpressionHitBreakpoint) - user_expression_plan->TransferExpressionOwnership(); - diagnostic_manager.AppendMessageToDiagnostic( - "The process has been left at the point where it was interrupted, " - "use \"thread return -x\" to return to the state before expression evaluation."); - } - - return execution_result; - } - else if (execution_result == lldb::eExpressionStoppedForDebug) - { - diagnostic_manager.PutCString( - eDiagnosticSeverityRemark, - "Execution was halted at the first instruction of the expression " - "function because \"debug\" was requested.\n" - "Use \"thread return -x\" to return to the state before expression evaluation."); - return execution_result; - } - else if (execution_result != lldb::eExpressionCompleted) - { - diagnostic_manager.Printf(eDiagnosticSeverityError, "Couldn't execute function; result was %s", - Process::ExecutionResultAsCString(execution_result)); - return execution_result; - } - } + Address wrapper_address(m_jit_start_addr); + + std::vector<lldb::addr_t> args; + + if (!AddArguments(exe_ctx, args, struct_address, diagnostic_manager)) { + diagnostic_manager.Printf(eDiagnosticSeverityError, + "errored out in %s, couldn't AddArguments", + __FUNCTION__); + return lldb::eExpressionSetupError; + } + + lldb::ThreadPlanSP call_plan_sp(new ThreadPlanCallUserExpression( + exe_ctx.GetThreadRef(), wrapper_address, args, options, + shared_ptr_to_me)); + + StreamString ss; + if (!call_plan_sp || !call_plan_sp->ValidatePlan(&ss)) { + diagnostic_manager.PutString(eDiagnosticSeverityError, ss.GetString()); + return lldb::eExpressionSetupError; + } + + ThreadPlanCallUserExpression *user_expression_plan = + static_cast<ThreadPlanCallUserExpression *>(call_plan_sp.get()); + + lldb::addr_t function_stack_pointer = + user_expression_plan->GetFunctionStackPointer(); - if (FinalizeJITExecution(diagnostic_manager, exe_ctx, result, function_stack_bottom, function_stack_top)) - { - return lldb::eExpressionCompleted; + function_stack_bottom = function_stack_pointer - HostInfo::GetPageSize(); + function_stack_top = function_stack_pointer; + + if (log) + log->Printf( + "-- [UserExpression::Execute] Execution of expression begins --"); + + if (exe_ctx.GetProcessPtr()) + exe_ctx.GetProcessPtr()->SetRunningUserExpression(true); + + lldb::ExpressionResults execution_result = + exe_ctx.GetProcessRef().RunThreadPlan(exe_ctx, call_plan_sp, options, + diagnostic_manager); + + if (exe_ctx.GetProcessPtr()) + exe_ctx.GetProcessPtr()->SetRunningUserExpression(false); + + if (log) + log->Printf("-- [UserExpression::Execute] Execution of expression " + "completed --"); + + if (execution_result == lldb::eExpressionInterrupted || + execution_result == lldb::eExpressionHitBreakpoint) { + const char *error_desc = NULL; + + if (call_plan_sp) { + lldb::StopInfoSP real_stop_info_sp = call_plan_sp->GetRealStopInfo(); + if (real_stop_info_sp) + error_desc = real_stop_info_sp->GetDescription(); } + if (error_desc) + diagnostic_manager.Printf(eDiagnosticSeverityError, + "Execution was interrupted, reason: %s.", + error_desc); else - { - return lldb::eExpressionResultUnavailable; + diagnostic_manager.PutString(eDiagnosticSeverityError, + "Execution was interrupted."); + + if ((execution_result == lldb::eExpressionInterrupted && + options.DoesUnwindOnError()) || + (execution_result == lldb::eExpressionHitBreakpoint && + options.DoesIgnoreBreakpoints())) + diagnostic_manager.AppendMessageToDiagnostic( + "The process has been returned to the state before expression " + "evaluation."); + else { + if (execution_result == lldb::eExpressionHitBreakpoint) + user_expression_plan->TransferExpressionOwnership(); + diagnostic_manager.AppendMessageToDiagnostic( + "The process has been left at the point where it was " + "interrupted, " + "use \"thread return -x\" to return to the state before " + "expression evaluation."); } + + return execution_result; + } else if (execution_result == lldb::eExpressionStoppedForDebug) { + diagnostic_manager.PutString( + eDiagnosticSeverityRemark, + "Execution was halted at the first instruction of the expression " + "function because \"debug\" was requested.\n" + "Use \"thread return -x\" to return to the state before expression " + "evaluation."); + return execution_result; + } else if (execution_result != lldb::eExpressionCompleted) { + diagnostic_manager.Printf( + eDiagnosticSeverityError, + "Couldn't execute function; result was %s", + Process::ExecutionResultAsCString(execution_result)); + return execution_result; + } } - else - { - diagnostic_manager.PutCString(eDiagnosticSeverityError, - "Expression can't be run, because there is no JIT compiled function"); - return lldb::eExpressionSetupError; + + if (FinalizeJITExecution(diagnostic_manager, exe_ctx, result, + function_stack_bottom, function_stack_top)) { + return lldb::eExpressionCompleted; + } else { + return lldb::eExpressionResultUnavailable; } + } else { + diagnostic_manager.PutString( + eDiagnosticSeverityError, + "Expression can't be run, because there is no JIT compiled function"); + return lldb::eExpressionSetupError; + } } -bool -LLVMUserExpression::FinalizeJITExecution(DiagnosticManager &diagnostic_manager, ExecutionContext &exe_ctx, - lldb::ExpressionVariableSP &result, lldb::addr_t function_stack_bottom, - lldb::addr_t function_stack_top) -{ - Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS)); +bool LLVMUserExpression::FinalizeJITExecution( + DiagnosticManager &diagnostic_manager, ExecutionContext &exe_ctx, + lldb::ExpressionVariableSP &result, lldb::addr_t function_stack_bottom, + lldb::addr_t function_stack_top) { + Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS)); - if (log) - log->Printf("-- [UserExpression::FinalizeJITExecution] Dematerializing after execution --"); + if (log) + log->Printf("-- [UserExpression::FinalizeJITExecution] Dematerializing " + "after execution --"); - if (!m_dematerializer_sp) - { - diagnostic_manager.Printf(eDiagnosticSeverityError, - "Couldn't apply expression side effects : no dematerializer is present"); - return false; - } + if (!m_dematerializer_sp) { + diagnostic_manager.Printf(eDiagnosticSeverityError, + "Couldn't apply expression side effects : no " + "dematerializer is present"); + return false; + } - Error dematerialize_error; + Error dematerialize_error; - m_dematerializer_sp->Dematerialize(dematerialize_error, function_stack_bottom, function_stack_top); + m_dematerializer_sp->Dematerialize(dematerialize_error, function_stack_bottom, + function_stack_top); - if (!dematerialize_error.Success()) - { - diagnostic_manager.Printf(eDiagnosticSeverityError, "Couldn't apply expression side effects : %s", - dematerialize_error.AsCString("unknown error")); - return false; - } + if (!dematerialize_error.Success()) { + diagnostic_manager.Printf(eDiagnosticSeverityError, + "Couldn't apply expression side effects : %s", + dematerialize_error.AsCString("unknown error")); + return false; + } - result = GetResultAfterDematerialization(exe_ctx.GetBestExecutionContextScope()); + result = + GetResultAfterDematerialization(exe_ctx.GetBestExecutionContextScope()); - if (result) - result->TransferAddress(); + if (result) + result->TransferAddress(); - m_dematerializer_sp.reset(); + m_dematerializer_sp.reset(); - return true; + return true; } -bool -LLVMUserExpression::PrepareToExecuteJITExpression(DiagnosticManager &diagnostic_manager, ExecutionContext &exe_ctx, - lldb::addr_t &struct_address) -{ - lldb::TargetSP target; - lldb::ProcessSP process; - lldb::StackFrameSP frame; - - if (!LockAndCheckContext(exe_ctx, target, process, frame)) - { - diagnostic_manager.PutCString(eDiagnosticSeverityError, - "The context has changed before we could JIT the expression!"); +bool LLVMUserExpression::PrepareToExecuteJITExpression( + DiagnosticManager &diagnostic_manager, ExecutionContext &exe_ctx, + lldb::addr_t &struct_address) { + lldb::TargetSP target; + lldb::ProcessSP process; + lldb::StackFrameSP frame; + + if (!LockAndCheckContext(exe_ctx, target, process, frame)) { + diagnostic_manager.PutString( + eDiagnosticSeverityError, + "The context has changed before we could JIT the expression!"); + return false; + } + + if (m_jit_start_addr != LLDB_INVALID_ADDRESS || m_can_interpret) { + if (m_materialized_address == LLDB_INVALID_ADDRESS) { + Error alloc_error; + + IRMemoryMap::AllocationPolicy policy = + m_can_interpret ? IRMemoryMap::eAllocationPolicyHostOnly + : IRMemoryMap::eAllocationPolicyMirror; + + const bool zero_memory = false; + + m_materialized_address = m_execution_unit_sp->Malloc( + m_materializer_ap->GetStructByteSize(), + m_materializer_ap->GetStructAlignment(), + lldb::ePermissionsReadable | lldb::ePermissionsWritable, policy, + zero_memory, alloc_error); + + if (!alloc_error.Success()) { + diagnostic_manager.Printf( + eDiagnosticSeverityError, + "Couldn't allocate space for materialized struct: %s", + alloc_error.AsCString()); return false; + } } - if (m_jit_start_addr != LLDB_INVALID_ADDRESS || m_can_interpret) - { - if (m_materialized_address == LLDB_INVALID_ADDRESS) - { - Error alloc_error; - - IRMemoryMap::AllocationPolicy policy = - m_can_interpret ? IRMemoryMap::eAllocationPolicyHostOnly : IRMemoryMap::eAllocationPolicyMirror; - - const bool zero_memory = false; - - m_materialized_address = m_execution_unit_sp->Malloc(m_materializer_ap->GetStructByteSize(), - m_materializer_ap->GetStructAlignment(), - lldb::ePermissionsReadable | lldb::ePermissionsWritable, - policy, - zero_memory, - alloc_error); - - if (!alloc_error.Success()) - { - diagnostic_manager.Printf(eDiagnosticSeverityError, - "Couldn't allocate space for materialized struct: %s", - alloc_error.AsCString()); - return false; - } - } - - struct_address = m_materialized_address; + struct_address = m_materialized_address; - if (m_can_interpret && m_stack_frame_bottom == LLDB_INVALID_ADDRESS) - { - Error alloc_error; + if (m_can_interpret && m_stack_frame_bottom == LLDB_INVALID_ADDRESS) { + Error alloc_error; - const size_t stack_frame_size = 512 * 1024; + const size_t stack_frame_size = 512 * 1024; - const bool zero_memory = false; + const bool zero_memory = false; - m_stack_frame_bottom = m_execution_unit_sp->Malloc(stack_frame_size, - 8, - lldb::ePermissionsReadable | lldb::ePermissionsWritable, - IRMemoryMap::eAllocationPolicyHostOnly, - zero_memory, - alloc_error); + m_stack_frame_bottom = m_execution_unit_sp->Malloc( + stack_frame_size, 8, + lldb::ePermissionsReadable | lldb::ePermissionsWritable, + IRMemoryMap::eAllocationPolicyHostOnly, zero_memory, alloc_error); - m_stack_frame_top = m_stack_frame_bottom + stack_frame_size; + m_stack_frame_top = m_stack_frame_bottom + stack_frame_size; - if (!alloc_error.Success()) - { - diagnostic_manager.Printf(eDiagnosticSeverityError, "Couldn't allocate space for the stack frame: %s", - alloc_error.AsCString()); - return false; - } - } + if (!alloc_error.Success()) { + diagnostic_manager.Printf( + eDiagnosticSeverityError, + "Couldn't allocate space for the stack frame: %s", + alloc_error.AsCString()); + return false; + } + } - Error materialize_error; + Error materialize_error; - m_dematerializer_sp = - m_materializer_ap->Materialize(frame, *m_execution_unit_sp, struct_address, materialize_error); + m_dematerializer_sp = m_materializer_ap->Materialize( + frame, *m_execution_unit_sp, struct_address, materialize_error); - if (!materialize_error.Success()) - { - diagnostic_manager.Printf(eDiagnosticSeverityError, "Couldn't materialize: %s", - materialize_error.AsCString()); - return false; - } + if (!materialize_error.Success()) { + diagnostic_manager.Printf(eDiagnosticSeverityError, + "Couldn't materialize: %s", + materialize_error.AsCString()); + return false; } - return true; + } + return true; } -lldb::ModuleSP -LLVMUserExpression::GetJITModule() -{ - if (m_execution_unit_sp) - return m_execution_unit_sp->GetJITModule(); - return lldb::ModuleSP(); +lldb::ModuleSP LLVMUserExpression::GetJITModule() { + if (m_execution_unit_sp) + return m_execution_unit_sp->GetJITModule(); + return lldb::ModuleSP(); } diff --git a/source/Expression/Materializer.cpp b/source/Expression/Materializer.cpp index 3575f5436d92..6ddd4a4d8fb0 100644 --- a/source/Expression/Materializer.cpp +++ b/source/Expression/Materializer.cpp @@ -11,12 +11,12 @@ // C++ Includes // Other libraries and framework includes // Project includes +#include "lldb/Expression/Materializer.h" #include "lldb/Core/Log.h" #include "lldb/Core/RegisterValue.h" #include "lldb/Core/ValueObjectConstResult.h" #include "lldb/Core/ValueObjectVariable.h" #include "lldb/Expression/ExpressionVariable.h" -#include "lldb/Expression/Materializer.h" #include "lldb/Symbol/ClangASTContext.h" #include "lldb/Symbol/Symbol.h" #include "lldb/Symbol/Type.h" @@ -29,1493 +29,1436 @@ using namespace lldb_private; -uint32_t -Materializer::AddStructMember (Entity &entity) -{ - uint32_t size = entity.GetSize(); - uint32_t alignment = entity.GetAlignment(); +uint32_t Materializer::AddStructMember(Entity &entity) { + uint32_t size = entity.GetSize(); + uint32_t alignment = entity.GetAlignment(); - uint32_t ret; + uint32_t ret; - if (m_current_offset == 0) - m_struct_alignment = alignment; + if (m_current_offset == 0) + m_struct_alignment = alignment; - if (m_current_offset % alignment) - m_current_offset += (alignment - (m_current_offset % alignment)); + if (m_current_offset % alignment) + m_current_offset += (alignment - (m_current_offset % alignment)); - ret = m_current_offset; + ret = m_current_offset; - m_current_offset += size; + m_current_offset += size; - return ret; + return ret; } -void -Materializer::Entity::SetSizeAndAlignmentFromType (CompilerType &type) -{ - m_size = type.GetByteSize(nullptr); +void Materializer::Entity::SetSizeAndAlignmentFromType(CompilerType &type) { + m_size = type.GetByteSize(nullptr); - uint32_t bit_alignment = type.GetTypeBitAlign(); + uint32_t bit_alignment = type.GetTypeBitAlign(); - if (bit_alignment % 8) - { - bit_alignment += 8; - bit_alignment &= ~((uint32_t)0x111u); - } + if (bit_alignment % 8) { + bit_alignment += 8; + bit_alignment &= ~((uint32_t)0x111u); + } - m_alignment = bit_alignment / 8; + m_alignment = bit_alignment / 8; } -class EntityPersistentVariable : public Materializer::Entity -{ +class EntityPersistentVariable : public Materializer::Entity { public: - EntityPersistentVariable (lldb::ExpressionVariableSP &persistent_variable_sp, - Materializer::PersistentVariableDelegate *delegate) : - Entity(), - m_persistent_variable_sp(persistent_variable_sp), - m_delegate(delegate) - { - // Hard-coding to maximum size of a pointer since persistent variables are materialized by reference - m_size = 8; - m_alignment = 8; + EntityPersistentVariable(lldb::ExpressionVariableSP &persistent_variable_sp, + Materializer::PersistentVariableDelegate *delegate) + : Entity(), m_persistent_variable_sp(persistent_variable_sp), + m_delegate(delegate) { + // Hard-coding to maximum size of a pointer since persistent variables are + // materialized by reference + m_size = 8; + m_alignment = 8; + } + + void MakeAllocation(IRMemoryMap &map, Error &err) { + Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS)); + + // Allocate a spare memory area to store the persistent variable's contents. + + Error allocate_error; + const bool zero_memory = false; + + lldb::addr_t mem = map.Malloc( + m_persistent_variable_sp->GetByteSize(), 8, + lldb::ePermissionsReadable | lldb::ePermissionsWritable, + IRMemoryMap::eAllocationPolicyMirror, zero_memory, allocate_error); + + if (!allocate_error.Success()) { + err.SetErrorStringWithFormat( + "couldn't allocate a memory area to store %s: %s", + m_persistent_variable_sp->GetName().GetCString(), + allocate_error.AsCString()); + return; } - void MakeAllocation (IRMemoryMap &map, Error &err) - { - Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); + if (log) + log->Printf("Allocated %s (0x%" PRIx64 ") successfully", + m_persistent_variable_sp->GetName().GetCString(), mem); - // Allocate a spare memory area to store the persistent variable's contents. + // Put the location of the spare memory into the live data of the + // ValueObject. - Error allocate_error; - const bool zero_memory = false; + m_persistent_variable_sp->m_live_sp = ValueObjectConstResult::Create( + map.GetBestExecutionContextScope(), + m_persistent_variable_sp->GetCompilerType(), + m_persistent_variable_sp->GetName(), mem, eAddressTypeLoad, + map.GetAddressByteSize()); - lldb::addr_t mem = map.Malloc(m_persistent_variable_sp->GetByteSize(), - 8, - lldb::ePermissionsReadable | lldb::ePermissionsWritable, - IRMemoryMap::eAllocationPolicyMirror, - zero_memory, - allocate_error); - - if (!allocate_error.Success()) - { - err.SetErrorStringWithFormat("couldn't allocate a memory area to store %s: %s", m_persistent_variable_sp->GetName().GetCString(), allocate_error.AsCString()); - return; - } + // Clear the flag if the variable will never be deallocated. - if (log) - log->Printf("Allocated %s (0x%" PRIx64 ") successfully", m_persistent_variable_sp->GetName().GetCString(), mem); + if (m_persistent_variable_sp->m_flags & + ExpressionVariable::EVKeepInTarget) { + Error leak_error; + map.Leak(mem, leak_error); + m_persistent_variable_sp->m_flags &= + ~ExpressionVariable::EVNeedsAllocation; + } - // Put the location of the spare memory into the live data of the ValueObject. + // Write the contents of the variable to the area. - m_persistent_variable_sp->m_live_sp = ValueObjectConstResult::Create (map.GetBestExecutionContextScope(), - m_persistent_variable_sp->GetCompilerType(), - m_persistent_variable_sp->GetName(), - mem, - eAddressTypeLoad, - map.GetAddressByteSize()); + Error write_error; - // Clear the flag if the variable will never be deallocated. + map.WriteMemory(mem, m_persistent_variable_sp->GetValueBytes(), + m_persistent_variable_sp->GetByteSize(), write_error); - if (m_persistent_variable_sp->m_flags & ExpressionVariable::EVKeepInTarget) - { - Error leak_error; - map.Leak(mem, leak_error); - m_persistent_variable_sp->m_flags &= ~ExpressionVariable::EVNeedsAllocation; - } + if (!write_error.Success()) { + err.SetErrorStringWithFormat( + "couldn't write %s to the target: %s", + m_persistent_variable_sp->GetName().AsCString(), + write_error.AsCString()); + return; + } + } - // Write the contents of the variable to the area. + void DestroyAllocation(IRMemoryMap &map, Error &err) { + Error deallocate_error; - Error write_error; + map.Free((lldb::addr_t)m_persistent_variable_sp->m_live_sp->GetValue() + .GetScalar() + .ULongLong(), + deallocate_error); - map.WriteMemory (mem, - m_persistent_variable_sp->GetValueBytes(), - m_persistent_variable_sp->GetByteSize(), - write_error); + m_persistent_variable_sp->m_live_sp.reset(); - if (!write_error.Success()) - { - err.SetErrorStringWithFormat ("couldn't write %s to the target: %s", m_persistent_variable_sp->GetName().AsCString(), - write_error.AsCString()); - return; - } + if (!deallocate_error.Success()) { + err.SetErrorStringWithFormat( + "couldn't deallocate memory for %s: %s", + m_persistent_variable_sp->GetName().GetCString(), + deallocate_error.AsCString()); } + } - void DestroyAllocation (IRMemoryMap &map, Error &err) - { - Error deallocate_error; - - map.Free((lldb::addr_t)m_persistent_variable_sp->m_live_sp->GetValue().GetScalar().ULongLong(), deallocate_error); + void Materialize(lldb::StackFrameSP &frame_sp, IRMemoryMap &map, + lldb::addr_t process_address, Error &err) override { + Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS)); - m_persistent_variable_sp->m_live_sp.reset(); + const lldb::addr_t load_addr = process_address + m_offset; - if (!deallocate_error.Success()) - { - err.SetErrorStringWithFormat ("couldn't deallocate memory for %s: %s", m_persistent_variable_sp->GetName().GetCString(), deallocate_error.AsCString()); - } + if (log) { + log->Printf("EntityPersistentVariable::Materialize [address = 0x%" PRIx64 + ", m_name = %s, m_flags = 0x%hx]", + (uint64_t)load_addr, + m_persistent_variable_sp->GetName().AsCString(), + m_persistent_variable_sp->m_flags); } - void Materialize(lldb::StackFrameSP &frame_sp, - IRMemoryMap &map, - lldb::addr_t process_address, - Error &err) override - { - Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); - - const lldb::addr_t load_addr = process_address + m_offset; + if (m_persistent_variable_sp->m_flags & + ExpressionVariable::EVNeedsAllocation) { + MakeAllocation(map, err); + m_persistent_variable_sp->m_flags |= + ExpressionVariable::EVIsLLDBAllocated; - if (log) - { - log->Printf("EntityPersistentVariable::Materialize [address = 0x%" PRIx64 ", m_name = %s, m_flags = 0x%hx]", - (uint64_t)load_addr, - m_persistent_variable_sp->GetName().AsCString(), - m_persistent_variable_sp->m_flags); - } + if (!err.Success()) + return; + } - if (m_persistent_variable_sp->m_flags & ExpressionVariable::EVNeedsAllocation) - { - MakeAllocation(map, err); - m_persistent_variable_sp->m_flags |= ExpressionVariable::EVIsLLDBAllocated; + if ((m_persistent_variable_sp->m_flags & + ExpressionVariable::EVIsProgramReference && + m_persistent_variable_sp->m_live_sp) || + m_persistent_variable_sp->m_flags & + ExpressionVariable::EVIsLLDBAllocated) { + Error write_error; + + map.WriteScalarToMemory( + load_addr, + m_persistent_variable_sp->m_live_sp->GetValue().GetScalar(), + map.GetAddressByteSize(), write_error); + + if (!write_error.Success()) { + err.SetErrorStringWithFormat( + "couldn't write the location of %s to memory: %s", + m_persistent_variable_sp->GetName().AsCString(), + write_error.AsCString()); + } + } else { + err.SetErrorStringWithFormat( + "no materialization happened for persistent variable %s", + m_persistent_variable_sp->GetName().AsCString()); + return; + } + } + + void Dematerialize(lldb::StackFrameSP &frame_sp, IRMemoryMap &map, + lldb::addr_t process_address, lldb::addr_t frame_top, + lldb::addr_t frame_bottom, Error &err) override { + Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS)); + + const lldb::addr_t load_addr = process_address + m_offset; + + if (log) { + log->Printf( + "EntityPersistentVariable::Dematerialize [address = 0x%" PRIx64 + ", m_name = %s, m_flags = 0x%hx]", + (uint64_t)process_address + m_offset, + m_persistent_variable_sp->GetName().AsCString(), + m_persistent_variable_sp->m_flags); + } - if (!err.Success()) - return; - } + if (m_delegate) { + m_delegate->DidDematerialize(m_persistent_variable_sp); + } - if ((m_persistent_variable_sp->m_flags & ExpressionVariable::EVIsProgramReference && m_persistent_variable_sp->m_live_sp) || - m_persistent_variable_sp->m_flags & ExpressionVariable::EVIsLLDBAllocated) - { - Error write_error; + if ((m_persistent_variable_sp->m_flags & + ExpressionVariable::EVIsLLDBAllocated) || + (m_persistent_variable_sp->m_flags & + ExpressionVariable::EVIsProgramReference)) { + if (m_persistent_variable_sp->m_flags & + ExpressionVariable::EVIsProgramReference && + !m_persistent_variable_sp->m_live_sp) { + // If the reference comes from the program, then the + // ClangExpressionVariable's + // live variable data hasn't been set up yet. Do this now. + + lldb::addr_t location; + Error read_error; - map.WriteScalarToMemory(load_addr, - m_persistent_variable_sp->m_live_sp->GetValue().GetScalar(), - map.GetAddressByteSize(), - write_error); + map.ReadPointerFromMemory(&location, load_addr, read_error); + + if (!read_error.Success()) { + err.SetErrorStringWithFormat( + "couldn't read the address of program-allocated variable %s: %s", + m_persistent_variable_sp->GetName().GetCString(), + read_error.AsCString()); + return; + } + + m_persistent_variable_sp->m_live_sp = ValueObjectConstResult::Create( + map.GetBestExecutionContextScope(), + m_persistent_variable_sp.get()->GetCompilerType(), + m_persistent_variable_sp->GetName(), location, eAddressTypeLoad, + m_persistent_variable_sp->GetByteSize()); + + if (frame_top != LLDB_INVALID_ADDRESS && + frame_bottom != LLDB_INVALID_ADDRESS && location >= frame_bottom && + location <= frame_top) { + // If the variable is resident in the stack frame created by the + // expression, + // then it cannot be relied upon to stay around. We treat it as + // needing + // reallocation. + m_persistent_variable_sp->m_flags |= + ExpressionVariable::EVIsLLDBAllocated; + m_persistent_variable_sp->m_flags |= + ExpressionVariable::EVNeedsAllocation; + m_persistent_variable_sp->m_flags |= + ExpressionVariable::EVNeedsFreezeDry; + m_persistent_variable_sp->m_flags &= + ~ExpressionVariable::EVIsProgramReference; + } + } + + lldb::addr_t mem = m_persistent_variable_sp->m_live_sp->GetValue() + .GetScalar() + .ULongLong(); + + if (!m_persistent_variable_sp->m_live_sp) { + err.SetErrorStringWithFormat( + "couldn't find the memory area used to store %s", + m_persistent_variable_sp->GetName().GetCString()); + return; + } - if (!write_error.Success()) - { - err.SetErrorStringWithFormat("couldn't write the location of %s to memory: %s", m_persistent_variable_sp->GetName().AsCString(), write_error.AsCString()); - } - } - else - { - err.SetErrorStringWithFormat("no materialization happened for persistent variable %s", m_persistent_variable_sp->GetName().AsCString()); - return; - } - } + if (m_persistent_variable_sp->m_live_sp->GetValue() + .GetValueAddressType() != eAddressTypeLoad) { + err.SetErrorStringWithFormat( + "the address of the memory area for %s is in an incorrect format", + m_persistent_variable_sp->GetName().GetCString()); + return; + } - void Dematerialize(lldb::StackFrameSP &frame_sp, - IRMemoryMap &map, - lldb::addr_t process_address, - lldb::addr_t frame_top, - lldb::addr_t frame_bottom, - Error &err) override - { - Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); + if (m_persistent_variable_sp->m_flags & + ExpressionVariable::EVNeedsFreezeDry || + m_persistent_variable_sp->m_flags & + ExpressionVariable::EVKeepInTarget) { + if (log) + log->Printf( + "Dematerializing %s from 0x%" PRIx64 " (size = %llu)", + m_persistent_variable_sp->GetName().GetCString(), (uint64_t)mem, + (unsigned long long)m_persistent_variable_sp->GetByteSize()); - const lldb::addr_t load_addr = process_address + m_offset; + // Read the contents of the spare memory area - if (log) - { - log->Printf("EntityPersistentVariable::Dematerialize [address = 0x%" PRIx64 ", m_name = %s, m_flags = 0x%hx]", - (uint64_t)process_address + m_offset, - m_persistent_variable_sp->GetName().AsCString(), - m_persistent_variable_sp->m_flags); - } + m_persistent_variable_sp->ValueUpdated(); - if (m_delegate) - { - m_delegate->DidDematerialize(m_persistent_variable_sp); - } + Error read_error; - if ((m_persistent_variable_sp->m_flags & ExpressionVariable::EVIsLLDBAllocated) || - (m_persistent_variable_sp->m_flags & ExpressionVariable::EVIsProgramReference)) - { - if (m_persistent_variable_sp->m_flags & ExpressionVariable::EVIsProgramReference && - !m_persistent_variable_sp->m_live_sp) - { - // If the reference comes from the program, then the ClangExpressionVariable's - // live variable data hasn't been set up yet. Do this now. - - lldb::addr_t location; - Error read_error; - - map.ReadPointerFromMemory(&location, load_addr, read_error); - - if (!read_error.Success()) - { - err.SetErrorStringWithFormat("couldn't read the address of program-allocated variable %s: %s", m_persistent_variable_sp->GetName().GetCString(), read_error.AsCString()); - return; - } - - m_persistent_variable_sp->m_live_sp = ValueObjectConstResult::Create (map.GetBestExecutionContextScope (), - m_persistent_variable_sp.get()->GetCompilerType(), - m_persistent_variable_sp->GetName(), - location, - eAddressTypeLoad, - m_persistent_variable_sp->GetByteSize()); - - if (frame_top != LLDB_INVALID_ADDRESS && - frame_bottom != LLDB_INVALID_ADDRESS && - location >= frame_bottom && - location <= frame_top) - { - // If the variable is resident in the stack frame created by the expression, - // then it cannot be relied upon to stay around. We treat it as needing - // reallocation. - m_persistent_variable_sp->m_flags |= ExpressionVariable::EVIsLLDBAllocated; - m_persistent_variable_sp->m_flags |= ExpressionVariable::EVNeedsAllocation; - m_persistent_variable_sp->m_flags |= ExpressionVariable::EVNeedsFreezeDry; - m_persistent_variable_sp->m_flags &= ~ExpressionVariable::EVIsProgramReference; - } - } - - lldb::addr_t mem = m_persistent_variable_sp->m_live_sp->GetValue().GetScalar().ULongLong(); - - if (!m_persistent_variable_sp->m_live_sp) - { - err.SetErrorStringWithFormat("couldn't find the memory area used to store %s", m_persistent_variable_sp->GetName().GetCString()); - return; - } - - if (m_persistent_variable_sp->m_live_sp->GetValue().GetValueAddressType() != eAddressTypeLoad) - { - err.SetErrorStringWithFormat("the address of the memory area for %s is in an incorrect format", m_persistent_variable_sp->GetName().GetCString()); - return; - } - - if (m_persistent_variable_sp->m_flags & ExpressionVariable::EVNeedsFreezeDry || - m_persistent_variable_sp->m_flags & ExpressionVariable::EVKeepInTarget) - { - if (log) - log->Printf("Dematerializing %s from 0x%" PRIx64 " (size = %llu)", m_persistent_variable_sp->GetName().GetCString(), (uint64_t)mem, (unsigned long long)m_persistent_variable_sp->GetByteSize()); - - // Read the contents of the spare memory area - - m_persistent_variable_sp->ValueUpdated (); - - Error read_error; - - map.ReadMemory(m_persistent_variable_sp->GetValueBytes(), - mem, - m_persistent_variable_sp->GetByteSize(), - read_error); - - if (!read_error.Success()) - { - err.SetErrorStringWithFormat ("couldn't read the contents of %s from memory: %s", m_persistent_variable_sp->GetName().GetCString(), read_error.AsCString()); - return; - } - - m_persistent_variable_sp->m_flags &= ~ExpressionVariable::EVNeedsFreezeDry; - } - } - else - { - err.SetErrorStringWithFormat("no dematerialization happened for persistent variable %s", m_persistent_variable_sp->GetName().AsCString()); - return; - } + map.ReadMemory(m_persistent_variable_sp->GetValueBytes(), mem, + m_persistent_variable_sp->GetByteSize(), read_error); + + if (!read_error.Success()) { + err.SetErrorStringWithFormat( + "couldn't read the contents of %s from memory: %s", + m_persistent_variable_sp->GetName().GetCString(), + read_error.AsCString()); + return; + } + + m_persistent_variable_sp->m_flags &= + ~ExpressionVariable::EVNeedsFreezeDry; + } + } else { + err.SetErrorStringWithFormat( + "no dematerialization happened for persistent variable %s", + m_persistent_variable_sp->GetName().AsCString()); + return; + } - lldb::ProcessSP process_sp = map.GetBestExecutionContextScope()->CalculateProcess(); - if (!process_sp || - !process_sp->CanJIT()) - { - // Allocations are not persistent so persistent variables cannot stay materialized. + lldb::ProcessSP process_sp = + map.GetBestExecutionContextScope()->CalculateProcess(); + if (!process_sp || !process_sp->CanJIT()) { + // Allocations are not persistent so persistent variables cannot stay + // materialized. - m_persistent_variable_sp->m_flags |= ExpressionVariable::EVNeedsAllocation; + m_persistent_variable_sp->m_flags |= + ExpressionVariable::EVNeedsAllocation; - DestroyAllocation(map, err); - if (!err.Success()) - return; - } - else if (m_persistent_variable_sp->m_flags & ExpressionVariable::EVNeedsAllocation && - !(m_persistent_variable_sp->m_flags & ExpressionVariable::EVKeepInTarget)) - { - DestroyAllocation(map, err); - if (!err.Success()) - return; - } + DestroyAllocation(map, err); + if (!err.Success()) + return; + } else if (m_persistent_variable_sp->m_flags & + ExpressionVariable::EVNeedsAllocation && + !(m_persistent_variable_sp->m_flags & + ExpressionVariable::EVKeepInTarget)) { + DestroyAllocation(map, err); + if (!err.Success()) + return; } + } - void DumpToLog(IRMemoryMap &map, lldb::addr_t process_address, Log *log) override - { - StreamString dump_stream; + void DumpToLog(IRMemoryMap &map, lldb::addr_t process_address, + Log *log) override { + StreamString dump_stream; - Error err; + Error err; - const lldb::addr_t load_addr = process_address + m_offset; + const lldb::addr_t load_addr = process_address + m_offset; - dump_stream.Printf("0x%" PRIx64 ": EntityPersistentVariable (%s)\n", load_addr, m_persistent_variable_sp->GetName().AsCString()); + dump_stream.Printf("0x%" PRIx64 ": EntityPersistentVariable (%s)\n", + load_addr, + m_persistent_variable_sp->GetName().AsCString()); - { - dump_stream.Printf("Pointer:\n"); + { + dump_stream.Printf("Pointer:\n"); - DataBufferHeap data (m_size, 0); + DataBufferHeap data(m_size, 0); - map.ReadMemory(data.GetBytes(), load_addr, m_size, err); + map.ReadMemory(data.GetBytes(), load_addr, m_size, err); - if (!err.Success()) - { - dump_stream.Printf(" <could not be read>\n"); - } - else - { - DataExtractor extractor (data.GetBytes(), data.GetByteSize(), map.GetByteOrder(), map.GetAddressByteSize()); + if (!err.Success()) { + dump_stream.Printf(" <could not be read>\n"); + } else { + DataExtractor extractor(data.GetBytes(), data.GetByteSize(), + map.GetByteOrder(), map.GetAddressByteSize()); - extractor.DumpHexBytes(&dump_stream, data.GetBytes(), data.GetByteSize(), 16, load_addr); + extractor.DumpHexBytes(&dump_stream, data.GetBytes(), + data.GetByteSize(), 16, load_addr); - dump_stream.PutChar('\n'); - } - } + dump_stream.PutChar('\n'); + } + } - { - dump_stream.Printf("Target:\n"); + { + dump_stream.Printf("Target:\n"); - lldb::addr_t target_address; + lldb::addr_t target_address; - map.ReadPointerFromMemory (&target_address, load_addr, err); + map.ReadPointerFromMemory(&target_address, load_addr, err); - if (!err.Success()) - { - dump_stream.Printf(" <could not be read>\n"); - } - else - { - DataBufferHeap data (m_persistent_variable_sp->GetByteSize(), 0); + if (!err.Success()) { + dump_stream.Printf(" <could not be read>\n"); + } else { + DataBufferHeap data(m_persistent_variable_sp->GetByteSize(), 0); - map.ReadMemory(data.GetBytes(), target_address, m_persistent_variable_sp->GetByteSize(), err); + map.ReadMemory(data.GetBytes(), target_address, + m_persistent_variable_sp->GetByteSize(), err); - if (!err.Success()) - { - dump_stream.Printf(" <could not be read>\n"); - } - else - { - DataExtractor extractor (data.GetBytes(), data.GetByteSize(), map.GetByteOrder(), map.GetAddressByteSize()); + if (!err.Success()) { + dump_stream.Printf(" <could not be read>\n"); + } else { + DataExtractor extractor(data.GetBytes(), data.GetByteSize(), + map.GetByteOrder(), map.GetAddressByteSize()); - extractor.DumpHexBytes(&dump_stream, data.GetBytes(), data.GetByteSize(), 16, target_address); + extractor.DumpHexBytes(&dump_stream, data.GetBytes(), + data.GetByteSize(), 16, target_address); - dump_stream.PutChar('\n'); - } - } + dump_stream.PutChar('\n'); } - - log->PutCString(dump_stream.GetData()); + } } - void Wipe(IRMemoryMap &map, lldb::addr_t process_address) override - { - } + log->PutString(dump_stream.GetString()); + } + + void Wipe(IRMemoryMap &map, lldb::addr_t process_address) override {} private: - lldb::ExpressionVariableSP m_persistent_variable_sp; - Materializer::PersistentVariableDelegate *m_delegate; + lldb::ExpressionVariableSP m_persistent_variable_sp; + Materializer::PersistentVariableDelegate *m_delegate; }; -uint32_t -Materializer::AddPersistentVariable (lldb::ExpressionVariableSP &persistent_variable_sp, - PersistentVariableDelegate *delegate, - Error &err) -{ - EntityVector::iterator iter = m_entities.insert(m_entities.end(), EntityUP()); - iter->reset (new EntityPersistentVariable (persistent_variable_sp, delegate)); - uint32_t ret = AddStructMember(**iter); - (*iter)->SetOffset(ret); - return ret; +uint32_t Materializer::AddPersistentVariable( + lldb::ExpressionVariableSP &persistent_variable_sp, + PersistentVariableDelegate *delegate, Error &err) { + EntityVector::iterator iter = m_entities.insert(m_entities.end(), EntityUP()); + iter->reset(new EntityPersistentVariable(persistent_variable_sp, delegate)); + uint32_t ret = AddStructMember(**iter); + (*iter)->SetOffset(ret); + return ret; } -class EntityVariable : public Materializer::Entity -{ +class EntityVariable : public Materializer::Entity { public: - EntityVariable (lldb::VariableSP &variable_sp) : - Entity(), - m_variable_sp(variable_sp), - m_is_reference(false), + EntityVariable(lldb::VariableSP &variable_sp) + : Entity(), m_variable_sp(variable_sp), m_is_reference(false), m_temporary_allocation(LLDB_INVALID_ADDRESS), - m_temporary_allocation_size(0) - { - // Hard-coding to maximum size of a pointer since all variables are materialized by reference - m_size = 8; - m_alignment = 8; - m_is_reference = m_variable_sp->GetType()->GetForwardCompilerType ().IsReferenceType(); + m_temporary_allocation_size(0) { + // Hard-coding to maximum size of a pointer since all variables are + // materialized by reference + m_size = 8; + m_alignment = 8; + m_is_reference = + m_variable_sp->GetType()->GetForwardCompilerType().IsReferenceType(); + } + + void Materialize(lldb::StackFrameSP &frame_sp, IRMemoryMap &map, + lldb::addr_t process_address, Error &err) override { + Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS)); + + const lldb::addr_t load_addr = process_address + m_offset; + if (log) { + log->Printf("EntityVariable::Materialize [address = 0x%" PRIx64 + ", m_variable_sp = %s]", + (uint64_t)load_addr, m_variable_sp->GetName().AsCString()); } - void Materialize(lldb::StackFrameSP &frame_sp, - IRMemoryMap &map, - lldb::addr_t process_address, - Error &err) override - { - Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); + ExecutionContextScope *scope = frame_sp.get(); - const lldb::addr_t load_addr = process_address + m_offset; - if (log) - { - log->Printf("EntityVariable::Materialize [address = 0x%" PRIx64 ", m_variable_sp = %s]", - (uint64_t)load_addr, - m_variable_sp->GetName().AsCString()); - } + if (!scope) + scope = map.GetBestExecutionContextScope(); - ExecutionContextScope *scope = frame_sp.get(); + lldb::ValueObjectSP valobj_sp = + ValueObjectVariable::Create(scope, m_variable_sp); - if (!scope) - scope = map.GetBestExecutionContextScope(); + if (!valobj_sp) { + err.SetErrorStringWithFormat( + "couldn't get a value object for variable %s", + m_variable_sp->GetName().AsCString()); + return; + } - lldb::ValueObjectSP valobj_sp = ValueObjectVariable::Create(scope, m_variable_sp); + Error valobj_error = valobj_sp->GetError(); - if (!valobj_sp) - { - err.SetErrorStringWithFormat("couldn't get a value object for variable %s", m_variable_sp->GetName().AsCString()); - return; - } + if (valobj_error.Fail()) { + err.SetErrorStringWithFormat("couldn't get the value of variable %s: %s", + m_variable_sp->GetName().AsCString(), + valobj_error.AsCString()); + return; + } + + if (m_is_reference) { + DataExtractor valobj_extractor; + Error extract_error; + valobj_sp->GetData(valobj_extractor, extract_error); - Error valobj_error = valobj_sp->GetError(); + if (!extract_error.Success()) { + err.SetErrorStringWithFormat( + "couldn't read contents of reference variable %s: %s", + m_variable_sp->GetName().AsCString(), extract_error.AsCString()); + return; + } + + lldb::offset_t offset = 0; + lldb::addr_t reference_addr = valobj_extractor.GetAddress(&offset); - if (valobj_error.Fail()) - { - err.SetErrorStringWithFormat("couldn't get the value of variable %s: %s", m_variable_sp->GetName().AsCString(), valobj_error.AsCString()); - return; + Error write_error; + map.WritePointerToMemory(load_addr, reference_addr, write_error); + + if (!write_error.Success()) { + err.SetErrorStringWithFormat("couldn't write the contents of reference " + "variable %s to memory: %s", + m_variable_sp->GetName().AsCString(), + write_error.AsCString()); + return; + } + } else { + AddressType address_type = eAddressTypeInvalid; + const bool scalar_is_load_address = false; + lldb::addr_t addr_of_valobj = + valobj_sp->GetAddressOf(scalar_is_load_address, &address_type); + if (addr_of_valobj != LLDB_INVALID_ADDRESS) { + Error write_error; + map.WritePointerToMemory(load_addr, addr_of_valobj, write_error); + + if (!write_error.Success()) { + err.SetErrorStringWithFormat( + "couldn't write the address of variable %s to memory: %s", + m_variable_sp->GetName().AsCString(), write_error.AsCString()); + return; } + } else { + DataExtractor data; + Error extract_error; + valobj_sp->GetData(data, extract_error); + if (!extract_error.Success()) { + err.SetErrorStringWithFormat("couldn't get the value of %s: %s", + m_variable_sp->GetName().AsCString(), + extract_error.AsCString()); + return; + } + + if (m_temporary_allocation != LLDB_INVALID_ADDRESS) { + err.SetErrorStringWithFormat( + "trying to create a temporary region for %s but one exists", + m_variable_sp->GetName().AsCString()); + return; + } + + if (data.GetByteSize() < m_variable_sp->GetType()->GetByteSize()) { + if (data.GetByteSize() == 0 && + m_variable_sp->LocationExpression().IsValid() == false) { + err.SetErrorStringWithFormat("the variable '%s' has no location, " + "it may have been optimized out", + m_variable_sp->GetName().AsCString()); + } else { + err.SetErrorStringWithFormat( + "size of variable %s (%" PRIu64 + ") is larger than the ValueObject's size (%" PRIu64 ")", + m_variable_sp->GetName().AsCString(), + m_variable_sp->GetType()->GetByteSize(), data.GetByteSize()); + } + return; + } + + size_t bit_align = + m_variable_sp->GetType()->GetLayoutCompilerType().GetTypeBitAlign(); + size_t byte_align = (bit_align + 7) / 8; + + if (!byte_align) + byte_align = 1; + + Error alloc_error; + const bool zero_memory = false; + + m_temporary_allocation = map.Malloc( + data.GetByteSize(), byte_align, + lldb::ePermissionsReadable | lldb::ePermissionsWritable, + IRMemoryMap::eAllocationPolicyMirror, zero_memory, alloc_error); + + m_temporary_allocation_size = data.GetByteSize(); + + m_original_data.reset( + new DataBufferHeap(data.GetDataStart(), data.GetByteSize())); - if (m_is_reference) - { - DataExtractor valobj_extractor; - Error extract_error; - valobj_sp->GetData(valobj_extractor, extract_error); - - if (!extract_error.Success()) - { - err.SetErrorStringWithFormat("couldn't read contents of reference variable %s: %s", m_variable_sp->GetName().AsCString(), extract_error.AsCString()); - return; - } - - lldb::offset_t offset = 0; - lldb::addr_t reference_addr = valobj_extractor.GetAddress(&offset); - - Error write_error; - map.WritePointerToMemory(load_addr, reference_addr, write_error); - - if (!write_error.Success()) - { - err.SetErrorStringWithFormat("couldn't write the contents of reference variable %s to memory: %s", m_variable_sp->GetName().AsCString(), write_error.AsCString()); - return; - } + if (!alloc_error.Success()) { + err.SetErrorStringWithFormat( + "couldn't allocate a temporary region for %s: %s", + m_variable_sp->GetName().AsCString(), alloc_error.AsCString()); + return; } - else - { - AddressType address_type = eAddressTypeInvalid; - const bool scalar_is_load_address = false; - lldb::addr_t addr_of_valobj = valobj_sp->GetAddressOf(scalar_is_load_address, &address_type); - if (addr_of_valobj != LLDB_INVALID_ADDRESS) - { - Error write_error; - map.WritePointerToMemory(load_addr, addr_of_valobj, write_error); - - if (!write_error.Success()) - { - err.SetErrorStringWithFormat("couldn't write the address of variable %s to memory: %s", m_variable_sp->GetName().AsCString(), write_error.AsCString()); - return; - } - } - else - { - DataExtractor data; - Error extract_error; - valobj_sp->GetData(data, extract_error); - if (!extract_error.Success()) - { - err.SetErrorStringWithFormat("couldn't get the value of %s: %s", m_variable_sp->GetName().AsCString(), extract_error.AsCString()); - return; - } - - if (m_temporary_allocation != LLDB_INVALID_ADDRESS) - { - err.SetErrorStringWithFormat("trying to create a temporary region for %s but one exists", m_variable_sp->GetName().AsCString()); - return; - } - - if (data.GetByteSize() < m_variable_sp->GetType()->GetByteSize()) - { - if (data.GetByteSize() == 0 && m_variable_sp->LocationExpression().IsValid() == false) - { - err.SetErrorStringWithFormat("the variable '%s' has no location, it may have been optimized out", m_variable_sp->GetName().AsCString()); - } - else - { - err.SetErrorStringWithFormat("size of variable %s (%" PRIu64 ") is larger than the ValueObject's size (%" PRIu64 ")", - m_variable_sp->GetName().AsCString(), - m_variable_sp->GetType()->GetByteSize(), - data.GetByteSize()); - } - return; - } - - size_t bit_align = m_variable_sp->GetType()->GetLayoutCompilerType ().GetTypeBitAlign(); - size_t byte_align = (bit_align + 7) / 8; - - if (!byte_align) - byte_align = 1; - - Error alloc_error; - const bool zero_memory = false; - - m_temporary_allocation = map.Malloc(data.GetByteSize(), - byte_align, - lldb::ePermissionsReadable | lldb::ePermissionsWritable, - IRMemoryMap::eAllocationPolicyMirror, - zero_memory, - alloc_error); - - m_temporary_allocation_size = data.GetByteSize(); - - m_original_data.reset(new DataBufferHeap(data.GetDataStart(), data.GetByteSize())); - - if (!alloc_error.Success()) - { - err.SetErrorStringWithFormat("couldn't allocate a temporary region for %s: %s", m_variable_sp->GetName().AsCString(), alloc_error.AsCString()); - return; - } - - Error write_error; - - map.WriteMemory(m_temporary_allocation, data.GetDataStart(), data.GetByteSize(), write_error); - - if (!write_error.Success()) - { - err.SetErrorStringWithFormat("couldn't write to the temporary region for %s: %s", m_variable_sp->GetName().AsCString(), write_error.AsCString()); - return; - } - - Error pointer_write_error; - - map.WritePointerToMemory(load_addr, m_temporary_allocation, pointer_write_error); - - if (!pointer_write_error.Success()) - { - err.SetErrorStringWithFormat("couldn't write the address of the temporary region for %s: %s", m_variable_sp->GetName().AsCString(), pointer_write_error.AsCString()); - } - } + + Error write_error; + + map.WriteMemory(m_temporary_allocation, data.GetDataStart(), + data.GetByteSize(), write_error); + + if (!write_error.Success()) { + err.SetErrorStringWithFormat( + "couldn't write to the temporary region for %s: %s", + m_variable_sp->GetName().AsCString(), write_error.AsCString()); + return; } - } - void Dematerialize(lldb::StackFrameSP &frame_sp, - IRMemoryMap &map, - lldb::addr_t process_address, - lldb::addr_t frame_top, - lldb::addr_t frame_bottom, - Error &err) override - { - Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); + Error pointer_write_error; - const lldb::addr_t load_addr = process_address + m_offset; - if (log) - { - log->Printf("EntityVariable::Dematerialize [address = 0x%" PRIx64 ", m_variable_sp = %s]", - (uint64_t)load_addr, - m_variable_sp->GetName().AsCString()); + map.WritePointerToMemory(load_addr, m_temporary_allocation, + pointer_write_error); + + if (!pointer_write_error.Success()) { + err.SetErrorStringWithFormat( + "couldn't write the address of the temporary region for %s: %s", + m_variable_sp->GetName().AsCString(), + pointer_write_error.AsCString()); } + } + } + } + + void Dematerialize(lldb::StackFrameSP &frame_sp, IRMemoryMap &map, + lldb::addr_t process_address, lldb::addr_t frame_top, + lldb::addr_t frame_bottom, Error &err) override { + Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS)); + + const lldb::addr_t load_addr = process_address + m_offset; + if (log) { + log->Printf("EntityVariable::Dematerialize [address = 0x%" PRIx64 + ", m_variable_sp = %s]", + (uint64_t)load_addr, m_variable_sp->GetName().AsCString()); + } - if (m_temporary_allocation != LLDB_INVALID_ADDRESS) - { - ExecutionContextScope *scope = frame_sp.get(); + if (m_temporary_allocation != LLDB_INVALID_ADDRESS) { + ExecutionContextScope *scope = frame_sp.get(); - if (!scope) - scope = map.GetBestExecutionContextScope(); + if (!scope) + scope = map.GetBestExecutionContextScope(); - lldb::ValueObjectSP valobj_sp = ValueObjectVariable::Create(scope, m_variable_sp); + lldb::ValueObjectSP valobj_sp = + ValueObjectVariable::Create(scope, m_variable_sp); - if (!valobj_sp) - { - err.SetErrorStringWithFormat("couldn't get a value object for variable %s", m_variable_sp->GetName().AsCString()); - return; - } + if (!valobj_sp) { + err.SetErrorStringWithFormat( + "couldn't get a value object for variable %s", + m_variable_sp->GetName().AsCString()); + return; + } - lldb_private::DataExtractor data; + lldb_private::DataExtractor data; - Error extract_error; + Error extract_error; - map.GetMemoryData(data, m_temporary_allocation, valobj_sp->GetByteSize(), extract_error); + map.GetMemoryData(data, m_temporary_allocation, valobj_sp->GetByteSize(), + extract_error); - if (!extract_error.Success()) - { - err.SetErrorStringWithFormat("couldn't get the data for variable %s", m_variable_sp->GetName().AsCString()); - return; - } + if (!extract_error.Success()) { + err.SetErrorStringWithFormat("couldn't get the data for variable %s", + m_variable_sp->GetName().AsCString()); + return; + } - bool actually_write = true; + bool actually_write = true; - if (m_original_data) - { - if ((data.GetByteSize() == m_original_data->GetByteSize()) && - !memcmp(m_original_data->GetBytes(), data.GetDataStart(), data.GetByteSize())) - { - actually_write = false; - } - } + if (m_original_data) { + if ((data.GetByteSize() == m_original_data->GetByteSize()) && + !memcmp(m_original_data->GetBytes(), data.GetDataStart(), + data.GetByteSize())) { + actually_write = false; + } + } - Error set_error; + Error set_error; - if (actually_write) - { - valobj_sp->SetData(data, set_error); + if (actually_write) { + valobj_sp->SetData(data, set_error); - if (!set_error.Success()) - { - err.SetErrorStringWithFormat("couldn't write the new contents of %s back into the variable", m_variable_sp->GetName().AsCString()); - return; - } - } + if (!set_error.Success()) { + err.SetErrorStringWithFormat( + "couldn't write the new contents of %s back into the variable", + m_variable_sp->GetName().AsCString()); + return; + } + } - Error free_error; + Error free_error; - map.Free(m_temporary_allocation, free_error); + map.Free(m_temporary_allocation, free_error); - if (!free_error.Success()) - { - err.SetErrorStringWithFormat("couldn't free the temporary region for %s: %s", m_variable_sp->GetName().AsCString(), free_error.AsCString()); - return; - } + if (!free_error.Success()) { + err.SetErrorStringWithFormat( + "couldn't free the temporary region for %s: %s", + m_variable_sp->GetName().AsCString(), free_error.AsCString()); + return; + } - m_original_data.reset(); - m_temporary_allocation = LLDB_INVALID_ADDRESS; - m_temporary_allocation_size = 0; - } + m_original_data.reset(); + m_temporary_allocation = LLDB_INVALID_ADDRESS; + m_temporary_allocation_size = 0; } + } - void DumpToLog(IRMemoryMap &map, lldb::addr_t process_address, Log *log) override - { - StreamString dump_stream; - - const lldb::addr_t load_addr = process_address + m_offset; - dump_stream.Printf("0x%" PRIx64 ": EntityVariable\n", load_addr); + void DumpToLog(IRMemoryMap &map, lldb::addr_t process_address, + Log *log) override { + StreamString dump_stream; - Error err; + const lldb::addr_t load_addr = process_address + m_offset; + dump_stream.Printf("0x%" PRIx64 ": EntityVariable\n", load_addr); - lldb::addr_t ptr = LLDB_INVALID_ADDRESS; + Error err; - { - dump_stream.Printf("Pointer:\n"); + lldb::addr_t ptr = LLDB_INVALID_ADDRESS; - DataBufferHeap data (m_size, 0); + { + dump_stream.Printf("Pointer:\n"); - map.ReadMemory(data.GetBytes(), load_addr, m_size, err); + DataBufferHeap data(m_size, 0); - if (!err.Success()) - { - dump_stream.Printf(" <could not be read>\n"); - } - else - { - DataExtractor extractor (data.GetBytes(), data.GetByteSize(), map.GetByteOrder(), map.GetAddressByteSize()); + map.ReadMemory(data.GetBytes(), load_addr, m_size, err); - extractor.DumpHexBytes(&dump_stream, data.GetBytes(), data.GetByteSize(), 16, load_addr); + if (!err.Success()) { + dump_stream.Printf(" <could not be read>\n"); + } else { + DataExtractor extractor(data.GetBytes(), data.GetByteSize(), + map.GetByteOrder(), map.GetAddressByteSize()); - lldb::offset_t offset; + extractor.DumpHexBytes(&dump_stream, data.GetBytes(), + data.GetByteSize(), 16, load_addr); - ptr = extractor.GetPointer(&offset); + lldb::offset_t offset; - dump_stream.PutChar('\n'); - } - } + ptr = extractor.GetPointer(&offset); - if (m_temporary_allocation == LLDB_INVALID_ADDRESS) - { - dump_stream.Printf("Points to process memory:\n"); - } - else - { - dump_stream.Printf("Temporary allocation:\n"); - } + dump_stream.PutChar('\n'); + } + } - if (ptr == LLDB_INVALID_ADDRESS) - { - dump_stream.Printf(" <could not be be found>\n"); - } - else - { - DataBufferHeap data (m_temporary_allocation_size, 0); + if (m_temporary_allocation == LLDB_INVALID_ADDRESS) { + dump_stream.Printf("Points to process memory:\n"); + } else { + dump_stream.Printf("Temporary allocation:\n"); + } - map.ReadMemory(data.GetBytes(), m_temporary_allocation, m_temporary_allocation_size, err); + if (ptr == LLDB_INVALID_ADDRESS) { + dump_stream.Printf(" <could not be be found>\n"); + } else { + DataBufferHeap data(m_temporary_allocation_size, 0); - if (!err.Success()) - { - dump_stream.Printf(" <could not be read>\n"); - } - else - { - DataExtractor extractor (data.GetBytes(), data.GetByteSize(), map.GetByteOrder(), map.GetAddressByteSize()); + map.ReadMemory(data.GetBytes(), m_temporary_allocation, + m_temporary_allocation_size, err); - extractor.DumpHexBytes(&dump_stream, data.GetBytes(), data.GetByteSize(), 16, load_addr); + if (!err.Success()) { + dump_stream.Printf(" <could not be read>\n"); + } else { + DataExtractor extractor(data.GetBytes(), data.GetByteSize(), + map.GetByteOrder(), map.GetAddressByteSize()); - dump_stream.PutChar('\n'); - } - } + extractor.DumpHexBytes(&dump_stream, data.GetBytes(), + data.GetByteSize(), 16, load_addr); - log->PutCString(dump_stream.GetData()); + dump_stream.PutChar('\n'); + } } - void Wipe(IRMemoryMap &map, lldb::addr_t process_address) override - { - if (m_temporary_allocation != LLDB_INVALID_ADDRESS) - { - Error free_error; + log->PutString(dump_stream.GetString()); + } - map.Free(m_temporary_allocation, free_error); + void Wipe(IRMemoryMap &map, lldb::addr_t process_address) override { + if (m_temporary_allocation != LLDB_INVALID_ADDRESS) { + Error free_error; - m_temporary_allocation = LLDB_INVALID_ADDRESS; - m_temporary_allocation_size = 0; - } + map.Free(m_temporary_allocation, free_error); + m_temporary_allocation = LLDB_INVALID_ADDRESS; + m_temporary_allocation_size = 0; } + } private: - lldb::VariableSP m_variable_sp; - bool m_is_reference; - lldb::addr_t m_temporary_allocation; - size_t m_temporary_allocation_size; - lldb::DataBufferSP m_original_data; + lldb::VariableSP m_variable_sp; + bool m_is_reference; + lldb::addr_t m_temporary_allocation; + size_t m_temporary_allocation_size; + lldb::DataBufferSP m_original_data; }; -uint32_t -Materializer::AddVariable (lldb::VariableSP &variable_sp, Error &err) -{ - EntityVector::iterator iter = m_entities.insert(m_entities.end(), EntityUP()); - iter->reset (new EntityVariable (variable_sp)); - uint32_t ret = AddStructMember(**iter); - (*iter)->SetOffset(ret); - return ret; +uint32_t Materializer::AddVariable(lldb::VariableSP &variable_sp, Error &err) { + EntityVector::iterator iter = m_entities.insert(m_entities.end(), EntityUP()); + iter->reset(new EntityVariable(variable_sp)); + uint32_t ret = AddStructMember(**iter); + (*iter)->SetOffset(ret); + return ret; } -class EntityResultVariable : public Materializer::Entity -{ +class EntityResultVariable : public Materializer::Entity { public: - EntityResultVariable (const CompilerType &type, - bool is_program_reference, - bool keep_in_memory, - Materializer::PersistentVariableDelegate *delegate) : - Entity(), - m_type(type), - m_is_program_reference(is_program_reference), + EntityResultVariable(const CompilerType &type, bool is_program_reference, + bool keep_in_memory, + Materializer::PersistentVariableDelegate *delegate) + : Entity(), m_type(type), m_is_program_reference(is_program_reference), m_keep_in_memory(keep_in_memory), m_temporary_allocation(LLDB_INVALID_ADDRESS), - m_temporary_allocation_size(0), - m_delegate(delegate) - { - // Hard-coding to maximum size of a pointer since all results are materialized by reference - m_size = 8; - m_alignment = 8; - } + m_temporary_allocation_size(0), m_delegate(delegate) { + // Hard-coding to maximum size of a pointer since all results are + // materialized by reference + m_size = 8; + m_alignment = 8; + } + + void Materialize(lldb::StackFrameSP &frame_sp, IRMemoryMap &map, + lldb::addr_t process_address, Error &err) override { + if (!m_is_program_reference) { + if (m_temporary_allocation != LLDB_INVALID_ADDRESS) { + err.SetErrorString("Trying to create a temporary region for the result " + "but one exists"); + return; + } - void Materialize(lldb::StackFrameSP &frame_sp, - IRMemoryMap &map, - lldb::addr_t process_address, - Error &err) override - { - if (!m_is_program_reference) - { - if (m_temporary_allocation != LLDB_INVALID_ADDRESS) - { - err.SetErrorString("Trying to create a temporary region for the result but one exists"); - return; - } - - const lldb::addr_t load_addr = process_address + m_offset; - - size_t byte_size = m_type.GetByteSize(nullptr); - size_t bit_align = m_type.GetTypeBitAlign(); - size_t byte_align = (bit_align + 7) / 8; - - if (!byte_align) - byte_align = 1; - - Error alloc_error; - const bool zero_memory = true; - - m_temporary_allocation = map.Malloc(byte_size, - byte_align, - lldb::ePermissionsReadable | lldb::ePermissionsWritable, - IRMemoryMap::eAllocationPolicyMirror, - zero_memory, - alloc_error); - m_temporary_allocation_size = byte_size; - - if (!alloc_error.Success()) - { - err.SetErrorStringWithFormat("couldn't allocate a temporary region for the result: %s", alloc_error.AsCString()); - return; - } - - Error pointer_write_error; - - map.WritePointerToMemory(load_addr, m_temporary_allocation, pointer_write_error); - - if (!pointer_write_error.Success()) - { - err.SetErrorStringWithFormat("couldn't write the address of the temporary region for the result: %s", pointer_write_error.AsCString()); - } - } - } + const lldb::addr_t load_addr = process_address + m_offset; - void Dematerialize(lldb::StackFrameSP &frame_sp, - IRMemoryMap &map, - lldb::addr_t process_address, - lldb::addr_t frame_top, - lldb::addr_t frame_bottom, - Error &err) override - { - err.Clear(); + ExecutionContextScope *exe_scope = map.GetBestExecutionContextScope(); - ExecutionContextScope *exe_scope = map.GetBestExecutionContextScope(); + size_t byte_size = m_type.GetByteSize(exe_scope); + size_t bit_align = m_type.GetTypeBitAlign(); + size_t byte_align = (bit_align + 7) / 8; - if (!exe_scope) - { - err.SetErrorString("Couldn't dematerialize a result variable: invalid execution context scope"); - return; - } + if (!byte_align) + byte_align = 1; - lldb::addr_t address; - Error read_error; - const lldb::addr_t load_addr = process_address + m_offset; + Error alloc_error; + const bool zero_memory = true; - map.ReadPointerFromMemory (&address, load_addr, read_error); + m_temporary_allocation = map.Malloc( + byte_size, byte_align, + lldb::ePermissionsReadable | lldb::ePermissionsWritable, + IRMemoryMap::eAllocationPolicyMirror, zero_memory, alloc_error); + m_temporary_allocation_size = byte_size; - if (!read_error.Success()) - { - err.SetErrorString("Couldn't dematerialize a result variable: couldn't read its address"); - return; - } + if (!alloc_error.Success()) { + err.SetErrorStringWithFormat( + "couldn't allocate a temporary region for the result: %s", + alloc_error.AsCString()); + return; + } - lldb::TargetSP target_sp = exe_scope->CalculateTarget(); + Error pointer_write_error; - if (!target_sp) - { - err.SetErrorString("Couldn't dematerialize a result variable: no target"); - return; - } + map.WritePointerToMemory(load_addr, m_temporary_allocation, + pointer_write_error); - Error type_system_error; - TypeSystem *type_system = target_sp->GetScratchTypeSystemForLanguage(&type_system_error, m_type.GetMinimumLanguage()); + if (!pointer_write_error.Success()) { + err.SetErrorStringWithFormat("couldn't write the address of the " + "temporary region for the result: %s", + pointer_write_error.AsCString()); + } + } + } - if (!type_system) - { - err.SetErrorStringWithFormat("Couldn't dematerialize a result variable: couldn't get the corresponding type system: %s", type_system_error.AsCString()); - return; - } + void Dematerialize(lldb::StackFrameSP &frame_sp, IRMemoryMap &map, + lldb::addr_t process_address, lldb::addr_t frame_top, + lldb::addr_t frame_bottom, Error &err) override { + err.Clear(); - PersistentExpressionState *persistent_state = type_system->GetPersistentExpressionState(); + ExecutionContextScope *exe_scope = map.GetBestExecutionContextScope(); - if (!persistent_state) - { - err.SetErrorString("Couldn't dematerialize a result variable: corresponding type system doesn't handle persistent variables"); - return; - } + if (!exe_scope) { + err.SetErrorString("Couldn't dematerialize a result variable: invalid " + "execution context scope"); + return; + } - ConstString name = m_delegate ? m_delegate->GetName() : persistent_state->GetNextPersistentVariableName(); + lldb::addr_t address; + Error read_error; + const lldb::addr_t load_addr = process_address + m_offset; - lldb::ExpressionVariableSP ret = persistent_state->CreatePersistentVariable(exe_scope, - name, - m_type, - map.GetByteOrder(), - map.GetAddressByteSize()); + map.ReadPointerFromMemory(&address, load_addr, read_error); - if (!ret) - { - err.SetErrorStringWithFormat("couldn't dematerialize a result variable: failed to make persistent variable %s", name.AsCString()); - return; - } + if (!read_error.Success()) { + err.SetErrorString("Couldn't dematerialize a result variable: couldn't " + "read its address"); + return; + } - lldb::ProcessSP process_sp = map.GetBestExecutionContextScope()->CalculateProcess(); + lldb::TargetSP target_sp = exe_scope->CalculateTarget(); - if (m_delegate) - { - m_delegate->DidDematerialize(ret); - } + if (!target_sp) { + err.SetErrorString("Couldn't dematerialize a result variable: no target"); + return; + } - bool can_persist = (m_is_program_reference && process_sp && process_sp->CanJIT() && !(address >= frame_bottom && address < frame_top)); + Error type_system_error; + TypeSystem *type_system = target_sp->GetScratchTypeSystemForLanguage( + &type_system_error, m_type.GetMinimumLanguage()); - if (can_persist && m_keep_in_memory) - { - ret->m_live_sp = ValueObjectConstResult::Create(exe_scope, - m_type, - name, - address, - eAddressTypeLoad, - map.GetAddressByteSize()); - } + if (!type_system) { + err.SetErrorStringWithFormat("Couldn't dematerialize a result variable: " + "couldn't get the corresponding type " + "system: %s", + type_system_error.AsCString()); + return; + } - ret->ValueUpdated(); + PersistentExpressionState *persistent_state = + type_system->GetPersistentExpressionState(); - const size_t pvar_byte_size = ret->GetByteSize(); - uint8_t *pvar_data = ret->GetValueBytes(); + if (!persistent_state) { + err.SetErrorString("Couldn't dematerialize a result variable: " + "corresponding type system doesn't handle persistent " + "variables"); + return; + } - map.ReadMemory(pvar_data, address, pvar_byte_size, read_error); + ConstString name = m_delegate + ? m_delegate->GetName() + : persistent_state->GetNextPersistentVariableName(); - if (!read_error.Success()) - { - err.SetErrorString("Couldn't dematerialize a result variable: couldn't read its memory"); - return; - } + lldb::ExpressionVariableSP ret = persistent_state->CreatePersistentVariable( + exe_scope, name, m_type, map.GetByteOrder(), map.GetAddressByteSize()); - if (!can_persist || !m_keep_in_memory) - { - ret->m_flags |= ExpressionVariable::EVNeedsAllocation; + if (!ret) { + err.SetErrorStringWithFormat("couldn't dematerialize a result variable: " + "failed to make persistent variable %s", + name.AsCString()); + return; + } - if (m_temporary_allocation != LLDB_INVALID_ADDRESS) - { - Error free_error; - map.Free(m_temporary_allocation, free_error); - } - } - else - { - ret->m_flags |= ExpressionVariable::EVIsLLDBAllocated; - } + lldb::ProcessSP process_sp = + map.GetBestExecutionContextScope()->CalculateProcess(); - m_temporary_allocation = LLDB_INVALID_ADDRESS; - m_temporary_allocation_size = 0; + if (m_delegate) { + m_delegate->DidDematerialize(ret); } - void DumpToLog(IRMemoryMap &map, lldb::addr_t process_address, Log *log) override - { - StreamString dump_stream; + bool can_persist = + (m_is_program_reference && process_sp && process_sp->CanJIT() && + !(address >= frame_bottom && address < frame_top)); - const lldb::addr_t load_addr = process_address + m_offset; + if (can_persist && m_keep_in_memory) { + ret->m_live_sp = ValueObjectConstResult::Create(exe_scope, m_type, name, + address, eAddressTypeLoad, + map.GetAddressByteSize()); + } - dump_stream.Printf("0x%" PRIx64 ": EntityResultVariable\n", load_addr); + ret->ValueUpdated(); - Error err; + const size_t pvar_byte_size = ret->GetByteSize(); + uint8_t *pvar_data = ret->GetValueBytes(); - lldb::addr_t ptr = LLDB_INVALID_ADDRESS; + map.ReadMemory(pvar_data, address, pvar_byte_size, read_error); - { - dump_stream.Printf("Pointer:\n"); + if (!read_error.Success()) { + err.SetErrorString( + "Couldn't dematerialize a result variable: couldn't read its memory"); + return; + } - DataBufferHeap data (m_size, 0); + if (!can_persist || !m_keep_in_memory) { + ret->m_flags |= ExpressionVariable::EVNeedsAllocation; - map.ReadMemory(data.GetBytes(), load_addr, m_size, err); + if (m_temporary_allocation != LLDB_INVALID_ADDRESS) { + Error free_error; + map.Free(m_temporary_allocation, free_error); + } + } else { + ret->m_flags |= ExpressionVariable::EVIsLLDBAllocated; + } - if (!err.Success()) - { - dump_stream.Printf(" <could not be read>\n"); - } - else - { - DataExtractor extractor (data.GetBytes(), data.GetByteSize(), map.GetByteOrder(), map.GetAddressByteSize()); + m_temporary_allocation = LLDB_INVALID_ADDRESS; + m_temporary_allocation_size = 0; + } - extractor.DumpHexBytes(&dump_stream, data.GetBytes(), data.GetByteSize(), 16, load_addr); + void DumpToLog(IRMemoryMap &map, lldb::addr_t process_address, + Log *log) override { + StreamString dump_stream; - lldb::offset_t offset; + const lldb::addr_t load_addr = process_address + m_offset; - ptr = extractor.GetPointer(&offset); + dump_stream.Printf("0x%" PRIx64 ": EntityResultVariable\n", load_addr); - dump_stream.PutChar('\n'); - } - } + Error err; - if (m_temporary_allocation == LLDB_INVALID_ADDRESS) - { - dump_stream.Printf("Points to process memory:\n"); - } - else - { - dump_stream.Printf("Temporary allocation:\n"); - } + lldb::addr_t ptr = LLDB_INVALID_ADDRESS; - if (ptr == LLDB_INVALID_ADDRESS) - { - dump_stream.Printf(" <could not be be found>\n"); - } - else - { - DataBufferHeap data (m_temporary_allocation_size, 0); + { + dump_stream.Printf("Pointer:\n"); - map.ReadMemory(data.GetBytes(), m_temporary_allocation, m_temporary_allocation_size, err); + DataBufferHeap data(m_size, 0); - if (!err.Success()) - { - dump_stream.Printf(" <could not be read>\n"); - } - else - { - DataExtractor extractor (data.GetBytes(), data.GetByteSize(), map.GetByteOrder(), map.GetAddressByteSize()); + map.ReadMemory(data.GetBytes(), load_addr, m_size, err); - extractor.DumpHexBytes(&dump_stream, data.GetBytes(), data.GetByteSize(), 16, load_addr); + if (!err.Success()) { + dump_stream.Printf(" <could not be read>\n"); + } else { + DataExtractor extractor(data.GetBytes(), data.GetByteSize(), + map.GetByteOrder(), map.GetAddressByteSize()); - dump_stream.PutChar('\n'); - } - } + extractor.DumpHexBytes(&dump_stream, data.GetBytes(), + data.GetByteSize(), 16, load_addr); + + lldb::offset_t offset; - log->PutCString(dump_stream.GetData()); + ptr = extractor.GetPointer(&offset); + + dump_stream.PutChar('\n'); + } } - void Wipe(IRMemoryMap &map, lldb::addr_t process_address) override - { - if (!m_keep_in_memory && m_temporary_allocation != LLDB_INVALID_ADDRESS) - { - Error free_error; + if (m_temporary_allocation == LLDB_INVALID_ADDRESS) { + dump_stream.Printf("Points to process memory:\n"); + } else { + dump_stream.Printf("Temporary allocation:\n"); + } - map.Free(m_temporary_allocation, free_error); - } + if (ptr == LLDB_INVALID_ADDRESS) { + dump_stream.Printf(" <could not be be found>\n"); + } else { + DataBufferHeap data(m_temporary_allocation_size, 0); + + map.ReadMemory(data.GetBytes(), m_temporary_allocation, + m_temporary_allocation_size, err); - m_temporary_allocation = LLDB_INVALID_ADDRESS; - m_temporary_allocation_size = 0; + if (!err.Success()) { + dump_stream.Printf(" <could not be read>\n"); + } else { + DataExtractor extractor(data.GetBytes(), data.GetByteSize(), + map.GetByteOrder(), map.GetAddressByteSize()); + + extractor.DumpHexBytes(&dump_stream, data.GetBytes(), + data.GetByteSize(), 16, load_addr); + + dump_stream.PutChar('\n'); + } + } + + log->PutString(dump_stream.GetString()); + } + + void Wipe(IRMemoryMap &map, lldb::addr_t process_address) override { + if (!m_keep_in_memory && m_temporary_allocation != LLDB_INVALID_ADDRESS) { + Error free_error; + + map.Free(m_temporary_allocation, free_error); } + m_temporary_allocation = LLDB_INVALID_ADDRESS; + m_temporary_allocation_size = 0; + } + private: - CompilerType m_type; - bool m_is_program_reference; - bool m_keep_in_memory; + CompilerType m_type; + bool m_is_program_reference; + bool m_keep_in_memory; - lldb::addr_t m_temporary_allocation; - size_t m_temporary_allocation_size; - Materializer::PersistentVariableDelegate *m_delegate; + lldb::addr_t m_temporary_allocation; + size_t m_temporary_allocation_size; + Materializer::PersistentVariableDelegate *m_delegate; }; -uint32_t -Materializer::AddResultVariable (const CompilerType &type, - bool is_program_reference, - bool keep_in_memory, - PersistentVariableDelegate *delegate, - Error &err) -{ - EntityVector::iterator iter = m_entities.insert(m_entities.end(), EntityUP()); - iter->reset (new EntityResultVariable (type, is_program_reference, keep_in_memory, delegate)); - uint32_t ret = AddStructMember(**iter); - (*iter)->SetOffset(ret); - return ret; +uint32_t Materializer::AddResultVariable(const CompilerType &type, + bool is_program_reference, + bool keep_in_memory, + PersistentVariableDelegate *delegate, + Error &err) { + EntityVector::iterator iter = m_entities.insert(m_entities.end(), EntityUP()); + iter->reset(new EntityResultVariable(type, is_program_reference, + keep_in_memory, delegate)); + uint32_t ret = AddStructMember(**iter); + (*iter)->SetOffset(ret); + return ret; } -class EntitySymbol : public Materializer::Entity -{ +class EntitySymbol : public Materializer::Entity { public: - EntitySymbol (const Symbol &symbol) : - Entity(), - m_symbol(symbol) - { - // Hard-coding to maximum size of a symbol - m_size = 8; - m_alignment = 8; + EntitySymbol(const Symbol &symbol) : Entity(), m_symbol(symbol) { + // Hard-coding to maximum size of a symbol + m_size = 8; + m_alignment = 8; + } + + void Materialize(lldb::StackFrameSP &frame_sp, IRMemoryMap &map, + lldb::addr_t process_address, Error &err) override { + Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS)); + + const lldb::addr_t load_addr = process_address + m_offset; + + if (log) { + log->Printf("EntitySymbol::Materialize [address = 0x%" PRIx64 + ", m_symbol = %s]", + (uint64_t)load_addr, m_symbol.GetName().AsCString()); } - void Materialize(lldb::StackFrameSP &frame_sp, - IRMemoryMap &map, - lldb::addr_t process_address, - Error &err) override - { - Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); - - const lldb::addr_t load_addr = process_address + m_offset; + const Address sym_address = m_symbol.GetAddress(); - if (log) - { - log->Printf("EntitySymbol::Materialize [address = 0x%" PRIx64 ", m_symbol = %s]", - (uint64_t)load_addr, - m_symbol.GetName().AsCString()); - } + ExecutionContextScope *exe_scope = map.GetBestExecutionContextScope(); - const Address sym_address = m_symbol.GetAddress(); + lldb::TargetSP target_sp; - ExecutionContextScope *exe_scope = map.GetBestExecutionContextScope(); + if (exe_scope) + target_sp = map.GetBestExecutionContextScope()->CalculateTarget(); - lldb::TargetSP target_sp; - - if (exe_scope) - target_sp = map.GetBestExecutionContextScope()->CalculateTarget(); - - if (!target_sp) - { - err.SetErrorStringWithFormat("couldn't resolve symbol %s because there is no target", m_symbol.GetName().AsCString()); - return; - } + if (!target_sp) { + err.SetErrorStringWithFormat( + "couldn't resolve symbol %s because there is no target", + m_symbol.GetName().AsCString()); + return; + } - lldb::addr_t resolved_address = sym_address.GetLoadAddress(target_sp.get()); + lldb::addr_t resolved_address = sym_address.GetLoadAddress(target_sp.get()); - if (resolved_address == LLDB_INVALID_ADDRESS) - resolved_address = sym_address.GetFileAddress(); + if (resolved_address == LLDB_INVALID_ADDRESS) + resolved_address = sym_address.GetFileAddress(); - Error pointer_write_error; + Error pointer_write_error; - map.WritePointerToMemory(load_addr, resolved_address, pointer_write_error); + map.WritePointerToMemory(load_addr, resolved_address, pointer_write_error); - if (!pointer_write_error.Success()) - { - err.SetErrorStringWithFormat("couldn't write the address of symbol %s: %s", m_symbol.GetName().AsCString(), pointer_write_error.AsCString()); - return; - } + if (!pointer_write_error.Success()) { + err.SetErrorStringWithFormat( + "couldn't write the address of symbol %s: %s", + m_symbol.GetName().AsCString(), pointer_write_error.AsCString()); + return; } + } - void Dematerialize(lldb::StackFrameSP &frame_sp, - IRMemoryMap &map, - lldb::addr_t process_address, - lldb::addr_t frame_top, - lldb::addr_t frame_bottom, - Error &err) override - { - Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); + void Dematerialize(lldb::StackFrameSP &frame_sp, IRMemoryMap &map, + lldb::addr_t process_address, lldb::addr_t frame_top, + lldb::addr_t frame_bottom, Error &err) override { + Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS)); - const lldb::addr_t load_addr = process_address + m_offset; - - if (log) - { - log->Printf("EntitySymbol::Dematerialize [address = 0x%" PRIx64 ", m_symbol = %s]", - (uint64_t)load_addr, - m_symbol.GetName().AsCString()); - } + const lldb::addr_t load_addr = process_address + m_offset; - // no work needs to be done + if (log) { + log->Printf("EntitySymbol::Dematerialize [address = 0x%" PRIx64 + ", m_symbol = %s]", + (uint64_t)load_addr, m_symbol.GetName().AsCString()); } - void DumpToLog(IRMemoryMap &map, lldb::addr_t process_address, Log *log) override - { - StreamString dump_stream; + // no work needs to be done + } - Error err; + void DumpToLog(IRMemoryMap &map, lldb::addr_t process_address, + Log *log) override { + StreamString dump_stream; - const lldb::addr_t load_addr = process_address + m_offset; + Error err; - dump_stream.Printf("0x%" PRIx64 ": EntitySymbol (%s)\n", load_addr, m_symbol.GetName().AsCString()); + const lldb::addr_t load_addr = process_address + m_offset; - { - dump_stream.Printf("Pointer:\n"); + dump_stream.Printf("0x%" PRIx64 ": EntitySymbol (%s)\n", load_addr, + m_symbol.GetName().AsCString()); - DataBufferHeap data (m_size, 0); + { + dump_stream.Printf("Pointer:\n"); - map.ReadMemory(data.GetBytes(), load_addr, m_size, err); + DataBufferHeap data(m_size, 0); - if (!err.Success()) - { - dump_stream.Printf(" <could not be read>\n"); - } - else - { - DataExtractor extractor (data.GetBytes(), data.GetByteSize(), map.GetByteOrder(), map.GetAddressByteSize()); + map.ReadMemory(data.GetBytes(), load_addr, m_size, err); - extractor.DumpHexBytes(&dump_stream, data.GetBytes(), data.GetByteSize(), 16, load_addr); + if (!err.Success()) { + dump_stream.Printf(" <could not be read>\n"); + } else { + DataExtractor extractor(data.GetBytes(), data.GetByteSize(), + map.GetByteOrder(), map.GetAddressByteSize()); - dump_stream.PutChar('\n'); - } - } + extractor.DumpHexBytes(&dump_stream, data.GetBytes(), + data.GetByteSize(), 16, load_addr); - log->PutCString(dump_stream.GetData()); + dump_stream.PutChar('\n'); + } } - void Wipe(IRMemoryMap &map, lldb::addr_t process_address) override - { - } + log->PutString(dump_stream.GetString()); + } + + void Wipe(IRMemoryMap &map, lldb::addr_t process_address) override {} private: - Symbol m_symbol; + Symbol m_symbol; }; -uint32_t -Materializer::AddSymbol (const Symbol &symbol_sp, Error &err) -{ - EntityVector::iterator iter = m_entities.insert(m_entities.end(), EntityUP()); - iter->reset (new EntitySymbol (symbol_sp)); - uint32_t ret = AddStructMember(**iter); - (*iter)->SetOffset(ret); - return ret; +uint32_t Materializer::AddSymbol(const Symbol &symbol_sp, Error &err) { + EntityVector::iterator iter = m_entities.insert(m_entities.end(), EntityUP()); + iter->reset(new EntitySymbol(symbol_sp)); + uint32_t ret = AddStructMember(**iter); + (*iter)->SetOffset(ret); + return ret; } -class EntityRegister : public Materializer::Entity -{ +class EntityRegister : public Materializer::Entity { public: - EntityRegister (const RegisterInfo ®ister_info) : - Entity(), - m_register_info(register_info) - { - // Hard-coding alignment conservatively - m_size = m_register_info.byte_size; - m_alignment = m_register_info.byte_size; + EntityRegister(const RegisterInfo ®ister_info) + : Entity(), m_register_info(register_info) { + // Hard-coding alignment conservatively + m_size = m_register_info.byte_size; + m_alignment = m_register_info.byte_size; + } + + void Materialize(lldb::StackFrameSP &frame_sp, IRMemoryMap &map, + lldb::addr_t process_address, Error &err) override { + Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS)); + + const lldb::addr_t load_addr = process_address + m_offset; + + if (log) { + log->Printf("EntityRegister::Materialize [address = 0x%" PRIx64 + ", m_register_info = %s]", + (uint64_t)load_addr, m_register_info.name); } - void Materialize(lldb::StackFrameSP &frame_sp, - IRMemoryMap &map, - lldb::addr_t process_address, - Error &err) override - { - Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); - - const lldb::addr_t load_addr = process_address + m_offset; + RegisterValue reg_value; - if (log) - { - log->Printf("EntityRegister::Materialize [address = 0x%" PRIx64 ", m_register_info = %s]", - (uint64_t)load_addr, - m_register_info.name); - } + if (!frame_sp.get()) { + err.SetErrorStringWithFormat( + "couldn't materialize register %s without a stack frame", + m_register_info.name); + return; + } - RegisterValue reg_value; + lldb::RegisterContextSP reg_context_sp = frame_sp->GetRegisterContext(); - if (!frame_sp.get()) - { - err.SetErrorStringWithFormat("couldn't materialize register %s without a stack frame", m_register_info.name); - return; - } + if (!reg_context_sp->ReadRegister(&m_register_info, reg_value)) { + err.SetErrorStringWithFormat("couldn't read the value of register %s", + m_register_info.name); + return; + } - lldb::RegisterContextSP reg_context_sp = frame_sp->GetRegisterContext(); + DataExtractor register_data; - if (!reg_context_sp->ReadRegister(&m_register_info, reg_value)) - { - err.SetErrorStringWithFormat("couldn't read the value of register %s", m_register_info.name); - return; - } + if (!reg_value.GetData(register_data)) { + err.SetErrorStringWithFormat("couldn't get the data for register %s", + m_register_info.name); + return; + } - DataExtractor register_data; + if (register_data.GetByteSize() != m_register_info.byte_size) { + err.SetErrorStringWithFormat( + "data for register %s had size %llu but we expected %llu", + m_register_info.name, (unsigned long long)register_data.GetByteSize(), + (unsigned long long)m_register_info.byte_size); + return; + } - if (!reg_value.GetData(register_data)) - { - err.SetErrorStringWithFormat("couldn't get the data for register %s", m_register_info.name); - return; - } + m_register_contents.reset(new DataBufferHeap(register_data.GetDataStart(), + register_data.GetByteSize())); - if (register_data.GetByteSize() != m_register_info.byte_size) - { - err.SetErrorStringWithFormat("data for register %s had size %llu but we expected %llu", m_register_info.name, (unsigned long long)register_data.GetByteSize(), (unsigned long long)m_register_info.byte_size); - return; - } + Error write_error; - m_register_contents.reset(new DataBufferHeap(register_data.GetDataStart(), register_data.GetByteSize())); + map.WriteMemory(load_addr, register_data.GetDataStart(), + register_data.GetByteSize(), write_error); - Error write_error; - - map.WriteMemory(load_addr, register_data.GetDataStart(), register_data.GetByteSize(), write_error); - - if (!write_error.Success()) - { - err.SetErrorStringWithFormat("couldn't write the contents of register %s: %s", m_register_info.name, write_error.AsCString()); - return; - } + if (!write_error.Success()) { + err.SetErrorStringWithFormat( + "couldn't write the contents of register %s: %s", + m_register_info.name, write_error.AsCString()); + return; } + } - void Dematerialize(lldb::StackFrameSP &frame_sp, - IRMemoryMap &map, - lldb::addr_t process_address, - lldb::addr_t frame_top, - lldb::addr_t frame_bottom, - Error &err) override - { - Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); + void Dematerialize(lldb::StackFrameSP &frame_sp, IRMemoryMap &map, + lldb::addr_t process_address, lldb::addr_t frame_top, + lldb::addr_t frame_bottom, Error &err) override { + Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS)); - const lldb::addr_t load_addr = process_address + m_offset; + const lldb::addr_t load_addr = process_address + m_offset; - if (log) - { - log->Printf("EntityRegister::Dematerialize [address = 0x%" PRIx64 ", m_register_info = %s]", - (uint64_t)load_addr, - m_register_info.name); - } + if (log) { + log->Printf("EntityRegister::Dematerialize [address = 0x%" PRIx64 + ", m_register_info = %s]", + (uint64_t)load_addr, m_register_info.name); + } - Error extract_error; + Error extract_error; - DataExtractor register_data; + DataExtractor register_data; - if (!frame_sp.get()) - { - err.SetErrorStringWithFormat("couldn't dematerialize register %s without a stack frame", m_register_info.name); - return; - } + if (!frame_sp.get()) { + err.SetErrorStringWithFormat( + "couldn't dematerialize register %s without a stack frame", + m_register_info.name); + return; + } - lldb::RegisterContextSP reg_context_sp = frame_sp->GetRegisterContext(); + lldb::RegisterContextSP reg_context_sp = frame_sp->GetRegisterContext(); - map.GetMemoryData(register_data, load_addr, m_register_info.byte_size, extract_error); + map.GetMemoryData(register_data, load_addr, m_register_info.byte_size, + extract_error); - if (!extract_error.Success()) - { - err.SetErrorStringWithFormat("couldn't get the data for register %s: %s", m_register_info.name, extract_error.AsCString()); - return; - } + if (!extract_error.Success()) { + err.SetErrorStringWithFormat("couldn't get the data for register %s: %s", + m_register_info.name, + extract_error.AsCString()); + return; + } - if (!memcmp(register_data.GetDataStart(), m_register_contents->GetBytes(), register_data.GetByteSize())) - { - // No write required, and in particular we avoid errors if the register wasn't writable + if (!memcmp(register_data.GetDataStart(), m_register_contents->GetBytes(), + register_data.GetByteSize())) { + // No write required, and in particular we avoid errors if the register + // wasn't writable - m_register_contents.reset(); - return; - } + m_register_contents.reset(); + return; + } - m_register_contents.reset(); + m_register_contents.reset(); - RegisterValue register_value (const_cast<uint8_t*>(register_data.GetDataStart()), register_data.GetByteSize(), register_data.GetByteOrder()); + RegisterValue register_value( + const_cast<uint8_t *>(register_data.GetDataStart()), + register_data.GetByteSize(), register_data.GetByteOrder()); - if (!reg_context_sp->WriteRegister(&m_register_info, register_value)) - { - err.SetErrorStringWithFormat("couldn't write the value of register %s", m_register_info.name); - return; - } + if (!reg_context_sp->WriteRegister(&m_register_info, register_value)) { + err.SetErrorStringWithFormat("couldn't write the value of register %s", + m_register_info.name); + return; } + } - void DumpToLog(IRMemoryMap &map, lldb::addr_t process_address, Log *log) override - { - StreamString dump_stream; - - Error err; - - const lldb::addr_t load_addr = process_address + m_offset; + void DumpToLog(IRMemoryMap &map, lldb::addr_t process_address, + Log *log) override { + StreamString dump_stream; + Error err; - dump_stream.Printf("0x%" PRIx64 ": EntityRegister (%s)\n", load_addr, m_register_info.name); + const lldb::addr_t load_addr = process_address + m_offset; - { - dump_stream.Printf("Value:\n"); + dump_stream.Printf("0x%" PRIx64 ": EntityRegister (%s)\n", load_addr, + m_register_info.name); - DataBufferHeap data (m_size, 0); + { + dump_stream.Printf("Value:\n"); - map.ReadMemory(data.GetBytes(), load_addr, m_size, err); + DataBufferHeap data(m_size, 0); - if (!err.Success()) - { - dump_stream.Printf(" <could not be read>\n"); - } - else - { - DataExtractor extractor (data.GetBytes(), data.GetByteSize(), map.GetByteOrder(), map.GetAddressByteSize()); + map.ReadMemory(data.GetBytes(), load_addr, m_size, err); - extractor.DumpHexBytes(&dump_stream, data.GetBytes(), data.GetByteSize(), 16, load_addr); + if (!err.Success()) { + dump_stream.Printf(" <could not be read>\n"); + } else { + DataExtractor extractor(data.GetBytes(), data.GetByteSize(), + map.GetByteOrder(), map.GetAddressByteSize()); - dump_stream.PutChar('\n'); - } - } + extractor.DumpHexBytes(&dump_stream, data.GetBytes(), + data.GetByteSize(), 16, load_addr); - log->PutCString(dump_stream.GetData()); + dump_stream.PutChar('\n'); + } } - void Wipe(IRMemoryMap &map, lldb::addr_t process_address) override - { - } + log->PutString(dump_stream.GetString()); + } + + void Wipe(IRMemoryMap &map, lldb::addr_t process_address) override {} private: - RegisterInfo m_register_info; - lldb::DataBufferSP m_register_contents; + RegisterInfo m_register_info; + lldb::DataBufferSP m_register_contents; }; -uint32_t -Materializer::AddRegister (const RegisterInfo ®ister_info, Error &err) -{ - EntityVector::iterator iter = m_entities.insert(m_entities.end(), EntityUP()); - iter->reset (new EntityRegister (register_info)); - uint32_t ret = AddStructMember(**iter); - (*iter)->SetOffset(ret); - return ret; +uint32_t Materializer::AddRegister(const RegisterInfo ®ister_info, + Error &err) { + EntityVector::iterator iter = m_entities.insert(m_entities.end(), EntityUP()); + iter->reset(new EntityRegister(register_info)); + uint32_t ret = AddStructMember(**iter); + (*iter)->SetOffset(ret); + return ret; } -Materializer::Materializer () : - m_dematerializer_wp(), - m_current_offset(0), - m_struct_alignment(8) -{ -} +Materializer::Materializer() + : m_dematerializer_wp(), m_current_offset(0), m_struct_alignment(8) {} -Materializer::~Materializer () -{ - DematerializerSP dematerializer_sp = m_dematerializer_wp.lock(); +Materializer::~Materializer() { + DematerializerSP dematerializer_sp = m_dematerializer_wp.lock(); - if (dematerializer_sp) - dematerializer_sp->Wipe(); + if (dematerializer_sp) + dematerializer_sp->Wipe(); } Materializer::DematerializerSP -Materializer::Materialize (lldb::StackFrameSP &frame_sp, IRMemoryMap &map, lldb::addr_t process_address, Error &error) -{ - ExecutionContextScope *exe_scope = frame_sp.get(); +Materializer::Materialize(lldb::StackFrameSP &frame_sp, IRMemoryMap &map, + lldb::addr_t process_address, Error &error) { + ExecutionContextScope *exe_scope = frame_sp.get(); - if (!exe_scope) - exe_scope = map.GetBestExecutionContextScope(); + if (!exe_scope) + exe_scope = map.GetBestExecutionContextScope(); - DematerializerSP dematerializer_sp = m_dematerializer_wp.lock(); + DematerializerSP dematerializer_sp = m_dematerializer_wp.lock(); - if (dematerializer_sp) - { - error.SetErrorToGenericError(); - error.SetErrorString("Couldn't materialize: already materialized"); - } + if (dematerializer_sp) { + error.SetErrorToGenericError(); + error.SetErrorString("Couldn't materialize: already materialized"); + } - DematerializerSP ret(new Dematerializer(*this, frame_sp, map, process_address)); + DematerializerSP ret( + new Dematerializer(*this, frame_sp, map, process_address)); - if (!exe_scope) - { - error.SetErrorToGenericError(); - error.SetErrorString("Couldn't materialize: target doesn't exist"); - } + if (!exe_scope) { + error.SetErrorToGenericError(); + error.SetErrorString("Couldn't materialize: target doesn't exist"); + } - for (EntityUP &entity_up : m_entities) - { - entity_up->Materialize(frame_sp, map, process_address, error); + for (EntityUP &entity_up : m_entities) { + entity_up->Materialize(frame_sp, map, process_address, error); - if (!error.Success()) - return DematerializerSP(); - } + if (!error.Success()) + return DematerializerSP(); + } - if (Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)) - { - log->Printf("Materializer::Materialize (frame_sp = %p, process_address = 0x%" PRIx64 ") materialized:", - static_cast<void*>(frame_sp.get()), process_address); - for (EntityUP &entity_up : m_entities) - entity_up->DumpToLog(map, process_address, log); - } + if (Log *log = + lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS)) { + log->Printf( + "Materializer::Materialize (frame_sp = %p, process_address = 0x%" PRIx64 + ") materialized:", + static_cast<void *>(frame_sp.get()), process_address); + for (EntityUP &entity_up : m_entities) + entity_up->DumpToLog(map, process_address, log); + } - m_dematerializer_wp = ret; + m_dematerializer_wp = ret; - return ret; + return ret; } -void -Materializer::Dematerializer::Dematerialize (Error &error, - lldb::addr_t frame_bottom, - lldb::addr_t frame_top) -{ - lldb::StackFrameSP frame_sp; - - lldb::ThreadSP thread_sp = m_thread_wp.lock(); - if (thread_sp) - frame_sp = thread_sp->GetFrameWithStackID(m_stack_id); - - ExecutionContextScope *exe_scope = m_map->GetBestExecutionContextScope(); - - if (!IsValid()) - { - error.SetErrorToGenericError(); - error.SetErrorString("Couldn't dematerialize: invalid dematerializer"); - } - - if (!exe_scope) - { - error.SetErrorToGenericError(); - error.SetErrorString("Couldn't dematerialize: target is gone"); +void Materializer::Dematerializer::Dematerialize(Error &error, + lldb::addr_t frame_bottom, + lldb::addr_t frame_top) { + lldb::StackFrameSP frame_sp; + + lldb::ThreadSP thread_sp = m_thread_wp.lock(); + if (thread_sp) + frame_sp = thread_sp->GetFrameWithStackID(m_stack_id); + + ExecutionContextScope *exe_scope = m_map->GetBestExecutionContextScope(); + + if (!IsValid()) { + error.SetErrorToGenericError(); + error.SetErrorString("Couldn't dematerialize: invalid dematerializer"); + } + + if (!exe_scope) { + error.SetErrorToGenericError(); + error.SetErrorString("Couldn't dematerialize: target is gone"); + } else { + if (Log *log = + lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS)) { + log->Printf("Materializer::Dematerialize (frame_sp = %p, process_address " + "= 0x%" PRIx64 ") about to dematerialize:", + static_cast<void *>(frame_sp.get()), m_process_address); + for (EntityUP &entity_up : m_materializer->m_entities) + entity_up->DumpToLog(*m_map, m_process_address, log); } - else - { - if (Log *log =lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)) - { - log->Printf("Materializer::Dematerialize (frame_sp = %p, process_address = 0x%" PRIx64 ") about to dematerialize:", - static_cast<void*>(frame_sp.get()), m_process_address); - for (EntityUP &entity_up : m_materializer->m_entities) - entity_up->DumpToLog(*m_map, m_process_address, log); - } - for (EntityUP &entity_up : m_materializer->m_entities) - { - entity_up->Dematerialize (frame_sp, *m_map, m_process_address, frame_top, frame_bottom, error); + for (EntityUP &entity_up : m_materializer->m_entities) { + entity_up->Dematerialize(frame_sp, *m_map, m_process_address, frame_top, + frame_bottom, error); - if (!error.Success()) - break; - } + if (!error.Success()) + break; } + } - Wipe(); + Wipe(); } -void -Materializer::Dematerializer::Wipe () -{ - if (!IsValid()) - return; +void Materializer::Dematerializer::Wipe() { + if (!IsValid()) + return; - for (EntityUP &entity_up : m_materializer->m_entities) - { - entity_up->Wipe (*m_map, m_process_address); - } + for (EntityUP &entity_up : m_materializer->m_entities) { + entity_up->Wipe(*m_map, m_process_address); + } - m_materializer = nullptr; - m_map = nullptr; - m_process_address = LLDB_INVALID_ADDRESS; + m_materializer = nullptr; + m_map = nullptr; + m_process_address = LLDB_INVALID_ADDRESS; } -Materializer::PersistentVariableDelegate::~PersistentVariableDelegate() = default; +Materializer::PersistentVariableDelegate::~PersistentVariableDelegate() = + default; diff --git a/source/Expression/REPL.cpp b/source/Expression/REPL.cpp index 30f256002fc8..e404537562b7 100644 --- a/source/Expression/REPL.cpp +++ b/source/Expression/REPL.cpp @@ -11,11 +11,11 @@ // C++ Includes // Other libraries and framework includes // Project includes +#include "lldb/Expression/REPL.h" #include "lldb/Core/Debugger.h" #include "lldb/Core/PluginManager.h" #include "lldb/Core/StreamFile.h" #include "lldb/Expression/ExpressionVariable.h" -#include "lldb/Expression/REPL.h" #include "lldb/Expression/UserExpression.h" #include "lldb/Host/HostInfo.h" #include "lldb/Interpreter/CommandInterpreter.h" @@ -26,625 +26,560 @@ using namespace lldb_private; -REPL::REPL(LLVMCastKind kind, Target &target) : - m_target(target), - m_kind(kind) -{ - // Make sure all option values have sane defaults - Debugger &debugger = m_target.GetDebugger(); - CommandInterpreter &ci = debugger.GetCommandInterpreter(); - m_format_options.OptionParsingStarting(ci); - m_varobj_options.OptionParsingStarting(ci); - m_command_options.OptionParsingStarting(ci); - - // Default certain settings for REPL regardless of the global settings. - m_command_options.unwind_on_error = false; - m_command_options.ignore_breakpoints = false; - m_command_options.debug = false; +REPL::REPL(LLVMCastKind kind, Target &target) : m_target(target), m_kind(kind) { + // Make sure all option values have sane defaults + Debugger &debugger = m_target.GetDebugger(); + auto exe_ctx = debugger.GetCommandInterpreter().GetExecutionContext(); + m_format_options.OptionParsingStarting(&exe_ctx); + m_varobj_options.OptionParsingStarting(&exe_ctx); + m_command_options.OptionParsingStarting(&exe_ctx); + + // Default certain settings for REPL regardless of the global settings. + m_command_options.unwind_on_error = false; + m_command_options.ignore_breakpoints = false; + m_command_options.debug = false; } REPL::~REPL() = default; -lldb::REPLSP -REPL::Create(Error &err, lldb::LanguageType language, Debugger *debugger, Target *target, const char *repl_options) -{ - uint32_t idx = 0; - lldb::REPLSP ret; - - while (REPLCreateInstance create_instance = PluginManager::GetREPLCreateCallbackAtIndex(idx++)) - { - ret = (*create_instance)(err, language, debugger, target, repl_options); - if (ret) - { - break; - } +lldb::REPLSP REPL::Create(Error &err, lldb::LanguageType language, + Debugger *debugger, Target *target, + const char *repl_options) { + uint32_t idx = 0; + lldb::REPLSP ret; + + while (REPLCreateInstance create_instance = + PluginManager::GetREPLCreateCallbackAtIndex(idx++)) { + ret = (*create_instance)(err, language, debugger, target, repl_options); + if (ret) { + break; } - - return ret; + } + + return ret; } -std::string -REPL::GetSourcePath() -{ - ConstString file_basename = GetSourceFileBasename(); - - FileSpec tmpdir_file_spec; - if (HostInfo::GetLLDBPath (lldb::ePathTypeLLDBTempSystemDir, tmpdir_file_spec)) - { - tmpdir_file_spec.GetFilename().SetCString(file_basename.AsCString()); - m_repl_source_path = tmpdir_file_spec.GetPath(); - } - else - { - tmpdir_file_spec = FileSpec("/tmp", false); - tmpdir_file_spec.AppendPathComponent(file_basename.AsCString()); - } - - return tmpdir_file_spec.GetPath(); +std::string REPL::GetSourcePath() { + ConstString file_basename = GetSourceFileBasename(); + + FileSpec tmpdir_file_spec; + if (HostInfo::GetLLDBPath(lldb::ePathTypeLLDBTempSystemDir, + tmpdir_file_spec)) { + tmpdir_file_spec.GetFilename().SetCString(file_basename.AsCString()); + m_repl_source_path = tmpdir_file_spec.GetPath(); + } else { + tmpdir_file_spec = FileSpec("/tmp", false); + tmpdir_file_spec.AppendPathComponent(file_basename.AsCString()); + } + + return tmpdir_file_spec.GetPath(); } -lldb::IOHandlerSP -REPL::GetIOHandler() -{ - if (!m_io_handler_sp) - { - Debugger &debugger = m_target.GetDebugger(); - m_io_handler_sp.reset (new IOHandlerEditline (debugger, - IOHandler::Type::REPL, - "lldb-repl", // Name of input reader for history - "> ", // prompt - ". ", // Continuation prompt - true, // Multi-line - true, // The REPL prompt is always colored - 1, // Line number - *this)); - - // Don't exit if CTRL+C is pressed - static_cast<IOHandlerEditline *>(m_io_handler_sp.get())->SetInterruptExits(false); - - if (m_io_handler_sp->GetIsInteractive() && m_io_handler_sp->GetIsRealTerminal()) - { - m_indent_str.assign (debugger.GetTabSize(), ' '); - m_enable_auto_indent = debugger.GetAutoIndent(); - } - else - { - m_indent_str.clear(); - m_enable_auto_indent = false; - } - +lldb::IOHandlerSP REPL::GetIOHandler() { + if (!m_io_handler_sp) { + Debugger &debugger = m_target.GetDebugger(); + m_io_handler_sp.reset( + new IOHandlerEditline(debugger, IOHandler::Type::REPL, + "lldb-repl", // Name of input reader for history + llvm::StringRef("> "), // prompt + llvm::StringRef(". "), // Continuation prompt + true, // Multi-line + true, // The REPL prompt is always colored + 1, // Line number + *this)); + + // Don't exit if CTRL+C is pressed + static_cast<IOHandlerEditline *>(m_io_handler_sp.get()) + ->SetInterruptExits(false); + + if (m_io_handler_sp->GetIsInteractive() && + m_io_handler_sp->GetIsRealTerminal()) { + m_indent_str.assign(debugger.GetTabSize(), ' '); + m_enable_auto_indent = debugger.GetAutoIndent(); + } else { + m_indent_str.clear(); + m_enable_auto_indent = false; } - return m_io_handler_sp; + } + return m_io_handler_sp; } -void -REPL::IOHandlerActivated (IOHandler &io_handler) -{ - lldb::ProcessSP process_sp = m_target.GetProcessSP(); - if (process_sp && process_sp->IsAlive()) - return; - lldb::StreamFileSP error_sp(io_handler.GetErrorStreamFile()); - error_sp->Printf("REPL requires a running target process.\n"); - io_handler.SetIsDone(true); +void REPL::IOHandlerActivated(IOHandler &io_handler) { + lldb::ProcessSP process_sp = m_target.GetProcessSP(); + if (process_sp && process_sp->IsAlive()) + return; + lldb::StreamFileSP error_sp(io_handler.GetErrorStreamFile()); + error_sp->Printf("REPL requires a running target process.\n"); + io_handler.SetIsDone(true); } -bool -REPL::IOHandlerInterrupt (IOHandler &io_handler) -{ - return false; -} +bool REPL::IOHandlerInterrupt(IOHandler &io_handler) { return false; } -void -REPL::IOHandlerInputInterrupted (IOHandler &io_handler, - std::string &line) -{ +void REPL::IOHandlerInputInterrupted(IOHandler &io_handler, std::string &line) { } -const char * -REPL::IOHandlerGetFixIndentationCharacters() -{ - return (m_enable_auto_indent ? GetAutoIndentCharacters() : nullptr); +const char *REPL::IOHandlerGetFixIndentationCharacters() { + return (m_enable_auto_indent ? GetAutoIndentCharacters() : nullptr); } -ConstString -REPL::IOHandlerGetControlSequence (char ch) -{ - if (ch == 'd') - return ConstString(":quit\n"); - return ConstString(); +ConstString REPL::IOHandlerGetControlSequence(char ch) { + if (ch == 'd') + return ConstString(":quit\n"); + return ConstString(); } -const char * -REPL::IOHandlerGetCommandPrefix () -{ - return ":"; -} +const char *REPL::IOHandlerGetCommandPrefix() { return ":"; } -const char * -REPL::IOHandlerGetHelpPrologue () -{ - return "\nThe REPL (Read-Eval-Print-Loop) acts like an interpreter. " - "Valid statements, expressions, and declarations are immediately compiled and executed.\n\n" - "The complete set of LLDB debugging commands are also available as described below. Commands " - "must be prefixed with a colon at the REPL prompt (:quit for example.) Typing just a colon " - "followed by return will switch to the LLDB prompt.\n\n"; +const char *REPL::IOHandlerGetHelpPrologue() { + return "\nThe REPL (Read-Eval-Print-Loop) acts like an interpreter. " + "Valid statements, expressions, and declarations are immediately " + "compiled and executed.\n\n" + "The complete set of LLDB debugging commands are also available as " + "described below. Commands " + "must be prefixed with a colon at the REPL prompt (:quit for " + "example.) Typing just a colon " + "followed by return will switch to the LLDB prompt.\n\n"; } -bool -REPL::IOHandlerIsInputComplete (IOHandler &io_handler, - StringList &lines) -{ - // Check for meta command - const size_t num_lines = lines.GetSize(); - if (num_lines == 1) - { - const char *first_line = lines.GetStringAtIndex(0); - if (first_line[0] == ':') - return true; // Meta command is a single line where that starts with ':' - } - - // Check if REPL input is done - std::string source_string (lines.CopyList()); - return SourceIsComplete(source_string); +bool REPL::IOHandlerIsInputComplete(IOHandler &io_handler, StringList &lines) { + // Check for meta command + const size_t num_lines = lines.GetSize(); + if (num_lines == 1) { + const char *first_line = lines.GetStringAtIndex(0); + if (first_line[0] == ':') + return true; // Meta command is a single line where that starts with ':' + } + + // Check if REPL input is done + std::string source_string(lines.CopyList()); + return SourceIsComplete(source_string); } -int -REPL::CalculateActualIndentation (const StringList &lines) -{ - std::string last_line = lines[lines.GetSize() - 1]; +int REPL::CalculateActualIndentation(const StringList &lines) { + std::string last_line = lines[lines.GetSize() - 1]; - int actual_indent = 0; - for (char &ch : last_line) - { - if (ch != ' ') break; - ++actual_indent; - } - - return actual_indent; + int actual_indent = 0; + for (char &ch : last_line) { + if (ch != ' ') + break; + ++actual_indent; + } + + return actual_indent; } -int -REPL::IOHandlerFixIndentation (IOHandler &io_handler, - const StringList &lines, - int cursor_position) -{ - if (!m_enable_auto_indent) return 0; - - if (!lines.GetSize()) - { - return 0; - } - - int tab_size = io_handler.GetDebugger().GetTabSize(); - - lldb::offset_t desired_indent = GetDesiredIndentation(lines, - cursor_position, - tab_size); - - int actual_indent = REPL::CalculateActualIndentation(lines); - - if (desired_indent == LLDB_INVALID_OFFSET) - return 0; - - return (int)desired_indent - actual_indent; +int REPL::IOHandlerFixIndentation(IOHandler &io_handler, + const StringList &lines, + int cursor_position) { + if (!m_enable_auto_indent) + return 0; + + if (!lines.GetSize()) { + return 0; + } + + int tab_size = io_handler.GetDebugger().GetTabSize(); + + lldb::offset_t desired_indent = + GetDesiredIndentation(lines, cursor_position, tab_size); + + int actual_indent = REPL::CalculateActualIndentation(lines); + + if (desired_indent == LLDB_INVALID_OFFSET) + return 0; + + return (int)desired_indent - actual_indent; } -void -REPL::IOHandlerInputComplete (IOHandler &io_handler, std::string &code) -{ - lldb::StreamFileSP output_sp(io_handler.GetOutputStreamFile()); - lldb::StreamFileSP error_sp(io_handler.GetErrorStreamFile()); - bool extra_line = false; - bool did_quit = false; - - if (code.empty()) - { - m_code.AppendString(""); - static_cast<IOHandlerEditline &>(io_handler).SetBaseLineNumber(m_code.GetSize()+1); - } - else - { - Debugger &debugger = m_target.GetDebugger(); - CommandInterpreter &ci = debugger.GetCommandInterpreter(); - extra_line = ci.GetSpaceReplPrompts(); - - ExecutionContext exe_ctx (m_target.GetProcessSP()->GetThreadList().GetSelectedThread()->GetSelectedFrame().get()); - - lldb::ProcessSP process_sp(exe_ctx.GetProcessSP()); - - if (code[0] == ':') - { - // Meta command - // Strip the ':' - code.erase(0, 1); - if (Args::StripSpaces (code)) - { - // "lldb" was followed by arguments, so just execute the command dump the results - - // Turn off prompt on quit in case the user types ":quit" - const bool saved_prompt_on_quit = ci.GetPromptOnQuit(); - if (saved_prompt_on_quit) - ci.SetPromptOnQuit(false); - - // Execute the command - CommandReturnObject result; - result.SetImmediateOutputStream(output_sp); - result.SetImmediateErrorStream(error_sp); - ci.HandleCommand(code.c_str(), eLazyBoolNo, result); - - if (saved_prompt_on_quit) - ci.SetPromptOnQuit(true); - - if (result.GetStatus() == lldb::eReturnStatusQuit) - { - did_quit = true; - io_handler.SetIsDone(true); - if (debugger.CheckTopIOHandlerTypes(IOHandler::Type::REPL, IOHandler::Type::CommandInterpreter)) - { - // We typed "quit" or an alias to quit so we need to check if the - // command interpreter is above us and tell it that it is done as well - // so we don't drop back into the command interpreter if we have already - // quit - lldb::IOHandlerSP io_handler_sp (ci.GetIOHandler()); - if (io_handler_sp) - io_handler_sp->SetIsDone(true); - } - } - } - else - { - // ":" was followed by no arguments, so push the LLDB command prompt - if (debugger.CheckTopIOHandlerTypes(IOHandler::Type::REPL, IOHandler::Type::CommandInterpreter)) - { - // If the user wants to get back to the command interpreter and the - // command interpreter is what launched the REPL, then just let the - // REPL exit and fall back to the command interpreter. - io_handler.SetIsDone(true); - } - else - { - // The REPL wasn't launched the by the command interpreter, it is the - // base IOHandler, so we need to get the command interpreter and - lldb::IOHandlerSP io_handler_sp (ci.GetIOHandler()); - if (io_handler_sp) - { - io_handler_sp->SetIsDone(false); - debugger.PushIOHandler(ci.GetIOHandler()); - } - } - } +void REPL::IOHandlerInputComplete(IOHandler &io_handler, std::string &code) { + lldb::StreamFileSP output_sp(io_handler.GetOutputStreamFile()); + lldb::StreamFileSP error_sp(io_handler.GetErrorStreamFile()); + bool extra_line = false; + bool did_quit = false; + + if (code.empty()) { + m_code.AppendString(""); + static_cast<IOHandlerEditline &>(io_handler) + .SetBaseLineNumber(m_code.GetSize() + 1); + } else { + Debugger &debugger = m_target.GetDebugger(); + CommandInterpreter &ci = debugger.GetCommandInterpreter(); + extra_line = ci.GetSpaceReplPrompts(); + + ExecutionContext exe_ctx(m_target.GetProcessSP() + ->GetThreadList() + .GetSelectedThread() + ->GetSelectedFrame() + .get()); + + lldb::ProcessSP process_sp(exe_ctx.GetProcessSP()); + + if (code[0] == ':') { + // Meta command + // Strip the ':' + code.erase(0, 1); + if (Args::StripSpaces(code)) { + // "lldb" was followed by arguments, so just execute the command dump + // the results + + // Turn off prompt on quit in case the user types ":quit" + const bool saved_prompt_on_quit = ci.GetPromptOnQuit(); + if (saved_prompt_on_quit) + ci.SetPromptOnQuit(false); + + // Execute the command + CommandReturnObject result; + result.SetImmediateOutputStream(output_sp); + result.SetImmediateErrorStream(error_sp); + ci.HandleCommand(code.c_str(), eLazyBoolNo, result); + + if (saved_prompt_on_quit) + ci.SetPromptOnQuit(true); + + if (result.GetStatus() == lldb::eReturnStatusQuit) { + did_quit = true; + io_handler.SetIsDone(true); + if (debugger.CheckTopIOHandlerTypes( + IOHandler::Type::REPL, IOHandler::Type::CommandInterpreter)) { + // We typed "quit" or an alias to quit so we need to check if the + // command interpreter is above us and tell it that it is done as + // well + // so we don't drop back into the command interpreter if we have + // already + // quit + lldb::IOHandlerSP io_handler_sp(ci.GetIOHandler()); + if (io_handler_sp) + io_handler_sp->SetIsDone(true); + } } - else - { - // Unwind any expression we might have been running in case our REPL - // expression crashed and the user was looking around - if (m_dedicated_repl_mode) - { - Thread *thread = exe_ctx.GetThreadPtr(); - if (thread && thread->UnwindInnermostExpression().Success()) - { - thread->SetSelectedFrameByIndex(0, false); - exe_ctx.SetFrameSP(thread->GetSelectedFrame()); - } - } - - const bool colorize_err = error_sp->GetFile().GetIsTerminalWithColors(); - - EvaluateExpressionOptions expr_options; - expr_options.SetCoerceToId(m_varobj_options.use_objc); - expr_options.SetUnwindOnError(m_command_options.unwind_on_error); - expr_options.SetIgnoreBreakpoints (m_command_options.ignore_breakpoints); - expr_options.SetKeepInMemory(true); - expr_options.SetUseDynamic(m_varobj_options.use_dynamic); - expr_options.SetTryAllThreads(m_command_options.try_all_threads); - expr_options.SetGenerateDebugInfo(true); - expr_options.SetREPLEnabled (true); - expr_options.SetColorizeErrors(colorize_err); - expr_options.SetPoundLine(m_repl_source_path.c_str(), m_code.GetSize() + 1); - if (m_command_options.timeout > 0) - expr_options.SetTimeoutUsec(m_command_options.timeout); - else - expr_options.SetTimeoutUsec(0); - - expr_options.SetLanguage(GetLanguage()); - - PersistentExpressionState *persistent_state = m_target.GetPersistentExpressionStateForLanguage(GetLanguage()); - - const size_t var_count_before = persistent_state->GetSize(); - - const char *expr_prefix = nullptr; - lldb::ValueObjectSP result_valobj_sp; - Error error; - lldb::ModuleSP jit_module_sp; - lldb::ExpressionResults execution_results = UserExpression::Evaluate (exe_ctx, - expr_options, - code.c_str(), - expr_prefix, - result_valobj_sp, - error, - 0, // Line offset - nullptr, // Fixed Expression - &jit_module_sp); - - //CommandInterpreter &ci = debugger.GetCommandInterpreter(); - - if (process_sp && process_sp->IsAlive()) - { - bool add_to_code = true; - bool handled = false; - if (result_valobj_sp) - { - lldb::Format format = m_format_options.GetFormat(); - - if (result_valobj_sp->GetError().Success()) - { - handled |= PrintOneVariable(debugger, output_sp, result_valobj_sp); - } - else if (result_valobj_sp->GetError().GetError() == UserExpression::kNoResult) - { - if (format != lldb::eFormatVoid && debugger.GetNotifyVoid()) - { - error_sp->PutCString("(void)\n"); - handled = true; - } - } - } - - if (debugger.GetPrintDecls()) - { - for (size_t vi = var_count_before, ve = persistent_state->GetSize(); - vi != ve; - ++vi) - { - lldb::ExpressionVariableSP persistent_var_sp = persistent_state->GetVariableAtIndex(vi); - lldb::ValueObjectSP valobj_sp = persistent_var_sp->GetValueObject(); - - PrintOneVariable(debugger, output_sp, valobj_sp, persistent_var_sp.get()); - } - } - - if (!handled) - { - bool useColors = error_sp->GetFile().GetIsTerminalWithColors(); - switch (execution_results) - { - case lldb::eExpressionSetupError: - case lldb::eExpressionParseError: - add_to_code = false; - LLVM_FALLTHROUGH; - case lldb::eExpressionDiscarded: - error_sp->Printf("%s\n", error.AsCString()); - break; - - case lldb::eExpressionCompleted: - break; - case lldb::eExpressionInterrupted: - if (useColors) { - error_sp->Printf(ANSI_ESCAPE1(ANSI_FG_COLOR_RED)); - error_sp->Printf(ANSI_ESCAPE1(ANSI_CTRL_BOLD)); - } - error_sp->Printf("Execution interrupted. "); - if (useColors) error_sp->Printf(ANSI_ESCAPE1(ANSI_CTRL_NORMAL)); - error_sp->Printf("Enter code to recover and continue.\nEnter LLDB commands to investigate (type :help for assistance.)\n"); - break; - - case lldb::eExpressionHitBreakpoint: - // Breakpoint was hit, drop into LLDB command interpreter - if (useColors) { - error_sp->Printf(ANSI_ESCAPE1(ANSI_FG_COLOR_RED)); - error_sp->Printf(ANSI_ESCAPE1(ANSI_CTRL_BOLD)); - } - output_sp->Printf("Execution stopped at breakpoint. "); - if (useColors) error_sp->Printf(ANSI_ESCAPE1(ANSI_CTRL_NORMAL)); - output_sp->Printf("Enter LLDB commands to investigate (type help for assistance.)\n"); - { - lldb::IOHandlerSP io_handler_sp (ci.GetIOHandler()); - if (io_handler_sp) - { - io_handler_sp->SetIsDone(false); - debugger.PushIOHandler(ci.GetIOHandler()); - } - } - break; - - case lldb::eExpressionTimedOut: - error_sp->Printf("error: timeout\n"); - if (error.AsCString()) - error_sp->Printf("error: %s\n", error.AsCString()); - break; - case lldb::eExpressionResultUnavailable: - // Shoulnd't happen??? - error_sp->Printf("error: could not fetch result -- %s\n", error.AsCString()); - break; - case lldb::eExpressionStoppedForDebug: - // Shoulnd't happen??? - error_sp->Printf("error: stopped for debug -- %s\n", error.AsCString()); - break; - } - } - - if (add_to_code) - { - const uint32_t new_default_line = m_code.GetSize() + 1; - - m_code.SplitIntoLines(code); - - // Update our code on disk - if (!m_repl_source_path.empty()) - { - lldb_private::File file (m_repl_source_path.c_str(), - File::eOpenOptionWrite | File::eOpenOptionTruncate | File::eOpenOptionCanCreate, - lldb::eFilePermissionsFileDefault); - std::string code (m_code.CopyList()); - code.append(1, '\n'); - size_t bytes_written = code.size(); - file.Write(code.c_str(), bytes_written); - file.Close(); - - // Now set the default file and line to the REPL source file - m_target.GetSourceManager().SetDefaultFileAndLine(FileSpec(m_repl_source_path.c_str(), false), new_default_line); - } - static_cast<IOHandlerEditline &>(io_handler).SetBaseLineNumber(m_code.GetSize()+1); - } - if (extra_line) - { - fprintf(output_sp->GetFile().GetStream(), "\n"); - } + } else { + // ":" was followed by no arguments, so push the LLDB command prompt + if (debugger.CheckTopIOHandlerTypes( + IOHandler::Type::REPL, IOHandler::Type::CommandInterpreter)) { + // If the user wants to get back to the command interpreter and the + // command interpreter is what launched the REPL, then just let the + // REPL exit and fall back to the command interpreter. + io_handler.SetIsDone(true); + } else { + // The REPL wasn't launched the by the command interpreter, it is the + // base IOHandler, so we need to get the command interpreter and + lldb::IOHandlerSP io_handler_sp(ci.GetIOHandler()); + if (io_handler_sp) { + io_handler_sp->SetIsDone(false); + debugger.PushIOHandler(ci.GetIOHandler()); + } + } + } + } else { + // Unwind any expression we might have been running in case our REPL + // expression crashed and the user was looking around + if (m_dedicated_repl_mode) { + Thread *thread = exe_ctx.GetThreadPtr(); + if (thread && thread->UnwindInnermostExpression().Success()) { + thread->SetSelectedFrameByIndex(0, false); + exe_ctx.SetFrameSP(thread->GetSelectedFrame()); + } + } + + const bool colorize_err = error_sp->GetFile().GetIsTerminalWithColors(); + + EvaluateExpressionOptions expr_options; + expr_options.SetCoerceToId(m_varobj_options.use_objc); + expr_options.SetUnwindOnError(m_command_options.unwind_on_error); + expr_options.SetIgnoreBreakpoints(m_command_options.ignore_breakpoints); + expr_options.SetKeepInMemory(true); + expr_options.SetUseDynamic(m_varobj_options.use_dynamic); + expr_options.SetTryAllThreads(m_command_options.try_all_threads); + expr_options.SetGenerateDebugInfo(true); + expr_options.SetREPLEnabled(true); + expr_options.SetColorizeErrors(colorize_err); + expr_options.SetPoundLine(m_repl_source_path.c_str(), + m_code.GetSize() + 1); + if (m_command_options.timeout > 0) + expr_options.SetTimeout(std::chrono::microseconds(m_command_options.timeout)); + else + expr_options.SetTimeout(llvm::None); + + expr_options.SetLanguage(GetLanguage()); + + PersistentExpressionState *persistent_state = + m_target.GetPersistentExpressionStateForLanguage(GetLanguage()); + + const size_t var_count_before = persistent_state->GetSize(); + + const char *expr_prefix = nullptr; + lldb::ValueObjectSP result_valobj_sp; + Error error; + lldb::ModuleSP jit_module_sp; + lldb::ExpressionResults execution_results = + UserExpression::Evaluate(exe_ctx, expr_options, code.c_str(), + expr_prefix, result_valobj_sp, error, + 0, // Line offset + nullptr, // Fixed Expression + &jit_module_sp); + + // CommandInterpreter &ci = debugger.GetCommandInterpreter(); + + if (process_sp && process_sp->IsAlive()) { + bool add_to_code = true; + bool handled = false; + if (result_valobj_sp) { + lldb::Format format = m_format_options.GetFormat(); + + if (result_valobj_sp->GetError().Success()) { + handled |= PrintOneVariable(debugger, output_sp, result_valobj_sp); + } else if (result_valobj_sp->GetError().GetError() == + UserExpression::kNoResult) { + if (format != lldb::eFormatVoid && debugger.GetNotifyVoid()) { + error_sp->PutCString("(void)\n"); + handled = true; } + } } - - // Don't complain about the REPL process going away if we are in the process of quitting. - if (!did_quit && (!process_sp || !process_sp->IsAlive())) - { - error_sp->Printf("error: REPL process is no longer alive, exiting REPL\n"); - io_handler.SetIsDone(true); + + if (debugger.GetPrintDecls()) { + for (size_t vi = var_count_before, ve = persistent_state->GetSize(); + vi != ve; ++vi) { + lldb::ExpressionVariableSP persistent_var_sp = + persistent_state->GetVariableAtIndex(vi); + lldb::ValueObjectSP valobj_sp = persistent_var_sp->GetValueObject(); + + PrintOneVariable(debugger, output_sp, valobj_sp, + persistent_var_sp.get()); + } } - } -} -int -REPL::IOHandlerComplete (IOHandler &io_handler, - const char *current_line, - const char *cursor, - const char *last_char, - int skip_first_n_matches, - int max_matches, - StringList &matches) -{ - matches.Clear(); - - llvm::StringRef line (current_line, cursor - current_line); - - // Complete an LLDB command if the first character is a colon... - if (!line.empty() && line[0] == ':') - { - Debugger &debugger = m_target.GetDebugger(); - - // auto complete LLDB commands - const char *lldb_current_line = line.substr(1).data(); - return debugger.GetCommandInterpreter().HandleCompletion (lldb_current_line, - cursor, - last_char, - skip_first_n_matches, - max_matches, - matches); - } - - // Strip spaces from the line and see if we had only spaces - line = line.ltrim(); - if (line.empty()) - { - // Only spaces on this line, so just indent - matches.AppendString(m_indent_str); - return 1; - } - - std::string current_code; - current_code.append(m_code.CopyList()); - - IOHandlerEditline &editline = static_cast<IOHandlerEditline &>(io_handler); - const StringList *current_lines = editline.GetCurrentLines(); - if (current_lines) - { - const uint32_t current_line_idx = editline.GetCurrentLineIndex(); - - if (current_line_idx < current_lines->GetSize()) - { - for (uint32_t i=0; i<current_line_idx; ++i) + if (!handled) { + bool useColors = error_sp->GetFile().GetIsTerminalWithColors(); + switch (execution_results) { + case lldb::eExpressionSetupError: + case lldb::eExpressionParseError: + add_to_code = false; + LLVM_FALLTHROUGH; + case lldb::eExpressionDiscarded: + error_sp->Printf("%s\n", error.AsCString()); + break; + + case lldb::eExpressionCompleted: + break; + case lldb::eExpressionInterrupted: + if (useColors) { + error_sp->Printf(ANSI_ESCAPE1(ANSI_FG_COLOR_RED)); + error_sp->Printf(ANSI_ESCAPE1(ANSI_CTRL_BOLD)); + } + error_sp->Printf("Execution interrupted. "); + if (useColors) + error_sp->Printf(ANSI_ESCAPE1(ANSI_CTRL_NORMAL)); + error_sp->Printf("Enter code to recover and continue.\nEnter LLDB " + "commands to investigate (type :help for " + "assistance.)\n"); + break; + + case lldb::eExpressionHitBreakpoint: + // Breakpoint was hit, drop into LLDB command interpreter + if (useColors) { + error_sp->Printf(ANSI_ESCAPE1(ANSI_FG_COLOR_RED)); + error_sp->Printf(ANSI_ESCAPE1(ANSI_CTRL_BOLD)); + } + output_sp->Printf("Execution stopped at breakpoint. "); + if (useColors) + error_sp->Printf(ANSI_ESCAPE1(ANSI_CTRL_NORMAL)); + output_sp->Printf("Enter LLDB commands to investigate (type help " + "for assistance.)\n"); { - const char *line_cstr = current_lines->GetStringAtIndex(i); - if (line_cstr) - { - current_code.append("\n"); - current_code.append (line_cstr); - } + lldb::IOHandlerSP io_handler_sp(ci.GetIOHandler()); + if (io_handler_sp) { + io_handler_sp->SetIsDone(false); + debugger.PushIOHandler(ci.GetIOHandler()); + } } + break; + + case lldb::eExpressionTimedOut: + error_sp->Printf("error: timeout\n"); + if (error.AsCString()) + error_sp->Printf("error: %s\n", error.AsCString()); + break; + case lldb::eExpressionResultUnavailable: + // Shoulnd't happen??? + error_sp->Printf("error: could not fetch result -- %s\n", + error.AsCString()); + break; + case lldb::eExpressionStoppedForDebug: + // Shoulnd't happen??? + error_sp->Printf("error: stopped for debug -- %s\n", + error.AsCString()); + break; + } } + + if (add_to_code) { + const uint32_t new_default_line = m_code.GetSize() + 1; + + m_code.SplitIntoLines(code); + + // Update our code on disk + if (!m_repl_source_path.empty()) { + lldb_private::File file(m_repl_source_path.c_str(), + File::eOpenOptionWrite | + File::eOpenOptionTruncate | + File::eOpenOptionCanCreate, + lldb::eFilePermissionsFileDefault); + std::string code(m_code.CopyList()); + code.append(1, '\n'); + size_t bytes_written = code.size(); + file.Write(code.c_str(), bytes_written); + file.Close(); + + // Now set the default file and line to the REPL source file + m_target.GetSourceManager().SetDefaultFileAndLine( + FileSpec(m_repl_source_path, false), new_default_line); + } + static_cast<IOHandlerEditline &>(io_handler) + .SetBaseLineNumber(m_code.GetSize() + 1); + } + if (extra_line) { + fprintf(output_sp->GetFile().GetStream(), "\n"); + } + } } - - if (cursor > current_line) - { - current_code.append("\n"); - current_code.append(current_line, cursor - current_line); - } - - return CompleteCode(current_code, matches); -} -bool -QuitCommandOverrideCallback(void *baton, const char **argv) -{ - Target *target = (Target *)baton; - lldb::ProcessSP process_sp (target->GetProcessSP()); - if (process_sp) - { - process_sp->Destroy(false); - process_sp->GetTarget().GetDebugger().ClearIOHandlers(); + // Don't complain about the REPL process going away if we are in the process + // of quitting. + if (!did_quit && (!process_sp || !process_sp->IsAlive())) { + error_sp->Printf( + "error: REPL process is no longer alive, exiting REPL\n"); + io_handler.SetIsDone(true); } - return false; + } } -Error -REPL::RunLoop () -{ - Error error; - - error = DoInitialization(); - m_repl_source_path = GetSourcePath(); - - if (!error.Success()) - return error; - +int REPL::IOHandlerComplete(IOHandler &io_handler, const char *current_line, + const char *cursor, const char *last_char, + int skip_first_n_matches, int max_matches, + StringList &matches) { + matches.Clear(); + + llvm::StringRef line(current_line, cursor - current_line); + + // Complete an LLDB command if the first character is a colon... + if (!line.empty() && line[0] == ':') { Debugger &debugger = m_target.GetDebugger(); - - lldb::IOHandlerSP io_handler_sp (GetIOHandler()); - - FileSpec save_default_file; - uint32_t save_default_line = 0; - - if (!m_repl_source_path.empty()) - { - // Save the current default file and line - m_target.GetSourceManager().GetDefaultFileAndLine(save_default_file, save_default_line); - } - - debugger.PushIOHandler(io_handler_sp); - - // Check if we are in dedicated REPL mode where LLDB was start with the "--repl" option - // from the command line. Currently we know this by checking if the debugger already - // has a IOHandler thread. - if (!debugger.HasIOHandlerThread()) - { - // The debugger doesn't have an existing IOHandler thread, so this must be - // dedicated REPL mode... - m_dedicated_repl_mode = true; - debugger.StartIOHandlerThread(); - std::string command_name_str ("quit"); - CommandObject *cmd_obj = debugger.GetCommandInterpreter().GetCommandObjectForCommand(command_name_str); - if (cmd_obj) - { - assert(command_name_str.empty()); - cmd_obj->SetOverrideCallback (QuitCommandOverrideCallback, &m_target); + + // auto complete LLDB commands + const char *lldb_current_line = line.substr(1).data(); + return debugger.GetCommandInterpreter().HandleCompletion( + lldb_current_line, cursor, last_char, skip_first_n_matches, max_matches, + matches); + } + + // Strip spaces from the line and see if we had only spaces + line = line.ltrim(); + if (line.empty()) { + // Only spaces on this line, so just indent + matches.AppendString(m_indent_str); + return 1; + } + + std::string current_code; + current_code.append(m_code.CopyList()); + + IOHandlerEditline &editline = static_cast<IOHandlerEditline &>(io_handler); + const StringList *current_lines = editline.GetCurrentLines(); + if (current_lines) { + const uint32_t current_line_idx = editline.GetCurrentLineIndex(); + + if (current_line_idx < current_lines->GetSize()) { + for (uint32_t i = 0; i < current_line_idx; ++i) { + const char *line_cstr = current_lines->GetStringAtIndex(i); + if (line_cstr) { + current_code.append("\n"); + current_code.append(line_cstr); } + } } - - // Wait for the REPL command interpreter to get popped - io_handler_sp->WaitForPop(); - - if (m_dedicated_repl_mode) - { - // If we were in dedicated REPL mode we would have started the - // IOHandler thread, and we should kill our process - lldb::ProcessSP process_sp = m_target.GetProcessSP(); - if (process_sp && process_sp->IsAlive()) - process_sp->Destroy(false); - - // Wait for the IO handler thread to exit (TODO: don't do this if the IO handler thread already exists...) - debugger.JoinIOHandlerThread(); - } - - // Restore the default file and line - if (save_default_file && save_default_line != 0) - m_target.GetSourceManager().SetDefaultFileAndLine(save_default_file, save_default_line); + } + + if (cursor > current_line) { + current_code.append("\n"); + current_code.append(current_line, cursor - current_line); + } + + return CompleteCode(current_code, matches); +} + +bool QuitCommandOverrideCallback(void *baton, const char **argv) { + Target *target = (Target *)baton; + lldb::ProcessSP process_sp(target->GetProcessSP()); + if (process_sp) { + process_sp->Destroy(false); + process_sp->GetTarget().GetDebugger().ClearIOHandlers(); + } + return false; +} + +Error REPL::RunLoop() { + Error error; + + error = DoInitialization(); + m_repl_source_path = GetSourcePath(); + + if (!error.Success()) return error; + + Debugger &debugger = m_target.GetDebugger(); + + lldb::IOHandlerSP io_handler_sp(GetIOHandler()); + + FileSpec save_default_file; + uint32_t save_default_line = 0; + + if (!m_repl_source_path.empty()) { + // Save the current default file and line + m_target.GetSourceManager().GetDefaultFileAndLine(save_default_file, + save_default_line); + } + + debugger.PushIOHandler(io_handler_sp); + + // Check if we are in dedicated REPL mode where LLDB was start with the + // "--repl" option + // from the command line. Currently we know this by checking if the debugger + // already + // has a IOHandler thread. + if (!debugger.HasIOHandlerThread()) { + // The debugger doesn't have an existing IOHandler thread, so this must be + // dedicated REPL mode... + m_dedicated_repl_mode = true; + debugger.StartIOHandlerThread(); + llvm::StringRef command_name_str("quit"); + CommandObject *cmd_obj = + debugger.GetCommandInterpreter().GetCommandObjectForCommand( + command_name_str); + if (cmd_obj) { + assert(command_name_str.empty()); + cmd_obj->SetOverrideCallback(QuitCommandOverrideCallback, &m_target); + } + } + + // Wait for the REPL command interpreter to get popped + io_handler_sp->WaitForPop(); + + if (m_dedicated_repl_mode) { + // If we were in dedicated REPL mode we would have started the + // IOHandler thread, and we should kill our process + lldb::ProcessSP process_sp = m_target.GetProcessSP(); + if (process_sp && process_sp->IsAlive()) + process_sp->Destroy(false); + + // Wait for the IO handler thread to exit (TODO: don't do this if the IO + // handler thread already exists...) + debugger.JoinIOHandlerThread(); + } + + // Restore the default file and line + if (save_default_file && save_default_line != 0) + m_target.GetSourceManager().SetDefaultFileAndLine(save_default_file, + save_default_line); + return error; } diff --git a/source/Expression/UserExpression.cpp b/source/Expression/UserExpression.cpp index 3e2e07e9cb22..041caf57bd31 100644 --- a/source/Expression/UserExpression.cpp +++ b/source/Expression/UserExpression.cpp @@ -9,12 +9,12 @@ #include <stdio.h> #if HAVE_SYS_TYPES_H -# include <sys/types.h> +#include <sys/types.h> #endif #include <cstdlib> -#include <string> #include <map> +#include <string> #include "Plugins/ExpressionParser/Clang/ClangPersistentVariables.h" #include "lldb/Core/ConstString.h" @@ -46,359 +46,329 @@ using namespace lldb_private; -UserExpression::UserExpression (ExecutionContextScope &exe_scope, - const char *expr, - const char *expr_prefix, - lldb::LanguageType language, - ResultType desired_type, - const EvaluateExpressionOptions &options) : - Expression(exe_scope), - m_expr_text(expr), - m_expr_prefix(expr_prefix ? expr_prefix : ""), - m_language(language), - m_desired_type(desired_type), - m_options (options) -{ -} - -UserExpression::~UserExpression () -{ -} - -void -UserExpression::InstallContext (ExecutionContext &exe_ctx) -{ - m_jit_process_wp = exe_ctx.GetProcessSP(); +UserExpression::UserExpression(ExecutionContextScope &exe_scope, + llvm::StringRef expr, llvm::StringRef prefix, + lldb::LanguageType language, + ResultType desired_type, + const EvaluateExpressionOptions &options) + : Expression(exe_scope), m_expr_text(expr), m_expr_prefix(prefix), + m_language(language), m_desired_type(desired_type), m_options(options) {} - lldb::StackFrameSP frame_sp = exe_ctx.GetFrameSP(); +UserExpression::~UserExpression() {} - if (frame_sp) - m_address = frame_sp->GetFrameCodeAddress(); -} +void UserExpression::InstallContext(ExecutionContext &exe_ctx) { + m_jit_process_wp = exe_ctx.GetProcessSP(); -bool -UserExpression::LockAndCheckContext (ExecutionContext &exe_ctx, - lldb::TargetSP &target_sp, - lldb::ProcessSP &process_sp, - lldb::StackFrameSP &frame_sp) -{ - lldb::ProcessSP expected_process_sp = m_jit_process_wp.lock(); - process_sp = exe_ctx.GetProcessSP(); - - if (process_sp != expected_process_sp) - return false; - - process_sp = exe_ctx.GetProcessSP(); - target_sp = exe_ctx.GetTargetSP(); - frame_sp = exe_ctx.GetFrameSP(); - - if (m_address.IsValid()) - { - if (!frame_sp) - return false; - else - return (0 == Address::CompareLoadAddress(m_address, frame_sp->GetFrameCodeAddress(), target_sp.get())); - } + lldb::StackFrameSP frame_sp = exe_ctx.GetFrameSP(); - return true; + if (frame_sp) + m_address = frame_sp->GetFrameCodeAddress(); } -bool -UserExpression::MatchesContext (ExecutionContext &exe_ctx) -{ - lldb::TargetSP target_sp; - lldb::ProcessSP process_sp; - lldb::StackFrameSP frame_sp; +bool UserExpression::LockAndCheckContext(ExecutionContext &exe_ctx, + lldb::TargetSP &target_sp, + lldb::ProcessSP &process_sp, + lldb::StackFrameSP &frame_sp) { + lldb::ProcessSP expected_process_sp = m_jit_process_wp.lock(); + process_sp = exe_ctx.GetProcessSP(); - return LockAndCheckContext(exe_ctx, target_sp, process_sp, frame_sp); -} + if (process_sp != expected_process_sp) + return false; -lldb::addr_t -UserExpression::GetObjectPointer (lldb::StackFrameSP frame_sp, - ConstString &object_name, - Error &err) -{ - err.Clear(); + process_sp = exe_ctx.GetProcessSP(); + target_sp = exe_ctx.GetTargetSP(); + frame_sp = exe_ctx.GetFrameSP(); + if (m_address.IsValid()) { if (!frame_sp) - { - err.SetErrorStringWithFormat("Couldn't load '%s' because the context is incomplete", object_name.AsCString()); - return LLDB_INVALID_ADDRESS; - } - - lldb::VariableSP var_sp; - lldb::ValueObjectSP valobj_sp; - - valobj_sp = frame_sp->GetValueForVariableExpressionPath(object_name.AsCString(), - lldb::eNoDynamicValues, - StackFrame::eExpressionPathOptionCheckPtrVsMember | - StackFrame::eExpressionPathOptionsNoFragileObjcIvar | - StackFrame::eExpressionPathOptionsNoSyntheticChildren | - StackFrame::eExpressionPathOptionsNoSyntheticArrayRange, - var_sp, - err); + return false; + else + return (0 == Address::CompareLoadAddress(m_address, + frame_sp->GetFrameCodeAddress(), + target_sp.get())); + } - if (!err.Success() || !valobj_sp.get()) - return LLDB_INVALID_ADDRESS; + return true; +} - lldb::addr_t ret = valobj_sp->GetValueAsUnsigned(LLDB_INVALID_ADDRESS); +bool UserExpression::MatchesContext(ExecutionContext &exe_ctx) { + lldb::TargetSP target_sp; + lldb::ProcessSP process_sp; + lldb::StackFrameSP frame_sp; - if (ret == LLDB_INVALID_ADDRESS) - { - err.SetErrorStringWithFormat("Couldn't load '%s' because its value couldn't be evaluated", object_name.AsCString()); - return LLDB_INVALID_ADDRESS; - } + return LockAndCheckContext(exe_ctx, target_sp, process_sp, frame_sp); +} - return ret; +lldb::addr_t UserExpression::GetObjectPointer(lldb::StackFrameSP frame_sp, + ConstString &object_name, + Error &err) { + err.Clear(); + + if (!frame_sp) { + err.SetErrorStringWithFormat( + "Couldn't load '%s' because the context is incomplete", + object_name.AsCString()); + return LLDB_INVALID_ADDRESS; + } + + lldb::VariableSP var_sp; + lldb::ValueObjectSP valobj_sp; + + valobj_sp = frame_sp->GetValueForVariableExpressionPath( + object_name.AsCString(), lldb::eNoDynamicValues, + StackFrame::eExpressionPathOptionCheckPtrVsMember | + StackFrame::eExpressionPathOptionsNoFragileObjcIvar | + StackFrame::eExpressionPathOptionsNoSyntheticChildren | + StackFrame::eExpressionPathOptionsNoSyntheticArrayRange, + var_sp, err); + + if (!err.Success() || !valobj_sp.get()) + return LLDB_INVALID_ADDRESS; + + lldb::addr_t ret = valobj_sp->GetValueAsUnsigned(LLDB_INVALID_ADDRESS); + + if (ret == LLDB_INVALID_ADDRESS) { + err.SetErrorStringWithFormat( + "Couldn't load '%s' because its value couldn't be evaluated", + object_name.AsCString()); + return LLDB_INVALID_ADDRESS; + } + + return ret; } -lldb::ExpressionResults -UserExpression::Evaluate (ExecutionContext &exe_ctx, - const EvaluateExpressionOptions& options, - const char *expr_cstr, - const char *expr_prefix, - lldb::ValueObjectSP &result_valobj_sp, - Error &error, - uint32_t line_offset, - std::string *fixed_expression, - lldb::ModuleSP *jit_module_sp_ptr) -{ - Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_EXPRESSIONS | LIBLLDB_LOG_STEP)); - - lldb_private::ExecutionPolicy execution_policy = options.GetExecutionPolicy(); - lldb::LanguageType language = options.GetLanguage(); - const ResultType desired_type = options.DoesCoerceToId() ? UserExpression::eResultTypeId : UserExpression::eResultTypeAny; - lldb::ExpressionResults execution_results = lldb::eExpressionSetupError; - - Target *target = exe_ctx.GetTargetPtr(); - if (!target) - { - if (log) - log->Printf("== [UserExpression::Evaluate] Passed a NULL target, can't run expressions."); - return lldb::eExpressionSetupError; - } +lldb::ExpressionResults UserExpression::Evaluate( + ExecutionContext &exe_ctx, const EvaluateExpressionOptions &options, + llvm::StringRef expr, llvm::StringRef prefix, + lldb::ValueObjectSP &result_valobj_sp, Error &error, uint32_t line_offset, + std::string *fixed_expression, lldb::ModuleSP *jit_module_sp_ptr) { + Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_EXPRESSIONS | + LIBLLDB_LOG_STEP)); + + lldb_private::ExecutionPolicy execution_policy = options.GetExecutionPolicy(); + lldb::LanguageType language = options.GetLanguage(); + const ResultType desired_type = options.DoesCoerceToId() + ? UserExpression::eResultTypeId + : UserExpression::eResultTypeAny; + lldb::ExpressionResults execution_results = lldb::eExpressionSetupError; + + Target *target = exe_ctx.GetTargetPtr(); + if (!target) { + if (log) + log->Printf("== [UserExpression::Evaluate] Passed a NULL target, can't " + "run expressions."); + error.SetErrorString("expression passed a null target"); + return lldb::eExpressionSetupError; + } - Process *process = exe_ctx.GetProcessPtr(); + Process *process = exe_ctx.GetProcessPtr(); - if (process == NULL || process->GetState() != lldb::eStateStopped) - { - if (execution_policy == eExecutionPolicyAlways) - { - if (log) - log->Printf("== [UserExpression::Evaluate] Expression may not run, but is not constant =="); + if (process == NULL || process->GetState() != lldb::eStateStopped) { + if (execution_policy == eExecutionPolicyAlways) { + if (log) + log->Printf("== [UserExpression::Evaluate] Expression may not run, but " + "is not constant =="); - error.SetErrorString ("expression needed to run but couldn't"); + error.SetErrorString("expression needed to run but couldn't"); - return execution_results; - } + return execution_results; } - - if (process == NULL || !process->CanJIT()) - execution_policy = eExecutionPolicyNever; - - // We need to set the expression execution thread here, turns out parse can call functions in the process of - // looking up symbols, which will escape the context set by exe_ctx passed to Execute. - lldb::ThreadSP thread_sp = exe_ctx.GetThreadSP(); - ThreadList::ExpressionExecutionThreadPusher execution_thread_pusher(thread_sp); - - const char *full_prefix = NULL; - const char *option_prefix = options.GetPrefix(); - std::string full_prefix_storage; - if (expr_prefix && option_prefix) - { - full_prefix_storage.assign(expr_prefix); - full_prefix_storage.append(option_prefix); - if (!full_prefix_storage.empty()) - full_prefix = full_prefix_storage.c_str(); - } - else if (expr_prefix) - full_prefix = expr_prefix; - else - full_prefix = option_prefix; - - // If the language was not specified in the expression command, - // set it to the language in the target's properties if - // specified, else default to the langage for the frame. - if (language == lldb::eLanguageTypeUnknown) - { - if (target->GetLanguage() != lldb::eLanguageTypeUnknown) - language = target->GetLanguage(); - else if (StackFrame *frame = exe_ctx.GetFramePtr()) - language = frame->GetLanguage(); + } + + if (process == NULL || !process->CanJIT()) + execution_policy = eExecutionPolicyNever; + + // We need to set the expression execution thread here, turns out parse can + // call functions in the process of + // looking up symbols, which will escape the context set by exe_ctx passed to + // Execute. + lldb::ThreadSP thread_sp = exe_ctx.GetThreadSP(); + ThreadList::ExpressionExecutionThreadPusher execution_thread_pusher( + thread_sp); + + llvm::StringRef full_prefix; + llvm::StringRef option_prefix(options.GetPrefix()); + std::string full_prefix_storage; + if (!prefix.empty() && !option_prefix.empty()) { + full_prefix_storage = prefix; + full_prefix_storage.append(option_prefix); + full_prefix = full_prefix_storage; + } else if (!prefix.empty()) + full_prefix = prefix; + else + full_prefix = option_prefix; + + // If the language was not specified in the expression command, + // set it to the language in the target's properties if + // specified, else default to the langage for the frame. + if (language == lldb::eLanguageTypeUnknown) { + if (target->GetLanguage() != lldb::eLanguageTypeUnknown) + language = target->GetLanguage(); + else if (StackFrame *frame = exe_ctx.GetFramePtr()) + language = frame->GetLanguage(); + } + + lldb::UserExpressionSP user_expression_sp( + target->GetUserExpressionForLanguage(expr, full_prefix, language, + desired_type, options, error)); + if (error.Fail()) { + if (log) + log->Printf("== [UserExpression::Evaluate] Getting expression: %s ==", + error.AsCString()); + return lldb::eExpressionSetupError; + } + + if (log) + log->Printf("== [UserExpression::Evaluate] Parsing expression %s ==", + expr.str().c_str()); + + const bool keep_expression_in_memory = true; + const bool generate_debug_info = options.GetGenerateDebugInfo(); + + if (options.InvokeCancelCallback(lldb::eExpressionEvaluationParse)) { + error.SetErrorString("expression interrupted by callback before parse"); + result_valobj_sp = ValueObjectConstResult::Create( + exe_ctx.GetBestExecutionContextScope(), error); + return lldb::eExpressionInterrupted; + } + + DiagnosticManager diagnostic_manager; + + bool parse_success = + user_expression_sp->Parse(diagnostic_manager, exe_ctx, execution_policy, + keep_expression_in_memory, generate_debug_info); + + // Calculate the fixed expression always, since we need it for errors. + std::string tmp_fixed_expression; + if (fixed_expression == nullptr) + fixed_expression = &tmp_fixed_expression; + + const char *fixed_text = user_expression_sp->GetFixedText(); + if (fixed_text != nullptr) + fixed_expression->append(fixed_text); + + // If there is a fixed expression, try to parse it: + if (!parse_success) { + execution_results = lldb::eExpressionParseError; + if (fixed_expression && !fixed_expression->empty() && + options.GetAutoApplyFixIts()) { + lldb::UserExpressionSP fixed_expression_sp( + target->GetUserExpressionForLanguage(fixed_expression->c_str(), + full_prefix, language, + desired_type, options, error)); + DiagnosticManager fixed_diagnostic_manager; + parse_success = fixed_expression_sp->Parse( + fixed_diagnostic_manager, exe_ctx, execution_policy, + keep_expression_in_memory, generate_debug_info); + if (parse_success) { + diagnostic_manager.Clear(); + user_expression_sp = fixed_expression_sp; + } else { + // If the fixed expression failed to parse, don't tell the user about, + // that won't help. + fixed_expression->clear(); + } } - lldb::UserExpressionSP user_expression_sp(target->GetUserExpressionForLanguage (expr_cstr, - full_prefix, - language, - desired_type, - options, - error)); - if (error.Fail()) - { - if (log) - log->Printf ("== [UserExpression::Evaluate] Getting expression: %s ==", error.AsCString()); - return lldb::eExpressionSetupError; + if (!parse_success) { + if (!fixed_expression->empty() && target->GetEnableNotifyAboutFixIts()) { + error.SetExpressionErrorWithFormat( + execution_results, + "expression failed to parse, fixed expression suggested:\n %s", + fixed_expression->c_str()); + } else { + if (!diagnostic_manager.Diagnostics().size()) + error.SetExpressionError(execution_results, + "expression failed to parse, unknown error"); + else + error.SetExpressionError(execution_results, + diagnostic_manager.GetString().c_str()); + } } + } + + if (parse_success) { + // If a pointer to a lldb::ModuleSP was passed in, return the JIT'ed module + // if one was created + if (jit_module_sp_ptr) + *jit_module_sp_ptr = user_expression_sp->GetJITModule(); + + lldb::ExpressionVariableSP expr_result; + + if (execution_policy == eExecutionPolicyNever && + !user_expression_sp->CanInterpret()) { + if (log) + log->Printf("== [UserExpression::Evaluate] Expression may not run, but " + "is not constant =="); + + if (!diagnostic_manager.Diagnostics().size()) + error.SetExpressionError(lldb::eExpressionSetupError, + "expression needed to run but couldn't"); + } else if (execution_policy == eExecutionPolicyTopLevel) { + error.SetError(UserExpression::kNoResult, lldb::eErrorTypeGeneric); + return lldb::eExpressionCompleted; + } else { + if (options.InvokeCancelCallback(lldb::eExpressionEvaluationExecution)) { + error.SetExpressionError( + lldb::eExpressionInterrupted, + "expression interrupted by callback before execution"); + result_valobj_sp = ValueObjectConstResult::Create( + exe_ctx.GetBestExecutionContextScope(), error); + return lldb::eExpressionInterrupted; + } - if (log) - log->Printf("== [UserExpression::Evaluate] Parsing expression %s ==", expr_cstr); + diagnostic_manager.Clear(); - const bool keep_expression_in_memory = true; - const bool generate_debug_info = options.GetGenerateDebugInfo(); + if (log) + log->Printf("== [UserExpression::Evaluate] Executing expression =="); - if (options.InvokeCancelCallback (lldb::eExpressionEvaluationParse)) - { - error.SetErrorString ("expression interrupted by callback before parse"); - result_valobj_sp = ValueObjectConstResult::Create(exe_ctx.GetBestExecutionContextScope(), error); - return lldb::eExpressionInterrupted; - } + execution_results = + user_expression_sp->Execute(diagnostic_manager, exe_ctx, options, + user_expression_sp, expr_result); - DiagnosticManager diagnostic_manager; - - bool parse_success = user_expression_sp->Parse(diagnostic_manager, - exe_ctx, - execution_policy, - keep_expression_in_memory, - generate_debug_info); - - // Calculate the fixed expression always, since we need it for errors. - std::string tmp_fixed_expression; - if (fixed_expression == nullptr) - fixed_expression = &tmp_fixed_expression; - - const char *fixed_text = user_expression_sp->GetFixedText(); - if (fixed_text != nullptr) - fixed_expression->append(fixed_text); - - // If there is a fixed expression, try to parse it: - if (!parse_success) - { - execution_results = lldb::eExpressionParseError; - if (fixed_expression && !fixed_expression->empty() && options.GetAutoApplyFixIts()) - { - lldb::UserExpressionSP fixed_expression_sp(target->GetUserExpressionForLanguage (fixed_expression->c_str(), - full_prefix, - language, - desired_type, - options, - error)); - DiagnosticManager fixed_diagnostic_manager; - parse_success = fixed_expression_sp->Parse(fixed_diagnostic_manager, - exe_ctx, - execution_policy, - keep_expression_in_memory, - generate_debug_info); - if (parse_success) - { - diagnostic_manager.Clear(); - user_expression_sp = fixed_expression_sp; - } - else - { - // If the fixed expression failed to parse, don't tell the user about, that won't help. - fixed_expression->clear(); - } - } - - if (!parse_success) - { - if (!fixed_expression->empty() && target->GetEnableNotifyAboutFixIts()) - { - error.SetExpressionErrorWithFormat(execution_results, "expression failed to parse, fixed expression suggested:\n %s", - fixed_expression->c_str()); - } - else - { - if (!diagnostic_manager.Diagnostics().size()) - error.SetExpressionError(execution_results, "expression failed to parse, unknown error"); - else - error.SetExpressionError(execution_results, diagnostic_manager.GetString().c_str()); - } - } - } - - if (parse_success) - { - // If a pointer to a lldb::ModuleSP was passed in, return the JIT'ed module if one was created - if (jit_module_sp_ptr) - *jit_module_sp_ptr = user_expression_sp->GetJITModule(); - - lldb::ExpressionVariableSP expr_result; - - if (execution_policy == eExecutionPolicyNever && - !user_expression_sp->CanInterpret()) - { - if (log) - log->Printf("== [UserExpression::Evaluate] Expression may not run, but is not constant =="); - - if (!diagnostic_manager.Diagnostics().size()) - error.SetExpressionError(lldb::eExpressionSetupError, "expression needed to run but couldn't"); - } - else if (execution_policy == eExecutionPolicyTopLevel) - { - error.SetError(UserExpression::kNoResult, lldb::eErrorTypeGeneric); - return lldb::eExpressionCompleted; - } + if (execution_results != lldb::eExpressionCompleted) { + if (log) + log->Printf("== [UserExpression::Evaluate] Execution completed " + "abnormally =="); + + if (!diagnostic_manager.Diagnostics().size()) + error.SetExpressionError( + execution_results, "expression failed to execute, unknown error"); else - { - if (options.InvokeCancelCallback (lldb::eExpressionEvaluationExecution)) - { - error.SetExpressionError (lldb::eExpressionInterrupted, "expression interrupted by callback before execution"); - result_valobj_sp = ValueObjectConstResult::Create (exe_ctx.GetBestExecutionContextScope(), error); - return lldb::eExpressionInterrupted; - } - - diagnostic_manager.Clear(); - - if (log) - log->Printf("== [UserExpression::Evaluate] Executing expression =="); - - execution_results = - user_expression_sp->Execute(diagnostic_manager, exe_ctx, options, user_expression_sp, expr_result); - - if (execution_results != lldb::eExpressionCompleted) - { - if (log) - log->Printf("== [UserExpression::Evaluate] Execution completed abnormally =="); - - if (!diagnostic_manager.Diagnostics().size()) - error.SetExpressionError(execution_results, "expression failed to execute, unknown error"); - else - error.SetExpressionError(execution_results, diagnostic_manager.GetString().c_str()); - } - else - { - if (expr_result) - { - result_valobj_sp = expr_result->GetValueObject(); - - if (log) - log->Printf("== [UserExpression::Evaluate] Execution completed normally with result %s ==", - result_valobj_sp->GetValueAsCString()); - } - else - { - if (log) - log->Printf("== [UserExpression::Evaluate] Execution completed normally with no result =="); - - error.SetError(UserExpression::kNoResult, lldb::eErrorTypeGeneric); - } - } + error.SetExpressionError(execution_results, + diagnostic_manager.GetString().c_str()); + } else { + if (expr_result) { + result_valobj_sp = expr_result->GetValueObject(); + + if (log) + log->Printf("== [UserExpression::Evaluate] Execution completed " + "normally with result %s ==", + result_valobj_sp->GetValueAsCString()); + } else { + if (log) + log->Printf("== [UserExpression::Evaluate] Execution completed " + "normally with no result =="); + + error.SetError(UserExpression::kNoResult, lldb::eErrorTypeGeneric); } + } } + } - if (options.InvokeCancelCallback(lldb::eExpressionEvaluationComplete)) - { - error.SetExpressionError (lldb::eExpressionInterrupted, "expression interrupted by callback after complete"); - return lldb::eExpressionInterrupted; - } + if (options.InvokeCancelCallback(lldb::eExpressionEvaluationComplete)) { + error.SetExpressionError( + lldb::eExpressionInterrupted, + "expression interrupted by callback after complete"); + return lldb::eExpressionInterrupted; + } - if (result_valobj_sp.get() == NULL) - { - result_valobj_sp = ValueObjectConstResult::Create (exe_ctx.GetBestExecutionContextScope(), error); - } + if (result_valobj_sp.get() == NULL) { + result_valobj_sp = ValueObjectConstResult::Create( + exe_ctx.GetBestExecutionContextScope(), error); + } - return execution_results; + return execution_results; } lldb::ExpressionResults @@ -406,15 +376,13 @@ UserExpression::Execute(DiagnosticManager &diagnostic_manager, ExecutionContext &exe_ctx, const EvaluateExpressionOptions &options, lldb::UserExpressionSP &shared_ptr_to_me, - lldb::ExpressionVariableSP &result_var) -{ - lldb::ExpressionResults expr_result = DoExecute(diagnostic_manager, exe_ctx, options, shared_ptr_to_me, result_var); - Target *target = exe_ctx.GetTargetPtr(); - if (options.GetResultIsInternal() && result_var && target) - { - target->GetPersistentExpressionStateForLanguage(m_language)->RemovePersistentVariable (result_var); - } - return expr_result; + lldb::ExpressionVariableSP &result_var) { + lldb::ExpressionResults expr_result = DoExecute( + diagnostic_manager, exe_ctx, options, shared_ptr_to_me, result_var); + Target *target = exe_ctx.GetTargetPtr(); + if (options.GetResultIsInternal() && result_var && target) { + target->GetPersistentExpressionStateForLanguage(m_language) + ->RemovePersistentVariable(result_var); + } + return expr_result; } - - diff --git a/source/Expression/UtilityFunction.cpp b/source/Expression/UtilityFunction.cpp index 2ff77f093db2..fdb21ba372bd 100644 --- a/source/Expression/UtilityFunction.cpp +++ b/source/Expression/UtilityFunction.cpp @@ -1,4 +1,4 @@ -//===-- ClangUserExpression.cpp -------------------------------------*- C++ -*-===// +//===-- UtilityFunction.cpp -------------------------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -10,7 +10,7 @@ // C Includes #include <stdio.h> #if HAVE_SYS_TYPES_H -# include <sys/types.h> +#include <sys/types.h> #endif // C++ Includes @@ -42,85 +42,74 @@ using namespace lldb; /// @param[in] name /// The name of the function, as used in the text. //------------------------------------------------------------------ -UtilityFunction::UtilityFunction (ExecutionContextScope &exe_scope, - const char *text, - const char *name) : - Expression (exe_scope), - m_execution_unit_sp (), - m_jit_module_wp (), - m_function_text (ExpressionSourceCode::g_expression_prefix), - m_function_name (name) -{ - if (text && text[0]) - m_function_text.append (text); +UtilityFunction::UtilityFunction(ExecutionContextScope &exe_scope, + const char *text, const char *name) + : Expression(exe_scope), m_execution_unit_sp(), m_jit_module_wp(), + m_function_text(ExpressionSourceCode::g_expression_prefix), + m_function_name(name) { + if (text && text[0]) + m_function_text.append(text); } -UtilityFunction::~UtilityFunction () -{ - lldb::ProcessSP process_sp (m_jit_process_wp.lock()); - if (process_sp) - { - lldb::ModuleSP jit_module_sp (m_jit_module_wp.lock()); - if (jit_module_sp) - process_sp->GetTarget().GetImages().Remove(jit_module_sp); - } - +UtilityFunction::~UtilityFunction() { + lldb::ProcessSP process_sp(m_jit_process_wp.lock()); + if (process_sp) { + lldb::ModuleSP jit_module_sp(m_jit_module_wp.lock()); + if (jit_module_sp) + process_sp->GetTarget().GetImages().Remove(jit_module_sp); + } } -// FIXME: We should check that every time this is called it is called with the same return type & arguments... +// FIXME: We should check that every time this is called it is called with the +// same return type & arguments... -FunctionCaller * -UtilityFunction::MakeFunctionCaller (const CompilerType &return_type, const ValueList &arg_value_list, lldb::ThreadSP thread_to_use_sp, Error &error) -{ - if (m_caller_up) - return m_caller_up.get(); - - ProcessSP process_sp = m_jit_process_wp.lock(); - if (!process_sp) - { - error.SetErrorString("Can't make a function caller without a process."); - return nullptr; - } - - Address impl_code_address; - impl_code_address.SetOffset(StartAddress()); - std::string name(m_function_name); - name.append("-caller"); - - m_caller_up.reset (process_sp->GetTarget().GetFunctionCallerForLanguage (Language(), - return_type, - impl_code_address, - arg_value_list, - name.c_str(), - error)); - if (error.Fail()) - { - - return nullptr; - } - if (m_caller_up) - { - DiagnosticManager diagnostics; +FunctionCaller *UtilityFunction::MakeFunctionCaller( + const CompilerType &return_type, const ValueList &arg_value_list, + lldb::ThreadSP thread_to_use_sp, Error &error) { + if (m_caller_up) + return m_caller_up.get(); + + ProcessSP process_sp = m_jit_process_wp.lock(); + if (!process_sp) { + error.SetErrorString("Can't make a function caller without a process."); + return nullptr; + } - unsigned num_errors = m_caller_up->CompileFunction(thread_to_use_sp, diagnostics); - if (num_errors) - { - error.SetErrorStringWithFormat("Error compiling %s caller function: \"%s\".", m_function_name.c_str(), - diagnostics.GetString().c_str()); - m_caller_up.reset(); - return nullptr; - } + Address impl_code_address; + impl_code_address.SetOffset(StartAddress()); + std::string name(m_function_name); + name.append("-caller"); - diagnostics.Clear(); - ExecutionContext exe_ctx(process_sp); + m_caller_up.reset(process_sp->GetTarget().GetFunctionCallerForLanguage( + Language(), return_type, impl_code_address, arg_value_list, name.c_str(), + error)); + if (error.Fail()) { - if (!m_caller_up->WriteFunctionWrapper(exe_ctx, diagnostics)) - { - error.SetErrorStringWithFormat("Error inserting caller function for %s: \"%s\".", m_function_name.c_str(), - diagnostics.GetString().c_str()); - m_caller_up.reset(); - return nullptr; - } + return nullptr; + } + if (m_caller_up) { + DiagnosticManager diagnostics; + + unsigned num_errors = + m_caller_up->CompileFunction(thread_to_use_sp, diagnostics); + if (num_errors) { + error.SetErrorStringWithFormat( + "Error compiling %s caller function: \"%s\".", + m_function_name.c_str(), diagnostics.GetString().c_str()); + m_caller_up.reset(); + return nullptr; } - return m_caller_up.get(); + + diagnostics.Clear(); + ExecutionContext exe_ctx(process_sp); + + if (!m_caller_up->WriteFunctionWrapper(exe_ctx, diagnostics)) { + error.SetErrorStringWithFormat( + "Error inserting caller function for %s: \"%s\".", + m_function_name.c_str(), diagnostics.GetString().c_str()); + m_caller_up.reset(); + return nullptr; + } + } + return m_caller_up.get(); } |