diff options
Diffstat (limited to 'lldb/source/Expression/DWARFExpression.cpp')
-rw-r--r-- | lldb/source/Expression/DWARFExpression.cpp | 6375 |
1 files changed, 3145 insertions, 3230 deletions
diff --git a/lldb/source/Expression/DWARFExpression.cpp b/lldb/source/Expression/DWARFExpression.cpp index 23a922c491b..446377e3b10 100644 --- a/lldb/source/Expression/DWARFExpression.cpp +++ b/lldb/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" @@ -46,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; @@ -703,2784 +745,2657 @@ 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; - 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; + default: + const_offset = 0; + const_value = 0; + const_byte_size = 0; + break; } - 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()) + + 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; + } + } + + // 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; +} - 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; +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; + } - if (IsLocationList()) - { - lldb::offset_t offset = 0; + if (base_addr != LLDB_INVALID_ADDRESS && pc != LLDB_INVALID_ADDRESS) { + addr_t curr_base_addr = base_addr; - if (loclist_base_addr == LLDB_INVALID_ADDRESS) - return false; + 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; - 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; - if (lo_pc == 0 && hi_pc == 0) - break; + lo_pc += curr_base_addr - m_loclist_slide; + hi_pc += curr_base_addr - m_loclist_slide; - lo_pc += loclist_base_addr - m_loclist_slide; - hi_pc += loclist_base_addr - m_loclist_slide; + length = m_data.GetU16(&offset); - if (lo_pc <= addr && addr < hi_pc) - return true; - - offset += m_data.GetU16(&offset); - } - } - 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(); + 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(); - } +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 (loclist_base_load_addr != LLDB_INVALID_ADDRESS) - { - if (pc == LLDB_INVALID_ADDRESS) - { - if (error_ptr) - error_ptr->SetErrorString("Invalid PC in frame."); - return false; - } - - 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; + } + } 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; - //---------------------------------------------------------------------- - // 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; + 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; - } - } + 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); } - 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; - } - 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; - - //---------------------------------------------------------------------- - // 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; - } - - if (!exe_ctx || !module_sp) - { - if (error_ptr) - error_ptr->SetErrorString("No context to evaluate TLS within."); - return false; - } + if (!exe_ctx || !module_sp) { + if (error_ptr) + error_ptr->SetErrorString("No context to evaluate TLS within."); + return false; + } - Thread *thread = exe_ctx->GetThreadPtr(); - if (!thread) - { - if (error_ptr) - error_ptr->SetErrorString("No thread to evaluate TLS within."); - return false; - } + Thread *thread = exe_ctx->GetThreadPtr(); + if (!thread) { + if (error_ptr) + error_ptr->SetErrorString("No thread to evaluate TLS within."); + 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); + // 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 (tls_load_addr == LLDB_INVALID_ADDRESS) - { - if (error_ptr) - error_ptr->SetErrorString ("No TLS data currently exists for this thread."); - 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; - stack.back().GetScalar() = tls_load_addr; - stack.back().SetValueType (Value::eValueTypeLoadAddress); - } - 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 +} - //---------------------------------------------------------------------- - // 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; +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; +} - //---------------------------------------------------------------------- - // 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; +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; - default: - if (log) - log->Printf("Unhandled opcode %s in DWARFExpression.", DW_OP_value_to_name(op)); - break; - } + 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; } - - 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; - } + 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; } - 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(); + default: + // Not supported entry type + return false; } - return true; // Return true on success + } + assert(false && "Not supported location list type"); + 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; +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; - if (start_addr == 0 && end_addr == 0) - break; + int size; - uint16_t loc_length = debug_loc_data.GetU16(&offset); - offset += loc_length; - } + opcode_class = DW_OP_value_to_class(opcode) & (~DRC_DWARFv3); - if (offset > debug_loc_offset) - return offset - debug_loc_offset; - return 0; -} + s.Printf("%s ", DW_OP_value_to_name(opcode)); -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; + /* Does this take zero parameters? If so we can shortcut this function. */ + if (opcode_class == DRC_ZEROOPERANDS) + return true; - 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 (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; } -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; - - int size; +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; +} - opcode_class = DW_OP_value_to_class (opcode) & (~DRC_DWARFv3); +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; + } +} - s.Printf("%s ", DW_OP_value_to_name (opcode)); +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; + } - /* Does this take zero parameters? If so we can shortcut this function. */ - if (opcode_class == DRC_ZEROOPERANDS) - return true; + addr_t loclist_base_file_addr = + sc.function->GetAddressRange().GetBaseAddress().GetFileAddress(); + if (loclist_base_file_addr == LLDB_INVALID_ADDRESS) { + return false; + } - 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; - } + 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 (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; - } + if (opcodes_length == 0) { + 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; - } + op_offset = opcodes_offset; + end_offset = opcodes_offset + opcodes_length; + return true; +} +bool DWARFExpression::IsRegister(StackFrame &frame, + const RegisterInfo *®ister_info) { + lldb::offset_t op_offset; + lldb::offset_t end_offset; + if (!GetOpAndEndOffsets(frame, op_offset, end_offset)) { 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 (!m_data.ValidOffset(op_offset) || op_offset >= end_offset) { + return false; + } - return true; + RegisterContextSP reg_ctx_sp = frame.GetRegisterContext(); + if (!reg_ctx_sp) { + return false; + } + + DataExtractor opcodes = m_data; + uint8_t opcode = opcodes.GetU8(&op_offset); + + if (opcode >= DW_OP_reg0 && opcode <= DW_OP_breg31) { + register_info = + reg_ctx_sp->GetRegisterInfo(m_reg_kind, opcode - DW_OP_reg0); + return register_info != nullptr; + } + switch (opcode) { + default: + return false; + case DW_OP_regx: { + uint32_t reg_num = m_data.GetULEB128(&op_offset); + register_info = reg_ctx_sp->GetRegisterInfo(m_reg_kind, reg_num); + return register_info != nullptr; + } + } } -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); +bool DWARFExpression::IsDereferenceOfRegister( + StackFrame &frame, const RegisterInfo *®ister_info, int64_t &offset) { + lldb::offset_t op_offset; + lldb::offset_t end_offset; + if (!GetOpAndEndOffsets(frame, op_offset, end_offset)) { + return false; + } - if (start_addr == 0 && end_addr == 0) - break; + if (!m_data.ValidOffset(op_offset) || op_offset >= end_offset) { + return false; + } - 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; - } -} + RegisterContextSP reg_ctx_sp = frame.GetRegisterContext(); + if (!reg_ctx_sp) { + return false; + } -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; - } + DataExtractor opcodes = m_data; + uint8_t opcode = opcodes.GetU8(&op_offset); - addr_t loclist_base_file_addr = sc.function->GetAddressRange().GetBaseAddress().GetFileAddress(); - if (loclist_base_file_addr == LLDB_INVALID_ADDRESS) - { - 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; - } - - if (opcodes_length == 0) - { - return false; + switch (opcode) { + default: + return false; + case DW_OP_bregx: { + uint32_t reg_num = static_cast<uint32_t>(opcodes.GetULEB128(&op_offset)); + int64_t breg_offset = opcodes.GetSLEB128(&op_offset); + + const RegisterInfo *reg_info = + reg_ctx_sp->GetRegisterInfo(m_reg_kind, reg_num); + if (!reg_info) { + return false; } - - op_offset = opcodes_offset; - end_offset = opcodes_offset + opcodes_length; + + register_info = reg_info; + offset = breg_offset; return true; -} + } + case DW_OP_fbreg: { + int64_t fbreg_offset = opcodes.GetSLEB128(&op_offset); -bool -DWARFExpression::IsRegister(StackFrame &frame, - const RegisterInfo *®ister_info) -{ - lldb::offset_t op_offset; - lldb::offset_t end_offset; - if (!GetOpAndEndOffsets(frame, op_offset, end_offset)) - { - return false; - } + DWARFExpression *dwarf_expression = frame.GetFrameBaseExpression(nullptr); - if (!m_data.ValidOffset(op_offset) || op_offset >= end_offset) - { - return false; - } - - RegisterContextSP reg_ctx_sp = frame.GetRegisterContext(); - if (!reg_ctx_sp) - { - return false; - } - - DataExtractor opcodes = m_data; - uint8_t opcode = opcodes.GetU8(&op_offset); - - if (opcode >= DW_OP_reg0 && opcode <= DW_OP_breg31) - { - register_info = reg_ctx_sp->GetRegisterInfo(m_reg_kind, opcode - DW_OP_reg0); - return register_info != nullptr; - } - switch (opcode) - { - default: - return false; - case DW_OP_regx: - { - uint32_t reg_num = m_data.GetULEB128(&op_offset); - register_info = reg_ctx_sp->GetRegisterInfo(m_reg_kind, reg_num); - return register_info != nullptr; - } + if (!dwarf_expression) { + return false; } -} -bool -DWARFExpression::IsDereferenceOfRegister(StackFrame &frame, - const RegisterInfo *®ister_info, - int64_t &offset) -{ - lldb::offset_t op_offset; - lldb::offset_t end_offset; - if (!GetOpAndEndOffsets(frame, op_offset, end_offset)) - { - return false; - } - - if (!m_data.ValidOffset(op_offset) || op_offset >= end_offset) - { - return false; - } - - RegisterContextSP reg_ctx_sp = frame.GetRegisterContext(); - if (!reg_ctx_sp) - { - return false; - } - - DataExtractor opcodes = m_data; - uint8_t opcode = opcodes.GetU8(&op_offset); + const RegisterInfo *fbr_info; - switch (opcode) - { - default: - return false; - case DW_OP_bregx: - { - uint32_t reg_num = static_cast<uint32_t>(opcodes.GetULEB128(&op_offset)); - int64_t breg_offset = opcodes.GetSLEB128(&op_offset); - - const RegisterInfo *reg_info = reg_ctx_sp->GetRegisterInfo(m_reg_kind, reg_num); - if (!reg_info) - { - return false; - } - - register_info = reg_info; - offset = breg_offset; - return true; - } - case DW_OP_fbreg: - { - int64_t fbreg_offset = opcodes.GetSLEB128(&op_offset); - - DWARFExpression *dwarf_expression = frame.GetFrameBaseExpression(nullptr); - - if (!dwarf_expression) - { - return false; - } - - const RegisterInfo *fbr_info; - - if (!dwarf_expression->IsRegister(frame, fbr_info)) - { - return false; - } - - register_info = fbr_info; - offset = fbreg_offset; - return true; - } + if (!dwarf_expression->IsRegister(frame, fbr_info)) { + return false; } -} + register_info = fbr_info; + offset = fbreg_offset; + return true; + } + } +} |