*** This commit represents a complete reformatting of the LLDB source code
*** to conform to clang-format’s LLVM style. This kind of mass change has
*** two obvious implications:
Firstly, merging this particular commit into a downstream fork may be a huge
effort. Alternatively, it may be worth merging all changes up to this commit,
performing the same reformatting operation locally, and then discarding the
merge for this particular commit. The commands used to accomplish this
reformatting were as follows (with current working directory as the root of
the repository):
find . \( -iname "*.c" -or -iname "*.cpp" -or -iname "*.h" -or -iname "*.mm" \) -exec clang-format -i {} +
find . -iname "*.py" -exec autopep8 --in-place --aggressive --aggressive {} + ;
The version of clang-format used was 3.9.0, and autopep8 was 1.2.4.
Secondly, “blame” style tools will generally point to this commit instead of
a meaningful prior commit. There are alternatives available that will attempt
to look through this change and find the appropriate prior commit. YMMV.
llvm-svn: 280751
diff --git a/lldb/source/Expression/DWARFExpression.cpp b/lldb/source/Expression/DWARFExpression.cpp
index 23a922c..446377e 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_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(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(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; }
+
+void DWARFExpression::SetOpcodeData(const DataExtractor &data) {
+ m_data = data;
}
-
-bool
-DWARFExpression::IsValid() const
-{
- return m_data.GetByteSize() > 0;
-}
-
-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 (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::SetOpcodeData (lldb::ModuleSP module_sp, const DataExtractor& data, lldb::offset_t data_offset, lldb::offset_t data_length)
-{
+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(data, data_offset, data_length);
+ m_data.SetData(DataBufferSP(new DataBufferHeap(bytes, data_length)));
+ m_data.SetByteOrder(data.GetByteOrder());
+ m_data.SetAddressByteSize(data.GetAddressByteSize());
+ }
}
-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);
+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);
+ }
+}
- switch (level)
- {
- default:
- break;
+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);
+ }
+}
- case lldb::eDescriptionLevelBrief:
- if (offset > start_offset)
- s->PutChar(' ');
- break;
+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);
+}
- 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) {
+ const lldb::offset_t op_offset = offset;
+ const uint8_t op = m_data.GetU8(&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;
+ switch (level) {
+ default:
+ 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 lldb::eDescriptionLevelBrief:
+ if (offset > start_offset)
+ s->PutChar(' ');
+ break;
- 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
- 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;
- }
+ 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::SetLocationListSlide (addr_t slide)
-{
- m_loclist_slide = slide;
-}
+ 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;
-int
-DWARFExpression::GetRegisterKind ()
-{
- return m_reg_kind;
-}
+ 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
-void
-DWARFExpression::SetRegisterKind (RegisterKind reg_kind)
-{
- m_reg_kind = reg_kind;
-}
+ 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
-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())
+ 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
{
- // 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++;
+ 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;
+ }
}
- }
- else
+ }
+ 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
{
- // We have a normal location that contains DW_OP location opcodes
- DumpLocation (s, 0, m_data.GetByteSize(), level, abi);
+ 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
+ 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;
}
+ }
}
-static bool
-ReadRegisterValueAsScalar
-(
- RegisterContext *reg_ctx,
- lldb::RegisterKind reg_kind,
- uint32_t reg_num,
- Error *error_ptr,
- Value &value
-)
-{
- if (reg_ctx == NULL)
- {
+void DWARFExpression::SetLocationListSlide(addr_t slide) {
+ m_loclist_slide = slide;
+}
+
+int DWARFExpression::GetRegisterKind() { return m_reg_kind; }
+
+void DWARFExpression::SetRegisterKind(RegisterKind reg_kind) {
+ m_reg_kind = reg_kind;
+}
+
+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++;
+ }
+ } 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("No register context in frame.\n");
+ error_ptr->SetErrorStringWithFormat("register %s is not available",
+ reg_info->name);
+ }
}
- 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 @@
// 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();
+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;
- }
- 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 LLDB_INVALID_ADDRESS;
-}
-
-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;
-
- // 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;
-
- const uint32_t addr_byte_size = m_data.GetAddressByteSize();
- // We have to make a copy of the data as we don't know if this
- // data is from a read only memory mapped buffer, so we duplicate
- // all of the data first, then modify it, and if all goes well,
- // we then replace the data for this expression
-
- // So first we copy the data into a heap buffer
- std::shared_ptr<DataBufferHeap> heap_data_sp(new DataBufferHeap(m_data.GetDataStart(), m_data.GetByteSize()));
-
- // Make en encoder so we can write the address into the buffer using
- // the correct byte order (endianness)
- DataEncoder encoder(heap_data_sp->GetBytes(), heap_data_sp->GetByteSize(), m_data.GetByteOrder(), addr_byte_size);
-
- lldb::offset_t offset = 0;
- lldb::offset_t const_offset = 0;
- lldb::addr_t const_value = 0;
- size_t const_byte_size = 0;
- while (m_data.ValidOffset(offset))
- {
- const uint8_t op = m_data.GetU8(&offset);
-
- bool decoded_data = false;
- switch (op)
- {
- case DW_OP_const4u:
- // Remember the const offset in case we later have a DW_OP_form_tls_address
- // or DW_OP_GNU_push_tls_address
- const_offset = offset;
- const_value = m_data.GetU32(&offset);
- decoded_data = true;
- const_byte_size = 4;
- break;
-
- case DW_OP_const8u:
- // Remember the const offset in case we later have a DW_OP_form_tls_address
- // or DW_OP_GNU_push_tls_address
- const_offset = offset;
- const_value = m_data.GetU64(&offset);
- decoded_data = true;
- const_byte_size = 8;
- break;
-
- case DW_OP_form_tls_address:
- case DW_OP_GNU_push_tls_address:
- // DW_OP_form_tls_address and DW_OP_GNU_push_tls_address must be preceded by
- // a file address on the stack. We assume that DW_OP_const4u or DW_OP_const8u
- // is used for these values, and we check that the last opcode we got before
- // either of these was DW_OP_const4u or DW_OP_const8u. If so, then we can link
- // the value accodingly. For Darwin, the value in the DW_OP_const4u or
- // DW_OP_const8u is the file address of a structure that contains a function
- // pointer, the pthread key and the offset into the data pointed to by the
- // pthread key. So we must link this address and also set the module of this
- // expression to the new_module_sp so we can resolve the file address correctly
- if (const_byte_size > 0)
- {
- lldb::addr_t linked_file_addr = link_address_callback(const_value);
- if (linked_file_addr == LLDB_INVALID_ADDRESS)
- return false;
- // Replace the address in the new buffer
- if (encoder.PutMaxU64(const_offset, const_byte_size, linked_file_addr) == UINT32_MAX)
- return false;
- }
- break;
-
- default:
- const_offset = 0;
- const_value = 0;
- const_byte_size = 0;
- break;
- }
-
- if (!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;
-}
-
-bool
-DWARFExpression::LocationListContainsAddress(lldb::addr_t loclist_base_addr, lldb::addr_t addr) const
-{
- if (addr == LLDB_INVALID_ADDRESS)
- return false;
-
- if (IsLocationList())
- {
- lldb::offset_t offset = 0;
-
- if (loclist_base_addr == LLDB_INVALID_ADDRESS)
- return false;
-
- 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 += loclist_base_addr - m_loclist_slide;
- hi_pc += loclist_base_addr - m_loclist_slide;
-
- 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();
- 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 = 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;
- }
- }
- 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
-(
- ExecutionContext *exe_ctx,
- ClangExpressionVariableList *expr_locals,
- ClangExpressionDeclMap *decl_map,
- RegisterContext *reg_ctx,
- lldb::addr_t loclist_base_load_addr,
- const Value* initial_value_ptr,
- const Value* object_address_ptr,
- Value& result,
- Error *error_ptr
-) const
-{
- ModuleSP module_sp = m_module_wp.lock();
-
- if (IsLocationList())
- {
- lldb::offset_t offset = 0;
- addr_t pc;
- StackFrame *frame = NULL;
- if (reg_ctx)
- pc = reg_ctx->GetPC();
- else
- {
- frame = exe_ctx->GetFramePtr();
- if (!frame)
- return false;
- RegisterContextSP reg_ctx_sp = frame->GetRegisterContext();
- if (!reg_ctx_sp)
- return false;
- pc = reg_ctx_sp->GetPC();
- }
-
- if (loclist_base_load_addr != LLDB_INVALID_ADDRESS)
- {
- if (pc == LLDB_INVALID_ADDRESS)
- {
- if (error_ptr)
- error_ptr->SetErrorString("Invalid PC in frame.");
- return false;
- }
-
- 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");
- return false;
- }
-
- // 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 (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->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;
- }
-
- }
- break;
-
- //----------------------------------------------------------------------
- // OPCODE: DW_OP_xderef_size
- // OPERANDS: 1
- // 1 - uint8_t that specifies the size of the data to dereference.
- // DESCRIPTION: Behaves like the DW_OP_xderef operation: the entry at
- // the top of the stack is treated as an address. The second stack
- // entry is treated as an "address space identifier" for those
- // architectures that support multiple address spaces. The top two
- // stack elements are popped, a data item is retrieved through an
- // implementation-defined address calculation and pushed as the new
- // stack top. In the DW_OP_xderef_size operation, however, the size in
- // bytes of the data retrieved from the dereferenced address is
- // specified by the single operand. This operand is a 1-byte unsigned
- // integral constant whose value may not be larger than the size of an
- // address on the target machine. The data retrieved is zero extended
- // to the size of an address on the target machine before being pushed
- // on the expression stack.
- //----------------------------------------------------------------------
- case DW_OP_xderef_size:
- if (error_ptr)
- error_ptr->SetErrorString("Unimplemented opcode: DW_OP_xderef_size.");
- return false;
- //----------------------------------------------------------------------
- // OPCODE: DW_OP_xderef
- // OPERANDS: none
- // DESCRIPTION: Provides an extended dereference mechanism. The entry at
- // the top of the stack is treated as an address. The second stack entry
- // is treated as an "address space identifier" for those architectures
- // that support multiple address spaces. The top two stack elements are
- // popped, a data item is retrieved through an implementation-defined
- // address calculation and pushed as the new stack top. The size of the
- // data retrieved from the dereferenced address is the size of an address
- // on the target machine.
- //----------------------------------------------------------------------
- case DW_OP_xderef:
- if (error_ptr)
- error_ptr->SetErrorString("Unimplemented opcode: DW_OP_xderef.");
- return false;
-
- //----------------------------------------------------------------------
- // All DW_OP_constXXX opcodes have a single operand as noted below:
- //
- // Opcode Operand 1
- // --------------- ----------------------------------------------------
- // DW_OP_const1u 1-byte unsigned integer constant
- // DW_OP_const1s 1-byte signed integer constant
- // DW_OP_const2u 2-byte unsigned integer constant
- // DW_OP_const2s 2-byte signed integer constant
- // DW_OP_const4u 4-byte unsigned integer constant
- // DW_OP_const4s 4-byte signed integer constant
- // DW_OP_const8u 8-byte unsigned integer constant
- // DW_OP_const8s 8-byte signed integer constant
- // DW_OP_constu unsigned LEB128 integer constant
- // DW_OP_consts signed LEB128 integer constant
- //----------------------------------------------------------------------
- case DW_OP_const1u : stack.push_back(Scalar(( uint8_t)opcodes.GetU8 (&offset))); break;
- case DW_OP_const1s : stack.push_back(Scalar(( int8_t)opcodes.GetU8 (&offset))); break;
- case DW_OP_const2u : stack.push_back(Scalar((uint16_t)opcodes.GetU16 (&offset))); break;
- case DW_OP_const2s : stack.push_back(Scalar(( int16_t)opcodes.GetU16 (&offset))); break;
- case DW_OP_const4u : stack.push_back(Scalar((uint32_t)opcodes.GetU32 (&offset))); break;
- case DW_OP_const4s : stack.push_back(Scalar(( int32_t)opcodes.GetU32 (&offset))); break;
- case DW_OP_const8u : stack.push_back(Scalar((uint64_t)opcodes.GetU64 (&offset))); break;
- case DW_OP_const8s : stack.push_back(Scalar(( int64_t)opcodes.GetU64 (&offset))); break;
- case DW_OP_constu : stack.push_back(Scalar(opcodes.GetULEB128 (&offset))); break;
- case DW_OP_consts : stack.push_back(Scalar(opcodes.GetSLEB128 (&offset))); break;
-
- //----------------------------------------------------------------------
- // OPCODE: DW_OP_dup
- // OPERANDS: none
- // DESCRIPTION: duplicates the value at the top of the stack
- //----------------------------------------------------------------------
- case DW_OP_dup:
- if (stack.empty())
- {
- if (error_ptr)
- error_ptr->SetErrorString("Expression stack empty for DW_OP_dup.");
- return false;
- }
- else
- stack.push_back(stack.back());
- break;
-
- //----------------------------------------------------------------------
- // OPCODE: DW_OP_drop
- // OPERANDS: none
- // DESCRIPTION: pops the value at the top of the stack
- //----------------------------------------------------------------------
- case DW_OP_drop:
- if (stack.empty())
- {
- if (error_ptr)
- error_ptr->SetErrorString("Expression stack empty for DW_OP_drop.");
- return false;
- }
- else
- stack.pop_back();
- break;
-
- //----------------------------------------------------------------------
- // OPCODE: DW_OP_over
- // OPERANDS: none
- // DESCRIPTION: Duplicates the entry currently second in the stack at
- // the top of the stack.
- //----------------------------------------------------------------------
- case DW_OP_over:
- if (stack.size() < 2)
- {
- if (error_ptr)
- error_ptr->SetErrorString("Expression stack needs at least 2 items for DW_OP_over.");
- return false;
- }
- else
- stack.push_back(stack[stack.size() - 2]);
- break;
-
-
- //----------------------------------------------------------------------
- // OPCODE: DW_OP_pick
- // OPERANDS: uint8_t index into the current stack
- // DESCRIPTION: The stack entry with the specified index (0 through 255,
- // inclusive) is pushed on the stack
- //----------------------------------------------------------------------
- case DW_OP_pick:
- {
- uint8_t pick_idx = opcodes.GetU8(&offset);
- if (pick_idx < stack.size())
- stack.push_back(stack[pick_idx]);
- else
- {
- if (error_ptr)
- error_ptr->SetErrorStringWithFormat("Index %u out of range for DW_OP_pick.\n", pick_idx);
- return false;
- }
- }
- break;
-
- //----------------------------------------------------------------------
- // OPCODE: DW_OP_swap
- // OPERANDS: none
- // DESCRIPTION: swaps the top two stack entries. The entry at the top
- // of the stack becomes the second stack entry, and the second entry
- // becomes the top of the stack
- //----------------------------------------------------------------------
- case DW_OP_swap:
- if (stack.size() < 2)
- {
- if (error_ptr)
- error_ptr->SetErrorString("Expression stack needs at least 2 items for DW_OP_swap.");
- return false;
- }
- else
- {
- tmp = stack.back();
- stack.back() = stack[stack.size() - 2];
- stack[stack.size() - 2] = tmp;
- }
- break;
-
- //----------------------------------------------------------------------
- // OPCODE: DW_OP_rot
- // OPERANDS: none
- // DESCRIPTION: Rotates the first three stack entries. The entry at
- // the top of the stack becomes the third stack entry, the second
- // entry becomes the top of the stack, and the third entry becomes
- // the second entry.
- //----------------------------------------------------------------------
- case DW_OP_rot:
- if (stack.size() < 3)
- {
- if (error_ptr)
- error_ptr->SetErrorString("Expression stack needs at least 3 items for DW_OP_rot.");
- return false;
- }
- else
- {
- size_t last_idx = stack.size() - 1;
- Value old_top = stack[last_idx];
- stack[last_idx] = stack[last_idx - 1];
- stack[last_idx - 1] = stack[last_idx - 2];
- stack[last_idx - 2] = old_top;
- }
- break;
-
- //----------------------------------------------------------------------
- // OPCODE: DW_OP_abs
- // OPERANDS: none
- // DESCRIPTION: pops the top stack entry, interprets it as a signed
- // value and pushes its absolute value. If the absolute value can not be
- // represented, the result is undefined.
- //----------------------------------------------------------------------
- case DW_OP_abs:
- if (stack.empty())
- {
- if (error_ptr)
- error_ptr->SetErrorString("Expression stack needs at least 1 item for DW_OP_abs.");
- return false;
- }
- else if (stack.back().ResolveValue(exe_ctx).AbsoluteValue() == false)
- {
- if (error_ptr)
- error_ptr->SetErrorString("Failed to take the absolute value of the first stack item.");
- return false;
- }
- break;
-
- //----------------------------------------------------------------------
- // OPCODE: DW_OP_and
- // OPERANDS: none
- // DESCRIPTION: pops the top two stack values, performs a bitwise and
- // operation on the two, and pushes the result.
- //----------------------------------------------------------------------
- case DW_OP_and:
- if (stack.size() < 2)
- {
- if (error_ptr)
- error_ptr->SetErrorString("Expression stack needs at least 2 items for DW_OP_and.");
- return false;
- }
- else
- {
- tmp = stack.back();
- stack.pop_back();
- stack.back().ResolveValue(exe_ctx) = stack.back().ResolveValue(exe_ctx) & tmp.ResolveValue(exe_ctx);
- }
- break;
-
- //----------------------------------------------------------------------
- // OPCODE: DW_OP_div
- // OPERANDS: none
- // DESCRIPTION: pops the top two stack values, divides the former second
- // entry by the former top of the stack using signed division, and
- // pushes the result.
- //----------------------------------------------------------------------
- case DW_OP_div:
- if (stack.size() < 2)
- {
- if (error_ptr)
- error_ptr->SetErrorString("Expression stack needs at least 2 items for DW_OP_div.");
- return false;
- }
- else
- {
- tmp = stack.back();
- if (tmp.ResolveValue(exe_ctx).IsZero())
- {
- if (error_ptr)
- error_ptr->SetErrorString("Divide by zero.");
- return false;
- }
- else
- {
- stack.pop_back();
- stack.back() = stack.back().ResolveValue(exe_ctx) / tmp.ResolveValue(exe_ctx);
- if (!stack.back().ResolveValue(exe_ctx).IsValid())
- {
- if (error_ptr)
- error_ptr->SetErrorString("Divide failed.");
- return false;
- }
- }
- }
- break;
-
- //----------------------------------------------------------------------
- // OPCODE: DW_OP_minus
- // OPERANDS: none
- // DESCRIPTION: pops the top two stack values, subtracts the former top
- // of the stack from the former second entry, and pushes the result.
- //----------------------------------------------------------------------
- case DW_OP_minus:
- if (stack.size() < 2)
- {
- if (error_ptr)
- error_ptr->SetErrorString("Expression stack needs at least 2 items for DW_OP_minus.");
- return false;
- }
- else
- {
- tmp = stack.back();
- stack.pop_back();
- stack.back().ResolveValue(exe_ctx) = stack.back().ResolveValue(exe_ctx) - tmp.ResolveValue(exe_ctx);
- }
- break;
-
- //----------------------------------------------------------------------
- // OPCODE: DW_OP_mod
- // OPERANDS: none
- // DESCRIPTION: pops the top two stack values and pushes the result of
- // the calculation: former second stack entry modulo the former top of
- // the stack.
- //----------------------------------------------------------------------
- case DW_OP_mod:
- if (stack.size() < 2)
- {
- if (error_ptr)
- error_ptr->SetErrorString("Expression stack needs at least 2 items for DW_OP_mod.");
- return false;
- }
- else
- {
- tmp = stack.back();
- stack.pop_back();
- stack.back().ResolveValue(exe_ctx) = stack.back().ResolveValue(exe_ctx) % tmp.ResolveValue(exe_ctx);
- }
- break;
-
-
- //----------------------------------------------------------------------
- // OPCODE: DW_OP_mul
- // OPERANDS: none
- // DESCRIPTION: pops the top two stack entries, multiplies them
- // together, and pushes the result.
- //----------------------------------------------------------------------
- case DW_OP_mul:
- if (stack.size() < 2)
- {
- if (error_ptr)
- error_ptr->SetErrorString("Expression stack needs at least 2 items for DW_OP_mul.");
- return false;
- }
- else
- {
- tmp = stack.back();
- stack.pop_back();
- stack.back().ResolveValue(exe_ctx) = stack.back().ResolveValue(exe_ctx) * tmp.ResolveValue(exe_ctx);
- }
- break;
-
- //----------------------------------------------------------------------
- // OPCODE: DW_OP_neg
- // OPERANDS: none
- // DESCRIPTION: pops the top stack entry, and pushes its negation.
- //----------------------------------------------------------------------
- case DW_OP_neg:
- if (stack.empty())
- {
- if (error_ptr)
- error_ptr->SetErrorString("Expression stack needs at least 1 item for DW_OP_neg.");
- return false;
- }
- else
- {
- if (stack.back().ResolveValue(exe_ctx).UnaryNegate() == false)
- {
- if (error_ptr)
- error_ptr->SetErrorString("Unary negate failed.");
- return false;
- }
- }
- break;
-
- //----------------------------------------------------------------------
- // OPCODE: DW_OP_not
- // OPERANDS: none
- // DESCRIPTION: pops the top stack entry, and pushes its bitwise
- // complement
- //----------------------------------------------------------------------
- case DW_OP_not:
- if (stack.empty())
- {
- if (error_ptr)
- error_ptr->SetErrorString("Expression stack needs at least 1 item for DW_OP_not.");
- return false;
- }
- else
- {
- if (stack.back().ResolveValue(exe_ctx).OnesComplement() == false)
- {
- if (error_ptr)
- error_ptr->SetErrorString("Logical NOT failed.");
- return false;
- }
- }
- break;
-
- //----------------------------------------------------------------------
- // OPCODE: DW_OP_or
- // OPERANDS: none
- // DESCRIPTION: pops the top two stack entries, performs a bitwise or
- // operation on the two, and pushes the result.
- //----------------------------------------------------------------------
- case DW_OP_or:
- if (stack.size() < 2)
- {
- if (error_ptr)
- error_ptr->SetErrorString("Expression stack needs at least 2 items for DW_OP_or.");
- return false;
- }
- else
- {
- tmp = stack.back();
- stack.pop_back();
- stack.back().ResolveValue(exe_ctx) = stack.back().ResolveValue(exe_ctx) | tmp.ResolveValue(exe_ctx);
- }
- break;
-
- //----------------------------------------------------------------------
- // OPCODE: DW_OP_plus
- // OPERANDS: none
- // DESCRIPTION: pops the top two stack entries, adds them together, and
- // pushes the result.
- //----------------------------------------------------------------------
- case DW_OP_plus:
- if (stack.size() < 2)
- {
- if (error_ptr)
- error_ptr->SetErrorString("Expression stack needs at least 2 items for DW_OP_plus.");
- return false;
- }
- else
- {
- tmp = stack.back();
- stack.pop_back();
- stack.back().GetScalar() += tmp.GetScalar();
- }
- break;
-
- //----------------------------------------------------------------------
- // OPCODE: DW_OP_plus_uconst
- // OPERANDS: none
- // DESCRIPTION: pops the top stack entry, adds it to the unsigned LEB128
- // constant operand and pushes the result.
- //----------------------------------------------------------------------
- case DW_OP_plus_uconst:
- if (stack.empty())
- {
- if (error_ptr)
- error_ptr->SetErrorString("Expression stack needs at least 1 item for DW_OP_plus_uconst.");
- return false;
- }
- else
- {
- const uint64_t uconst_value = opcodes.GetULEB128(&offset);
- // Implicit conversion from a UINT to a Scalar...
- stack.back().GetScalar() += uconst_value;
- if (!stack.back().GetScalar().IsValid())
- {
- if (error_ptr)
- error_ptr->SetErrorString("DW_OP_plus_uconst failed.");
- return false;
- }
- }
- break;
-
- //----------------------------------------------------------------------
- // OPCODE: DW_OP_shl
- // OPERANDS: none
- // DESCRIPTION: pops the top two stack entries, shifts the former
- // second entry left by the number of bits specified by the former top
- // of the stack, and pushes the result.
- //----------------------------------------------------------------------
- case DW_OP_shl:
- if (stack.size() < 2)
- {
- if (error_ptr)
- error_ptr->SetErrorString("Expression stack needs at least 2 items for DW_OP_shl.");
- return false;
- }
- else
- {
- tmp = stack.back();
- stack.pop_back();
- stack.back().ResolveValue(exe_ctx) <<= tmp.ResolveValue(exe_ctx);
- }
- break;
-
- //----------------------------------------------------------------------
- // OPCODE: DW_OP_shr
- // OPERANDS: none
- // DESCRIPTION: pops the top two stack entries, shifts the former second
- // entry right logically (filling with zero bits) by the number of bits
- // specified by the former top of the stack, and pushes the result.
- //----------------------------------------------------------------------
- case DW_OP_shr:
- if (stack.size() < 2)
- {
- if (error_ptr)
- error_ptr->SetErrorString("Expression stack needs at least 2 items for DW_OP_shr.");
- return false;
- }
- else
- {
- tmp = stack.back();
- stack.pop_back();
- if (stack.back().ResolveValue(exe_ctx).ShiftRightLogical(tmp.ResolveValue(exe_ctx)) == false)
- {
- if (error_ptr)
- error_ptr->SetErrorString("DW_OP_shr failed.");
- return false;
- }
- }
- break;
-
- //----------------------------------------------------------------------
- // OPCODE: DW_OP_shra
- // OPERANDS: none
- // DESCRIPTION: pops the top two stack entries, shifts the former second
- // entry right arithmetically (divide the magnitude by 2, keep the same
- // sign for the result) by the number of bits specified by the former
- // top of the stack, and pushes the result.
- //----------------------------------------------------------------------
- case DW_OP_shra:
- if (stack.size() < 2)
- {
- if (error_ptr)
- error_ptr->SetErrorString("Expression stack needs at least 2 items for DW_OP_shra.");
- return false;
- }
- else
- {
- tmp = stack.back();
- stack.pop_back();
- stack.back().ResolveValue(exe_ctx) >>= tmp.ResolveValue(exe_ctx);
- }
- break;
-
- //----------------------------------------------------------------------
- // OPCODE: DW_OP_xor
- // OPERANDS: none
- // DESCRIPTION: pops the top two stack entries, performs the bitwise
- // exclusive-or operation on the two, and pushes the result.
- //----------------------------------------------------------------------
- case DW_OP_xor:
- if (stack.size() < 2)
- {
- if (error_ptr)
- error_ptr->SetErrorString("Expression stack needs at least 2 items for DW_OP_xor.");
- return false;
- }
- else
- {
- tmp = stack.back();
- stack.pop_back();
- stack.back().ResolveValue(exe_ctx) = stack.back().ResolveValue(exe_ctx) ^ tmp.ResolveValue(exe_ctx);
- }
- break;
-
-
- //----------------------------------------------------------------------
- // OPCODE: DW_OP_skip
- // OPERANDS: int16_t
- // DESCRIPTION: An unconditional branch. Its single operand is a 2-byte
- // signed integer constant. The 2-byte constant is the number of bytes
- // of the DWARF expression to skip forward or backward from the current
- // operation, beginning after the 2-byte constant.
- //----------------------------------------------------------------------
- case DW_OP_skip:
- {
- int16_t skip_offset = (int16_t)opcodes.GetU16(&offset);
- lldb::offset_t new_offset = offset + skip_offset;
- if (new_offset >= opcodes_offset && new_offset < end_offset)
- offset = new_offset;
- else
- {
- if (error_ptr)
- error_ptr->SetErrorString("Invalid opcode offset in DW_OP_skip.");
- return false;
- }
- }
- break;
-
- //----------------------------------------------------------------------
- // OPCODE: DW_OP_bra
- // OPERANDS: int16_t
- // DESCRIPTION: A conditional branch. Its single operand is a 2-byte
- // signed integer constant. This operation pops the top of stack. If
- // the value popped is not the constant 0, the 2-byte constant operand
- // is the number of bytes of the DWARF expression to skip forward or
- // backward from the current operation, beginning after the 2-byte
- // constant.
- //----------------------------------------------------------------------
- case DW_OP_bra:
- if (stack.empty())
- {
- if (error_ptr)
- error_ptr->SetErrorString("Expression stack needs at least 1 item for DW_OP_bra.");
- return false;
- }
- else
- {
- tmp = stack.back();
- stack.pop_back();
- int16_t bra_offset = (int16_t)opcodes.GetU16(&offset);
- Scalar zero(0);
- if (tmp.ResolveValue(exe_ctx) != zero)
- {
- lldb::offset_t new_offset = offset + bra_offset;
- if (new_offset >= opcodes_offset && new_offset < end_offset)
- offset = new_offset;
- else
- {
- if (error_ptr)
- error_ptr->SetErrorString("Invalid opcode offset in DW_OP_bra.");
- return false;
- }
- }
- }
- break;
-
- //----------------------------------------------------------------------
- // OPCODE: DW_OP_eq
- // OPERANDS: none
- // DESCRIPTION: pops the top two stack values, compares using the
- // equals (==) operator.
- // STACK RESULT: push the constant value 1 onto the stack if the result
- // of the operation is true or the constant value 0 if the result of the
- // operation is false.
- //----------------------------------------------------------------------
- case DW_OP_eq:
- if (stack.size() < 2)
- {
- if (error_ptr)
- error_ptr->SetErrorString("Expression stack needs at least 2 items for DW_OP_eq.");
- return false;
- }
- else
- {
- tmp = stack.back();
- stack.pop_back();
- stack.back().ResolveValue(exe_ctx) = stack.back().ResolveValue(exe_ctx) == tmp.ResolveValue(exe_ctx);
- }
- break;
-
- //----------------------------------------------------------------------
- // OPCODE: DW_OP_ge
- // OPERANDS: none
- // DESCRIPTION: pops the top two stack values, compares using the
- // greater than or equal to (>=) operator.
- // STACK RESULT: push the constant value 1 onto the stack if the result
- // of the operation is true or the constant value 0 if the result of the
- // operation is false.
- //----------------------------------------------------------------------
- case DW_OP_ge:
- if (stack.size() < 2)
- {
- if (error_ptr)
- error_ptr->SetErrorString("Expression stack needs at least 2 items for DW_OP_ge.");
- return false;
- }
- else
- {
- tmp = stack.back();
- stack.pop_back();
- stack.back().ResolveValue(exe_ctx) = stack.back().ResolveValue(exe_ctx) >= tmp.ResolveValue(exe_ctx);
- }
- break;
-
- //----------------------------------------------------------------------
- // OPCODE: DW_OP_gt
- // OPERANDS: none
- // DESCRIPTION: pops the top two stack values, compares using the
- // greater than (>) operator.
- // STACK RESULT: push the constant value 1 onto the stack if the result
- // of the operation is true or the constant value 0 if the result of the
- // operation is false.
- //----------------------------------------------------------------------
- case DW_OP_gt:
- if (stack.size() < 2)
- {
- if (error_ptr)
- error_ptr->SetErrorString("Expression stack needs at least 2 items for DW_OP_gt.");
- return false;
- }
- else
- {
- tmp = stack.back();
- stack.pop_back();
- stack.back().ResolveValue(exe_ctx) = stack.back().ResolveValue(exe_ctx) > tmp.ResolveValue(exe_ctx);
- }
- break;
-
- //----------------------------------------------------------------------
- // OPCODE: DW_OP_le
- // OPERANDS: none
- // DESCRIPTION: pops the top two stack values, compares using the
- // less than or equal to (<=) operator.
- // STACK RESULT: push the constant value 1 onto the stack if the result
- // of the operation is true or the constant value 0 if the result of the
- // operation is false.
- //----------------------------------------------------------------------
- case DW_OP_le:
- if (stack.size() < 2)
- {
- if (error_ptr)
- error_ptr->SetErrorString("Expression stack needs at least 2 items for DW_OP_le.");
- return false;
- }
- else
- {
- tmp = stack.back();
- stack.pop_back();
- stack.back().ResolveValue(exe_ctx) = stack.back().ResolveValue(exe_ctx) <= tmp.ResolveValue(exe_ctx);
- }
- break;
-
- //----------------------------------------------------------------------
- // OPCODE: DW_OP_lt
- // OPERANDS: none
- // DESCRIPTION: pops the top two stack values, compares using the
- // less than (<) operator.
- // STACK RESULT: push the constant value 1 onto the stack if the result
- // of the operation is true or the constant value 0 if the result of the
- // operation is false.
- //----------------------------------------------------------------------
- case DW_OP_lt:
- if (stack.size() < 2)
- {
- if (error_ptr)
- error_ptr->SetErrorString("Expression stack needs at least 2 items for DW_OP_lt.");
- return false;
- }
- else
- {
- tmp = stack.back();
- stack.pop_back();
- stack.back().ResolveValue(exe_ctx) = stack.back().ResolveValue(exe_ctx) < tmp.ResolveValue(exe_ctx);
- }
- break;
-
- //----------------------------------------------------------------------
- // OPCODE: DW_OP_ne
- // OPERANDS: none
- // DESCRIPTION: pops the top two stack values, compares using the
- // not equal (!=) operator.
- // STACK RESULT: push the constant value 1 onto the stack if the result
- // of the operation is true or the constant value 0 if the result of the
- // operation is false.
- //----------------------------------------------------------------------
- case DW_OP_ne:
- if (stack.size() < 2)
- {
- if (error_ptr)
- error_ptr->SetErrorString("Expression stack needs at least 2 items for DW_OP_ne.");
- return false;
- }
- else
- {
- tmp = stack.back();
- stack.pop_back();
- stack.back().ResolveValue(exe_ctx) = stack.back().ResolveValue(exe_ctx) != tmp.ResolveValue(exe_ctx);
- }
- break;
-
- //----------------------------------------------------------------------
- // OPCODE: DW_OP_litn
- // OPERANDS: none
- // DESCRIPTION: encode the unsigned literal values from 0 through 31.
- // STACK RESULT: push the unsigned literal constant value onto the top
- // of the stack.
- //----------------------------------------------------------------------
- case DW_OP_lit0:
- case DW_OP_lit1:
- case DW_OP_lit2:
- case DW_OP_lit3:
- case DW_OP_lit4:
- case DW_OP_lit5:
- case DW_OP_lit6:
- case DW_OP_lit7:
- case DW_OP_lit8:
- case DW_OP_lit9:
- case DW_OP_lit10:
- case DW_OP_lit11:
- case DW_OP_lit12:
- case DW_OP_lit13:
- case DW_OP_lit14:
- case DW_OP_lit15:
- case DW_OP_lit16:
- case DW_OP_lit17:
- case DW_OP_lit18:
- case DW_OP_lit19:
- case DW_OP_lit20:
- case DW_OP_lit21:
- case DW_OP_lit22:
- case DW_OP_lit23:
- case DW_OP_lit24:
- case DW_OP_lit25:
- case DW_OP_lit26:
- case DW_OP_lit27:
- case DW_OP_lit28:
- case DW_OP_lit29:
- case DW_OP_lit30:
- case DW_OP_lit31:
- stack.push_back(Scalar(op - DW_OP_lit0));
- break;
-
- //----------------------------------------------------------------------
- // OPCODE: DW_OP_regN
- // OPERANDS: none
- // DESCRIPTION: Push the value in register n on the top of the stack.
- //----------------------------------------------------------------------
- case DW_OP_reg0:
- case DW_OP_reg1:
- case DW_OP_reg2:
- case DW_OP_reg3:
- case DW_OP_reg4:
- case DW_OP_reg5:
- case DW_OP_reg6:
- case DW_OP_reg7:
- case DW_OP_reg8:
- case DW_OP_reg9:
- case DW_OP_reg10:
- case DW_OP_reg11:
- case DW_OP_reg12:
- case DW_OP_reg13:
- case DW_OP_reg14:
- case DW_OP_reg15:
- case DW_OP_reg16:
- case DW_OP_reg17:
- case DW_OP_reg18:
- case DW_OP_reg19:
- case DW_OP_reg20:
- case DW_OP_reg21:
- case DW_OP_reg22:
- case DW_OP_reg23:
- case DW_OP_reg24:
- case DW_OP_reg25:
- case DW_OP_reg26:
- case DW_OP_reg27:
- case DW_OP_reg28:
- case DW_OP_reg29:
- case DW_OP_reg30:
- case DW_OP_reg31:
- {
- reg_num = op - DW_OP_reg0;
-
- if (ReadRegisterValueAsScalar (reg_ctx, reg_kind, reg_num, error_ptr, tmp))
- stack.push_back(tmp);
- else
- return false;
- }
- break;
- //----------------------------------------------------------------------
- // OPCODE: DW_OP_regx
- // OPERANDS:
- // ULEB128 literal operand that encodes the register.
- // DESCRIPTION: Push the value in register on the top of the stack.
- //----------------------------------------------------------------------
- case DW_OP_regx:
- {
- reg_num = opcodes.GetULEB128(&offset);
- if (ReadRegisterValueAsScalar (reg_ctx, reg_kind, reg_num, error_ptr, tmp))
- stack.push_back(tmp);
- else
- return false;
- }
- break;
-
- //----------------------------------------------------------------------
- // OPCODE: DW_OP_bregN
- // OPERANDS:
- // SLEB128 offset from register N
- // DESCRIPTION: Value is in memory at the address specified by register
- // N plus an offset.
- //----------------------------------------------------------------------
- case DW_OP_breg0:
- case DW_OP_breg1:
- case DW_OP_breg2:
- case DW_OP_breg3:
- case DW_OP_breg4:
- case DW_OP_breg5:
- case DW_OP_breg6:
- case DW_OP_breg7:
- case DW_OP_breg8:
- case DW_OP_breg9:
- case DW_OP_breg10:
- case DW_OP_breg11:
- case DW_OP_breg12:
- case DW_OP_breg13:
- case DW_OP_breg14:
- case DW_OP_breg15:
- case DW_OP_breg16:
- case DW_OP_breg17:
- case DW_OP_breg18:
- case DW_OP_breg19:
- case DW_OP_breg20:
- case DW_OP_breg21:
- case DW_OP_breg22:
- case DW_OP_breg23:
- case DW_OP_breg24:
- case DW_OP_breg25:
- case DW_OP_breg26:
- case DW_OP_breg27:
- case DW_OP_breg28:
- case DW_OP_breg29:
- case DW_OP_breg30:
- case DW_OP_breg31:
- {
- reg_num = op - DW_OP_breg0;
-
- if (ReadRegisterValueAsScalar (reg_ctx, reg_kind, reg_num, error_ptr, tmp))
- {
- int64_t breg_offset = opcodes.GetSLEB128(&offset);
- tmp.ResolveValue(exe_ctx) += (uint64_t)breg_offset;
- tmp.ClearContext();
- stack.push_back(tmp);
- stack.back().SetValueType (Value::eValueTypeLoadAddress);
- }
- else
- return false;
- }
- break;
- //----------------------------------------------------------------------
- // OPCODE: DW_OP_bregx
- // OPERANDS: 2
- // ULEB128 literal operand that encodes the register.
- // SLEB128 offset from register N
- // DESCRIPTION: Value is in memory at the address specified by register
- // N plus an offset.
- //----------------------------------------------------------------------
- case DW_OP_bregx:
- {
- reg_num = opcodes.GetULEB128(&offset);
-
- if (ReadRegisterValueAsScalar (reg_ctx, reg_kind, reg_num, error_ptr, tmp))
- {
- int64_t breg_offset = opcodes.GetSLEB128(&offset);
- tmp.ResolveValue(exe_ctx) += (uint64_t)breg_offset;
- tmp.ClearContext();
- stack.push_back(tmp);
- stack.back().SetValueType (Value::eValueTypeLoadAddress);
- }
- else
- return false;
- }
- break;
-
- case DW_OP_fbreg:
- if (exe_ctx)
- {
- if (frame)
- {
- Scalar value;
- if (frame->GetFrameBaseValue(value, error_ptr))
- {
- int64_t fbreg_offset = opcodes.GetSLEB128(&offset);
- value += fbreg_offset;
- stack.push_back(value);
- stack.back().SetValueType (Value::eValueTypeLoadAddress);
- }
- else
- return false;
- }
- else
- {
- if (error_ptr)
- error_ptr->SetErrorString ("Invalid stack frame in context for DW_OP_fbreg opcode.");
- return false;
- }
- }
- else
- {
- if (error_ptr)
- error_ptr->SetErrorStringWithFormat ("NULL execution context for DW_OP_fbreg.\n");
- return false;
- }
-
- break;
-
- //----------------------------------------------------------------------
- // OPCODE: DW_OP_nop
- // OPERANDS: none
- // DESCRIPTION: A place holder. It has no effect on the location stack
- // or any of its values.
- //----------------------------------------------------------------------
- case DW_OP_nop:
- break;
-
- //----------------------------------------------------------------------
- // OPCODE: DW_OP_piece
- // OPERANDS: 1
- // ULEB128: byte size of the piece
- // DESCRIPTION: The operand describes the size in bytes of the piece of
- // the object referenced by the DWARF expression whose result is at the
- // top of the stack. If the piece is located in a register, but does not
- // occupy the entire register, the placement of the piece within that
- // register is defined by the ABI.
- //
- // Many compilers store a single variable in sets of registers, or store
- // a variable partially in memory and partially in registers.
- // DW_OP_piece provides a way of describing how large a part of a
- // variable a particular DWARF expression refers to.
- //----------------------------------------------------------------------
- case DW_OP_piece:
- {
- const uint64_t piece_byte_size = opcodes.GetULEB128(&offset);
-
- if (piece_byte_size > 0)
- {
- Value curr_piece;
-
- if (stack.empty())
- {
- // In a multi-piece expression, this means that the current piece is not available.
- // Fill with zeros for now by resizing the data and appending it
- curr_piece.ResizeData(piece_byte_size);
- ::memset (curr_piece.GetBuffer().GetBytes(), 0, piece_byte_size);
- pieces.AppendDataToHostBuffer(curr_piece);
- }
- else
- {
- Error error;
- // Extract the current piece into "curr_piece"
- Value curr_piece_source_value(stack.back());
- stack.pop_back();
-
- const Value::ValueType curr_piece_source_value_type = curr_piece_source_value.GetValueType();
- switch (curr_piece_source_value_type)
- {
- case Value::eValueTypeLoadAddress:
- if (process)
- {
- if (curr_piece.ResizeData(piece_byte_size) == piece_byte_size)
- {
- lldb::addr_t load_addr = curr_piece_source_value.GetScalar().ULongLong(LLDB_INVALID_ADDRESS);
- if (process->ReadMemory(load_addr, curr_piece.GetBuffer().GetBytes(), piece_byte_size, error) != piece_byte_size)
- {
- if (error_ptr)
- error_ptr->SetErrorStringWithFormat ("failed to read memory DW_OP_piece(%" PRIu64 ") from 0x%" PRIx64,
- piece_byte_size,
- load_addr);
- return false;
- }
- }
- else
- {
- if (error_ptr)
- error_ptr->SetErrorStringWithFormat ("failed to resize the piece memory buffer for DW_OP_piece(%" PRIu64 ")", piece_byte_size);
- return false;
- }
- }
- break;
-
- case Value::eValueTypeFileAddress:
- case Value::eValueTypeHostAddress:
- if (error_ptr)
- {
- lldb::addr_t addr = curr_piece_source_value.GetScalar().ULongLong(LLDB_INVALID_ADDRESS);
- error_ptr->SetErrorStringWithFormat ("failed to read memory DW_OP_piece(%" PRIu64 ") from %s address 0x%" PRIx64,
- piece_byte_size,
- curr_piece_source_value.GetValueType() == Value::eValueTypeFileAddress ? "file" : "host",
- addr);
- }
- return false;
-
- case Value::eValueTypeScalar:
- {
- uint32_t bit_size = piece_byte_size * 8;
- uint32_t bit_offset = 0;
- if (!curr_piece_source_value.GetScalar().ExtractBitfield (bit_size, bit_offset))
- {
- if (error_ptr)
- error_ptr->SetErrorStringWithFormat("unable to extract %" PRIu64 " bytes from a %" PRIu64 " byte scalar value.", piece_byte_size, (uint64_t)curr_piece_source_value.GetScalar().GetByteSize());
- return false;
- }
- curr_piece = curr_piece_source_value;
- }
- break;
-
- case Value::eValueTypeVector:
- {
- if (curr_piece_source_value.GetVector().length >= piece_byte_size)
- curr_piece_source_value.GetVector().length = piece_byte_size;
- else
- {
- if (error_ptr)
- error_ptr->SetErrorStringWithFormat("unable to extract %" PRIu64 " bytes from a %" PRIu64 " byte vector value.", piece_byte_size, (uint64_t)curr_piece_source_value.GetVector().length);
- return false;
- }
- }
- break;
-
- }
-
- // Check if this is the first piece?
- if (op_piece_offset == 0)
- {
- // This is the first piece, we should push it back onto the stack so subsequent
- // pieces will be able to access this piece and add to it
- if (pieces.AppendDataToHostBuffer(curr_piece) == 0)
- {
- if (error_ptr)
- error_ptr->SetErrorString("failed to append piece data");
- return false;
- }
- }
- else
- {
- // If this is the second or later piece there should be a value on the stack
- if (pieces.GetBuffer().GetByteSize() != op_piece_offset)
- {
- if (error_ptr)
- error_ptr->SetErrorStringWithFormat ("DW_OP_piece for offset %" PRIu64 " but top of stack is of size %" PRIu64,
- op_piece_offset,
- pieces.GetBuffer().GetByteSize());
- return false;
- }
-
- if (pieces.AppendDataToHostBuffer(curr_piece) == 0)
- {
- if (error_ptr)
- error_ptr->SetErrorString("failed to append piece data");
- return false;
- }
- }
- op_piece_offset += piece_byte_size;
- }
- }
- }
- break;
-
- case DW_OP_bit_piece: // 0x9d ULEB128 bit size, ULEB128 bit offset (DWARF3);
- if (stack.size() < 1)
- {
- if (error_ptr)
- error_ptr->SetErrorString("Expression stack needs at least 1 item for DW_OP_bit_piece.");
- return false;
- }
- 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;
-
- //----------------------------------------------------------------------
- // 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;
- }
-
- 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;
- }
-
- // 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;
- }
-
- stack.back().GetScalar() = tls_load_addr;
- stack.back().SetValueType (Value::eValueTypeLoadAddress);
- }
- break;
-
- //----------------------------------------------------------------------
- // OPCODE: DW_OP_GNU_addr_index
- // OPERANDS: 1
- // ULEB128: index to the .debug_addr section
- // DESCRIPTION: Pushes an address to the stack from the .debug_addr
- // section with the base address specified by the DW_AT_addr_base
- // attribute and the 0 based index is the ULEB128 encoded index.
- //----------------------------------------------------------------------
- case DW_OP_GNU_addr_index:
- {
- if (!dwarf_cu)
- {
- if (error_ptr)
- error_ptr->SetErrorString ("DW_OP_GNU_addr_index found without a compile unit being specified");
- return false;
- }
- uint64_t index = opcodes.GetULEB128(&offset);
- uint32_t index_size = dwarf_cu->GetAddressByteSize();
- dw_offset_t addr_base = dwarf_cu->GetAddrBase();
- lldb::offset_t offset = addr_base + index * index_size;
- uint64_t value = dwarf_cu->GetSymbolFileDWARF()->get_debug_addr_data().GetMaxU64(&offset, index_size);
- stack.push_back(Scalar(value));
- stack.back().SetValueType(Value::eValueTypeFileAddress);
- }
- break;
-
- //----------------------------------------------------------------------
- // OPCODE: DW_OP_GNU_const_index
- // OPERANDS: 1
- // ULEB128: index to the .debug_addr section
- // DESCRIPTION: Pushes an constant with the size of a machine address to
- // the stack from the .debug_addr section with the base address specified
- // by the DW_AT_addr_base attribute and the 0 based index is the ULEB128
- // encoded index.
- //----------------------------------------------------------------------
- case DW_OP_GNU_const_index:
- {
- if (!dwarf_cu)
- {
- if (error_ptr)
- error_ptr->SetErrorString ("DW_OP_GNU_const_index found without a compile unit being specified");
- return false;
- }
- uint64_t index = opcodes.GetULEB128(&offset);
- uint32_t index_size = dwarf_cu->GetAddressByteSize();
- dw_offset_t addr_base = dwarf_cu->GetAddrBase();
- lldb::offset_t offset = addr_base + index * index_size;
- const DWARFDataExtractor& debug_addr = dwarf_cu->GetSymbolFileDWARF()->get_debug_addr_data();
- switch (index_size)
- {
- case 4:
- stack.push_back(Scalar(debug_addr.GetU32(&offset)));
- break;
- case 8:
- stack.push_back(Scalar(debug_addr.GetU64(&offset)));
- break;
- default:
- assert(false && "Unhandled index size");
- return false;
- }
- }
- break;
-
- default:
- if (log)
- log->Printf("Unhandled opcode %s in DWARFExpression.", DW_OP_value_to_name(op));
- break;
- }
- }
-
- if (stack.empty())
- {
- // Nothing on the stack, check if we created a piece value from DW_OP_piece or DW_OP_bit_piece opcodes
- if (pieces.GetBuffer().GetByteSize())
- {
- result = pieces;
- }
- else
- {
- if (error_ptr)
- error_ptr->SetErrorString ("Stack empty after evaluation.");
- return false;
- }
- }
- else
- {
- if (log && log->GetVerbose())
- {
- size_t count = stack.size();
- log->Printf("Stack after operation has %" PRIu64 " values:", (uint64_t)count);
- for (size_t i=0; i<count; ++i)
- {
- StreamString new_value;
- new_value.Printf("[%" PRIu64 "]", (uint64_t)i);
- stack[i].Dump(&new_value);
- log->Printf(" %s", new_value.GetData());
- }
- }
- result = stack.back();
- }
- return true; // Return true on success
-}
-
-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;
+ // 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;
}
-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))
+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;
+ }
+
+ 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;
+}
+
+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;
- 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;
- }
+ // 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;
}
- assert (false && "Not supported location list type");
- return false;
+ }
+ 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;
+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);
- int size;
+ 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;
- opcode_class = DW_OP_value_to_class (opcode) & (~DRC_DWARFv3);
+ 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
- s.Printf("%s ", DW_OP_value_to_name (opcode));
+ // 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()));
- /* Does this take zero parameters? If so we can shortcut this function. */
- if (opcode_class == DRC_ZEROOPERANDS)
- return true;
+ // 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 (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;
+ lldb::offset_t offset = 0;
+ lldb::offset_t const_offset = 0;
+ lldb::addr_t const_value = 0;
+ size_t const_byte_size = 0;
+ while (m_data.ValidOffset(offset)) {
+ const uint8_t op = m_data.GetU8(&offset);
+
+ bool decoded_data = false;
+ switch (op) {
+ case DW_OP_const4u:
+ // Remember the const offset in case we later have a
+ // DW_OP_form_tls_address
+ // or DW_OP_GNU_push_tls_address
+ const_offset = offset;
+ const_value = m_data.GetU32(&offset);
+ decoded_data = true;
+ const_byte_size = 4;
+ break;
+
+ case DW_OP_const8u:
+ // Remember the const offset in case we later have a
+ // DW_OP_form_tls_address
+ // or DW_OP_GNU_push_tls_address
+ const_offset = offset;
+ const_value = m_data.GetU64(&offset);
+ decoded_data = true;
+ const_byte_size = 8;
+ break;
+
+ case DW_OP_form_tls_address:
+ case DW_OP_GNU_push_tls_address:
+ // DW_OP_form_tls_address and DW_OP_GNU_push_tls_address must be preceded
+ // by
+ // a file address on the stack. We assume that DW_OP_const4u or
+ // DW_OP_const8u
+ // is used for these values, and we check that the last opcode we got
+ // before
+ // either of these was DW_OP_const4u or DW_OP_const8u. If so, then we can
+ // link
+ // the value accodingly. For Darwin, the value in the DW_OP_const4u or
+ // DW_OP_const8u is the file address of a structure that contains a
+ // function
+ // pointer, the pthread key and the offset into the data pointed to by the
+ // pthread key. So we must link this address and also set the module of
+ // this
+ // expression to the new_module_sp so we can resolve the file address
+ // correctly
+ if (const_byte_size > 0) {
+ lldb::addr_t linked_file_addr = link_address_callback(const_value);
+ if (linked_file_addr == LLDB_INVALID_ADDRESS)
+ return false;
+ // Replace the address in the new buffer
+ if (encoder.PutMaxU64(const_offset, const_byte_size,
+ linked_file_addr) == UINT32_MAX)
+ return false;
+ }
+ break;
+
+ default:
+ const_offset = 0;
+ const_value = 0;
+ const_byte_size = 0;
+ break;
}
- if (opcode_class != DRC_ONEOPERAND)
- {
- s.Printf("UNKNOWN OP %u", opcode);
+
+ 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;
}
+ }
- 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;
+ // If we linked the TLS address correctly, update the module so that when the
+ // expression
+ // is evaluated it can resolve the file address to a load address and read the
+ // TLS data
+ m_module_wp = new_module_sp;
+ m_data.SetData(heap_data_sp);
+ return true;
}
-bool
-DWARFExpression::PrintDWARFExpression(Stream &s,
- const DataExtractor& data,
- int address_size,
- int dwarf_ref_size,
- bool location_expression)
-{
- int op_count = 0;
+bool DWARFExpression::LocationListContainsAddress(
+ lldb::addr_t loclist_base_addr, lldb::addr_t addr) const {
+ if (addr == LLDB_INVALID_ADDRESS)
+ return false;
+
+ if (IsLocationList()) {
lldb::offset_t offset = 0;
- while (data.ValidOffset(offset))
- {
- if (location_expression && op_count > 0)
- return false;
- if (op_count > 0)
- s.PutCString(", ");
- if (!print_dwarf_exp_op (s, data, &offset, address_size, dwarf_ref_size))
- return false;
- op_count++;
- }
- return true;
+ if (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;
+
+ if (lo_pc == 0 && hi_pc == 0)
+ break;
+
+ lo_pc += loclist_base_addr - m_loclist_slide;
+ hi_pc += loclist_base_addr - m_loclist_slide;
+
+ if (lo_pc <= addr && addr < hi_pc)
+ return true;
+
+ offset += m_data.GetU16(&offset);
+ }
+ }
+ return false;
}
-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::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 (start_addr == 0 && end_addr == 0)
+ 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 = 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;
+ }
+ }
+ 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(
+ ExecutionContext *exe_ctx, ClangExpressionVariableList *expr_locals,
+ ClangExpressionDeclMap *decl_map, RegisterContext *reg_ctx,
+ lldb::addr_t loclist_base_load_addr, const Value *initial_value_ptr,
+ const Value *object_address_ptr, Value &result, Error *error_ptr) const {
+ ModuleSP module_sp = m_module_wp.lock();
+
+ if (IsLocationList()) {
+ lldb::offset_t offset = 0;
+ addr_t pc;
+ StackFrame *frame = NULL;
+ if (reg_ctx)
+ pc = reg_ctx->GetPC();
+ else {
+ frame = exe_ctx->GetFramePtr();
+ if (!frame)
+ return false;
+ RegisterContextSP reg_ctx_sp = frame->GetRegisterContext();
+ if (!reg_ctx_sp)
+ return false;
+ pc = reg_ctx_sp->GetPC();
+ }
+
+ if (loclist_base_load_addr != LLDB_INVALID_ADDRESS) {
+ if (pc == LLDB_INVALID_ADDRESS) {
+ if (error_ptr)
+ error_ptr->SetErrorString("Invalid PC in frame.");
+ return false;
+ }
+
+ 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");
+ return false;
+ }
+
+ // 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 (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->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;
+ }
+
+ } break;
+
+ //----------------------------------------------------------------------
+ // OPCODE: DW_OP_xderef_size
+ // OPERANDS: 1
+ // 1 - uint8_t that specifies the size of the data to dereference.
+ // DESCRIPTION: Behaves like the DW_OP_xderef operation: the entry at
+ // the top of the stack is treated as an address. The second stack
+ // entry is treated as an "address space identifier" for those
+ // architectures that support multiple address spaces. The top two
+ // stack elements are popped, a data item is retrieved through an
+ // implementation-defined address calculation and pushed as the new
+ // stack top. In the DW_OP_xderef_size operation, however, the size in
+ // bytes of the data retrieved from the dereferenced address is
+ // specified by the single operand. This operand is a 1-byte unsigned
+ // integral constant whose value may not be larger than the size of an
+ // address on the target machine. The data retrieved is zero extended
+ // to the size of an address on the target machine before being pushed
+ // on the expression stack.
+ //----------------------------------------------------------------------
+ case DW_OP_xderef_size:
+ if (error_ptr)
+ error_ptr->SetErrorString("Unimplemented opcode: DW_OP_xderef_size.");
+ return false;
+ //----------------------------------------------------------------------
+ // OPCODE: DW_OP_xderef
+ // OPERANDS: none
+ // DESCRIPTION: Provides an extended dereference mechanism. The entry at
+ // the top of the stack is treated as an address. The second stack entry
+ // is treated as an "address space identifier" for those architectures
+ // that support multiple address spaces. The top two stack elements are
+ // popped, a data item is retrieved through an implementation-defined
+ // address calculation and pushed as the new stack top. The size of the
+ // data retrieved from the dereferenced address is the size of an address
+ // on the target machine.
+ //----------------------------------------------------------------------
+ case DW_OP_xderef:
+ if (error_ptr)
+ error_ptr->SetErrorString("Unimplemented opcode: DW_OP_xderef.");
+ return false;
+
+ //----------------------------------------------------------------------
+ // All DW_OP_constXXX opcodes have a single operand as noted below:
+ //
+ // Opcode Operand 1
+ // --------------- ----------------------------------------------------
+ // DW_OP_const1u 1-byte unsigned integer constant
+ // DW_OP_const1s 1-byte signed integer constant
+ // DW_OP_const2u 2-byte unsigned integer constant
+ // DW_OP_const2s 2-byte signed integer constant
+ // DW_OP_const4u 4-byte unsigned integer constant
+ // DW_OP_const4s 4-byte signed integer constant
+ // DW_OP_const8u 8-byte unsigned integer constant
+ // DW_OP_const8s 8-byte signed integer constant
+ // DW_OP_constu unsigned LEB128 integer constant
+ // DW_OP_consts signed LEB128 integer constant
+ //----------------------------------------------------------------------
+ case DW_OP_const1u:
+ stack.push_back(Scalar((uint8_t)opcodes.GetU8(&offset)));
+ break;
+ case DW_OP_const1s:
+ stack.push_back(Scalar((int8_t)opcodes.GetU8(&offset)));
+ break;
+ case DW_OP_const2u:
+ stack.push_back(Scalar((uint16_t)opcodes.GetU16(&offset)));
+ break;
+ case DW_OP_const2s:
+ stack.push_back(Scalar((int16_t)opcodes.GetU16(&offset)));
+ break;
+ case DW_OP_const4u:
+ stack.push_back(Scalar((uint32_t)opcodes.GetU32(&offset)));
+ break;
+ case DW_OP_const4s:
+ stack.push_back(Scalar((int32_t)opcodes.GetU32(&offset)));
+ break;
+ case DW_OP_const8u:
+ stack.push_back(Scalar((uint64_t)opcodes.GetU64(&offset)));
+ break;
+ case DW_OP_const8s:
+ stack.push_back(Scalar((int64_t)opcodes.GetU64(&offset)));
+ break;
+ case DW_OP_constu:
+ stack.push_back(Scalar(opcodes.GetULEB128(&offset)));
+ break;
+ case DW_OP_consts:
+ stack.push_back(Scalar(opcodes.GetSLEB128(&offset)));
+ break;
+
+ //----------------------------------------------------------------------
+ // OPCODE: DW_OP_dup
+ // OPERANDS: none
+ // DESCRIPTION: duplicates the value at the top of the stack
+ //----------------------------------------------------------------------
+ case DW_OP_dup:
+ if (stack.empty()) {
+ if (error_ptr)
+ error_ptr->SetErrorString("Expression stack empty for DW_OP_dup.");
+ return false;
+ } else
+ stack.push_back(stack.back());
+ break;
+
+ //----------------------------------------------------------------------
+ // OPCODE: DW_OP_drop
+ // OPERANDS: none
+ // DESCRIPTION: pops the value at the top of the stack
+ //----------------------------------------------------------------------
+ case DW_OP_drop:
+ if (stack.empty()) {
+ if (error_ptr)
+ error_ptr->SetErrorString("Expression stack empty for DW_OP_drop.");
+ return false;
+ } else
+ stack.pop_back();
+ break;
+
+ //----------------------------------------------------------------------
+ // OPCODE: DW_OP_over
+ // OPERANDS: none
+ // DESCRIPTION: Duplicates the entry currently second in the stack at
+ // the top of the stack.
+ //----------------------------------------------------------------------
+ case DW_OP_over:
+ if (stack.size() < 2) {
+ if (error_ptr)
+ error_ptr->SetErrorString(
+ "Expression stack needs at least 2 items for DW_OP_over.");
+ return false;
+ } else
+ stack.push_back(stack[stack.size() - 2]);
+ break;
+
+ //----------------------------------------------------------------------
+ // OPCODE: DW_OP_pick
+ // OPERANDS: uint8_t index into the current stack
+ // DESCRIPTION: The stack entry with the specified index (0 through 255,
+ // inclusive) is pushed on the stack
+ //----------------------------------------------------------------------
+ case DW_OP_pick: {
+ uint8_t pick_idx = opcodes.GetU8(&offset);
+ if (pick_idx < stack.size())
+ stack.push_back(stack[pick_idx]);
+ else {
+ if (error_ptr)
+ error_ptr->SetErrorStringWithFormat(
+ "Index %u out of range for DW_OP_pick.\n", pick_idx);
+ return false;
+ }
+ } break;
+
+ //----------------------------------------------------------------------
+ // OPCODE: DW_OP_swap
+ // OPERANDS: none
+ // DESCRIPTION: swaps the top two stack entries. The entry at the top
+ // of the stack becomes the second stack entry, and the second entry
+ // becomes the top of the stack
+ //----------------------------------------------------------------------
+ case DW_OP_swap:
+ if (stack.size() < 2) {
+ if (error_ptr)
+ error_ptr->SetErrorString(
+ "Expression stack needs at least 2 items for DW_OP_swap.");
+ return false;
+ } else {
+ tmp = stack.back();
+ stack.back() = stack[stack.size() - 2];
+ stack[stack.size() - 2] = tmp;
+ }
+ break;
+
+ //----------------------------------------------------------------------
+ // OPCODE: DW_OP_rot
+ // OPERANDS: none
+ // DESCRIPTION: Rotates the first three stack entries. The entry at
+ // the top of the stack becomes the third stack entry, the second
+ // entry becomes the top of the stack, and the third entry becomes
+ // the second entry.
+ //----------------------------------------------------------------------
+ case DW_OP_rot:
+ if (stack.size() < 3) {
+ if (error_ptr)
+ error_ptr->SetErrorString(
+ "Expression stack needs at least 3 items for DW_OP_rot.");
+ return false;
+ } else {
+ size_t last_idx = stack.size() - 1;
+ Value old_top = stack[last_idx];
+ stack[last_idx] = stack[last_idx - 1];
+ stack[last_idx - 1] = stack[last_idx - 2];
+ stack[last_idx - 2] = old_top;
+ }
+ break;
+
+ //----------------------------------------------------------------------
+ // OPCODE: DW_OP_abs
+ // OPERANDS: none
+ // DESCRIPTION: pops the top stack entry, interprets it as a signed
+ // value and pushes its absolute value. If the absolute value can not be
+ // represented, the result is undefined.
+ //----------------------------------------------------------------------
+ case DW_OP_abs:
+ if (stack.empty()) {
+ if (error_ptr)
+ error_ptr->SetErrorString(
+ "Expression stack needs at least 1 item for DW_OP_abs.");
+ return false;
+ } else if (stack.back().ResolveValue(exe_ctx).AbsoluteValue() == false) {
+ if (error_ptr)
+ error_ptr->SetErrorString(
+ "Failed to take the absolute value of the first stack item.");
+ return false;
+ }
+ break;
+
+ //----------------------------------------------------------------------
+ // OPCODE: DW_OP_and
+ // OPERANDS: none
+ // DESCRIPTION: pops the top two stack values, performs a bitwise and
+ // operation on the two, and pushes the result.
+ //----------------------------------------------------------------------
+ case DW_OP_and:
+ if (stack.size() < 2) {
+ if (error_ptr)
+ error_ptr->SetErrorString(
+ "Expression stack needs at least 2 items for DW_OP_and.");
+ return false;
+ } else {
+ tmp = stack.back();
+ stack.pop_back();
+ stack.back().ResolveValue(exe_ctx) =
+ stack.back().ResolveValue(exe_ctx) & tmp.ResolveValue(exe_ctx);
+ }
+ break;
+
+ //----------------------------------------------------------------------
+ // OPCODE: DW_OP_div
+ // OPERANDS: none
+ // DESCRIPTION: pops the top two stack values, divides the former second
+ // entry by the former top of the stack using signed division, and
+ // pushes the result.
+ //----------------------------------------------------------------------
+ case DW_OP_div:
+ if (stack.size() < 2) {
+ if (error_ptr)
+ error_ptr->SetErrorString(
+ "Expression stack needs at least 2 items for DW_OP_div.");
+ return false;
+ } else {
+ tmp = stack.back();
+ if (tmp.ResolveValue(exe_ctx).IsZero()) {
+ if (error_ptr)
+ error_ptr->SetErrorString("Divide by zero.");
+ return false;
+ } else {
+ stack.pop_back();
+ stack.back() =
+ stack.back().ResolveValue(exe_ctx) / tmp.ResolveValue(exe_ctx);
+ if (!stack.back().ResolveValue(exe_ctx).IsValid()) {
+ if (error_ptr)
+ error_ptr->SetErrorString("Divide failed.");
+ return false;
+ }
+ }
+ }
+ break;
+
+ //----------------------------------------------------------------------
+ // OPCODE: DW_OP_minus
+ // OPERANDS: none
+ // DESCRIPTION: pops the top two stack values, subtracts the former top
+ // of the stack from the former second entry, and pushes the result.
+ //----------------------------------------------------------------------
+ case DW_OP_minus:
+ if (stack.size() < 2) {
+ if (error_ptr)
+ error_ptr->SetErrorString(
+ "Expression stack needs at least 2 items for DW_OP_minus.");
+ return false;
+ } else {
+ tmp = stack.back();
+ stack.pop_back();
+ stack.back().ResolveValue(exe_ctx) =
+ stack.back().ResolveValue(exe_ctx) - tmp.ResolveValue(exe_ctx);
+ }
+ break;
+
+ //----------------------------------------------------------------------
+ // OPCODE: DW_OP_mod
+ // OPERANDS: none
+ // DESCRIPTION: pops the top two stack values and pushes the result of
+ // the calculation: former second stack entry modulo the former top of
+ // the stack.
+ //----------------------------------------------------------------------
+ case DW_OP_mod:
+ if (stack.size() < 2) {
+ if (error_ptr)
+ error_ptr->SetErrorString(
+ "Expression stack needs at least 2 items for DW_OP_mod.");
+ return false;
+ } else {
+ tmp = stack.back();
+ stack.pop_back();
+ stack.back().ResolveValue(exe_ctx) =
+ stack.back().ResolveValue(exe_ctx) % tmp.ResolveValue(exe_ctx);
+ }
+ break;
+
+ //----------------------------------------------------------------------
+ // OPCODE: DW_OP_mul
+ // OPERANDS: none
+ // DESCRIPTION: pops the top two stack entries, multiplies them
+ // together, and pushes the result.
+ //----------------------------------------------------------------------
+ case DW_OP_mul:
+ if (stack.size() < 2) {
+ if (error_ptr)
+ error_ptr->SetErrorString(
+ "Expression stack needs at least 2 items for DW_OP_mul.");
+ return false;
+ } else {
+ tmp = stack.back();
+ stack.pop_back();
+ stack.back().ResolveValue(exe_ctx) =
+ stack.back().ResolveValue(exe_ctx) * tmp.ResolveValue(exe_ctx);
+ }
+ break;
+
+ //----------------------------------------------------------------------
+ // OPCODE: DW_OP_neg
+ // OPERANDS: none
+ // DESCRIPTION: pops the top stack entry, and pushes its negation.
+ //----------------------------------------------------------------------
+ case DW_OP_neg:
+ if (stack.empty()) {
+ if (error_ptr)
+ error_ptr->SetErrorString(
+ "Expression stack needs at least 1 item for DW_OP_neg.");
+ return false;
+ } else {
+ if (stack.back().ResolveValue(exe_ctx).UnaryNegate() == false) {
+ if (error_ptr)
+ error_ptr->SetErrorString("Unary negate failed.");
+ return false;
+ }
+ }
+ break;
+
+ //----------------------------------------------------------------------
+ // OPCODE: DW_OP_not
+ // OPERANDS: none
+ // DESCRIPTION: pops the top stack entry, and pushes its bitwise
+ // complement
+ //----------------------------------------------------------------------
+ case DW_OP_not:
+ if (stack.empty()) {
+ if (error_ptr)
+ error_ptr->SetErrorString(
+ "Expression stack needs at least 1 item for DW_OP_not.");
+ return false;
+ } else {
+ if (stack.back().ResolveValue(exe_ctx).OnesComplement() == false) {
+ if (error_ptr)
+ error_ptr->SetErrorString("Logical NOT failed.");
+ return false;
+ }
+ }
+ break;
+
+ //----------------------------------------------------------------------
+ // OPCODE: DW_OP_or
+ // OPERANDS: none
+ // DESCRIPTION: pops the top two stack entries, performs a bitwise or
+ // operation on the two, and pushes the result.
+ //----------------------------------------------------------------------
+ case DW_OP_or:
+ if (stack.size() < 2) {
+ if (error_ptr)
+ error_ptr->SetErrorString(
+ "Expression stack needs at least 2 items for DW_OP_or.");
+ return false;
+ } else {
+ tmp = stack.back();
+ stack.pop_back();
+ stack.back().ResolveValue(exe_ctx) =
+ stack.back().ResolveValue(exe_ctx) | tmp.ResolveValue(exe_ctx);
+ }
+ break;
+
+ //----------------------------------------------------------------------
+ // OPCODE: DW_OP_plus
+ // OPERANDS: none
+ // DESCRIPTION: pops the top two stack entries, adds them together, and
+ // pushes the result.
+ //----------------------------------------------------------------------
+ case DW_OP_plus:
+ if (stack.size() < 2) {
+ if (error_ptr)
+ error_ptr->SetErrorString(
+ "Expression stack needs at least 2 items for DW_OP_plus.");
+ return false;
+ } else {
+ tmp = stack.back();
+ stack.pop_back();
+ stack.back().GetScalar() += tmp.GetScalar();
+ }
+ break;
+
+ //----------------------------------------------------------------------
+ // OPCODE: DW_OP_plus_uconst
+ // OPERANDS: none
+ // DESCRIPTION: pops the top stack entry, adds it to the unsigned LEB128
+ // constant operand and pushes the result.
+ //----------------------------------------------------------------------
+ case DW_OP_plus_uconst:
+ if (stack.empty()) {
+ if (error_ptr)
+ error_ptr->SetErrorString(
+ "Expression stack needs at least 1 item for DW_OP_plus_uconst.");
+ return false;
+ } else {
+ const uint64_t uconst_value = opcodes.GetULEB128(&offset);
+ // Implicit conversion from a UINT to a Scalar...
+ stack.back().GetScalar() += uconst_value;
+ if (!stack.back().GetScalar().IsValid()) {
+ if (error_ptr)
+ error_ptr->SetErrorString("DW_OP_plus_uconst failed.");
+ return false;
+ }
+ }
+ break;
+
+ //----------------------------------------------------------------------
+ // OPCODE: DW_OP_shl
+ // OPERANDS: none
+ // DESCRIPTION: pops the top two stack entries, shifts the former
+ // second entry left by the number of bits specified by the former top
+ // of the stack, and pushes the result.
+ //----------------------------------------------------------------------
+ case DW_OP_shl:
+ if (stack.size() < 2) {
+ if (error_ptr)
+ error_ptr->SetErrorString(
+ "Expression stack needs at least 2 items for DW_OP_shl.");
+ return false;
+ } else {
+ tmp = stack.back();
+ stack.pop_back();
+ stack.back().ResolveValue(exe_ctx) <<= tmp.ResolveValue(exe_ctx);
+ }
+ break;
+
+ //----------------------------------------------------------------------
+ // OPCODE: DW_OP_shr
+ // OPERANDS: none
+ // DESCRIPTION: pops the top two stack entries, shifts the former second
+ // entry right logically (filling with zero bits) by the number of bits
+ // specified by the former top of the stack, and pushes the result.
+ //----------------------------------------------------------------------
+ case DW_OP_shr:
+ if (stack.size() < 2) {
+ if (error_ptr)
+ error_ptr->SetErrorString(
+ "Expression stack needs at least 2 items for DW_OP_shr.");
+ return false;
+ } else {
+ tmp = stack.back();
+ stack.pop_back();
+ if (stack.back().ResolveValue(exe_ctx).ShiftRightLogical(
+ tmp.ResolveValue(exe_ctx)) == false) {
+ if (error_ptr)
+ error_ptr->SetErrorString("DW_OP_shr failed.");
+ return false;
+ }
+ }
+ break;
+
+ //----------------------------------------------------------------------
+ // OPCODE: DW_OP_shra
+ // OPERANDS: none
+ // DESCRIPTION: pops the top two stack entries, shifts the former second
+ // entry right arithmetically (divide the magnitude by 2, keep the same
+ // sign for the result) by the number of bits specified by the former
+ // top of the stack, and pushes the result.
+ //----------------------------------------------------------------------
+ case DW_OP_shra:
+ if (stack.size() < 2) {
+ if (error_ptr)
+ error_ptr->SetErrorString(
+ "Expression stack needs at least 2 items for DW_OP_shra.");
+ return false;
+ } else {
+ tmp = stack.back();
+ stack.pop_back();
+ stack.back().ResolveValue(exe_ctx) >>= tmp.ResolveValue(exe_ctx);
+ }
+ break;
+
+ //----------------------------------------------------------------------
+ // OPCODE: DW_OP_xor
+ // OPERANDS: none
+ // DESCRIPTION: pops the top two stack entries, performs the bitwise
+ // exclusive-or operation on the two, and pushes the result.
+ //----------------------------------------------------------------------
+ case DW_OP_xor:
+ if (stack.size() < 2) {
+ if (error_ptr)
+ error_ptr->SetErrorString(
+ "Expression stack needs at least 2 items for DW_OP_xor.");
+ return false;
+ } else {
+ tmp = stack.back();
+ stack.pop_back();
+ stack.back().ResolveValue(exe_ctx) =
+ stack.back().ResolveValue(exe_ctx) ^ tmp.ResolveValue(exe_ctx);
+ }
+ break;
+
+ //----------------------------------------------------------------------
+ // OPCODE: DW_OP_skip
+ // OPERANDS: int16_t
+ // DESCRIPTION: An unconditional branch. Its single operand is a 2-byte
+ // signed integer constant. The 2-byte constant is the number of bytes
+ // of the DWARF expression to skip forward or backward from the current
+ // operation, beginning after the 2-byte constant.
+ //----------------------------------------------------------------------
+ case DW_OP_skip: {
+ int16_t skip_offset = (int16_t)opcodes.GetU16(&offset);
+ lldb::offset_t new_offset = offset + skip_offset;
+ if (new_offset >= opcodes_offset && new_offset < end_offset)
+ offset = new_offset;
+ else {
+ if (error_ptr)
+ error_ptr->SetErrorString("Invalid opcode offset in DW_OP_skip.");
+ return false;
+ }
+ } break;
+
+ //----------------------------------------------------------------------
+ // OPCODE: DW_OP_bra
+ // OPERANDS: int16_t
+ // DESCRIPTION: A conditional branch. Its single operand is a 2-byte
+ // signed integer constant. This operation pops the top of stack. If
+ // the value popped is not the constant 0, the 2-byte constant operand
+ // is the number of bytes of the DWARF expression to skip forward or
+ // backward from the current operation, beginning after the 2-byte
+ // constant.
+ //----------------------------------------------------------------------
+ case DW_OP_bra:
+ if (stack.empty()) {
+ if (error_ptr)
+ error_ptr->SetErrorString(
+ "Expression stack needs at least 1 item for DW_OP_bra.");
+ return false;
+ } else {
+ tmp = stack.back();
+ stack.pop_back();
+ int16_t bra_offset = (int16_t)opcodes.GetU16(&offset);
+ Scalar zero(0);
+ if (tmp.ResolveValue(exe_ctx) != zero) {
+ lldb::offset_t new_offset = offset + bra_offset;
+ if (new_offset >= opcodes_offset && new_offset < end_offset)
+ offset = new_offset;
+ else {
+ if (error_ptr)
+ error_ptr->SetErrorString("Invalid opcode offset in DW_OP_bra.");
+ return false;
+ }
+ }
+ }
+ break;
+
+ //----------------------------------------------------------------------
+ // OPCODE: DW_OP_eq
+ // OPERANDS: none
+ // DESCRIPTION: pops the top two stack values, compares using the
+ // equals (==) operator.
+ // STACK RESULT: push the constant value 1 onto the stack if the result
+ // of the operation is true or the constant value 0 if the result of the
+ // operation is false.
+ //----------------------------------------------------------------------
+ case DW_OP_eq:
+ if (stack.size() < 2) {
+ if (error_ptr)
+ error_ptr->SetErrorString(
+ "Expression stack needs at least 2 items for DW_OP_eq.");
+ return false;
+ } else {
+ tmp = stack.back();
+ stack.pop_back();
+ stack.back().ResolveValue(exe_ctx) =
+ stack.back().ResolveValue(exe_ctx) == tmp.ResolveValue(exe_ctx);
+ }
+ break;
+
+ //----------------------------------------------------------------------
+ // OPCODE: DW_OP_ge
+ // OPERANDS: none
+ // DESCRIPTION: pops the top two stack values, compares using the
+ // greater than or equal to (>=) operator.
+ // STACK RESULT: push the constant value 1 onto the stack if the result
+ // of the operation is true or the constant value 0 if the result of the
+ // operation is false.
+ //----------------------------------------------------------------------
+ case DW_OP_ge:
+ if (stack.size() < 2) {
+ if (error_ptr)
+ error_ptr->SetErrorString(
+ "Expression stack needs at least 2 items for DW_OP_ge.");
+ return false;
+ } else {
+ tmp = stack.back();
+ stack.pop_back();
+ stack.back().ResolveValue(exe_ctx) =
+ stack.back().ResolveValue(exe_ctx) >= tmp.ResolveValue(exe_ctx);
+ }
+ break;
+
+ //----------------------------------------------------------------------
+ // OPCODE: DW_OP_gt
+ // OPERANDS: none
+ // DESCRIPTION: pops the top two stack values, compares using the
+ // greater than (>) operator.
+ // STACK RESULT: push the constant value 1 onto the stack if the result
+ // of the operation is true or the constant value 0 if the result of the
+ // operation is false.
+ //----------------------------------------------------------------------
+ case DW_OP_gt:
+ if (stack.size() < 2) {
+ if (error_ptr)
+ error_ptr->SetErrorString(
+ "Expression stack needs at least 2 items for DW_OP_gt.");
+ return false;
+ } else {
+ tmp = stack.back();
+ stack.pop_back();
+ stack.back().ResolveValue(exe_ctx) =
+ stack.back().ResolveValue(exe_ctx) > tmp.ResolveValue(exe_ctx);
+ }
+ break;
+
+ //----------------------------------------------------------------------
+ // OPCODE: DW_OP_le
+ // OPERANDS: none
+ // DESCRIPTION: pops the top two stack values, compares using the
+ // less than or equal to (<=) operator.
+ // STACK RESULT: push the constant value 1 onto the stack if the result
+ // of the operation is true or the constant value 0 if the result of the
+ // operation is false.
+ //----------------------------------------------------------------------
+ case DW_OP_le:
+ if (stack.size() < 2) {
+ if (error_ptr)
+ error_ptr->SetErrorString(
+ "Expression stack needs at least 2 items for DW_OP_le.");
+ return false;
+ } else {
+ tmp = stack.back();
+ stack.pop_back();
+ stack.back().ResolveValue(exe_ctx) =
+ stack.back().ResolveValue(exe_ctx) <= tmp.ResolveValue(exe_ctx);
+ }
+ break;
+
+ //----------------------------------------------------------------------
+ // OPCODE: DW_OP_lt
+ // OPERANDS: none
+ // DESCRIPTION: pops the top two stack values, compares using the
+ // less than (<) operator.
+ // STACK RESULT: push the constant value 1 onto the stack if the result
+ // of the operation is true or the constant value 0 if the result of the
+ // operation is false.
+ //----------------------------------------------------------------------
+ case DW_OP_lt:
+ if (stack.size() < 2) {
+ if (error_ptr)
+ error_ptr->SetErrorString(
+ "Expression stack needs at least 2 items for DW_OP_lt.");
+ return false;
+ } else {
+ tmp = stack.back();
+ stack.pop_back();
+ stack.back().ResolveValue(exe_ctx) =
+ stack.back().ResolveValue(exe_ctx) < tmp.ResolveValue(exe_ctx);
+ }
+ break;
+
+ //----------------------------------------------------------------------
+ // OPCODE: DW_OP_ne
+ // OPERANDS: none
+ // DESCRIPTION: pops the top two stack values, compares using the
+ // not equal (!=) operator.
+ // STACK RESULT: push the constant value 1 onto the stack if the result
+ // of the operation is true or the constant value 0 if the result of the
+ // operation is false.
+ //----------------------------------------------------------------------
+ case DW_OP_ne:
+ if (stack.size() < 2) {
+ if (error_ptr)
+ error_ptr->SetErrorString(
+ "Expression stack needs at least 2 items for DW_OP_ne.");
+ return false;
+ } else {
+ tmp = stack.back();
+ stack.pop_back();
+ stack.back().ResolveValue(exe_ctx) =
+ stack.back().ResolveValue(exe_ctx) != tmp.ResolveValue(exe_ctx);
+ }
+ break;
+
+ //----------------------------------------------------------------------
+ // OPCODE: DW_OP_litn
+ // OPERANDS: none
+ // DESCRIPTION: encode the unsigned literal values from 0 through 31.
+ // STACK RESULT: push the unsigned literal constant value onto the top
+ // of the stack.
+ //----------------------------------------------------------------------
+ case DW_OP_lit0:
+ case DW_OP_lit1:
+ case DW_OP_lit2:
+ case DW_OP_lit3:
+ case DW_OP_lit4:
+ case DW_OP_lit5:
+ case DW_OP_lit6:
+ case DW_OP_lit7:
+ case DW_OP_lit8:
+ case DW_OP_lit9:
+ case DW_OP_lit10:
+ case DW_OP_lit11:
+ case DW_OP_lit12:
+ case DW_OP_lit13:
+ case DW_OP_lit14:
+ case DW_OP_lit15:
+ case DW_OP_lit16:
+ case DW_OP_lit17:
+ case DW_OP_lit18:
+ case DW_OP_lit19:
+ case DW_OP_lit20:
+ case DW_OP_lit21:
+ case DW_OP_lit22:
+ case DW_OP_lit23:
+ case DW_OP_lit24:
+ case DW_OP_lit25:
+ case DW_OP_lit26:
+ case DW_OP_lit27:
+ case DW_OP_lit28:
+ case DW_OP_lit29:
+ case DW_OP_lit30:
+ case DW_OP_lit31:
+ stack.push_back(Scalar(op - DW_OP_lit0));
+ break;
+
+ //----------------------------------------------------------------------
+ // OPCODE: DW_OP_regN
+ // OPERANDS: none
+ // DESCRIPTION: Push the value in register n on the top of the stack.
+ //----------------------------------------------------------------------
+ case DW_OP_reg0:
+ case DW_OP_reg1:
+ case DW_OP_reg2:
+ case DW_OP_reg3:
+ case DW_OP_reg4:
+ case DW_OP_reg5:
+ case DW_OP_reg6:
+ case DW_OP_reg7:
+ case DW_OP_reg8:
+ case DW_OP_reg9:
+ case DW_OP_reg10:
+ case DW_OP_reg11:
+ case DW_OP_reg12:
+ case DW_OP_reg13:
+ case DW_OP_reg14:
+ case DW_OP_reg15:
+ case DW_OP_reg16:
+ case DW_OP_reg17:
+ case DW_OP_reg18:
+ case DW_OP_reg19:
+ case DW_OP_reg20:
+ case DW_OP_reg21:
+ case DW_OP_reg22:
+ case DW_OP_reg23:
+ case DW_OP_reg24:
+ case DW_OP_reg25:
+ case DW_OP_reg26:
+ case DW_OP_reg27:
+ case DW_OP_reg28:
+ case DW_OP_reg29:
+ case DW_OP_reg30:
+ case DW_OP_reg31: {
+ reg_num = op - DW_OP_reg0;
+
+ if (ReadRegisterValueAsScalar(reg_ctx, reg_kind, reg_num, error_ptr, tmp))
+ stack.push_back(tmp);
+ else
+ return false;
+ } break;
+ //----------------------------------------------------------------------
+ // OPCODE: DW_OP_regx
+ // OPERANDS:
+ // ULEB128 literal operand that encodes the register.
+ // DESCRIPTION: Push the value in register on the top of the stack.
+ //----------------------------------------------------------------------
+ case DW_OP_regx: {
+ reg_num = opcodes.GetULEB128(&offset);
+ if (ReadRegisterValueAsScalar(reg_ctx, reg_kind, reg_num, error_ptr, tmp))
+ stack.push_back(tmp);
+ else
+ return false;
+ } break;
+
+ //----------------------------------------------------------------------
+ // OPCODE: DW_OP_bregN
+ // OPERANDS:
+ // SLEB128 offset from register N
+ // DESCRIPTION: Value is in memory at the address specified by register
+ // N plus an offset.
+ //----------------------------------------------------------------------
+ case DW_OP_breg0:
+ case DW_OP_breg1:
+ case DW_OP_breg2:
+ case DW_OP_breg3:
+ case DW_OP_breg4:
+ case DW_OP_breg5:
+ case DW_OP_breg6:
+ case DW_OP_breg7:
+ case DW_OP_breg8:
+ case DW_OP_breg9:
+ case DW_OP_breg10:
+ case DW_OP_breg11:
+ case DW_OP_breg12:
+ case DW_OP_breg13:
+ case DW_OP_breg14:
+ case DW_OP_breg15:
+ case DW_OP_breg16:
+ case DW_OP_breg17:
+ case DW_OP_breg18:
+ case DW_OP_breg19:
+ case DW_OP_breg20:
+ case DW_OP_breg21:
+ case DW_OP_breg22:
+ case DW_OP_breg23:
+ case DW_OP_breg24:
+ case DW_OP_breg25:
+ case DW_OP_breg26:
+ case DW_OP_breg27:
+ case DW_OP_breg28:
+ case DW_OP_breg29:
+ case DW_OP_breg30:
+ case DW_OP_breg31: {
+ reg_num = op - DW_OP_breg0;
+
+ if (ReadRegisterValueAsScalar(reg_ctx, reg_kind, reg_num, error_ptr,
+ tmp)) {
+ int64_t breg_offset = opcodes.GetSLEB128(&offset);
+ tmp.ResolveValue(exe_ctx) += (uint64_t)breg_offset;
+ tmp.ClearContext();
+ stack.push_back(tmp);
+ stack.back().SetValueType(Value::eValueTypeLoadAddress);
+ } else
+ return false;
+ } break;
+ //----------------------------------------------------------------------
+ // OPCODE: DW_OP_bregx
+ // OPERANDS: 2
+ // ULEB128 literal operand that encodes the register.
+ // SLEB128 offset from register N
+ // DESCRIPTION: Value is in memory at the address specified by register
+ // N plus an offset.
+ //----------------------------------------------------------------------
+ case DW_OP_bregx: {
+ reg_num = opcodes.GetULEB128(&offset);
+
+ if (ReadRegisterValueAsScalar(reg_ctx, reg_kind, reg_num, error_ptr,
+ tmp)) {
+ int64_t breg_offset = opcodes.GetSLEB128(&offset);
+ tmp.ResolveValue(exe_ctx) += (uint64_t)breg_offset;
+ tmp.ClearContext();
+ stack.push_back(tmp);
+ stack.back().SetValueType(Value::eValueTypeLoadAddress);
+ } else
+ return false;
+ } break;
+
+ case DW_OP_fbreg:
+ if (exe_ctx) {
+ if (frame) {
+ Scalar value;
+ if (frame->GetFrameBaseValue(value, error_ptr)) {
+ int64_t fbreg_offset = opcodes.GetSLEB128(&offset);
+ value += fbreg_offset;
+ stack.push_back(value);
+ stack.back().SetValueType(Value::eValueTypeLoadAddress);
+ } else
+ return false;
+ } else {
+ if (error_ptr)
+ error_ptr->SetErrorString(
+ "Invalid stack frame in context for DW_OP_fbreg opcode.");
+ return false;
+ }
+ } else {
+ if (error_ptr)
+ error_ptr->SetErrorStringWithFormat(
+ "NULL execution context for DW_OP_fbreg.\n");
+ return false;
+ }
+
+ break;
+
+ //----------------------------------------------------------------------
+ // OPCODE: DW_OP_nop
+ // OPERANDS: none
+ // DESCRIPTION: A place holder. It has no effect on the location stack
+ // or any of its values.
+ //----------------------------------------------------------------------
+ case DW_OP_nop:
+ break;
+
+ //----------------------------------------------------------------------
+ // OPCODE: DW_OP_piece
+ // OPERANDS: 1
+ // ULEB128: byte size of the piece
+ // DESCRIPTION: The operand describes the size in bytes of the piece of
+ // the object referenced by the DWARF expression whose result is at the
+ // top of the stack. If the piece is located in a register, but does not
+ // occupy the entire register, the placement of the piece within that
+ // register is defined by the ABI.
+ //
+ // Many compilers store a single variable in sets of registers, or store
+ // a variable partially in memory and partially in registers.
+ // DW_OP_piece provides a way of describing how large a part of a
+ // variable a particular DWARF expression refers to.
+ //----------------------------------------------------------------------
+ case DW_OP_piece: {
+ const uint64_t piece_byte_size = opcodes.GetULEB128(&offset);
+
+ if (piece_byte_size > 0) {
+ Value curr_piece;
+
+ if (stack.empty()) {
+ // In a multi-piece expression, this means that the current piece is
+ // not available.
+ // Fill with zeros for now by resizing the data and appending it
+ curr_piece.ResizeData(piece_byte_size);
+ ::memset(curr_piece.GetBuffer().GetBytes(), 0, piece_byte_size);
+ pieces.AppendDataToHostBuffer(curr_piece);
+ } else {
+ Error error;
+ // Extract the current piece into "curr_piece"
+ Value curr_piece_source_value(stack.back());
+ stack.pop_back();
+
+ const Value::ValueType curr_piece_source_value_type =
+ curr_piece_source_value.GetValueType();
+ switch (curr_piece_source_value_type) {
+ case Value::eValueTypeLoadAddress:
+ if (process) {
+ if (curr_piece.ResizeData(piece_byte_size) == piece_byte_size) {
+ lldb::addr_t load_addr =
+ curr_piece_source_value.GetScalar().ULongLong(
+ LLDB_INVALID_ADDRESS);
+ if (process->ReadMemory(
+ load_addr, curr_piece.GetBuffer().GetBytes(),
+ piece_byte_size, error) != piece_byte_size) {
+ if (error_ptr)
+ error_ptr->SetErrorStringWithFormat(
+ "failed to read memory DW_OP_piece(%" PRIu64
+ ") from 0x%" PRIx64,
+ piece_byte_size, load_addr);
+ return false;
+ }
+ } else {
+ if (error_ptr)
+ error_ptr->SetErrorStringWithFormat(
+ "failed to resize the piece memory buffer for "
+ "DW_OP_piece(%" PRIu64 ")",
+ piece_byte_size);
+ return false;
+ }
+ }
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;
- }
-}
-
-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;
- }
-
- 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;
- }
-
- 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;
- }
-
- 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:
+ 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 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;
+
+ 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;
-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))
- {
+ 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;
- }
-
- 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);
+ } 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;
- switch (opcode)
- {
+ 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;
+ }
+
+ 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;
+ }
+
+ // 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;
+ }
+
+ stack.back().GetScalar() = tls_load_addr;
+ stack.back().SetValueType(Value::eValueTypeLoadAddress);
+ } break;
+
+ //----------------------------------------------------------------------
+ // OPCODE: DW_OP_GNU_addr_index
+ // OPERANDS: 1
+ // ULEB128: index to the .debug_addr section
+ // DESCRIPTION: Pushes an address to the stack from the .debug_addr
+ // section with the base address specified by the DW_AT_addr_base
+ // attribute and the 0 based index is the ULEB128 encoded index.
+ //----------------------------------------------------------------------
+ case DW_OP_GNU_addr_index: {
+ if (!dwarf_cu) {
+ if (error_ptr)
+ error_ptr->SetErrorString("DW_OP_GNU_addr_index found without a "
+ "compile unit being specified");
+ return false;
+ }
+ uint64_t index = opcodes.GetULEB128(&offset);
+ uint32_t index_size = dwarf_cu->GetAddressByteSize();
+ dw_offset_t addr_base = dwarf_cu->GetAddrBase();
+ lldb::offset_t offset = addr_base + index * index_size;
+ uint64_t value =
+ dwarf_cu->GetSymbolFileDWARF()->get_debug_addr_data().GetMaxU64(
+ &offset, index_size);
+ stack.push_back(Scalar(value));
+ stack.back().SetValueType(Value::eValueTypeFileAddress);
+ } break;
+
+ //----------------------------------------------------------------------
+ // OPCODE: DW_OP_GNU_const_index
+ // OPERANDS: 1
+ // ULEB128: index to the .debug_addr section
+ // DESCRIPTION: Pushes an constant with the size of a machine address to
+ // the stack from the .debug_addr section with the base address specified
+ // by the DW_AT_addr_base attribute and the 0 based index is the ULEB128
+ // encoded index.
+ //----------------------------------------------------------------------
+ case DW_OP_GNU_const_index: {
+ if (!dwarf_cu) {
+ if (error_ptr)
+ error_ptr->SetErrorString("DW_OP_GNU_const_index found without a "
+ "compile unit being specified");
+ return false;
+ }
+ uint64_t index = opcodes.GetULEB128(&offset);
+ uint32_t index_size = dwarf_cu->GetAddressByteSize();
+ dw_offset_t addr_base = dwarf_cu->GetAddrBase();
+ lldb::offset_t offset = addr_base + index * index_size;
+ const DWARFDataExtractor &debug_addr =
+ dwarf_cu->GetSymbolFileDWARF()->get_debug_addr_data();
+ switch (index_size) {
+ case 4:
+ stack.push_back(Scalar(debug_addr.GetU32(&offset)));
+ break;
+ case 8:
+ stack.push_back(Scalar(debug_addr.GetU64(&offset)));
+ break;
+ default:
+ assert(false && "Unhandled index size");
+ return false;
+ }
+ } break;
+
default:
- 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 (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
}
+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;
+}
+
+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;
+
+ 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");
+ 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;
+
+ opcode_class = DW_OP_value_to_class(opcode) & (~DRC_DWARFv3);
+
+ s.Printf("%s ", DW_OP_value_to_name(opcode));
+
+ /* Does this take zero parameters? If so we can shortcut this function. */
+ if (opcode_class == DRC_ZEROOPERANDS)
+ return true;
+
+ if (opcode_class == DRC_TWOOPERANDS && opcode == DW_OP_bregx) {
+ uint = data.GetULEB128(offset_ptr);
+ sint = data.GetSLEB128(offset_ptr);
+ s.Printf("%" PRIu64 " %" PRIi64, uint, sint);
+ return true;
+ }
+ if (opcode_class != DRC_ONEOPERAND) {
+ s.Printf("UNKNOWN OP %u", opcode);
+ return false;
+ }
+
+ switch (opcode) {
+ case DW_OP_addr:
+ size = address_size;
+ break;
+ case DW_OP_const1u:
+ size = 1;
+ break;
+ case DW_OP_const1s:
+ size = -1;
+ break;
+ case DW_OP_const2u:
+ size = 2;
+ break;
+ case DW_OP_const2s:
+ size = -2;
+ break;
+ case DW_OP_const4u:
+ size = 4;
+ break;
+ case DW_OP_const4s:
+ size = -4;
+ break;
+ case DW_OP_const8u:
+ size = 8;
+ break;
+ case DW_OP_const8s:
+ size = -8;
+ break;
+ case DW_OP_constu:
+ size = 128;
+ break;
+ case DW_OP_consts:
+ size = -128;
+ break;
+ case DW_OP_fbreg:
+ size = -128;
+ break;
+ case DW_OP_breg0:
+ case DW_OP_breg1:
+ case DW_OP_breg2:
+ case DW_OP_breg3:
+ case DW_OP_breg4:
+ case DW_OP_breg5:
+ case DW_OP_breg6:
+ case DW_OP_breg7:
+ case DW_OP_breg8:
+ case DW_OP_breg9:
+ case DW_OP_breg10:
+ case DW_OP_breg11:
+ case DW_OP_breg12:
+ case DW_OP_breg13:
+ case DW_OP_breg14:
+ case DW_OP_breg15:
+ case DW_OP_breg16:
+ case DW_OP_breg17:
+ case DW_OP_breg18:
+ case DW_OP_breg19:
+ case DW_OP_breg20:
+ case DW_OP_breg21:
+ case DW_OP_breg22:
+ case DW_OP_breg23:
+ case DW_OP_breg24:
+ case DW_OP_breg25:
+ case DW_OP_breg26:
+ case DW_OP_breg27:
+ case DW_OP_breg28:
+ case DW_OP_breg29:
+ case DW_OP_breg30:
+ case DW_OP_breg31:
+ size = -128;
+ break;
+ case DW_OP_pick:
+ case DW_OP_deref_size:
+ case DW_OP_xderef_size:
+ size = 1;
+ break;
+ case DW_OP_skip:
+ case DW_OP_bra:
+ size = -2;
+ break;
+ case DW_OP_call2:
+ size = 2;
+ break;
+ case DW_OP_call4:
+ size = 4;
+ break;
+ case DW_OP_call_ref:
+ size = dwarf_ref_size;
+ break;
+ case DW_OP_piece:
+ case DW_OP_plus_uconst:
+ case DW_OP_regx:
+ case DW_OP_GNU_addr_index:
+ case DW_OP_GNU_const_index:
+ size = 128;
+ break;
+ default:
+ s.Printf("UNKNOWN ONE-OPERAND OPCODE, #%u", opcode);
+ return true;
+ }
+
+ switch (size) {
+ case -1:
+ sint = (int8_t)data.GetU8(offset_ptr);
+ s.Printf("%+" PRIi64, sint);
+ break;
+ case -2:
+ sint = (int16_t)data.GetU16(offset_ptr);
+ s.Printf("%+" PRIi64, sint);
+ break;
+ case -4:
+ sint = (int32_t)data.GetU32(offset_ptr);
+ s.Printf("%+" PRIi64, sint);
+ break;
+ case -8:
+ sint = (int64_t)data.GetU64(offset_ptr);
+ s.Printf("%+" PRIi64, sint);
+ break;
+ case -128:
+ sint = data.GetSLEB128(offset_ptr);
+ s.Printf("%+" PRIi64, sint);
+ break;
+ case 1:
+ uint = data.GetU8(offset_ptr);
+ s.Printf("0x%2.2" PRIx64, uint);
+ break;
+ case 2:
+ uint = data.GetU16(offset_ptr);
+ s.Printf("0x%4.4" PRIx64, uint);
+ break;
+ case 4:
+ uint = data.GetU32(offset_ptr);
+ s.Printf("0x%8.8" PRIx64, uint);
+ break;
+ case 8:
+ uint = data.GetU64(offset_ptr);
+ s.Printf("0x%16.16" PRIx64, uint);
+ break;
+ case 128:
+ uint = data.GetULEB128(offset_ptr);
+ s.Printf("0x%" PRIx64, uint);
+ break;
+ }
+
+ return false;
+}
+
+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;
+}
+
+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;
+ }
+}
+
+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;
+ }
+
+ 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;
+ }
+
+ 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;
+ }
+
+ 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;
+ }
+ }
+}
+
+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);
+
+ 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;
+ }
+ }
+}
diff --git a/lldb/source/Expression/DiagnosticManager.cpp b/lldb/source/Expression/DiagnosticManager.cpp
index 5156ee3..37a9df7 100644
--- a/lldb/source/Expression/DiagnosticManager.cpp
+++ b/lldb/source/Expression/DiagnosticManager.cpp
@@ -16,76 +16,66 @@
using namespace lldb_private;
-void
-DiagnosticManager::Dump(Log *log)
-{
- if (!log)
- return;
+void DiagnosticManager::Dump(Log *log) {
+ if (!log)
+ return;
- std::string str = GetString();
+ std::string str = GetString();
- // GetString() puts a separator after each diagnostic.
- // We want to remove the last '\n' because log->PutCString will add one for us.
+ // GetString() puts a separator after each diagnostic.
+ // We want to remove the last '\n' because log->PutCString will add one for
+ // us.
- if (str.size() && str.back() == '\n')
- {
- str.pop_back();
- }
+ if (str.size() && str.back() == '\n') {
+ str.pop_back();
+ }
- log->PutCString(str.c_str());
+ log->PutCString(str.c_str());
}
-static const char *
-StringForSeverity(DiagnosticSeverity severity)
-{
- switch (severity)
- {
- // this should be exhaustive
- case lldb_private::eDiagnosticSeverityError:
- return "error: ";
- case lldb_private::eDiagnosticSeverityWarning:
- return "warning: ";
- case lldb_private::eDiagnosticSeverityRemark:
- return "";
- }
- llvm_unreachable("switch needs another case for DiagnosticSeverity enum");
+static const char *StringForSeverity(DiagnosticSeverity severity) {
+ switch (severity) {
+ // this should be exhaustive
+ case lldb_private::eDiagnosticSeverityError:
+ return "error: ";
+ case lldb_private::eDiagnosticSeverityWarning:
+ return "warning: ";
+ case lldb_private::eDiagnosticSeverityRemark:
+ return "";
+ }
+ llvm_unreachable("switch needs another case for DiagnosticSeverity enum");
}
-std::string
-DiagnosticManager::GetString(char separator)
-{
- std::string ret;
+std::string DiagnosticManager::GetString(char separator) {
+ std::string ret;
- for (const Diagnostic *diagnostic : Diagnostics())
- {
- ret.append(StringForSeverity(diagnostic->GetSeverity()));
- ret.append(diagnostic->GetMessage());
- ret.push_back(separator);
- }
+ for (const Diagnostic *diagnostic : Diagnostics()) {
+ ret.append(StringForSeverity(diagnostic->GetSeverity()));
+ ret.append(diagnostic->GetMessage());
+ ret.push_back(separator);
+ }
- return ret;
+ return ret;
}
-size_t
-DiagnosticManager::Printf(DiagnosticSeverity severity, const char *format, ...)
-{
- StreamString ss;
+size_t DiagnosticManager::Printf(DiagnosticSeverity severity,
+ const char *format, ...) {
+ StreamString ss;
- va_list args;
- va_start(args, format);
- size_t result = ss.PrintfVarArg(format, args);
- va_end(args);
+ va_list args;
+ va_start(args, format);
+ size_t result = ss.PrintfVarArg(format, args);
+ va_end(args);
- AddDiagnostic(ss.GetData(), severity, eDiagnosticOriginLLDB);
+ AddDiagnostic(ss.GetData(), severity, eDiagnosticOriginLLDB);
- return result;
+ return result;
}
-size_t
-DiagnosticManager::PutCString(DiagnosticSeverity severity, const char *cstr)
-{
- if (!cstr)
- return 0;
- AddDiagnostic(cstr, severity, eDiagnosticOriginLLDB);
- return strlen(cstr);
+size_t DiagnosticManager::PutCString(DiagnosticSeverity severity,
+ const char *cstr) {
+ if (!cstr)
+ return 0;
+ AddDiagnostic(cstr, severity, eDiagnosticOriginLLDB);
+ return strlen(cstr);
}
diff --git a/lldb/source/Expression/Expression.cpp b/lldb/source/Expression/Expression.cpp
index e5dd9c0..f637f0d 100644
--- a/lldb/source/Expression/Expression.cpp
+++ b/lldb/source/Expression/Expression.cpp
@@ -13,20 +13,17 @@
using namespace lldb_private;
-Expression::Expression (Target &target) :
- m_target_wp (target.shared_from_this()),
- m_jit_start_addr (LLDB_INVALID_ADDRESS),
- m_jit_end_addr (LLDB_INVALID_ADDRESS)
-{
- // Can't make any kind of expression without a target.
- assert (m_target_wp.lock());
+Expression::Expression(Target &target)
+ : m_target_wp(target.shared_from_this()),
+ m_jit_start_addr(LLDB_INVALID_ADDRESS),
+ m_jit_end_addr(LLDB_INVALID_ADDRESS) {
+ // Can't make any kind of expression without a target.
+ assert(m_target_wp.lock());
}
-Expression::Expression (ExecutionContextScope &exe_scope) :
- m_target_wp (exe_scope.CalculateTarget()),
- m_jit_start_addr (LLDB_INVALID_ADDRESS),
- m_jit_end_addr (LLDB_INVALID_ADDRESS)
-{
- assert (m_target_wp.lock());
+Expression::Expression(ExecutionContextScope &exe_scope)
+ : m_target_wp(exe_scope.CalculateTarget()),
+ m_jit_start_addr(LLDB_INVALID_ADDRESS),
+ m_jit_end_addr(LLDB_INVALID_ADDRESS) {
+ assert(m_target_wp.lock());
}
-
diff --git a/lldb/source/Expression/ExpressionSourceCode.cpp b/lldb/source/Expression/ExpressionSourceCode.cpp
index 2d41d1a..90a9ff2 100644
--- a/lldb/source/Expression/ExpressionSourceCode.cpp
+++ b/lldb/source/Expression/ExpressionSourceCode.cpp
@@ -9,12 +9,12 @@
#include "lldb/Expression/ExpressionSourceCode.h"
-#include "lldb/Core/StreamString.h"
#include "Plugins/ExpressionParser/Clang/ClangModulesDeclVendor.h"
#include "Plugins/ExpressionParser/Clang/ClangPersistentVariables.h"
+#include "lldb/Core/StreamString.h"
+#include "lldb/Symbol/Block.h"
#include "lldb/Symbol/CompileUnit.h"
#include "lldb/Symbol/DebugMacros.h"
-#include "lldb/Symbol/Block.h"
#include "lldb/Symbol/TypeSystem.h"
#include "lldb/Symbol/VariableList.h"
#include "lldb/Target/ExecutionContext.h"
@@ -25,8 +25,7 @@
using namespace lldb_private;
-const char *
-ExpressionSourceCode::g_expression_prefix = R"(
+const char *ExpressionSourceCode::g_expression_prefix = R"(
#ifndef NULL
#define NULL (__null)
#endif
@@ -62,366 +61,324 @@
)";
static const char *c_start_marker = " /*LLDB_BODY_START*/\n ";
-static const char *c_end_marker = ";\n /*LLDB_BODY_END*/\n";
+static const char *c_end_marker = ";\n /*LLDB_BODY_END*/\n";
namespace {
-class AddMacroState
-{
- enum State
- {
- CURRENT_FILE_NOT_YET_PUSHED,
- CURRENT_FILE_PUSHED,
- CURRENT_FILE_POPPED
- };
+class AddMacroState {
+ enum State {
+ CURRENT_FILE_NOT_YET_PUSHED,
+ CURRENT_FILE_PUSHED,
+ CURRENT_FILE_POPPED
+ };
public:
- AddMacroState(const FileSpec ¤t_file, const uint32_t current_file_line)
- : m_state(CURRENT_FILE_NOT_YET_PUSHED),
- m_current_file(current_file),
- m_current_file_line(current_file_line)
- { }
+ AddMacroState(const FileSpec ¤t_file, const uint32_t current_file_line)
+ : m_state(CURRENT_FILE_NOT_YET_PUSHED), m_current_file(current_file),
+ m_current_file_line(current_file_line) {}
- void
- StartFile(const FileSpec &file)
- {
- m_file_stack.push_back(file);
- if (file == m_current_file)
- m_state = CURRENT_FILE_PUSHED;
+ void StartFile(const FileSpec &file) {
+ m_file_stack.push_back(file);
+ if (file == m_current_file)
+ m_state = CURRENT_FILE_PUSHED;
+ }
+
+ void EndFile() {
+ if (m_file_stack.size() == 0)
+ return;
+
+ FileSpec old_top = m_file_stack.back();
+ m_file_stack.pop_back();
+ if (old_top == m_current_file)
+ m_state = CURRENT_FILE_POPPED;
+ }
+
+ // An entry is valid if it occurs before the current line in
+ // the current file.
+ bool IsValidEntry(uint32_t line) {
+ switch (m_state) {
+ case CURRENT_FILE_NOT_YET_PUSHED:
+ return true;
+ case CURRENT_FILE_PUSHED:
+ // If we are in file included in the current file,
+ // the entry should be added.
+ if (m_file_stack.back() != m_current_file)
+ return true;
+
+ if (line >= m_current_file_line)
+ return false;
+ else
+ return true;
+ default:
+ return false;
}
-
- void
- EndFile()
- {
- if (m_file_stack.size() == 0)
- return;
-
- FileSpec old_top = m_file_stack.back();
- m_file_stack.pop_back();
- if (old_top == m_current_file)
- m_state = CURRENT_FILE_POPPED;
- }
-
- // An entry is valid if it occurs before the current line in
- // the current file.
- bool
- IsValidEntry(uint32_t line)
- {
- switch (m_state)
- {
- case CURRENT_FILE_NOT_YET_PUSHED:
- return true;
- case CURRENT_FILE_PUSHED:
- // If we are in file included in the current file,
- // the entry should be added.
- if (m_file_stack.back() != m_current_file)
- return true;
-
- if (line >= m_current_file_line)
- return false;
- else
- return true;
- default:
- return false;
- }
- }
+ }
private:
- std::vector<FileSpec> m_file_stack;
- State m_state;
- FileSpec m_current_file;
- uint32_t m_current_file_line;
+ std::vector<FileSpec> m_file_stack;
+ State m_state;
+ FileSpec m_current_file;
+ uint32_t m_current_file_line;
};
} // anonymous namespace
-static void
-AddMacros(const DebugMacros *dm, CompileUnit *comp_unit, AddMacroState &state, StreamString &stream)
-{
- if (dm == nullptr)
+static void AddMacros(const DebugMacros *dm, CompileUnit *comp_unit,
+ AddMacroState &state, StreamString &stream) {
+ if (dm == nullptr)
+ return;
+
+ for (size_t i = 0; i < dm->GetNumMacroEntries(); i++) {
+ const DebugMacroEntry &entry = dm->GetMacroEntryAtIndex(i);
+ uint32_t line;
+
+ switch (entry.GetType()) {
+ case DebugMacroEntry::DEFINE:
+ if (state.IsValidEntry(entry.GetLineNumber()))
+ stream.Printf("#define %s\n", entry.GetMacroString().AsCString());
+ else
return;
-
- for (size_t i = 0; i < dm->GetNumMacroEntries(); i++)
- {
- const DebugMacroEntry &entry = dm->GetMacroEntryAtIndex(i);
- uint32_t line;
-
- switch (entry.GetType())
- {
- case DebugMacroEntry::DEFINE:
- if (state.IsValidEntry(entry.GetLineNumber()))
- stream.Printf("#define %s\n", entry.GetMacroString().AsCString());
- else
- return;
- break;
- case DebugMacroEntry::UNDEF:
- if (state.IsValidEntry(entry.GetLineNumber()))
- stream.Printf("#undef %s\n", entry.GetMacroString().AsCString());
- else
- return;
- break;
- case DebugMacroEntry::START_FILE:
- line = entry.GetLineNumber();
- if (state.IsValidEntry(line))
- state.StartFile(entry.GetFileSpec(comp_unit));
- else
- return;
- break;
- case DebugMacroEntry::END_FILE:
- state.EndFile();
- break;
- case DebugMacroEntry::INDIRECT:
- AddMacros(entry.GetIndirectDebugMacros(), comp_unit, state, stream);
- break;
- default:
- // This is an unknown/invalid entry. Ignore.
- break;
- }
- }
-}
-
-static void
-AddLocalVariableDecls(const lldb::VariableListSP &var_list_sp, StreamString &stream)
-{
- for (size_t i = 0; i < var_list_sp->GetSize(); i++)
- {
- lldb::VariableSP var_sp = var_list_sp->GetVariableAtIndex(i);
-
- ConstString var_name = var_sp->GetName();
- if (!var_name || var_name == ConstString("this") || var_name == ConstString(".block_descriptor"))
- continue;
-
- stream.Printf("using $__lldb_local_vars::%s;\n", var_name.AsCString());
- }
-}
-
-bool ExpressionSourceCode::GetText (std::string &text, lldb::LanguageType wrapping_language, bool static_method, ExecutionContext &exe_ctx) const
-{
- const char *target_specific_defines = "typedef signed char BOOL;\n";
- std::string module_macros;
-
- Target *target = exe_ctx.GetTargetPtr();
- if (target)
- {
- if (target->GetArchitecture().GetMachine() == llvm::Triple::aarch64)
- {
- target_specific_defines = "typedef bool BOOL;\n";
- }
- if (target->GetArchitecture().GetMachine() == llvm::Triple::x86_64)
- {
- if (lldb::PlatformSP platform_sp = target->GetPlatform())
- {
- static ConstString g_platform_ios_simulator ("ios-simulator");
- if (platform_sp->GetPluginName() == g_platform_ios_simulator)
- {
- target_specific_defines = "typedef bool BOOL;\n";
- }
- }
- }
-
- if (ClangModulesDeclVendor *decl_vendor = target->GetClangModulesDeclVendor())
- {
- ClangPersistentVariables *persistent_vars = llvm::cast<ClangPersistentVariables>(target->GetPersistentExpressionStateForLanguage(lldb::eLanguageTypeC));
- const ClangModulesDeclVendor::ModuleVector &hand_imported_modules = persistent_vars->GetHandLoadedClangModules();
- ClangModulesDeclVendor::ModuleVector modules_for_macros;
-
- for (ClangModulesDeclVendor::ModuleID module : hand_imported_modules)
- {
- modules_for_macros.push_back(module);
- }
-
- if (target->GetEnableAutoImportClangModules())
- {
- if (StackFrame *frame = exe_ctx.GetFramePtr())
- {
- if (Block *block = frame->GetFrameBlock())
- {
- SymbolContext sc;
-
- block->CalculateSymbolContext(&sc);
-
- if (sc.comp_unit)
- {
- StreamString error_stream;
-
- decl_vendor->AddModulesForCompileUnit(*sc.comp_unit, modules_for_macros, error_stream);
- }
- }
- }
- }
-
- decl_vendor->ForEachMacro(modules_for_macros, [&module_macros] (const std::string &expansion) -> bool {
- module_macros.append(expansion);
- module_macros.append("\n");
- return false;
- });
- }
-
- }
-
- StreamString debug_macros_stream;
- StreamString lldb_local_var_decls;
- if (StackFrame *frame = exe_ctx.GetFramePtr())
- {
- const SymbolContext &sc = frame->GetSymbolContext(
- lldb:: eSymbolContextCompUnit | lldb::eSymbolContextLineEntry);
-
- if (sc.comp_unit && sc.line_entry.IsValid())
- {
- DebugMacros *dm = sc.comp_unit->GetDebugMacros();
- if (dm)
- {
- AddMacroState state(sc.line_entry.file, sc.line_entry.line);
- AddMacros(dm, sc.comp_unit, state, debug_macros_stream);
- }
- }
-
- ConstString object_name;
- if (Language::LanguageIsCPlusPlus(frame->GetLanguage()))
- {
- if (target->GetInjectLocalVariables(&exe_ctx))
- {
- lldb::VariableListSP var_list_sp = frame->GetInScopeVariableList(false, true);
- AddLocalVariableDecls(var_list_sp, lldb_local_var_decls);
- }
- }
- }
-
- if (m_wrap)
- {
- switch (wrapping_language)
- {
- default:
- return false;
- case lldb::eLanguageTypeC:
- case lldb::eLanguageTypeC_plus_plus:
- case lldb::eLanguageTypeObjC:
- break;
- }
-
- StreamString wrap_stream;
-
- wrap_stream.Printf("%s\n%s\n%s\n%s\n%s\n",
- module_macros.c_str(),
- debug_macros_stream.GetData(),
- g_expression_prefix,
- target_specific_defines,
- m_prefix.c_str());
-
- // First construct a tagged form of the user expression so we can find it later:
- std::string tagged_body;
- switch (wrapping_language)
- {
- default:
- tagged_body = m_body;
- break;
- case lldb::eLanguageTypeC:
- case lldb::eLanguageTypeC_plus_plus:
- case lldb::eLanguageTypeObjC:
- tagged_body.append(c_start_marker);
- tagged_body.append(m_body);
- tagged_body.append(c_end_marker);
- break;
-
- }
- switch (wrapping_language)
- {
- default:
- break;
- case lldb::eLanguageTypeC:
- wrap_stream.Printf("void \n"
- "%s(void *$__lldb_arg) \n"
- "{ \n"
- " %s; \n"
- "%s"
- "} \n",
- m_name.c_str(),
- lldb_local_var_decls.GetData(),
- tagged_body.c_str());
- break;
- case lldb::eLanguageTypeC_plus_plus:
- wrap_stream.Printf("void \n"
- "$__lldb_class::%s(void *$__lldb_arg) \n"
- "{ \n"
- " %s; \n"
- "%s"
- "} \n",
- m_name.c_str(),
- lldb_local_var_decls.GetData(),
- tagged_body.c_str());
- break;
- case lldb::eLanguageTypeObjC:
- if (static_method)
- {
- wrap_stream.Printf("@interface $__lldb_objc_class ($__lldb_category) \n"
- "+(void)%s:(void *)$__lldb_arg; \n"
- "@end \n"
- "@implementation $__lldb_objc_class ($__lldb_category) \n"
- "+(void)%s:(void *)$__lldb_arg \n"
- "{ \n"
- "%s"
- "} \n"
- "@end \n",
- m_name.c_str(),
- m_name.c_str(),
- tagged_body.c_str());
- }
- else
- {
- wrap_stream.Printf("@interface $__lldb_objc_class ($__lldb_category) \n"
- "-(void)%s:(void *)$__lldb_arg; \n"
- "@end \n"
- "@implementation $__lldb_objc_class ($__lldb_category) \n"
- "-(void)%s:(void *)$__lldb_arg \n"
- "{ \n"
- "%s"
- "} \n"
- "@end \n",
- m_name.c_str(),
- m_name.c_str(),
- tagged_body.c_str());
- }
- break;
- }
-
- text = wrap_stream.GetString();
- }
- else
- {
- text.append(m_body);
- }
-
- return true;
-}
-
-bool
-ExpressionSourceCode::GetOriginalBodyBounds(std::string transformed_text,
- lldb::LanguageType wrapping_language,
- size_t &start_loc,
- size_t &end_loc)
-{
- const char *start_marker;
- const char *end_marker;
-
- switch (wrapping_language)
- {
+ break;
+ case DebugMacroEntry::UNDEF:
+ if (state.IsValidEntry(entry.GetLineNumber()))
+ stream.Printf("#undef %s\n", entry.GetMacroString().AsCString());
+ else
+ return;
+ break;
+ case DebugMacroEntry::START_FILE:
+ line = entry.GetLineNumber();
+ if (state.IsValidEntry(line))
+ state.StartFile(entry.GetFileSpec(comp_unit));
+ else
+ return;
+ break;
+ case DebugMacroEntry::END_FILE:
+ state.EndFile();
+ break;
+ case DebugMacroEntry::INDIRECT:
+ AddMacros(entry.GetIndirectDebugMacros(), comp_unit, state, stream);
+ break;
default:
- return false;
+ // This is an unknown/invalid entry. Ignore.
+ break;
+ }
+ }
+}
+
+static void AddLocalVariableDecls(const lldb::VariableListSP &var_list_sp,
+ StreamString &stream) {
+ for (size_t i = 0; i < var_list_sp->GetSize(); i++) {
+ lldb::VariableSP var_sp = var_list_sp->GetVariableAtIndex(i);
+
+ ConstString var_name = var_sp->GetName();
+ if (!var_name || var_name == ConstString("this") ||
+ var_name == ConstString(".block_descriptor"))
+ continue;
+
+ stream.Printf("using $__lldb_local_vars::%s;\n", var_name.AsCString());
+ }
+}
+
+bool ExpressionSourceCode::GetText(std::string &text,
+ lldb::LanguageType wrapping_language,
+ bool static_method,
+ ExecutionContext &exe_ctx) const {
+ const char *target_specific_defines = "typedef signed char BOOL;\n";
+ std::string module_macros;
+
+ Target *target = exe_ctx.GetTargetPtr();
+ if (target) {
+ if (target->GetArchitecture().GetMachine() == llvm::Triple::aarch64) {
+ target_specific_defines = "typedef bool BOOL;\n";
+ }
+ if (target->GetArchitecture().GetMachine() == llvm::Triple::x86_64) {
+ if (lldb::PlatformSP platform_sp = target->GetPlatform()) {
+ static ConstString g_platform_ios_simulator("ios-simulator");
+ if (platform_sp->GetPluginName() == g_platform_ios_simulator) {
+ target_specific_defines = "typedef bool BOOL;\n";
+ }
+ }
+ }
+
+ if (ClangModulesDeclVendor *decl_vendor =
+ target->GetClangModulesDeclVendor()) {
+ ClangPersistentVariables *persistent_vars =
+ llvm::cast<ClangPersistentVariables>(
+ target->GetPersistentExpressionStateForLanguage(
+ lldb::eLanguageTypeC));
+ const ClangModulesDeclVendor::ModuleVector &hand_imported_modules =
+ persistent_vars->GetHandLoadedClangModules();
+ ClangModulesDeclVendor::ModuleVector modules_for_macros;
+
+ for (ClangModulesDeclVendor::ModuleID module : hand_imported_modules) {
+ modules_for_macros.push_back(module);
+ }
+
+ if (target->GetEnableAutoImportClangModules()) {
+ if (StackFrame *frame = exe_ctx.GetFramePtr()) {
+ if (Block *block = frame->GetFrameBlock()) {
+ SymbolContext sc;
+
+ block->CalculateSymbolContext(&sc);
+
+ if (sc.comp_unit) {
+ StreamString error_stream;
+
+ decl_vendor->AddModulesForCompileUnit(
+ *sc.comp_unit, modules_for_macros, error_stream);
+ }
+ }
+ }
+ }
+
+ decl_vendor->ForEachMacro(
+ modules_for_macros,
+ [&module_macros](const std::string &expansion) -> bool {
+ module_macros.append(expansion);
+ module_macros.append("\n");
+ return false;
+ });
+ }
+ }
+
+ StreamString debug_macros_stream;
+ StreamString lldb_local_var_decls;
+ if (StackFrame *frame = exe_ctx.GetFramePtr()) {
+ const SymbolContext &sc = frame->GetSymbolContext(
+ lldb::eSymbolContextCompUnit | lldb::eSymbolContextLineEntry);
+
+ if (sc.comp_unit && sc.line_entry.IsValid()) {
+ DebugMacros *dm = sc.comp_unit->GetDebugMacros();
+ if (dm) {
+ AddMacroState state(sc.line_entry.file, sc.line_entry.line);
+ AddMacros(dm, sc.comp_unit, state, debug_macros_stream);
+ }
+ }
+
+ ConstString object_name;
+ if (Language::LanguageIsCPlusPlus(frame->GetLanguage())) {
+ if (target->GetInjectLocalVariables(&exe_ctx)) {
+ lldb::VariableListSP var_list_sp =
+ frame->GetInScopeVariableList(false, true);
+ AddLocalVariableDecls(var_list_sp, lldb_local_var_decls);
+ }
+ }
+ }
+
+ if (m_wrap) {
+ switch (wrapping_language) {
+ default:
+ return false;
case lldb::eLanguageTypeC:
case lldb::eLanguageTypeC_plus_plus:
case lldb::eLanguageTypeObjC:
- start_marker = c_start_marker;
- end_marker = c_end_marker;
- break;
+ break;
}
-
- start_loc = transformed_text.find(start_marker);
- if (start_loc == std::string::npos)
- return false;
- start_loc += strlen(start_marker);
- end_loc = transformed_text.find(end_marker);
- if (end_loc == std::string::npos)
- return false;
- return true;
+
+ StreamString wrap_stream;
+
+ wrap_stream.Printf("%s\n%s\n%s\n%s\n%s\n", module_macros.c_str(),
+ debug_macros_stream.GetData(), g_expression_prefix,
+ target_specific_defines, m_prefix.c_str());
+
+ // First construct a tagged form of the user expression so we can find it
+ // later:
+ std::string tagged_body;
+ switch (wrapping_language) {
+ default:
+ tagged_body = m_body;
+ break;
+ case lldb::eLanguageTypeC:
+ case lldb::eLanguageTypeC_plus_plus:
+ case lldb::eLanguageTypeObjC:
+ tagged_body.append(c_start_marker);
+ tagged_body.append(m_body);
+ tagged_body.append(c_end_marker);
+ break;
+ }
+ switch (wrapping_language) {
+ default:
+ break;
+ case lldb::eLanguageTypeC:
+ wrap_stream.Printf("void \n"
+ "%s(void *$__lldb_arg) \n"
+ "{ \n"
+ " %s; \n"
+ "%s"
+ "} \n",
+ m_name.c_str(), lldb_local_var_decls.GetData(),
+ tagged_body.c_str());
+ break;
+ case lldb::eLanguageTypeC_plus_plus:
+ wrap_stream.Printf("void \n"
+ "$__lldb_class::%s(void *$__lldb_arg) \n"
+ "{ \n"
+ " %s; \n"
+ "%s"
+ "} \n",
+ m_name.c_str(), lldb_local_var_decls.GetData(),
+ tagged_body.c_str());
+ break;
+ case lldb::eLanguageTypeObjC:
+ if (static_method) {
+ wrap_stream.Printf(
+ "@interface $__lldb_objc_class ($__lldb_category) \n"
+ "+(void)%s:(void *)$__lldb_arg; \n"
+ "@end \n"
+ "@implementation $__lldb_objc_class ($__lldb_category) \n"
+ "+(void)%s:(void *)$__lldb_arg \n"
+ "{ \n"
+ "%s"
+ "} \n"
+ "@end \n",
+ m_name.c_str(), m_name.c_str(), tagged_body.c_str());
+ } else {
+ wrap_stream.Printf(
+ "@interface $__lldb_objc_class ($__lldb_category) \n"
+ "-(void)%s:(void *)$__lldb_arg; \n"
+ "@end \n"
+ "@implementation $__lldb_objc_class ($__lldb_category) \n"
+ "-(void)%s:(void *)$__lldb_arg \n"
+ "{ \n"
+ "%s"
+ "} \n"
+ "@end \n",
+ m_name.c_str(), m_name.c_str(), tagged_body.c_str());
+ }
+ break;
+ }
+
+ text = wrap_stream.GetString();
+ } else {
+ text.append(m_body);
+ }
+
+ return true;
}
+bool ExpressionSourceCode::GetOriginalBodyBounds(
+ std::string transformed_text, lldb::LanguageType wrapping_language,
+ size_t &start_loc, size_t &end_loc) {
+ const char *start_marker;
+ const char *end_marker;
+
+ switch (wrapping_language) {
+ default:
+ return false;
+ case lldb::eLanguageTypeC:
+ case lldb::eLanguageTypeC_plus_plus:
+ case lldb::eLanguageTypeObjC:
+ start_marker = c_start_marker;
+ end_marker = c_end_marker;
+ break;
+ }
+
+ start_loc = transformed_text.find(start_marker);
+ if (start_loc == std::string::npos)
+ return false;
+ start_loc += strlen(start_marker);
+ end_loc = transformed_text.find(end_marker);
+ if (end_loc == std::string::npos)
+ return false;
+ return true;
+}
diff --git a/lldb/source/Expression/ExpressionVariable.cpp b/lldb/source/Expression/ExpressionVariable.cpp
index 5567ee2..00e6896 100644
--- a/lldb/source/Expression/ExpressionVariable.cpp
+++ b/lldb/source/Expression/ExpressionVariable.cpp
@@ -7,84 +7,76 @@
//
//===----------------------------------------------------------------------===//
-#include "lldb/Core/Log.h"
#include "lldb/Expression/ExpressionVariable.h"
+#include "lldb/Core/Log.h"
#include "lldb/Expression/IRExecutionUnit.h"
using namespace lldb_private;
-ExpressionVariable::~ExpressionVariable()
-{
-}
+ExpressionVariable::~ExpressionVariable() {}
-uint8_t *
-ExpressionVariable::GetValueBytes()
-{
- const size_t byte_size = m_frozen_sp->GetByteSize();
- if (byte_size > 0)
- {
- if (m_frozen_sp->GetDataExtractor().GetByteSize() < byte_size)
- {
- m_frozen_sp->GetValue().ResizeData(byte_size);
- m_frozen_sp->GetValue().GetData (m_frozen_sp->GetDataExtractor());
- }
- return const_cast<uint8_t *>(m_frozen_sp->GetDataExtractor().GetDataStart());
+uint8_t *ExpressionVariable::GetValueBytes() {
+ const size_t byte_size = m_frozen_sp->GetByteSize();
+ if (byte_size > 0) {
+ if (m_frozen_sp->GetDataExtractor().GetByteSize() < byte_size) {
+ m_frozen_sp->GetValue().ResizeData(byte_size);
+ m_frozen_sp->GetValue().GetData(m_frozen_sp->GetDataExtractor());
}
- return NULL;
+ return const_cast<uint8_t *>(
+ m_frozen_sp->GetDataExtractor().GetDataStart());
+ }
+ return NULL;
}
-PersistentExpressionState::~PersistentExpressionState ()
-{
+PersistentExpressionState::~PersistentExpressionState() {}
+
+lldb::addr_t PersistentExpressionState::LookupSymbol(const ConstString &name) {
+ SymbolMap::iterator si = m_symbol_map.find(name.GetCString());
+
+ if (si != m_symbol_map.end())
+ return si->second;
+ else
+ return LLDB_INVALID_ADDRESS;
}
-lldb::addr_t
-PersistentExpressionState::LookupSymbol (const ConstString &name)
-{
- SymbolMap::iterator si = m_symbol_map.find(name.GetCString());
-
- if (si != m_symbol_map.end())
- return si->second;
- else
- return LLDB_INVALID_ADDRESS;
-}
+void PersistentExpressionState::RegisterExecutionUnit(
+ lldb::IRExecutionUnitSP &execution_unit_sp) {
+ Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS));
+ m_execution_units.insert(execution_unit_sp);
-void
-PersistentExpressionState::RegisterExecutionUnit (lldb::IRExecutionUnitSP &execution_unit_sp)
-{
- Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
-
- m_execution_units.insert(execution_unit_sp);
-
- if (log)
- log->Printf ("Registering JITted Functions:\n");
-
- for (const IRExecutionUnit::JittedFunction &jitted_function : execution_unit_sp->GetJittedFunctions())
- {
- if (jitted_function.m_external &&
- jitted_function.m_name != execution_unit_sp->GetFunctionName() &&
- jitted_function.m_remote_addr != LLDB_INVALID_ADDRESS)
- {
- m_symbol_map[jitted_function.m_name.GetCString()] = jitted_function.m_remote_addr;
- if (log)
- log->Printf (" Function: %s at 0x%" PRIx64 ".", jitted_function.m_name.GetCString(), jitted_function.m_remote_addr);
- }
+ if (log)
+ log->Printf("Registering JITted Functions:\n");
+
+ for (const IRExecutionUnit::JittedFunction &jitted_function :
+ execution_unit_sp->GetJittedFunctions()) {
+ if (jitted_function.m_external &&
+ jitted_function.m_name != execution_unit_sp->GetFunctionName() &&
+ jitted_function.m_remote_addr != LLDB_INVALID_ADDRESS) {
+ m_symbol_map[jitted_function.m_name.GetCString()] =
+ jitted_function.m_remote_addr;
+ if (log)
+ log->Printf(" Function: %s at 0x%" PRIx64 ".",
+ jitted_function.m_name.GetCString(),
+ jitted_function.m_remote_addr);
}
-
- if (log)
- log->Printf ("Registering JIIted Symbols:\n");
-
- for (const IRExecutionUnit::JittedGlobalVariable &global_var : execution_unit_sp->GetJittedGlobalVariables())
- {
- if (global_var.m_remote_addr != LLDB_INVALID_ADDRESS)
- {
- // Demangle the name before inserting it, so that lookups by the ConstStr of the demangled name
- // will find the mangled one (needed for looking up metadata pointers.)
- Mangled mangler(global_var.m_name);
- mangler.GetDemangledName(lldb::eLanguageTypeUnknown);
- m_symbol_map[global_var.m_name.GetCString()] = global_var.m_remote_addr;
- if (log)
- log->Printf (" Symbol: %s at 0x%" PRIx64 ".", global_var.m_name.GetCString(), global_var.m_remote_addr);
- }
+ }
+
+ if (log)
+ log->Printf("Registering JIIted Symbols:\n");
+
+ for (const IRExecutionUnit::JittedGlobalVariable &global_var :
+ execution_unit_sp->GetJittedGlobalVariables()) {
+ if (global_var.m_remote_addr != LLDB_INVALID_ADDRESS) {
+ // Demangle the name before inserting it, so that lookups by the ConstStr
+ // of the demangled name
+ // will find the mangled one (needed for looking up metadata pointers.)
+ Mangled mangler(global_var.m_name);
+ mangler.GetDemangledName(lldb::eLanguageTypeUnknown);
+ m_symbol_map[global_var.m_name.GetCString()] = global_var.m_remote_addr;
+ if (log)
+ log->Printf(" Symbol: %s at 0x%" PRIx64 ".",
+ global_var.m_name.GetCString(), global_var.m_remote_addr);
}
+ }
}
diff --git a/lldb/source/Expression/FunctionCaller.cpp b/lldb/source/Expression/FunctionCaller.cpp
index 3a4f1fe..805afda 100644
--- a/lldb/source/Expression/FunctionCaller.cpp
+++ b/lldb/source/Expression/FunctionCaller.cpp
@@ -1,4 +1,5 @@
-//===-- FunctionCaller.cpp ---------------------------------------*- C++ -*-===//
+//===-- FunctionCaller.cpp ---------------------------------------*- C++
+//-*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -7,7 +8,6 @@
//
//===----------------------------------------------------------------------===//
-
// C Includes
// C++ Includes
// Other libraries and framework includes
@@ -38,364 +38,358 @@
//----------------------------------------------------------------------
// FunctionCaller constructor
//----------------------------------------------------------------------
-FunctionCaller::FunctionCaller
-(
- ExecutionContextScope &exe_scope,
- const CompilerType &return_type,
- const Address& functionAddress,
- const ValueList &arg_value_list,
- const char *name
-) :
- Expression (exe_scope),
- m_execution_unit_sp(),
- m_parser(),
- m_jit_module_wp(),
- m_name (name ? name : "<unknown>"),
- m_function_ptr (NULL),
- m_function_addr (functionAddress),
- m_function_return_type(return_type),
- m_wrapper_function_name ("__lldb_caller_function"),
- m_wrapper_struct_name ("__lldb_caller_struct"),
- m_wrapper_args_addrs (),
- m_arg_values (arg_value_list),
- m_compiled (false),
- m_JITted (false)
-{
- m_jit_process_wp = lldb::ProcessWP(exe_scope.CalculateProcess());
- // Can't make a FunctionCaller without a process.
- assert (m_jit_process_wp.lock());
+FunctionCaller::FunctionCaller(ExecutionContextScope &exe_scope,
+ const CompilerType &return_type,
+ const Address &functionAddress,
+ const ValueList &arg_value_list,
+ const char *name)
+ : Expression(exe_scope), m_execution_unit_sp(), m_parser(),
+ m_jit_module_wp(), m_name(name ? name : "<unknown>"),
+ m_function_ptr(NULL), m_function_addr(functionAddress),
+ m_function_return_type(return_type),
+ m_wrapper_function_name("__lldb_caller_function"),
+ m_wrapper_struct_name("__lldb_caller_struct"), m_wrapper_args_addrs(),
+ m_arg_values(arg_value_list), m_compiled(false), m_JITted(false) {
+ m_jit_process_wp = lldb::ProcessWP(exe_scope.CalculateProcess());
+ // Can't make a FunctionCaller without a process.
+ assert(m_jit_process_wp.lock());
}
//----------------------------------------------------------------------
// Destructor
//----------------------------------------------------------------------
-FunctionCaller::~FunctionCaller()
-{
- lldb::ProcessSP process_sp (m_jit_process_wp.lock());
- if (process_sp)
- {
- lldb::ModuleSP jit_module_sp (m_jit_module_wp.lock());
- if (jit_module_sp)
- process_sp->GetTarget().GetImages().Remove(jit_module_sp);
- }
+FunctionCaller::~FunctionCaller() {
+ lldb::ProcessSP process_sp(m_jit_process_wp.lock());
+ if (process_sp) {
+ lldb::ModuleSP jit_module_sp(m_jit_module_wp.lock());
+ if (jit_module_sp)
+ process_sp->GetTarget().GetImages().Remove(jit_module_sp);
+ }
}
-bool
-FunctionCaller::WriteFunctionWrapper(ExecutionContext &exe_ctx, DiagnosticManager &diagnostic_manager)
-{
- Process *process = exe_ctx.GetProcessPtr();
+bool FunctionCaller::WriteFunctionWrapper(
+ ExecutionContext &exe_ctx, DiagnosticManager &diagnostic_manager) {
+ Process *process = exe_ctx.GetProcessPtr();
- if (!process)
- return false;
-
- lldb::ProcessSP jit_process_sp(m_jit_process_wp.lock());
-
- if (process != jit_process_sp.get())
- return false;
-
- if (!m_compiled)
- return false;
+ if (!process)
+ return false;
- if (m_JITted)
- return true;
-
- bool can_interpret = false; // should stay that way
-
- Error jit_error (m_parser->PrepareForExecution (m_jit_start_addr,
- m_jit_end_addr,
- m_execution_unit_sp,
- exe_ctx,
- can_interpret,
- eExecutionPolicyAlways));
-
- if (!jit_error.Success())
- return false;
-
- if (m_parser->GetGenerateDebugInfo())
- {
- lldb::ModuleSP jit_module_sp ( m_execution_unit_sp->GetJITModule());
-
- if (jit_module_sp)
- {
- ConstString const_func_name(FunctionName());
- FileSpec jit_file;
- jit_file.GetFilename() = const_func_name;
- jit_module_sp->SetFileSpecAndObjectName (jit_file, ConstString());
- m_jit_module_wp = jit_module_sp;
- process->GetTarget().GetImages().Append(jit_module_sp);
- }
- }
- if (process && m_jit_start_addr)
- m_jit_process_wp = process->shared_from_this();
-
- m_JITted = true;
+ lldb::ProcessSP jit_process_sp(m_jit_process_wp.lock());
+ if (process != jit_process_sp.get())
+ return false;
+
+ if (!m_compiled)
+ return false;
+
+ if (m_JITted)
return true;
-}
-bool
-FunctionCaller::WriteFunctionArguments(ExecutionContext &exe_ctx, lldb::addr_t &args_addr_ref,
- DiagnosticManager &diagnostic_manager)
-{
- return WriteFunctionArguments(exe_ctx, args_addr_ref, m_arg_values, diagnostic_manager);
-}
+ bool can_interpret = false; // should stay that way
-// FIXME: Assure that the ValueList we were passed in is consistent with the one that defined this function.
+ Error jit_error(m_parser->PrepareForExecution(
+ m_jit_start_addr, m_jit_end_addr, m_execution_unit_sp, exe_ctx,
+ can_interpret, eExecutionPolicyAlways));
-bool
-FunctionCaller::WriteFunctionArguments(ExecutionContext &exe_ctx, lldb::addr_t &args_addr_ref, ValueList &arg_values,
- DiagnosticManager &diagnostic_manager)
-{
- // All the information to reconstruct the struct is provided by the
- // StructExtractor.
- if (!m_struct_valid)
- {
- diagnostic_manager.PutCString(
- eDiagnosticSeverityError,
- "Argument information was not correctly parsed, so the function cannot be called.");
- return false;
+ if (!jit_error.Success())
+ return false;
+
+ if (m_parser->GetGenerateDebugInfo()) {
+ lldb::ModuleSP jit_module_sp(m_execution_unit_sp->GetJITModule());
+
+ if (jit_module_sp) {
+ ConstString const_func_name(FunctionName());
+ FileSpec jit_file;
+ jit_file.GetFilename() = const_func_name;
+ jit_module_sp->SetFileSpecAndObjectName(jit_file, ConstString());
+ m_jit_module_wp = jit_module_sp;
+ process->GetTarget().GetImages().Append(jit_module_sp);
}
+ }
+ if (process && m_jit_start_addr)
+ m_jit_process_wp = process->shared_from_this();
- Error error;
- lldb::ExpressionResults return_value = lldb::eExpressionSetupError;
+ m_JITted = true;
- Process *process = exe_ctx.GetProcessPtr();
+ return true;
+}
- if (process == NULL)
- return return_value;
+bool FunctionCaller::WriteFunctionArguments(
+ ExecutionContext &exe_ctx, lldb::addr_t &args_addr_ref,
+ DiagnosticManager &diagnostic_manager) {
+ return WriteFunctionArguments(exe_ctx, args_addr_ref, m_arg_values,
+ diagnostic_manager);
+}
- lldb::ProcessSP jit_process_sp(m_jit_process_wp.lock());
-
- if (process != jit_process_sp.get())
- return false;
-
+// FIXME: Assure that the ValueList we were passed in is consistent with the one
+// that defined this function.
+
+bool FunctionCaller::WriteFunctionArguments(
+ ExecutionContext &exe_ctx, lldb::addr_t &args_addr_ref,
+ ValueList &arg_values, DiagnosticManager &diagnostic_manager) {
+ // All the information to reconstruct the struct is provided by the
+ // StructExtractor.
+ if (!m_struct_valid) {
+ diagnostic_manager.PutCString(eDiagnosticSeverityError,
+ "Argument information was not correctly "
+ "parsed, so the function cannot be called.");
+ return false;
+ }
+
+ Error error;
+ lldb::ExpressionResults return_value = lldb::eExpressionSetupError;
+
+ Process *process = exe_ctx.GetProcessPtr();
+
+ if (process == NULL)
+ return return_value;
+
+ lldb::ProcessSP jit_process_sp(m_jit_process_wp.lock());
+
+ if (process != jit_process_sp.get())
+ return false;
+
+ if (args_addr_ref == LLDB_INVALID_ADDRESS) {
+ args_addr_ref = process->AllocateMemory(
+ m_struct_size, lldb::ePermissionsReadable | lldb::ePermissionsWritable,
+ error);
if (args_addr_ref == LLDB_INVALID_ADDRESS)
- {
- args_addr_ref = process->AllocateMemory(m_struct_size, lldb::ePermissionsReadable|lldb::ePermissionsWritable, error);
- if (args_addr_ref == LLDB_INVALID_ADDRESS)
- return false;
- m_wrapper_args_addrs.push_back (args_addr_ref);
- }
- else
- {
- // Make sure this is an address that we've already handed out.
- if (find (m_wrapper_args_addrs.begin(), m_wrapper_args_addrs.end(), args_addr_ref) == m_wrapper_args_addrs.end())
- {
- return false;
- }
+ return false;
+ m_wrapper_args_addrs.push_back(args_addr_ref);
+ } else {
+ // Make sure this is an address that we've already handed out.
+ if (find(m_wrapper_args_addrs.begin(), m_wrapper_args_addrs.end(),
+ args_addr_ref) == m_wrapper_args_addrs.end()) {
+ return false;
}
+ }
- // TODO: verify fun_addr needs to be a callable address
- Scalar fun_addr (m_function_addr.GetCallableLoadAddress(exe_ctx.GetTargetPtr()));
- uint64_t first_offset = m_member_offsets[0];
- process->WriteScalarToMemory(args_addr_ref + first_offset, fun_addr, process->GetAddressByteSize(), error);
+ // TODO: verify fun_addr needs to be a callable address
+ Scalar fun_addr(
+ m_function_addr.GetCallableLoadAddress(exe_ctx.GetTargetPtr()));
+ uint64_t first_offset = m_member_offsets[0];
+ process->WriteScalarToMemory(args_addr_ref + first_offset, fun_addr,
+ process->GetAddressByteSize(), error);
- // FIXME: We will need to extend this for Variadic functions.
+ // FIXME: We will need to extend this for Variadic functions.
- Error value_error;
+ Error value_error;
- size_t num_args = arg_values.GetSize();
- if (num_args != m_arg_values.GetSize())
- {
- diagnostic_manager.Printf(eDiagnosticSeverityError,
- "Wrong number of arguments - was: %" PRIu64 " should be: %" PRIu64 "",
- (uint64_t)num_args, (uint64_t)m_arg_values.GetSize());
- return false;
- }
+ size_t num_args = arg_values.GetSize();
+ if (num_args != m_arg_values.GetSize()) {
+ diagnostic_manager.Printf(
+ eDiagnosticSeverityError,
+ "Wrong number of arguments - was: %" PRIu64 " should be: %" PRIu64 "",
+ (uint64_t)num_args, (uint64_t)m_arg_values.GetSize());
+ return false;
+ }
- for (size_t i = 0; i < num_args; i++)
- {
- // FIXME: We should sanity check sizes.
+ for (size_t i = 0; i < num_args; i++) {
+ // FIXME: We should sanity check sizes.
- uint64_t offset = m_member_offsets[i+1]; // Clang sizes are in bytes.
- Value *arg_value = arg_values.GetValueAtIndex(i);
-
- // FIXME: For now just do scalars:
-
- // Special case: if it's a pointer, don't do anything (the ABI supports passing cstrings)
-
- if (arg_value->GetValueType() == Value::eValueTypeHostAddress &&
- arg_value->GetContextType() == Value::eContextTypeInvalid &&
- arg_value->GetCompilerType().IsPointerType())
- continue;
-
- const Scalar &arg_scalar = arg_value->ResolveValue(&exe_ctx);
+ uint64_t offset = m_member_offsets[i + 1]; // Clang sizes are in bytes.
+ Value *arg_value = arg_values.GetValueAtIndex(i);
- if (!process->WriteScalarToMemory(args_addr_ref + offset, arg_scalar, arg_scalar.GetByteSize(), error))
- return false;
- }
+ // FIXME: For now just do scalars:
- return true;
+ // Special case: if it's a pointer, don't do anything (the ABI supports
+ // passing cstrings)
+
+ if (arg_value->GetValueType() == Value::eValueTypeHostAddress &&
+ arg_value->GetContextType() == Value::eContextTypeInvalid &&
+ arg_value->GetCompilerType().IsPointerType())
+ continue;
+
+ const Scalar &arg_scalar = arg_value->ResolveValue(&exe_ctx);
+
+ if (!process->WriteScalarToMemory(args_addr_ref + offset, arg_scalar,
+ arg_scalar.GetByteSize(), error))
+ return false;
+ }
+
+ return true;
}
-bool
-FunctionCaller::InsertFunction(ExecutionContext &exe_ctx, lldb::addr_t &args_addr_ref,
- DiagnosticManager &diagnostic_manager)
-{
- if (CompileFunction(exe_ctx.GetThreadSP(), diagnostic_manager) != 0)
- return false;
- if (!WriteFunctionWrapper(exe_ctx, diagnostic_manager))
- return false;
- if (!WriteFunctionArguments(exe_ctx, args_addr_ref, diagnostic_manager))
- return false;
+bool FunctionCaller::InsertFunction(ExecutionContext &exe_ctx,
+ lldb::addr_t &args_addr_ref,
+ DiagnosticManager &diagnostic_manager) {
+ if (CompileFunction(exe_ctx.GetThreadSP(), diagnostic_manager) != 0)
+ return false;
+ if (!WriteFunctionWrapper(exe_ctx, diagnostic_manager))
+ return false;
+ if (!WriteFunctionArguments(exe_ctx, args_addr_ref, diagnostic_manager))
+ return false;
- Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_STEP));
- if (log)
- log->Printf ("Call Address: 0x%" PRIx64 " Struct Address: 0x%" PRIx64 ".\n", m_jit_start_addr, args_addr_ref);
-
- return true;
+ Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_STEP));
+ if (log)
+ log->Printf("Call Address: 0x%" PRIx64 " Struct Address: 0x%" PRIx64 ".\n",
+ m_jit_start_addr, args_addr_ref);
+
+ return true;
}
-lldb::ThreadPlanSP
-FunctionCaller::GetThreadPlanToCallFunction(ExecutionContext &exe_ctx, lldb::addr_t args_addr,
- const EvaluateExpressionOptions &options,
- DiagnosticManager &diagnostic_manager)
-{
- Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_EXPRESSIONS | LIBLLDB_LOG_STEP));
+lldb::ThreadPlanSP FunctionCaller::GetThreadPlanToCallFunction(
+ ExecutionContext &exe_ctx, lldb::addr_t args_addr,
+ const EvaluateExpressionOptions &options,
+ DiagnosticManager &diagnostic_manager) {
+ Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_EXPRESSIONS |
+ LIBLLDB_LOG_STEP));
- if (log)
- log->Printf("-- [FunctionCaller::GetThreadPlanToCallFunction] Creating thread plan to call function \"%s\" --", m_name.c_str());
-
- // FIXME: Use the errors Stream for better error reporting.
- Thread *thread = exe_ctx.GetThreadPtr();
- if (thread == NULL)
- {
- diagnostic_manager.PutCString(eDiagnosticSeverityError, "Can't call a function without a valid thread.");
- return NULL;
+ if (log)
+ log->Printf("-- [FunctionCaller::GetThreadPlanToCallFunction] Creating "
+ "thread plan to call function \"%s\" --",
+ m_name.c_str());
+
+ // FIXME: Use the errors Stream for better error reporting.
+ Thread *thread = exe_ctx.GetThreadPtr();
+ if (thread == NULL) {
+ diagnostic_manager.PutCString(
+ eDiagnosticSeverityError,
+ "Can't call a function without a valid thread.");
+ return NULL;
+ }
+
+ // Okay, now run the function:
+
+ Address wrapper_address(m_jit_start_addr);
+
+ lldb::addr_t args = {args_addr};
+
+ lldb::ThreadPlanSP new_plan_sp(new ThreadPlanCallFunction(
+ *thread, wrapper_address, CompilerType(), args, options));
+ new_plan_sp->SetIsMasterPlan(true);
+ new_plan_sp->SetOkayToDiscard(false);
+ return new_plan_sp;
+}
+
+bool FunctionCaller::FetchFunctionResults(ExecutionContext &exe_ctx,
+ lldb::addr_t args_addr,
+ Value &ret_value) {
+ // Read the return value - it is the last field in the struct:
+ // FIXME: How does clang tell us there's no return value? We need to handle
+ // that case.
+ // FIXME: Create our ThreadPlanCallFunction with the return CompilerType, and
+ // then use GetReturnValueObject
+ // to fetch the value. That way we can fetch any values we need.
+
+ Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_EXPRESSIONS |
+ LIBLLDB_LOG_STEP));
+
+ if (log)
+ log->Printf("-- [FunctionCaller::FetchFunctionResults] Fetching function "
+ "results for \"%s\"--",
+ m_name.c_str());
+
+ Process *process = exe_ctx.GetProcessPtr();
+
+ if (process == NULL)
+ return false;
+
+ lldb::ProcessSP jit_process_sp(m_jit_process_wp.lock());
+
+ if (process != jit_process_sp.get())
+ return false;
+
+ Error error;
+ ret_value.GetScalar() = process->ReadUnsignedIntegerFromMemory(
+ args_addr + m_return_offset, m_return_size, 0, error);
+
+ if (error.Fail())
+ return false;
+
+ ret_value.SetCompilerType(m_function_return_type);
+ ret_value.SetValueType(Value::eValueTypeScalar);
+ return true;
+}
+
+void FunctionCaller::DeallocateFunctionResults(ExecutionContext &exe_ctx,
+ lldb::addr_t args_addr) {
+ std::list<lldb::addr_t>::iterator pos;
+ pos = std::find(m_wrapper_args_addrs.begin(), m_wrapper_args_addrs.end(),
+ args_addr);
+ if (pos != m_wrapper_args_addrs.end())
+ m_wrapper_args_addrs.erase(pos);
+
+ exe_ctx.GetProcessRef().DeallocateMemory(args_addr);
+}
+
+lldb::ExpressionResults FunctionCaller::ExecuteFunction(
+ ExecutionContext &exe_ctx, lldb::addr_t *args_addr_ptr,
+ const EvaluateExpressionOptions &options,
+ DiagnosticManager &diagnostic_manager, Value &results) {
+ lldb::ExpressionResults return_value = lldb::eExpressionSetupError;
+
+ // FunctionCaller::ExecuteFunction execution is always just to get the result.
+ // Do make sure we ignore
+ // breakpoints, unwind on error, and don't try to debug it.
+ EvaluateExpressionOptions real_options = options;
+ real_options.SetDebug(false);
+ real_options.SetUnwindOnError(true);
+ real_options.SetIgnoreBreakpoints(true);
+
+ lldb::addr_t args_addr;
+
+ if (args_addr_ptr != NULL)
+ args_addr = *args_addr_ptr;
+ else
+ args_addr = LLDB_INVALID_ADDRESS;
+
+ if (CompileFunction(exe_ctx.GetThreadSP(), diagnostic_manager) != 0)
+ return lldb::eExpressionSetupError;
+
+ if (args_addr == LLDB_INVALID_ADDRESS) {
+ if (!InsertFunction(exe_ctx, args_addr, diagnostic_manager))
+ return lldb::eExpressionSetupError;
+ }
+
+ Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_EXPRESSIONS |
+ LIBLLDB_LOG_STEP));
+
+ if (log)
+ log->Printf(
+ "== [FunctionCaller::ExecuteFunction] Executing function \"%s\" ==",
+ m_name.c_str());
+
+ lldb::ThreadPlanSP call_plan_sp = GetThreadPlanToCallFunction(
+ exe_ctx, args_addr, real_options, diagnostic_manager);
+ if (!call_plan_sp)
+ return lldb::eExpressionSetupError;
+
+ // We need to make sure we record the fact that we are running an expression
+ // here
+ // otherwise this fact will fail to be recorded when fetching an Objective-C
+ // object description
+ if (exe_ctx.GetProcessPtr())
+ exe_ctx.GetProcessPtr()->SetRunningUserExpression(true);
+
+ return_value = exe_ctx.GetProcessRef().RunThreadPlan(
+ exe_ctx, call_plan_sp, real_options, diagnostic_manager);
+
+ if (log) {
+ if (return_value != lldb::eExpressionCompleted) {
+ log->Printf("== [FunctionCaller::ExecuteFunction] Execution of \"%s\" "
+ "completed abnormally ==",
+ m_name.c_str());
+ } else {
+ log->Printf("== [FunctionCaller::ExecuteFunction] Execution of \"%s\" "
+ "completed normally ==",
+ m_name.c_str());
}
+ }
- // Okay, now run the function:
+ if (exe_ctx.GetProcessPtr())
+ exe_ctx.GetProcessPtr()->SetRunningUserExpression(false);
- Address wrapper_address (m_jit_start_addr);
-
- lldb::addr_t args = { args_addr };
-
- lldb::ThreadPlanSP new_plan_sp (new ThreadPlanCallFunction (*thread,
- wrapper_address,
- CompilerType(),
- args,
- options));
- new_plan_sp->SetIsMasterPlan(true);
- new_plan_sp->SetOkayToDiscard (false);
- return new_plan_sp;
-}
+ if (args_addr_ptr != NULL)
+ *args_addr_ptr = args_addr;
-bool
-FunctionCaller::FetchFunctionResults (ExecutionContext &exe_ctx, lldb::addr_t args_addr, Value &ret_value)
-{
- // Read the return value - it is the last field in the struct:
- // FIXME: How does clang tell us there's no return value? We need to handle that case.
- // FIXME: Create our ThreadPlanCallFunction with the return CompilerType, and then use GetReturnValueObject
- // to fetch the value. That way we can fetch any values we need.
-
- Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_EXPRESSIONS | LIBLLDB_LOG_STEP));
-
- if (log)
- log->Printf("-- [FunctionCaller::FetchFunctionResults] Fetching function results for \"%s\"--", m_name.c_str());
-
- Process *process = exe_ctx.GetProcessPtr();
-
- if (process == NULL)
- return false;
+ if (return_value != lldb::eExpressionCompleted)
+ return return_value;
- lldb::ProcessSP jit_process_sp(m_jit_process_wp.lock());
-
- if (process != jit_process_sp.get())
- return false;
-
- Error error;
- ret_value.GetScalar() = process->ReadUnsignedIntegerFromMemory (args_addr + m_return_offset, m_return_size, 0, error);
+ FetchFunctionResults(exe_ctx, args_addr, results);
- if (error.Fail())
- return false;
+ if (args_addr_ptr == NULL)
+ DeallocateFunctionResults(exe_ctx, args_addr);
- ret_value.SetCompilerType(m_function_return_type);
- ret_value.SetValueType(Value::eValueTypeScalar);
- return true;
-}
-
-void
-FunctionCaller::DeallocateFunctionResults (ExecutionContext &exe_ctx, lldb::addr_t args_addr)
-{
- std::list<lldb::addr_t>::iterator pos;
- pos = std::find(m_wrapper_args_addrs.begin(), m_wrapper_args_addrs.end(), args_addr);
- if (pos != m_wrapper_args_addrs.end())
- m_wrapper_args_addrs.erase(pos);
-
- exe_ctx.GetProcessRef().DeallocateMemory(args_addr);
-}
-
-lldb::ExpressionResults
-FunctionCaller::ExecuteFunction(ExecutionContext &exe_ctx, lldb::addr_t *args_addr_ptr,
- const EvaluateExpressionOptions &options, DiagnosticManager &diagnostic_manager,
- Value &results)
-{
- lldb::ExpressionResults return_value = lldb::eExpressionSetupError;
-
- // FunctionCaller::ExecuteFunction execution is always just to get the result. Do make sure we ignore
- // breakpoints, unwind on error, and don't try to debug it.
- EvaluateExpressionOptions real_options = options;
- real_options.SetDebug(false);
- real_options.SetUnwindOnError(true);
- real_options.SetIgnoreBreakpoints(true);
-
- lldb::addr_t args_addr;
-
- if (args_addr_ptr != NULL)
- args_addr = *args_addr_ptr;
- else
- args_addr = LLDB_INVALID_ADDRESS;
-
- if (CompileFunction(exe_ctx.GetThreadSP(), diagnostic_manager) != 0)
- return lldb::eExpressionSetupError;
-
- if (args_addr == LLDB_INVALID_ADDRESS)
- {
- if (!InsertFunction(exe_ctx, args_addr, diagnostic_manager))
- return lldb::eExpressionSetupError;
- }
-
- Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_EXPRESSIONS | LIBLLDB_LOG_STEP));
-
- if (log)
- log->Printf("== [FunctionCaller::ExecuteFunction] Executing function \"%s\" ==", m_name.c_str());
-
- lldb::ThreadPlanSP call_plan_sp = GetThreadPlanToCallFunction(exe_ctx, args_addr, real_options, diagnostic_manager);
- if (!call_plan_sp)
- return lldb::eExpressionSetupError;
-
- // We need to make sure we record the fact that we are running an expression here
- // otherwise this fact will fail to be recorded when fetching an Objective-C object description
- if (exe_ctx.GetProcessPtr())
- exe_ctx.GetProcessPtr()->SetRunningUserExpression(true);
-
- return_value = exe_ctx.GetProcessRef().RunThreadPlan(exe_ctx, call_plan_sp, real_options, diagnostic_manager);
-
- if (log)
- {
- if (return_value != lldb::eExpressionCompleted)
- {
- log->Printf("== [FunctionCaller::ExecuteFunction] Execution of \"%s\" completed abnormally ==", m_name.c_str());
- }
- else
- {
- log->Printf("== [FunctionCaller::ExecuteFunction] Execution of \"%s\" completed normally ==", m_name.c_str());
- }
- }
-
- if (exe_ctx.GetProcessPtr())
- exe_ctx.GetProcessPtr()->SetRunningUserExpression(false);
-
- if (args_addr_ptr != NULL)
- *args_addr_ptr = args_addr;
-
- if (return_value != lldb::eExpressionCompleted)
- return return_value;
-
- FetchFunctionResults(exe_ctx, args_addr, results);
-
- if (args_addr_ptr == NULL)
- DeallocateFunctionResults(exe_ctx, args_addr);
-
- return lldb::eExpressionCompleted;
+ return lldb::eExpressionCompleted;
}
diff --git a/lldb/source/Expression/IRDynamicChecks.cpp b/lldb/source/Expression/IRDynamicChecks.cpp
index 62bcfe0..bcc365a 100644
--- a/lldb/source/Expression/IRDynamicChecks.cpp
+++ b/lldb/source/Expression/IRDynamicChecks.cpp
@@ -10,13 +10,13 @@
// C Includes
// C++ Includes
// Other libraries and framework includes
-#include "llvm/Support/raw_ostream.h"
#include "llvm/IR/Constants.h"
#include "llvm/IR/DataLayout.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/Instructions.h"
#include "llvm/IR/Module.h"
#include "llvm/IR/Value.h"
+#include "llvm/Support/raw_ostream.h"
// Project includes
#include "lldb/Expression/IRDynamicChecks.h"
@@ -39,76 +39,72 @@
#define VALID_OBJC_OBJECT_CHECK_NAME "$__lldb_objc_object_check"
static const char g_valid_pointer_check_text[] =
-"extern \"C\" void\n"
-"_$__lldb_valid_pointer_check (unsigned char *$__lldb_arg_ptr)\n"
-"{\n"
-" unsigned char $__lldb_local_val = *$__lldb_arg_ptr;\n"
-"}";
+ "extern \"C\" void\n"
+ "_$__lldb_valid_pointer_check (unsigned char *$__lldb_arg_ptr)\n"
+ "{\n"
+ " unsigned char $__lldb_local_val = *$__lldb_arg_ptr;\n"
+ "}";
DynamicCheckerFunctions::DynamicCheckerFunctions() = default;
DynamicCheckerFunctions::~DynamicCheckerFunctions() = default;
-bool
-DynamicCheckerFunctions::Install(DiagnosticManager &diagnostic_manager, ExecutionContext &exe_ctx)
-{
- Error error;
- m_valid_pointer_check.reset(exe_ctx.GetTargetRef().GetUtilityFunctionForLanguage(g_valid_pointer_check_text,
- lldb::eLanguageTypeC,
- VALID_POINTER_CHECK_NAME,
- error));
- if (error.Fail())
- return false;
-
- if (!m_valid_pointer_check->Install(diagnostic_manager, exe_ctx))
- return false;
-
- Process *process = exe_ctx.GetProcessPtr();
-
- if (process)
- {
- ObjCLanguageRuntime *objc_language_runtime = process->GetObjCLanguageRuntime();
-
- if (objc_language_runtime)
- {
- m_objc_object_check.reset(objc_language_runtime->CreateObjectChecker(VALID_OBJC_OBJECT_CHECK_NAME));
-
- if (!m_objc_object_check->Install(diagnostic_manager, exe_ctx))
- return false;
- }
- }
-
- return true;
-}
-
-bool
-DynamicCheckerFunctions::DoCheckersExplainStop (lldb::addr_t addr, Stream &message)
-{
- // FIXME: We have to get the checkers to know why they scotched the call in more detail,
- // so we can print a better message here.
- if (m_valid_pointer_check && m_valid_pointer_check->ContainsAddress(addr))
- {
- message.Printf ("Attempted to dereference an invalid pointer.");
- return true;
- }
- else if (m_objc_object_check && m_objc_object_check->ContainsAddress(addr))
- {
- message.Printf ("Attempted to dereference an invalid ObjC Object or send it an unrecognized selector");
- return true;
- }
+bool DynamicCheckerFunctions::Install(DiagnosticManager &diagnostic_manager,
+ ExecutionContext &exe_ctx) {
+ Error error;
+ m_valid_pointer_check.reset(
+ exe_ctx.GetTargetRef().GetUtilityFunctionForLanguage(
+ g_valid_pointer_check_text, lldb::eLanguageTypeC,
+ VALID_POINTER_CHECK_NAME, error));
+ if (error.Fail())
return false;
+
+ if (!m_valid_pointer_check->Install(diagnostic_manager, exe_ctx))
+ return false;
+
+ Process *process = exe_ctx.GetProcessPtr();
+
+ if (process) {
+ ObjCLanguageRuntime *objc_language_runtime =
+ process->GetObjCLanguageRuntime();
+
+ if (objc_language_runtime) {
+ m_objc_object_check.reset(objc_language_runtime->CreateObjectChecker(
+ VALID_OBJC_OBJECT_CHECK_NAME));
+
+ if (!m_objc_object_check->Install(diagnostic_manager, exe_ctx))
+ return false;
+ }
+ }
+
+ return true;
}
-static std::string
-PrintValue(llvm::Value *V, bool truncate = false)
-{
- std::string s;
- raw_string_ostream rso(s);
- V->print(rso);
- rso.flush();
- if (truncate)
- s.resize(s.length() - 1);
- return s;
+bool DynamicCheckerFunctions::DoCheckersExplainStop(lldb::addr_t addr,
+ Stream &message) {
+ // FIXME: We have to get the checkers to know why they scotched the call in
+ // more detail,
+ // so we can print a better message here.
+ if (m_valid_pointer_check && m_valid_pointer_check->ContainsAddress(addr)) {
+ message.Printf("Attempted to dereference an invalid pointer.");
+ return true;
+ } else if (m_objc_object_check &&
+ m_objc_object_check->ContainsAddress(addr)) {
+ message.Printf("Attempted to dereference an invalid ObjC Object or send it "
+ "an unrecognized selector");
+ return true;
+ }
+ return false;
+}
+
+static std::string PrintValue(llvm::Value *V, bool truncate = false) {
+ std::string s;
+ raw_string_ostream rso(s);
+ V->print(rso);
+ rso.flush();
+ if (truncate)
+ s.resize(s.length() - 1);
+ return s;
}
//----------------------------------------------------------------------
@@ -141,537 +137,476 @@
//----------------------------------------------------------------------
class Instrumenter {
public:
- //------------------------------------------------------------------
- /// Constructor
- ///
- /// @param[in] module
- /// The module being instrumented.
- //------------------------------------------------------------------
- Instrumenter (llvm::Module &module,
- DynamicCheckerFunctions &checker_functions) :
- m_module(module),
- m_checker_functions(checker_functions),
- m_i8ptr_ty(nullptr),
- m_intptr_ty(nullptr)
- {
- }
+ //------------------------------------------------------------------
+ /// Constructor
+ ///
+ /// @param[in] module
+ /// The module being instrumented.
+ //------------------------------------------------------------------
+ Instrumenter(llvm::Module &module, DynamicCheckerFunctions &checker_functions)
+ : m_module(module), m_checker_functions(checker_functions),
+ m_i8ptr_ty(nullptr), m_intptr_ty(nullptr) {}
- virtual ~Instrumenter() = default;
+ virtual ~Instrumenter() = default;
- //------------------------------------------------------------------
- /// Inspect a function to find instructions to instrument
- ///
- /// @param[in] function
- /// The function to inspect.
- ///
- /// @return
- /// True on success; false on error.
- //------------------------------------------------------------------
- bool Inspect (llvm::Function &function)
- {
- return InspectFunction(function);
- }
+ //------------------------------------------------------------------
+ /// Inspect a function to find instructions to instrument
+ ///
+ /// @param[in] function
+ /// The function to inspect.
+ ///
+ /// @return
+ /// True on success; false on error.
+ //------------------------------------------------------------------
+ bool Inspect(llvm::Function &function) { return InspectFunction(function); }
- //------------------------------------------------------------------
- /// Instrument all the instructions found by Inspect()
- ///
- /// @return
- /// True on success; false on error.
- //------------------------------------------------------------------
- bool Instrument ()
- {
- for (InstIterator ii = m_to_instrument.begin(), last_ii = m_to_instrument.end();
- ii != last_ii;
- ++ii)
- {
- if (!InstrumentInstruction(*ii))
- return false;
- }
-
- return true;
- }
-
-protected:
- //------------------------------------------------------------------
- /// Add instrumentation to a single instruction
- ///
- /// @param[in] inst
- /// The instruction to be instrumented.
- ///
- /// @return
- /// True on success; false otherwise.
- //------------------------------------------------------------------
- virtual bool InstrumentInstruction(llvm::Instruction *inst) = 0;
-
- //------------------------------------------------------------------
- /// Register a single instruction to be instrumented
- ///
- /// @param[in] inst
- /// The instruction to be instrumented.
- //------------------------------------------------------------------
- void RegisterInstruction(llvm::Instruction &i)
- {
- m_to_instrument.push_back(&i);
- }
-
- //------------------------------------------------------------------
- /// Determine whether a single instruction is interesting to
- /// instrument, and, if so, call RegisterInstruction
- ///
- /// @param[in] i
- /// The instruction to be inspected.
- ///
- /// @return
- /// False if there was an error scanning; true otherwise.
- //------------------------------------------------------------------
- virtual bool InspectInstruction(llvm::Instruction &i)
- {
- return true;
- }
-
- //------------------------------------------------------------------
- /// Scan a basic block to see if any instructions are interesting
- ///
- /// @param[in] bb
- /// The basic block to be inspected.
- ///
- /// @return
- /// False if there was an error scanning; true otherwise.
- //------------------------------------------------------------------
- virtual bool InspectBasicBlock(llvm::BasicBlock &bb)
- {
- for (llvm::BasicBlock::iterator ii = bb.begin(), last_ii = bb.end();
- ii != last_ii;
- ++ii)
- {
- if (!InspectInstruction(*ii))
- return false;
- }
-
- return true;
- }
-
- //------------------------------------------------------------------
- /// Scan a function to see if any instructions are interesting
- ///
- /// @param[in] f
- /// The function to be inspected.
- ///
- /// @return
- /// False if there was an error scanning; true otherwise.
- //------------------------------------------------------------------
- virtual bool InspectFunction(llvm::Function &f)
- {
- for (llvm::Function::iterator bbi = f.begin(), last_bbi = f.end();
- bbi != last_bbi;
- ++bbi)
- {
- if (!InspectBasicBlock(*bbi))
- return false;
- }
-
- return true;
- }
-
- //------------------------------------------------------------------
- /// Build a function pointer for a function with signature
- /// void (*)(uint8_t*) with a given address
- ///
- /// @param[in] start_address
- /// The address of the function.
- ///
- /// @return
- /// The function pointer, for use in a CallInst.
- //------------------------------------------------------------------
- llvm::Value *BuildPointerValidatorFunc(lldb::addr_t start_address)
- {
- llvm::Type *param_array[1];
-
- param_array[0] = const_cast<llvm::PointerType*>(GetI8PtrTy());
-
- ArrayRef<llvm::Type*> params(param_array, 1);
-
- FunctionType *fun_ty = FunctionType::get(llvm::Type::getVoidTy(m_module.getContext()), params, true);
- PointerType *fun_ptr_ty = PointerType::getUnqual(fun_ty);
- Constant *fun_addr_int = ConstantInt::get(GetIntptrTy(), start_address, false);
- return ConstantExpr::getIntToPtr(fun_addr_int, fun_ptr_ty);
- }
-
- //------------------------------------------------------------------
- /// Build a function pointer for a function with signature
- /// void (*)(uint8_t*, uint8_t*) with a given address
- ///
- /// @param[in] start_address
- /// The address of the function.
- ///
- /// @return
- /// The function pointer, for use in a CallInst.
- //------------------------------------------------------------------
- llvm::Value *BuildObjectCheckerFunc(lldb::addr_t start_address)
- {
- llvm::Type *param_array[2];
-
- param_array[0] = const_cast<llvm::PointerType*>(GetI8PtrTy());
- param_array[1] = const_cast<llvm::PointerType*>(GetI8PtrTy());
-
- ArrayRef<llvm::Type*> params(param_array, 2);
-
- FunctionType *fun_ty = FunctionType::get(llvm::Type::getVoidTy(m_module.getContext()), params, true);
- PointerType *fun_ptr_ty = PointerType::getUnqual(fun_ty);
- Constant *fun_addr_int = ConstantInt::get(GetIntptrTy(), start_address, false);
- return ConstantExpr::getIntToPtr(fun_addr_int, fun_ptr_ty);
- }
-
- PointerType *GetI8PtrTy()
- {
- if (!m_i8ptr_ty)
- m_i8ptr_ty = llvm::Type::getInt8PtrTy(m_module.getContext());
-
- return m_i8ptr_ty;
- }
-
- IntegerType *GetIntptrTy()
- {
- if (!m_intptr_ty)
- {
- llvm::DataLayout data_layout(&m_module);
-
- m_intptr_ty = llvm::Type::getIntNTy(m_module.getContext(), data_layout.getPointerSizeInBits());
- }
-
- return m_intptr_ty;
- }
-
- typedef std::vector <llvm::Instruction *> InstVector;
- typedef InstVector::iterator InstIterator;
-
- InstVector m_to_instrument; ///< List of instructions the inspector found
- llvm::Module &m_module; ///< The module which is being instrumented
- DynamicCheckerFunctions &m_checker_functions; ///< The dynamic checker functions for the process
-
-private:
- PointerType *m_i8ptr_ty;
- IntegerType *m_intptr_ty;
-};
-
-class ValidPointerChecker : public Instrumenter
-{
-public:
- ValidPointerChecker (llvm::Module &module,
- DynamicCheckerFunctions &checker_functions) :
- Instrumenter(module, checker_functions),
- m_valid_pointer_check_func(nullptr)
- {
- }
-
- ~ValidPointerChecker() override = default;
-
-protected:
- bool InstrumentInstruction(llvm::Instruction *inst) override
- {
- Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
-
- if (log)
- log->Printf("Instrumenting load/store instruction: %s\n",
- PrintValue(inst).c_str());
-
- if (!m_valid_pointer_check_func)
- m_valid_pointer_check_func = BuildPointerValidatorFunc(m_checker_functions.m_valid_pointer_check->StartAddress());
-
- llvm::Value *dereferenced_ptr = nullptr;
-
- if (llvm::LoadInst *li = dyn_cast<llvm::LoadInst> (inst))
- dereferenced_ptr = li->getPointerOperand();
- else if (llvm::StoreInst *si = dyn_cast<llvm::StoreInst> (inst))
- dereferenced_ptr = si->getPointerOperand();
- else
- return false;
-
- // Insert an instruction to cast the loaded value to int8_t*
-
- BitCastInst *bit_cast = new BitCastInst(dereferenced_ptr,
- GetI8PtrTy(),
- "",
- inst);
-
- // Insert an instruction to call the helper with the result
-
- llvm::Value *arg_array[1];
-
- arg_array[0] = bit_cast;
-
- llvm::ArrayRef<llvm::Value *> args(arg_array, 1);
-
- CallInst::Create(m_valid_pointer_check_func,
- args,
- "",
- inst);
-
- return true;
- }
-
- bool InspectInstruction(llvm::Instruction &i) override
- {
- if (dyn_cast<llvm::LoadInst> (&i) ||
- dyn_cast<llvm::StoreInst> (&i))
- RegisterInstruction(i);
-
- return true;
- }
-
-private:
- llvm::Value *m_valid_pointer_check_func;
-};
-
-class ObjcObjectChecker : public Instrumenter
-{
-public:
- ObjcObjectChecker(llvm::Module &module,
- DynamicCheckerFunctions &checker_functions) :
- Instrumenter(module, checker_functions),
- m_objc_object_check_func(nullptr)
- {
- }
-
- ~ObjcObjectChecker() override = default;
-
- enum msgSend_type
- {
- eMsgSend = 0,
- eMsgSendSuper,
- eMsgSendSuper_stret,
- eMsgSend_fpret,
- eMsgSend_stret
- };
-
- std::map <llvm::Instruction *, msgSend_type> msgSend_types;
-
-protected:
- bool InstrumentInstruction(llvm::Instruction *inst) override
- {
- CallInst *call_inst = dyn_cast<CallInst>(inst);
-
- if (!call_inst)
- return false; // call_inst really shouldn't be nullptr, because otherwise InspectInstruction wouldn't have registered it
-
- if (!m_objc_object_check_func)
- m_objc_object_check_func = BuildObjectCheckerFunc(m_checker_functions.m_objc_object_check->StartAddress());
-
- // id objc_msgSend(id theReceiver, SEL theSelector, ...)
-
- llvm::Value *target_object;
- llvm::Value *selector;
-
- switch (msgSend_types[inst])
- {
- case eMsgSend:
- case eMsgSend_fpret:
- target_object = call_inst->getArgOperand(0);
- selector = call_inst->getArgOperand(1);
- break;
- case eMsgSend_stret:
- target_object = call_inst->getArgOperand(1);
- selector = call_inst->getArgOperand(2);
- break;
- case eMsgSendSuper:
- case eMsgSendSuper_stret:
- return true;
- }
-
- // These objects should always be valid according to Sean Calannan
- assert (target_object);
- assert (selector);
-
- // Insert an instruction to cast the receiver id to int8_t*
-
- BitCastInst *bit_cast = new BitCastInst(target_object,
- GetI8PtrTy(),
- "",
- inst);
-
- // Insert an instruction to call the helper with the result
-
- llvm::Value *arg_array[2];
-
- arg_array[0] = bit_cast;
- arg_array[1] = selector;
-
- ArrayRef<llvm::Value*> args(arg_array, 2);
-
- CallInst::Create(m_objc_object_check_func,
- args,
- "",
- inst);
-
- return true;
- }
-
- static llvm::Function *GetFunction(llvm::Value *value)
- {
- if (llvm::Function *function = llvm::dyn_cast<llvm::Function>(value))
- {
- return function;
- }
-
- if (llvm::ConstantExpr *const_expr = llvm::dyn_cast<llvm::ConstantExpr>(value))
- {
- switch (const_expr->getOpcode())
- {
- default:
- return nullptr;
- case llvm::Instruction::BitCast:
- return GetFunction(const_expr->getOperand(0));
- }
- }
-
- return nullptr;
- }
-
- static llvm::Function *GetCalledFunction(llvm::CallInst *inst)
- {
- return GetFunction(inst->getCalledValue());
- }
-
- bool InspectInstruction(llvm::Instruction &i) override
- {
- Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
-
- CallInst *call_inst = dyn_cast<CallInst>(&i);
-
- if (call_inst)
- {
- const llvm::Function *called_function = GetCalledFunction(call_inst);
-
- if (!called_function)
- return true;
-
- std::string name_str = called_function->getName().str();
- const char* name_cstr = name_str.c_str();
-
- if (log)
- log->Printf("Found call to %s: %s\n", name_cstr, PrintValue(call_inst).c_str());
-
- if (name_str.find("objc_msgSend") == std::string::npos)
- return true;
-
- if (!strcmp(name_cstr, "objc_msgSend"))
- {
- RegisterInstruction(i);
- msgSend_types[&i] = eMsgSend;
- return true;
- }
-
- if (!strcmp(name_cstr, "objc_msgSend_stret"))
- {
- RegisterInstruction(i);
- msgSend_types[&i] = eMsgSend_stret;
- return true;
- }
-
- if (!strcmp(name_cstr, "objc_msgSend_fpret"))
- {
- RegisterInstruction(i);
- msgSend_types[&i] = eMsgSend_fpret;
- return true;
- }
-
- if (!strcmp(name_cstr, "objc_msgSendSuper"))
- {
- RegisterInstruction(i);
- msgSend_types[&i] = eMsgSendSuper;
- return true;
- }
-
- if (!strcmp(name_cstr, "objc_msgSendSuper_stret"))
- {
- RegisterInstruction(i);
- msgSend_types[&i] = eMsgSendSuper_stret;
- return true;
- }
-
- if (log)
- log->Printf("Function name '%s' contains 'objc_msgSend' but is not handled", name_str.c_str());
-
- return true;
- }
-
- return true;
- }
-
-private:
- llvm::Value *m_objc_object_check_func;
-};
-
-IRDynamicChecks::IRDynamicChecks(DynamicCheckerFunctions &checker_functions,
- const char *func_name) :
- ModulePass(ID),
- m_func_name(func_name),
- m_checker_functions(checker_functions)
-{
-}
-
-IRDynamicChecks::~IRDynamicChecks() = default;
-
-bool
-IRDynamicChecks::runOnModule(llvm::Module &M)
-{
- Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
-
- llvm::Function* function = M.getFunction(StringRef(m_func_name.c_str()));
-
- if (!function)
- {
- if (log)
- log->Printf("Couldn't find %s() in the module", m_func_name.c_str());
-
+ //------------------------------------------------------------------
+ /// Instrument all the instructions found by Inspect()
+ ///
+ /// @return
+ /// True on success; false on error.
+ //------------------------------------------------------------------
+ bool Instrument() {
+ for (InstIterator ii = m_to_instrument.begin(),
+ last_ii = m_to_instrument.end();
+ ii != last_ii; ++ii) {
+ if (!InstrumentInstruction(*ii))
return false;
}
- if (m_checker_functions.m_valid_pointer_check)
- {
- ValidPointerChecker vpc(M, m_checker_functions);
+ return true;
+ }
- if (!vpc.Inspect(*function))
- return false;
+protected:
+ //------------------------------------------------------------------
+ /// Add instrumentation to a single instruction
+ ///
+ /// @param[in] inst
+ /// The instruction to be instrumented.
+ ///
+ /// @return
+ /// True on success; false otherwise.
+ //------------------------------------------------------------------
+ virtual bool InstrumentInstruction(llvm::Instruction *inst) = 0;
- if (!vpc.Instrument())
- return false;
- }
+ //------------------------------------------------------------------
+ /// Register a single instruction to be instrumented
+ ///
+ /// @param[in] inst
+ /// The instruction to be instrumented.
+ //------------------------------------------------------------------
+ void RegisterInstruction(llvm::Instruction &i) {
+ m_to_instrument.push_back(&i);
+ }
- if (m_checker_functions.m_objc_object_check)
- {
- ObjcObjectChecker ooc(M, m_checker_functions);
+ //------------------------------------------------------------------
+ /// Determine whether a single instruction is interesting to
+ /// instrument, and, if so, call RegisterInstruction
+ ///
+ /// @param[in] i
+ /// The instruction to be inspected.
+ ///
+ /// @return
+ /// False if there was an error scanning; true otherwise.
+ //------------------------------------------------------------------
+ virtual bool InspectInstruction(llvm::Instruction &i) { return true; }
- if (!ooc.Inspect(*function))
- return false;
-
- if (!ooc.Instrument())
- return false;
- }
-
- if (log && log->GetVerbose())
- {
- std::string s;
- raw_string_ostream oss(s);
-
- M.print(oss, nullptr);
-
- oss.flush();
-
- log->Printf ("Module after dynamic checks: \n%s", s.c_str());
+ //------------------------------------------------------------------
+ /// Scan a basic block to see if any instructions are interesting
+ ///
+ /// @param[in] bb
+ /// The basic block to be inspected.
+ ///
+ /// @return
+ /// False if there was an error scanning; true otherwise.
+ //------------------------------------------------------------------
+ virtual bool InspectBasicBlock(llvm::BasicBlock &bb) {
+ for (llvm::BasicBlock::iterator ii = bb.begin(), last_ii = bb.end();
+ ii != last_ii; ++ii) {
+ if (!InspectInstruction(*ii))
+ return false;
}
return true;
+ }
+
+ //------------------------------------------------------------------
+ /// Scan a function to see if any instructions are interesting
+ ///
+ /// @param[in] f
+ /// The function to be inspected.
+ ///
+ /// @return
+ /// False if there was an error scanning; true otherwise.
+ //------------------------------------------------------------------
+ virtual bool InspectFunction(llvm::Function &f) {
+ for (llvm::Function::iterator bbi = f.begin(), last_bbi = f.end();
+ bbi != last_bbi; ++bbi) {
+ if (!InspectBasicBlock(*bbi))
+ return false;
+ }
+
+ return true;
+ }
+
+ //------------------------------------------------------------------
+ /// Build a function pointer for a function with signature
+ /// void (*)(uint8_t*) with a given address
+ ///
+ /// @param[in] start_address
+ /// The address of the function.
+ ///
+ /// @return
+ /// The function pointer, for use in a CallInst.
+ //------------------------------------------------------------------
+ llvm::Value *BuildPointerValidatorFunc(lldb::addr_t start_address) {
+ llvm::Type *param_array[1];
+
+ param_array[0] = const_cast<llvm::PointerType *>(GetI8PtrTy());
+
+ ArrayRef<llvm::Type *> params(param_array, 1);
+
+ FunctionType *fun_ty = FunctionType::get(
+ llvm::Type::getVoidTy(m_module.getContext()), params, true);
+ PointerType *fun_ptr_ty = PointerType::getUnqual(fun_ty);
+ Constant *fun_addr_int =
+ ConstantInt::get(GetIntptrTy(), start_address, false);
+ return ConstantExpr::getIntToPtr(fun_addr_int, fun_ptr_ty);
+ }
+
+ //------------------------------------------------------------------
+ /// Build a function pointer for a function with signature
+ /// void (*)(uint8_t*, uint8_t*) with a given address
+ ///
+ /// @param[in] start_address
+ /// The address of the function.
+ ///
+ /// @return
+ /// The function pointer, for use in a CallInst.
+ //------------------------------------------------------------------
+ llvm::Value *BuildObjectCheckerFunc(lldb::addr_t start_address) {
+ llvm::Type *param_array[2];
+
+ param_array[0] = const_cast<llvm::PointerType *>(GetI8PtrTy());
+ param_array[1] = const_cast<llvm::PointerType *>(GetI8PtrTy());
+
+ ArrayRef<llvm::Type *> params(param_array, 2);
+
+ FunctionType *fun_ty = FunctionType::get(
+ llvm::Type::getVoidTy(m_module.getContext()), params, true);
+ PointerType *fun_ptr_ty = PointerType::getUnqual(fun_ty);
+ Constant *fun_addr_int =
+ ConstantInt::get(GetIntptrTy(), start_address, false);
+ return ConstantExpr::getIntToPtr(fun_addr_int, fun_ptr_ty);
+ }
+
+ PointerType *GetI8PtrTy() {
+ if (!m_i8ptr_ty)
+ m_i8ptr_ty = llvm::Type::getInt8PtrTy(m_module.getContext());
+
+ return m_i8ptr_ty;
+ }
+
+ IntegerType *GetIntptrTy() {
+ if (!m_intptr_ty) {
+ llvm::DataLayout data_layout(&m_module);
+
+ m_intptr_ty = llvm::Type::getIntNTy(m_module.getContext(),
+ data_layout.getPointerSizeInBits());
+ }
+
+ return m_intptr_ty;
+ }
+
+ typedef std::vector<llvm::Instruction *> InstVector;
+ typedef InstVector::iterator InstIterator;
+
+ InstVector m_to_instrument; ///< List of instructions the inspector found
+ llvm::Module &m_module; ///< The module which is being instrumented
+ DynamicCheckerFunctions
+ &m_checker_functions; ///< The dynamic checker functions for the process
+
+private:
+ PointerType *m_i8ptr_ty;
+ IntegerType *m_intptr_ty;
+};
+
+class ValidPointerChecker : public Instrumenter {
+public:
+ ValidPointerChecker(llvm::Module &module,
+ DynamicCheckerFunctions &checker_functions)
+ : Instrumenter(module, checker_functions),
+ m_valid_pointer_check_func(nullptr) {}
+
+ ~ValidPointerChecker() override = default;
+
+protected:
+ bool InstrumentInstruction(llvm::Instruction *inst) override {
+ Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS));
+
+ if (log)
+ log->Printf("Instrumenting load/store instruction: %s\n",
+ PrintValue(inst).c_str());
+
+ if (!m_valid_pointer_check_func)
+ m_valid_pointer_check_func = BuildPointerValidatorFunc(
+ m_checker_functions.m_valid_pointer_check->StartAddress());
+
+ llvm::Value *dereferenced_ptr = nullptr;
+
+ if (llvm::LoadInst *li = dyn_cast<llvm::LoadInst>(inst))
+ dereferenced_ptr = li->getPointerOperand();
+ else if (llvm::StoreInst *si = dyn_cast<llvm::StoreInst>(inst))
+ dereferenced_ptr = si->getPointerOperand();
+ else
+ return false;
+
+ // Insert an instruction to cast the loaded value to int8_t*
+
+ BitCastInst *bit_cast =
+ new BitCastInst(dereferenced_ptr, GetI8PtrTy(), "", inst);
+
+ // Insert an instruction to call the helper with the result
+
+ llvm::Value *arg_array[1];
+
+ arg_array[0] = bit_cast;
+
+ llvm::ArrayRef<llvm::Value *> args(arg_array, 1);
+
+ CallInst::Create(m_valid_pointer_check_func, args, "", inst);
+
+ return true;
+ }
+
+ bool InspectInstruction(llvm::Instruction &i) override {
+ if (dyn_cast<llvm::LoadInst>(&i) || dyn_cast<llvm::StoreInst>(&i))
+ RegisterInstruction(i);
+
+ return true;
+ }
+
+private:
+ llvm::Value *m_valid_pointer_check_func;
+};
+
+class ObjcObjectChecker : public Instrumenter {
+public:
+ ObjcObjectChecker(llvm::Module &module,
+ DynamicCheckerFunctions &checker_functions)
+ : Instrumenter(module, checker_functions),
+ m_objc_object_check_func(nullptr) {}
+
+ ~ObjcObjectChecker() override = default;
+
+ enum msgSend_type {
+ eMsgSend = 0,
+ eMsgSendSuper,
+ eMsgSendSuper_stret,
+ eMsgSend_fpret,
+ eMsgSend_stret
+ };
+
+ std::map<llvm::Instruction *, msgSend_type> msgSend_types;
+
+protected:
+ bool InstrumentInstruction(llvm::Instruction *inst) override {
+ CallInst *call_inst = dyn_cast<CallInst>(inst);
+
+ if (!call_inst)
+ return false; // call_inst really shouldn't be nullptr, because otherwise
+ // InspectInstruction wouldn't have registered it
+
+ if (!m_objc_object_check_func)
+ m_objc_object_check_func = BuildObjectCheckerFunc(
+ m_checker_functions.m_objc_object_check->StartAddress());
+
+ // id objc_msgSend(id theReceiver, SEL theSelector, ...)
+
+ llvm::Value *target_object;
+ llvm::Value *selector;
+
+ switch (msgSend_types[inst]) {
+ case eMsgSend:
+ case eMsgSend_fpret:
+ target_object = call_inst->getArgOperand(0);
+ selector = call_inst->getArgOperand(1);
+ break;
+ case eMsgSend_stret:
+ target_object = call_inst->getArgOperand(1);
+ selector = call_inst->getArgOperand(2);
+ break;
+ case eMsgSendSuper:
+ case eMsgSendSuper_stret:
+ return true;
+ }
+
+ // These objects should always be valid according to Sean Calannan
+ assert(target_object);
+ assert(selector);
+
+ // Insert an instruction to cast the receiver id to int8_t*
+
+ BitCastInst *bit_cast =
+ new BitCastInst(target_object, GetI8PtrTy(), "", inst);
+
+ // Insert an instruction to call the helper with the result
+
+ llvm::Value *arg_array[2];
+
+ arg_array[0] = bit_cast;
+ arg_array[1] = selector;
+
+ ArrayRef<llvm::Value *> args(arg_array, 2);
+
+ CallInst::Create(m_objc_object_check_func, args, "", inst);
+
+ return true;
+ }
+
+ static llvm::Function *GetFunction(llvm::Value *value) {
+ if (llvm::Function *function = llvm::dyn_cast<llvm::Function>(value)) {
+ return function;
+ }
+
+ if (llvm::ConstantExpr *const_expr =
+ llvm::dyn_cast<llvm::ConstantExpr>(value)) {
+ switch (const_expr->getOpcode()) {
+ default:
+ return nullptr;
+ case llvm::Instruction::BitCast:
+ return GetFunction(const_expr->getOperand(0));
+ }
+ }
+
+ return nullptr;
+ }
+
+ static llvm::Function *GetCalledFunction(llvm::CallInst *inst) {
+ return GetFunction(inst->getCalledValue());
+ }
+
+ bool InspectInstruction(llvm::Instruction &i) override {
+ Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS));
+
+ CallInst *call_inst = dyn_cast<CallInst>(&i);
+
+ if (call_inst) {
+ const llvm::Function *called_function = GetCalledFunction(call_inst);
+
+ if (!called_function)
+ return true;
+
+ std::string name_str = called_function->getName().str();
+ const char *name_cstr = name_str.c_str();
+
+ if (log)
+ log->Printf("Found call to %s: %s\n", name_cstr,
+ PrintValue(call_inst).c_str());
+
+ if (name_str.find("objc_msgSend") == std::string::npos)
+ return true;
+
+ if (!strcmp(name_cstr, "objc_msgSend")) {
+ RegisterInstruction(i);
+ msgSend_types[&i] = eMsgSend;
+ return true;
+ }
+
+ if (!strcmp(name_cstr, "objc_msgSend_stret")) {
+ RegisterInstruction(i);
+ msgSend_types[&i] = eMsgSend_stret;
+ return true;
+ }
+
+ if (!strcmp(name_cstr, "objc_msgSend_fpret")) {
+ RegisterInstruction(i);
+ msgSend_types[&i] = eMsgSend_fpret;
+ return true;
+ }
+
+ if (!strcmp(name_cstr, "objc_msgSendSuper")) {
+ RegisterInstruction(i);
+ msgSend_types[&i] = eMsgSendSuper;
+ return true;
+ }
+
+ if (!strcmp(name_cstr, "objc_msgSendSuper_stret")) {
+ RegisterInstruction(i);
+ msgSend_types[&i] = eMsgSendSuper_stret;
+ return true;
+ }
+
+ if (log)
+ log->Printf(
+ "Function name '%s' contains 'objc_msgSend' but is not handled",
+ name_str.c_str());
+
+ return true;
+ }
+
+ return true;
+ }
+
+private:
+ llvm::Value *m_objc_object_check_func;
+};
+
+IRDynamicChecks::IRDynamicChecks(DynamicCheckerFunctions &checker_functions,
+ const char *func_name)
+ : ModulePass(ID), m_func_name(func_name),
+ m_checker_functions(checker_functions) {}
+
+IRDynamicChecks::~IRDynamicChecks() = default;
+
+bool IRDynamicChecks::runOnModule(llvm::Module &M) {
+ Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS));
+
+ llvm::Function *function = M.getFunction(StringRef(m_func_name.c_str()));
+
+ if (!function) {
+ if (log)
+ log->Printf("Couldn't find %s() in the module", m_func_name.c_str());
+
+ return false;
+ }
+
+ if (m_checker_functions.m_valid_pointer_check) {
+ ValidPointerChecker vpc(M, m_checker_functions);
+
+ if (!vpc.Inspect(*function))
+ return false;
+
+ if (!vpc.Instrument())
+ return false;
+ }
+
+ if (m_checker_functions.m_objc_object_check) {
+ ObjcObjectChecker ooc(M, m_checker_functions);
+
+ if (!ooc.Inspect(*function))
+ return false;
+
+ if (!ooc.Instrument())
+ return false;
+ }
+
+ if (log && log->GetVerbose()) {
+ std::string s;
+ raw_string_ostream oss(s);
+
+ M.print(oss, nullptr);
+
+ oss.flush();
+
+ log->Printf("Module after dynamic checks: \n%s", s.c_str());
+ }
+
+ return true;
}
-void
-IRDynamicChecks::assignPassManager(PMStack &PMS,
- PassManagerType T)
-{
-}
+void IRDynamicChecks::assignPassManager(PMStack &PMS, PassManagerType T) {}
-PassManagerType
-IRDynamicChecks::getPotentialPassManagerType() const
-{
- return PMT_ModulePassManager;
+PassManagerType IRDynamicChecks::getPotentialPassManagerType() const {
+ return PMT_ModulePassManager;
}
diff --git a/lldb/source/Expression/IRExecutionUnit.cpp b/lldb/source/Expression/IRExecutionUnit.cpp
index dc4b792..3500530 100644
--- a/lldb/source/Expression/IRExecutionUnit.cpp
+++ b/lldb/source/Expression/IRExecutionUnit.cpp
@@ -21,576 +21,549 @@
#include "lldb/Core/Log.h"
#include "lldb/Core/Module.h"
#include "lldb/Core/Section.h"
+#include "lldb/Expression/IRExecutionUnit.h"
#include "lldb/Symbol/CompileUnit.h"
#include "lldb/Symbol/SymbolContext.h"
-#include "lldb/Symbol/SymbolVendor.h"
#include "lldb/Symbol/SymbolFile.h"
-#include "lldb/Expression/IRExecutionUnit.h"
+#include "lldb/Symbol/SymbolVendor.h"
#include "lldb/Target/ExecutionContext.h"
-#include "lldb/Target/Target.h"
#include "lldb/Target/ObjCLanguageRuntime.h"
+#include "lldb/Target/Target.h"
#include "lldb/Utility/LLDBAssert.h"
#include "lldb/../../source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.h"
using namespace lldb_private;
-IRExecutionUnit::IRExecutionUnit (std::unique_ptr<llvm::LLVMContext> &context_ap,
- std::unique_ptr<llvm::Module> &module_ap,
- ConstString &name,
- const lldb::TargetSP &target_sp,
- const SymbolContext &sym_ctx,
- std::vector<std::string> &cpu_features) :
- IRMemoryMap(target_sp),
- m_context_ap(context_ap.release()),
- m_module_ap(module_ap.release()),
- m_module(m_module_ap.get()),
- m_cpu_features(cpu_features),
- m_name(name),
- m_sym_ctx(sym_ctx),
- m_did_jit(false),
- m_function_load_addr(LLDB_INVALID_ADDRESS),
- m_function_end_load_addr(LLDB_INVALID_ADDRESS),
- m_reported_allocations(false)
-{
-}
+IRExecutionUnit::IRExecutionUnit(std::unique_ptr<llvm::LLVMContext> &context_ap,
+ std::unique_ptr<llvm::Module> &module_ap,
+ ConstString &name,
+ const lldb::TargetSP &target_sp,
+ const SymbolContext &sym_ctx,
+ std::vector<std::string> &cpu_features)
+ : IRMemoryMap(target_sp), m_context_ap(context_ap.release()),
+ m_module_ap(module_ap.release()), m_module(m_module_ap.get()),
+ m_cpu_features(cpu_features), m_name(name), m_sym_ctx(sym_ctx),
+ m_did_jit(false), m_function_load_addr(LLDB_INVALID_ADDRESS),
+ m_function_end_load_addr(LLDB_INVALID_ADDRESS),
+ m_reported_allocations(false) {}
-lldb::addr_t
-IRExecutionUnit::WriteNow (const uint8_t *bytes,
- size_t size,
- Error &error)
-{
- const bool zero_memory = false;
- lldb::addr_t allocation_process_addr = Malloc (size,
- 8,
- lldb::ePermissionsWritable | lldb::ePermissionsReadable,
- eAllocationPolicyMirror,
- zero_memory,
- error);
+lldb::addr_t IRExecutionUnit::WriteNow(const uint8_t *bytes, size_t size,
+ Error &error) {
+ const bool zero_memory = false;
+ lldb::addr_t allocation_process_addr =
+ Malloc(size, 8, lldb::ePermissionsWritable | lldb::ePermissionsReadable,
+ eAllocationPolicyMirror, zero_memory, error);
- if (!error.Success())
- return LLDB_INVALID_ADDRESS;
+ if (!error.Success())
+ return LLDB_INVALID_ADDRESS;
- WriteMemory(allocation_process_addr, bytes, size, error);
+ WriteMemory(allocation_process_addr, bytes, size, error);
- if (!error.Success())
- {
- Error err;
- Free (allocation_process_addr, err);
-
- return LLDB_INVALID_ADDRESS;
- }
-
- if (Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS))
- {
- DataBufferHeap my_buffer(size, 0);
- Error err;
- ReadMemory(my_buffer.GetBytes(), allocation_process_addr, size, err);
-
- if (err.Success())
- {
- DataExtractor my_extractor(my_buffer.GetBytes(), my_buffer.GetByteSize(), lldb::eByteOrderBig, 8);
- my_extractor.PutToLog(log, 0, my_buffer.GetByteSize(), allocation_process_addr, 16, DataExtractor::TypeUInt8);
- }
- }
-
- return allocation_process_addr;
-}
-
-void
-IRExecutionUnit::FreeNow (lldb::addr_t allocation)
-{
- if (allocation == LLDB_INVALID_ADDRESS)
- return;
-
+ if (!error.Success()) {
Error err;
+ Free(allocation_process_addr, err);
- Free(allocation, err);
-}
+ return LLDB_INVALID_ADDRESS;
+ }
-Error
-IRExecutionUnit::DisassembleFunction (Stream &stream,
- lldb::ProcessSP &process_wp)
-{
- Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
-
- ExecutionContext exe_ctx(process_wp);
-
- Error ret;
-
- ret.Clear();
-
- lldb::addr_t func_local_addr = LLDB_INVALID_ADDRESS;
- lldb::addr_t func_remote_addr = LLDB_INVALID_ADDRESS;
-
- for (JittedFunction &function : m_jitted_functions)
- {
- if (function.m_name == m_name)
- {
- func_local_addr = function.m_local_addr;
- func_remote_addr = function.m_remote_addr;
- }
- }
-
- if (func_local_addr == LLDB_INVALID_ADDRESS)
- {
- ret.SetErrorToGenericError();
- ret.SetErrorStringWithFormat("Couldn't find function %s for disassembly", m_name.AsCString());
- return ret;
- }
-
- if (log)
- log->Printf("Found function, has local address 0x%" PRIx64 " and remote address 0x%" PRIx64, (uint64_t)func_local_addr, (uint64_t)func_remote_addr);
-
- std::pair <lldb::addr_t, lldb::addr_t> func_range;
-
- func_range = GetRemoteRangeForLocal(func_local_addr);
-
- if (func_range.first == 0 && func_range.second == 0)
- {
- ret.SetErrorToGenericError();
- ret.SetErrorStringWithFormat("Couldn't find code range for function %s", m_name.AsCString());
- return ret;
- }
-
- if (log)
- log->Printf("Function's code range is [0x%" PRIx64 "+0x%" PRIx64 "]", func_range.first, func_range.second);
-
- Target *target = exe_ctx.GetTargetPtr();
- if (!target)
- {
- ret.SetErrorToGenericError();
- ret.SetErrorString("Couldn't find the target");
- return ret;
- }
-
- lldb::DataBufferSP buffer_sp(new DataBufferHeap(func_range.second, 0));
-
- Process *process = exe_ctx.GetProcessPtr();
+ if (Log *log =
+ lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS)) {
+ DataBufferHeap my_buffer(size, 0);
Error err;
- process->ReadMemory(func_remote_addr, buffer_sp->GetBytes(), buffer_sp->GetByteSize(), err);
+ ReadMemory(my_buffer.GetBytes(), allocation_process_addr, size, err);
- if (!err.Success())
- {
- ret.SetErrorToGenericError();
- ret.SetErrorStringWithFormat("Couldn't read from process: %s", err.AsCString("unknown error"));
- return ret;
- }
-
- ArchSpec arch(target->GetArchitecture());
-
- const char *plugin_name = NULL;
- const char *flavor_string = NULL;
- lldb::DisassemblerSP disassembler_sp = Disassembler::FindPlugin(arch, flavor_string, plugin_name);
-
- if (!disassembler_sp)
- {
- ret.SetErrorToGenericError();
- ret.SetErrorStringWithFormat("Unable to find disassembler plug-in for %s architecture.", arch.GetArchitectureName());
- return ret;
- }
-
- if (!process)
- {
- ret.SetErrorToGenericError();
- ret.SetErrorString("Couldn't find the process");
- return ret;
- }
-
- DataExtractor extractor(buffer_sp,
- process->GetByteOrder(),
- target->GetArchitecture().GetAddressByteSize());
-
- if (log)
- {
- log->Printf("Function data has contents:");
- extractor.PutToLog (log,
- 0,
- extractor.GetByteSize(),
- func_remote_addr,
- 16,
+ if (err.Success()) {
+ DataExtractor my_extractor(my_buffer.GetBytes(), my_buffer.GetByteSize(),
+ lldb::eByteOrderBig, 8);
+ my_extractor.PutToLog(log, 0, my_buffer.GetByteSize(),
+ allocation_process_addr, 16,
DataExtractor::TypeUInt8);
}
+ }
- disassembler_sp->DecodeInstructions (Address (func_remote_addr), extractor, 0, UINT32_MAX, false, false);
+ return allocation_process_addr;
+}
- InstructionList &instruction_list = disassembler_sp->GetInstructionList();
- instruction_list.Dump(&stream, true, true, &exe_ctx);
+void IRExecutionUnit::FreeNow(lldb::addr_t allocation) {
+ if (allocation == LLDB_INVALID_ADDRESS)
+ return;
+
+ Error err;
+
+ Free(allocation, err);
+}
+
+Error IRExecutionUnit::DisassembleFunction(Stream &stream,
+ lldb::ProcessSP &process_wp) {
+ Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS));
+
+ ExecutionContext exe_ctx(process_wp);
+
+ Error ret;
+
+ ret.Clear();
+
+ lldb::addr_t func_local_addr = LLDB_INVALID_ADDRESS;
+ lldb::addr_t func_remote_addr = LLDB_INVALID_ADDRESS;
+
+ for (JittedFunction &function : m_jitted_functions) {
+ if (function.m_name == m_name) {
+ func_local_addr = function.m_local_addr;
+ func_remote_addr = function.m_remote_addr;
+ }
+ }
+
+ if (func_local_addr == LLDB_INVALID_ADDRESS) {
+ ret.SetErrorToGenericError();
+ ret.SetErrorStringWithFormat("Couldn't find function %s for disassembly",
+ m_name.AsCString());
return ret;
+ }
+
+ if (log)
+ log->Printf("Found function, has local address 0x%" PRIx64
+ " and remote address 0x%" PRIx64,
+ (uint64_t)func_local_addr, (uint64_t)func_remote_addr);
+
+ std::pair<lldb::addr_t, lldb::addr_t> func_range;
+
+ func_range = GetRemoteRangeForLocal(func_local_addr);
+
+ if (func_range.first == 0 && func_range.second == 0) {
+ ret.SetErrorToGenericError();
+ ret.SetErrorStringWithFormat("Couldn't find code range for function %s",
+ m_name.AsCString());
+ return ret;
+ }
+
+ if (log)
+ log->Printf("Function's code range is [0x%" PRIx64 "+0x%" PRIx64 "]",
+ func_range.first, func_range.second);
+
+ Target *target = exe_ctx.GetTargetPtr();
+ if (!target) {
+ ret.SetErrorToGenericError();
+ ret.SetErrorString("Couldn't find the target");
+ return ret;
+ }
+
+ lldb::DataBufferSP buffer_sp(new DataBufferHeap(func_range.second, 0));
+
+ Process *process = exe_ctx.GetProcessPtr();
+ Error err;
+ process->ReadMemory(func_remote_addr, buffer_sp->GetBytes(),
+ buffer_sp->GetByteSize(), err);
+
+ if (!err.Success()) {
+ ret.SetErrorToGenericError();
+ ret.SetErrorStringWithFormat("Couldn't read from process: %s",
+ err.AsCString("unknown error"));
+ return ret;
+ }
+
+ ArchSpec arch(target->GetArchitecture());
+
+ const char *plugin_name = NULL;
+ const char *flavor_string = NULL;
+ lldb::DisassemblerSP disassembler_sp =
+ Disassembler::FindPlugin(arch, flavor_string, plugin_name);
+
+ if (!disassembler_sp) {
+ ret.SetErrorToGenericError();
+ ret.SetErrorStringWithFormat(
+ "Unable to find disassembler plug-in for %s architecture.",
+ arch.GetArchitectureName());
+ return ret;
+ }
+
+ if (!process) {
+ ret.SetErrorToGenericError();
+ ret.SetErrorString("Couldn't find the process");
+ return ret;
+ }
+
+ DataExtractor extractor(buffer_sp, process->GetByteOrder(),
+ target->GetArchitecture().GetAddressByteSize());
+
+ if (log) {
+ log->Printf("Function data has contents:");
+ extractor.PutToLog(log, 0, extractor.GetByteSize(), func_remote_addr, 16,
+ DataExtractor::TypeUInt8);
+ }
+
+ disassembler_sp->DecodeInstructions(Address(func_remote_addr), extractor, 0,
+ UINT32_MAX, false, false);
+
+ InstructionList &instruction_list = disassembler_sp->GetInstructionList();
+ instruction_list.Dump(&stream, true, true, &exe_ctx);
+ return ret;
}
-static void ReportInlineAsmError(const llvm::SMDiagnostic &diagnostic, void *Context, unsigned LocCookie)
-{
- Error *err = static_cast<Error*>(Context);
+static void ReportInlineAsmError(const llvm::SMDiagnostic &diagnostic,
+ void *Context, unsigned LocCookie) {
+ Error *err = static_cast<Error *>(Context);
- if (err && err->Success())
- {
- err->SetErrorToGenericError();
- err->SetErrorStringWithFormat("Inline assembly error: %s", diagnostic.getMessage().str().c_str());
- }
+ if (err && err->Success()) {
+ err->SetErrorToGenericError();
+ err->SetErrorStringWithFormat("Inline assembly error: %s",
+ diagnostic.getMessage().str().c_str());
+ }
}
-void
-IRExecutionUnit::ReportSymbolLookupError(const ConstString &name)
-{
- m_failed_lookups.push_back(name);
+void IRExecutionUnit::ReportSymbolLookupError(const ConstString &name) {
+ m_failed_lookups.push_back(name);
}
-void
-IRExecutionUnit::GetRunnableInfo(Error &error,
- lldb::addr_t &func_addr,
- lldb::addr_t &func_end)
-{
- lldb::ProcessSP process_sp(GetProcessWP().lock());
+void IRExecutionUnit::GetRunnableInfo(Error &error, lldb::addr_t &func_addr,
+ lldb::addr_t &func_end) {
+ lldb::ProcessSP process_sp(GetProcessWP().lock());
- static std::recursive_mutex s_runnable_info_mutex;
+ static std::recursive_mutex s_runnable_info_mutex;
- func_addr = LLDB_INVALID_ADDRESS;
- func_end = LLDB_INVALID_ADDRESS;
+ func_addr = LLDB_INVALID_ADDRESS;
+ func_end = LLDB_INVALID_ADDRESS;
- if (!process_sp)
- {
- error.SetErrorToGenericError();
- error.SetErrorString("Couldn't write the JIT compiled code into the process because the process is invalid");
- return;
- }
+ if (!process_sp) {
+ error.SetErrorToGenericError();
+ error.SetErrorString("Couldn't write the JIT compiled code into the "
+ "process because the process is invalid");
+ return;
+ }
- if (m_did_jit)
- {
- func_addr = m_function_load_addr;
- func_end = m_function_end_load_addr;
-
- return;
- };
-
- std::lock_guard<std::recursive_mutex> guard(s_runnable_info_mutex);
-
- m_did_jit = true;
-
- Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
-
- std::string error_string;
-
- if (log)
- {
- std::string s;
- llvm::raw_string_ostream oss(s);
-
- m_module->print(oss, NULL);
-
- oss.flush();
-
- log->Printf ("Module being sent to JIT: \n%s", s.c_str());
- }
-
- llvm::Triple triple(m_module->getTargetTriple());
- llvm::Reloc::Model relocModel;
- llvm::CodeModel::Model codeModel;
-
- if (triple.isOSBinFormatELF())
- {
- relocModel = llvm::Reloc::Static;
- }
- else
- {
- relocModel = llvm::Reloc::PIC_;
- }
-
- // This will be small for 32-bit and large for 64-bit.
- codeModel = llvm::CodeModel::JITDefault;
-
- m_module_ap->getContext().setInlineAsmDiagnosticHandler(ReportInlineAsmError, &error);
-
- llvm::EngineBuilder builder(std::move(m_module_ap));
-
- builder.setEngineKind(llvm::EngineKind::JIT)
- .setErrorStr(&error_string)
- .setRelocationModel(relocModel)
- .setMCJITMemoryManager(std::unique_ptr<MemoryManager>(new MemoryManager(*this)))
- .setCodeModel(codeModel)
- .setOptLevel(llvm::CodeGenOpt::Less)
- .setUseOrcMCJITReplacement(true);
-
- llvm::StringRef mArch;
- llvm::StringRef mCPU;
- llvm::SmallVector<std::string, 0> mAttrs;
-
- for (std::string &feature : m_cpu_features)
- mAttrs.push_back(feature);
-
- llvm::TargetMachine *target_machine = builder.selectTarget(triple,
- mArch,
- mCPU,
- mAttrs);
-
- m_execution_engine_ap.reset(builder.create(target_machine));
-
- m_strip_underscore = (m_execution_engine_ap->getDataLayout().getGlobalPrefix() == '_');
-
- if (!m_execution_engine_ap.get())
- {
- error.SetErrorToGenericError();
- error.SetErrorStringWithFormat("Couldn't JIT the function: %s", error_string.c_str());
- return;
- }
-
- // Make sure we see all sections, including ones that don't have relocations...
- m_execution_engine_ap->setProcessAllSections(true);
-
- m_execution_engine_ap->DisableLazyCompilation();
-
- for (llvm::Function &function : *m_module)
- {
- if (function.isDeclaration() || function.hasPrivateLinkage())
- continue;
-
- const bool external = function.hasExternalLinkage() || function.hasLinkOnceODRLinkage();
-
- void *fun_ptr = m_execution_engine_ap->getPointerToFunction(&function);
-
- if (!error.Success())
- {
- // We got an error through our callback!
- return;
- }
-
- if (!fun_ptr)
- {
- error.SetErrorToGenericError();
- error.SetErrorStringWithFormat("'%s' was in the JITted module but wasn't lowered", function.getName().str().c_str());
- return;
- }
- m_jitted_functions.push_back (JittedFunction(function.getName().str().c_str(), external, (lldb::addr_t)fun_ptr));
- }
-
- CommitAllocations(process_sp);
- ReportAllocations(*m_execution_engine_ap);
-
- // We have to do this after calling ReportAllocations because for the MCJIT, getGlobalValueAddress
- // will cause the JIT to perform all relocations. That can only be done once, and has to happen
- // after we do the remapping from local -> remote.
- // That means we don't know the local address of the Variables, but we don't need that for anything,
- // so that's okay.
-
- std::function<void (llvm::GlobalValue &)> RegisterOneValue = [this] (llvm::GlobalValue &val) {
- if (val.hasExternalLinkage() && !val.isDeclaration())
- {
- uint64_t var_ptr_addr = m_execution_engine_ap->getGlobalValueAddress(val.getName().str());
-
- lldb::addr_t remote_addr = GetRemoteAddressForLocal(var_ptr_addr);
-
- // This is a really unfortunae API that sometimes returns local addresses and sometimes returns remote addresses, based on whether
- // the variable was relocated during ReportAllocations or not.
-
- if (remote_addr == LLDB_INVALID_ADDRESS)
- {
- remote_addr = var_ptr_addr;
- }
-
- if (var_ptr_addr != 0)
- m_jitted_global_variables.push_back (JittedGlobalVariable (val.getName().str().c_str(), LLDB_INVALID_ADDRESS, remote_addr));
- }
- };
-
- for (llvm::GlobalVariable &global_var : m_module->getGlobalList())
- {
- RegisterOneValue(global_var);
- }
-
- for (llvm::GlobalAlias &global_alias : m_module->getAliasList())
- {
- RegisterOneValue(global_alias);
- }
-
- WriteData(process_sp);
-
- if (m_failed_lookups.size())
- {
- StreamString ss;
-
- ss.PutCString("Couldn't lookup symbols:\n");
-
- bool emitNewLine = false;
-
- for (const ConstString &failed_lookup : m_failed_lookups)
- {
- if (emitNewLine)
- ss.PutCString("\n");
- emitNewLine = true;
- ss.PutCString(" ");
- ss.PutCString(Mangled(failed_lookup).GetDemangledName(lldb::eLanguageTypeObjC_plus_plus).AsCString());
- }
-
- m_failed_lookups.clear();
-
- error.SetErrorString(ss.GetData());
-
- return;
- }
-
- m_function_load_addr = LLDB_INVALID_ADDRESS;
- m_function_end_load_addr = LLDB_INVALID_ADDRESS;
-
- for (JittedFunction &jitted_function : m_jitted_functions)
- {
- jitted_function.m_remote_addr = GetRemoteAddressForLocal (jitted_function.m_local_addr);
-
- if (!m_name.IsEmpty() && jitted_function.m_name == m_name)
- {
- AddrRange func_range = GetRemoteRangeForLocal(jitted_function.m_local_addr);
- m_function_end_load_addr = func_range.first + func_range.second;
- m_function_load_addr = jitted_function.m_remote_addr;
- }
- }
-
- if (log)
- {
- log->Printf("Code can be run in the target.");
-
- StreamString disassembly_stream;
-
- Error err = DisassembleFunction(disassembly_stream, process_sp);
-
- if (!err.Success())
- {
- log->Printf("Couldn't disassemble function : %s", err.AsCString("unknown error"));
- }
- else
- {
- log->Printf("Function disassembly:\n%s", disassembly_stream.GetData());
- }
-
- log->Printf("Sections: ");
- for (AllocationRecord &record : m_records)
- {
- if (record.m_process_address != LLDB_INVALID_ADDRESS)
- {
- record.dump(log);
-
- DataBufferHeap my_buffer(record.m_size, 0);
- Error err;
- ReadMemory(my_buffer.GetBytes(), record.m_process_address, record.m_size, err);
-
- if (err.Success())
- {
- DataExtractor my_extractor(my_buffer.GetBytes(), my_buffer.GetByteSize(), lldb::eByteOrderBig, 8);
- my_extractor.PutToLog(log, 0, my_buffer.GetByteSize(), record.m_process_address, 16, DataExtractor::TypeUInt8);
- }
- }
- else
- {
- record.dump(log);
-
- DataExtractor my_extractor ((const void*)record.m_host_address, record.m_size, lldb::eByteOrderBig, 8);
- my_extractor.PutToLog(log, 0, record.m_size, record.m_host_address, 16, DataExtractor::TypeUInt8);
- }
- }
- }
-
+ if (m_did_jit) {
func_addr = m_function_load_addr;
func_end = m_function_end_load_addr;
return;
-}
+ };
-IRExecutionUnit::~IRExecutionUnit ()
-{
- m_module_ap.reset();
- m_execution_engine_ap.reset();
- m_context_ap.reset();
-}
+ std::lock_guard<std::recursive_mutex> guard(s_runnable_info_mutex);
-IRExecutionUnit::MemoryManager::MemoryManager (IRExecutionUnit &parent) :
- m_default_mm_ap (new llvm::SectionMemoryManager()),
- m_parent (parent)
-{
-}
+ m_did_jit = true;
-IRExecutionUnit::MemoryManager::~MemoryManager ()
-{
-}
+ Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS));
-lldb::SectionType
-IRExecutionUnit::GetSectionTypeFromSectionName (const llvm::StringRef &name, IRExecutionUnit::AllocationKind alloc_kind)
-{
- lldb::SectionType sect_type = lldb::eSectionTypeCode;
- switch (alloc_kind)
- {
- case AllocationKind::Stub: sect_type = lldb::eSectionTypeCode; break;
- case AllocationKind::Code: sect_type = lldb::eSectionTypeCode; break;
- case AllocationKind::Data: sect_type = lldb::eSectionTypeData; break;
- case AllocationKind::Global:sect_type = lldb::eSectionTypeData; break;
- case AllocationKind::Bytes: sect_type = lldb::eSectionTypeOther; break;
+ std::string error_string;
+
+ if (log) {
+ std::string s;
+ llvm::raw_string_ostream oss(s);
+
+ m_module->print(oss, NULL);
+
+ oss.flush();
+
+ log->Printf("Module being sent to JIT: \n%s", s.c_str());
+ }
+
+ llvm::Triple triple(m_module->getTargetTriple());
+ llvm::Reloc::Model relocModel;
+ llvm::CodeModel::Model codeModel;
+
+ if (triple.isOSBinFormatELF()) {
+ relocModel = llvm::Reloc::Static;
+ } else {
+ relocModel = llvm::Reloc::PIC_;
+ }
+
+ // This will be small for 32-bit and large for 64-bit.
+ codeModel = llvm::CodeModel::JITDefault;
+
+ m_module_ap->getContext().setInlineAsmDiagnosticHandler(ReportInlineAsmError,
+ &error);
+
+ llvm::EngineBuilder builder(std::move(m_module_ap));
+
+ builder.setEngineKind(llvm::EngineKind::JIT)
+ .setErrorStr(&error_string)
+ .setRelocationModel(relocModel)
+ .setMCJITMemoryManager(
+ std::unique_ptr<MemoryManager>(new MemoryManager(*this)))
+ .setCodeModel(codeModel)
+ .setOptLevel(llvm::CodeGenOpt::Less)
+ .setUseOrcMCJITReplacement(true);
+
+ llvm::StringRef mArch;
+ llvm::StringRef mCPU;
+ llvm::SmallVector<std::string, 0> mAttrs;
+
+ for (std::string &feature : m_cpu_features)
+ mAttrs.push_back(feature);
+
+ llvm::TargetMachine *target_machine =
+ builder.selectTarget(triple, mArch, mCPU, mAttrs);
+
+ m_execution_engine_ap.reset(builder.create(target_machine));
+
+ m_strip_underscore =
+ (m_execution_engine_ap->getDataLayout().getGlobalPrefix() == '_');
+
+ if (!m_execution_engine_ap.get()) {
+ error.SetErrorToGenericError();
+ error.SetErrorStringWithFormat("Couldn't JIT the function: %s",
+ error_string.c_str());
+ return;
+ }
+
+ // Make sure we see all sections, including ones that don't have
+ // relocations...
+ m_execution_engine_ap->setProcessAllSections(true);
+
+ m_execution_engine_ap->DisableLazyCompilation();
+
+ for (llvm::Function &function : *m_module) {
+ if (function.isDeclaration() || function.hasPrivateLinkage())
+ continue;
+
+ const bool external =
+ function.hasExternalLinkage() || function.hasLinkOnceODRLinkage();
+
+ void *fun_ptr = m_execution_engine_ap->getPointerToFunction(&function);
+
+ if (!error.Success()) {
+ // We got an error through our callback!
+ return;
}
- if (!name.empty())
- {
- if (name.equals("__text") || name.equals(".text"))
- sect_type = lldb::eSectionTypeCode;
- else if (name.equals("__data") || name.equals(".data"))
- sect_type = lldb::eSectionTypeCode;
- else if (name.startswith("__debug_") || name.startswith(".debug_"))
- {
- const uint32_t name_idx = name[0] == '_' ? 8 : 7;
- llvm::StringRef dwarf_name(name.substr(name_idx));
- switch (dwarf_name[0])
- {
- case 'a':
- if (dwarf_name.equals("abbrev"))
- sect_type = lldb::eSectionTypeDWARFDebugAbbrev;
- else if (dwarf_name.equals("aranges"))
- sect_type = lldb::eSectionTypeDWARFDebugAranges;
- else if (dwarf_name.equals("addr"))
- sect_type = lldb::eSectionTypeDWARFDebugAddr;
- break;
+ if (!fun_ptr) {
+ error.SetErrorToGenericError();
+ error.SetErrorStringWithFormat(
+ "'%s' was in the JITted module but wasn't lowered",
+ function.getName().str().c_str());
+ return;
+ }
+ m_jitted_functions.push_back(JittedFunction(
+ function.getName().str().c_str(), external, (lldb::addr_t)fun_ptr));
+ }
- case 'f':
- if (dwarf_name.equals("frame"))
- sect_type = lldb::eSectionTypeDWARFDebugFrame;
- break;
+ CommitAllocations(process_sp);
+ ReportAllocations(*m_execution_engine_ap);
- case 'i':
- if (dwarf_name.equals("info"))
- sect_type = lldb::eSectionTypeDWARFDebugInfo;
- break;
+ // We have to do this after calling ReportAllocations because for the MCJIT,
+ // getGlobalValueAddress
+ // will cause the JIT to perform all relocations. That can only be done once,
+ // and has to happen
+ // after we do the remapping from local -> remote.
+ // That means we don't know the local address of the Variables, but we don't
+ // need that for anything,
+ // so that's okay.
- case 'l':
- if (dwarf_name.equals("line"))
- sect_type = lldb::eSectionTypeDWARFDebugLine;
- else if (dwarf_name.equals("loc"))
- sect_type = lldb::eSectionTypeDWARFDebugLoc;
- break;
+ std::function<void(llvm::GlobalValue &)> RegisterOneValue = [this](
+ llvm::GlobalValue &val) {
+ if (val.hasExternalLinkage() && !val.isDeclaration()) {
+ uint64_t var_ptr_addr =
+ m_execution_engine_ap->getGlobalValueAddress(val.getName().str());
- case 'm':
- if (dwarf_name.equals("macinfo"))
- sect_type = lldb::eSectionTypeDWARFDebugMacInfo;
- break;
+ lldb::addr_t remote_addr = GetRemoteAddressForLocal(var_ptr_addr);
- case 'p':
- if (dwarf_name.equals("pubnames"))
- sect_type = lldb::eSectionTypeDWARFDebugPubNames;
- else if (dwarf_name.equals("pubtypes"))
- sect_type = lldb::eSectionTypeDWARFDebugPubTypes;
- break;
+ // This is a really unfortunae API that sometimes returns local addresses
+ // and sometimes returns remote addresses, based on whether
+ // the variable was relocated during ReportAllocations or not.
- case 's':
- if (dwarf_name.equals("str"))
- sect_type = lldb::eSectionTypeDWARFDebugStr;
- else if (dwarf_name.equals("str_offsets"))
- sect_type = lldb::eSectionTypeDWARFDebugStrOffsets;
- break;
+ if (remote_addr == LLDB_INVALID_ADDRESS) {
+ remote_addr = var_ptr_addr;
+ }
- case 'r':
- if (dwarf_name.equals("ranges"))
- sect_type = lldb::eSectionTypeDWARFDebugRanges;
- break;
+ if (var_ptr_addr != 0)
+ m_jitted_global_variables.push_back(JittedGlobalVariable(
+ val.getName().str().c_str(), LLDB_INVALID_ADDRESS, remote_addr));
+ }
+ };
- default:
- break;
- }
+ for (llvm::GlobalVariable &global_var : m_module->getGlobalList()) {
+ RegisterOneValue(global_var);
+ }
+
+ for (llvm::GlobalAlias &global_alias : m_module->getAliasList()) {
+ RegisterOneValue(global_alias);
+ }
+
+ WriteData(process_sp);
+
+ if (m_failed_lookups.size()) {
+ StreamString ss;
+
+ ss.PutCString("Couldn't lookup symbols:\n");
+
+ bool emitNewLine = false;
+
+ for (const ConstString &failed_lookup : m_failed_lookups) {
+ if (emitNewLine)
+ ss.PutCString("\n");
+ emitNewLine = true;
+ ss.PutCString(" ");
+ ss.PutCString(Mangled(failed_lookup)
+ .GetDemangledName(lldb::eLanguageTypeObjC_plus_plus)
+ .AsCString());
+ }
+
+ m_failed_lookups.clear();
+
+ error.SetErrorString(ss.GetData());
+
+ return;
+ }
+
+ m_function_load_addr = LLDB_INVALID_ADDRESS;
+ m_function_end_load_addr = LLDB_INVALID_ADDRESS;
+
+ for (JittedFunction &jitted_function : m_jitted_functions) {
+ jitted_function.m_remote_addr =
+ GetRemoteAddressForLocal(jitted_function.m_local_addr);
+
+ if (!m_name.IsEmpty() && jitted_function.m_name == m_name) {
+ AddrRange func_range =
+ GetRemoteRangeForLocal(jitted_function.m_local_addr);
+ m_function_end_load_addr = func_range.first + func_range.second;
+ m_function_load_addr = jitted_function.m_remote_addr;
+ }
+ }
+
+ if (log) {
+ log->Printf("Code can be run in the target.");
+
+ StreamString disassembly_stream;
+
+ Error err = DisassembleFunction(disassembly_stream, process_sp);
+
+ if (!err.Success()) {
+ log->Printf("Couldn't disassemble function : %s",
+ err.AsCString("unknown error"));
+ } else {
+ log->Printf("Function disassembly:\n%s", disassembly_stream.GetData());
+ }
+
+ log->Printf("Sections: ");
+ for (AllocationRecord &record : m_records) {
+ if (record.m_process_address != LLDB_INVALID_ADDRESS) {
+ record.dump(log);
+
+ DataBufferHeap my_buffer(record.m_size, 0);
+ Error err;
+ ReadMemory(my_buffer.GetBytes(), record.m_process_address,
+ record.m_size, err);
+
+ if (err.Success()) {
+ DataExtractor my_extractor(my_buffer.GetBytes(),
+ my_buffer.GetByteSize(),
+ lldb::eByteOrderBig, 8);
+ my_extractor.PutToLog(log, 0, my_buffer.GetByteSize(),
+ record.m_process_address, 16,
+ DataExtractor::TypeUInt8);
}
- else if (name.startswith("__apple_") || name.startswith(".apple_"))
- {
+ } else {
+ record.dump(log);
+
+ DataExtractor my_extractor((const void *)record.m_host_address,
+ record.m_size, lldb::eByteOrderBig, 8);
+ my_extractor.PutToLog(log, 0, record.m_size, record.m_host_address, 16,
+ DataExtractor::TypeUInt8);
+ }
+ }
+ }
+
+ func_addr = m_function_load_addr;
+ func_end = m_function_end_load_addr;
+
+ return;
+}
+
+IRExecutionUnit::~IRExecutionUnit() {
+ m_module_ap.reset();
+ m_execution_engine_ap.reset();
+ m_context_ap.reset();
+}
+
+IRExecutionUnit::MemoryManager::MemoryManager(IRExecutionUnit &parent)
+ : m_default_mm_ap(new llvm::SectionMemoryManager()), m_parent(parent) {}
+
+IRExecutionUnit::MemoryManager::~MemoryManager() {}
+
+lldb::SectionType IRExecutionUnit::GetSectionTypeFromSectionName(
+ const llvm::StringRef &name, IRExecutionUnit::AllocationKind alloc_kind) {
+ lldb::SectionType sect_type = lldb::eSectionTypeCode;
+ switch (alloc_kind) {
+ case AllocationKind::Stub:
+ sect_type = lldb::eSectionTypeCode;
+ break;
+ case AllocationKind::Code:
+ sect_type = lldb::eSectionTypeCode;
+ break;
+ case AllocationKind::Data:
+ sect_type = lldb::eSectionTypeData;
+ break;
+ case AllocationKind::Global:
+ sect_type = lldb::eSectionTypeData;
+ break;
+ case AllocationKind::Bytes:
+ sect_type = lldb::eSectionTypeOther;
+ break;
+ }
+
+ if (!name.empty()) {
+ if (name.equals("__text") || name.equals(".text"))
+ sect_type = lldb::eSectionTypeCode;
+ else if (name.equals("__data") || name.equals(".data"))
+ sect_type = lldb::eSectionTypeCode;
+ else if (name.startswith("__debug_") || name.startswith(".debug_")) {
+ const uint32_t name_idx = name[0] == '_' ? 8 : 7;
+ llvm::StringRef dwarf_name(name.substr(name_idx));
+ switch (dwarf_name[0]) {
+ case 'a':
+ if (dwarf_name.equals("abbrev"))
+ sect_type = lldb::eSectionTypeDWARFDebugAbbrev;
+ else if (dwarf_name.equals("aranges"))
+ sect_type = lldb::eSectionTypeDWARFDebugAranges;
+ else if (dwarf_name.equals("addr"))
+ sect_type = lldb::eSectionTypeDWARFDebugAddr;
+ break;
+
+ case 'f':
+ if (dwarf_name.equals("frame"))
+ sect_type = lldb::eSectionTypeDWARFDebugFrame;
+ break;
+
+ case 'i':
+ if (dwarf_name.equals("info"))
+ sect_type = lldb::eSectionTypeDWARFDebugInfo;
+ break;
+
+ case 'l':
+ if (dwarf_name.equals("line"))
+ sect_type = lldb::eSectionTypeDWARFDebugLine;
+ else if (dwarf_name.equals("loc"))
+ sect_type = lldb::eSectionTypeDWARFDebugLoc;
+ break;
+
+ case 'm':
+ if (dwarf_name.equals("macinfo"))
+ sect_type = lldb::eSectionTypeDWARFDebugMacInfo;
+ break;
+
+ case 'p':
+ if (dwarf_name.equals("pubnames"))
+ sect_type = lldb::eSectionTypeDWARFDebugPubNames;
+ else if (dwarf_name.equals("pubtypes"))
+ sect_type = lldb::eSectionTypeDWARFDebugPubTypes;
+ break;
+
+ case 's':
+ if (dwarf_name.equals("str"))
+ sect_type = lldb::eSectionTypeDWARFDebugStr;
+ else if (dwarf_name.equals("str_offsets"))
+ sect_type = lldb::eSectionTypeDWARFDebugStrOffsets;
+ break;
+
+ case 'r':
+ if (dwarf_name.equals("ranges"))
+ sect_type = lldb::eSectionTypeDWARFDebugRanges;
+ break;
+
+ default:
+ break;
+ }
+ } else if (name.startswith("__apple_") || name.startswith(".apple_")) {
#if 0
const uint32_t name_idx = name[0] == '_' ? 8 : 7;
llvm::StringRef apple_name(name.substr(name_idx));
@@ -614,776 +587,672 @@
break;
}
#else
- sect_type = lldb::eSectionTypeInvalid;
+ sect_type = lldb::eSectionTypeInvalid;
#endif
- }
- else if (name.equals("__objc_imageinfo"))
- sect_type = lldb::eSectionTypeOther;
- }
- return sect_type;
+ } else if (name.equals("__objc_imageinfo"))
+ sect_type = lldb::eSectionTypeOther;
+ }
+ return sect_type;
}
-uint8_t *
-IRExecutionUnit::MemoryManager::allocateCodeSection(uintptr_t Size,
- unsigned Alignment,
- unsigned SectionID,
- llvm::StringRef SectionName)
-{
- Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
+uint8_t *IRExecutionUnit::MemoryManager::allocateCodeSection(
+ uintptr_t Size, unsigned Alignment, unsigned SectionID,
+ llvm::StringRef SectionName) {
+ Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS));
- uint8_t *return_value = m_default_mm_ap->allocateCodeSection(Size, Alignment, SectionID, SectionName);
+ uint8_t *return_value = m_default_mm_ap->allocateCodeSection(
+ Size, Alignment, SectionID, SectionName);
- m_parent.m_records.push_back(AllocationRecord((uintptr_t)return_value,
- lldb::ePermissionsReadable | lldb::ePermissionsExecutable,
- GetSectionTypeFromSectionName (SectionName, AllocationKind::Code),
- Size,
- Alignment,
- SectionID,
- SectionName.str().c_str()));
+ m_parent.m_records.push_back(AllocationRecord(
+ (uintptr_t)return_value,
+ lldb::ePermissionsReadable | lldb::ePermissionsExecutable,
+ GetSectionTypeFromSectionName(SectionName, AllocationKind::Code), Size,
+ Alignment, SectionID, SectionName.str().c_str()));
- if (log)
- {
- log->Printf("IRExecutionUnit::allocateCodeSection(Size=0x%" PRIx64 ", Alignment=%u, SectionID=%u) = %p",
- (uint64_t)Size, Alignment, SectionID, (void *)return_value);
- }
-
- if (m_parent.m_reported_allocations)
- {
- Error err;
- lldb::ProcessSP process_sp = m_parent.GetBestExecutionContextScope()->CalculateProcess();
-
- m_parent.CommitOneAllocation(process_sp, err, m_parent.m_records.back());
- }
+ if (log) {
+ log->Printf("IRExecutionUnit::allocateCodeSection(Size=0x%" PRIx64
+ ", Alignment=%u, SectionID=%u) = %p",
+ (uint64_t)Size, Alignment, SectionID, (void *)return_value);
+ }
- return return_value;
+ if (m_parent.m_reported_allocations) {
+ Error err;
+ lldb::ProcessSP process_sp =
+ m_parent.GetBestExecutionContextScope()->CalculateProcess();
+
+ m_parent.CommitOneAllocation(process_sp, err, m_parent.m_records.back());
+ }
+
+ return return_value;
}
-uint8_t *
-IRExecutionUnit::MemoryManager::allocateDataSection(uintptr_t Size,
- unsigned Alignment,
- unsigned SectionID,
- llvm::StringRef SectionName,
- bool IsReadOnly)
-{
- Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
+uint8_t *IRExecutionUnit::MemoryManager::allocateDataSection(
+ uintptr_t Size, unsigned Alignment, unsigned SectionID,
+ llvm::StringRef SectionName, bool IsReadOnly) {
+ Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS));
- uint8_t *return_value = m_default_mm_ap->allocateDataSection(Size, Alignment, SectionID, SectionName, IsReadOnly);
+ uint8_t *return_value = m_default_mm_ap->allocateDataSection(
+ Size, Alignment, SectionID, SectionName, IsReadOnly);
- uint32_t permissions = lldb::ePermissionsReadable;
- if (!IsReadOnly)
- permissions |= lldb::ePermissionsWritable;
- m_parent.m_records.push_back(AllocationRecord((uintptr_t)return_value,
- permissions,
- GetSectionTypeFromSectionName (SectionName, AllocationKind::Data),
- Size,
- Alignment,
- SectionID,
- SectionName.str().c_str()));
- if (log)
- {
- log->Printf("IRExecutionUnit::allocateDataSection(Size=0x%" PRIx64 ", Alignment=%u, SectionID=%u) = %p",
- (uint64_t)Size, Alignment, SectionID, (void *)return_value);
- }
-
- if (m_parent.m_reported_allocations)
- {
- Error err;
- lldb::ProcessSP process_sp = m_parent.GetBestExecutionContextScope()->CalculateProcess();
-
- m_parent.CommitOneAllocation(process_sp, err, m_parent.m_records.back());
- }
+ uint32_t permissions = lldb::ePermissionsReadable;
+ if (!IsReadOnly)
+ permissions |= lldb::ePermissionsWritable;
+ m_parent.m_records.push_back(AllocationRecord(
+ (uintptr_t)return_value, permissions,
+ GetSectionTypeFromSectionName(SectionName, AllocationKind::Data), Size,
+ Alignment, SectionID, SectionName.str().c_str()));
+ if (log) {
+ log->Printf("IRExecutionUnit::allocateDataSection(Size=0x%" PRIx64
+ ", Alignment=%u, SectionID=%u) = %p",
+ (uint64_t)Size, Alignment, SectionID, (void *)return_value);
+ }
- return return_value;
+ if (m_parent.m_reported_allocations) {
+ Error err;
+ lldb::ProcessSP process_sp =
+ m_parent.GetBestExecutionContextScope()->CalculateProcess();
+
+ m_parent.CommitOneAllocation(process_sp, err, m_parent.m_records.back());
+ }
+
+ return return_value;
}
static ConstString
FindBestAlternateMangledName(const ConstString &demangled,
const lldb::LanguageType &lang_type,
- const SymbolContext &sym_ctx)
-{
- CPlusPlusLanguage::MethodName cpp_name(demangled);
- std::string scope_qualified_name = cpp_name.GetScopeQualifiedName();
+ const SymbolContext &sym_ctx) {
+ CPlusPlusLanguage::MethodName cpp_name(demangled);
+ std::string scope_qualified_name = cpp_name.GetScopeQualifiedName();
- if (!scope_qualified_name.size())
- return ConstString();
+ if (!scope_qualified_name.size())
+ return ConstString();
- if (!sym_ctx.module_sp)
- return ConstString();
+ if (!sym_ctx.module_sp)
+ return ConstString();
- SymbolVendor *sym_vendor = sym_ctx.module_sp->GetSymbolVendor();
- if (!sym_vendor)
- return ConstString();
+ SymbolVendor *sym_vendor = sym_ctx.module_sp->GetSymbolVendor();
+ if (!sym_vendor)
+ return ConstString();
- lldb_private::SymbolFile *sym_file = sym_vendor->GetSymbolFile();
- if (!sym_file)
- return ConstString();
+ lldb_private::SymbolFile *sym_file = sym_vendor->GetSymbolFile();
+ if (!sym_file)
+ return ConstString();
- std::vector<ConstString> alternates;
- sym_file->GetMangledNamesForFunction(scope_qualified_name, alternates);
+ std::vector<ConstString> alternates;
+ sym_file->GetMangledNamesForFunction(scope_qualified_name, alternates);
- std::vector<ConstString> param_and_qual_matches;
- std::vector<ConstString> param_matches;
- for (size_t i = 0; i < alternates.size(); i++)
- {
- ConstString alternate_mangled_name = alternates[i];
- Mangled mangled(alternate_mangled_name, true);
- ConstString demangled = mangled.GetDemangledName(lang_type);
+ std::vector<ConstString> param_and_qual_matches;
+ std::vector<ConstString> param_matches;
+ for (size_t i = 0; i < alternates.size(); i++) {
+ ConstString alternate_mangled_name = alternates[i];
+ Mangled mangled(alternate_mangled_name, true);
+ ConstString demangled = mangled.GetDemangledName(lang_type);
- CPlusPlusLanguage::MethodName alternate_cpp_name(demangled);
- if (!cpp_name.IsValid())
- continue;
+ CPlusPlusLanguage::MethodName alternate_cpp_name(demangled);
+ if (!cpp_name.IsValid())
+ continue;
- if (alternate_cpp_name.GetArguments() == cpp_name.GetArguments())
- {
- if (alternate_cpp_name.GetQualifiers() == cpp_name.GetQualifiers())
- param_and_qual_matches.push_back(alternate_mangled_name);
- else
- param_matches.push_back(alternate_mangled_name);
- }
+ if (alternate_cpp_name.GetArguments() == cpp_name.GetArguments()) {
+ if (alternate_cpp_name.GetQualifiers() == cpp_name.GetQualifiers())
+ param_and_qual_matches.push_back(alternate_mangled_name);
+ else
+ param_matches.push_back(alternate_mangled_name);
}
+ }
- if (param_and_qual_matches.size())
- return param_and_qual_matches[0]; // It is assumed that there will be only one!
- else if (param_matches.size())
- return param_matches[0]; // Return one of them as a best match
- else
- return ConstString();
+ if (param_and_qual_matches.size())
+ return param_and_qual_matches[0]; // It is assumed that there will be only
+ // one!
+ else if (param_matches.size())
+ return param_matches[0]; // Return one of them as a best match
+ else
+ return ConstString();
}
-struct IRExecutionUnit::SearchSpec
-{
- ConstString name;
- uint32_t mask;
+struct IRExecutionUnit::SearchSpec {
+ ConstString name;
+ uint32_t mask;
- SearchSpec(ConstString n, uint32_t m = lldb::eFunctionNameTypeFull) :
- name(n),
- mask(m)
- {
- }
+ SearchSpec(ConstString n, uint32_t m = lldb::eFunctionNameTypeFull)
+ : name(n), mask(m) {}
};
-void
-IRExecutionUnit::CollectCandidateCNames(std::vector<IRExecutionUnit::SearchSpec> &C_specs, const ConstString &name)
-{
- if (m_strip_underscore && name.AsCString()[0] == '_')
- C_specs.insert(C_specs.begin(), ConstString(&name.AsCString()[1]));
- C_specs.push_back(SearchSpec(name));
+void IRExecutionUnit::CollectCandidateCNames(
+ std::vector<IRExecutionUnit::SearchSpec> &C_specs,
+ const ConstString &name) {
+ if (m_strip_underscore && name.AsCString()[0] == '_')
+ C_specs.insert(C_specs.begin(), ConstString(&name.AsCString()[1]));
+ C_specs.push_back(SearchSpec(name));
}
-void
-IRExecutionUnit::CollectCandidateCPlusPlusNames(std::vector<IRExecutionUnit::SearchSpec> &CPP_specs, const std::vector<SearchSpec> &C_specs, const SymbolContext &sc)
-{
- for (const SearchSpec &C_spec : C_specs)
- {
- const ConstString &name = C_spec.name;
+void IRExecutionUnit::CollectCandidateCPlusPlusNames(
+ std::vector<IRExecutionUnit::SearchSpec> &CPP_specs,
+ const std::vector<SearchSpec> &C_specs, const SymbolContext &sc) {
+ for (const SearchSpec &C_spec : C_specs) {
+ const ConstString &name = C_spec.name;
- if (CPlusPlusLanguage::IsCPPMangledName(name.GetCString()))
- {
- Mangled mangled(name, true);
- ConstString demangled = mangled.GetDemangledName(lldb::eLanguageTypeC_plus_plus);
+ if (CPlusPlusLanguage::IsCPPMangledName(name.GetCString())) {
+ Mangled mangled(name, true);
+ ConstString demangled =
+ mangled.GetDemangledName(lldb::eLanguageTypeC_plus_plus);
- if (demangled)
- {
- ConstString best_alternate_mangled_name = FindBestAlternateMangledName(demangled, lldb::eLanguageTypeC_plus_plus, sc);
+ if (demangled) {
+ ConstString best_alternate_mangled_name = FindBestAlternateMangledName(
+ demangled, lldb::eLanguageTypeC_plus_plus, sc);
- if (best_alternate_mangled_name)
- {
- CPP_specs.push_back(best_alternate_mangled_name);
- }
-
- CPP_specs.push_back(SearchSpec(demangled, lldb::eFunctionNameTypeFull));
- }
+ if (best_alternate_mangled_name) {
+ CPP_specs.push_back(best_alternate_mangled_name);
}
- // Maybe we're looking for a const symbol but the debug info told us it was const...
- if (!strncmp(name.GetCString(), "_ZN", 3) &&
- strncmp(name.GetCString(), "_ZNK", 4))
- {
- std::string fixed_scratch("_ZNK");
- fixed_scratch.append(name.GetCString() + 3);
- CPP_specs.push_back(ConstString(fixed_scratch.c_str()));
- }
-
- // Maybe we're looking for a static symbol but we thought it was global...
- if (!strncmp(name.GetCString(), "_Z", 2) &&
- strncmp(name.GetCString(), "_ZL", 3))
- {
- std::string fixed_scratch("_ZL");
- fixed_scratch.append(name.GetCString() + 2);
- CPP_specs.push_back(ConstString(fixed_scratch.c_str()));
- }
-
+ CPP_specs.push_back(SearchSpec(demangled, lldb::eFunctionNameTypeFull));
+ }
}
+
+ // Maybe we're looking for a const symbol but the debug info told us it was
+ // const...
+ if (!strncmp(name.GetCString(), "_ZN", 3) &&
+ strncmp(name.GetCString(), "_ZNK", 4)) {
+ std::string fixed_scratch("_ZNK");
+ fixed_scratch.append(name.GetCString() + 3);
+ CPP_specs.push_back(ConstString(fixed_scratch.c_str()));
+ }
+
+ // Maybe we're looking for a static symbol but we thought it was global...
+ if (!strncmp(name.GetCString(), "_Z", 2) &&
+ strncmp(name.GetCString(), "_ZL", 3)) {
+ std::string fixed_scratch("_ZL");
+ fixed_scratch.append(name.GetCString() + 2);
+ CPP_specs.push_back(ConstString(fixed_scratch.c_str()));
+ }
+ }
}
-void
-IRExecutionUnit::CollectFallbackNames(std::vector<SearchSpec> &fallback_specs,
- const std::vector<SearchSpec> &C_specs)
-{
- // As a last-ditch fallback, try the base name for C++ names. It's terrible,
- // but the DWARF doesn't always encode "extern C" correctly.
-
- for (const SearchSpec &C_spec : C_specs)
- {
- const ConstString &name = C_spec.name;
-
- if (CPlusPlusLanguage::IsCPPMangledName(name.GetCString()))
- {
- Mangled mangled_name(name);
- ConstString demangled_name = mangled_name.GetDemangledName(lldb::eLanguageTypeC_plus_plus);
- if (!demangled_name.IsEmpty())
- {
- const char *demangled_cstr = demangled_name.AsCString();
- const char *lparen_loc = strchr(demangled_cstr, '(');
- if (lparen_loc)
- {
- llvm::StringRef base_name(demangled_cstr, lparen_loc-demangled_cstr);
- fallback_specs.push_back(ConstString(base_name));
- }
- }
+void IRExecutionUnit::CollectFallbackNames(
+ std::vector<SearchSpec> &fallback_specs,
+ const std::vector<SearchSpec> &C_specs) {
+ // As a last-ditch fallback, try the base name for C++ names. It's terrible,
+ // but the DWARF doesn't always encode "extern C" correctly.
+
+ for (const SearchSpec &C_spec : C_specs) {
+ const ConstString &name = C_spec.name;
+
+ if (CPlusPlusLanguage::IsCPPMangledName(name.GetCString())) {
+ Mangled mangled_name(name);
+ ConstString demangled_name =
+ mangled_name.GetDemangledName(lldb::eLanguageTypeC_plus_plus);
+ if (!demangled_name.IsEmpty()) {
+ const char *demangled_cstr = demangled_name.AsCString();
+ const char *lparen_loc = strchr(demangled_cstr, '(');
+ if (lparen_loc) {
+ llvm::StringRef base_name(demangled_cstr,
+ lparen_loc - demangled_cstr);
+ fallback_specs.push_back(ConstString(base_name));
}
+ }
}
+ }
}
+lldb::addr_t IRExecutionUnit::FindInSymbols(
+ const std::vector<IRExecutionUnit::SearchSpec> &specs,
+ const lldb_private::SymbolContext &sc) {
+ Target *target = sc.target_sp.get();
-lldb::addr_t
-IRExecutionUnit::FindInSymbols(const std::vector<IRExecutionUnit::SearchSpec> &specs, const lldb_private::SymbolContext &sc)
-{
- Target *target = sc.target_sp.get();
+ if (!target) {
+ // we shouldn't be doing any symbol lookup at all without a target
+ return LLDB_INVALID_ADDRESS;
+ }
- if (!target)
- {
- // we shouldn't be doing any symbol lookup at all without a target
- return LLDB_INVALID_ADDRESS;
- }
+ for (const SearchSpec &spec : specs) {
+ SymbolContextList sc_list;
- for (const SearchSpec &spec : specs)
- {
- SymbolContextList sc_list;
+ lldb::addr_t best_internal_load_address = LLDB_INVALID_ADDRESS;
- lldb::addr_t best_internal_load_address = LLDB_INVALID_ADDRESS;
+ std::function<bool(lldb::addr_t &, SymbolContextList &,
+ const lldb_private::SymbolContext &)>
+ get_external_load_address = [&best_internal_load_address, target](
+ lldb::addr_t &load_address, SymbolContextList &sc_list,
+ const lldb_private::SymbolContext &sc) -> lldb::addr_t {
+ load_address = LLDB_INVALID_ADDRESS;
- std::function<bool (lldb::addr_t &, SymbolContextList &, const lldb_private::SymbolContext &)> get_external_load_address =
- [&best_internal_load_address, target](lldb::addr_t &load_address,
- SymbolContextList &sc_list,
- const lldb_private::SymbolContext &sc) -> lldb::addr_t
- {
+ for (size_t si = 0, se = sc_list.GetSize(); si < se; ++si) {
+ SymbolContext candidate_sc;
+
+ sc_list.GetContextAtIndex(si, candidate_sc);
+
+ const bool is_external =
+ (candidate_sc.function) ||
+ (candidate_sc.symbol && candidate_sc.symbol->IsExternal());
+ if (candidate_sc.symbol) {
+ load_address = candidate_sc.symbol->ResolveCallableAddress(*target);
+
+ if (load_address == LLDB_INVALID_ADDRESS) {
+ if (target->GetProcessSP())
+ load_address =
+ candidate_sc.symbol->GetAddress().GetLoadAddress(target);
+ else
+ load_address = candidate_sc.symbol->GetAddress().GetFileAddress();
+ }
+ }
+
+ if (load_address == LLDB_INVALID_ADDRESS && candidate_sc.function) {
+ if (target->GetProcessSP())
+ load_address = candidate_sc.function->GetAddressRange()
+ .GetBaseAddress()
+ .GetLoadAddress(target);
+ else
+ load_address = candidate_sc.function->GetAddressRange()
+ .GetBaseAddress()
+ .GetFileAddress();
+ }
+
+ if (load_address != LLDB_INVALID_ADDRESS) {
+ if (is_external) {
+ return true;
+ } else if (best_internal_load_address == LLDB_INVALID_ADDRESS) {
+ best_internal_load_address = load_address;
load_address = LLDB_INVALID_ADDRESS;
+ }
+ }
+ }
- for (size_t si = 0, se = sc_list.GetSize(); si < se; ++si)
- {
- SymbolContext candidate_sc;
+ return false;
+ };
- sc_list.GetContextAtIndex(si, candidate_sc);
+ if (sc.module_sp) {
+ sc.module_sp->FindFunctions(spec.name, NULL, spec.mask,
+ true, // include_symbols
+ false, // include_inlines
+ true, // append
+ sc_list);
+ }
- const bool is_external = (candidate_sc.function) ||
- (candidate_sc.symbol && candidate_sc.symbol->IsExternal());
- if (candidate_sc.symbol)
- {
- load_address = candidate_sc.symbol->ResolveCallableAddress(*target);
+ lldb::addr_t load_address = LLDB_INVALID_ADDRESS;
- if (load_address == LLDB_INVALID_ADDRESS)
- {
- if (target->GetProcessSP())
- load_address = candidate_sc.symbol->GetAddress().GetLoadAddress(target);
- else
- load_address = candidate_sc.symbol->GetAddress().GetFileAddress();
- }
+ if (get_external_load_address(load_address, sc_list, sc)) {
+ return load_address;
+ } else {
+ sc_list.Clear();
+ }
+
+ if (sc_list.GetSize() == 0 && sc.target_sp) {
+ sc.target_sp->GetImages().FindFunctions(spec.name, spec.mask,
+ true, // include_symbols
+ false, // include_inlines
+ true, // append
+ sc_list);
+ }
+
+ if (get_external_load_address(load_address, sc_list, sc)) {
+ return load_address;
+ } else {
+ sc_list.Clear();
+ }
+
+ if (sc_list.GetSize() == 0 && sc.target_sp) {
+ sc.target_sp->GetImages().FindSymbolsWithNameAndType(
+ spec.name, lldb::eSymbolTypeAny, sc_list);
+ }
+
+ if (get_external_load_address(load_address, sc_list, sc)) {
+ return load_address;
+ }
+ // if there are any searches we try after this, add an sc_list.Clear() in an
+ // "else" clause here
+
+ if (best_internal_load_address != LLDB_INVALID_ADDRESS) {
+ return best_internal_load_address;
+ }
+ }
+
+ return LLDB_INVALID_ADDRESS;
+}
+
+lldb::addr_t
+IRExecutionUnit::FindInRuntimes(const std::vector<SearchSpec> &specs,
+ const lldb_private::SymbolContext &sc) {
+ lldb::TargetSP target_sp = sc.target_sp;
+
+ if (!target_sp) {
+ return LLDB_INVALID_ADDRESS;
+ }
+
+ lldb::ProcessSP process_sp = sc.target_sp->GetProcessSP();
+
+ if (!process_sp) {
+ return LLDB_INVALID_ADDRESS;
+ }
+
+ ObjCLanguageRuntime *runtime = process_sp->GetObjCLanguageRuntime();
+
+ if (runtime) {
+ for (const SearchSpec &spec : specs) {
+ lldb::addr_t symbol_load_addr = runtime->LookupRuntimeSymbol(spec.name);
+
+ if (symbol_load_addr != LLDB_INVALID_ADDRESS)
+ return symbol_load_addr;
+ }
+ }
+
+ return LLDB_INVALID_ADDRESS;
+}
+
+lldb::addr_t IRExecutionUnit::FindInUserDefinedSymbols(
+ const std::vector<SearchSpec> &specs,
+ const lldb_private::SymbolContext &sc) {
+ lldb::TargetSP target_sp = sc.target_sp;
+
+ for (const SearchSpec &spec : specs) {
+ lldb::addr_t symbol_load_addr = target_sp->GetPersistentSymbol(spec.name);
+
+ if (symbol_load_addr != LLDB_INVALID_ADDRESS)
+ return symbol_load_addr;
+ }
+
+ return LLDB_INVALID_ADDRESS;
+}
+
+lldb::addr_t
+IRExecutionUnit::FindSymbol(const lldb_private::ConstString &name) {
+ std::vector<SearchSpec> candidate_C_names;
+ std::vector<SearchSpec> candidate_CPlusPlus_names;
+
+ CollectCandidateCNames(candidate_C_names, name);
+
+ lldb::addr_t ret = FindInSymbols(candidate_C_names, m_sym_ctx);
+ if (ret == LLDB_INVALID_ADDRESS)
+ ret = FindInRuntimes(candidate_C_names, m_sym_ctx);
+
+ if (ret == LLDB_INVALID_ADDRESS)
+ ret = FindInUserDefinedSymbols(candidate_C_names, m_sym_ctx);
+
+ if (ret == LLDB_INVALID_ADDRESS) {
+ CollectCandidateCPlusPlusNames(candidate_CPlusPlus_names, candidate_C_names,
+ m_sym_ctx);
+ ret = FindInSymbols(candidate_CPlusPlus_names, m_sym_ctx);
+ }
+
+ if (ret == LLDB_INVALID_ADDRESS) {
+ std::vector<SearchSpec> candidate_fallback_names;
+
+ CollectFallbackNames(candidate_fallback_names, candidate_C_names);
+ ret = FindInSymbols(candidate_fallback_names, m_sym_ctx);
+ }
+
+ return ret;
+}
+
+void IRExecutionUnit::GetStaticInitializers(
+ std::vector<lldb::addr_t> &static_initializers) {
+ if (llvm::GlobalVariable *global_ctors =
+ m_module->getNamedGlobal("llvm.global_ctors")) {
+ if (llvm::ConstantArray *ctor_array = llvm::dyn_cast<llvm::ConstantArray>(
+ global_ctors->getInitializer())) {
+ for (llvm::Use &ctor_use : ctor_array->operands()) {
+ if (llvm::ConstantStruct *ctor_struct =
+ llvm::dyn_cast<llvm::ConstantStruct>(ctor_use)) {
+ lldbassert(ctor_struct->getNumOperands() ==
+ 3); // this is standardized
+ if (llvm::Function *ctor_function =
+ llvm::dyn_cast<llvm::Function>(ctor_struct->getOperand(1))) {
+ ctor_function->dump();
+
+ ConstString ctor_function_name_cs(ctor_function->getName().str());
+
+ for (JittedFunction &jitted_function : m_jitted_functions) {
+ if (ctor_function_name_cs == jitted_function.m_name) {
+ if (jitted_function.m_remote_addr != LLDB_INVALID_ADDRESS) {
+ static_initializers.push_back(jitted_function.m_remote_addr);
}
-
- if (load_address == LLDB_INVALID_ADDRESS && candidate_sc.function)
- {
- if (target->GetProcessSP())
- load_address = candidate_sc.function->GetAddressRange().GetBaseAddress().GetLoadAddress(target);
- else
- load_address = candidate_sc.function->GetAddressRange().GetBaseAddress().GetFileAddress();
- }
-
- if (load_address != LLDB_INVALID_ADDRESS)
- {
- if (is_external)
- {
- return true;
- }
- else if (best_internal_load_address == LLDB_INVALID_ADDRESS)
- {
- best_internal_load_address = load_address;
- load_address = LLDB_INVALID_ADDRESS;
- }
- }
+ break;
+ }
}
-
- return false;
- };
-
- if (sc.module_sp)
- {
- sc.module_sp->FindFunctions(spec.name,
- NULL,
- spec.mask,
- true, // include_symbols
- false, // include_inlines
- true, // append
- sc_list);
+ }
}
-
- lldb::addr_t load_address = LLDB_INVALID_ADDRESS;
-
- if (get_external_load_address(load_address, sc_list, sc))
- {
- return load_address;
- }
- else
- {
- sc_list.Clear();
- }
-
- if (sc_list.GetSize() == 0 && sc.target_sp)
- {
- sc.target_sp->GetImages().FindFunctions(spec.name,
- spec.mask,
- true, // include_symbols
- false, // include_inlines
- true, // append
- sc_list);
- }
-
- if (get_external_load_address(load_address, sc_list, sc))
- {
- return load_address;
- }
- else
- {
- sc_list.Clear();
- }
-
- if (sc_list.GetSize() == 0 && sc.target_sp)
- {
- sc.target_sp->GetImages().FindSymbolsWithNameAndType(spec.name, lldb::eSymbolTypeAny, sc_list);
- }
-
- if (get_external_load_address(load_address, sc_list, sc))
- {
- return load_address;
- }
- // if there are any searches we try after this, add an sc_list.Clear() in an "else" clause here
-
- if (best_internal_load_address != LLDB_INVALID_ADDRESS)
- {
- return best_internal_load_address;
- }
+ }
}
-
- return LLDB_INVALID_ADDRESS;
-}
-
-lldb::addr_t
-IRExecutionUnit::FindInRuntimes(const std::vector<SearchSpec> &specs, const lldb_private::SymbolContext &sc)
-{
- lldb::TargetSP target_sp = sc.target_sp;
-
- if (!target_sp)
- {
- return LLDB_INVALID_ADDRESS;
- }
-
- lldb::ProcessSP process_sp = sc.target_sp->GetProcessSP();
-
- if (!process_sp)
- {
- return LLDB_INVALID_ADDRESS;
- }
-
- ObjCLanguageRuntime *runtime = process_sp->GetObjCLanguageRuntime();
-
- if (runtime)
- {
- for (const SearchSpec &spec : specs)
- {
- lldb::addr_t symbol_load_addr = runtime->LookupRuntimeSymbol(spec.name);
-
- if (symbol_load_addr != LLDB_INVALID_ADDRESS)
- return symbol_load_addr;
- }
- }
-
- return LLDB_INVALID_ADDRESS;
-}
-
-lldb::addr_t
-IRExecutionUnit::FindInUserDefinedSymbols(const std::vector<SearchSpec> &specs, const lldb_private::SymbolContext &sc)
-{
- lldb::TargetSP target_sp = sc.target_sp;
-
- for (const SearchSpec &spec : specs)
- {
- lldb::addr_t symbol_load_addr = target_sp->GetPersistentSymbol(spec.name);
-
- if (symbol_load_addr != LLDB_INVALID_ADDRESS)
- return symbol_load_addr;
- }
-
- return LLDB_INVALID_ADDRESS;
-}
-
-lldb::addr_t
-IRExecutionUnit::FindSymbol(const lldb_private::ConstString &name)
-{
- std::vector<SearchSpec> candidate_C_names;
- std::vector<SearchSpec> candidate_CPlusPlus_names;
-
- CollectCandidateCNames(candidate_C_names, name);
-
- lldb::addr_t ret = FindInSymbols(candidate_C_names, m_sym_ctx);
- if (ret == LLDB_INVALID_ADDRESS)
- ret = FindInRuntimes(candidate_C_names, m_sym_ctx);
-
- if (ret == LLDB_INVALID_ADDRESS)
- ret = FindInUserDefinedSymbols(candidate_C_names, m_sym_ctx);
-
- if (ret == LLDB_INVALID_ADDRESS)
- {
- CollectCandidateCPlusPlusNames(candidate_CPlusPlus_names, candidate_C_names, m_sym_ctx);
- ret = FindInSymbols(candidate_CPlusPlus_names, m_sym_ctx);
- }
-
- if (ret == LLDB_INVALID_ADDRESS)
- {
- std::vector<SearchSpec> candidate_fallback_names;
-
- CollectFallbackNames(candidate_fallback_names, candidate_C_names);
- ret = FindInSymbols(candidate_fallback_names, m_sym_ctx);
- }
-
- return ret;
-}
-
-void
-IRExecutionUnit::GetStaticInitializers(std::vector <lldb::addr_t> &static_initializers)
-{
- if (llvm::GlobalVariable *global_ctors = m_module->getNamedGlobal("llvm.global_ctors"))
- {
- if (llvm::ConstantArray *ctor_array = llvm::dyn_cast<llvm::ConstantArray>(global_ctors->getInitializer()))
- {
- for (llvm::Use &ctor_use : ctor_array->operands())
- {
- if (llvm::ConstantStruct *ctor_struct = llvm::dyn_cast<llvm::ConstantStruct>(ctor_use))
- {
- lldbassert(ctor_struct->getNumOperands() == 3); // this is standardized
- if (llvm::Function *ctor_function = llvm::dyn_cast<llvm::Function>(ctor_struct->getOperand(1)))
- {
- ctor_function->dump();
-
- ConstString ctor_function_name_cs(ctor_function->getName().str());
-
- for (JittedFunction &jitted_function : m_jitted_functions)
- {
- if (ctor_function_name_cs == jitted_function.m_name)
- {
- if (jitted_function.m_remote_addr != LLDB_INVALID_ADDRESS)
- {
- static_initializers.push_back(jitted_function.m_remote_addr);
- }
- break;
- }
- }
- }
- }
- }
- }
- }
+ }
}
uint64_t
-IRExecutionUnit::MemoryManager::getSymbolAddress(const std::string &Name)
-{
- Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
+IRExecutionUnit::MemoryManager::getSymbolAddress(const std::string &Name) {
+ Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS));
- ConstString name_cs(Name.c_str());
+ ConstString name_cs(Name.c_str());
- lldb::addr_t ret = m_parent.FindSymbol(name_cs);
+ lldb::addr_t ret = m_parent.FindSymbol(name_cs);
- if (ret == LLDB_INVALID_ADDRESS)
- {
- if (log)
- log->Printf("IRExecutionUnit::getSymbolAddress(Name=\"%s\") = <not found>",
- Name.c_str());
+ if (ret == LLDB_INVALID_ADDRESS) {
+ if (log)
+ log->Printf(
+ "IRExecutionUnit::getSymbolAddress(Name=\"%s\") = <not found>",
+ Name.c_str());
- m_parent.ReportSymbolLookupError(name_cs);
- return 0xbad0bad0;
- }
- else
- {
- if (log)
- log->Printf("IRExecutionUnit::getSymbolAddress(Name=\"%s\") = %" PRIx64,
- Name.c_str(),
- ret);
- return ret;
- }
+ m_parent.ReportSymbolLookupError(name_cs);
+ return 0xbad0bad0;
+ } else {
+ if (log)
+ log->Printf("IRExecutionUnit::getSymbolAddress(Name=\"%s\") = %" PRIx64,
+ Name.c_str(), ret);
+ return ret;
+ }
}
-void *
-IRExecutionUnit::MemoryManager::getPointerToNamedFunction(const std::string &Name,
- bool AbortOnFailure) {
- assert (sizeof(void *) == 8);
+void *IRExecutionUnit::MemoryManager::getPointerToNamedFunction(
+ const std::string &Name, bool AbortOnFailure) {
+ assert(sizeof(void *) == 8);
- return (void*)getSymbolAddress(Name);
+ return (void *)getSymbolAddress(Name);
}
lldb::addr_t
-IRExecutionUnit::GetRemoteAddressForLocal (lldb::addr_t local_address)
-{
- Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
+IRExecutionUnit::GetRemoteAddressForLocal(lldb::addr_t local_address) {
+ Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS));
- for (AllocationRecord &record : m_records)
- {
- if (local_address >= record.m_host_address &&
- local_address < record.m_host_address + record.m_size)
- {
- if (record.m_process_address == LLDB_INVALID_ADDRESS)
- return LLDB_INVALID_ADDRESS;
+ for (AllocationRecord &record : m_records) {
+ if (local_address >= record.m_host_address &&
+ local_address < record.m_host_address + record.m_size) {
+ if (record.m_process_address == LLDB_INVALID_ADDRESS)
+ return LLDB_INVALID_ADDRESS;
- lldb::addr_t ret = record.m_process_address + (local_address - record.m_host_address);
+ lldb::addr_t ret =
+ record.m_process_address + (local_address - record.m_host_address);
- if (log)
- {
- log->Printf("IRExecutionUnit::GetRemoteAddressForLocal() found 0x%" PRIx64 " in [0x%" PRIx64 "..0x%" PRIx64 "], and returned 0x%" PRIx64 " from [0x%" PRIx64 "..0x%" PRIx64 "].",
- local_address,
- (uint64_t)record.m_host_address,
- (uint64_t)record.m_host_address + (uint64_t)record.m_size,
- ret,
- record.m_process_address,
- record.m_process_address + record.m_size);
- }
+ if (log) {
+ log->Printf(
+ "IRExecutionUnit::GetRemoteAddressForLocal() found 0x%" PRIx64
+ " in [0x%" PRIx64 "..0x%" PRIx64 "], and returned 0x%" PRIx64
+ " from [0x%" PRIx64 "..0x%" PRIx64 "].",
+ local_address, (uint64_t)record.m_host_address,
+ (uint64_t)record.m_host_address + (uint64_t)record.m_size, ret,
+ record.m_process_address, record.m_process_address + record.m_size);
+ }
- return ret;
- }
+ return ret;
}
+ }
- return LLDB_INVALID_ADDRESS;
+ return LLDB_INVALID_ADDRESS;
}
IRExecutionUnit::AddrRange
-IRExecutionUnit::GetRemoteRangeForLocal (lldb::addr_t local_address)
-{
- for (AllocationRecord &record : m_records)
- {
- if (local_address >= record.m_host_address &&
- local_address < record.m_host_address + record.m_size)
- {
- if (record.m_process_address == LLDB_INVALID_ADDRESS)
- return AddrRange(0, 0);
+IRExecutionUnit::GetRemoteRangeForLocal(lldb::addr_t local_address) {
+ for (AllocationRecord &record : m_records) {
+ if (local_address >= record.m_host_address &&
+ local_address < record.m_host_address + record.m_size) {
+ if (record.m_process_address == LLDB_INVALID_ADDRESS)
+ return AddrRange(0, 0);
- return AddrRange(record.m_process_address, record.m_size);
- }
+ return AddrRange(record.m_process_address, record.m_size);
}
+ }
- return AddrRange (0, 0);
+ return AddrRange(0, 0);
}
-bool
-IRExecutionUnit::CommitOneAllocation (lldb::ProcessSP &process_sp,
- Error &error,
- AllocationRecord &record)
-{
- if (record.m_process_address != LLDB_INVALID_ADDRESS)
- {
- return true;
+bool IRExecutionUnit::CommitOneAllocation(lldb::ProcessSP &process_sp,
+ Error &error,
+ AllocationRecord &record) {
+ if (record.m_process_address != LLDB_INVALID_ADDRESS) {
+ return true;
+ }
+
+ switch (record.m_sect_type) {
+ case lldb::eSectionTypeInvalid:
+ case lldb::eSectionTypeDWARFDebugAbbrev:
+ case lldb::eSectionTypeDWARFDebugAddr:
+ case lldb::eSectionTypeDWARFDebugAranges:
+ case lldb::eSectionTypeDWARFDebugFrame:
+ case lldb::eSectionTypeDWARFDebugInfo:
+ case lldb::eSectionTypeDWARFDebugLine:
+ case lldb::eSectionTypeDWARFDebugLoc:
+ case lldb::eSectionTypeDWARFDebugMacInfo:
+ case lldb::eSectionTypeDWARFDebugPubNames:
+ case lldb::eSectionTypeDWARFDebugPubTypes:
+ case lldb::eSectionTypeDWARFDebugRanges:
+ case lldb::eSectionTypeDWARFDebugStr:
+ case lldb::eSectionTypeDWARFDebugStrOffsets:
+ case lldb::eSectionTypeDWARFAppleNames:
+ case lldb::eSectionTypeDWARFAppleTypes:
+ case lldb::eSectionTypeDWARFAppleNamespaces:
+ case lldb::eSectionTypeDWARFAppleObjC:
+ error.Clear();
+ break;
+ default:
+ const bool zero_memory = false;
+ record.m_process_address =
+ Malloc(record.m_size, record.m_alignment, record.m_permissions,
+ eAllocationPolicyProcessOnly, zero_memory, error);
+ break;
+ }
+
+ return error.Success();
+}
+
+bool IRExecutionUnit::CommitAllocations(lldb::ProcessSP &process_sp) {
+ bool ret = true;
+
+ lldb_private::Error err;
+
+ for (AllocationRecord &record : m_records) {
+ ret = CommitOneAllocation(process_sp, err, record);
+
+ if (!ret) {
+ break;
}
-
- switch (record.m_sect_type)
- {
- case lldb::eSectionTypeInvalid:
- case lldb::eSectionTypeDWARFDebugAbbrev:
- case lldb::eSectionTypeDWARFDebugAddr:
- case lldb::eSectionTypeDWARFDebugAranges:
- case lldb::eSectionTypeDWARFDebugFrame:
- case lldb::eSectionTypeDWARFDebugInfo:
- case lldb::eSectionTypeDWARFDebugLine:
- case lldb::eSectionTypeDWARFDebugLoc:
- case lldb::eSectionTypeDWARFDebugMacInfo:
- case lldb::eSectionTypeDWARFDebugPubNames:
- case lldb::eSectionTypeDWARFDebugPubTypes:
- case lldb::eSectionTypeDWARFDebugRanges:
- case lldb::eSectionTypeDWARFDebugStr:
- case lldb::eSectionTypeDWARFDebugStrOffsets:
- case lldb::eSectionTypeDWARFAppleNames:
- case lldb::eSectionTypeDWARFAppleTypes:
- case lldb::eSectionTypeDWARFAppleNamespaces:
- case lldb::eSectionTypeDWARFAppleObjC:
- error.Clear();
- break;
- default:
- const bool zero_memory = false;
- record.m_process_address = Malloc (record.m_size,
- record.m_alignment,
- record.m_permissions,
- eAllocationPolicyProcessOnly,
- zero_memory,
- error);
- break;
+ }
+
+ if (!ret) {
+ for (AllocationRecord &record : m_records) {
+ if (record.m_process_address != LLDB_INVALID_ADDRESS) {
+ Free(record.m_process_address, err);
+ record.m_process_address = LLDB_INVALID_ADDRESS;
+ }
}
-
- return error.Success();
+ }
+
+ return ret;
}
-bool
-IRExecutionUnit::CommitAllocations (lldb::ProcessSP &process_sp)
-{
- bool ret = true;
+void IRExecutionUnit::ReportAllocations(llvm::ExecutionEngine &engine) {
+ m_reported_allocations = true;
- lldb_private::Error err;
+ for (AllocationRecord &record : m_records) {
+ if (record.m_process_address == LLDB_INVALID_ADDRESS)
+ continue;
- for (AllocationRecord &record : m_records)
- {
- ret = CommitOneAllocation(process_sp, err, record);
-
- if (!ret)
- {
- break;
- }
+ if (record.m_section_id == eSectionIDInvalid)
+ continue;
+
+ engine.mapSectionAddress((void *)record.m_host_address,
+ record.m_process_address);
+ }
+
+ // Trigger re-application of relocations.
+ engine.finalizeObject();
+}
+
+bool IRExecutionUnit::WriteData(lldb::ProcessSP &process_sp) {
+ bool wrote_something = false;
+ for (AllocationRecord &record : m_records) {
+ if (record.m_process_address != LLDB_INVALID_ADDRESS) {
+ lldb_private::Error err;
+ WriteMemory(record.m_process_address, (uint8_t *)record.m_host_address,
+ record.m_size, err);
+ if (err.Success())
+ wrote_something = true;
}
+ }
+ return wrote_something;
+}
- if (!ret)
- {
- for (AllocationRecord &record : m_records)
- {
- if (record.m_process_address != LLDB_INVALID_ADDRESS)
- {
- Free(record.m_process_address, err);
- record.m_process_address = LLDB_INVALID_ADDRESS;
- }
- }
+void IRExecutionUnit::AllocationRecord::dump(Log *log) {
+ if (!log)
+ return;
+
+ log->Printf("[0x%llx+0x%llx]->0x%llx (alignment %d, section ID %d, name %s)",
+ (unsigned long long)m_host_address, (unsigned long long)m_size,
+ (unsigned long long)m_process_address, (unsigned)m_alignment,
+ (unsigned)m_section_id, m_name.c_str());
+}
+
+lldb::ByteOrder IRExecutionUnit::GetByteOrder() const {
+ ExecutionContext exe_ctx(GetBestExecutionContextScope());
+ return exe_ctx.GetByteOrder();
+}
+
+uint32_t IRExecutionUnit::GetAddressByteSize() const {
+ ExecutionContext exe_ctx(GetBestExecutionContextScope());
+ return exe_ctx.GetAddressByteSize();
+}
+
+void IRExecutionUnit::PopulateSymtab(lldb_private::ObjectFile *obj_file,
+ lldb_private::Symtab &symtab) {
+ // No symbols yet...
+}
+
+void IRExecutionUnit::PopulateSectionList(
+ lldb_private::ObjectFile *obj_file,
+ lldb_private::SectionList §ion_list) {
+ for (AllocationRecord &record : m_records) {
+ if (record.m_size > 0) {
+ lldb::SectionSP section_sp(new lldb_private::Section(
+ obj_file->GetModule(), obj_file, record.m_section_id,
+ ConstString(record.m_name), record.m_sect_type,
+ record.m_process_address, record.m_size,
+ record.m_host_address, // file_offset (which is the host address for
+ // the data)
+ record.m_size, // file_size
+ 0,
+ record.m_permissions)); // flags
+ section_list.AddSection(section_sp);
}
-
- return ret;
+ }
}
-void
-IRExecutionUnit::ReportAllocations (llvm::ExecutionEngine &engine)
-{
- m_reported_allocations = true;
-
- for (AllocationRecord &record : m_records)
- {
- if (record.m_process_address == LLDB_INVALID_ADDRESS)
- continue;
+bool IRExecutionUnit::GetArchitecture(lldb_private::ArchSpec &arch) {
+ ExecutionContext exe_ctx(GetBestExecutionContextScope());
+ Target *target = exe_ctx.GetTargetPtr();
+ if (target)
+ arch = target->GetArchitecture();
+ else
+ arch.Clear();
+ return arch.IsValid();
+}
- if (record.m_section_id == eSectionIDInvalid)
- continue;
-
- engine.mapSectionAddress((void*)record.m_host_address, record.m_process_address);
+lldb::ModuleSP IRExecutionUnit::GetJITModule() {
+ ExecutionContext exe_ctx(GetBestExecutionContextScope());
+ Target *target = exe_ctx.GetTargetPtr();
+ if (target) {
+ lldb::ModuleSP jit_module_sp = lldb_private::Module::CreateJITModule(
+ std::static_pointer_cast<lldb_private::ObjectFileJITDelegate>(
+ shared_from_this()));
+ if (jit_module_sp) {
+ bool changed = false;
+ jit_module_sp->SetLoadAddress(*target, 0, true, changed);
}
-
- // Trigger re-application of relocations.
- engine.finalizeObject();
-}
-
-bool
-IRExecutionUnit::WriteData (lldb::ProcessSP &process_sp)
-{
- bool wrote_something = false;
- for (AllocationRecord &record : m_records)
- {
- if (record.m_process_address != LLDB_INVALID_ADDRESS)
- {
- lldb_private::Error err;
- WriteMemory (record.m_process_address, (uint8_t*)record.m_host_address, record.m_size, err);
- if (err.Success())
- wrote_something = true;
- }
- }
- return wrote_something;
-}
-
-void
-IRExecutionUnit::AllocationRecord::dump (Log *log)
-{
- if (!log)
- return;
-
- log->Printf("[0x%llx+0x%llx]->0x%llx (alignment %d, section ID %d, name %s)",
- (unsigned long long)m_host_address,
- (unsigned long long)m_size,
- (unsigned long long)m_process_address,
- (unsigned)m_alignment,
- (unsigned)m_section_id,
- m_name.c_str());
-}
-
-
-lldb::ByteOrder
-IRExecutionUnit::GetByteOrder () const
-{
- ExecutionContext exe_ctx (GetBestExecutionContextScope());
- return exe_ctx.GetByteOrder();
-}
-
-uint32_t
-IRExecutionUnit::GetAddressByteSize () const
-{
- ExecutionContext exe_ctx (GetBestExecutionContextScope());
- return exe_ctx.GetAddressByteSize();
-}
-
-void
-IRExecutionUnit::PopulateSymtab (lldb_private::ObjectFile *obj_file,
- lldb_private::Symtab &symtab)
-{
- // No symbols yet...
-}
-
-
-void
-IRExecutionUnit::PopulateSectionList (lldb_private::ObjectFile *obj_file,
- lldb_private::SectionList §ion_list)
-{
- for (AllocationRecord &record : m_records)
- {
- if (record.m_size > 0)
- {
- lldb::SectionSP section_sp (new lldb_private::Section (obj_file->GetModule(),
- obj_file,
- record.m_section_id,
- ConstString(record.m_name),
- record.m_sect_type,
- record.m_process_address,
- record.m_size,
- record.m_host_address, // file_offset (which is the host address for the data)
- record.m_size, // file_size
- 0,
- record.m_permissions)); // flags
- section_list.AddSection (section_sp);
- }
- }
-}
-
-bool
-IRExecutionUnit::GetArchitecture (lldb_private::ArchSpec &arch)
-{
- ExecutionContext exe_ctx (GetBestExecutionContextScope());
- Target *target = exe_ctx.GetTargetPtr();
- if (target)
- arch = target->GetArchitecture();
- else
- arch.Clear();
- return arch.IsValid();
-}
-
-lldb::ModuleSP
-IRExecutionUnit::GetJITModule ()
-{
- ExecutionContext exe_ctx (GetBestExecutionContextScope());
- Target *target = exe_ctx.GetTargetPtr();
- if (target)
- {
- lldb::ModuleSP jit_module_sp = lldb_private::Module::CreateJITModule (std::static_pointer_cast<lldb_private::ObjectFileJITDelegate>(shared_from_this()));
- if (jit_module_sp)
- {
- bool changed = false;
- jit_module_sp->SetLoadAddress(*target, 0, true, changed);
- }
- return jit_module_sp;
- }
- return lldb::ModuleSP();
+ return jit_module_sp;
+ }
+ return lldb::ModuleSP();
}
diff --git a/lldb/source/Expression/IRInterpreter.cpp b/lldb/source/Expression/IRInterpreter.cpp
index 0285248..ef96b85 100644
--- a/lldb/source/Expression/IRInterpreter.cpp
+++ b/lldb/source/Expression/IRInterpreter.cpp
@@ -43,1801 +43,1665 @@
using namespace llvm;
-static std::string
-PrintValue(const Value *value, bool truncate = false)
-{
- std::string s;
- raw_string_ostream rso(s);
- value->print(rso);
- rso.flush();
- if (truncate)
- s.resize(s.length() - 1);
+static std::string PrintValue(const Value *value, bool truncate = false) {
+ std::string s;
+ raw_string_ostream rso(s);
+ value->print(rso);
+ rso.flush();
+ if (truncate)
+ s.resize(s.length() - 1);
- size_t offset;
- while ((offset = s.find('\n')) != s.npos)
- s.erase(offset, 1);
- while (s[0] == ' ' || s[0] == '\t')
- s.erase(0, 1);
+ size_t offset;
+ while ((offset = s.find('\n')) != s.npos)
+ s.erase(offset, 1);
+ while (s[0] == ' ' || s[0] == '\t')
+ s.erase(0, 1);
- return s;
+ return s;
}
-static std::string
-PrintType(const Type *type, bool truncate = false)
-{
- std::string s;
- raw_string_ostream rso(s);
- type->print(rso);
- rso.flush();
- if (truncate)
- s.resize(s.length() - 1);
- return s;
+static std::string PrintType(const Type *type, bool truncate = false) {
+ std::string s;
+ raw_string_ostream rso(s);
+ type->print(rso);
+ rso.flush();
+ if (truncate)
+ s.resize(s.length() - 1);
+ return s;
}
-static bool
-CanIgnoreCall (const CallInst *call)
-{
- const llvm::Function *called_function = call->getCalledFunction();
+static bool CanIgnoreCall(const CallInst *call) {
+ const llvm::Function *called_function = call->getCalledFunction();
- if (!called_function)
- return false;
-
- if (called_function->isIntrinsic())
- {
- switch (called_function->getIntrinsicID())
- {
- default:
- break;
- case llvm::Intrinsic::dbg_declare:
- case llvm::Intrinsic::dbg_value:
- return true;
- }
- }
-
+ if (!called_function)
return false;
-}
-class InterpreterStackFrame
-{
-public:
- typedef std::map <const Value*, lldb::addr_t> ValueMap;
-
- ValueMap m_values;
- DataLayout &m_target_data;
- lldb_private::IRExecutionUnit &m_execution_unit;
- const BasicBlock *m_bb;
- const BasicBlock *m_prev_bb;
- BasicBlock::const_iterator m_ii;
- BasicBlock::const_iterator m_ie;
-
- lldb::addr_t m_frame_process_address;
- size_t m_frame_size;
- lldb::addr_t m_stack_pointer;
-
- lldb::ByteOrder m_byte_order;
- size_t m_addr_byte_size;
-
- InterpreterStackFrame (DataLayout &target_data,
- lldb_private::IRExecutionUnit &execution_unit,
- lldb::addr_t stack_frame_bottom,
- lldb::addr_t stack_frame_top) :
- m_target_data (target_data),
- m_execution_unit (execution_unit),
- m_bb (nullptr),
- m_prev_bb (nullptr)
- {
- m_byte_order = (target_data.isLittleEndian() ? lldb::eByteOrderLittle : lldb::eByteOrderBig);
- m_addr_byte_size = (target_data.getPointerSize(0));
-
- m_frame_process_address = stack_frame_bottom;
- m_frame_size = stack_frame_top - stack_frame_bottom;
- m_stack_pointer = stack_frame_top;
- }
-
- ~InterpreterStackFrame ()
- {
- }
-
- void Jump (const BasicBlock *bb)
- {
- m_prev_bb = m_bb;
- m_bb = bb;
- m_ii = m_bb->begin();
- m_ie = m_bb->end();
- }
-
- std::string SummarizeValue (const Value *value)
- {
- lldb_private::StreamString ss;
-
- ss.Printf("%s", PrintValue(value).c_str());
-
- ValueMap::iterator i = m_values.find(value);
-
- if (i != m_values.end())
- {
- lldb::addr_t addr = i->second;
-
- ss.Printf(" 0x%llx", (unsigned long long)addr);
- }
-
- return ss.GetString();
- }
-
- bool AssignToMatchType (lldb_private::Scalar &scalar, uint64_t u64value, Type *type)
- {
- size_t type_size = m_target_data.getTypeStoreSize(type);
-
- switch (type_size)
- {
- case 1:
- scalar = (uint8_t)u64value;
- break;
- case 2:
- scalar = (uint16_t)u64value;
- break;
- case 4:
- scalar = (uint32_t)u64value;
- break;
- case 8:
- scalar = (uint64_t)u64value;
- break;
- default:
- return false;
- }
-
- return true;
- }
-
- bool EvaluateValue (lldb_private::Scalar &scalar, const Value *value, Module &module)
- {
- const Constant *constant = dyn_cast<Constant>(value);
-
- if (constant)
- {
- APInt value_apint;
-
- if (!ResolveConstantValue(value_apint, constant))
- return false;
-
- return AssignToMatchType(scalar, value_apint.getLimitedValue(), value->getType());
- }
- else
- {
- lldb::addr_t process_address = ResolveValue(value, module);
- size_t value_size = m_target_data.getTypeStoreSize(value->getType());
-
- lldb_private::DataExtractor value_extractor;
- lldb_private::Error extract_error;
-
- m_execution_unit.GetMemoryData(value_extractor, process_address, value_size, extract_error);
-
- if (!extract_error.Success())
- return false;
-
- lldb::offset_t offset = 0;
- if (value_size == 1 || value_size == 2 || value_size == 4 || value_size == 8)
- {
- uint64_t u64value = value_extractor.GetMaxU64(&offset, value_size);
- return AssignToMatchType(scalar, u64value, value->getType());
- }
- }
-
- return false;
- }
-
- bool AssignValue (const Value *value, lldb_private::Scalar &scalar, Module &module)
- {
- lldb::addr_t process_address = ResolveValue (value, module);
-
- if (process_address == LLDB_INVALID_ADDRESS)
- return false;
-
- lldb_private::Scalar cast_scalar;
-
- if (!AssignToMatchType(cast_scalar, scalar.ULongLong(), value->getType()))
- return false;
-
- size_t value_byte_size = m_target_data.getTypeStoreSize(value->getType());
-
- lldb_private::DataBufferHeap buf(value_byte_size, 0);
-
- lldb_private::Error get_data_error;
-
- if (!cast_scalar.GetAsMemoryData(buf.GetBytes(), buf.GetByteSize(), m_byte_order, get_data_error))
- return false;
-
- lldb_private::Error write_error;
-
- m_execution_unit.WriteMemory(process_address, buf.GetBytes(), buf.GetByteSize(), write_error);
-
- return write_error.Success();
- }
-
- bool ResolveConstantValue (APInt &value, const Constant *constant)
- {
- switch (constant->getValueID())
- {
- default:
- break;
- case Value::FunctionVal:
- if (const Function *constant_func = dyn_cast<Function>(constant))
- {
- lldb_private::ConstString name(constant_func->getName());
- lldb::addr_t addr = m_execution_unit.FindSymbol(name);
- if (addr == LLDB_INVALID_ADDRESS)
- return false;
- value = APInt(m_target_data.getPointerSizeInBits(), addr);
- return true;
- }
- break;
- case Value::ConstantIntVal:
- if (const ConstantInt *constant_int = dyn_cast<ConstantInt>(constant))
- {
- value = constant_int->getValue();
- return true;
- }
- break;
- case Value::ConstantFPVal:
- if (const ConstantFP *constant_fp = dyn_cast<ConstantFP>(constant))
- {
- value = constant_fp->getValueAPF().bitcastToAPInt();
- return true;
- }
- break;
- case Value::ConstantExprVal:
- if (const ConstantExpr *constant_expr = dyn_cast<ConstantExpr>(constant))
- {
- switch (constant_expr->getOpcode())
- {
- default:
- return false;
- case Instruction::IntToPtr:
- case Instruction::PtrToInt:
- case Instruction::BitCast:
- return ResolveConstantValue(value, constant_expr->getOperand(0));
- case Instruction::GetElementPtr:
- {
- ConstantExpr::const_op_iterator op_cursor = constant_expr->op_begin();
- ConstantExpr::const_op_iterator op_end = constant_expr->op_end();
-
- Constant *base = dyn_cast<Constant>(*op_cursor);
-
- if (!base)
- return false;
-
- if (!ResolveConstantValue(value, base))
- return false;
-
- op_cursor++;
-
- if (op_cursor == op_end)
- return true; // no offset to apply!
-
- SmallVector <Value *, 8> indices (op_cursor, op_end);
-
- Type *src_elem_ty = cast<GEPOperator>(constant_expr)->getSourceElementType();
- uint64_t offset = m_target_data.getIndexedOffsetInType(src_elem_ty, indices);
-
- const bool is_signed = true;
- value += APInt(value.getBitWidth(), offset, is_signed);
-
- return true;
- }
- }
- }
- break;
- case Value::ConstantPointerNullVal:
- if (isa<ConstantPointerNull>(constant))
- {
- value = APInt(m_target_data.getPointerSizeInBits(), 0);
- return true;
- }
- break;
- }
- return false;
- }
-
- bool MakeArgument(const Argument *value, uint64_t address)
- {
- lldb::addr_t data_address = Malloc(value->getType());
-
- if (data_address == LLDB_INVALID_ADDRESS)
- return false;
-
- lldb_private::Error write_error;
-
- m_execution_unit.WritePointerToMemory(data_address, address, write_error);
-
- if (!write_error.Success())
- {
- lldb_private::Error free_error;
- m_execution_unit.Free(data_address, free_error);
- return false;
- }
-
- m_values[value] = data_address;
-
- lldb_private::Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
-
- if (log)
- {
- log->Printf("Made an allocation for argument %s", PrintValue(value).c_str());
- log->Printf(" Data region : %llx", (unsigned long long)address);
- log->Printf(" Ref region : %llx", (unsigned long long)data_address);
- }
-
- return true;
- }
-
- bool ResolveConstant (lldb::addr_t process_address, const Constant *constant)
- {
- APInt resolved_value;
-
- if (!ResolveConstantValue(resolved_value, constant))
- return false;
-
- size_t constant_size = m_target_data.getTypeStoreSize(constant->getType());
- lldb_private::DataBufferHeap buf(constant_size, 0);
-
- lldb_private::Error get_data_error;
-
- lldb_private::Scalar resolved_scalar(resolved_value.zextOrTrunc(llvm::NextPowerOf2(constant_size) * 8));
- if (!resolved_scalar.GetAsMemoryData(buf.GetBytes(), buf.GetByteSize(), m_byte_order, get_data_error))
- return false;
-
- lldb_private::Error write_error;
-
- m_execution_unit.WriteMemory(process_address, buf.GetBytes(), buf.GetByteSize(), write_error);
-
- return write_error.Success();
- }
-
- lldb::addr_t Malloc (size_t size, uint8_t byte_alignment)
- {
- lldb::addr_t ret = m_stack_pointer;
-
- ret -= size;
- ret -= (ret % byte_alignment);
-
- if (ret < m_frame_process_address)
- return LLDB_INVALID_ADDRESS;
-
- m_stack_pointer = ret;
- return ret;
- }
-
- lldb::addr_t MallocPointer ()
- {
- return Malloc(m_target_data.getPointerSize(), m_target_data.getPointerPrefAlignment());
- }
-
- lldb::addr_t Malloc (llvm::Type *type)
- {
- lldb_private::Error alloc_error;
-
- return Malloc(m_target_data.getTypeAllocSize(type), m_target_data.getPrefTypeAlignment(type));
- }
-
- std::string PrintData (lldb::addr_t addr, llvm::Type *type)
- {
- size_t length = m_target_data.getTypeStoreSize(type);
-
- lldb_private::DataBufferHeap buf(length, 0);
-
- lldb_private::Error read_error;
-
- m_execution_unit.ReadMemory(buf.GetBytes(), addr, length, read_error);
-
- if (!read_error.Success())
- return std::string("<couldn't read data>");
-
- lldb_private::StreamString ss;
-
- for (size_t i = 0; i < length; i++)
- {
- if ((!(i & 0xf)) && i)
- ss.Printf("%02hhx - ", buf.GetBytes()[i]);
- else
- ss.Printf("%02hhx ", buf.GetBytes()[i]);
- }
-
- return ss.GetString();
- }
-
- lldb::addr_t ResolveValue (const Value *value, Module &module)
- {
- ValueMap::iterator i = m_values.find(value);
-
- if (i != m_values.end())
- return i->second;
-
- // Fall back and allocate space [allocation type Alloca]
-
- lldb::addr_t data_address = Malloc(value->getType());
-
- if (const Constant *constant = dyn_cast<Constant>(value))
- {
- if (!ResolveConstant (data_address, constant))
- {
- lldb_private::Error free_error;
- m_execution_unit.Free(data_address, free_error);
- return LLDB_INVALID_ADDRESS;
- }
- }
-
- m_values[value] = data_address;
- return data_address;
- }
-};
-
-static const char *unsupported_opcode_error = "Interpreter doesn't handle one of the expression's opcodes";
-static const char *unsupported_operand_error = "Interpreter doesn't handle one of the expression's operands";
-//static const char *interpreter_initialization_error = "Interpreter couldn't be initialized";
-static const char *interpreter_internal_error = "Interpreter encountered an internal error";
-static const char *bad_value_error = "Interpreter couldn't resolve a value during execution";
-static const char *memory_allocation_error = "Interpreter couldn't allocate memory";
-static const char *memory_write_error = "Interpreter couldn't write to memory";
-static const char *memory_read_error = "Interpreter couldn't read from memory";
-static const char *infinite_loop_error = "Interpreter ran for too many cycles";
-//static const char *bad_result_error = "Result of expression is in bad memory";
-static const char *too_many_functions_error = "Interpreter doesn't handle modules with multiple function bodies.";
-
-static bool
-CanResolveConstant (llvm::Constant *constant)
-{
- switch (constant->getValueID())
- {
+ if (called_function->isIntrinsic()) {
+ switch (called_function->getIntrinsicID()) {
default:
- return false;
- case Value::ConstantIntVal:
- case Value::ConstantFPVal:
- case Value::FunctionVal:
- return true;
- case Value::ConstantExprVal:
- if (const ConstantExpr *constant_expr = dyn_cast<ConstantExpr>(constant))
- {
- switch (constant_expr->getOpcode())
- {
- default:
- return false;
- case Instruction::IntToPtr:
- case Instruction::PtrToInt:
- case Instruction::BitCast:
- return CanResolveConstant(constant_expr->getOperand(0));
- case Instruction::GetElementPtr:
- {
- ConstantExpr::const_op_iterator op_cursor = constant_expr->op_begin();
- Constant *base = dyn_cast<Constant>(*op_cursor);
- if (!base)
- return false;
-
- return CanResolveConstant(base);
- }
- }
- } else {
- return false;
- }
- case Value::ConstantPointerNullVal:
- return true;
+ break;
+ case llvm::Intrinsic::dbg_declare:
+ case llvm::Intrinsic::dbg_value:
+ return true;
}
+ }
+
+ return false;
}
-bool
-IRInterpreter::CanInterpret (llvm::Module &module,
- llvm::Function &function,
- lldb_private::Error &error,
- const bool support_function_calls)
-{
- lldb_private::Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
+class InterpreterStackFrame {
+public:
+ typedef std::map<const Value *, lldb::addr_t> ValueMap;
- bool saw_function_with_body = false;
+ ValueMap m_values;
+ DataLayout &m_target_data;
+ lldb_private::IRExecutionUnit &m_execution_unit;
+ const BasicBlock *m_bb;
+ const BasicBlock *m_prev_bb;
+ BasicBlock::const_iterator m_ii;
+ BasicBlock::const_iterator m_ie;
- for (Module::iterator fi = module.begin(), fe = module.end();
- fi != fe;
- ++fi)
- {
- if (fi->begin() != fi->end())
- {
- if (saw_function_with_body)
- {
- if (log)
- log->Printf("More than one function in the module has a body");
- error.SetErrorToGenericError();
- error.SetErrorString(too_many_functions_error);
- return false;
- }
- saw_function_with_body = true;
- }
+ lldb::addr_t m_frame_process_address;
+ size_t m_frame_size;
+ lldb::addr_t m_stack_pointer;
+
+ lldb::ByteOrder m_byte_order;
+ size_t m_addr_byte_size;
+
+ InterpreterStackFrame(DataLayout &target_data,
+ lldb_private::IRExecutionUnit &execution_unit,
+ lldb::addr_t stack_frame_bottom,
+ lldb::addr_t stack_frame_top)
+ : m_target_data(target_data), m_execution_unit(execution_unit),
+ m_bb(nullptr), m_prev_bb(nullptr) {
+ m_byte_order = (target_data.isLittleEndian() ? lldb::eByteOrderLittle
+ : lldb::eByteOrderBig);
+ m_addr_byte_size = (target_data.getPointerSize(0));
+
+ m_frame_process_address = stack_frame_bottom;
+ m_frame_size = stack_frame_top - stack_frame_bottom;
+ m_stack_pointer = stack_frame_top;
+ }
+
+ ~InterpreterStackFrame() {}
+
+ void Jump(const BasicBlock *bb) {
+ m_prev_bb = m_bb;
+ m_bb = bb;
+ m_ii = m_bb->begin();
+ m_ie = m_bb->end();
+ }
+
+ std::string SummarizeValue(const Value *value) {
+ lldb_private::StreamString ss;
+
+ ss.Printf("%s", PrintValue(value).c_str());
+
+ ValueMap::iterator i = m_values.find(value);
+
+ if (i != m_values.end()) {
+ lldb::addr_t addr = i->second;
+
+ ss.Printf(" 0x%llx", (unsigned long long)addr);
}
- for (Function::iterator bbi = function.begin(), bbe = function.end();
- bbi != bbe;
- ++bbi)
- {
- for (BasicBlock::iterator ii = bbi->begin(), ie = bbi->end();
- ii != ie;
- ++ii)
- {
- switch (ii->getOpcode())
- {
- default:
- {
- if (log)
- log->Printf("Unsupported instruction: %s", PrintValue(&*ii).c_str());
- error.SetErrorToGenericError();
- error.SetErrorString(unsupported_opcode_error);
- return false;
- }
- case Instruction::Add:
- case Instruction::Alloca:
- case Instruction::BitCast:
- case Instruction::Br:
- case Instruction::PHI:
- break;
- case Instruction::Call:
- {
- CallInst *call_inst = dyn_cast<CallInst>(ii);
+ return ss.GetString();
+ }
- if (!call_inst)
- {
- error.SetErrorToGenericError();
- error.SetErrorString(interpreter_internal_error);
- return false;
- }
+ bool AssignToMatchType(lldb_private::Scalar &scalar, uint64_t u64value,
+ Type *type) {
+ size_t type_size = m_target_data.getTypeStoreSize(type);
- if (!CanIgnoreCall(call_inst) && !support_function_calls)
- {
- if (log)
- log->Printf("Unsupported instruction: %s", PrintValue(&*ii).c_str());
- error.SetErrorToGenericError();
- error.SetErrorString(unsupported_opcode_error);
- return false;
- }
- }
- break;
- case Instruction::GetElementPtr:
- break;
- case Instruction::ICmp:
- {
- ICmpInst *icmp_inst = dyn_cast<ICmpInst>(ii);
-
- if (!icmp_inst)
- {
- error.SetErrorToGenericError();
- error.SetErrorString(interpreter_internal_error);
- return false;
- }
-
- switch (icmp_inst->getPredicate())
- {
- default:
- {
- if (log)
- log->Printf("Unsupported ICmp predicate: %s", PrintValue(&*ii).c_str());
-
- error.SetErrorToGenericError();
- error.SetErrorString(unsupported_opcode_error);
- return false;
- }
- case CmpInst::ICMP_EQ:
- case CmpInst::ICMP_NE:
- case CmpInst::ICMP_UGT:
- case CmpInst::ICMP_UGE:
- case CmpInst::ICMP_ULT:
- case CmpInst::ICMP_ULE:
- case CmpInst::ICMP_SGT:
- case CmpInst::ICMP_SGE:
- case CmpInst::ICMP_SLT:
- case CmpInst::ICMP_SLE:
- break;
- }
- }
- break;
- case Instruction::And:
- case Instruction::AShr:
- case Instruction::IntToPtr:
- case Instruction::PtrToInt:
- case Instruction::Load:
- case Instruction::LShr:
- case Instruction::Mul:
- case Instruction::Or:
- case Instruction::Ret:
- case Instruction::SDiv:
- case Instruction::SExt:
- case Instruction::Shl:
- case Instruction::SRem:
- case Instruction::Store:
- case Instruction::Sub:
- case Instruction::Trunc:
- case Instruction::UDiv:
- case Instruction::URem:
- case Instruction::Xor:
- case Instruction::ZExt:
- break;
- }
-
- for (int oi = 0, oe = ii->getNumOperands();
- oi != oe;
- ++oi)
- {
- Value *operand = ii->getOperand(oi);
- Type *operand_type = operand->getType();
-
- switch (operand_type->getTypeID())
- {
- default:
- break;
- case Type::VectorTyID:
- {
- if (log)
- log->Printf("Unsupported operand type: %s", PrintType(operand_type).c_str());
- error.SetErrorString(unsupported_operand_error);
- return false;
- }
- }
-
- if (Constant *constant = llvm::dyn_cast<Constant>(operand))
- {
- if (!CanResolveConstant(constant))
- {
- if (log)
- log->Printf("Unsupported constant: %s", PrintValue(constant).c_str());
- error.SetErrorString(unsupported_operand_error);
- return false;
- }
- }
- }
- }
-
+ switch (type_size) {
+ case 1:
+ scalar = (uint8_t)u64value;
+ break;
+ case 2:
+ scalar = (uint16_t)u64value;
+ break;
+ case 4:
+ scalar = (uint32_t)u64value;
+ break;
+ case 8:
+ scalar = (uint64_t)u64value;
+ break;
+ default:
+ return false;
}
return true;
-}
+ }
-bool
-IRInterpreter::Interpret (llvm::Module &module,
- llvm::Function &function,
- llvm::ArrayRef<lldb::addr_t> args,
- lldb_private::IRExecutionUnit &execution_unit,
- lldb_private::Error &error,
- lldb::addr_t stack_frame_bottom,
- lldb::addr_t stack_frame_top,
- lldb_private::ExecutionContext &exe_ctx)
-{
- lldb_private::Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
+ bool EvaluateValue(lldb_private::Scalar &scalar, const Value *value,
+ Module &module) {
+ const Constant *constant = dyn_cast<Constant>(value);
- if (log)
- {
- std::string s;
- raw_string_ostream oss(s);
+ if (constant) {
+ APInt value_apint;
- module.print(oss, NULL);
-
- oss.flush();
-
- log->Printf("Module as passed in to IRInterpreter::Interpret: \n\"%s\"", s.c_str());
- }
-
- DataLayout data_layout(&module);
-
- InterpreterStackFrame frame(data_layout, execution_unit, stack_frame_bottom, stack_frame_top);
-
- if (frame.m_frame_process_address == LLDB_INVALID_ADDRESS)
- {
- error.SetErrorString("Couldn't allocate stack frame");
- }
-
- int arg_index = 0;
-
- for (llvm::Function::arg_iterator ai = function.arg_begin(), ae = function.arg_end();
- ai != ae;
- ++ai, ++arg_index)
- {
- if (args.size() <= static_cast<size_t>(arg_index))
- {
- error.SetErrorString ("Not enough arguments passed in to function");
- return false;
- }
-
- lldb::addr_t ptr = args[arg_index];
-
- frame.MakeArgument(&*ai, ptr);
- }
-
- uint32_t num_insts = 0;
-
- frame.Jump(&function.front());
-
- while (frame.m_ii != frame.m_ie && (++num_insts < 4096))
- {
- const Instruction *inst = &*frame.m_ii;
-
- if (log)
- log->Printf("Interpreting %s", PrintValue(inst).c_str());
-
- switch (inst->getOpcode())
- {
- default:
- break;
-
- case Instruction::Add:
- case Instruction::Sub:
- case Instruction::Mul:
- case Instruction::SDiv:
- case Instruction::UDiv:
- case Instruction::SRem:
- case Instruction::URem:
- case Instruction::Shl:
- case Instruction::LShr:
- case Instruction::AShr:
- case Instruction::And:
- case Instruction::Or:
- case Instruction::Xor:
- {
- const BinaryOperator *bin_op = dyn_cast<BinaryOperator>(inst);
-
- if (!bin_op)
- {
- if (log)
- log->Printf("getOpcode() returns %s, but instruction is not a BinaryOperator", inst->getOpcodeName());
- error.SetErrorToGenericError();
- error.SetErrorString(interpreter_internal_error);
- return false;
- }
-
- Value *lhs = inst->getOperand(0);
- Value *rhs = inst->getOperand(1);
-
- lldb_private::Scalar L;
- lldb_private::Scalar R;
-
- if (!frame.EvaluateValue(L, lhs, module))
- {
- if (log)
- log->Printf("Couldn't evaluate %s", PrintValue(lhs).c_str());
- error.SetErrorToGenericError();
- error.SetErrorString(bad_value_error);
- return false;
- }
-
- if (!frame.EvaluateValue(R, rhs, module))
- {
- if (log)
- log->Printf("Couldn't evaluate %s", PrintValue(rhs).c_str());
- error.SetErrorToGenericError();
- error.SetErrorString(bad_value_error);
- return false;
- }
-
- lldb_private::Scalar result;
-
- switch (inst->getOpcode())
- {
- default:
- break;
- case Instruction::Add:
- result = L + R;
- break;
- case Instruction::Mul:
- result = L * R;
- break;
- case Instruction::Sub:
- result = L - R;
- break;
- case Instruction::SDiv:
- L.MakeSigned();
- R.MakeSigned();
- result = L / R;
- break;
- case Instruction::UDiv:
- L.MakeUnsigned();
- R.MakeUnsigned();
- result = L / R;
- break;
- case Instruction::SRem:
- L.MakeSigned();
- R.MakeSigned();
- result = L % R;
- break;
- case Instruction::URem:
- L.MakeUnsigned();
- R.MakeUnsigned();
- result = L % R;
- break;
- case Instruction::Shl:
- result = L << R;
- break;
- case Instruction::AShr:
- result = L >> R;
- break;
- case Instruction::LShr:
- result = L;
- result.ShiftRightLogical(R);
- break;
- case Instruction::And:
- result = L & R;
- break;
- case Instruction::Or:
- result = L | R;
- break;
- case Instruction::Xor:
- result = L ^ R;
- break;
- }
-
- frame.AssignValue(inst, result, module);
-
- if (log)
- {
- log->Printf("Interpreted a %s", inst->getOpcodeName());
- log->Printf(" L : %s", frame.SummarizeValue(lhs).c_str());
- log->Printf(" R : %s", frame.SummarizeValue(rhs).c_str());
- log->Printf(" = : %s", frame.SummarizeValue(inst).c_str());
- }
- }
- break;
- case Instruction::Alloca:
- {
- const AllocaInst *alloca_inst = dyn_cast<AllocaInst>(inst);
-
- if (!alloca_inst)
- {
- if (log)
- log->Printf("getOpcode() returns Alloca, but instruction is not an AllocaInst");
- error.SetErrorToGenericError();
- error.SetErrorString(interpreter_internal_error);
- return false;
- }
-
- if (alloca_inst->isArrayAllocation())
- {
- if (log)
- log->Printf("AllocaInsts are not handled if isArrayAllocation() is true");
- error.SetErrorToGenericError();
- error.SetErrorString(unsupported_opcode_error);
- return false;
- }
-
- // The semantics of Alloca are:
- // Create a region R of virtual memory of type T, backed by a data buffer
- // Create a region P of virtual memory of type T*, backed by a data buffer
- // Write the virtual address of R into P
-
- Type *T = alloca_inst->getAllocatedType();
- Type *Tptr = alloca_inst->getType();
-
- lldb::addr_t R = frame.Malloc(T);
-
- if (R == LLDB_INVALID_ADDRESS)
- {
- if (log)
- log->Printf("Couldn't allocate memory for an AllocaInst");
- error.SetErrorToGenericError();
- error.SetErrorString(memory_allocation_error);
- return false;
- }
-
- lldb::addr_t P = frame.Malloc(Tptr);
-
- if (P == LLDB_INVALID_ADDRESS)
- {
- if (log)
- log->Printf("Couldn't allocate the result pointer for an AllocaInst");
- error.SetErrorToGenericError();
- error.SetErrorString(memory_allocation_error);
- return false;
- }
-
- lldb_private::Error write_error;
-
- execution_unit.WritePointerToMemory(P, R, write_error);
-
- if (!write_error.Success())
- {
- if (log)
- log->Printf("Couldn't write the result pointer for an AllocaInst");
- error.SetErrorToGenericError();
- error.SetErrorString(memory_write_error);
- lldb_private::Error free_error;
- execution_unit.Free(P, free_error);
- execution_unit.Free(R, free_error);
- return false;
- }
-
- frame.m_values[alloca_inst] = P;
-
- if (log)
- {
- log->Printf("Interpreted an AllocaInst");
- log->Printf(" R : 0x%" PRIx64, R);
- log->Printf(" P : 0x%" PRIx64, P);
- }
- }
- break;
- case Instruction::BitCast:
- case Instruction::ZExt:
- {
- const CastInst *cast_inst = dyn_cast<CastInst>(inst);
-
- if (!cast_inst)
- {
- if (log)
- log->Printf("getOpcode() returns %s, but instruction is not a BitCastInst", cast_inst->getOpcodeName());
- error.SetErrorToGenericError();
- error.SetErrorString(interpreter_internal_error);
- return false;
- }
-
- Value *source = cast_inst->getOperand(0);
-
- lldb_private::Scalar S;
-
- if (!frame.EvaluateValue(S, source, module))
- {
- if (log)
- log->Printf("Couldn't evaluate %s", PrintValue(source).c_str());
- error.SetErrorToGenericError();
- error.SetErrorString(bad_value_error);
- return false;
- }
-
- frame.AssignValue(inst, S, module);
- }
- break;
- case Instruction::SExt:
- {
- const CastInst *cast_inst = dyn_cast<CastInst>(inst);
-
- if (!cast_inst)
- {
- if (log)
- log->Printf("getOpcode() returns %s, but instruction is not a BitCastInst", cast_inst->getOpcodeName());
- error.SetErrorToGenericError();
- error.SetErrorString(interpreter_internal_error);
- return false;
- }
-
- Value *source = cast_inst->getOperand(0);
-
- lldb_private::Scalar S;
-
- if (!frame.EvaluateValue(S, source, module))
- {
- if (log)
- log->Printf("Couldn't evaluate %s", PrintValue(source).c_str());
- error.SetErrorToGenericError();
- error.SetErrorString(bad_value_error);
- return false;
- }
-
- S.MakeSigned();
-
- lldb_private::Scalar S_signextend(S.SLongLong());
-
- frame.AssignValue(inst, S_signextend, module);
- }
- break;
- case Instruction::Br:
- {
- const BranchInst *br_inst = dyn_cast<BranchInst>(inst);
-
- if (!br_inst)
- {
- if (log)
- log->Printf("getOpcode() returns Br, but instruction is not a BranchInst");
- error.SetErrorToGenericError();
- error.SetErrorString(interpreter_internal_error);
- return false;
- }
-
- if (br_inst->isConditional())
- {
- Value *condition = br_inst->getCondition();
-
- lldb_private::Scalar C;
-
- if (!frame.EvaluateValue(C, condition, module))
- {
- if (log)
- log->Printf("Couldn't evaluate %s", PrintValue(condition).c_str());
- error.SetErrorToGenericError();
- error.SetErrorString(bad_value_error);
- return false;
- }
-
- if (!C.IsZero())
- frame.Jump(br_inst->getSuccessor(0));
- else
- frame.Jump(br_inst->getSuccessor(1));
-
- if (log)
- {
- log->Printf("Interpreted a BrInst with a condition");
- log->Printf(" cond : %s", frame.SummarizeValue(condition).c_str());
- }
- }
- else
- {
- frame.Jump(br_inst->getSuccessor(0));
-
- if (log)
- {
- log->Printf("Interpreted a BrInst with no condition");
- }
- }
- }
- continue;
- case Instruction::PHI:
- {
- const PHINode *phi_inst = dyn_cast<PHINode>(inst);
-
- if (!phi_inst)
- {
- if (log)
- log->Printf("getOpcode() returns PHI, but instruction is not a PHINode");
- error.SetErrorToGenericError();
- error.SetErrorString(interpreter_internal_error);
- return false;
- }
- if (!frame.m_prev_bb)
- {
- if (log)
- log->Printf("Encountered PHI node without having jumped from another basic block");
- error.SetErrorToGenericError();
- error.SetErrorString(interpreter_internal_error);
- return false;
- }
-
- Value* value = phi_inst->getIncomingValueForBlock(frame.m_prev_bb);
- lldb_private::Scalar result;
- if (!frame.EvaluateValue(result, value, module))
- {
- if (log)
- log->Printf("Couldn't evaluate %s", PrintValue(value).c_str());
- error.SetErrorToGenericError();
- error.SetErrorString(bad_value_error);
- return false;
- }
- frame.AssignValue(inst, result, module);
-
- if (log)
- {
- log->Printf("Interpreted a %s", inst->getOpcodeName());
- log->Printf(" Incoming value : %s", frame.SummarizeValue(value).c_str());
- }
- }
- break;
- case Instruction::GetElementPtr:
- {
- const GetElementPtrInst *gep_inst = dyn_cast<GetElementPtrInst>(inst);
-
- if (!gep_inst)
- {
- if (log)
- log->Printf("getOpcode() returns GetElementPtr, but instruction is not a GetElementPtrInst");
- error.SetErrorToGenericError();
- error.SetErrorString(interpreter_internal_error);
- return false;
- }
-
- const Value *pointer_operand = gep_inst->getPointerOperand();
- Type *src_elem_ty = gep_inst->getSourceElementType();
-
- lldb_private::Scalar P;
-
- if (!frame.EvaluateValue(P, pointer_operand, module))
- {
- if (log)
- log->Printf("Couldn't evaluate %s", PrintValue(pointer_operand).c_str());
- error.SetErrorToGenericError();
- error.SetErrorString(bad_value_error);
- return false;
- }
-
- typedef SmallVector <Value *, 8> IndexVector;
- typedef IndexVector::iterator IndexIterator;
-
- SmallVector <Value *, 8> indices (gep_inst->idx_begin(),
- gep_inst->idx_end());
-
- SmallVector <Value *, 8> const_indices;
-
- for (IndexIterator ii = indices.begin(), ie = indices.end();
- ii != ie;
- ++ii)
- {
- ConstantInt *constant_index = dyn_cast<ConstantInt>(*ii);
-
- if (!constant_index)
- {
- lldb_private::Scalar I;
-
- if (!frame.EvaluateValue(I, *ii, module))
- {
- if (log)
- log->Printf("Couldn't evaluate %s", PrintValue(*ii).c_str());
- error.SetErrorToGenericError();
- error.SetErrorString(bad_value_error);
- return false;
- }
-
- if (log)
- log->Printf("Evaluated constant index %s as %llu", PrintValue(*ii).c_str(), I.ULongLong(LLDB_INVALID_ADDRESS));
-
- constant_index = cast<ConstantInt>(ConstantInt::get((*ii)->getType(), I.ULongLong(LLDB_INVALID_ADDRESS)));
- }
-
- const_indices.push_back(constant_index);
- }
-
- uint64_t offset = data_layout.getIndexedOffsetInType(src_elem_ty, const_indices);
-
- lldb_private::Scalar Poffset = P + offset;
-
- frame.AssignValue(inst, Poffset, module);
-
- if (log)
- {
- log->Printf("Interpreted a GetElementPtrInst");
- log->Printf(" P : %s", frame.SummarizeValue(pointer_operand).c_str());
- log->Printf(" Poffset : %s", frame.SummarizeValue(inst).c_str());
- }
- }
- break;
- case Instruction::ICmp:
- {
- const ICmpInst *icmp_inst = dyn_cast<ICmpInst>(inst);
-
- if (!icmp_inst)
- {
- if (log)
- log->Printf("getOpcode() returns ICmp, but instruction is not an ICmpInst");
- error.SetErrorToGenericError();
- error.SetErrorString(interpreter_internal_error);
- return false;
- }
-
- CmpInst::Predicate predicate = icmp_inst->getPredicate();
-
- Value *lhs = inst->getOperand(0);
- Value *rhs = inst->getOperand(1);
-
- lldb_private::Scalar L;
- lldb_private::Scalar R;
-
- if (!frame.EvaluateValue(L, lhs, module))
- {
- if (log)
- log->Printf("Couldn't evaluate %s", PrintValue(lhs).c_str());
- error.SetErrorToGenericError();
- error.SetErrorString(bad_value_error);
- return false;
- }
-
- if (!frame.EvaluateValue(R, rhs, module))
- {
- if (log)
- log->Printf("Couldn't evaluate %s", PrintValue(rhs).c_str());
- error.SetErrorToGenericError();
- error.SetErrorString(bad_value_error);
- return false;
- }
-
- lldb_private::Scalar result;
-
- switch (predicate)
- {
- default:
- return false;
- case CmpInst::ICMP_EQ:
- result = (L == R);
- break;
- case CmpInst::ICMP_NE:
- result = (L != R);
- break;
- case CmpInst::ICMP_UGT:
- L.MakeUnsigned();
- R.MakeUnsigned();
- result = (L > R);
- break;
- case CmpInst::ICMP_UGE:
- L.MakeUnsigned();
- R.MakeUnsigned();
- result = (L >= R);
- break;
- case CmpInst::ICMP_ULT:
- L.MakeUnsigned();
- R.MakeUnsigned();
- result = (L < R);
- break;
- case CmpInst::ICMP_ULE:
- L.MakeUnsigned();
- R.MakeUnsigned();
- result = (L <= R);
- break;
- case CmpInst::ICMP_SGT:
- L.MakeSigned();
- R.MakeSigned();
- result = (L > R);
- break;
- case CmpInst::ICMP_SGE:
- L.MakeSigned();
- R.MakeSigned();
- result = (L >= R);
- break;
- case CmpInst::ICMP_SLT:
- L.MakeSigned();
- R.MakeSigned();
- result = (L < R);
- break;
- case CmpInst::ICMP_SLE:
- L.MakeSigned();
- R.MakeSigned();
- result = (L <= R);
- break;
- }
-
- frame.AssignValue(inst, result, module);
-
- if (log)
- {
- log->Printf("Interpreted an ICmpInst");
- log->Printf(" L : %s", frame.SummarizeValue(lhs).c_str());
- log->Printf(" R : %s", frame.SummarizeValue(rhs).c_str());
- log->Printf(" = : %s", frame.SummarizeValue(inst).c_str());
- }
- }
- break;
- case Instruction::IntToPtr:
- {
- const IntToPtrInst *int_to_ptr_inst = dyn_cast<IntToPtrInst>(inst);
-
- if (!int_to_ptr_inst)
- {
- if (log)
- log->Printf("getOpcode() returns IntToPtr, but instruction is not an IntToPtrInst");
- error.SetErrorToGenericError();
- error.SetErrorString(interpreter_internal_error);
- return false;
- }
-
- Value *src_operand = int_to_ptr_inst->getOperand(0);
-
- lldb_private::Scalar I;
-
- if (!frame.EvaluateValue(I, src_operand, module))
- {
- if (log)
- log->Printf("Couldn't evaluate %s", PrintValue(src_operand).c_str());
- error.SetErrorToGenericError();
- error.SetErrorString(bad_value_error);
- return false;
- }
-
- frame.AssignValue(inst, I, module);
-
- if (log)
- {
- log->Printf("Interpreted an IntToPtr");
- log->Printf(" Src : %s", frame.SummarizeValue(src_operand).c_str());
- log->Printf(" = : %s", frame.SummarizeValue(inst).c_str());
- }
- }
- break;
- case Instruction::PtrToInt:
- {
- const PtrToIntInst *ptr_to_int_inst = dyn_cast<PtrToIntInst>(inst);
-
- if (!ptr_to_int_inst)
- {
- if (log)
- log->Printf("getOpcode() returns PtrToInt, but instruction is not an PtrToIntInst");
- error.SetErrorToGenericError();
- error.SetErrorString(interpreter_internal_error);
- return false;
- }
-
- Value *src_operand = ptr_to_int_inst->getOperand(0);
-
- lldb_private::Scalar I;
-
- if (!frame.EvaluateValue(I, src_operand, module))
- {
- if (log)
- log->Printf("Couldn't evaluate %s", PrintValue(src_operand).c_str());
- error.SetErrorToGenericError();
- error.SetErrorString(bad_value_error);
- return false;
- }
-
- frame.AssignValue(inst, I, module);
-
- if (log)
- {
- log->Printf("Interpreted a PtrToInt");
- log->Printf(" Src : %s", frame.SummarizeValue(src_operand).c_str());
- log->Printf(" = : %s", frame.SummarizeValue(inst).c_str());
- }
- }
- break;
- case Instruction::Trunc:
- {
- const TruncInst *trunc_inst = dyn_cast<TruncInst>(inst);
-
- if (!trunc_inst)
- {
- if (log)
- log->Printf("getOpcode() returns Trunc, but instruction is not a TruncInst");
- error.SetErrorToGenericError();
- error.SetErrorString(interpreter_internal_error);
- return false;
- }
-
- Value *src_operand = trunc_inst->getOperand(0);
-
- lldb_private::Scalar I;
-
- if (!frame.EvaluateValue(I, src_operand, module))
- {
- if (log)
- log->Printf("Couldn't evaluate %s", PrintValue(src_operand).c_str());
- error.SetErrorToGenericError();
- error.SetErrorString(bad_value_error);
- return false;
- }
-
- frame.AssignValue(inst, I, module);
-
- if (log)
- {
- log->Printf("Interpreted a Trunc");
- log->Printf(" Src : %s", frame.SummarizeValue(src_operand).c_str());
- log->Printf(" = : %s", frame.SummarizeValue(inst).c_str());
- }
- }
- break;
- case Instruction::Load:
- {
- const LoadInst *load_inst = dyn_cast<LoadInst>(inst);
-
- if (!load_inst)
- {
- if (log)
- log->Printf("getOpcode() returns Load, but instruction is not a LoadInst");
- error.SetErrorToGenericError();
- error.SetErrorString(interpreter_internal_error);
- return false;
- }
-
- // The semantics of Load are:
- // Create a region D that will contain the loaded data
- // Resolve the region P containing a pointer
- // Dereference P to get the region R that the data should be loaded from
- // Transfer a unit of type type(D) from R to D
-
- const Value *pointer_operand = load_inst->getPointerOperand();
-
- Type *pointer_ty = pointer_operand->getType();
- PointerType *pointer_ptr_ty = dyn_cast<PointerType>(pointer_ty);
- if (!pointer_ptr_ty)
- {
- if (log)
- log->Printf("getPointerOperand()->getType() is not a PointerType");
- error.SetErrorToGenericError();
- error.SetErrorString(interpreter_internal_error);
- return false;
- }
- Type *target_ty = pointer_ptr_ty->getElementType();
-
- lldb::addr_t D = frame.ResolveValue(load_inst, module);
- lldb::addr_t P = frame.ResolveValue(pointer_operand, module);
-
- if (D == LLDB_INVALID_ADDRESS)
- {
- if (log)
- log->Printf("LoadInst's value doesn't resolve to anything");
- error.SetErrorToGenericError();
- error.SetErrorString(bad_value_error);
- return false;
- }
-
- if (P == LLDB_INVALID_ADDRESS)
- {
- if (log)
- log->Printf("LoadInst's pointer doesn't resolve to anything");
- error.SetErrorToGenericError();
- error.SetErrorString(bad_value_error);
- return false;
- }
-
- lldb::addr_t R;
- lldb_private::Error read_error;
- execution_unit.ReadPointerFromMemory(&R, P, read_error);
-
- if (!read_error.Success())
- {
- if (log)
- log->Printf("Couldn't read the address to be loaded for a LoadInst");
- error.SetErrorToGenericError();
- error.SetErrorString(memory_read_error);
- return false;
- }
-
- size_t target_size = data_layout.getTypeStoreSize(target_ty);
- lldb_private::DataBufferHeap buffer(target_size, 0);
-
- read_error.Clear();
- execution_unit.ReadMemory(buffer.GetBytes(), R, buffer.GetByteSize(), read_error);
- if (!read_error.Success())
- {
- if (log)
- log->Printf("Couldn't read from a region on behalf of a LoadInst");
- error.SetErrorToGenericError();
- error.SetErrorString(memory_read_error);
- return false;
- }
-
- lldb_private::Error write_error;
- execution_unit.WriteMemory(D, buffer.GetBytes(), buffer.GetByteSize(), write_error);
- if (!write_error.Success())
- {
- if (log)
- log->Printf("Couldn't write to a region on behalf of a LoadInst");
- error.SetErrorToGenericError();
- error.SetErrorString(memory_read_error);
- return false;
- }
-
- if (log)
- {
- log->Printf("Interpreted a LoadInst");
- log->Printf(" P : 0x%" PRIx64, P);
- log->Printf(" R : 0x%" PRIx64, R);
- log->Printf(" D : 0x%" PRIx64, D);
- }
- }
- break;
- case Instruction::Ret:
- {
- return true;
- }
- case Instruction::Store:
- {
- const StoreInst *store_inst = dyn_cast<StoreInst>(inst);
-
- if (!store_inst)
- {
- if (log)
- log->Printf("getOpcode() returns Store, but instruction is not a StoreInst");
- error.SetErrorToGenericError();
- error.SetErrorString(interpreter_internal_error);
- return false;
- }
-
- // The semantics of Store are:
- // Resolve the region D containing the data to be stored
- // Resolve the region P containing a pointer
- // Dereference P to get the region R that the data should be stored in
- // Transfer a unit of type type(D) from D to R
-
- const Value *value_operand = store_inst->getValueOperand();
- const Value *pointer_operand = store_inst->getPointerOperand();
-
- Type *pointer_ty = pointer_operand->getType();
- PointerType *pointer_ptr_ty = dyn_cast<PointerType>(pointer_ty);
- if (!pointer_ptr_ty)
- return false;
- Type *target_ty = pointer_ptr_ty->getElementType();
-
- lldb::addr_t D = frame.ResolveValue(value_operand, module);
- lldb::addr_t P = frame.ResolveValue(pointer_operand, module);
-
- if (D == LLDB_INVALID_ADDRESS)
- {
- if (log)
- log->Printf("StoreInst's value doesn't resolve to anything");
- error.SetErrorToGenericError();
- error.SetErrorString(bad_value_error);
- return false;
- }
-
- if (P == LLDB_INVALID_ADDRESS)
- {
- if (log)
- log->Printf("StoreInst's pointer doesn't resolve to anything");
- error.SetErrorToGenericError();
- error.SetErrorString(bad_value_error);
- return false;
- }
-
- lldb::addr_t R;
- lldb_private::Error read_error;
- execution_unit.ReadPointerFromMemory(&R, P, read_error);
-
- if (!read_error.Success())
- {
- if (log)
- log->Printf("Couldn't read the address to be loaded for a LoadInst");
- error.SetErrorToGenericError();
- error.SetErrorString(memory_read_error);
- return false;
- }
-
- size_t target_size = data_layout.getTypeStoreSize(target_ty);
- lldb_private::DataBufferHeap buffer(target_size, 0);
-
- read_error.Clear();
- execution_unit.ReadMemory(buffer.GetBytes(), D, buffer.GetByteSize(), read_error);
- if (!read_error.Success())
- {
- if (log)
- log->Printf("Couldn't read from a region on behalf of a StoreInst");
- error.SetErrorToGenericError();
- error.SetErrorString(memory_read_error);
- return false;
- }
-
- lldb_private::Error write_error;
- execution_unit.WriteMemory(R, buffer.GetBytes(), buffer.GetByteSize(), write_error);
- if (!write_error.Success())
- {
- if (log)
- log->Printf("Couldn't write to a region on behalf of a StoreInst");
- error.SetErrorToGenericError();
- error.SetErrorString(memory_write_error);
- return false;
- }
-
- if (log)
- {
- log->Printf("Interpreted a StoreInst");
- log->Printf(" D : 0x%" PRIx64, D);
- log->Printf(" P : 0x%" PRIx64, P);
- log->Printf(" R : 0x%" PRIx64, R);
- }
- }
- break;
- case Instruction::Call:
- {
- const CallInst *call_inst = dyn_cast<CallInst>(inst);
-
- if (!call_inst)
- {
- if (log)
- log->Printf("getOpcode() returns %s, but instruction is not a CallInst", inst->getOpcodeName());
- error.SetErrorToGenericError();
- error.SetErrorString(interpreter_internal_error);
- return false;
- }
-
- if (CanIgnoreCall(call_inst))
- break;
-
- // Get the return type
- llvm::Type *returnType = call_inst->getType();
- if (returnType == nullptr)
- {
- error.SetErrorToGenericError();
- error.SetErrorString("unable to access return type");
- return false;
- }
-
- // Work with void, integer and pointer return types
- if (!returnType->isVoidTy() &&
- !returnType->isIntegerTy() &&
- !returnType->isPointerTy())
- {
- error.SetErrorToGenericError();
- error.SetErrorString("return type is not supported");
- return false;
- }
-
- // Check we can actually get a thread
- if (exe_ctx.GetThreadPtr() == nullptr)
- {
- error.SetErrorToGenericError();
- error.SetErrorStringWithFormat("unable to acquire thread");
- return false;
- }
-
- // Make sure we have a valid process
- if (!exe_ctx.GetProcessPtr())
- {
- error.SetErrorToGenericError();
- error.SetErrorStringWithFormat("unable to get the process");
- return false;
- }
-
- // Find the address of the callee function
- lldb_private::Scalar I;
- const llvm::Value *val = call_inst->getCalledValue();
-
- if (!frame.EvaluateValue(I, val, module))
- {
- error.SetErrorToGenericError();
- error.SetErrorString("unable to get address of function");
- return false;
- }
- lldb_private::Address funcAddr(I.ULongLong(LLDB_INVALID_ADDRESS));
-
- lldb_private::DiagnosticManager diagnostics;
- lldb_private::EvaluateExpressionOptions options;
-
- // We generally receive a function pointer which we must dereference
- llvm::Type* prototype = val->getType();
- if (!prototype->isPointerTy())
- {
- error.SetErrorToGenericError();
- error.SetErrorString("call need function pointer");
- return false;
- }
-
- // Dereference the function pointer
- prototype = prototype->getPointerElementType();
- if (!(prototype->isFunctionTy() || prototype->isFunctionVarArg()))
- {
- error.SetErrorToGenericError();
- error.SetErrorString("call need function pointer");
- return false;
- }
-
- // Find number of arguments
- const int numArgs = call_inst->getNumArgOperands();
-
- // We work with a fixed array of 16 arguments which is our upper limit
- static lldb_private::ABI::CallArgument rawArgs[16];
- if (numArgs >= 16)
- {
- error.SetErrorToGenericError();
- error.SetErrorStringWithFormat("function takes too many arguments");
- return false;
- }
-
- // Push all function arguments to the argument list that will
- // be passed to the call function thread plan
- for (int i = 0; i < numArgs; i++)
- {
- // Get details of this argument
- llvm::Value *arg_op = call_inst->getArgOperand(i);
- llvm::Type *arg_ty = arg_op->getType();
-
- // Ensure that this argument is an supported type
- if (!arg_ty->isIntegerTy() && !arg_ty->isPointerTy())
- {
- error.SetErrorToGenericError();
- error.SetErrorStringWithFormat("argument %d must be integer type", i);
- return false;
- }
-
- // Extract the arguments value
- lldb_private::Scalar tmp_op = 0;
- if (!frame.EvaluateValue(tmp_op, arg_op, module))
- {
- error.SetErrorToGenericError();
- error.SetErrorStringWithFormat("unable to evaluate argument %d", i);
- return false;
- }
-
- // Check if this is a string literal or constant string pointer
- if (arg_ty->isPointerTy())
- {
- // Pointer to just one type
- assert(arg_ty->getNumContainedTypes() == 1);
-
- lldb::addr_t addr = tmp_op.ULongLong();
- size_t dataSize = 0;
-
- if (execution_unit.GetAllocSize(addr, dataSize))
- {
- // Create the required buffer
- rawArgs[i].size = dataSize;
- rawArgs[i].data_ap.reset(new uint8_t[dataSize + 1]);
-
- // Read string from host memory
- execution_unit.ReadMemory(rawArgs[i].data_ap.get(), addr, dataSize, error);
- if (error.Fail())
- {
- assert(!"we have failed to read the string from memory");
- return false;
- }
- // Add null terminator
- rawArgs[i].data_ap[dataSize] = '\0';
- rawArgs[i].type = lldb_private::ABI::CallArgument::HostPointer;
- }
- else
- {
- assert(!"unable to locate host data for transfer to device");
- return false;
- }
- }
- else /* if ( arg_ty->isPointerTy() ) */
- {
- rawArgs[i].type = lldb_private::ABI::CallArgument::TargetValue;
- // Get argument size in bytes
- rawArgs[i].size = arg_ty->getIntegerBitWidth() / 8;
- // Push value into argument list for thread plan
- rawArgs[i].value = tmp_op.ULongLong();
- }
-
- }
-
- // Pack the arguments into an llvm::array
- llvm::ArrayRef<lldb_private::ABI::CallArgument> args(rawArgs, numArgs);
-
- // Setup a thread plan to call the target function
- lldb::ThreadPlanSP call_plan_sp(new lldb_private::ThreadPlanCallFunctionUsingABI(
- exe_ctx.GetThreadRef(), funcAddr, *prototype, *returnType, args, options));
-
- // Check if the plan is valid
- lldb_private::StreamString ss;
- if (!call_plan_sp || !call_plan_sp->ValidatePlan(&ss))
- {
- error.SetErrorToGenericError();
- error.SetErrorStringWithFormat("unable to make ThreadPlanCallFunctionUsingABI for 0x%llx",
- I.ULongLong());
- return false;
- }
-
- exe_ctx.GetProcessPtr()->SetRunningUserExpression(true);
-
- // Execute the actual function call thread plan
- lldb::ExpressionResults res =
- exe_ctx.GetProcessRef().RunThreadPlan(exe_ctx, call_plan_sp, options, diagnostics);
-
- // Check that the thread plan completed successfully
- if (res != lldb::ExpressionResults::eExpressionCompleted)
- {
- error.SetErrorToGenericError();
- error.SetErrorStringWithFormat("ThreadPlanCallFunctionUsingABI failed");
- return false;
- }
-
- exe_ctx.GetProcessPtr()->SetRunningUserExpression(false);
-
- // Void return type
- if (returnType->isVoidTy())
- {
- // Cant assign to void types, so we leave the frame untouched
- }
- else
- // Integer or pointer return type
- if (returnType->isIntegerTy() || returnType->isPointerTy())
- {
- // Get the encapsulated return value
- lldb::ValueObjectSP retVal = call_plan_sp.get()->GetReturnValueObject();
-
- lldb_private::Scalar returnVal = -1;
- lldb_private::ValueObject *vobj = retVal.get();
-
- // Check if the return value is valid
- if (vobj == nullptr || retVal.empty())
- {
- error.SetErrorToGenericError();
- error.SetErrorStringWithFormat("unable to get the return value");
- return false;
- }
-
- // Extract the return value as a integer
- lldb_private::Value & value = vobj->GetValue();
- returnVal = value.GetScalar();
-
- // Push the return value as the result
- frame.AssignValue(inst, returnVal, module);
- }
- }
- break;
- }
-
- ++frame.m_ii;
- }
-
- if (num_insts >= 4096)
- {
- error.SetErrorToGenericError();
- error.SetErrorString(infinite_loop_error);
+ if (!ResolveConstantValue(value_apint, constant))
return false;
+
+ return AssignToMatchType(scalar, value_apint.getLimitedValue(),
+ value->getType());
+ } else {
+ lldb::addr_t process_address = ResolveValue(value, module);
+ size_t value_size = m_target_data.getTypeStoreSize(value->getType());
+
+ lldb_private::DataExtractor value_extractor;
+ lldb_private::Error extract_error;
+
+ m_execution_unit.GetMemoryData(value_extractor, process_address,
+ value_size, extract_error);
+
+ if (!extract_error.Success())
+ return false;
+
+ lldb::offset_t offset = 0;
+ if (value_size == 1 || value_size == 2 || value_size == 4 ||
+ value_size == 8) {
+ uint64_t u64value = value_extractor.GetMaxU64(&offset, value_size);
+ return AssignToMatchType(scalar, u64value, value->getType());
+ }
}
return false;
+ }
+
+ bool AssignValue(const Value *value, lldb_private::Scalar &scalar,
+ Module &module) {
+ lldb::addr_t process_address = ResolveValue(value, module);
+
+ if (process_address == LLDB_INVALID_ADDRESS)
+ return false;
+
+ lldb_private::Scalar cast_scalar;
+
+ if (!AssignToMatchType(cast_scalar, scalar.ULongLong(), value->getType()))
+ return false;
+
+ size_t value_byte_size = m_target_data.getTypeStoreSize(value->getType());
+
+ lldb_private::DataBufferHeap buf(value_byte_size, 0);
+
+ lldb_private::Error get_data_error;
+
+ if (!cast_scalar.GetAsMemoryData(buf.GetBytes(), buf.GetByteSize(),
+ m_byte_order, get_data_error))
+ return false;
+
+ lldb_private::Error write_error;
+
+ m_execution_unit.WriteMemory(process_address, buf.GetBytes(),
+ buf.GetByteSize(), write_error);
+
+ return write_error.Success();
+ }
+
+ bool ResolveConstantValue(APInt &value, const Constant *constant) {
+ switch (constant->getValueID()) {
+ default:
+ break;
+ case Value::FunctionVal:
+ if (const Function *constant_func = dyn_cast<Function>(constant)) {
+ lldb_private::ConstString name(constant_func->getName());
+ lldb::addr_t addr = m_execution_unit.FindSymbol(name);
+ if (addr == LLDB_INVALID_ADDRESS)
+ return false;
+ value = APInt(m_target_data.getPointerSizeInBits(), addr);
+ return true;
+ }
+ break;
+ case Value::ConstantIntVal:
+ if (const ConstantInt *constant_int = dyn_cast<ConstantInt>(constant)) {
+ value = constant_int->getValue();
+ return true;
+ }
+ break;
+ case Value::ConstantFPVal:
+ if (const ConstantFP *constant_fp = dyn_cast<ConstantFP>(constant)) {
+ value = constant_fp->getValueAPF().bitcastToAPInt();
+ return true;
+ }
+ break;
+ case Value::ConstantExprVal:
+ if (const ConstantExpr *constant_expr =
+ dyn_cast<ConstantExpr>(constant)) {
+ switch (constant_expr->getOpcode()) {
+ default:
+ return false;
+ case Instruction::IntToPtr:
+ case Instruction::PtrToInt:
+ case Instruction::BitCast:
+ return ResolveConstantValue(value, constant_expr->getOperand(0));
+ case Instruction::GetElementPtr: {
+ ConstantExpr::const_op_iterator op_cursor = constant_expr->op_begin();
+ ConstantExpr::const_op_iterator op_end = constant_expr->op_end();
+
+ Constant *base = dyn_cast<Constant>(*op_cursor);
+
+ if (!base)
+ return false;
+
+ if (!ResolveConstantValue(value, base))
+ return false;
+
+ op_cursor++;
+
+ if (op_cursor == op_end)
+ return true; // no offset to apply!
+
+ SmallVector<Value *, 8> indices(op_cursor, op_end);
+
+ Type *src_elem_ty =
+ cast<GEPOperator>(constant_expr)->getSourceElementType();
+ uint64_t offset =
+ m_target_data.getIndexedOffsetInType(src_elem_ty, indices);
+
+ const bool is_signed = true;
+ value += APInt(value.getBitWidth(), offset, is_signed);
+
+ return true;
+ }
+ }
+ }
+ break;
+ case Value::ConstantPointerNullVal:
+ if (isa<ConstantPointerNull>(constant)) {
+ value = APInt(m_target_data.getPointerSizeInBits(), 0);
+ return true;
+ }
+ break;
+ }
+ return false;
+ }
+
+ bool MakeArgument(const Argument *value, uint64_t address) {
+ lldb::addr_t data_address = Malloc(value->getType());
+
+ if (data_address == LLDB_INVALID_ADDRESS)
+ return false;
+
+ lldb_private::Error write_error;
+
+ m_execution_unit.WritePointerToMemory(data_address, address, write_error);
+
+ if (!write_error.Success()) {
+ lldb_private::Error free_error;
+ m_execution_unit.Free(data_address, free_error);
+ return false;
+ }
+
+ m_values[value] = data_address;
+
+ lldb_private::Log *log(
+ lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS));
+
+ if (log) {
+ log->Printf("Made an allocation for argument %s",
+ PrintValue(value).c_str());
+ log->Printf(" Data region : %llx", (unsigned long long)address);
+ log->Printf(" Ref region : %llx", (unsigned long long)data_address);
+ }
+
+ return true;
+ }
+
+ bool ResolveConstant(lldb::addr_t process_address, const Constant *constant) {
+ APInt resolved_value;
+
+ if (!ResolveConstantValue(resolved_value, constant))
+ return false;
+
+ size_t constant_size = m_target_data.getTypeStoreSize(constant->getType());
+ lldb_private::DataBufferHeap buf(constant_size, 0);
+
+ lldb_private::Error get_data_error;
+
+ lldb_private::Scalar resolved_scalar(
+ resolved_value.zextOrTrunc(llvm::NextPowerOf2(constant_size) * 8));
+ if (!resolved_scalar.GetAsMemoryData(buf.GetBytes(), buf.GetByteSize(),
+ m_byte_order, get_data_error))
+ return false;
+
+ lldb_private::Error write_error;
+
+ m_execution_unit.WriteMemory(process_address, buf.GetBytes(),
+ buf.GetByteSize(), write_error);
+
+ return write_error.Success();
+ }
+
+ lldb::addr_t Malloc(size_t size, uint8_t byte_alignment) {
+ lldb::addr_t ret = m_stack_pointer;
+
+ ret -= size;
+ ret -= (ret % byte_alignment);
+
+ if (ret < m_frame_process_address)
+ return LLDB_INVALID_ADDRESS;
+
+ m_stack_pointer = ret;
+ return ret;
+ }
+
+ lldb::addr_t MallocPointer() {
+ return Malloc(m_target_data.getPointerSize(),
+ m_target_data.getPointerPrefAlignment());
+ }
+
+ lldb::addr_t Malloc(llvm::Type *type) {
+ lldb_private::Error alloc_error;
+
+ return Malloc(m_target_data.getTypeAllocSize(type),
+ m_target_data.getPrefTypeAlignment(type));
+ }
+
+ std::string PrintData(lldb::addr_t addr, llvm::Type *type) {
+ size_t length = m_target_data.getTypeStoreSize(type);
+
+ lldb_private::DataBufferHeap buf(length, 0);
+
+ lldb_private::Error read_error;
+
+ m_execution_unit.ReadMemory(buf.GetBytes(), addr, length, read_error);
+
+ if (!read_error.Success())
+ return std::string("<couldn't read data>");
+
+ lldb_private::StreamString ss;
+
+ for (size_t i = 0; i < length; i++) {
+ if ((!(i & 0xf)) && i)
+ ss.Printf("%02hhx - ", buf.GetBytes()[i]);
+ else
+ ss.Printf("%02hhx ", buf.GetBytes()[i]);
+ }
+
+ return ss.GetString();
+ }
+
+ lldb::addr_t ResolveValue(const Value *value, Module &module) {
+ ValueMap::iterator i = m_values.find(value);
+
+ if (i != m_values.end())
+ return i->second;
+
+ // Fall back and allocate space [allocation type Alloca]
+
+ lldb::addr_t data_address = Malloc(value->getType());
+
+ if (const Constant *constant = dyn_cast<Constant>(value)) {
+ if (!ResolveConstant(data_address, constant)) {
+ lldb_private::Error free_error;
+ m_execution_unit.Free(data_address, free_error);
+ return LLDB_INVALID_ADDRESS;
+ }
+ }
+
+ m_values[value] = data_address;
+ return data_address;
+ }
+};
+
+static const char *unsupported_opcode_error =
+ "Interpreter doesn't handle one of the expression's opcodes";
+static const char *unsupported_operand_error =
+ "Interpreter doesn't handle one of the expression's operands";
+// static const char *interpreter_initialization_error = "Interpreter couldn't
+// be initialized";
+static const char *interpreter_internal_error =
+ "Interpreter encountered an internal error";
+static const char *bad_value_error =
+ "Interpreter couldn't resolve a value during execution";
+static const char *memory_allocation_error =
+ "Interpreter couldn't allocate memory";
+static const char *memory_write_error = "Interpreter couldn't write to memory";
+static const char *memory_read_error = "Interpreter couldn't read from memory";
+static const char *infinite_loop_error = "Interpreter ran for too many cycles";
+// static const char *bad_result_error = "Result of expression
+// is in bad memory";
+static const char *too_many_functions_error =
+ "Interpreter doesn't handle modules with multiple function bodies.";
+
+static bool CanResolveConstant(llvm::Constant *constant) {
+ switch (constant->getValueID()) {
+ default:
+ return false;
+ case Value::ConstantIntVal:
+ case Value::ConstantFPVal:
+ case Value::FunctionVal:
+ return true;
+ case Value::ConstantExprVal:
+ if (const ConstantExpr *constant_expr = dyn_cast<ConstantExpr>(constant)) {
+ switch (constant_expr->getOpcode()) {
+ default:
+ return false;
+ case Instruction::IntToPtr:
+ case Instruction::PtrToInt:
+ case Instruction::BitCast:
+ return CanResolveConstant(constant_expr->getOperand(0));
+ case Instruction::GetElementPtr: {
+ ConstantExpr::const_op_iterator op_cursor = constant_expr->op_begin();
+ Constant *base = dyn_cast<Constant>(*op_cursor);
+ if (!base)
+ return false;
+
+ return CanResolveConstant(base);
+ }
+ }
+ } else {
+ return false;
+ }
+ case Value::ConstantPointerNullVal:
+ return true;
+ }
+}
+
+bool IRInterpreter::CanInterpret(llvm::Module &module, llvm::Function &function,
+ lldb_private::Error &error,
+ const bool support_function_calls) {
+ lldb_private::Log *log(
+ lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS));
+
+ bool saw_function_with_body = false;
+
+ for (Module::iterator fi = module.begin(), fe = module.end(); fi != fe;
+ ++fi) {
+ if (fi->begin() != fi->end()) {
+ if (saw_function_with_body) {
+ if (log)
+ log->Printf("More than one function in the module has a body");
+ error.SetErrorToGenericError();
+ error.SetErrorString(too_many_functions_error);
+ return false;
+ }
+ saw_function_with_body = true;
+ }
+ }
+
+ for (Function::iterator bbi = function.begin(), bbe = function.end();
+ bbi != bbe; ++bbi) {
+ for (BasicBlock::iterator ii = bbi->begin(), ie = bbi->end(); ii != ie;
+ ++ii) {
+ switch (ii->getOpcode()) {
+ default: {
+ if (log)
+ log->Printf("Unsupported instruction: %s", PrintValue(&*ii).c_str());
+ error.SetErrorToGenericError();
+ error.SetErrorString(unsupported_opcode_error);
+ return false;
+ }
+ case Instruction::Add:
+ case Instruction::Alloca:
+ case Instruction::BitCast:
+ case Instruction::Br:
+ case Instruction::PHI:
+ break;
+ case Instruction::Call: {
+ CallInst *call_inst = dyn_cast<CallInst>(ii);
+
+ if (!call_inst) {
+ error.SetErrorToGenericError();
+ error.SetErrorString(interpreter_internal_error);
+ return false;
+ }
+
+ if (!CanIgnoreCall(call_inst) && !support_function_calls) {
+ if (log)
+ log->Printf("Unsupported instruction: %s",
+ PrintValue(&*ii).c_str());
+ error.SetErrorToGenericError();
+ error.SetErrorString(unsupported_opcode_error);
+ return false;
+ }
+ } break;
+ case Instruction::GetElementPtr:
+ break;
+ case Instruction::ICmp: {
+ ICmpInst *icmp_inst = dyn_cast<ICmpInst>(ii);
+
+ if (!icmp_inst) {
+ error.SetErrorToGenericError();
+ error.SetErrorString(interpreter_internal_error);
+ return false;
+ }
+
+ switch (icmp_inst->getPredicate()) {
+ default: {
+ if (log)
+ log->Printf("Unsupported ICmp predicate: %s",
+ PrintValue(&*ii).c_str());
+
+ error.SetErrorToGenericError();
+ error.SetErrorString(unsupported_opcode_error);
+ return false;
+ }
+ case CmpInst::ICMP_EQ:
+ case CmpInst::ICMP_NE:
+ case CmpInst::ICMP_UGT:
+ case CmpInst::ICMP_UGE:
+ case CmpInst::ICMP_ULT:
+ case CmpInst::ICMP_ULE:
+ case CmpInst::ICMP_SGT:
+ case CmpInst::ICMP_SGE:
+ case CmpInst::ICMP_SLT:
+ case CmpInst::ICMP_SLE:
+ break;
+ }
+ } break;
+ case Instruction::And:
+ case Instruction::AShr:
+ case Instruction::IntToPtr:
+ case Instruction::PtrToInt:
+ case Instruction::Load:
+ case Instruction::LShr:
+ case Instruction::Mul:
+ case Instruction::Or:
+ case Instruction::Ret:
+ case Instruction::SDiv:
+ case Instruction::SExt:
+ case Instruction::Shl:
+ case Instruction::SRem:
+ case Instruction::Store:
+ case Instruction::Sub:
+ case Instruction::Trunc:
+ case Instruction::UDiv:
+ case Instruction::URem:
+ case Instruction::Xor:
+ case Instruction::ZExt:
+ break;
+ }
+
+ for (int oi = 0, oe = ii->getNumOperands(); oi != oe; ++oi) {
+ Value *operand = ii->getOperand(oi);
+ Type *operand_type = operand->getType();
+
+ switch (operand_type->getTypeID()) {
+ default:
+ break;
+ case Type::VectorTyID: {
+ if (log)
+ log->Printf("Unsupported operand type: %s",
+ PrintType(operand_type).c_str());
+ error.SetErrorString(unsupported_operand_error);
+ return false;
+ }
+ }
+
+ if (Constant *constant = llvm::dyn_cast<Constant>(operand)) {
+ if (!CanResolveConstant(constant)) {
+ if (log)
+ log->Printf("Unsupported constant: %s",
+ PrintValue(constant).c_str());
+ error.SetErrorString(unsupported_operand_error);
+ return false;
+ }
+ }
+ }
+ }
+ }
+
+ return true;
+}
+
+bool IRInterpreter::Interpret(llvm::Module &module, llvm::Function &function,
+ llvm::ArrayRef<lldb::addr_t> args,
+ lldb_private::IRExecutionUnit &execution_unit,
+ lldb_private::Error &error,
+ lldb::addr_t stack_frame_bottom,
+ lldb::addr_t stack_frame_top,
+ lldb_private::ExecutionContext &exe_ctx) {
+ lldb_private::Log *log(
+ lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS));
+
+ if (log) {
+ std::string s;
+ raw_string_ostream oss(s);
+
+ module.print(oss, NULL);
+
+ oss.flush();
+
+ log->Printf("Module as passed in to IRInterpreter::Interpret: \n\"%s\"",
+ s.c_str());
+ }
+
+ DataLayout data_layout(&module);
+
+ InterpreterStackFrame frame(data_layout, execution_unit, stack_frame_bottom,
+ stack_frame_top);
+
+ if (frame.m_frame_process_address == LLDB_INVALID_ADDRESS) {
+ error.SetErrorString("Couldn't allocate stack frame");
+ }
+
+ int arg_index = 0;
+
+ for (llvm::Function::arg_iterator ai = function.arg_begin(),
+ ae = function.arg_end();
+ ai != ae; ++ai, ++arg_index) {
+ if (args.size() <= static_cast<size_t>(arg_index)) {
+ error.SetErrorString("Not enough arguments passed in to function");
+ return false;
+ }
+
+ lldb::addr_t ptr = args[arg_index];
+
+ frame.MakeArgument(&*ai, ptr);
+ }
+
+ uint32_t num_insts = 0;
+
+ frame.Jump(&function.front());
+
+ while (frame.m_ii != frame.m_ie && (++num_insts < 4096)) {
+ const Instruction *inst = &*frame.m_ii;
+
+ if (log)
+ log->Printf("Interpreting %s", PrintValue(inst).c_str());
+
+ switch (inst->getOpcode()) {
+ default:
+ break;
+
+ case Instruction::Add:
+ case Instruction::Sub:
+ case Instruction::Mul:
+ case Instruction::SDiv:
+ case Instruction::UDiv:
+ case Instruction::SRem:
+ case Instruction::URem:
+ case Instruction::Shl:
+ case Instruction::LShr:
+ case Instruction::AShr:
+ case Instruction::And:
+ case Instruction::Or:
+ case Instruction::Xor: {
+ const BinaryOperator *bin_op = dyn_cast<BinaryOperator>(inst);
+
+ if (!bin_op) {
+ if (log)
+ log->Printf(
+ "getOpcode() returns %s, but instruction is not a BinaryOperator",
+ inst->getOpcodeName());
+ error.SetErrorToGenericError();
+ error.SetErrorString(interpreter_internal_error);
+ return false;
+ }
+
+ Value *lhs = inst->getOperand(0);
+ Value *rhs = inst->getOperand(1);
+
+ lldb_private::Scalar L;
+ lldb_private::Scalar R;
+
+ if (!frame.EvaluateValue(L, lhs, module)) {
+ if (log)
+ log->Printf("Couldn't evaluate %s", PrintValue(lhs).c_str());
+ error.SetErrorToGenericError();
+ error.SetErrorString(bad_value_error);
+ return false;
+ }
+
+ if (!frame.EvaluateValue(R, rhs, module)) {
+ if (log)
+ log->Printf("Couldn't evaluate %s", PrintValue(rhs).c_str());
+ error.SetErrorToGenericError();
+ error.SetErrorString(bad_value_error);
+ return false;
+ }
+
+ lldb_private::Scalar result;
+
+ switch (inst->getOpcode()) {
+ default:
+ break;
+ case Instruction::Add:
+ result = L + R;
+ break;
+ case Instruction::Mul:
+ result = L * R;
+ break;
+ case Instruction::Sub:
+ result = L - R;
+ break;
+ case Instruction::SDiv:
+ L.MakeSigned();
+ R.MakeSigned();
+ result = L / R;
+ break;
+ case Instruction::UDiv:
+ L.MakeUnsigned();
+ R.MakeUnsigned();
+ result = L / R;
+ break;
+ case Instruction::SRem:
+ L.MakeSigned();
+ R.MakeSigned();
+ result = L % R;
+ break;
+ case Instruction::URem:
+ L.MakeUnsigned();
+ R.MakeUnsigned();
+ result = L % R;
+ break;
+ case Instruction::Shl:
+ result = L << R;
+ break;
+ case Instruction::AShr:
+ result = L >> R;
+ break;
+ case Instruction::LShr:
+ result = L;
+ result.ShiftRightLogical(R);
+ break;
+ case Instruction::And:
+ result = L & R;
+ break;
+ case Instruction::Or:
+ result = L | R;
+ break;
+ case Instruction::Xor:
+ result = L ^ R;
+ break;
+ }
+
+ frame.AssignValue(inst, result, module);
+
+ if (log) {
+ log->Printf("Interpreted a %s", inst->getOpcodeName());
+ log->Printf(" L : %s", frame.SummarizeValue(lhs).c_str());
+ log->Printf(" R : %s", frame.SummarizeValue(rhs).c_str());
+ log->Printf(" = : %s", frame.SummarizeValue(inst).c_str());
+ }
+ } break;
+ case Instruction::Alloca: {
+ const AllocaInst *alloca_inst = dyn_cast<AllocaInst>(inst);
+
+ if (!alloca_inst) {
+ if (log)
+ log->Printf("getOpcode() returns Alloca, but instruction is not an "
+ "AllocaInst");
+ error.SetErrorToGenericError();
+ error.SetErrorString(interpreter_internal_error);
+ return false;
+ }
+
+ if (alloca_inst->isArrayAllocation()) {
+ if (log)
+ log->Printf(
+ "AllocaInsts are not handled if isArrayAllocation() is true");
+ error.SetErrorToGenericError();
+ error.SetErrorString(unsupported_opcode_error);
+ return false;
+ }
+
+ // The semantics of Alloca are:
+ // Create a region R of virtual memory of type T, backed by a data
+ // buffer
+ // Create a region P of virtual memory of type T*, backed by a data
+ // buffer
+ // Write the virtual address of R into P
+
+ Type *T = alloca_inst->getAllocatedType();
+ Type *Tptr = alloca_inst->getType();
+
+ lldb::addr_t R = frame.Malloc(T);
+
+ if (R == LLDB_INVALID_ADDRESS) {
+ if (log)
+ log->Printf("Couldn't allocate memory for an AllocaInst");
+ error.SetErrorToGenericError();
+ error.SetErrorString(memory_allocation_error);
+ return false;
+ }
+
+ lldb::addr_t P = frame.Malloc(Tptr);
+
+ if (P == LLDB_INVALID_ADDRESS) {
+ if (log)
+ log->Printf("Couldn't allocate the result pointer for an AllocaInst");
+ error.SetErrorToGenericError();
+ error.SetErrorString(memory_allocation_error);
+ return false;
+ }
+
+ lldb_private::Error write_error;
+
+ execution_unit.WritePointerToMemory(P, R, write_error);
+
+ if (!write_error.Success()) {
+ if (log)
+ log->Printf("Couldn't write the result pointer for an AllocaInst");
+ error.SetErrorToGenericError();
+ error.SetErrorString(memory_write_error);
+ lldb_private::Error free_error;
+ execution_unit.Free(P, free_error);
+ execution_unit.Free(R, free_error);
+ return false;
+ }
+
+ frame.m_values[alloca_inst] = P;
+
+ if (log) {
+ log->Printf("Interpreted an AllocaInst");
+ log->Printf(" R : 0x%" PRIx64, R);
+ log->Printf(" P : 0x%" PRIx64, P);
+ }
+ } break;
+ case Instruction::BitCast:
+ case Instruction::ZExt: {
+ const CastInst *cast_inst = dyn_cast<CastInst>(inst);
+
+ if (!cast_inst) {
+ if (log)
+ log->Printf(
+ "getOpcode() returns %s, but instruction is not a BitCastInst",
+ cast_inst->getOpcodeName());
+ error.SetErrorToGenericError();
+ error.SetErrorString(interpreter_internal_error);
+ return false;
+ }
+
+ Value *source = cast_inst->getOperand(0);
+
+ lldb_private::Scalar S;
+
+ if (!frame.EvaluateValue(S, source, module)) {
+ if (log)
+ log->Printf("Couldn't evaluate %s", PrintValue(source).c_str());
+ error.SetErrorToGenericError();
+ error.SetErrorString(bad_value_error);
+ return false;
+ }
+
+ frame.AssignValue(inst, S, module);
+ } break;
+ case Instruction::SExt: {
+ const CastInst *cast_inst = dyn_cast<CastInst>(inst);
+
+ if (!cast_inst) {
+ if (log)
+ log->Printf(
+ "getOpcode() returns %s, but instruction is not a BitCastInst",
+ cast_inst->getOpcodeName());
+ error.SetErrorToGenericError();
+ error.SetErrorString(interpreter_internal_error);
+ return false;
+ }
+
+ Value *source = cast_inst->getOperand(0);
+
+ lldb_private::Scalar S;
+
+ if (!frame.EvaluateValue(S, source, module)) {
+ if (log)
+ log->Printf("Couldn't evaluate %s", PrintValue(source).c_str());
+ error.SetErrorToGenericError();
+ error.SetErrorString(bad_value_error);
+ return false;
+ }
+
+ S.MakeSigned();
+
+ lldb_private::Scalar S_signextend(S.SLongLong());
+
+ frame.AssignValue(inst, S_signextend, module);
+ } break;
+ case Instruction::Br: {
+ const BranchInst *br_inst = dyn_cast<BranchInst>(inst);
+
+ if (!br_inst) {
+ if (log)
+ log->Printf(
+ "getOpcode() returns Br, but instruction is not a BranchInst");
+ error.SetErrorToGenericError();
+ error.SetErrorString(interpreter_internal_error);
+ return false;
+ }
+
+ if (br_inst->isConditional()) {
+ Value *condition = br_inst->getCondition();
+
+ lldb_private::Scalar C;
+
+ if (!frame.EvaluateValue(C, condition, module)) {
+ if (log)
+ log->Printf("Couldn't evaluate %s", PrintValue(condition).c_str());
+ error.SetErrorToGenericError();
+ error.SetErrorString(bad_value_error);
+ return false;
+ }
+
+ if (!C.IsZero())
+ frame.Jump(br_inst->getSuccessor(0));
+ else
+ frame.Jump(br_inst->getSuccessor(1));
+
+ if (log) {
+ log->Printf("Interpreted a BrInst with a condition");
+ log->Printf(" cond : %s", frame.SummarizeValue(condition).c_str());
+ }
+ } else {
+ frame.Jump(br_inst->getSuccessor(0));
+
+ if (log) {
+ log->Printf("Interpreted a BrInst with no condition");
+ }
+ }
+ }
+ continue;
+ case Instruction::PHI: {
+ const PHINode *phi_inst = dyn_cast<PHINode>(inst);
+
+ if (!phi_inst) {
+ if (log)
+ log->Printf(
+ "getOpcode() returns PHI, but instruction is not a PHINode");
+ error.SetErrorToGenericError();
+ error.SetErrorString(interpreter_internal_error);
+ return false;
+ }
+ if (!frame.m_prev_bb) {
+ if (log)
+ log->Printf("Encountered PHI node without having jumped from another "
+ "basic block");
+ error.SetErrorToGenericError();
+ error.SetErrorString(interpreter_internal_error);
+ return false;
+ }
+
+ Value *value = phi_inst->getIncomingValueForBlock(frame.m_prev_bb);
+ lldb_private::Scalar result;
+ if (!frame.EvaluateValue(result, value, module)) {
+ if (log)
+ log->Printf("Couldn't evaluate %s", PrintValue(value).c_str());
+ error.SetErrorToGenericError();
+ error.SetErrorString(bad_value_error);
+ return false;
+ }
+ frame.AssignValue(inst, result, module);
+
+ if (log) {
+ log->Printf("Interpreted a %s", inst->getOpcodeName());
+ log->Printf(" Incoming value : %s",
+ frame.SummarizeValue(value).c_str());
+ }
+ } break;
+ case Instruction::GetElementPtr: {
+ const GetElementPtrInst *gep_inst = dyn_cast<GetElementPtrInst>(inst);
+
+ if (!gep_inst) {
+ if (log)
+ log->Printf("getOpcode() returns GetElementPtr, but instruction is "
+ "not a GetElementPtrInst");
+ error.SetErrorToGenericError();
+ error.SetErrorString(interpreter_internal_error);
+ return false;
+ }
+
+ const Value *pointer_operand = gep_inst->getPointerOperand();
+ Type *src_elem_ty = gep_inst->getSourceElementType();
+
+ lldb_private::Scalar P;
+
+ if (!frame.EvaluateValue(P, pointer_operand, module)) {
+ if (log)
+ log->Printf("Couldn't evaluate %s",
+ PrintValue(pointer_operand).c_str());
+ error.SetErrorToGenericError();
+ error.SetErrorString(bad_value_error);
+ return false;
+ }
+
+ typedef SmallVector<Value *, 8> IndexVector;
+ typedef IndexVector::iterator IndexIterator;
+
+ SmallVector<Value *, 8> indices(gep_inst->idx_begin(),
+ gep_inst->idx_end());
+
+ SmallVector<Value *, 8> const_indices;
+
+ for (IndexIterator ii = indices.begin(), ie = indices.end(); ii != ie;
+ ++ii) {
+ ConstantInt *constant_index = dyn_cast<ConstantInt>(*ii);
+
+ if (!constant_index) {
+ lldb_private::Scalar I;
+
+ if (!frame.EvaluateValue(I, *ii, module)) {
+ if (log)
+ log->Printf("Couldn't evaluate %s", PrintValue(*ii).c_str());
+ error.SetErrorToGenericError();
+ error.SetErrorString(bad_value_error);
+ return false;
+ }
+
+ if (log)
+ log->Printf("Evaluated constant index %s as %llu",
+ PrintValue(*ii).c_str(),
+ I.ULongLong(LLDB_INVALID_ADDRESS));
+
+ constant_index = cast<ConstantInt>(ConstantInt::get(
+ (*ii)->getType(), I.ULongLong(LLDB_INVALID_ADDRESS)));
+ }
+
+ const_indices.push_back(constant_index);
+ }
+
+ uint64_t offset =
+ data_layout.getIndexedOffsetInType(src_elem_ty, const_indices);
+
+ lldb_private::Scalar Poffset = P + offset;
+
+ frame.AssignValue(inst, Poffset, module);
+
+ if (log) {
+ log->Printf("Interpreted a GetElementPtrInst");
+ log->Printf(" P : %s",
+ frame.SummarizeValue(pointer_operand).c_str());
+ log->Printf(" Poffset : %s", frame.SummarizeValue(inst).c_str());
+ }
+ } break;
+ case Instruction::ICmp: {
+ const ICmpInst *icmp_inst = dyn_cast<ICmpInst>(inst);
+
+ if (!icmp_inst) {
+ if (log)
+ log->Printf(
+ "getOpcode() returns ICmp, but instruction is not an ICmpInst");
+ error.SetErrorToGenericError();
+ error.SetErrorString(interpreter_internal_error);
+ return false;
+ }
+
+ CmpInst::Predicate predicate = icmp_inst->getPredicate();
+
+ Value *lhs = inst->getOperand(0);
+ Value *rhs = inst->getOperand(1);
+
+ lldb_private::Scalar L;
+ lldb_private::Scalar R;
+
+ if (!frame.EvaluateValue(L, lhs, module)) {
+ if (log)
+ log->Printf("Couldn't evaluate %s", PrintValue(lhs).c_str());
+ error.SetErrorToGenericError();
+ error.SetErrorString(bad_value_error);
+ return false;
+ }
+
+ if (!frame.EvaluateValue(R, rhs, module)) {
+ if (log)
+ log->Printf("Couldn't evaluate %s", PrintValue(rhs).c_str());
+ error.SetErrorToGenericError();
+ error.SetErrorString(bad_value_error);
+ return false;
+ }
+
+ lldb_private::Scalar result;
+
+ switch (predicate) {
+ default:
+ return false;
+ case CmpInst::ICMP_EQ:
+ result = (L == R);
+ break;
+ case CmpInst::ICMP_NE:
+ result = (L != R);
+ break;
+ case CmpInst::ICMP_UGT:
+ L.MakeUnsigned();
+ R.MakeUnsigned();
+ result = (L > R);
+ break;
+ case CmpInst::ICMP_UGE:
+ L.MakeUnsigned();
+ R.MakeUnsigned();
+ result = (L >= R);
+ break;
+ case CmpInst::ICMP_ULT:
+ L.MakeUnsigned();
+ R.MakeUnsigned();
+ result = (L < R);
+ break;
+ case CmpInst::ICMP_ULE:
+ L.MakeUnsigned();
+ R.MakeUnsigned();
+ result = (L <= R);
+ break;
+ case CmpInst::ICMP_SGT:
+ L.MakeSigned();
+ R.MakeSigned();
+ result = (L > R);
+ break;
+ case CmpInst::ICMP_SGE:
+ L.MakeSigned();
+ R.MakeSigned();
+ result = (L >= R);
+ break;
+ case CmpInst::ICMP_SLT:
+ L.MakeSigned();
+ R.MakeSigned();
+ result = (L < R);
+ break;
+ case CmpInst::ICMP_SLE:
+ L.MakeSigned();
+ R.MakeSigned();
+ result = (L <= R);
+ break;
+ }
+
+ frame.AssignValue(inst, result, module);
+
+ if (log) {
+ log->Printf("Interpreted an ICmpInst");
+ log->Printf(" L : %s", frame.SummarizeValue(lhs).c_str());
+ log->Printf(" R : %s", frame.SummarizeValue(rhs).c_str());
+ log->Printf(" = : %s", frame.SummarizeValue(inst).c_str());
+ }
+ } break;
+ case Instruction::IntToPtr: {
+ const IntToPtrInst *int_to_ptr_inst = dyn_cast<IntToPtrInst>(inst);
+
+ if (!int_to_ptr_inst) {
+ if (log)
+ log->Printf("getOpcode() returns IntToPtr, but instruction is not an "
+ "IntToPtrInst");
+ error.SetErrorToGenericError();
+ error.SetErrorString(interpreter_internal_error);
+ return false;
+ }
+
+ Value *src_operand = int_to_ptr_inst->getOperand(0);
+
+ lldb_private::Scalar I;
+
+ if (!frame.EvaluateValue(I, src_operand, module)) {
+ if (log)
+ log->Printf("Couldn't evaluate %s", PrintValue(src_operand).c_str());
+ error.SetErrorToGenericError();
+ error.SetErrorString(bad_value_error);
+ return false;
+ }
+
+ frame.AssignValue(inst, I, module);
+
+ if (log) {
+ log->Printf("Interpreted an IntToPtr");
+ log->Printf(" Src : %s", frame.SummarizeValue(src_operand).c_str());
+ log->Printf(" = : %s", frame.SummarizeValue(inst).c_str());
+ }
+ } break;
+ case Instruction::PtrToInt: {
+ const PtrToIntInst *ptr_to_int_inst = dyn_cast<PtrToIntInst>(inst);
+
+ if (!ptr_to_int_inst) {
+ if (log)
+ log->Printf("getOpcode() returns PtrToInt, but instruction is not an "
+ "PtrToIntInst");
+ error.SetErrorToGenericError();
+ error.SetErrorString(interpreter_internal_error);
+ return false;
+ }
+
+ Value *src_operand = ptr_to_int_inst->getOperand(0);
+
+ lldb_private::Scalar I;
+
+ if (!frame.EvaluateValue(I, src_operand, module)) {
+ if (log)
+ log->Printf("Couldn't evaluate %s", PrintValue(src_operand).c_str());
+ error.SetErrorToGenericError();
+ error.SetErrorString(bad_value_error);
+ return false;
+ }
+
+ frame.AssignValue(inst, I, module);
+
+ if (log) {
+ log->Printf("Interpreted a PtrToInt");
+ log->Printf(" Src : %s", frame.SummarizeValue(src_operand).c_str());
+ log->Printf(" = : %s", frame.SummarizeValue(inst).c_str());
+ }
+ } break;
+ case Instruction::Trunc: {
+ const TruncInst *trunc_inst = dyn_cast<TruncInst>(inst);
+
+ if (!trunc_inst) {
+ if (log)
+ log->Printf(
+ "getOpcode() returns Trunc, but instruction is not a TruncInst");
+ error.SetErrorToGenericError();
+ error.SetErrorString(interpreter_internal_error);
+ return false;
+ }
+
+ Value *src_operand = trunc_inst->getOperand(0);
+
+ lldb_private::Scalar I;
+
+ if (!frame.EvaluateValue(I, src_operand, module)) {
+ if (log)
+ log->Printf("Couldn't evaluate %s", PrintValue(src_operand).c_str());
+ error.SetErrorToGenericError();
+ error.SetErrorString(bad_value_error);
+ return false;
+ }
+
+ frame.AssignValue(inst, I, module);
+
+ if (log) {
+ log->Printf("Interpreted a Trunc");
+ log->Printf(" Src : %s", frame.SummarizeValue(src_operand).c_str());
+ log->Printf(" = : %s", frame.SummarizeValue(inst).c_str());
+ }
+ } break;
+ case Instruction::Load: {
+ const LoadInst *load_inst = dyn_cast<LoadInst>(inst);
+
+ if (!load_inst) {
+ if (log)
+ log->Printf(
+ "getOpcode() returns Load, but instruction is not a LoadInst");
+ error.SetErrorToGenericError();
+ error.SetErrorString(interpreter_internal_error);
+ return false;
+ }
+
+ // The semantics of Load are:
+ // Create a region D that will contain the loaded data
+ // Resolve the region P containing a pointer
+ // Dereference P to get the region R that the data should be loaded from
+ // Transfer a unit of type type(D) from R to D
+
+ const Value *pointer_operand = load_inst->getPointerOperand();
+
+ Type *pointer_ty = pointer_operand->getType();
+ PointerType *pointer_ptr_ty = dyn_cast<PointerType>(pointer_ty);
+ if (!pointer_ptr_ty) {
+ if (log)
+ log->Printf("getPointerOperand()->getType() is not a PointerType");
+ error.SetErrorToGenericError();
+ error.SetErrorString(interpreter_internal_error);
+ return false;
+ }
+ Type *target_ty = pointer_ptr_ty->getElementType();
+
+ lldb::addr_t D = frame.ResolveValue(load_inst, module);
+ lldb::addr_t P = frame.ResolveValue(pointer_operand, module);
+
+ if (D == LLDB_INVALID_ADDRESS) {
+ if (log)
+ log->Printf("LoadInst's value doesn't resolve to anything");
+ error.SetErrorToGenericError();
+ error.SetErrorString(bad_value_error);
+ return false;
+ }
+
+ if (P == LLDB_INVALID_ADDRESS) {
+ if (log)
+ log->Printf("LoadInst's pointer doesn't resolve to anything");
+ error.SetErrorToGenericError();
+ error.SetErrorString(bad_value_error);
+ return false;
+ }
+
+ lldb::addr_t R;
+ lldb_private::Error read_error;
+ execution_unit.ReadPointerFromMemory(&R, P, read_error);
+
+ if (!read_error.Success()) {
+ if (log)
+ log->Printf("Couldn't read the address to be loaded for a LoadInst");
+ error.SetErrorToGenericError();
+ error.SetErrorString(memory_read_error);
+ return false;
+ }
+
+ size_t target_size = data_layout.getTypeStoreSize(target_ty);
+ lldb_private::DataBufferHeap buffer(target_size, 0);
+
+ read_error.Clear();
+ execution_unit.ReadMemory(buffer.GetBytes(), R, buffer.GetByteSize(),
+ read_error);
+ if (!read_error.Success()) {
+ if (log)
+ log->Printf("Couldn't read from a region on behalf of a LoadInst");
+ error.SetErrorToGenericError();
+ error.SetErrorString(memory_read_error);
+ return false;
+ }
+
+ lldb_private::Error write_error;
+ execution_unit.WriteMemory(D, buffer.GetBytes(), buffer.GetByteSize(),
+ write_error);
+ if (!write_error.Success()) {
+ if (log)
+ log->Printf("Couldn't write to a region on behalf of a LoadInst");
+ error.SetErrorToGenericError();
+ error.SetErrorString(memory_read_error);
+ return false;
+ }
+
+ if (log) {
+ log->Printf("Interpreted a LoadInst");
+ log->Printf(" P : 0x%" PRIx64, P);
+ log->Printf(" R : 0x%" PRIx64, R);
+ log->Printf(" D : 0x%" PRIx64, D);
+ }
+ } break;
+ case Instruction::Ret: {
+ return true;
+ }
+ case Instruction::Store: {
+ const StoreInst *store_inst = dyn_cast<StoreInst>(inst);
+
+ if (!store_inst) {
+ if (log)
+ log->Printf(
+ "getOpcode() returns Store, but instruction is not a StoreInst");
+ error.SetErrorToGenericError();
+ error.SetErrorString(interpreter_internal_error);
+ return false;
+ }
+
+ // The semantics of Store are:
+ // Resolve the region D containing the data to be stored
+ // Resolve the region P containing a pointer
+ // Dereference P to get the region R that the data should be stored in
+ // Transfer a unit of type type(D) from D to R
+
+ const Value *value_operand = store_inst->getValueOperand();
+ const Value *pointer_operand = store_inst->getPointerOperand();
+
+ Type *pointer_ty = pointer_operand->getType();
+ PointerType *pointer_ptr_ty = dyn_cast<PointerType>(pointer_ty);
+ if (!pointer_ptr_ty)
+ return false;
+ Type *target_ty = pointer_ptr_ty->getElementType();
+
+ lldb::addr_t D = frame.ResolveValue(value_operand, module);
+ lldb::addr_t P = frame.ResolveValue(pointer_operand, module);
+
+ if (D == LLDB_INVALID_ADDRESS) {
+ if (log)
+ log->Printf("StoreInst's value doesn't resolve to anything");
+ error.SetErrorToGenericError();
+ error.SetErrorString(bad_value_error);
+ return false;
+ }
+
+ if (P == LLDB_INVALID_ADDRESS) {
+ if (log)
+ log->Printf("StoreInst's pointer doesn't resolve to anything");
+ error.SetErrorToGenericError();
+ error.SetErrorString(bad_value_error);
+ return false;
+ }
+
+ lldb::addr_t R;
+ lldb_private::Error read_error;
+ execution_unit.ReadPointerFromMemory(&R, P, read_error);
+
+ if (!read_error.Success()) {
+ if (log)
+ log->Printf("Couldn't read the address to be loaded for a LoadInst");
+ error.SetErrorToGenericError();
+ error.SetErrorString(memory_read_error);
+ return false;
+ }
+
+ size_t target_size = data_layout.getTypeStoreSize(target_ty);
+ lldb_private::DataBufferHeap buffer(target_size, 0);
+
+ read_error.Clear();
+ execution_unit.ReadMemory(buffer.GetBytes(), D, buffer.GetByteSize(),
+ read_error);
+ if (!read_error.Success()) {
+ if (log)
+ log->Printf("Couldn't read from a region on behalf of a StoreInst");
+ error.SetErrorToGenericError();
+ error.SetErrorString(memory_read_error);
+ return false;
+ }
+
+ lldb_private::Error write_error;
+ execution_unit.WriteMemory(R, buffer.GetBytes(), buffer.GetByteSize(),
+ write_error);
+ if (!write_error.Success()) {
+ if (log)
+ log->Printf("Couldn't write to a region on behalf of a StoreInst");
+ error.SetErrorToGenericError();
+ error.SetErrorString(memory_write_error);
+ return false;
+ }
+
+ if (log) {
+ log->Printf("Interpreted a StoreInst");
+ log->Printf(" D : 0x%" PRIx64, D);
+ log->Printf(" P : 0x%" PRIx64, P);
+ log->Printf(" R : 0x%" PRIx64, R);
+ }
+ } break;
+ case Instruction::Call: {
+ const CallInst *call_inst = dyn_cast<CallInst>(inst);
+
+ if (!call_inst) {
+ if (log)
+ log->Printf(
+ "getOpcode() returns %s, but instruction is not a CallInst",
+ inst->getOpcodeName());
+ error.SetErrorToGenericError();
+ error.SetErrorString(interpreter_internal_error);
+ return false;
+ }
+
+ if (CanIgnoreCall(call_inst))
+ break;
+
+ // Get the return type
+ llvm::Type *returnType = call_inst->getType();
+ if (returnType == nullptr) {
+ error.SetErrorToGenericError();
+ error.SetErrorString("unable to access return type");
+ return false;
+ }
+
+ // Work with void, integer and pointer return types
+ if (!returnType->isVoidTy() && !returnType->isIntegerTy() &&
+ !returnType->isPointerTy()) {
+ error.SetErrorToGenericError();
+ error.SetErrorString("return type is not supported");
+ return false;
+ }
+
+ // Check we can actually get a thread
+ if (exe_ctx.GetThreadPtr() == nullptr) {
+ error.SetErrorToGenericError();
+ error.SetErrorStringWithFormat("unable to acquire thread");
+ return false;
+ }
+
+ // Make sure we have a valid process
+ if (!exe_ctx.GetProcessPtr()) {
+ error.SetErrorToGenericError();
+ error.SetErrorStringWithFormat("unable to get the process");
+ return false;
+ }
+
+ // Find the address of the callee function
+ lldb_private::Scalar I;
+ const llvm::Value *val = call_inst->getCalledValue();
+
+ if (!frame.EvaluateValue(I, val, module)) {
+ error.SetErrorToGenericError();
+ error.SetErrorString("unable to get address of function");
+ return false;
+ }
+ lldb_private::Address funcAddr(I.ULongLong(LLDB_INVALID_ADDRESS));
+
+ lldb_private::DiagnosticManager diagnostics;
+ lldb_private::EvaluateExpressionOptions options;
+
+ // We generally receive a function pointer which we must dereference
+ llvm::Type *prototype = val->getType();
+ if (!prototype->isPointerTy()) {
+ error.SetErrorToGenericError();
+ error.SetErrorString("call need function pointer");
+ return false;
+ }
+
+ // Dereference the function pointer
+ prototype = prototype->getPointerElementType();
+ if (!(prototype->isFunctionTy() || prototype->isFunctionVarArg())) {
+ error.SetErrorToGenericError();
+ error.SetErrorString("call need function pointer");
+ return false;
+ }
+
+ // Find number of arguments
+ const int numArgs = call_inst->getNumArgOperands();
+
+ // We work with a fixed array of 16 arguments which is our upper limit
+ static lldb_private::ABI::CallArgument rawArgs[16];
+ if (numArgs >= 16) {
+ error.SetErrorToGenericError();
+ error.SetErrorStringWithFormat("function takes too many arguments");
+ return false;
+ }
+
+ // Push all function arguments to the argument list that will
+ // be passed to the call function thread plan
+ for (int i = 0; i < numArgs; i++) {
+ // Get details of this argument
+ llvm::Value *arg_op = call_inst->getArgOperand(i);
+ llvm::Type *arg_ty = arg_op->getType();
+
+ // Ensure that this argument is an supported type
+ if (!arg_ty->isIntegerTy() && !arg_ty->isPointerTy()) {
+ error.SetErrorToGenericError();
+ error.SetErrorStringWithFormat("argument %d must be integer type", i);
+ return false;
+ }
+
+ // Extract the arguments value
+ lldb_private::Scalar tmp_op = 0;
+ if (!frame.EvaluateValue(tmp_op, arg_op, module)) {
+ error.SetErrorToGenericError();
+ error.SetErrorStringWithFormat("unable to evaluate argument %d", i);
+ return false;
+ }
+
+ // Check if this is a string literal or constant string pointer
+ if (arg_ty->isPointerTy()) {
+ // Pointer to just one type
+ assert(arg_ty->getNumContainedTypes() == 1);
+
+ lldb::addr_t addr = tmp_op.ULongLong();
+ size_t dataSize = 0;
+
+ if (execution_unit.GetAllocSize(addr, dataSize)) {
+ // Create the required buffer
+ rawArgs[i].size = dataSize;
+ rawArgs[i].data_ap.reset(new uint8_t[dataSize + 1]);
+
+ // Read string from host memory
+ execution_unit.ReadMemory(rawArgs[i].data_ap.get(), addr, dataSize,
+ error);
+ if (error.Fail()) {
+ assert(!"we have failed to read the string from memory");
+ return false;
+ }
+ // Add null terminator
+ rawArgs[i].data_ap[dataSize] = '\0';
+ rawArgs[i].type = lldb_private::ABI::CallArgument::HostPointer;
+ } else {
+ assert(!"unable to locate host data for transfer to device");
+ return false;
+ }
+ } else /* if ( arg_ty->isPointerTy() ) */
+ {
+ rawArgs[i].type = lldb_private::ABI::CallArgument::TargetValue;
+ // Get argument size in bytes
+ rawArgs[i].size = arg_ty->getIntegerBitWidth() / 8;
+ // Push value into argument list for thread plan
+ rawArgs[i].value = tmp_op.ULongLong();
+ }
+ }
+
+ // Pack the arguments into an llvm::array
+ llvm::ArrayRef<lldb_private::ABI::CallArgument> args(rawArgs, numArgs);
+
+ // Setup a thread plan to call the target function
+ lldb::ThreadPlanSP call_plan_sp(
+ new lldb_private::ThreadPlanCallFunctionUsingABI(
+ exe_ctx.GetThreadRef(), funcAddr, *prototype, *returnType, args,
+ options));
+
+ // Check if the plan is valid
+ lldb_private::StreamString ss;
+ if (!call_plan_sp || !call_plan_sp->ValidatePlan(&ss)) {
+ error.SetErrorToGenericError();
+ error.SetErrorStringWithFormat(
+ "unable to make ThreadPlanCallFunctionUsingABI for 0x%llx",
+ I.ULongLong());
+ return false;
+ }
+
+ exe_ctx.GetProcessPtr()->SetRunningUserExpression(true);
+
+ // Execute the actual function call thread plan
+ lldb::ExpressionResults res = exe_ctx.GetProcessRef().RunThreadPlan(
+ exe_ctx, call_plan_sp, options, diagnostics);
+
+ // Check that the thread plan completed successfully
+ if (res != lldb::ExpressionResults::eExpressionCompleted) {
+ error.SetErrorToGenericError();
+ error.SetErrorStringWithFormat("ThreadPlanCallFunctionUsingABI failed");
+ return false;
+ }
+
+ exe_ctx.GetProcessPtr()->SetRunningUserExpression(false);
+
+ // Void return type
+ if (returnType->isVoidTy()) {
+ // Cant assign to void types, so we leave the frame untouched
+ } else
+ // Integer or pointer return type
+ if (returnType->isIntegerTy() || returnType->isPointerTy()) {
+ // Get the encapsulated return value
+ lldb::ValueObjectSP retVal = call_plan_sp.get()->GetReturnValueObject();
+
+ lldb_private::Scalar returnVal = -1;
+ lldb_private::ValueObject *vobj = retVal.get();
+
+ // Check if the return value is valid
+ if (vobj == nullptr || retVal.empty()) {
+ error.SetErrorToGenericError();
+ error.SetErrorStringWithFormat("unable to get the return value");
+ return false;
+ }
+
+ // Extract the return value as a integer
+ lldb_private::Value &value = vobj->GetValue();
+ returnVal = value.GetScalar();
+
+ // Push the return value as the result
+ frame.AssignValue(inst, returnVal, module);
+ }
+ } break;
+ }
+
+ ++frame.m_ii;
+ }
+
+ if (num_insts >= 4096) {
+ error.SetErrorToGenericError();
+ error.SetErrorString(infinite_loop_error);
+ return false;
+ }
+
+ return false;
}
diff --git a/lldb/source/Expression/IRMemoryMap.cpp b/lldb/source/Expression/IRMemoryMap.cpp
index aa16572..008838d 100644
--- a/lldb/source/Expression/IRMemoryMap.cpp
+++ b/lldb/source/Expression/IRMemoryMap.cpp
@@ -7,12 +7,12 @@
//
//===----------------------------------------------------------------------===//
+#include "lldb/Expression/IRMemoryMap.h"
#include "lldb/Core/DataBufferHeap.h"
#include "lldb/Core/DataExtractor.h"
#include "lldb/Core/Error.h"
#include "lldb/Core/Log.h"
#include "lldb/Core/Scalar.h"
-#include "lldb/Expression/IRMemoryMap.h"
#include "lldb/Target/MemoryRegionInfo.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/Target.h"
@@ -20,223 +20,204 @@
using namespace lldb_private;
-IRMemoryMap::IRMemoryMap (lldb::TargetSP target_sp) :
- m_target_wp(target_sp)
-{
- if (target_sp)
- m_process_wp = target_sp->GetProcessSP();
+IRMemoryMap::IRMemoryMap(lldb::TargetSP target_sp) : m_target_wp(target_sp) {
+ if (target_sp)
+ m_process_wp = target_sp->GetProcessSP();
}
-IRMemoryMap::~IRMemoryMap ()
-{
- lldb::ProcessSP process_sp = m_process_wp.lock();
+IRMemoryMap::~IRMemoryMap() {
+ lldb::ProcessSP process_sp = m_process_wp.lock();
- if (process_sp)
- {
- AllocationMap::iterator iter;
+ if (process_sp) {
+ AllocationMap::iterator iter;
- Error err;
+ Error err;
- while ((iter = m_allocations.begin()) != m_allocations.end())
- {
- err.Clear();
- if (iter->second.m_leak)
- m_allocations.erase(iter);
- else
- Free(iter->first, err);
- }
+ while ((iter = m_allocations.begin()) != m_allocations.end()) {
+ err.Clear();
+ if (iter->second.m_leak)
+ m_allocations.erase(iter);
+ else
+ Free(iter->first, err);
}
+ }
}
-lldb::addr_t
-IRMemoryMap::FindSpace (size_t size)
-{
- // The FindSpace algorithm's job is to find a region of memory that the
- // underlying process is unlikely to be using.
- //
- // The memory returned by this function will never be written to. The only
- // point is that it should not shadow process memory if possible, so that
- // expressions processing real values from the process do not use the
- // wrong data.
- //
- // If the process can in fact allocate memory (CanJIT() lets us know this)
- // then this can be accomplished just be allocating memory in the inferior.
- // Then no guessing is required.
+lldb::addr_t IRMemoryMap::FindSpace(size_t size) {
+ // The FindSpace algorithm's job is to find a region of memory that the
+ // underlying process is unlikely to be using.
+ //
+ // The memory returned by this function will never be written to. The only
+ // point is that it should not shadow process memory if possible, so that
+ // expressions processing real values from the process do not use the
+ // wrong data.
+ //
+ // If the process can in fact allocate memory (CanJIT() lets us know this)
+ // then this can be accomplished just be allocating memory in the inferior.
+ // Then no guessing is required.
- lldb::TargetSP target_sp = m_target_wp.lock();
- lldb::ProcessSP process_sp = m_process_wp.lock();
-
- const bool process_is_alive = process_sp && process_sp->IsAlive();
+ lldb::TargetSP target_sp = m_target_wp.lock();
+ lldb::ProcessSP process_sp = m_process_wp.lock();
- lldb::addr_t ret = LLDB_INVALID_ADDRESS;
- if (size == 0)
- return ret;
+ const bool process_is_alive = process_sp && process_sp->IsAlive();
- if (process_is_alive && process_sp->CanJIT())
- {
- Error alloc_error;
-
- ret = process_sp->AllocateMemory(size, lldb::ePermissionsReadable | lldb::ePermissionsWritable, alloc_error);
-
- if (!alloc_error.Success())
- return LLDB_INVALID_ADDRESS;
- else
- return ret;
- }
-
- // At this point we know that we need to hunt.
- //
- // First, go to the end of the existing allocations we've made if there are
- // any allocations. Otherwise start at the beginning of memory.
-
- if (m_allocations.empty())
- {
- ret = 0x0;
- }
- else
- {
- auto back = m_allocations.rbegin();
- lldb::addr_t addr = back->first;
- size_t alloc_size = back->second.m_size;
- ret = llvm::alignTo(addr+alloc_size, 4096);
- }
-
- // Now, if it's possible to use the GetMemoryRegionInfo API to detect mapped
- // regions, walk forward through memory until a region is found that
- // has adequate space for our allocation.
- if (process_is_alive)
- {
- const uint64_t end_of_memory = process_sp->GetAddressByteSize() == 8 ?
- 0xffffffffffffffffull : 0xffffffffull;
-
- lldbassert(process_sp->GetAddressByteSize() == 4 || end_of_memory != 0xffffffffull);
-
- MemoryRegionInfo region_info;
- Error err = process_sp->GetMemoryRegionInfo(ret, region_info);
- if (err.Success())
- {
- while (true)
- {
- if (region_info.GetReadable() != MemoryRegionInfo::OptionalBool::eNo ||
- region_info.GetWritable() != MemoryRegionInfo::OptionalBool::eNo ||
- region_info.GetExecutable() != MemoryRegionInfo::OptionalBool::eNo)
- {
- if (region_info.GetRange().GetRangeEnd() - 1 >= end_of_memory)
- {
- ret = LLDB_INVALID_ADDRESS;
- break;
- }
- else
- {
- ret = region_info.GetRange().GetRangeEnd();
- }
- }
- else if (ret + size < region_info.GetRange().GetRangeEnd())
- {
- return ret;
- }
- else
- {
- // ret stays the same. We just need to walk a bit further.
- }
-
- err = process_sp->GetMemoryRegionInfo(region_info.GetRange().GetRangeEnd(), region_info);
- if (err.Fail())
- {
- lldbassert(!"GetMemoryRegionInfo() succeeded, then failed");
- ret = LLDB_INVALID_ADDRESS;
- break;
- }
- }
- }
- }
-
- // We've tried our algorithm, and it didn't work. Now we have to reset back
- // to the end of the allocations we've already reported, or use a 'sensible'
- // default if this is our first allocation.
-
- if (m_allocations.empty())
- {
- uint32_t address_byte_size = GetAddressByteSize();
- if (address_byte_size != UINT32_MAX)
- {
- switch (address_byte_size)
- {
- case 8:
- ret = 0xffffffff00000000ull;
- break;
- case 4:
- ret = 0xee000000ull;
- break;
- default:
- break;
- }
- }
- }
- else
- {
- auto back = m_allocations.rbegin();
- lldb::addr_t addr = back->first;
- size_t alloc_size = back->second.m_size;
- ret = llvm::alignTo(addr+alloc_size, 4096);
- }
-
+ lldb::addr_t ret = LLDB_INVALID_ADDRESS;
+ if (size == 0)
return ret;
+
+ if (process_is_alive && process_sp->CanJIT()) {
+ Error alloc_error;
+
+ ret = process_sp->AllocateMemory(size, lldb::ePermissionsReadable |
+ lldb::ePermissionsWritable,
+ alloc_error);
+
+ if (!alloc_error.Success())
+ return LLDB_INVALID_ADDRESS;
+ else
+ return ret;
+ }
+
+ // At this point we know that we need to hunt.
+ //
+ // First, go to the end of the existing allocations we've made if there are
+ // any allocations. Otherwise start at the beginning of memory.
+
+ if (m_allocations.empty()) {
+ ret = 0x0;
+ } else {
+ auto back = m_allocations.rbegin();
+ lldb::addr_t addr = back->first;
+ size_t alloc_size = back->second.m_size;
+ ret = llvm::alignTo(addr + alloc_size, 4096);
+ }
+
+ // Now, if it's possible to use the GetMemoryRegionInfo API to detect mapped
+ // regions, walk forward through memory until a region is found that
+ // has adequate space for our allocation.
+ if (process_is_alive) {
+ const uint64_t end_of_memory = process_sp->GetAddressByteSize() == 8
+ ? 0xffffffffffffffffull
+ : 0xffffffffull;
+
+ lldbassert(process_sp->GetAddressByteSize() == 4 ||
+ end_of_memory != 0xffffffffull);
+
+ MemoryRegionInfo region_info;
+ Error err = process_sp->GetMemoryRegionInfo(ret, region_info);
+ if (err.Success()) {
+ while (true) {
+ if (region_info.GetReadable() != MemoryRegionInfo::OptionalBool::eNo ||
+ region_info.GetWritable() != MemoryRegionInfo::OptionalBool::eNo ||
+ region_info.GetExecutable() !=
+ MemoryRegionInfo::OptionalBool::eNo) {
+ if (region_info.GetRange().GetRangeEnd() - 1 >= end_of_memory) {
+ ret = LLDB_INVALID_ADDRESS;
+ break;
+ } else {
+ ret = region_info.GetRange().GetRangeEnd();
+ }
+ } else if (ret + size < region_info.GetRange().GetRangeEnd()) {
+ return ret;
+ } else {
+ // ret stays the same. We just need to walk a bit further.
+ }
+
+ err = process_sp->GetMemoryRegionInfo(
+ region_info.GetRange().GetRangeEnd(), region_info);
+ if (err.Fail()) {
+ lldbassert(!"GetMemoryRegionInfo() succeeded, then failed");
+ ret = LLDB_INVALID_ADDRESS;
+ break;
+ }
+ }
+ }
+ }
+
+ // We've tried our algorithm, and it didn't work. Now we have to reset back
+ // to the end of the allocations we've already reported, or use a 'sensible'
+ // default if this is our first allocation.
+
+ if (m_allocations.empty()) {
+ uint32_t address_byte_size = GetAddressByteSize();
+ if (address_byte_size != UINT32_MAX) {
+ switch (address_byte_size) {
+ case 8:
+ ret = 0xffffffff00000000ull;
+ break;
+ case 4:
+ ret = 0xee000000ull;
+ break;
+ default:
+ break;
+ }
+ }
+ } else {
+ auto back = m_allocations.rbegin();
+ lldb::addr_t addr = back->first;
+ size_t alloc_size = back->second.m_size;
+ ret = llvm::alignTo(addr + alloc_size, 4096);
+ }
+
+ return ret;
}
IRMemoryMap::AllocationMap::iterator
-IRMemoryMap::FindAllocation (lldb::addr_t addr, size_t size)
-{
- if (addr == LLDB_INVALID_ADDRESS)
- return m_allocations.end();
-
- AllocationMap::iterator iter = m_allocations.lower_bound (addr);
-
- if (iter == m_allocations.end() ||
- iter->first > addr)
- {
- if (iter == m_allocations.begin())
- return m_allocations.end();
- iter--;
- }
-
- if (iter->first <= addr && iter->first + iter->second.m_size >= addr + size)
- return iter;
-
+IRMemoryMap::FindAllocation(lldb::addr_t addr, size_t size) {
+ if (addr == LLDB_INVALID_ADDRESS)
return m_allocations.end();
+
+ AllocationMap::iterator iter = m_allocations.lower_bound(addr);
+
+ if (iter == m_allocations.end() || iter->first > addr) {
+ if (iter == m_allocations.begin())
+ return m_allocations.end();
+ iter--;
+ }
+
+ if (iter->first <= addr && iter->first + iter->second.m_size >= addr + size)
+ return iter;
+
+ return m_allocations.end();
}
-bool
-IRMemoryMap::IntersectsAllocation (lldb::addr_t addr, size_t size) const
-{
- if (addr == LLDB_INVALID_ADDRESS)
- return false;
-
- AllocationMap::const_iterator iter = m_allocations.lower_bound (addr);
-
- // Since we only know that the returned interval begins at a location greater than or
- // equal to where the given interval begins, it's possible that the given interval
- // intersects either the returned interval or the previous interval. Thus, we need to
- // check both. Note that we only need to check these two intervals. Since all intervals
- // are disjoint it is not possible that an adjacent interval does not intersect, but a
- // non-adjacent interval does intersect.
- if (iter != m_allocations.end()) {
- if (AllocationsIntersect(addr, size, iter->second.m_process_start, iter->second.m_size))
- return true;
- }
-
- if (iter != m_allocations.begin()) {
- --iter;
- if (AllocationsIntersect(addr, size, iter->second.m_process_start, iter->second.m_size))
- return true;
- }
-
+bool IRMemoryMap::IntersectsAllocation(lldb::addr_t addr, size_t size) const {
+ if (addr == LLDB_INVALID_ADDRESS)
return false;
+
+ AllocationMap::const_iterator iter = m_allocations.lower_bound(addr);
+
+ // Since we only know that the returned interval begins at a location greater
+ // than or
+ // equal to where the given interval begins, it's possible that the given
+ // interval
+ // intersects either the returned interval or the previous interval. Thus, we
+ // need to
+ // check both. Note that we only need to check these two intervals. Since all
+ // intervals
+ // are disjoint it is not possible that an adjacent interval does not
+ // intersect, but a
+ // non-adjacent interval does intersect.
+ if (iter != m_allocations.end()) {
+ if (AllocationsIntersect(addr, size, iter->second.m_process_start,
+ iter->second.m_size))
+ return true;
+ }
+
+ if (iter != m_allocations.begin()) {
+ --iter;
+ if (AllocationsIntersect(addr, size, iter->second.m_process_start,
+ iter->second.m_size))
+ return true;
+ }
+
+ return false;
}
-bool
-IRMemoryMap::AllocationsIntersect(lldb::addr_t addr1, size_t size1, lldb::addr_t addr2, size_t size2) {
- // Given two half open intervals [A, B) and [X, Y), the only 6 permutations that satisfy
+bool IRMemoryMap::AllocationsIntersect(lldb::addr_t addr1, size_t size1,
+ lldb::addr_t addr2, size_t size2) {
+ // Given two half open intervals [A, B) and [X, Y), the only 6 permutations
+ // that satisfy
// A<B and X<Y are the following:
// A B X Y
// A X B Y (intersects)
@@ -249,666 +230,615 @@
return (addr2 < (addr1 + size1)) && (addr1 < (addr2 + size2));
}
-lldb::ByteOrder
-IRMemoryMap::GetByteOrder()
-{
- lldb::ProcessSP process_sp = m_process_wp.lock();
+lldb::ByteOrder IRMemoryMap::GetByteOrder() {
+ lldb::ProcessSP process_sp = m_process_wp.lock();
- if (process_sp)
- return process_sp->GetByteOrder();
+ if (process_sp)
+ return process_sp->GetByteOrder();
- lldb::TargetSP target_sp = m_target_wp.lock();
+ lldb::TargetSP target_sp = m_target_wp.lock();
- if (target_sp)
- return target_sp->GetArchitecture().GetByteOrder();
+ if (target_sp)
+ return target_sp->GetArchitecture().GetByteOrder();
- return lldb::eByteOrderInvalid;
+ return lldb::eByteOrderInvalid;
}
-uint32_t
-IRMemoryMap::GetAddressByteSize()
-{
- lldb::ProcessSP process_sp = m_process_wp.lock();
+uint32_t IRMemoryMap::GetAddressByteSize() {
+ lldb::ProcessSP process_sp = m_process_wp.lock();
- if (process_sp)
- return process_sp->GetAddressByteSize();
+ if (process_sp)
+ return process_sp->GetAddressByteSize();
- lldb::TargetSP target_sp = m_target_wp.lock();
+ lldb::TargetSP target_sp = m_target_wp.lock();
- if (target_sp)
- return target_sp->GetArchitecture().GetAddressByteSize();
+ if (target_sp)
+ return target_sp->GetArchitecture().GetAddressByteSize();
- return UINT32_MAX;
+ return UINT32_MAX;
}
-ExecutionContextScope *
-IRMemoryMap::GetBestExecutionContextScope() const
-{
- lldb::ProcessSP process_sp = m_process_wp.lock();
+ExecutionContextScope *IRMemoryMap::GetBestExecutionContextScope() const {
+ lldb::ProcessSP process_sp = m_process_wp.lock();
- if (process_sp)
- return process_sp.get();
+ if (process_sp)
+ return process_sp.get();
- lldb::TargetSP target_sp = m_target_wp.lock();
+ lldb::TargetSP target_sp = m_target_wp.lock();
- if (target_sp)
- return target_sp.get();
+ if (target_sp)
+ return target_sp.get();
- return NULL;
+ return NULL;
}
-IRMemoryMap::Allocation::Allocation (lldb::addr_t process_alloc,
- lldb::addr_t process_start,
- size_t size,
- uint32_t permissions,
- uint8_t alignment,
- AllocationPolicy policy) :
- m_process_alloc (process_alloc),
- m_process_start (process_start),
- m_size (size),
- m_permissions (permissions),
- m_alignment (alignment),
- m_policy (policy),
- m_leak (false)
-{
- switch (policy)
- {
- default:
- assert (0 && "We cannot reach this!");
- case eAllocationPolicyHostOnly:
- m_data.SetByteSize(size);
- memset(m_data.GetBytes(), 0, size);
- break;
- case eAllocationPolicyProcessOnly:
- break;
- case eAllocationPolicyMirror:
- m_data.SetByteSize(size);
- memset(m_data.GetBytes(), 0, size);
- break;
+IRMemoryMap::Allocation::Allocation(lldb::addr_t process_alloc,
+ lldb::addr_t process_start, size_t size,
+ uint32_t permissions, uint8_t alignment,
+ AllocationPolicy policy)
+ : m_process_alloc(process_alloc), m_process_start(process_start),
+ m_size(size), m_permissions(permissions), m_alignment(alignment),
+ m_policy(policy), m_leak(false) {
+ switch (policy) {
+ default:
+ assert(0 && "We cannot reach this!");
+ case eAllocationPolicyHostOnly:
+ m_data.SetByteSize(size);
+ memset(m_data.GetBytes(), 0, size);
+ break;
+ case eAllocationPolicyProcessOnly:
+ break;
+ case eAllocationPolicyMirror:
+ m_data.SetByteSize(size);
+ memset(m_data.GetBytes(), 0, size);
+ break;
+ }
+}
+
+lldb::addr_t IRMemoryMap::Malloc(size_t size, uint8_t alignment,
+ uint32_t permissions, AllocationPolicy policy,
+ bool zero_memory, Error &error) {
+ lldb_private::Log *log(
+ lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS));
+ error.Clear();
+
+ lldb::ProcessSP process_sp;
+ lldb::addr_t allocation_address = LLDB_INVALID_ADDRESS;
+ lldb::addr_t aligned_address = LLDB_INVALID_ADDRESS;
+
+ size_t alignment_mask = alignment - 1;
+ size_t allocation_size;
+
+ if (size == 0)
+ allocation_size = alignment;
+ else
+ allocation_size = (size & alignment_mask)
+ ? ((size + alignment) & (~alignment_mask))
+ : size;
+
+ switch (policy) {
+ default:
+ error.SetErrorToGenericError();
+ error.SetErrorString("Couldn't malloc: invalid allocation policy");
+ return LLDB_INVALID_ADDRESS;
+ case eAllocationPolicyHostOnly:
+ allocation_address = FindSpace(allocation_size);
+ if (allocation_address == LLDB_INVALID_ADDRESS) {
+ error.SetErrorToGenericError();
+ error.SetErrorString("Couldn't malloc: address space is full");
+ return LLDB_INVALID_ADDRESS;
}
-}
-
-lldb::addr_t
-IRMemoryMap::Malloc (size_t size, uint8_t alignment, uint32_t permissions, AllocationPolicy policy, bool zero_memory, Error &error)
-{
- lldb_private::Log *log (lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
- error.Clear();
-
- lldb::ProcessSP process_sp;
- lldb::addr_t allocation_address = LLDB_INVALID_ADDRESS;
- lldb::addr_t aligned_address = LLDB_INVALID_ADDRESS;
-
- size_t alignment_mask = alignment - 1;
- size_t allocation_size;
-
- if (size == 0)
- allocation_size = alignment;
- else
- allocation_size = (size & alignment_mask) ? ((size + alignment) & (~alignment_mask)) : size;
-
- switch (policy)
- {
- default:
- error.SetErrorToGenericError();
- error.SetErrorString("Couldn't malloc: invalid allocation policy");
- return LLDB_INVALID_ADDRESS;
- case eAllocationPolicyHostOnly:
- allocation_address = FindSpace(allocation_size);
- if (allocation_address == LLDB_INVALID_ADDRESS)
- {
- error.SetErrorToGenericError();
- error.SetErrorString("Couldn't malloc: address space is full");
- return LLDB_INVALID_ADDRESS;
- }
- break;
- case eAllocationPolicyMirror:
- process_sp = m_process_wp.lock();
- if (log)
- log->Printf ("IRMemoryMap::%s process_sp=0x%" PRIx64 ", process_sp->CanJIT()=%s, process_sp->IsAlive()=%s", __FUNCTION__, (lldb::addr_t) process_sp.get (), process_sp && process_sp->CanJIT () ? "true" : "false", process_sp && process_sp->IsAlive () ? "true" : "false");
- if (process_sp && process_sp->CanJIT() && process_sp->IsAlive())
- {
- if (!zero_memory)
- allocation_address = process_sp->AllocateMemory(allocation_size, permissions, error);
- else
- allocation_address = process_sp->CallocateMemory(allocation_size, permissions, error);
-
- if (!error.Success())
- return LLDB_INVALID_ADDRESS;
- }
- else
- {
- if (log)
- log->Printf ("IRMemoryMap::%s switching to eAllocationPolicyHostOnly due to failed condition (see previous expr log message)", __FUNCTION__);
- policy = eAllocationPolicyHostOnly;
- allocation_address = FindSpace(allocation_size);
- if (allocation_address == LLDB_INVALID_ADDRESS)
- {
- error.SetErrorToGenericError();
- error.SetErrorString("Couldn't malloc: address space is full");
- return LLDB_INVALID_ADDRESS;
- }
- }
- break;
- case eAllocationPolicyProcessOnly:
- process_sp = m_process_wp.lock();
- if (process_sp)
- {
- if (process_sp->CanJIT() && process_sp->IsAlive())
- {
- if (!zero_memory)
- allocation_address = process_sp->AllocateMemory(allocation_size, permissions, error);
- else
- allocation_address = process_sp->CallocateMemory(allocation_size, permissions, error);
-
- if (!error.Success())
- return LLDB_INVALID_ADDRESS;
- }
- else
- {
- error.SetErrorToGenericError();
- error.SetErrorString("Couldn't malloc: process doesn't support allocating memory");
- return LLDB_INVALID_ADDRESS;
- }
- }
- else
- {
- error.SetErrorToGenericError();
- error.SetErrorString("Couldn't malloc: process doesn't exist, and this memory must be in the process");
- return LLDB_INVALID_ADDRESS;
- }
- break;
- }
-
-
- lldb::addr_t mask = alignment - 1;
- aligned_address = (allocation_address + mask) & (~mask);
-
- m_allocations[aligned_address] = Allocation(allocation_address,
- aligned_address,
- allocation_size,
- permissions,
- alignment,
- policy);
-
- if (zero_memory)
- {
- Error write_error;
- std::vector<uint8_t> zero_buf(size, 0);
- WriteMemory(aligned_address, zero_buf.data(), size, write_error);
- }
-
+ break;
+ case eAllocationPolicyMirror:
+ process_sp = m_process_wp.lock();
if (log)
- {
- const char * policy_string;
+ log->Printf("IRMemoryMap::%s process_sp=0x%" PRIx64
+ ", process_sp->CanJIT()=%s, process_sp->IsAlive()=%s",
+ __FUNCTION__, (lldb::addr_t)process_sp.get(),
+ process_sp && process_sp->CanJIT() ? "true" : "false",
+ process_sp && process_sp->IsAlive() ? "true" : "false");
+ if (process_sp && process_sp->CanJIT() && process_sp->IsAlive()) {
+ if (!zero_memory)
+ allocation_address =
+ process_sp->AllocateMemory(allocation_size, permissions, error);
+ else
+ allocation_address =
+ process_sp->CallocateMemory(allocation_size, permissions, error);
- switch (policy)
- {
- default:
- policy_string = "<invalid policy>";
- break;
- case eAllocationPolicyHostOnly:
- policy_string = "eAllocationPolicyHostOnly";
- break;
- case eAllocationPolicyProcessOnly:
- policy_string = "eAllocationPolicyProcessOnly";
- break;
- case eAllocationPolicyMirror:
- policy_string = "eAllocationPolicyMirror";
- break;
- }
-
- log->Printf("IRMemoryMap::Malloc (%" PRIu64 ", 0x%" PRIx64 ", 0x%" PRIx64 ", %s) -> 0x%" PRIx64,
- (uint64_t)allocation_size,
- (uint64_t)alignment,
- (uint64_t)permissions,
- policy_string,
- aligned_address);
- }
-
- return aligned_address;
-}
-
-void
-IRMemoryMap::Leak (lldb::addr_t process_address, Error &error)
-{
- error.Clear();
-
- AllocationMap::iterator iter = m_allocations.find(process_address);
-
- if (iter == m_allocations.end())
- {
+ if (!error.Success())
+ return LLDB_INVALID_ADDRESS;
+ } else {
+ if (log)
+ log->Printf("IRMemoryMap::%s switching to eAllocationPolicyHostOnly "
+ "due to failed condition (see previous expr log message)",
+ __FUNCTION__);
+ policy = eAllocationPolicyHostOnly;
+ allocation_address = FindSpace(allocation_size);
+ if (allocation_address == LLDB_INVALID_ADDRESS) {
error.SetErrorToGenericError();
- error.SetErrorString("Couldn't leak: allocation doesn't exist");
- return;
+ error.SetErrorString("Couldn't malloc: address space is full");
+ return LLDB_INVALID_ADDRESS;
+ }
}
-
- Allocation &allocation = iter->second;
-
- allocation.m_leak = true;
-}
-
-void
-IRMemoryMap::Free (lldb::addr_t process_address, Error &error)
-{
- error.Clear();
-
- AllocationMap::iterator iter = m_allocations.find(process_address);
-
- if (iter == m_allocations.end())
- {
- error.SetErrorToGenericError();
- error.SetErrorString("Couldn't free: allocation doesn't exist");
- return;
- }
-
- Allocation &allocation = iter->second;
-
- switch (allocation.m_policy)
- {
- default:
- case eAllocationPolicyHostOnly:
- {
- lldb::ProcessSP process_sp = m_process_wp.lock();
- if (process_sp)
- {
- if (process_sp->CanJIT() && process_sp->IsAlive())
- process_sp->DeallocateMemory(allocation.m_process_alloc); // FindSpace allocated this for real
- }
-
- break;
- }
- case eAllocationPolicyMirror:
- case eAllocationPolicyProcessOnly:
- {
- lldb::ProcessSP process_sp = m_process_wp.lock();
- if (process_sp)
- process_sp->DeallocateMemory(allocation.m_process_alloc);
- }
- }
-
- if (lldb_private::Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS))
- {
- log->Printf("IRMemoryMap::Free (0x%" PRIx64 ") freed [0x%" PRIx64 "..0x%" PRIx64 ")",
- (uint64_t)process_address,
- iter->second.m_process_start,
- iter->second.m_process_start + iter->second.m_size);
- }
-
- m_allocations.erase(iter);
-}
-
-bool
-IRMemoryMap::GetAllocSize(lldb::addr_t address, size_t &size)
-{
- AllocationMap::iterator iter = FindAllocation(address, size);
- if (iter == m_allocations.end())
- return false;
-
- Allocation &al = iter->second;
-
- if (address > (al.m_process_start + al.m_size))
- {
- size = 0;
- return false;
- }
-
- if (address > al.m_process_start)
- {
- int dif = address - al.m_process_start;
- size = al.m_size - dif;
- return true;
- }
-
- size = al.m_size;
- return true;
-}
-
-void
-IRMemoryMap::WriteMemory (lldb::addr_t process_address, const uint8_t *bytes, size_t size, Error &error)
-{
- error.Clear();
-
- AllocationMap::iterator iter = FindAllocation(process_address, size);
-
- if (iter == m_allocations.end())
- {
- lldb::ProcessSP process_sp = m_process_wp.lock();
-
- if (process_sp)
- {
- process_sp->WriteMemory(process_address, bytes, size, error);
- return;
- }
-
- error.SetErrorToGenericError();
- error.SetErrorString("Couldn't write: no allocation contains the target range and the process doesn't exist");
- return;
- }
-
- Allocation &allocation = iter->second;
-
- uint64_t offset = process_address - allocation.m_process_start;
-
- lldb::ProcessSP process_sp;
-
- switch (allocation.m_policy)
- {
- default:
- error.SetErrorToGenericError();
- error.SetErrorString("Couldn't write: invalid allocation policy");
- return;
- case eAllocationPolicyHostOnly:
- if (!allocation.m_data.GetByteSize())
- {
- error.SetErrorToGenericError();
- error.SetErrorString("Couldn't write: data buffer is empty");
- return;
- }
- ::memcpy (allocation.m_data.GetBytes() + offset, bytes, size);
- break;
- case eAllocationPolicyMirror:
- if (!allocation.m_data.GetByteSize())
- {
- error.SetErrorToGenericError();
- error.SetErrorString("Couldn't write: data buffer is empty");
- return;
- }
- ::memcpy (allocation.m_data.GetBytes() + offset, bytes, size);
- process_sp = m_process_wp.lock();
- if (process_sp)
- {
- process_sp->WriteMemory(process_address, bytes, size, error);
- if (!error.Success())
- return;
- }
- break;
- case eAllocationPolicyProcessOnly:
- process_sp = m_process_wp.lock();
- if (process_sp)
- {
- process_sp->WriteMemory(process_address, bytes, size, error);
- if (!error.Success())
- return;
- }
- break;
- }
-
- if (lldb_private::Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS))
- {
- log->Printf("IRMemoryMap::WriteMemory (0x%" PRIx64 ", 0x%" PRIx64 ", 0x%" PRId64 ") went to [0x%" PRIx64 "..0x%" PRIx64 ")",
- (uint64_t)process_address,
- (uint64_t)bytes,
- (uint64_t)size,
- (uint64_t)allocation.m_process_start,
- (uint64_t)allocation.m_process_start + (uint64_t)allocation.m_size);
- }
-}
-
-void
-IRMemoryMap::WriteScalarToMemory (lldb::addr_t process_address, Scalar &scalar, size_t size, Error &error)
-{
- error.Clear();
-
- if (size == UINT32_MAX)
- size = scalar.GetByteSize();
-
- if (size > 0)
- {
- uint8_t buf[32];
- const size_t mem_size = scalar.GetAsMemoryData (buf, size, GetByteOrder(), error);
- if (mem_size > 0)
- {
- return WriteMemory(process_address, buf, mem_size, error);
- }
+ break;
+ case eAllocationPolicyProcessOnly:
+ process_sp = m_process_wp.lock();
+ if (process_sp) {
+ if (process_sp->CanJIT() && process_sp->IsAlive()) {
+ if (!zero_memory)
+ allocation_address =
+ process_sp->AllocateMemory(allocation_size, permissions, error);
else
- {
- error.SetErrorToGenericError();
- error.SetErrorString ("Couldn't write scalar: failed to get scalar as memory data");
- }
- }
- else
- {
- error.SetErrorToGenericError();
- error.SetErrorString ("Couldn't write scalar: its size was zero");
- }
- return;
-}
-
-void
-IRMemoryMap::WritePointerToMemory (lldb::addr_t process_address, lldb::addr_t address, Error &error)
-{
- error.Clear();
-
- Scalar scalar(address);
-
- WriteScalarToMemory(process_address, scalar, GetAddressByteSize(), error);
-}
-
-void
-IRMemoryMap::ReadMemory (uint8_t *bytes, lldb::addr_t process_address, size_t size, Error &error)
-{
- error.Clear();
-
- AllocationMap::iterator iter = FindAllocation(process_address, size);
-
- if (iter == m_allocations.end())
- {
- lldb::ProcessSP process_sp = m_process_wp.lock();
-
- if (process_sp)
- {
- process_sp->ReadMemory(process_address, bytes, size, error);
- return;
- }
-
- lldb::TargetSP target_sp = m_target_wp.lock();
-
- if (target_sp)
- {
- Address absolute_address(process_address);
- target_sp->ReadMemory(absolute_address, false, bytes, size, error);
- return;
- }
-
- error.SetErrorToGenericError();
- error.SetErrorString("Couldn't read: no allocation contains the target range, and neither the process nor the target exist");
- return;
- }
-
- Allocation &allocation = iter->second;
-
- uint64_t offset = process_address - allocation.m_process_start;
-
- if (offset > allocation.m_size)
- {
- error.SetErrorToGenericError();
- error.SetErrorString("Couldn't read: data is not in the allocation");
- return;
- }
-
- lldb::ProcessSP process_sp;
-
- switch (allocation.m_policy)
- {
- default:
- error.SetErrorToGenericError();
- error.SetErrorString("Couldn't read: invalid allocation policy");
- return;
- case eAllocationPolicyHostOnly:
- if (!allocation.m_data.GetByteSize())
- {
- error.SetErrorToGenericError();
- error.SetErrorString("Couldn't read: data buffer is empty");
- return;
- }
- if (allocation.m_data.GetByteSize() < offset + size)
- {
- error.SetErrorToGenericError();
- error.SetErrorString("Couldn't read: not enough underlying data");
- return;
- }
-
- ::memcpy (bytes, allocation.m_data.GetBytes() + offset, size);
- break;
- case eAllocationPolicyMirror:
- process_sp = m_process_wp.lock();
- if (process_sp)
- {
- process_sp->ReadMemory(process_address, bytes, size, error);
- if (!error.Success())
- return;
- }
- else
- {
- if (!allocation.m_data.GetByteSize())
- {
- error.SetErrorToGenericError();
- error.SetErrorString("Couldn't read: data buffer is empty");
- return;
- }
- ::memcpy (bytes, allocation.m_data.GetBytes() + offset, size);
- }
- break;
- case eAllocationPolicyProcessOnly:
- process_sp = m_process_wp.lock();
- if (process_sp)
- {
- process_sp->ReadMemory(process_address, bytes, size, error);
- if (!error.Success())
- return;
- }
- break;
- }
-
- if (lldb_private::Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS))
- {
- log->Printf("IRMemoryMap::ReadMemory (0x%" PRIx64 ", 0x%" PRIx64 ", 0x%" PRId64 ") came from [0x%" PRIx64 "..0x%" PRIx64 ")",
- (uint64_t)process_address,
- (uint64_t)bytes,
- (uint64_t)size,
- (uint64_t)allocation.m_process_start,
- (uint64_t)allocation.m_process_start + (uint64_t)allocation.m_size);
- }
-}
-
-void
-IRMemoryMap::ReadScalarFromMemory (Scalar &scalar, lldb::addr_t process_address, size_t size, Error &error)
-{
- error.Clear();
-
- if (size > 0)
- {
- DataBufferHeap buf(size, 0);
- ReadMemory(buf.GetBytes(), process_address, size, error);
+ allocation_address =
+ process_sp->CallocateMemory(allocation_size, permissions, error);
if (!error.Success())
- return;
-
- DataExtractor extractor(buf.GetBytes(), buf.GetByteSize(), GetByteOrder(), GetAddressByteSize());
-
- lldb::offset_t offset = 0;
-
- switch (size)
- {
- default:
- error.SetErrorToGenericError();
- error.SetErrorStringWithFormat("Couldn't read scalar: unsupported size %" PRIu64, (uint64_t)size);
- return;
- case 1: scalar = extractor.GetU8(&offset); break;
- case 2: scalar = extractor.GetU16(&offset); break;
- case 4: scalar = extractor.GetU32(&offset); break;
- case 8: scalar = extractor.GetU64(&offset); break;
- }
- }
- else
- {
+ return LLDB_INVALID_ADDRESS;
+ } else {
error.SetErrorToGenericError();
- error.SetErrorString ("Couldn't read scalar: its size was zero");
+ error.SetErrorString(
+ "Couldn't malloc: process doesn't support allocating memory");
+ return LLDB_INVALID_ADDRESS;
+ }
+ } else {
+ error.SetErrorToGenericError();
+ error.SetErrorString("Couldn't malloc: process doesn't exist, and this "
+ "memory must be in the process");
+ return LLDB_INVALID_ADDRESS;
}
- return;
+ break;
+ }
+
+ lldb::addr_t mask = alignment - 1;
+ aligned_address = (allocation_address + mask) & (~mask);
+
+ m_allocations[aligned_address] =
+ Allocation(allocation_address, aligned_address, allocation_size,
+ permissions, alignment, policy);
+
+ if (zero_memory) {
+ Error write_error;
+ std::vector<uint8_t> zero_buf(size, 0);
+ WriteMemory(aligned_address, zero_buf.data(), size, write_error);
+ }
+
+ if (log) {
+ const char *policy_string;
+
+ switch (policy) {
+ default:
+ policy_string = "<invalid policy>";
+ break;
+ case eAllocationPolicyHostOnly:
+ policy_string = "eAllocationPolicyHostOnly";
+ break;
+ case eAllocationPolicyProcessOnly:
+ policy_string = "eAllocationPolicyProcessOnly";
+ break;
+ case eAllocationPolicyMirror:
+ policy_string = "eAllocationPolicyMirror";
+ break;
+ }
+
+ log->Printf("IRMemoryMap::Malloc (%" PRIu64 ", 0x%" PRIx64 ", 0x%" PRIx64
+ ", %s) -> 0x%" PRIx64,
+ (uint64_t)allocation_size, (uint64_t)alignment,
+ (uint64_t)permissions, policy_string, aligned_address);
+ }
+
+ return aligned_address;
}
-void
-IRMemoryMap::ReadPointerFromMemory (lldb::addr_t *address, lldb::addr_t process_address, Error &error)
-{
- error.Clear();
+void IRMemoryMap::Leak(lldb::addr_t process_address, Error &error) {
+ error.Clear();
- Scalar pointer_scalar;
- ReadScalarFromMemory(pointer_scalar, process_address, GetAddressByteSize(), error);
+ AllocationMap::iterator iter = m_allocations.find(process_address);
+
+ if (iter == m_allocations.end()) {
+ error.SetErrorToGenericError();
+ error.SetErrorString("Couldn't leak: allocation doesn't exist");
+ return;
+ }
+
+ Allocation &allocation = iter->second;
+
+ allocation.m_leak = true;
+}
+
+void IRMemoryMap::Free(lldb::addr_t process_address, Error &error) {
+ error.Clear();
+
+ AllocationMap::iterator iter = m_allocations.find(process_address);
+
+ if (iter == m_allocations.end()) {
+ error.SetErrorToGenericError();
+ error.SetErrorString("Couldn't free: allocation doesn't exist");
+ return;
+ }
+
+ Allocation &allocation = iter->second;
+
+ switch (allocation.m_policy) {
+ default:
+ case eAllocationPolicyHostOnly: {
+ lldb::ProcessSP process_sp = m_process_wp.lock();
+ if (process_sp) {
+ if (process_sp->CanJIT() && process_sp->IsAlive())
+ process_sp->DeallocateMemory(
+ allocation.m_process_alloc); // FindSpace allocated this for real
+ }
+
+ break;
+ }
+ case eAllocationPolicyMirror:
+ case eAllocationPolicyProcessOnly: {
+ lldb::ProcessSP process_sp = m_process_wp.lock();
+ if (process_sp)
+ process_sp->DeallocateMemory(allocation.m_process_alloc);
+ }
+ }
+
+ if (lldb_private::Log *log =
+ lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS)) {
+ log->Printf("IRMemoryMap::Free (0x%" PRIx64 ") freed [0x%" PRIx64
+ "..0x%" PRIx64 ")",
+ (uint64_t)process_address, iter->second.m_process_start,
+ iter->second.m_process_start + iter->second.m_size);
+ }
+
+ m_allocations.erase(iter);
+}
+
+bool IRMemoryMap::GetAllocSize(lldb::addr_t address, size_t &size) {
+ AllocationMap::iterator iter = FindAllocation(address, size);
+ if (iter == m_allocations.end())
+ return false;
+
+ Allocation &al = iter->second;
+
+ if (address > (al.m_process_start + al.m_size)) {
+ size = 0;
+ return false;
+ }
+
+ if (address > al.m_process_start) {
+ int dif = address - al.m_process_start;
+ size = al.m_size - dif;
+ return true;
+ }
+
+ size = al.m_size;
+ return true;
+}
+
+void IRMemoryMap::WriteMemory(lldb::addr_t process_address,
+ const uint8_t *bytes, size_t size, Error &error) {
+ error.Clear();
+
+ AllocationMap::iterator iter = FindAllocation(process_address, size);
+
+ if (iter == m_allocations.end()) {
+ lldb::ProcessSP process_sp = m_process_wp.lock();
+
+ if (process_sp) {
+ process_sp->WriteMemory(process_address, bytes, size, error);
+ return;
+ }
+
+ error.SetErrorToGenericError();
+ error.SetErrorString("Couldn't write: no allocation contains the target "
+ "range and the process doesn't exist");
+ return;
+ }
+
+ Allocation &allocation = iter->second;
+
+ uint64_t offset = process_address - allocation.m_process_start;
+
+ lldb::ProcessSP process_sp;
+
+ switch (allocation.m_policy) {
+ default:
+ error.SetErrorToGenericError();
+ error.SetErrorString("Couldn't write: invalid allocation policy");
+ return;
+ case eAllocationPolicyHostOnly:
+ if (!allocation.m_data.GetByteSize()) {
+ error.SetErrorToGenericError();
+ error.SetErrorString("Couldn't write: data buffer is empty");
+ return;
+ }
+ ::memcpy(allocation.m_data.GetBytes() + offset, bytes, size);
+ break;
+ case eAllocationPolicyMirror:
+ if (!allocation.m_data.GetByteSize()) {
+ error.SetErrorToGenericError();
+ error.SetErrorString("Couldn't write: data buffer is empty");
+ return;
+ }
+ ::memcpy(allocation.m_data.GetBytes() + offset, bytes, size);
+ process_sp = m_process_wp.lock();
+ if (process_sp) {
+ process_sp->WriteMemory(process_address, bytes, size, error);
+ if (!error.Success())
+ return;
+ }
+ break;
+ case eAllocationPolicyProcessOnly:
+ process_sp = m_process_wp.lock();
+ if (process_sp) {
+ process_sp->WriteMemory(process_address, bytes, size, error);
+ if (!error.Success())
+ return;
+ }
+ break;
+ }
+
+ if (lldb_private::Log *log =
+ lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS)) {
+ log->Printf("IRMemoryMap::WriteMemory (0x%" PRIx64 ", 0x%" PRIx64
+ ", 0x%" PRId64 ") went to [0x%" PRIx64 "..0x%" PRIx64 ")",
+ (uint64_t)process_address, (uint64_t)bytes, (uint64_t)size,
+ (uint64_t)allocation.m_process_start,
+ (uint64_t)allocation.m_process_start +
+ (uint64_t)allocation.m_size);
+ }
+}
+
+void IRMemoryMap::WriteScalarToMemory(lldb::addr_t process_address,
+ Scalar &scalar, size_t size,
+ Error &error) {
+ error.Clear();
+
+ if (size == UINT32_MAX)
+ size = scalar.GetByteSize();
+
+ if (size > 0) {
+ uint8_t buf[32];
+ const size_t mem_size =
+ scalar.GetAsMemoryData(buf, size, GetByteOrder(), error);
+ if (mem_size > 0) {
+ return WriteMemory(process_address, buf, mem_size, error);
+ } else {
+ error.SetErrorToGenericError();
+ error.SetErrorString(
+ "Couldn't write scalar: failed to get scalar as memory data");
+ }
+ } else {
+ error.SetErrorToGenericError();
+ error.SetErrorString("Couldn't write scalar: its size was zero");
+ }
+ return;
+}
+
+void IRMemoryMap::WritePointerToMemory(lldb::addr_t process_address,
+ lldb::addr_t address, Error &error) {
+ error.Clear();
+
+ Scalar scalar(address);
+
+ WriteScalarToMemory(process_address, scalar, GetAddressByteSize(), error);
+}
+
+void IRMemoryMap::ReadMemory(uint8_t *bytes, lldb::addr_t process_address,
+ size_t size, Error &error) {
+ error.Clear();
+
+ AllocationMap::iterator iter = FindAllocation(process_address, size);
+
+ if (iter == m_allocations.end()) {
+ lldb::ProcessSP process_sp = m_process_wp.lock();
+
+ if (process_sp) {
+ process_sp->ReadMemory(process_address, bytes, size, error);
+ return;
+ }
+
+ lldb::TargetSP target_sp = m_target_wp.lock();
+
+ if (target_sp) {
+ Address absolute_address(process_address);
+ target_sp->ReadMemory(absolute_address, false, bytes, size, error);
+ return;
+ }
+
+ error.SetErrorToGenericError();
+ error.SetErrorString("Couldn't read: no allocation contains the target "
+ "range, and neither the process nor the target exist");
+ return;
+ }
+
+ Allocation &allocation = iter->second;
+
+ uint64_t offset = process_address - allocation.m_process_start;
+
+ if (offset > allocation.m_size) {
+ error.SetErrorToGenericError();
+ error.SetErrorString("Couldn't read: data is not in the allocation");
+ return;
+ }
+
+ lldb::ProcessSP process_sp;
+
+ switch (allocation.m_policy) {
+ default:
+ error.SetErrorToGenericError();
+ error.SetErrorString("Couldn't read: invalid allocation policy");
+ return;
+ case eAllocationPolicyHostOnly:
+ if (!allocation.m_data.GetByteSize()) {
+ error.SetErrorToGenericError();
+ error.SetErrorString("Couldn't read: data buffer is empty");
+ return;
+ }
+ if (allocation.m_data.GetByteSize() < offset + size) {
+ error.SetErrorToGenericError();
+ error.SetErrorString("Couldn't read: not enough underlying data");
+ return;
+ }
+
+ ::memcpy(bytes, allocation.m_data.GetBytes() + offset, size);
+ break;
+ case eAllocationPolicyMirror:
+ process_sp = m_process_wp.lock();
+ if (process_sp) {
+ process_sp->ReadMemory(process_address, bytes, size, error);
+ if (!error.Success())
+ return;
+ } else {
+ if (!allocation.m_data.GetByteSize()) {
+ error.SetErrorToGenericError();
+ error.SetErrorString("Couldn't read: data buffer is empty");
+ return;
+ }
+ ::memcpy(bytes, allocation.m_data.GetBytes() + offset, size);
+ }
+ break;
+ case eAllocationPolicyProcessOnly:
+ process_sp = m_process_wp.lock();
+ if (process_sp) {
+ process_sp->ReadMemory(process_address, bytes, size, error);
+ if (!error.Success())
+ return;
+ }
+ break;
+ }
+
+ if (lldb_private::Log *log =
+ lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS)) {
+ log->Printf("IRMemoryMap::ReadMemory (0x%" PRIx64 ", 0x%" PRIx64
+ ", 0x%" PRId64 ") came from [0x%" PRIx64 "..0x%" PRIx64 ")",
+ (uint64_t)process_address, (uint64_t)bytes, (uint64_t)size,
+ (uint64_t)allocation.m_process_start,
+ (uint64_t)allocation.m_process_start +
+ (uint64_t)allocation.m_size);
+ }
+}
+
+void IRMemoryMap::ReadScalarFromMemory(Scalar &scalar,
+ lldb::addr_t process_address,
+ size_t size, Error &error) {
+ error.Clear();
+
+ if (size > 0) {
+ DataBufferHeap buf(size, 0);
+ ReadMemory(buf.GetBytes(), process_address, size, error);
if (!error.Success())
- return;
+ return;
- *address = pointer_scalar.ULongLong();
+ DataExtractor extractor(buf.GetBytes(), buf.GetByteSize(), GetByteOrder(),
+ GetAddressByteSize());
- return;
+ lldb::offset_t offset = 0;
+
+ switch (size) {
+ default:
+ error.SetErrorToGenericError();
+ error.SetErrorStringWithFormat(
+ "Couldn't read scalar: unsupported size %" PRIu64, (uint64_t)size);
+ return;
+ case 1:
+ scalar = extractor.GetU8(&offset);
+ break;
+ case 2:
+ scalar = extractor.GetU16(&offset);
+ break;
+ case 4:
+ scalar = extractor.GetU32(&offset);
+ break;
+ case 8:
+ scalar = extractor.GetU64(&offset);
+ break;
+ }
+ } else {
+ error.SetErrorToGenericError();
+ error.SetErrorString("Couldn't read scalar: its size was zero");
+ }
+ return;
}
-void
-IRMemoryMap::GetMemoryData (DataExtractor &extractor, lldb::addr_t process_address, size_t size, Error &error)
-{
- error.Clear();
+void IRMemoryMap::ReadPointerFromMemory(lldb::addr_t *address,
+ lldb::addr_t process_address,
+ Error &error) {
+ error.Clear();
- if (size > 0)
- {
- AllocationMap::iterator iter = FindAllocation(process_address, size);
+ Scalar pointer_scalar;
+ ReadScalarFromMemory(pointer_scalar, process_address, GetAddressByteSize(),
+ error);
- if (iter == m_allocations.end())
- {
- error.SetErrorToGenericError();
- error.SetErrorStringWithFormat("Couldn't find an allocation containing [0x%" PRIx64 "..0x%" PRIx64 ")", process_address, process_address + size);
- return;
- }
+ if (!error.Success())
+ return;
- Allocation &allocation = iter->second;
+ *address = pointer_scalar.ULongLong();
- switch (allocation.m_policy)
- {
- default:
- error.SetErrorToGenericError();
- error.SetErrorString("Couldn't get memory data: invalid allocation policy");
- return;
- case eAllocationPolicyProcessOnly:
- error.SetErrorToGenericError();
- error.SetErrorString("Couldn't get memory data: memory is only in the target");
- return;
- case eAllocationPolicyMirror:
- {
- lldb::ProcessSP process_sp = m_process_wp.lock();
+ return;
+}
- if (!allocation.m_data.GetByteSize())
- {
- error.SetErrorToGenericError();
- error.SetErrorString("Couldn't get memory data: data buffer is empty");
- return;
- }
- if (process_sp)
- {
- process_sp->ReadMemory(allocation.m_process_start, allocation.m_data.GetBytes(), allocation.m_data.GetByteSize(), error);
- if (!error.Success())
- return;
- uint64_t offset = process_address - allocation.m_process_start;
- extractor = DataExtractor(allocation.m_data.GetBytes() + offset, size, GetByteOrder(), GetAddressByteSize());
- return;
- }
- }
- break;
- case eAllocationPolicyHostOnly:
- if (!allocation.m_data.GetByteSize())
- {
- error.SetErrorToGenericError();
- error.SetErrorString("Couldn't get memory data: data buffer is empty");
- return;
- }
- uint64_t offset = process_address - allocation.m_process_start;
- extractor = DataExtractor(allocation.m_data.GetBytes() + offset, size, GetByteOrder(), GetAddressByteSize());
- return;
- }
+void IRMemoryMap::GetMemoryData(DataExtractor &extractor,
+ lldb::addr_t process_address, size_t size,
+ Error &error) {
+ error.Clear();
+
+ if (size > 0) {
+ AllocationMap::iterator iter = FindAllocation(process_address, size);
+
+ if (iter == m_allocations.end()) {
+ error.SetErrorToGenericError();
+ error.SetErrorStringWithFormat(
+ "Couldn't find an allocation containing [0x%" PRIx64 "..0x%" PRIx64
+ ")",
+ process_address, process_address + size);
+ return;
}
- else
- {
+
+ Allocation &allocation = iter->second;
+
+ switch (allocation.m_policy) {
+ default:
+ error.SetErrorToGenericError();
+ error.SetErrorString(
+ "Couldn't get memory data: invalid allocation policy");
+ return;
+ case eAllocationPolicyProcessOnly:
+ error.SetErrorToGenericError();
+ error.SetErrorString(
+ "Couldn't get memory data: memory is only in the target");
+ return;
+ case eAllocationPolicyMirror: {
+ lldb::ProcessSP process_sp = m_process_wp.lock();
+
+ if (!allocation.m_data.GetByteSize()) {
error.SetErrorToGenericError();
- error.SetErrorString ("Couldn't get memory data: its size was zero");
+ error.SetErrorString("Couldn't get memory data: data buffer is empty");
return;
+ }
+ if (process_sp) {
+ process_sp->ReadMemory(allocation.m_process_start,
+ allocation.m_data.GetBytes(),
+ allocation.m_data.GetByteSize(), error);
+ if (!error.Success())
+ return;
+ uint64_t offset = process_address - allocation.m_process_start;
+ extractor = DataExtractor(allocation.m_data.GetBytes() + offset, size,
+ GetByteOrder(), GetAddressByteSize());
+ return;
+ }
+ } break;
+ case eAllocationPolicyHostOnly:
+ if (!allocation.m_data.GetByteSize()) {
+ error.SetErrorToGenericError();
+ error.SetErrorString("Couldn't get memory data: data buffer is empty");
+ return;
+ }
+ uint64_t offset = process_address - allocation.m_process_start;
+ extractor = DataExtractor(allocation.m_data.GetBytes() + offset, size,
+ GetByteOrder(), GetAddressByteSize());
+ return;
}
+ } else {
+ error.SetErrorToGenericError();
+ error.SetErrorString("Couldn't get memory data: its size was zero");
+ return;
+ }
}
diff --git a/lldb/source/Expression/LLVMUserExpression.cpp b/lldb/source/Expression/LLVMUserExpression.cpp
index 0b96980..92347de 100644
--- a/lldb/source/Expression/LLVMUserExpression.cpp
+++ b/lldb/source/Expression/LLVMUserExpression.cpp
@@ -41,341 +41,337 @@
using namespace lldb_private;
-LLVMUserExpression::LLVMUserExpression(ExecutionContextScope &exe_scope,
- const char *expr,
+LLVMUserExpression::LLVMUserExpression(ExecutionContextScope &exe_scope,
+ const char *expr,
const char *expr_prefix,
- lldb::LanguageType language,
- ResultType desired_type,
+ lldb::LanguageType language,
+ ResultType desired_type,
const EvaluateExpressionOptions &options)
- : UserExpression(exe_scope, expr, expr_prefix, language, desired_type, options),
+ : UserExpression(exe_scope, expr, expr_prefix, language, desired_type,
+ options),
m_stack_frame_bottom(LLDB_INVALID_ADDRESS),
- m_stack_frame_top(LLDB_INVALID_ADDRESS),
- m_transformed_text(),
- m_execution_unit_sp(),
- m_materializer_ap(),
- m_jit_module_wp(),
- m_enforce_valid_object(true),
- m_in_cplusplus_method(false),
- m_in_objectivec_method(false),
- m_in_static_method(false),
- m_needs_object_ptr(false),
- m_target(NULL),
- m_can_interpret(false),
- m_materialized_address(LLDB_INVALID_ADDRESS)
-{
-}
+ m_stack_frame_top(LLDB_INVALID_ADDRESS), m_transformed_text(),
+ m_execution_unit_sp(), m_materializer_ap(), m_jit_module_wp(),
+ m_enforce_valid_object(true), m_in_cplusplus_method(false),
+ m_in_objectivec_method(false), m_in_static_method(false),
+ m_needs_object_ptr(false), m_target(NULL), m_can_interpret(false),
+ m_materialized_address(LLDB_INVALID_ADDRESS) {}
-LLVMUserExpression::~LLVMUserExpression()
-{
- if (m_target)
- {
- lldb::ModuleSP jit_module_sp(m_jit_module_wp.lock());
- if (jit_module_sp)
- m_target->GetImages().Remove(jit_module_sp);
- }
+LLVMUserExpression::~LLVMUserExpression() {
+ if (m_target) {
+ lldb::ModuleSP jit_module_sp(m_jit_module_wp.lock());
+ if (jit_module_sp)
+ m_target->GetImages().Remove(jit_module_sp);
+ }
}
lldb::ExpressionResults
-LLVMUserExpression::DoExecute(DiagnosticManager &diagnostic_manager, ExecutionContext &exe_ctx,
- const EvaluateExpressionOptions &options, lldb::UserExpressionSP &shared_ptr_to_me,
- lldb::ExpressionVariableSP &result)
-{
- // The expression log is quite verbose, and if you're just tracking the execution of the
- // expression, it's quite convenient to have these logs come out with the STEP log as well.
- Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_EXPRESSIONS | LIBLLDB_LOG_STEP));
+LLVMUserExpression::DoExecute(DiagnosticManager &diagnostic_manager,
+ ExecutionContext &exe_ctx,
+ const EvaluateExpressionOptions &options,
+ lldb::UserExpressionSP &shared_ptr_to_me,
+ lldb::ExpressionVariableSP &result) {
+ // The expression log is quite verbose, and if you're just tracking the
+ // execution of the
+ // expression, it's quite convenient to have these logs come out with the STEP
+ // log as well.
+ Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_EXPRESSIONS |
+ LIBLLDB_LOG_STEP));
- if (m_jit_start_addr != LLDB_INVALID_ADDRESS || m_can_interpret)
- {
- lldb::addr_t struct_address = LLDB_INVALID_ADDRESS;
+ if (m_jit_start_addr != LLDB_INVALID_ADDRESS || m_can_interpret) {
+ lldb::addr_t struct_address = LLDB_INVALID_ADDRESS;
- if (!PrepareToExecuteJITExpression(diagnostic_manager, exe_ctx, struct_address))
- {
- diagnostic_manager.Printf(eDiagnosticSeverityError,
- "errored out in %s, couldn't PrepareToExecuteJITExpression", __FUNCTION__);
- return lldb::eExpressionSetupError;
- }
-
- lldb::addr_t function_stack_bottom = LLDB_INVALID_ADDRESS;
- lldb::addr_t function_stack_top = LLDB_INVALID_ADDRESS;
-
- if (m_can_interpret)
- {
- llvm::Module *module = m_execution_unit_sp->GetModule();
- llvm::Function *function = m_execution_unit_sp->GetFunction();
-
- if (!module || !function)
- {
- diagnostic_manager.PutCString(eDiagnosticSeverityError, "supposed to interpret, but nothing is there");
- return lldb::eExpressionSetupError;
- }
-
- Error interpreter_error;
-
- std::vector<lldb::addr_t> args;
-
- if (!AddArguments(exe_ctx, args, struct_address, diagnostic_manager))
- {
- diagnostic_manager.Printf(eDiagnosticSeverityError, "errored out in %s, couldn't AddArguments",
- __FUNCTION__);
- return lldb::eExpressionSetupError;
- }
-
- function_stack_bottom = m_stack_frame_bottom;
- function_stack_top = m_stack_frame_top;
-
- IRInterpreter::Interpret(*module, *function, args, *m_execution_unit_sp.get(), interpreter_error,
- function_stack_bottom, function_stack_top, exe_ctx);
-
- if (!interpreter_error.Success())
- {
- diagnostic_manager.Printf(eDiagnosticSeverityError, "supposed to interpret, but failed: %s",
- interpreter_error.AsCString());
- return lldb::eExpressionDiscarded;
- }
- }
- else
- {
- if (!exe_ctx.HasThreadScope())
- {
- diagnostic_manager.Printf(eDiagnosticSeverityError, "%s called with no thread selected", __FUNCTION__);
- return lldb::eExpressionSetupError;
- }
-
- Address wrapper_address(m_jit_start_addr);
-
- std::vector<lldb::addr_t> args;
-
- if (!AddArguments(exe_ctx, args, struct_address, diagnostic_manager))
- {
- diagnostic_manager.Printf(eDiagnosticSeverityError, "errored out in %s, couldn't AddArguments",
- __FUNCTION__);
- return lldb::eExpressionSetupError;
- }
-
- lldb::ThreadPlanSP call_plan_sp(new ThreadPlanCallUserExpression(exe_ctx.GetThreadRef(), wrapper_address,
- args, options, shared_ptr_to_me));
-
- StreamString ss;
- if (!call_plan_sp || !call_plan_sp->ValidatePlan(&ss))
- {
- diagnostic_manager.PutCString(eDiagnosticSeverityError, ss.GetData());
- return lldb::eExpressionSetupError;
- }
-
- ThreadPlanCallUserExpression *user_expression_plan =
- static_cast<ThreadPlanCallUserExpression *>(call_plan_sp.get());
-
- lldb::addr_t function_stack_pointer = user_expression_plan->GetFunctionStackPointer();
-
- function_stack_bottom = function_stack_pointer - HostInfo::GetPageSize();
- function_stack_top = function_stack_pointer;
-
- if (log)
- log->Printf("-- [UserExpression::Execute] Execution of expression begins --");
-
- if (exe_ctx.GetProcessPtr())
- exe_ctx.GetProcessPtr()->SetRunningUserExpression(true);
-
- lldb::ExpressionResults execution_result =
- exe_ctx.GetProcessRef().RunThreadPlan(exe_ctx, call_plan_sp, options, diagnostic_manager);
-
- if (exe_ctx.GetProcessPtr())
- exe_ctx.GetProcessPtr()->SetRunningUserExpression(false);
-
- if (log)
- log->Printf("-- [UserExpression::Execute] Execution of expression completed --");
-
- if (execution_result == lldb::eExpressionInterrupted || execution_result == lldb::eExpressionHitBreakpoint)
- {
- const char *error_desc = NULL;
-
- if (call_plan_sp)
- {
- lldb::StopInfoSP real_stop_info_sp = call_plan_sp->GetRealStopInfo();
- if (real_stop_info_sp)
- error_desc = real_stop_info_sp->GetDescription();
- }
- if (error_desc)
- diagnostic_manager.Printf(eDiagnosticSeverityError, "Execution was interrupted, reason: %s.",
- error_desc);
- else
- diagnostic_manager.PutCString(eDiagnosticSeverityError, "Execution was interrupted.");
-
- if ((execution_result == lldb::eExpressionInterrupted && options.DoesUnwindOnError()) ||
- (execution_result == lldb::eExpressionHitBreakpoint && options.DoesIgnoreBreakpoints()))
- diagnostic_manager.AppendMessageToDiagnostic(
- "The process has been returned to the state before expression evaluation.");
- else
- {
- if (execution_result == lldb::eExpressionHitBreakpoint)
- user_expression_plan->TransferExpressionOwnership();
- diagnostic_manager.AppendMessageToDiagnostic(
- "The process has been left at the point where it was interrupted, "
- "use \"thread return -x\" to return to the state before expression evaluation.");
- }
-
- return execution_result;
- }
- else if (execution_result == lldb::eExpressionStoppedForDebug)
- {
- diagnostic_manager.PutCString(
- eDiagnosticSeverityRemark,
- "Execution was halted at the first instruction of the expression "
- "function because \"debug\" was requested.\n"
- "Use \"thread return -x\" to return to the state before expression evaluation.");
- return execution_result;
- }
- else if (execution_result != lldb::eExpressionCompleted)
- {
- diagnostic_manager.Printf(eDiagnosticSeverityError, "Couldn't execute function; result was %s",
- Process::ExecutionResultAsCString(execution_result));
- return execution_result;
- }
- }
-
- if (FinalizeJITExecution(diagnostic_manager, exe_ctx, result, function_stack_bottom, function_stack_top))
- {
- return lldb::eExpressionCompleted;
- }
- else
- {
- return lldb::eExpressionResultUnavailable;
- }
+ if (!PrepareToExecuteJITExpression(diagnostic_manager, exe_ctx,
+ struct_address)) {
+ diagnostic_manager.Printf(
+ eDiagnosticSeverityError,
+ "errored out in %s, couldn't PrepareToExecuteJITExpression",
+ __FUNCTION__);
+ return lldb::eExpressionSetupError;
}
- else
- {
- diagnostic_manager.PutCString(eDiagnosticSeverityError,
- "Expression can't be run, because there is no JIT compiled function");
+
+ lldb::addr_t function_stack_bottom = LLDB_INVALID_ADDRESS;
+ lldb::addr_t function_stack_top = LLDB_INVALID_ADDRESS;
+
+ if (m_can_interpret) {
+ llvm::Module *module = m_execution_unit_sp->GetModule();
+ llvm::Function *function = m_execution_unit_sp->GetFunction();
+
+ if (!module || !function) {
+ diagnostic_manager.PutCString(
+ eDiagnosticSeverityError,
+ "supposed to interpret, but nothing is there");
return lldb::eExpressionSetupError;
- }
-}
+ }
-bool
-LLVMUserExpression::FinalizeJITExecution(DiagnosticManager &diagnostic_manager, ExecutionContext &exe_ctx,
- lldb::ExpressionVariableSP &result, lldb::addr_t function_stack_bottom,
- lldb::addr_t function_stack_top)
-{
- Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS));
+ Error interpreter_error;
- if (log)
- log->Printf("-- [UserExpression::FinalizeJITExecution] Dematerializing after execution --");
+ std::vector<lldb::addr_t> args;
- if (!m_dematerializer_sp)
- {
+ if (!AddArguments(exe_ctx, args, struct_address, diagnostic_manager)) {
diagnostic_manager.Printf(eDiagnosticSeverityError,
- "Couldn't apply expression side effects : no dematerializer is present");
- return false;
+ "errored out in %s, couldn't AddArguments",
+ __FUNCTION__);
+ return lldb::eExpressionSetupError;
+ }
+
+ function_stack_bottom = m_stack_frame_bottom;
+ function_stack_top = m_stack_frame_top;
+
+ IRInterpreter::Interpret(*module, *function, args,
+ *m_execution_unit_sp.get(), interpreter_error,
+ function_stack_bottom, function_stack_top,
+ exe_ctx);
+
+ if (!interpreter_error.Success()) {
+ diagnostic_manager.Printf(eDiagnosticSeverityError,
+ "supposed to interpret, but failed: %s",
+ interpreter_error.AsCString());
+ return lldb::eExpressionDiscarded;
+ }
+ } else {
+ if (!exe_ctx.HasThreadScope()) {
+ diagnostic_manager.Printf(eDiagnosticSeverityError,
+ "%s called with no thread selected",
+ __FUNCTION__);
+ return lldb::eExpressionSetupError;
+ }
+
+ Address wrapper_address(m_jit_start_addr);
+
+ std::vector<lldb::addr_t> args;
+
+ if (!AddArguments(exe_ctx, args, struct_address, diagnostic_manager)) {
+ diagnostic_manager.Printf(eDiagnosticSeverityError,
+ "errored out in %s, couldn't AddArguments",
+ __FUNCTION__);
+ return lldb::eExpressionSetupError;
+ }
+
+ lldb::ThreadPlanSP call_plan_sp(new ThreadPlanCallUserExpression(
+ exe_ctx.GetThreadRef(), wrapper_address, args, options,
+ shared_ptr_to_me));
+
+ StreamString ss;
+ if (!call_plan_sp || !call_plan_sp->ValidatePlan(&ss)) {
+ diagnostic_manager.PutCString(eDiagnosticSeverityError, ss.GetData());
+ return lldb::eExpressionSetupError;
+ }
+
+ ThreadPlanCallUserExpression *user_expression_plan =
+ static_cast<ThreadPlanCallUserExpression *>(call_plan_sp.get());
+
+ lldb::addr_t function_stack_pointer =
+ user_expression_plan->GetFunctionStackPointer();
+
+ function_stack_bottom = function_stack_pointer - HostInfo::GetPageSize();
+ function_stack_top = function_stack_pointer;
+
+ if (log)
+ log->Printf(
+ "-- [UserExpression::Execute] Execution of expression begins --");
+
+ if (exe_ctx.GetProcessPtr())
+ exe_ctx.GetProcessPtr()->SetRunningUserExpression(true);
+
+ lldb::ExpressionResults execution_result =
+ exe_ctx.GetProcessRef().RunThreadPlan(exe_ctx, call_plan_sp, options,
+ diagnostic_manager);
+
+ if (exe_ctx.GetProcessPtr())
+ exe_ctx.GetProcessPtr()->SetRunningUserExpression(false);
+
+ if (log)
+ log->Printf("-- [UserExpression::Execute] Execution of expression "
+ "completed --");
+
+ if (execution_result == lldb::eExpressionInterrupted ||
+ execution_result == lldb::eExpressionHitBreakpoint) {
+ const char *error_desc = NULL;
+
+ if (call_plan_sp) {
+ lldb::StopInfoSP real_stop_info_sp = call_plan_sp->GetRealStopInfo();
+ if (real_stop_info_sp)
+ error_desc = real_stop_info_sp->GetDescription();
+ }
+ if (error_desc)
+ diagnostic_manager.Printf(eDiagnosticSeverityError,
+ "Execution was interrupted, reason: %s.",
+ error_desc);
+ else
+ diagnostic_manager.PutCString(eDiagnosticSeverityError,
+ "Execution was interrupted.");
+
+ if ((execution_result == lldb::eExpressionInterrupted &&
+ options.DoesUnwindOnError()) ||
+ (execution_result == lldb::eExpressionHitBreakpoint &&
+ options.DoesIgnoreBreakpoints()))
+ diagnostic_manager.AppendMessageToDiagnostic(
+ "The process has been returned to the state before expression "
+ "evaluation.");
+ else {
+ if (execution_result == lldb::eExpressionHitBreakpoint)
+ user_expression_plan->TransferExpressionOwnership();
+ diagnostic_manager.AppendMessageToDiagnostic(
+ "The process has been left at the point where it was "
+ "interrupted, "
+ "use \"thread return -x\" to return to the state before "
+ "expression evaluation.");
+ }
+
+ return execution_result;
+ } else if (execution_result == lldb::eExpressionStoppedForDebug) {
+ diagnostic_manager.PutCString(
+ eDiagnosticSeverityRemark,
+ "Execution was halted at the first instruction of the expression "
+ "function because \"debug\" was requested.\n"
+ "Use \"thread return -x\" to return to the state before expression "
+ "evaluation.");
+ return execution_result;
+ } else if (execution_result != lldb::eExpressionCompleted) {
+ diagnostic_manager.Printf(
+ eDiagnosticSeverityError,
+ "Couldn't execute function; result was %s",
+ Process::ExecutionResultAsCString(execution_result));
+ return execution_result;
+ }
}
- Error dematerialize_error;
-
- m_dematerializer_sp->Dematerialize(dematerialize_error, function_stack_bottom, function_stack_top);
-
- if (!dematerialize_error.Success())
- {
- diagnostic_manager.Printf(eDiagnosticSeverityError, "Couldn't apply expression side effects : %s",
- dematerialize_error.AsCString("unknown error"));
- return false;
+ if (FinalizeJITExecution(diagnostic_manager, exe_ctx, result,
+ function_stack_bottom, function_stack_top)) {
+ return lldb::eExpressionCompleted;
+ } else {
+ return lldb::eExpressionResultUnavailable;
}
-
- result = GetResultAfterDematerialization(exe_ctx.GetBestExecutionContextScope());
-
- if (result)
- result->TransferAddress();
-
- m_dematerializer_sp.reset();
-
- return true;
+ } else {
+ diagnostic_manager.PutCString(
+ eDiagnosticSeverityError,
+ "Expression can't be run, because there is no JIT compiled function");
+ return lldb::eExpressionSetupError;
+ }
}
-bool
-LLVMUserExpression::PrepareToExecuteJITExpression(DiagnosticManager &diagnostic_manager, ExecutionContext &exe_ctx,
- lldb::addr_t &struct_address)
-{
- lldb::TargetSP target;
- lldb::ProcessSP process;
- lldb::StackFrameSP frame;
+bool LLVMUserExpression::FinalizeJITExecution(
+ DiagnosticManager &diagnostic_manager, ExecutionContext &exe_ctx,
+ lldb::ExpressionVariableSP &result, lldb::addr_t function_stack_bottom,
+ lldb::addr_t function_stack_top) {
+ Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS));
- if (!LockAndCheckContext(exe_ctx, target, process, frame))
- {
- diagnostic_manager.PutCString(eDiagnosticSeverityError,
- "The context has changed before we could JIT the expression!");
- return false;
- }
+ if (log)
+ log->Printf("-- [UserExpression::FinalizeJITExecution] Dematerializing "
+ "after execution --");
- if (m_jit_start_addr != LLDB_INVALID_ADDRESS || m_can_interpret)
- {
- if (m_materialized_address == LLDB_INVALID_ADDRESS)
- {
- Error alloc_error;
+ if (!m_dematerializer_sp) {
+ diagnostic_manager.Printf(eDiagnosticSeverityError,
+ "Couldn't apply expression side effects : no "
+ "dematerializer is present");
+ return false;
+ }
- IRMemoryMap::AllocationPolicy policy =
- m_can_interpret ? IRMemoryMap::eAllocationPolicyHostOnly : IRMemoryMap::eAllocationPolicyMirror;
+ Error dematerialize_error;
- const bool zero_memory = false;
+ m_dematerializer_sp->Dematerialize(dematerialize_error, function_stack_bottom,
+ function_stack_top);
- m_materialized_address = m_execution_unit_sp->Malloc(m_materializer_ap->GetStructByteSize(),
- m_materializer_ap->GetStructAlignment(),
- lldb::ePermissionsReadable | lldb::ePermissionsWritable,
- policy,
- zero_memory,
- alloc_error);
+ if (!dematerialize_error.Success()) {
+ diagnostic_manager.Printf(eDiagnosticSeverityError,
+ "Couldn't apply expression side effects : %s",
+ dematerialize_error.AsCString("unknown error"));
+ return false;
+ }
- if (!alloc_error.Success())
- {
- diagnostic_manager.Printf(eDiagnosticSeverityError,
- "Couldn't allocate space for materialized struct: %s",
- alloc_error.AsCString());
- return false;
- }
- }
+ result =
+ GetResultAfterDematerialization(exe_ctx.GetBestExecutionContextScope());
- struct_address = m_materialized_address;
+ if (result)
+ result->TransferAddress();
- if (m_can_interpret && m_stack_frame_bottom == LLDB_INVALID_ADDRESS)
- {
- Error alloc_error;
+ m_dematerializer_sp.reset();
- const size_t stack_frame_size = 512 * 1024;
-
- const bool zero_memory = false;
-
- m_stack_frame_bottom = m_execution_unit_sp->Malloc(stack_frame_size,
- 8,
- lldb::ePermissionsReadable | lldb::ePermissionsWritable,
- IRMemoryMap::eAllocationPolicyHostOnly,
- zero_memory,
- alloc_error);
-
- m_stack_frame_top = m_stack_frame_bottom + stack_frame_size;
-
- if (!alloc_error.Success())
- {
- diagnostic_manager.Printf(eDiagnosticSeverityError, "Couldn't allocate space for the stack frame: %s",
- alloc_error.AsCString());
- return false;
- }
- }
-
- Error materialize_error;
-
- m_dematerializer_sp =
- m_materializer_ap->Materialize(frame, *m_execution_unit_sp, struct_address, materialize_error);
-
- if (!materialize_error.Success())
- {
- diagnostic_manager.Printf(eDiagnosticSeverityError, "Couldn't materialize: %s",
- materialize_error.AsCString());
- return false;
- }
- }
- return true;
+ return true;
}
-lldb::ModuleSP
-LLVMUserExpression::GetJITModule()
-{
- if (m_execution_unit_sp)
- return m_execution_unit_sp->GetJITModule();
- return lldb::ModuleSP();
+bool LLVMUserExpression::PrepareToExecuteJITExpression(
+ DiagnosticManager &diagnostic_manager, ExecutionContext &exe_ctx,
+ lldb::addr_t &struct_address) {
+ lldb::TargetSP target;
+ lldb::ProcessSP process;
+ lldb::StackFrameSP frame;
+
+ if (!LockAndCheckContext(exe_ctx, target, process, frame)) {
+ diagnostic_manager.PutCString(
+ eDiagnosticSeverityError,
+ "The context has changed before we could JIT the expression!");
+ return false;
+ }
+
+ if (m_jit_start_addr != LLDB_INVALID_ADDRESS || m_can_interpret) {
+ if (m_materialized_address == LLDB_INVALID_ADDRESS) {
+ Error alloc_error;
+
+ IRMemoryMap::AllocationPolicy policy =
+ m_can_interpret ? IRMemoryMap::eAllocationPolicyHostOnly
+ : IRMemoryMap::eAllocationPolicyMirror;
+
+ const bool zero_memory = false;
+
+ m_materialized_address = m_execution_unit_sp->Malloc(
+ m_materializer_ap->GetStructByteSize(),
+ m_materializer_ap->GetStructAlignment(),
+ lldb::ePermissionsReadable | lldb::ePermissionsWritable, policy,
+ zero_memory, alloc_error);
+
+ if (!alloc_error.Success()) {
+ diagnostic_manager.Printf(
+ eDiagnosticSeverityError,
+ "Couldn't allocate space for materialized struct: %s",
+ alloc_error.AsCString());
+ return false;
+ }
+ }
+
+ struct_address = m_materialized_address;
+
+ if (m_can_interpret && m_stack_frame_bottom == LLDB_INVALID_ADDRESS) {
+ Error alloc_error;
+
+ const size_t stack_frame_size = 512 * 1024;
+
+ const bool zero_memory = false;
+
+ m_stack_frame_bottom = m_execution_unit_sp->Malloc(
+ stack_frame_size, 8,
+ lldb::ePermissionsReadable | lldb::ePermissionsWritable,
+ IRMemoryMap::eAllocationPolicyHostOnly, zero_memory, alloc_error);
+
+ m_stack_frame_top = m_stack_frame_bottom + stack_frame_size;
+
+ if (!alloc_error.Success()) {
+ diagnostic_manager.Printf(
+ eDiagnosticSeverityError,
+ "Couldn't allocate space for the stack frame: %s",
+ alloc_error.AsCString());
+ return false;
+ }
+ }
+
+ Error materialize_error;
+
+ m_dematerializer_sp = m_materializer_ap->Materialize(
+ frame, *m_execution_unit_sp, struct_address, materialize_error);
+
+ if (!materialize_error.Success()) {
+ diagnostic_manager.Printf(eDiagnosticSeverityError,
+ "Couldn't materialize: %s",
+ materialize_error.AsCString());
+ return false;
+ }
+ }
+ return true;
+}
+
+lldb::ModuleSP LLVMUserExpression::GetJITModule() {
+ if (m_execution_unit_sp)
+ return m_execution_unit_sp->GetJITModule();
+ return lldb::ModuleSP();
}
diff --git a/lldb/source/Expression/Materializer.cpp b/lldb/source/Expression/Materializer.cpp
index 0502f0f..80fb244 100644
--- a/lldb/source/Expression/Materializer.cpp
+++ b/lldb/source/Expression/Materializer.cpp
@@ -11,12 +11,12 @@
// C++ Includes
// Other libraries and framework includes
// Project includes
+#include "lldb/Expression/Materializer.h"
#include "lldb/Core/Log.h"
#include "lldb/Core/RegisterValue.h"
#include "lldb/Core/ValueObjectConstResult.h"
#include "lldb/Core/ValueObjectVariable.h"
#include "lldb/Expression/ExpressionVariable.h"
-#include "lldb/Expression/Materializer.h"
#include "lldb/Symbol/ClangASTContext.h"
#include "lldb/Symbol/Symbol.h"
#include "lldb/Symbol/Type.h"
@@ -29,1495 +29,1436 @@
using namespace lldb_private;
-uint32_t
-Materializer::AddStructMember (Entity &entity)
-{
- uint32_t size = entity.GetSize();
- uint32_t alignment = entity.GetAlignment();
+uint32_t Materializer::AddStructMember(Entity &entity) {
+ uint32_t size = entity.GetSize();
+ uint32_t alignment = entity.GetAlignment();
- uint32_t ret;
+ uint32_t ret;
- if (m_current_offset == 0)
- m_struct_alignment = alignment;
+ if (m_current_offset == 0)
+ m_struct_alignment = alignment;
- if (m_current_offset % alignment)
- m_current_offset += (alignment - (m_current_offset % alignment));
+ if (m_current_offset % alignment)
+ m_current_offset += (alignment - (m_current_offset % alignment));
- ret = m_current_offset;
+ ret = m_current_offset;
- m_current_offset += size;
+ m_current_offset += size;
- return ret;
+ return ret;
}
-void
-Materializer::Entity::SetSizeAndAlignmentFromType (CompilerType &type)
-{
- m_size = type.GetByteSize(nullptr);
+void Materializer::Entity::SetSizeAndAlignmentFromType(CompilerType &type) {
+ m_size = type.GetByteSize(nullptr);
- uint32_t bit_alignment = type.GetTypeBitAlign();
+ uint32_t bit_alignment = type.GetTypeBitAlign();
- if (bit_alignment % 8)
- {
- bit_alignment += 8;
- bit_alignment &= ~((uint32_t)0x111u);
- }
+ if (bit_alignment % 8) {
+ bit_alignment += 8;
+ bit_alignment &= ~((uint32_t)0x111u);
+ }
- m_alignment = bit_alignment / 8;
+ m_alignment = bit_alignment / 8;
}
-class EntityPersistentVariable : public Materializer::Entity
-{
+class EntityPersistentVariable : public Materializer::Entity {
public:
- EntityPersistentVariable (lldb::ExpressionVariableSP &persistent_variable_sp,
- Materializer::PersistentVariableDelegate *delegate) :
- Entity(),
- m_persistent_variable_sp(persistent_variable_sp),
- m_delegate(delegate)
- {
- // Hard-coding to maximum size of a pointer since persistent variables are materialized by reference
- m_size = 8;
- m_alignment = 8;
+ EntityPersistentVariable(lldb::ExpressionVariableSP &persistent_variable_sp,
+ Materializer::PersistentVariableDelegate *delegate)
+ : Entity(), m_persistent_variable_sp(persistent_variable_sp),
+ m_delegate(delegate) {
+ // Hard-coding to maximum size of a pointer since persistent variables are
+ // materialized by reference
+ m_size = 8;
+ m_alignment = 8;
+ }
+
+ void MakeAllocation(IRMemoryMap &map, Error &err) {
+ Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS));
+
+ // Allocate a spare memory area to store the persistent variable's contents.
+
+ Error allocate_error;
+ const bool zero_memory = false;
+
+ lldb::addr_t mem = map.Malloc(
+ m_persistent_variable_sp->GetByteSize(), 8,
+ lldb::ePermissionsReadable | lldb::ePermissionsWritable,
+ IRMemoryMap::eAllocationPolicyMirror, zero_memory, allocate_error);
+
+ if (!allocate_error.Success()) {
+ err.SetErrorStringWithFormat(
+ "couldn't allocate a memory area to store %s: %s",
+ m_persistent_variable_sp->GetName().GetCString(),
+ allocate_error.AsCString());
+ return;
}
- void MakeAllocation (IRMemoryMap &map, Error &err)
+ if (log)
+ log->Printf("Allocated %s (0x%" PRIx64 ") successfully",
+ m_persistent_variable_sp->GetName().GetCString(), mem);
+
+ // Put the location of the spare memory into the live data of the
+ // ValueObject.
+
+ m_persistent_variable_sp->m_live_sp = ValueObjectConstResult::Create(
+ map.GetBestExecutionContextScope(),
+ m_persistent_variable_sp->GetCompilerType(),
+ m_persistent_variable_sp->GetName(), mem, eAddressTypeLoad,
+ map.GetAddressByteSize());
+
+ // Clear the flag if the variable will never be deallocated.
+
+ if (m_persistent_variable_sp->m_flags &
+ ExpressionVariable::EVKeepInTarget) {
+ Error leak_error;
+ map.Leak(mem, leak_error);
+ m_persistent_variable_sp->m_flags &=
+ ~ExpressionVariable::EVNeedsAllocation;
+ }
+
+ // Write the contents of the variable to the area.
+
+ Error write_error;
+
+ map.WriteMemory(mem, m_persistent_variable_sp->GetValueBytes(),
+ m_persistent_variable_sp->GetByteSize(), write_error);
+
+ if (!write_error.Success()) {
+ err.SetErrorStringWithFormat(
+ "couldn't write %s to the target: %s",
+ m_persistent_variable_sp->GetName().AsCString(),
+ write_error.AsCString());
+ return;
+ }
+ }
+
+ void DestroyAllocation(IRMemoryMap &map, Error &err) {
+ Error deallocate_error;
+
+ map.Free((lldb::addr_t)m_persistent_variable_sp->m_live_sp->GetValue()
+ .GetScalar()
+ .ULongLong(),
+ deallocate_error);
+
+ m_persistent_variable_sp->m_live_sp.reset();
+
+ if (!deallocate_error.Success()) {
+ err.SetErrorStringWithFormat(
+ "couldn't deallocate memory for %s: %s",
+ m_persistent_variable_sp->GetName().GetCString(),
+ deallocate_error.AsCString());
+ }
+ }
+
+ void Materialize(lldb::StackFrameSP &frame_sp, IRMemoryMap &map,
+ lldb::addr_t process_address, Error &err) override {
+ Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS));
+
+ const lldb::addr_t load_addr = process_address + m_offset;
+
+ if (log) {
+ log->Printf("EntityPersistentVariable::Materialize [address = 0x%" PRIx64
+ ", m_name = %s, m_flags = 0x%hx]",
+ (uint64_t)load_addr,
+ m_persistent_variable_sp->GetName().AsCString(),
+ m_persistent_variable_sp->m_flags);
+ }
+
+ if (m_persistent_variable_sp->m_flags &
+ ExpressionVariable::EVNeedsAllocation) {
+ MakeAllocation(map, err);
+ m_persistent_variable_sp->m_flags |=
+ ExpressionVariable::EVIsLLDBAllocated;
+
+ if (!err.Success())
+ return;
+ }
+
+ if ((m_persistent_variable_sp->m_flags &
+ ExpressionVariable::EVIsProgramReference &&
+ m_persistent_variable_sp->m_live_sp) ||
+ m_persistent_variable_sp->m_flags &
+ ExpressionVariable::EVIsLLDBAllocated) {
+ Error write_error;
+
+ map.WriteScalarToMemory(
+ load_addr,
+ m_persistent_variable_sp->m_live_sp->GetValue().GetScalar(),
+ map.GetAddressByteSize(), write_error);
+
+ if (!write_error.Success()) {
+ err.SetErrorStringWithFormat(
+ "couldn't write the location of %s to memory: %s",
+ m_persistent_variable_sp->GetName().AsCString(),
+ write_error.AsCString());
+ }
+ } else {
+ err.SetErrorStringWithFormat(
+ "no materialization happened for persistent variable %s",
+ m_persistent_variable_sp->GetName().AsCString());
+ return;
+ }
+ }
+
+ void Dematerialize(lldb::StackFrameSP &frame_sp, IRMemoryMap &map,
+ lldb::addr_t process_address, lldb::addr_t frame_top,
+ lldb::addr_t frame_bottom, Error &err) override {
+ Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS));
+
+ const lldb::addr_t load_addr = process_address + m_offset;
+
+ if (log) {
+ log->Printf(
+ "EntityPersistentVariable::Dematerialize [address = 0x%" PRIx64
+ ", m_name = %s, m_flags = 0x%hx]",
+ (uint64_t)process_address + m_offset,
+ m_persistent_variable_sp->GetName().AsCString(),
+ m_persistent_variable_sp->m_flags);
+ }
+
+ if (m_delegate) {
+ m_delegate->DidDematerialize(m_persistent_variable_sp);
+ }
+
+ if ((m_persistent_variable_sp->m_flags &
+ ExpressionVariable::EVIsLLDBAllocated) ||
+ (m_persistent_variable_sp->m_flags &
+ ExpressionVariable::EVIsProgramReference)) {
+ if (m_persistent_variable_sp->m_flags &
+ ExpressionVariable::EVIsProgramReference &&
+ !m_persistent_variable_sp->m_live_sp) {
+ // If the reference comes from the program, then the
+ // ClangExpressionVariable's
+ // live variable data hasn't been set up yet. Do this now.
+
+ lldb::addr_t location;
+ Error read_error;
+
+ map.ReadPointerFromMemory(&location, load_addr, read_error);
+
+ if (!read_error.Success()) {
+ err.SetErrorStringWithFormat(
+ "couldn't read the address of program-allocated variable %s: %s",
+ m_persistent_variable_sp->GetName().GetCString(),
+ read_error.AsCString());
+ return;
+ }
+
+ m_persistent_variable_sp->m_live_sp = ValueObjectConstResult::Create(
+ map.GetBestExecutionContextScope(),
+ m_persistent_variable_sp.get()->GetCompilerType(),
+ m_persistent_variable_sp->GetName(), location, eAddressTypeLoad,
+ m_persistent_variable_sp->GetByteSize());
+
+ if (frame_top != LLDB_INVALID_ADDRESS &&
+ frame_bottom != LLDB_INVALID_ADDRESS && location >= frame_bottom &&
+ location <= frame_top) {
+ // If the variable is resident in the stack frame created by the
+ // expression,
+ // then it cannot be relied upon to stay around. We treat it as
+ // needing
+ // reallocation.
+ m_persistent_variable_sp->m_flags |=
+ ExpressionVariable::EVIsLLDBAllocated;
+ m_persistent_variable_sp->m_flags |=
+ ExpressionVariable::EVNeedsAllocation;
+ m_persistent_variable_sp->m_flags |=
+ ExpressionVariable::EVNeedsFreezeDry;
+ m_persistent_variable_sp->m_flags &=
+ ~ExpressionVariable::EVIsProgramReference;
+ }
+ }
+
+ lldb::addr_t mem = m_persistent_variable_sp->m_live_sp->GetValue()
+ .GetScalar()
+ .ULongLong();
+
+ if (!m_persistent_variable_sp->m_live_sp) {
+ err.SetErrorStringWithFormat(
+ "couldn't find the memory area used to store %s",
+ m_persistent_variable_sp->GetName().GetCString());
+ return;
+ }
+
+ if (m_persistent_variable_sp->m_live_sp->GetValue()
+ .GetValueAddressType() != eAddressTypeLoad) {
+ err.SetErrorStringWithFormat(
+ "the address of the memory area for %s is in an incorrect format",
+ m_persistent_variable_sp->GetName().GetCString());
+ return;
+ }
+
+ if (m_persistent_variable_sp->m_flags &
+ ExpressionVariable::EVNeedsFreezeDry ||
+ m_persistent_variable_sp->m_flags &
+ ExpressionVariable::EVKeepInTarget) {
+ if (log)
+ log->Printf(
+ "Dematerializing %s from 0x%" PRIx64 " (size = %llu)",
+ m_persistent_variable_sp->GetName().GetCString(), (uint64_t)mem,
+ (unsigned long long)m_persistent_variable_sp->GetByteSize());
+
+ // Read the contents of the spare memory area
+
+ m_persistent_variable_sp->ValueUpdated();
+
+ Error read_error;
+
+ map.ReadMemory(m_persistent_variable_sp->GetValueBytes(), mem,
+ m_persistent_variable_sp->GetByteSize(), read_error);
+
+ if (!read_error.Success()) {
+ err.SetErrorStringWithFormat(
+ "couldn't read the contents of %s from memory: %s",
+ m_persistent_variable_sp->GetName().GetCString(),
+ read_error.AsCString());
+ return;
+ }
+
+ m_persistent_variable_sp->m_flags &=
+ ~ExpressionVariable::EVNeedsFreezeDry;
+ }
+ } else {
+ err.SetErrorStringWithFormat(
+ "no dematerialization happened for persistent variable %s",
+ m_persistent_variable_sp->GetName().AsCString());
+ return;
+ }
+
+ lldb::ProcessSP process_sp =
+ map.GetBestExecutionContextScope()->CalculateProcess();
+ if (!process_sp || !process_sp->CanJIT()) {
+ // Allocations are not persistent so persistent variables cannot stay
+ // materialized.
+
+ m_persistent_variable_sp->m_flags |=
+ ExpressionVariable::EVNeedsAllocation;
+
+ DestroyAllocation(map, err);
+ if (!err.Success())
+ return;
+ } else if (m_persistent_variable_sp->m_flags &
+ ExpressionVariable::EVNeedsAllocation &&
+ !(m_persistent_variable_sp->m_flags &
+ ExpressionVariable::EVKeepInTarget)) {
+ DestroyAllocation(map, err);
+ if (!err.Success())
+ return;
+ }
+ }
+
+ void DumpToLog(IRMemoryMap &map, lldb::addr_t process_address,
+ Log *log) override {
+ StreamString dump_stream;
+
+ Error err;
+
+ const lldb::addr_t load_addr = process_address + m_offset;
+
+ dump_stream.Printf("0x%" PRIx64 ": EntityPersistentVariable (%s)\n",
+ load_addr,
+ m_persistent_variable_sp->GetName().AsCString());
+
{
- Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
+ dump_stream.Printf("Pointer:\n");
- // Allocate a spare memory area to store the persistent variable's contents.
+ DataBufferHeap data(m_size, 0);
- Error allocate_error;
+ map.ReadMemory(data.GetBytes(), load_addr, m_size, err);
+
+ if (!err.Success()) {
+ dump_stream.Printf(" <could not be read>\n");
+ } else {
+ DataExtractor extractor(data.GetBytes(), data.GetByteSize(),
+ map.GetByteOrder(), map.GetAddressByteSize());
+
+ extractor.DumpHexBytes(&dump_stream, data.GetBytes(),
+ data.GetByteSize(), 16, load_addr);
+
+ dump_stream.PutChar('\n');
+ }
+ }
+
+ {
+ dump_stream.Printf("Target:\n");
+
+ lldb::addr_t target_address;
+
+ map.ReadPointerFromMemory(&target_address, load_addr, err);
+
+ if (!err.Success()) {
+ dump_stream.Printf(" <could not be read>\n");
+ } else {
+ DataBufferHeap data(m_persistent_variable_sp->GetByteSize(), 0);
+
+ map.ReadMemory(data.GetBytes(), target_address,
+ m_persistent_variable_sp->GetByteSize(), err);
+
+ if (!err.Success()) {
+ dump_stream.Printf(" <could not be read>\n");
+ } else {
+ DataExtractor extractor(data.GetBytes(), data.GetByteSize(),
+ map.GetByteOrder(), map.GetAddressByteSize());
+
+ extractor.DumpHexBytes(&dump_stream, data.GetBytes(),
+ data.GetByteSize(), 16, target_address);
+
+ dump_stream.PutChar('\n');
+ }
+ }
+ }
+
+ log->PutCString(dump_stream.GetData());
+ }
+
+ void Wipe(IRMemoryMap &map, lldb::addr_t process_address) override {}
+
+private:
+ lldb::ExpressionVariableSP m_persistent_variable_sp;
+ Materializer::PersistentVariableDelegate *m_delegate;
+};
+
+uint32_t Materializer::AddPersistentVariable(
+ lldb::ExpressionVariableSP &persistent_variable_sp,
+ PersistentVariableDelegate *delegate, Error &err) {
+ EntityVector::iterator iter = m_entities.insert(m_entities.end(), EntityUP());
+ iter->reset(new EntityPersistentVariable(persistent_variable_sp, delegate));
+ uint32_t ret = AddStructMember(**iter);
+ (*iter)->SetOffset(ret);
+ return ret;
+}
+
+class EntityVariable : public Materializer::Entity {
+public:
+ EntityVariable(lldb::VariableSP &variable_sp)
+ : Entity(), m_variable_sp(variable_sp), m_is_reference(false),
+ m_temporary_allocation(LLDB_INVALID_ADDRESS),
+ m_temporary_allocation_size(0) {
+ // Hard-coding to maximum size of a pointer since all variables are
+ // materialized by reference
+ m_size = 8;
+ m_alignment = 8;
+ m_is_reference =
+ m_variable_sp->GetType()->GetForwardCompilerType().IsReferenceType();
+ }
+
+ void Materialize(lldb::StackFrameSP &frame_sp, IRMemoryMap &map,
+ lldb::addr_t process_address, Error &err) override {
+ Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS));
+
+ const lldb::addr_t load_addr = process_address + m_offset;
+ if (log) {
+ log->Printf("EntityVariable::Materialize [address = 0x%" PRIx64
+ ", m_variable_sp = %s]",
+ (uint64_t)load_addr, m_variable_sp->GetName().AsCString());
+ }
+
+ ExecutionContextScope *scope = frame_sp.get();
+
+ if (!scope)
+ scope = map.GetBestExecutionContextScope();
+
+ lldb::ValueObjectSP valobj_sp =
+ ValueObjectVariable::Create(scope, m_variable_sp);
+
+ if (!valobj_sp) {
+ err.SetErrorStringWithFormat(
+ "couldn't get a value object for variable %s",
+ m_variable_sp->GetName().AsCString());
+ return;
+ }
+
+ Error valobj_error = valobj_sp->GetError();
+
+ if (valobj_error.Fail()) {
+ err.SetErrorStringWithFormat("couldn't get the value of variable %s: %s",
+ m_variable_sp->GetName().AsCString(),
+ valobj_error.AsCString());
+ return;
+ }
+
+ if (m_is_reference) {
+ DataExtractor valobj_extractor;
+ Error extract_error;
+ valobj_sp->GetData(valobj_extractor, extract_error);
+
+ if (!extract_error.Success()) {
+ err.SetErrorStringWithFormat(
+ "couldn't read contents of reference variable %s: %s",
+ m_variable_sp->GetName().AsCString(), extract_error.AsCString());
+ return;
+ }
+
+ lldb::offset_t offset = 0;
+ lldb::addr_t reference_addr = valobj_extractor.GetAddress(&offset);
+
+ Error write_error;
+ map.WritePointerToMemory(load_addr, reference_addr, write_error);
+
+ if (!write_error.Success()) {
+ err.SetErrorStringWithFormat("couldn't write the contents of reference "
+ "variable %s to memory: %s",
+ m_variable_sp->GetName().AsCString(),
+ write_error.AsCString());
+ return;
+ }
+ } else {
+ AddressType address_type = eAddressTypeInvalid;
+ const bool scalar_is_load_address = false;
+ lldb::addr_t addr_of_valobj =
+ valobj_sp->GetAddressOf(scalar_is_load_address, &address_type);
+ if (addr_of_valobj != LLDB_INVALID_ADDRESS) {
+ Error write_error;
+ map.WritePointerToMemory(load_addr, addr_of_valobj, write_error);
+
+ if (!write_error.Success()) {
+ err.SetErrorStringWithFormat(
+ "couldn't write the address of variable %s to memory: %s",
+ m_variable_sp->GetName().AsCString(), write_error.AsCString());
+ return;
+ }
+ } else {
+ DataExtractor data;
+ Error extract_error;
+ valobj_sp->GetData(data, extract_error);
+ if (!extract_error.Success()) {
+ err.SetErrorStringWithFormat("couldn't get the value of %s: %s",
+ m_variable_sp->GetName().AsCString(),
+ extract_error.AsCString());
+ return;
+ }
+
+ if (m_temporary_allocation != LLDB_INVALID_ADDRESS) {
+ err.SetErrorStringWithFormat(
+ "trying to create a temporary region for %s but one exists",
+ m_variable_sp->GetName().AsCString());
+ return;
+ }
+
+ if (data.GetByteSize() < m_variable_sp->GetType()->GetByteSize()) {
+ if (data.GetByteSize() == 0 &&
+ m_variable_sp->LocationExpression().IsValid() == false) {
+ err.SetErrorStringWithFormat("the variable '%s' has no location, "
+ "it may have been optimized out",
+ m_variable_sp->GetName().AsCString());
+ } else {
+ err.SetErrorStringWithFormat(
+ "size of variable %s (%" PRIu64
+ ") is larger than the ValueObject's size (%" PRIu64 ")",
+ m_variable_sp->GetName().AsCString(),
+ m_variable_sp->GetType()->GetByteSize(), data.GetByteSize());
+ }
+ return;
+ }
+
+ size_t bit_align =
+ m_variable_sp->GetType()->GetLayoutCompilerType().GetTypeBitAlign();
+ size_t byte_align = (bit_align + 7) / 8;
+
+ if (!byte_align)
+ byte_align = 1;
+
+ Error alloc_error;
const bool zero_memory = false;
- lldb::addr_t mem = map.Malloc(m_persistent_variable_sp->GetByteSize(),
- 8,
- lldb::ePermissionsReadable | lldb::ePermissionsWritable,
- IRMemoryMap::eAllocationPolicyMirror,
- zero_memory,
- allocate_error);
+ m_temporary_allocation = map.Malloc(
+ data.GetByteSize(), byte_align,
+ lldb::ePermissionsReadable | lldb::ePermissionsWritable,
+ IRMemoryMap::eAllocationPolicyMirror, zero_memory, alloc_error);
- if (!allocate_error.Success())
- {
- err.SetErrorStringWithFormat("couldn't allocate a memory area to store %s: %s", m_persistent_variable_sp->GetName().GetCString(), allocate_error.AsCString());
- return;
+ m_temporary_allocation_size = data.GetByteSize();
+
+ m_original_data.reset(
+ new DataBufferHeap(data.GetDataStart(), data.GetByteSize()));
+
+ if (!alloc_error.Success()) {
+ err.SetErrorStringWithFormat(
+ "couldn't allocate a temporary region for %s: %s",
+ m_variable_sp->GetName().AsCString(), alloc_error.AsCString());
+ return;
}
- if (log)
- log->Printf("Allocated %s (0x%" PRIx64 ") successfully", m_persistent_variable_sp->GetName().GetCString(), mem);
-
- // Put the location of the spare memory into the live data of the ValueObject.
-
- m_persistent_variable_sp->m_live_sp = ValueObjectConstResult::Create (map.GetBestExecutionContextScope(),
- m_persistent_variable_sp->GetCompilerType(),
- m_persistent_variable_sp->GetName(),
- mem,
- eAddressTypeLoad,
- map.GetAddressByteSize());
-
- // Clear the flag if the variable will never be deallocated.
-
- if (m_persistent_variable_sp->m_flags & ExpressionVariable::EVKeepInTarget)
- {
- Error leak_error;
- map.Leak(mem, leak_error);
- m_persistent_variable_sp->m_flags &= ~ExpressionVariable::EVNeedsAllocation;
- }
-
- // Write the contents of the variable to the area.
-
Error write_error;
- map.WriteMemory (mem,
- m_persistent_variable_sp->GetValueBytes(),
- m_persistent_variable_sp->GetByteSize(),
- write_error);
+ map.WriteMemory(m_temporary_allocation, data.GetDataStart(),
+ data.GetByteSize(), write_error);
- if (!write_error.Success())
- {
- err.SetErrorStringWithFormat ("couldn't write %s to the target: %s", m_persistent_variable_sp->GetName().AsCString(),
- write_error.AsCString());
- return;
+ if (!write_error.Success()) {
+ err.SetErrorStringWithFormat(
+ "couldn't write to the temporary region for %s: %s",
+ m_variable_sp->GetName().AsCString(), write_error.AsCString());
+ return;
}
- }
-
- void DestroyAllocation (IRMemoryMap &map, Error &err)
- {
- Error deallocate_error;
-
- map.Free((lldb::addr_t)m_persistent_variable_sp->m_live_sp->GetValue().GetScalar().ULongLong(), deallocate_error);
-
- m_persistent_variable_sp->m_live_sp.reset();
-
- if (!deallocate_error.Success())
- {
- err.SetErrorStringWithFormat ("couldn't deallocate memory for %s: %s", m_persistent_variable_sp->GetName().GetCString(), deallocate_error.AsCString());
- }
- }
-
- void Materialize(lldb::StackFrameSP &frame_sp,
- IRMemoryMap &map,
- lldb::addr_t process_address,
- Error &err) override
- {
- Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
-
- const lldb::addr_t load_addr = process_address + m_offset;
-
- if (log)
- {
- log->Printf("EntityPersistentVariable::Materialize [address = 0x%" PRIx64 ", m_name = %s, m_flags = 0x%hx]",
- (uint64_t)load_addr,
- m_persistent_variable_sp->GetName().AsCString(),
- m_persistent_variable_sp->m_flags);
- }
-
- if (m_persistent_variable_sp->m_flags & ExpressionVariable::EVNeedsAllocation)
- {
- MakeAllocation(map, err);
- m_persistent_variable_sp->m_flags |= ExpressionVariable::EVIsLLDBAllocated;
-
- if (!err.Success())
- return;
- }
-
- if ((m_persistent_variable_sp->m_flags & ExpressionVariable::EVIsProgramReference && m_persistent_variable_sp->m_live_sp) ||
- m_persistent_variable_sp->m_flags & ExpressionVariable::EVIsLLDBAllocated)
- {
- Error write_error;
-
- map.WriteScalarToMemory(load_addr,
- m_persistent_variable_sp->m_live_sp->GetValue().GetScalar(),
- map.GetAddressByteSize(),
- write_error);
-
- if (!write_error.Success())
- {
- err.SetErrorStringWithFormat("couldn't write the location of %s to memory: %s", m_persistent_variable_sp->GetName().AsCString(), write_error.AsCString());
- }
- }
- else
- {
- err.SetErrorStringWithFormat("no materialization happened for persistent variable %s", m_persistent_variable_sp->GetName().AsCString());
- return;
- }
- }
-
- void Dematerialize(lldb::StackFrameSP &frame_sp,
- IRMemoryMap &map,
- lldb::addr_t process_address,
- lldb::addr_t frame_top,
- lldb::addr_t frame_bottom,
- Error &err) override
- {
- Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
-
- const lldb::addr_t load_addr = process_address + m_offset;
-
- if (log)
- {
- log->Printf("EntityPersistentVariable::Dematerialize [address = 0x%" PRIx64 ", m_name = %s, m_flags = 0x%hx]",
- (uint64_t)process_address + m_offset,
- m_persistent_variable_sp->GetName().AsCString(),
- m_persistent_variable_sp->m_flags);
- }
-
- if (m_delegate)
- {
- m_delegate->DidDematerialize(m_persistent_variable_sp);
- }
-
- if ((m_persistent_variable_sp->m_flags & ExpressionVariable::EVIsLLDBAllocated) ||
- (m_persistent_variable_sp->m_flags & ExpressionVariable::EVIsProgramReference))
- {
- if (m_persistent_variable_sp->m_flags & ExpressionVariable::EVIsProgramReference &&
- !m_persistent_variable_sp->m_live_sp)
- {
- // If the reference comes from the program, then the ClangExpressionVariable's
- // live variable data hasn't been set up yet. Do this now.
-
- lldb::addr_t location;
- Error read_error;
-
- map.ReadPointerFromMemory(&location, load_addr, read_error);
-
- if (!read_error.Success())
- {
- err.SetErrorStringWithFormat("couldn't read the address of program-allocated variable %s: %s", m_persistent_variable_sp->GetName().GetCString(), read_error.AsCString());
- return;
- }
-
- m_persistent_variable_sp->m_live_sp = ValueObjectConstResult::Create (map.GetBestExecutionContextScope (),
- m_persistent_variable_sp.get()->GetCompilerType(),
- m_persistent_variable_sp->GetName(),
- location,
- eAddressTypeLoad,
- m_persistent_variable_sp->GetByteSize());
-
- if (frame_top != LLDB_INVALID_ADDRESS &&
- frame_bottom != LLDB_INVALID_ADDRESS &&
- location >= frame_bottom &&
- location <= frame_top)
- {
- // If the variable is resident in the stack frame created by the expression,
- // then it cannot be relied upon to stay around. We treat it as needing
- // reallocation.
- m_persistent_variable_sp->m_flags |= ExpressionVariable::EVIsLLDBAllocated;
- m_persistent_variable_sp->m_flags |= ExpressionVariable::EVNeedsAllocation;
- m_persistent_variable_sp->m_flags |= ExpressionVariable::EVNeedsFreezeDry;
- m_persistent_variable_sp->m_flags &= ~ExpressionVariable::EVIsProgramReference;
- }
- }
-
- lldb::addr_t mem = m_persistent_variable_sp->m_live_sp->GetValue().GetScalar().ULongLong();
-
- if (!m_persistent_variable_sp->m_live_sp)
- {
- err.SetErrorStringWithFormat("couldn't find the memory area used to store %s", m_persistent_variable_sp->GetName().GetCString());
- return;
- }
-
- if (m_persistent_variable_sp->m_live_sp->GetValue().GetValueAddressType() != eAddressTypeLoad)
- {
- err.SetErrorStringWithFormat("the address of the memory area for %s is in an incorrect format", m_persistent_variable_sp->GetName().GetCString());
- return;
- }
-
- if (m_persistent_variable_sp->m_flags & ExpressionVariable::EVNeedsFreezeDry ||
- m_persistent_variable_sp->m_flags & ExpressionVariable::EVKeepInTarget)
- {
- if (log)
- log->Printf("Dematerializing %s from 0x%" PRIx64 " (size = %llu)", m_persistent_variable_sp->GetName().GetCString(), (uint64_t)mem, (unsigned long long)m_persistent_variable_sp->GetByteSize());
-
- // Read the contents of the spare memory area
-
- m_persistent_variable_sp->ValueUpdated ();
-
- Error read_error;
-
- map.ReadMemory(m_persistent_variable_sp->GetValueBytes(),
- mem,
- m_persistent_variable_sp->GetByteSize(),
- read_error);
-
- if (!read_error.Success())
- {
- err.SetErrorStringWithFormat ("couldn't read the contents of %s from memory: %s", m_persistent_variable_sp->GetName().GetCString(), read_error.AsCString());
- return;
- }
-
- m_persistent_variable_sp->m_flags &= ~ExpressionVariable::EVNeedsFreezeDry;
- }
- }
- else
- {
- err.SetErrorStringWithFormat("no dematerialization happened for persistent variable %s", m_persistent_variable_sp->GetName().AsCString());
- return;
- }
-
- lldb::ProcessSP process_sp = map.GetBestExecutionContextScope()->CalculateProcess();
- if (!process_sp ||
- !process_sp->CanJIT())
- {
- // Allocations are not persistent so persistent variables cannot stay materialized.
-
- m_persistent_variable_sp->m_flags |= ExpressionVariable::EVNeedsAllocation;
-
- DestroyAllocation(map, err);
- if (!err.Success())
- return;
- }
- else if (m_persistent_variable_sp->m_flags & ExpressionVariable::EVNeedsAllocation &&
- !(m_persistent_variable_sp->m_flags & ExpressionVariable::EVKeepInTarget))
- {
- DestroyAllocation(map, err);
- if (!err.Success())
- return;
- }
- }
-
- void DumpToLog(IRMemoryMap &map, lldb::addr_t process_address, Log *log) override
- {
- StreamString dump_stream;
-
- Error err;
-
- const lldb::addr_t load_addr = process_address + m_offset;
-
- dump_stream.Printf("0x%" PRIx64 ": EntityPersistentVariable (%s)\n", load_addr, m_persistent_variable_sp->GetName().AsCString());
-
- {
- dump_stream.Printf("Pointer:\n");
-
- DataBufferHeap data (m_size, 0);
-
- map.ReadMemory(data.GetBytes(), load_addr, m_size, err);
-
- if (!err.Success())
- {
- dump_stream.Printf(" <could not be read>\n");
- }
- else
- {
- DataExtractor extractor (data.GetBytes(), data.GetByteSize(), map.GetByteOrder(), map.GetAddressByteSize());
-
- extractor.DumpHexBytes(&dump_stream, data.GetBytes(), data.GetByteSize(), 16, load_addr);
-
- dump_stream.PutChar('\n');
- }
- }
-
- {
- dump_stream.Printf("Target:\n");
-
- lldb::addr_t target_address;
-
- map.ReadPointerFromMemory (&target_address, load_addr, err);
-
- if (!err.Success())
- {
- dump_stream.Printf(" <could not be read>\n");
- }
- else
- {
- DataBufferHeap data (m_persistent_variable_sp->GetByteSize(), 0);
-
- map.ReadMemory(data.GetBytes(), target_address, m_persistent_variable_sp->GetByteSize(), err);
-
- if (!err.Success())
- {
- dump_stream.Printf(" <could not be read>\n");
- }
- else
- {
- DataExtractor extractor (data.GetBytes(), data.GetByteSize(), map.GetByteOrder(), map.GetAddressByteSize());
-
- extractor.DumpHexBytes(&dump_stream, data.GetBytes(), data.GetByteSize(), 16, target_address);
-
- dump_stream.PutChar('\n');
- }
- }
- }
-
- log->PutCString(dump_stream.GetData());
- }
-
- void Wipe(IRMemoryMap &map, lldb::addr_t process_address) override
- {
- }
-
-private:
- lldb::ExpressionVariableSP m_persistent_variable_sp;
- Materializer::PersistentVariableDelegate *m_delegate;
-};
-
-uint32_t
-Materializer::AddPersistentVariable (lldb::ExpressionVariableSP &persistent_variable_sp,
- PersistentVariableDelegate *delegate,
- Error &err)
-{
- EntityVector::iterator iter = m_entities.insert(m_entities.end(), EntityUP());
- iter->reset (new EntityPersistentVariable (persistent_variable_sp, delegate));
- uint32_t ret = AddStructMember(**iter);
- (*iter)->SetOffset(ret);
- return ret;
-}
-
-class EntityVariable : public Materializer::Entity
-{
-public:
- EntityVariable (lldb::VariableSP &variable_sp) :
- Entity(),
- m_variable_sp(variable_sp),
- m_is_reference(false),
- m_temporary_allocation(LLDB_INVALID_ADDRESS),
- m_temporary_allocation_size(0)
- {
- // Hard-coding to maximum size of a pointer since all variables are materialized by reference
- m_size = 8;
- m_alignment = 8;
- m_is_reference = m_variable_sp->GetType()->GetForwardCompilerType ().IsReferenceType();
- }
-
- void Materialize(lldb::StackFrameSP &frame_sp,
- IRMemoryMap &map,
- lldb::addr_t process_address,
- Error &err) override
- {
- Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
-
- const lldb::addr_t load_addr = process_address + m_offset;
- if (log)
- {
- log->Printf("EntityVariable::Materialize [address = 0x%" PRIx64 ", m_variable_sp = %s]",
- (uint64_t)load_addr,
- m_variable_sp->GetName().AsCString());
- }
-
- ExecutionContextScope *scope = frame_sp.get();
-
- if (!scope)
- scope = map.GetBestExecutionContextScope();
-
- lldb::ValueObjectSP valobj_sp = ValueObjectVariable::Create(scope, m_variable_sp);
-
- if (!valobj_sp)
- {
- err.SetErrorStringWithFormat("couldn't get a value object for variable %s", m_variable_sp->GetName().AsCString());
- return;
- }
-
- Error valobj_error = valobj_sp->GetError();
-
- if (valobj_error.Fail())
- {
- err.SetErrorStringWithFormat("couldn't get the value of variable %s: %s", m_variable_sp->GetName().AsCString(), valobj_error.AsCString());
- return;
- }
-
- if (m_is_reference)
- {
- DataExtractor valobj_extractor;
- Error extract_error;
- valobj_sp->GetData(valobj_extractor, extract_error);
-
- if (!extract_error.Success())
- {
- err.SetErrorStringWithFormat("couldn't read contents of reference variable %s: %s", m_variable_sp->GetName().AsCString(), extract_error.AsCString());
- return;
- }
-
- lldb::offset_t offset = 0;
- lldb::addr_t reference_addr = valobj_extractor.GetAddress(&offset);
-
- Error write_error;
- map.WritePointerToMemory(load_addr, reference_addr, write_error);
-
- if (!write_error.Success())
- {
- err.SetErrorStringWithFormat("couldn't write the contents of reference variable %s to memory: %s", m_variable_sp->GetName().AsCString(), write_error.AsCString());
- return;
- }
- }
- else
- {
- AddressType address_type = eAddressTypeInvalid;
- const bool scalar_is_load_address = false;
- lldb::addr_t addr_of_valobj = valobj_sp->GetAddressOf(scalar_is_load_address, &address_type);
- if (addr_of_valobj != LLDB_INVALID_ADDRESS)
- {
- Error write_error;
- map.WritePointerToMemory(load_addr, addr_of_valobj, write_error);
-
- if (!write_error.Success())
- {
- err.SetErrorStringWithFormat("couldn't write the address of variable %s to memory: %s", m_variable_sp->GetName().AsCString(), write_error.AsCString());
- return;
- }
- }
- else
- {
- DataExtractor data;
- Error extract_error;
- valobj_sp->GetData(data, extract_error);
- if (!extract_error.Success())
- {
- err.SetErrorStringWithFormat("couldn't get the value of %s: %s", m_variable_sp->GetName().AsCString(), extract_error.AsCString());
- return;
- }
-
- if (m_temporary_allocation != LLDB_INVALID_ADDRESS)
- {
- err.SetErrorStringWithFormat("trying to create a temporary region for %s but one exists", m_variable_sp->GetName().AsCString());
- return;
- }
-
- if (data.GetByteSize() < m_variable_sp->GetType()->GetByteSize())
- {
- if (data.GetByteSize() == 0 && m_variable_sp->LocationExpression().IsValid() == false)
- {
- err.SetErrorStringWithFormat("the variable '%s' has no location, it may have been optimized out", m_variable_sp->GetName().AsCString());
- }
- else
- {
- err.SetErrorStringWithFormat("size of variable %s (%" PRIu64 ") is larger than the ValueObject's size (%" PRIu64 ")",
- m_variable_sp->GetName().AsCString(),
- m_variable_sp->GetType()->GetByteSize(),
- data.GetByteSize());
- }
- return;
- }
-
- size_t bit_align = m_variable_sp->GetType()->GetLayoutCompilerType ().GetTypeBitAlign();
- size_t byte_align = (bit_align + 7) / 8;
-
- if (!byte_align)
- byte_align = 1;
-
- Error alloc_error;
- const bool zero_memory = false;
-
- m_temporary_allocation = map.Malloc(data.GetByteSize(),
- byte_align,
- lldb::ePermissionsReadable | lldb::ePermissionsWritable,
- IRMemoryMap::eAllocationPolicyMirror,
- zero_memory,
- alloc_error);
-
- m_temporary_allocation_size = data.GetByteSize();
-
- m_original_data.reset(new DataBufferHeap(data.GetDataStart(), data.GetByteSize()));
-
- if (!alloc_error.Success())
- {
- err.SetErrorStringWithFormat("couldn't allocate a temporary region for %s: %s", m_variable_sp->GetName().AsCString(), alloc_error.AsCString());
- return;
- }
-
- Error write_error;
-
- map.WriteMemory(m_temporary_allocation, data.GetDataStart(), data.GetByteSize(), write_error);
-
- if (!write_error.Success())
- {
- err.SetErrorStringWithFormat("couldn't write to the temporary region for %s: %s", m_variable_sp->GetName().AsCString(), write_error.AsCString());
- return;
- }
-
- Error pointer_write_error;
-
- map.WritePointerToMemory(load_addr, m_temporary_allocation, pointer_write_error);
-
- if (!pointer_write_error.Success())
- {
- err.SetErrorStringWithFormat("couldn't write the address of the temporary region for %s: %s", m_variable_sp->GetName().AsCString(), pointer_write_error.AsCString());
- }
- }
- }
- }
-
- void Dematerialize(lldb::StackFrameSP &frame_sp,
- IRMemoryMap &map,
- lldb::addr_t process_address,
- lldb::addr_t frame_top,
- lldb::addr_t frame_bottom,
- Error &err) override
- {
- Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
-
- const lldb::addr_t load_addr = process_address + m_offset;
- if (log)
- {
- log->Printf("EntityVariable::Dematerialize [address = 0x%" PRIx64 ", m_variable_sp = %s]",
- (uint64_t)load_addr,
- m_variable_sp->GetName().AsCString());
- }
-
- if (m_temporary_allocation != LLDB_INVALID_ADDRESS)
- {
- ExecutionContextScope *scope = frame_sp.get();
-
- if (!scope)
- scope = map.GetBestExecutionContextScope();
-
- lldb::ValueObjectSP valobj_sp = ValueObjectVariable::Create(scope, m_variable_sp);
-
- if (!valobj_sp)
- {
- err.SetErrorStringWithFormat("couldn't get a value object for variable %s", m_variable_sp->GetName().AsCString());
- return;
- }
-
- lldb_private::DataExtractor data;
-
- Error extract_error;
-
- map.GetMemoryData(data, m_temporary_allocation, valobj_sp->GetByteSize(), extract_error);
-
- if (!extract_error.Success())
- {
- err.SetErrorStringWithFormat("couldn't get the data for variable %s", m_variable_sp->GetName().AsCString());
- return;
- }
-
- bool actually_write = true;
-
- if (m_original_data)
- {
- if ((data.GetByteSize() == m_original_data->GetByteSize()) &&
- !memcmp(m_original_data->GetBytes(), data.GetDataStart(), data.GetByteSize()))
- {
- actually_write = false;
- }
- }
-
- Error set_error;
-
- if (actually_write)
- {
- valobj_sp->SetData(data, set_error);
-
- if (!set_error.Success())
- {
- err.SetErrorStringWithFormat("couldn't write the new contents of %s back into the variable", m_variable_sp->GetName().AsCString());
- return;
- }
- }
-
- Error free_error;
-
- map.Free(m_temporary_allocation, free_error);
-
- if (!free_error.Success())
- {
- err.SetErrorStringWithFormat("couldn't free the temporary region for %s: %s", m_variable_sp->GetName().AsCString(), free_error.AsCString());
- return;
- }
-
- m_original_data.reset();
- m_temporary_allocation = LLDB_INVALID_ADDRESS;
- m_temporary_allocation_size = 0;
- }
- }
-
- void DumpToLog(IRMemoryMap &map, lldb::addr_t process_address, Log *log) override
- {
- StreamString dump_stream;
-
- const lldb::addr_t load_addr = process_address + m_offset;
- dump_stream.Printf("0x%" PRIx64 ": EntityVariable\n", load_addr);
-
- Error err;
-
- lldb::addr_t ptr = LLDB_INVALID_ADDRESS;
-
- {
- dump_stream.Printf("Pointer:\n");
-
- DataBufferHeap data (m_size, 0);
-
- map.ReadMemory(data.GetBytes(), load_addr, m_size, err);
-
- if (!err.Success())
- {
- dump_stream.Printf(" <could not be read>\n");
- }
- else
- {
- DataExtractor extractor (data.GetBytes(), data.GetByteSize(), map.GetByteOrder(), map.GetAddressByteSize());
-
- extractor.DumpHexBytes(&dump_stream, data.GetBytes(), data.GetByteSize(), 16, load_addr);
-
- lldb::offset_t offset;
-
- ptr = extractor.GetPointer(&offset);
-
- dump_stream.PutChar('\n');
- }
- }
-
- if (m_temporary_allocation == LLDB_INVALID_ADDRESS)
- {
- dump_stream.Printf("Points to process memory:\n");
- }
- else
- {
- dump_stream.Printf("Temporary allocation:\n");
- }
-
- if (ptr == LLDB_INVALID_ADDRESS)
- {
- dump_stream.Printf(" <could not be be found>\n");
- }
- else
- {
- DataBufferHeap data (m_temporary_allocation_size, 0);
-
- map.ReadMemory(data.GetBytes(), m_temporary_allocation, m_temporary_allocation_size, err);
-
- if (!err.Success())
- {
- dump_stream.Printf(" <could not be read>\n");
- }
- else
- {
- DataExtractor extractor (data.GetBytes(), data.GetByteSize(), map.GetByteOrder(), map.GetAddressByteSize());
-
- extractor.DumpHexBytes(&dump_stream, data.GetBytes(), data.GetByteSize(), 16, load_addr);
-
- dump_stream.PutChar('\n');
- }
- }
-
- log->PutCString(dump_stream.GetData());
- }
-
- void Wipe(IRMemoryMap &map, lldb::addr_t process_address) override
- {
- if (m_temporary_allocation != LLDB_INVALID_ADDRESS)
- {
- Error free_error;
-
- map.Free(m_temporary_allocation, free_error);
-
- m_temporary_allocation = LLDB_INVALID_ADDRESS;
- m_temporary_allocation_size = 0;
- }
-
- }
-
-private:
- lldb::VariableSP m_variable_sp;
- bool m_is_reference;
- lldb::addr_t m_temporary_allocation;
- size_t m_temporary_allocation_size;
- lldb::DataBufferSP m_original_data;
-};
-
-uint32_t
-Materializer::AddVariable (lldb::VariableSP &variable_sp, Error &err)
-{
- EntityVector::iterator iter = m_entities.insert(m_entities.end(), EntityUP());
- iter->reset (new EntityVariable (variable_sp));
- uint32_t ret = AddStructMember(**iter);
- (*iter)->SetOffset(ret);
- return ret;
-}
-
-class EntityResultVariable : public Materializer::Entity
-{
-public:
- EntityResultVariable (const CompilerType &type,
- bool is_program_reference,
- bool keep_in_memory,
- Materializer::PersistentVariableDelegate *delegate) :
- Entity(),
- m_type(type),
- m_is_program_reference(is_program_reference),
- m_keep_in_memory(keep_in_memory),
- m_temporary_allocation(LLDB_INVALID_ADDRESS),
- m_temporary_allocation_size(0),
- m_delegate(delegate)
- {
- // Hard-coding to maximum size of a pointer since all results are materialized by reference
- m_size = 8;
- m_alignment = 8;
- }
-
- void Materialize(lldb::StackFrameSP &frame_sp,
- IRMemoryMap &map,
- lldb::addr_t process_address,
- Error &err) override
- {
- if (!m_is_program_reference)
- {
- if (m_temporary_allocation != LLDB_INVALID_ADDRESS)
- {
- err.SetErrorString("Trying to create a temporary region for the result but one exists");
- return;
- }
-
- const lldb::addr_t load_addr = process_address + m_offset;
-
- ExecutionContextScope *exe_scope = map.GetBestExecutionContextScope();
-
- size_t byte_size = m_type.GetByteSize(exe_scope);
- size_t bit_align = m_type.GetTypeBitAlign();
- size_t byte_align = (bit_align + 7) / 8;
-
- if (!byte_align)
- byte_align = 1;
-
- Error alloc_error;
- const bool zero_memory = true;
-
- m_temporary_allocation = map.Malloc(byte_size,
- byte_align,
- lldb::ePermissionsReadable | lldb::ePermissionsWritable,
- IRMemoryMap::eAllocationPolicyMirror,
- zero_memory,
- alloc_error);
- m_temporary_allocation_size = byte_size;
-
- if (!alloc_error.Success())
- {
- err.SetErrorStringWithFormat("couldn't allocate a temporary region for the result: %s", alloc_error.AsCString());
- return;
- }
-
- Error pointer_write_error;
-
- map.WritePointerToMemory(load_addr, m_temporary_allocation, pointer_write_error);
-
- if (!pointer_write_error.Success())
- {
- err.SetErrorStringWithFormat("couldn't write the address of the temporary region for the result: %s", pointer_write_error.AsCString());
- }
- }
- }
-
- void Dematerialize(lldb::StackFrameSP &frame_sp,
- IRMemoryMap &map,
- lldb::addr_t process_address,
- lldb::addr_t frame_top,
- lldb::addr_t frame_bottom,
- Error &err) override
- {
- err.Clear();
-
- ExecutionContextScope *exe_scope = map.GetBestExecutionContextScope();
-
- if (!exe_scope)
- {
- err.SetErrorString("Couldn't dematerialize a result variable: invalid execution context scope");
- return;
- }
-
- lldb::addr_t address;
- Error read_error;
- const lldb::addr_t load_addr = process_address + m_offset;
-
- map.ReadPointerFromMemory (&address, load_addr, read_error);
-
- if (!read_error.Success())
- {
- err.SetErrorString("Couldn't dematerialize a result variable: couldn't read its address");
- return;
- }
-
- lldb::TargetSP target_sp = exe_scope->CalculateTarget();
-
- if (!target_sp)
- {
- err.SetErrorString("Couldn't dematerialize a result variable: no target");
- return;
- }
-
- Error type_system_error;
- TypeSystem *type_system = target_sp->GetScratchTypeSystemForLanguage(&type_system_error, m_type.GetMinimumLanguage());
-
- if (!type_system)
- {
- err.SetErrorStringWithFormat("Couldn't dematerialize a result variable: couldn't get the corresponding type system: %s", type_system_error.AsCString());
- return;
- }
-
- PersistentExpressionState *persistent_state = type_system->GetPersistentExpressionState();
-
- if (!persistent_state)
- {
- err.SetErrorString("Couldn't dematerialize a result variable: corresponding type system doesn't handle persistent variables");
- return;
- }
-
- ConstString name = m_delegate ? m_delegate->GetName() : persistent_state->GetNextPersistentVariableName();
-
- lldb::ExpressionVariableSP ret = persistent_state->CreatePersistentVariable(exe_scope,
- name,
- m_type,
- map.GetByteOrder(),
- map.GetAddressByteSize());
-
- if (!ret)
- {
- err.SetErrorStringWithFormat("couldn't dematerialize a result variable: failed to make persistent variable %s", name.AsCString());
- return;
- }
-
- lldb::ProcessSP process_sp = map.GetBestExecutionContextScope()->CalculateProcess();
-
- if (m_delegate)
- {
- m_delegate->DidDematerialize(ret);
- }
-
- bool can_persist = (m_is_program_reference && process_sp && process_sp->CanJIT() && !(address >= frame_bottom && address < frame_top));
-
- if (can_persist && m_keep_in_memory)
- {
- ret->m_live_sp = ValueObjectConstResult::Create(exe_scope,
- m_type,
- name,
- address,
- eAddressTypeLoad,
- map.GetAddressByteSize());
- }
-
- ret->ValueUpdated();
-
- const size_t pvar_byte_size = ret->GetByteSize();
- uint8_t *pvar_data = ret->GetValueBytes();
-
- map.ReadMemory(pvar_data, address, pvar_byte_size, read_error);
-
- if (!read_error.Success())
- {
- err.SetErrorString("Couldn't dematerialize a result variable: couldn't read its memory");
- return;
- }
-
- if (!can_persist || !m_keep_in_memory)
- {
- ret->m_flags |= ExpressionVariable::EVNeedsAllocation;
-
- if (m_temporary_allocation != LLDB_INVALID_ADDRESS)
- {
- Error free_error;
- map.Free(m_temporary_allocation, free_error);
- }
- }
- else
- {
- ret->m_flags |= ExpressionVariable::EVIsLLDBAllocated;
- }
-
- m_temporary_allocation = LLDB_INVALID_ADDRESS;
- m_temporary_allocation_size = 0;
- }
-
- void DumpToLog(IRMemoryMap &map, lldb::addr_t process_address, Log *log) override
- {
- StreamString dump_stream;
-
- const lldb::addr_t load_addr = process_address + m_offset;
-
- dump_stream.Printf("0x%" PRIx64 ": EntityResultVariable\n", load_addr);
-
- Error err;
-
- lldb::addr_t ptr = LLDB_INVALID_ADDRESS;
-
- {
- dump_stream.Printf("Pointer:\n");
-
- DataBufferHeap data (m_size, 0);
-
- map.ReadMemory(data.GetBytes(), load_addr, m_size, err);
-
- if (!err.Success())
- {
- dump_stream.Printf(" <could not be read>\n");
- }
- else
- {
- DataExtractor extractor (data.GetBytes(), data.GetByteSize(), map.GetByteOrder(), map.GetAddressByteSize());
-
- extractor.DumpHexBytes(&dump_stream, data.GetBytes(), data.GetByteSize(), 16, load_addr);
-
- lldb::offset_t offset;
-
- ptr = extractor.GetPointer(&offset);
-
- dump_stream.PutChar('\n');
- }
- }
-
- if (m_temporary_allocation == LLDB_INVALID_ADDRESS)
- {
- dump_stream.Printf("Points to process memory:\n");
- }
- else
- {
- dump_stream.Printf("Temporary allocation:\n");
- }
-
- if (ptr == LLDB_INVALID_ADDRESS)
- {
- dump_stream.Printf(" <could not be be found>\n");
- }
- else
- {
- DataBufferHeap data (m_temporary_allocation_size, 0);
-
- map.ReadMemory(data.GetBytes(), m_temporary_allocation, m_temporary_allocation_size, err);
-
- if (!err.Success())
- {
- dump_stream.Printf(" <could not be read>\n");
- }
- else
- {
- DataExtractor extractor (data.GetBytes(), data.GetByteSize(), map.GetByteOrder(), map.GetAddressByteSize());
-
- extractor.DumpHexBytes(&dump_stream, data.GetBytes(), data.GetByteSize(), 16, load_addr);
-
- dump_stream.PutChar('\n');
- }
- }
-
- log->PutCString(dump_stream.GetData());
- }
-
- void Wipe(IRMemoryMap &map, lldb::addr_t process_address) override
- {
- if (!m_keep_in_memory && m_temporary_allocation != LLDB_INVALID_ADDRESS)
- {
- Error free_error;
-
- map.Free(m_temporary_allocation, free_error);
- }
-
- m_temporary_allocation = LLDB_INVALID_ADDRESS;
- m_temporary_allocation_size = 0;
- }
-
-private:
- CompilerType m_type;
- bool m_is_program_reference;
- bool m_keep_in_memory;
-
- lldb::addr_t m_temporary_allocation;
- size_t m_temporary_allocation_size;
- Materializer::PersistentVariableDelegate *m_delegate;
-};
-
-uint32_t
-Materializer::AddResultVariable (const CompilerType &type,
- bool is_program_reference,
- bool keep_in_memory,
- PersistentVariableDelegate *delegate,
- Error &err)
-{
- EntityVector::iterator iter = m_entities.insert(m_entities.end(), EntityUP());
- iter->reset (new EntityResultVariable (type, is_program_reference, keep_in_memory, delegate));
- uint32_t ret = AddStructMember(**iter);
- (*iter)->SetOffset(ret);
- return ret;
-}
-
-class EntitySymbol : public Materializer::Entity
-{
-public:
- EntitySymbol (const Symbol &symbol) :
- Entity(),
- m_symbol(symbol)
- {
- // Hard-coding to maximum size of a symbol
- m_size = 8;
- m_alignment = 8;
- }
-
- void Materialize(lldb::StackFrameSP &frame_sp,
- IRMemoryMap &map,
- lldb::addr_t process_address,
- Error &err) override
- {
- Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
-
- const lldb::addr_t load_addr = process_address + m_offset;
-
- if (log)
- {
- log->Printf("EntitySymbol::Materialize [address = 0x%" PRIx64 ", m_symbol = %s]",
- (uint64_t)load_addr,
- m_symbol.GetName().AsCString());
- }
-
- const Address sym_address = m_symbol.GetAddress();
-
- ExecutionContextScope *exe_scope = map.GetBestExecutionContextScope();
-
- lldb::TargetSP target_sp;
-
- if (exe_scope)
- target_sp = map.GetBestExecutionContextScope()->CalculateTarget();
-
- if (!target_sp)
- {
- err.SetErrorStringWithFormat("couldn't resolve symbol %s because there is no target", m_symbol.GetName().AsCString());
- return;
- }
-
- lldb::addr_t resolved_address = sym_address.GetLoadAddress(target_sp.get());
-
- if (resolved_address == LLDB_INVALID_ADDRESS)
- resolved_address = sym_address.GetFileAddress();
Error pointer_write_error;
- map.WritePointerToMemory(load_addr, resolved_address, pointer_write_error);
+ map.WritePointerToMemory(load_addr, m_temporary_allocation,
+ pointer_write_error);
- if (!pointer_write_error.Success())
- {
- err.SetErrorStringWithFormat("couldn't write the address of symbol %s: %s", m_symbol.GetName().AsCString(), pointer_write_error.AsCString());
- return;
+ if (!pointer_write_error.Success()) {
+ err.SetErrorStringWithFormat(
+ "couldn't write the address of the temporary region for %s: %s",
+ m_variable_sp->GetName().AsCString(),
+ pointer_write_error.AsCString());
}
+ }
+ }
+ }
+
+ void Dematerialize(lldb::StackFrameSP &frame_sp, IRMemoryMap &map,
+ lldb::addr_t process_address, lldb::addr_t frame_top,
+ lldb::addr_t frame_bottom, Error &err) override {
+ Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS));
+
+ const lldb::addr_t load_addr = process_address + m_offset;
+ if (log) {
+ log->Printf("EntityVariable::Dematerialize [address = 0x%" PRIx64
+ ", m_variable_sp = %s]",
+ (uint64_t)load_addr, m_variable_sp->GetName().AsCString());
}
- void Dematerialize(lldb::StackFrameSP &frame_sp,
- IRMemoryMap &map,
- lldb::addr_t process_address,
- lldb::addr_t frame_top,
- lldb::addr_t frame_bottom,
- Error &err) override
- {
- Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
+ if (m_temporary_allocation != LLDB_INVALID_ADDRESS) {
+ ExecutionContextScope *scope = frame_sp.get();
- const lldb::addr_t load_addr = process_address + m_offset;
+ if (!scope)
+ scope = map.GetBestExecutionContextScope();
- if (log)
- {
- log->Printf("EntitySymbol::Dematerialize [address = 0x%" PRIx64 ", m_symbol = %s]",
- (uint64_t)load_addr,
- m_symbol.GetName().AsCString());
+ lldb::ValueObjectSP valobj_sp =
+ ValueObjectVariable::Create(scope, m_variable_sp);
+
+ if (!valobj_sp) {
+ err.SetErrorStringWithFormat(
+ "couldn't get a value object for variable %s",
+ m_variable_sp->GetName().AsCString());
+ return;
+ }
+
+ lldb_private::DataExtractor data;
+
+ Error extract_error;
+
+ map.GetMemoryData(data, m_temporary_allocation, valobj_sp->GetByteSize(),
+ extract_error);
+
+ if (!extract_error.Success()) {
+ err.SetErrorStringWithFormat("couldn't get the data for variable %s",
+ m_variable_sp->GetName().AsCString());
+ return;
+ }
+
+ bool actually_write = true;
+
+ if (m_original_data) {
+ if ((data.GetByteSize() == m_original_data->GetByteSize()) &&
+ !memcmp(m_original_data->GetBytes(), data.GetDataStart(),
+ data.GetByteSize())) {
+ actually_write = false;
}
+ }
- // no work needs to be done
- }
+ Error set_error;
- void DumpToLog(IRMemoryMap &map, lldb::addr_t process_address, Log *log) override
- {
- StreamString dump_stream;
+ if (actually_write) {
+ valobj_sp->SetData(data, set_error);
- Error err;
-
- const lldb::addr_t load_addr = process_address + m_offset;
-
- dump_stream.Printf("0x%" PRIx64 ": EntitySymbol (%s)\n", load_addr, m_symbol.GetName().AsCString());
-
- {
- dump_stream.Printf("Pointer:\n");
-
- DataBufferHeap data (m_size, 0);
-
- map.ReadMemory(data.GetBytes(), load_addr, m_size, err);
-
- if (!err.Success())
- {
- dump_stream.Printf(" <could not be read>\n");
- }
- else
- {
- DataExtractor extractor (data.GetBytes(), data.GetByteSize(), map.GetByteOrder(), map.GetAddressByteSize());
-
- extractor.DumpHexBytes(&dump_stream, data.GetBytes(), data.GetByteSize(), 16, load_addr);
-
- dump_stream.PutChar('\n');
- }
+ if (!set_error.Success()) {
+ err.SetErrorStringWithFormat(
+ "couldn't write the new contents of %s back into the variable",
+ m_variable_sp->GetName().AsCString());
+ return;
}
+ }
- log->PutCString(dump_stream.GetData());
+ Error free_error;
+
+ map.Free(m_temporary_allocation, free_error);
+
+ if (!free_error.Success()) {
+ err.SetErrorStringWithFormat(
+ "couldn't free the temporary region for %s: %s",
+ m_variable_sp->GetName().AsCString(), free_error.AsCString());
+ return;
+ }
+
+ m_original_data.reset();
+ m_temporary_allocation = LLDB_INVALID_ADDRESS;
+ m_temporary_allocation_size = 0;
}
+ }
- void Wipe(IRMemoryMap &map, lldb::addr_t process_address) override
+ void DumpToLog(IRMemoryMap &map, lldb::addr_t process_address,
+ Log *log) override {
+ StreamString dump_stream;
+
+ const lldb::addr_t load_addr = process_address + m_offset;
+ dump_stream.Printf("0x%" PRIx64 ": EntityVariable\n", load_addr);
+
+ Error err;
+
+ lldb::addr_t ptr = LLDB_INVALID_ADDRESS;
+
{
+ dump_stream.Printf("Pointer:\n");
+
+ DataBufferHeap data(m_size, 0);
+
+ map.ReadMemory(data.GetBytes(), load_addr, m_size, err);
+
+ if (!err.Success()) {
+ dump_stream.Printf(" <could not be read>\n");
+ } else {
+ DataExtractor extractor(data.GetBytes(), data.GetByteSize(),
+ map.GetByteOrder(), map.GetAddressByteSize());
+
+ extractor.DumpHexBytes(&dump_stream, data.GetBytes(),
+ data.GetByteSize(), 16, load_addr);
+
+ lldb::offset_t offset;
+
+ ptr = extractor.GetPointer(&offset);
+
+ dump_stream.PutChar('\n');
+ }
}
+ if (m_temporary_allocation == LLDB_INVALID_ADDRESS) {
+ dump_stream.Printf("Points to process memory:\n");
+ } else {
+ dump_stream.Printf("Temporary allocation:\n");
+ }
+
+ if (ptr == LLDB_INVALID_ADDRESS) {
+ dump_stream.Printf(" <could not be be found>\n");
+ } else {
+ DataBufferHeap data(m_temporary_allocation_size, 0);
+
+ map.ReadMemory(data.GetBytes(), m_temporary_allocation,
+ m_temporary_allocation_size, err);
+
+ if (!err.Success()) {
+ dump_stream.Printf(" <could not be read>\n");
+ } else {
+ DataExtractor extractor(data.GetBytes(), data.GetByteSize(),
+ map.GetByteOrder(), map.GetAddressByteSize());
+
+ extractor.DumpHexBytes(&dump_stream, data.GetBytes(),
+ data.GetByteSize(), 16, load_addr);
+
+ dump_stream.PutChar('\n');
+ }
+ }
+
+ log->PutCString(dump_stream.GetData());
+ }
+
+ void Wipe(IRMemoryMap &map, lldb::addr_t process_address) override {
+ if (m_temporary_allocation != LLDB_INVALID_ADDRESS) {
+ Error free_error;
+
+ map.Free(m_temporary_allocation, free_error);
+
+ m_temporary_allocation = LLDB_INVALID_ADDRESS;
+ m_temporary_allocation_size = 0;
+ }
+ }
+
private:
- Symbol m_symbol;
+ lldb::VariableSP m_variable_sp;
+ bool m_is_reference;
+ lldb::addr_t m_temporary_allocation;
+ size_t m_temporary_allocation_size;
+ lldb::DataBufferSP m_original_data;
};
-uint32_t
-Materializer::AddSymbol (const Symbol &symbol_sp, Error &err)
-{
- EntityVector::iterator iter = m_entities.insert(m_entities.end(), EntityUP());
- iter->reset (new EntitySymbol (symbol_sp));
- uint32_t ret = AddStructMember(**iter);
- (*iter)->SetOffset(ret);
- return ret;
+uint32_t Materializer::AddVariable(lldb::VariableSP &variable_sp, Error &err) {
+ EntityVector::iterator iter = m_entities.insert(m_entities.end(), EntityUP());
+ iter->reset(new EntityVariable(variable_sp));
+ uint32_t ret = AddStructMember(**iter);
+ (*iter)->SetOffset(ret);
+ return ret;
}
-class EntityRegister : public Materializer::Entity
-{
+class EntityResultVariable : public Materializer::Entity {
public:
- EntityRegister (const RegisterInfo ®ister_info) :
- Entity(),
- m_register_info(register_info)
- {
- // Hard-coding alignment conservatively
- m_size = m_register_info.byte_size;
- m_alignment = m_register_info.byte_size;
+ EntityResultVariable(const CompilerType &type, bool is_program_reference,
+ bool keep_in_memory,
+ Materializer::PersistentVariableDelegate *delegate)
+ : Entity(), m_type(type), m_is_program_reference(is_program_reference),
+ m_keep_in_memory(keep_in_memory),
+ m_temporary_allocation(LLDB_INVALID_ADDRESS),
+ m_temporary_allocation_size(0), m_delegate(delegate) {
+ // Hard-coding to maximum size of a pointer since all results are
+ // materialized by reference
+ m_size = 8;
+ m_alignment = 8;
+ }
+
+ void Materialize(lldb::StackFrameSP &frame_sp, IRMemoryMap &map,
+ lldb::addr_t process_address, Error &err) override {
+ if (!m_is_program_reference) {
+ if (m_temporary_allocation != LLDB_INVALID_ADDRESS) {
+ err.SetErrorString("Trying to create a temporary region for the result "
+ "but one exists");
+ return;
+ }
+
+ const lldb::addr_t load_addr = process_address + m_offset;
+
+ ExecutionContextScope *exe_scope = map.GetBestExecutionContextScope();
+
+ size_t byte_size = m_type.GetByteSize(exe_scope);
+ size_t bit_align = m_type.GetTypeBitAlign();
+ size_t byte_align = (bit_align + 7) / 8;
+
+ if (!byte_align)
+ byte_align = 1;
+
+ Error alloc_error;
+ const bool zero_memory = true;
+
+ m_temporary_allocation = map.Malloc(
+ byte_size, byte_align,
+ lldb::ePermissionsReadable | lldb::ePermissionsWritable,
+ IRMemoryMap::eAllocationPolicyMirror, zero_memory, alloc_error);
+ m_temporary_allocation_size = byte_size;
+
+ if (!alloc_error.Success()) {
+ err.SetErrorStringWithFormat(
+ "couldn't allocate a temporary region for the result: %s",
+ alloc_error.AsCString());
+ return;
+ }
+
+ Error pointer_write_error;
+
+ map.WritePointerToMemory(load_addr, m_temporary_allocation,
+ pointer_write_error);
+
+ if (!pointer_write_error.Success()) {
+ err.SetErrorStringWithFormat("couldn't write the address of the "
+ "temporary region for the result: %s",
+ pointer_write_error.AsCString());
+ }
+ }
+ }
+
+ void Dematerialize(lldb::StackFrameSP &frame_sp, IRMemoryMap &map,
+ lldb::addr_t process_address, lldb::addr_t frame_top,
+ lldb::addr_t frame_bottom, Error &err) override {
+ err.Clear();
+
+ ExecutionContextScope *exe_scope = map.GetBestExecutionContextScope();
+
+ if (!exe_scope) {
+ err.SetErrorString("Couldn't dematerialize a result variable: invalid "
+ "execution context scope");
+ return;
}
- void Materialize(lldb::StackFrameSP &frame_sp,
- IRMemoryMap &map,
- lldb::addr_t process_address,
- Error &err) override
- {
- Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
+ lldb::addr_t address;
+ Error read_error;
+ const lldb::addr_t load_addr = process_address + m_offset;
- const lldb::addr_t load_addr = process_address + m_offset;
+ map.ReadPointerFromMemory(&address, load_addr, read_error);
- if (log)
- {
- log->Printf("EntityRegister::Materialize [address = 0x%" PRIx64 ", m_register_info = %s]",
- (uint64_t)load_addr,
- m_register_info.name);
- }
-
- RegisterValue reg_value;
-
- if (!frame_sp.get())
- {
- err.SetErrorStringWithFormat("couldn't materialize register %s without a stack frame", m_register_info.name);
- return;
- }
-
- lldb::RegisterContextSP reg_context_sp = frame_sp->GetRegisterContext();
-
- if (!reg_context_sp->ReadRegister(&m_register_info, reg_value))
- {
- err.SetErrorStringWithFormat("couldn't read the value of register %s", m_register_info.name);
- return;
- }
-
- DataExtractor register_data;
-
- if (!reg_value.GetData(register_data))
- {
- err.SetErrorStringWithFormat("couldn't get the data for register %s", m_register_info.name);
- return;
- }
-
- if (register_data.GetByteSize() != m_register_info.byte_size)
- {
- err.SetErrorStringWithFormat("data for register %s had size %llu but we expected %llu", m_register_info.name, (unsigned long long)register_data.GetByteSize(), (unsigned long long)m_register_info.byte_size);
- return;
- }
-
- m_register_contents.reset(new DataBufferHeap(register_data.GetDataStart(), register_data.GetByteSize()));
-
- Error write_error;
-
- map.WriteMemory(load_addr, register_data.GetDataStart(), register_data.GetByteSize(), write_error);
-
- if (!write_error.Success())
- {
- err.SetErrorStringWithFormat("couldn't write the contents of register %s: %s", m_register_info.name, write_error.AsCString());
- return;
- }
+ if (!read_error.Success()) {
+ err.SetErrorString("Couldn't dematerialize a result variable: couldn't "
+ "read its address");
+ return;
}
- void Dematerialize(lldb::StackFrameSP &frame_sp,
- IRMemoryMap &map,
- lldb::addr_t process_address,
- lldb::addr_t frame_top,
- lldb::addr_t frame_bottom,
- Error &err) override
- {
- Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
+ lldb::TargetSP target_sp = exe_scope->CalculateTarget();
- const lldb::addr_t load_addr = process_address + m_offset;
-
- if (log)
- {
- log->Printf("EntityRegister::Dematerialize [address = 0x%" PRIx64 ", m_register_info = %s]",
- (uint64_t)load_addr,
- m_register_info.name);
- }
-
- Error extract_error;
-
- DataExtractor register_data;
-
- if (!frame_sp.get())
- {
- err.SetErrorStringWithFormat("couldn't dematerialize register %s without a stack frame", m_register_info.name);
- return;
- }
-
- lldb::RegisterContextSP reg_context_sp = frame_sp->GetRegisterContext();
-
- map.GetMemoryData(register_data, load_addr, m_register_info.byte_size, extract_error);
-
- if (!extract_error.Success())
- {
- err.SetErrorStringWithFormat("couldn't get the data for register %s: %s", m_register_info.name, extract_error.AsCString());
- return;
- }
-
- if (!memcmp(register_data.GetDataStart(), m_register_contents->GetBytes(), register_data.GetByteSize()))
- {
- // No write required, and in particular we avoid errors if the register wasn't writable
-
- m_register_contents.reset();
- return;
- }
-
- m_register_contents.reset();
-
- RegisterValue register_value (const_cast<uint8_t*>(register_data.GetDataStart()), register_data.GetByteSize(), register_data.GetByteOrder());
-
- if (!reg_context_sp->WriteRegister(&m_register_info, register_value))
- {
- err.SetErrorStringWithFormat("couldn't write the value of register %s", m_register_info.name);
- return;
- }
+ if (!target_sp) {
+ err.SetErrorString("Couldn't dematerialize a result variable: no target");
+ return;
}
- void DumpToLog(IRMemoryMap &map, lldb::addr_t process_address, Log *log) override
- {
- StreamString dump_stream;
+ Error type_system_error;
+ TypeSystem *type_system = target_sp->GetScratchTypeSystemForLanguage(
+ &type_system_error, m_type.GetMinimumLanguage());
- Error err;
-
- const lldb::addr_t load_addr = process_address + m_offset;
-
-
- dump_stream.Printf("0x%" PRIx64 ": EntityRegister (%s)\n", load_addr, m_register_info.name);
-
- {
- dump_stream.Printf("Value:\n");
-
- DataBufferHeap data (m_size, 0);
-
- map.ReadMemory(data.GetBytes(), load_addr, m_size, err);
-
- if (!err.Success())
- {
- dump_stream.Printf(" <could not be read>\n");
- }
- else
- {
- DataExtractor extractor (data.GetBytes(), data.GetByteSize(), map.GetByteOrder(), map.GetAddressByteSize());
-
- extractor.DumpHexBytes(&dump_stream, data.GetBytes(), data.GetByteSize(), 16, load_addr);
-
- dump_stream.PutChar('\n');
- }
- }
-
- log->PutCString(dump_stream.GetData());
+ if (!type_system) {
+ err.SetErrorStringWithFormat("Couldn't dematerialize a result variable: "
+ "couldn't get the corresponding type "
+ "system: %s",
+ type_system_error.AsCString());
+ return;
}
- void Wipe(IRMemoryMap &map, lldb::addr_t process_address) override
- {
+ PersistentExpressionState *persistent_state =
+ type_system->GetPersistentExpressionState();
+
+ if (!persistent_state) {
+ err.SetErrorString("Couldn't dematerialize a result variable: "
+ "corresponding type system doesn't handle persistent "
+ "variables");
+ return;
}
+ ConstString name = m_delegate
+ ? m_delegate->GetName()
+ : persistent_state->GetNextPersistentVariableName();
+
+ lldb::ExpressionVariableSP ret = persistent_state->CreatePersistentVariable(
+ exe_scope, name, m_type, map.GetByteOrder(), map.GetAddressByteSize());
+
+ if (!ret) {
+ err.SetErrorStringWithFormat("couldn't dematerialize a result variable: "
+ "failed to make persistent variable %s",
+ name.AsCString());
+ return;
+ }
+
+ lldb::ProcessSP process_sp =
+ map.GetBestExecutionContextScope()->CalculateProcess();
+
+ if (m_delegate) {
+ m_delegate->DidDematerialize(ret);
+ }
+
+ bool can_persist =
+ (m_is_program_reference && process_sp && process_sp->CanJIT() &&
+ !(address >= frame_bottom && address < frame_top));
+
+ if (can_persist && m_keep_in_memory) {
+ ret->m_live_sp = ValueObjectConstResult::Create(exe_scope, m_type, name,
+ address, eAddressTypeLoad,
+ map.GetAddressByteSize());
+ }
+
+ ret->ValueUpdated();
+
+ const size_t pvar_byte_size = ret->GetByteSize();
+ uint8_t *pvar_data = ret->GetValueBytes();
+
+ map.ReadMemory(pvar_data, address, pvar_byte_size, read_error);
+
+ if (!read_error.Success()) {
+ err.SetErrorString(
+ "Couldn't dematerialize a result variable: couldn't read its memory");
+ return;
+ }
+
+ if (!can_persist || !m_keep_in_memory) {
+ ret->m_flags |= ExpressionVariable::EVNeedsAllocation;
+
+ if (m_temporary_allocation != LLDB_INVALID_ADDRESS) {
+ Error free_error;
+ map.Free(m_temporary_allocation, free_error);
+ }
+ } else {
+ ret->m_flags |= ExpressionVariable::EVIsLLDBAllocated;
+ }
+
+ m_temporary_allocation = LLDB_INVALID_ADDRESS;
+ m_temporary_allocation_size = 0;
+ }
+
+ void DumpToLog(IRMemoryMap &map, lldb::addr_t process_address,
+ Log *log) override {
+ StreamString dump_stream;
+
+ const lldb::addr_t load_addr = process_address + m_offset;
+
+ dump_stream.Printf("0x%" PRIx64 ": EntityResultVariable\n", load_addr);
+
+ Error err;
+
+ lldb::addr_t ptr = LLDB_INVALID_ADDRESS;
+
+ {
+ dump_stream.Printf("Pointer:\n");
+
+ DataBufferHeap data(m_size, 0);
+
+ map.ReadMemory(data.GetBytes(), load_addr, m_size, err);
+
+ if (!err.Success()) {
+ dump_stream.Printf(" <could not be read>\n");
+ } else {
+ DataExtractor extractor(data.GetBytes(), data.GetByteSize(),
+ map.GetByteOrder(), map.GetAddressByteSize());
+
+ extractor.DumpHexBytes(&dump_stream, data.GetBytes(),
+ data.GetByteSize(), 16, load_addr);
+
+ lldb::offset_t offset;
+
+ ptr = extractor.GetPointer(&offset);
+
+ dump_stream.PutChar('\n');
+ }
+ }
+
+ if (m_temporary_allocation == LLDB_INVALID_ADDRESS) {
+ dump_stream.Printf("Points to process memory:\n");
+ } else {
+ dump_stream.Printf("Temporary allocation:\n");
+ }
+
+ if (ptr == LLDB_INVALID_ADDRESS) {
+ dump_stream.Printf(" <could not be be found>\n");
+ } else {
+ DataBufferHeap data(m_temporary_allocation_size, 0);
+
+ map.ReadMemory(data.GetBytes(), m_temporary_allocation,
+ m_temporary_allocation_size, err);
+
+ if (!err.Success()) {
+ dump_stream.Printf(" <could not be read>\n");
+ } else {
+ DataExtractor extractor(data.GetBytes(), data.GetByteSize(),
+ map.GetByteOrder(), map.GetAddressByteSize());
+
+ extractor.DumpHexBytes(&dump_stream, data.GetBytes(),
+ data.GetByteSize(), 16, load_addr);
+
+ dump_stream.PutChar('\n');
+ }
+ }
+
+ log->PutCString(dump_stream.GetData());
+ }
+
+ void Wipe(IRMemoryMap &map, lldb::addr_t process_address) override {
+ if (!m_keep_in_memory && m_temporary_allocation != LLDB_INVALID_ADDRESS) {
+ Error free_error;
+
+ map.Free(m_temporary_allocation, free_error);
+ }
+
+ m_temporary_allocation = LLDB_INVALID_ADDRESS;
+ m_temporary_allocation_size = 0;
+ }
+
private:
- RegisterInfo m_register_info;
- lldb::DataBufferSP m_register_contents;
+ CompilerType m_type;
+ bool m_is_program_reference;
+ bool m_keep_in_memory;
+
+ lldb::addr_t m_temporary_allocation;
+ size_t m_temporary_allocation_size;
+ Materializer::PersistentVariableDelegate *m_delegate;
};
-uint32_t
-Materializer::AddRegister (const RegisterInfo ®ister_info, Error &err)
-{
- EntityVector::iterator iter = m_entities.insert(m_entities.end(), EntityUP());
- iter->reset (new EntityRegister (register_info));
- uint32_t ret = AddStructMember(**iter);
- (*iter)->SetOffset(ret);
- return ret;
+uint32_t Materializer::AddResultVariable(const CompilerType &type,
+ bool is_program_reference,
+ bool keep_in_memory,
+ PersistentVariableDelegate *delegate,
+ Error &err) {
+ EntityVector::iterator iter = m_entities.insert(m_entities.end(), EntityUP());
+ iter->reset(new EntityResultVariable(type, is_program_reference,
+ keep_in_memory, delegate));
+ uint32_t ret = AddStructMember(**iter);
+ (*iter)->SetOffset(ret);
+ return ret;
}
-Materializer::Materializer () :
- m_dematerializer_wp(),
- m_current_offset(0),
- m_struct_alignment(8)
-{
+class EntitySymbol : public Materializer::Entity {
+public:
+ EntitySymbol(const Symbol &symbol) : Entity(), m_symbol(symbol) {
+ // Hard-coding to maximum size of a symbol
+ m_size = 8;
+ m_alignment = 8;
+ }
+
+ void Materialize(lldb::StackFrameSP &frame_sp, IRMemoryMap &map,
+ lldb::addr_t process_address, Error &err) override {
+ Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS));
+
+ const lldb::addr_t load_addr = process_address + m_offset;
+
+ if (log) {
+ log->Printf("EntitySymbol::Materialize [address = 0x%" PRIx64
+ ", m_symbol = %s]",
+ (uint64_t)load_addr, m_symbol.GetName().AsCString());
+ }
+
+ const Address sym_address = m_symbol.GetAddress();
+
+ ExecutionContextScope *exe_scope = map.GetBestExecutionContextScope();
+
+ lldb::TargetSP target_sp;
+
+ if (exe_scope)
+ target_sp = map.GetBestExecutionContextScope()->CalculateTarget();
+
+ if (!target_sp) {
+ err.SetErrorStringWithFormat(
+ "couldn't resolve symbol %s because there is no target",
+ m_symbol.GetName().AsCString());
+ return;
+ }
+
+ lldb::addr_t resolved_address = sym_address.GetLoadAddress(target_sp.get());
+
+ if (resolved_address == LLDB_INVALID_ADDRESS)
+ resolved_address = sym_address.GetFileAddress();
+
+ Error pointer_write_error;
+
+ map.WritePointerToMemory(load_addr, resolved_address, pointer_write_error);
+
+ if (!pointer_write_error.Success()) {
+ err.SetErrorStringWithFormat(
+ "couldn't write the address of symbol %s: %s",
+ m_symbol.GetName().AsCString(), pointer_write_error.AsCString());
+ return;
+ }
+ }
+
+ void Dematerialize(lldb::StackFrameSP &frame_sp, IRMemoryMap &map,
+ lldb::addr_t process_address, lldb::addr_t frame_top,
+ lldb::addr_t frame_bottom, Error &err) override {
+ Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS));
+
+ const lldb::addr_t load_addr = process_address + m_offset;
+
+ if (log) {
+ log->Printf("EntitySymbol::Dematerialize [address = 0x%" PRIx64
+ ", m_symbol = %s]",
+ (uint64_t)load_addr, m_symbol.GetName().AsCString());
+ }
+
+ // no work needs to be done
+ }
+
+ void DumpToLog(IRMemoryMap &map, lldb::addr_t process_address,
+ Log *log) override {
+ StreamString dump_stream;
+
+ Error err;
+
+ const lldb::addr_t load_addr = process_address + m_offset;
+
+ dump_stream.Printf("0x%" PRIx64 ": EntitySymbol (%s)\n", load_addr,
+ m_symbol.GetName().AsCString());
+
+ {
+ dump_stream.Printf("Pointer:\n");
+
+ DataBufferHeap data(m_size, 0);
+
+ map.ReadMemory(data.GetBytes(), load_addr, m_size, err);
+
+ if (!err.Success()) {
+ dump_stream.Printf(" <could not be read>\n");
+ } else {
+ DataExtractor extractor(data.GetBytes(), data.GetByteSize(),
+ map.GetByteOrder(), map.GetAddressByteSize());
+
+ extractor.DumpHexBytes(&dump_stream, data.GetBytes(),
+ data.GetByteSize(), 16, load_addr);
+
+ dump_stream.PutChar('\n');
+ }
+ }
+
+ log->PutCString(dump_stream.GetData());
+ }
+
+ void Wipe(IRMemoryMap &map, lldb::addr_t process_address) override {}
+
+private:
+ Symbol m_symbol;
+};
+
+uint32_t Materializer::AddSymbol(const Symbol &symbol_sp, Error &err) {
+ EntityVector::iterator iter = m_entities.insert(m_entities.end(), EntityUP());
+ iter->reset(new EntitySymbol(symbol_sp));
+ uint32_t ret = AddStructMember(**iter);
+ (*iter)->SetOffset(ret);
+ return ret;
}
-Materializer::~Materializer ()
-{
- DematerializerSP dematerializer_sp = m_dematerializer_wp.lock();
+class EntityRegister : public Materializer::Entity {
+public:
+ EntityRegister(const RegisterInfo ®ister_info)
+ : Entity(), m_register_info(register_info) {
+ // Hard-coding alignment conservatively
+ m_size = m_register_info.byte_size;
+ m_alignment = m_register_info.byte_size;
+ }
- if (dematerializer_sp)
- dematerializer_sp->Wipe();
+ void Materialize(lldb::StackFrameSP &frame_sp, IRMemoryMap &map,
+ lldb::addr_t process_address, Error &err) override {
+ Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS));
+
+ const lldb::addr_t load_addr = process_address + m_offset;
+
+ if (log) {
+ log->Printf("EntityRegister::Materialize [address = 0x%" PRIx64
+ ", m_register_info = %s]",
+ (uint64_t)load_addr, m_register_info.name);
+ }
+
+ RegisterValue reg_value;
+
+ if (!frame_sp.get()) {
+ err.SetErrorStringWithFormat(
+ "couldn't materialize register %s without a stack frame",
+ m_register_info.name);
+ return;
+ }
+
+ lldb::RegisterContextSP reg_context_sp = frame_sp->GetRegisterContext();
+
+ if (!reg_context_sp->ReadRegister(&m_register_info, reg_value)) {
+ err.SetErrorStringWithFormat("couldn't read the value of register %s",
+ m_register_info.name);
+ return;
+ }
+
+ DataExtractor register_data;
+
+ if (!reg_value.GetData(register_data)) {
+ err.SetErrorStringWithFormat("couldn't get the data for register %s",
+ m_register_info.name);
+ return;
+ }
+
+ if (register_data.GetByteSize() != m_register_info.byte_size) {
+ err.SetErrorStringWithFormat(
+ "data for register %s had size %llu but we expected %llu",
+ m_register_info.name, (unsigned long long)register_data.GetByteSize(),
+ (unsigned long long)m_register_info.byte_size);
+ return;
+ }
+
+ m_register_contents.reset(new DataBufferHeap(register_data.GetDataStart(),
+ register_data.GetByteSize()));
+
+ Error write_error;
+
+ map.WriteMemory(load_addr, register_data.GetDataStart(),
+ register_data.GetByteSize(), write_error);
+
+ if (!write_error.Success()) {
+ err.SetErrorStringWithFormat(
+ "couldn't write the contents of register %s: %s",
+ m_register_info.name, write_error.AsCString());
+ return;
+ }
+ }
+
+ void Dematerialize(lldb::StackFrameSP &frame_sp, IRMemoryMap &map,
+ lldb::addr_t process_address, lldb::addr_t frame_top,
+ lldb::addr_t frame_bottom, Error &err) override {
+ Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS));
+
+ const lldb::addr_t load_addr = process_address + m_offset;
+
+ if (log) {
+ log->Printf("EntityRegister::Dematerialize [address = 0x%" PRIx64
+ ", m_register_info = %s]",
+ (uint64_t)load_addr, m_register_info.name);
+ }
+
+ Error extract_error;
+
+ DataExtractor register_data;
+
+ if (!frame_sp.get()) {
+ err.SetErrorStringWithFormat(
+ "couldn't dematerialize register %s without a stack frame",
+ m_register_info.name);
+ return;
+ }
+
+ lldb::RegisterContextSP reg_context_sp = frame_sp->GetRegisterContext();
+
+ map.GetMemoryData(register_data, load_addr, m_register_info.byte_size,
+ extract_error);
+
+ if (!extract_error.Success()) {
+ err.SetErrorStringWithFormat("couldn't get the data for register %s: %s",
+ m_register_info.name,
+ extract_error.AsCString());
+ return;
+ }
+
+ if (!memcmp(register_data.GetDataStart(), m_register_contents->GetBytes(),
+ register_data.GetByteSize())) {
+ // No write required, and in particular we avoid errors if the register
+ // wasn't writable
+
+ m_register_contents.reset();
+ return;
+ }
+
+ m_register_contents.reset();
+
+ RegisterValue register_value(
+ const_cast<uint8_t *>(register_data.GetDataStart()),
+ register_data.GetByteSize(), register_data.GetByteOrder());
+
+ if (!reg_context_sp->WriteRegister(&m_register_info, register_value)) {
+ err.SetErrorStringWithFormat("couldn't write the value of register %s",
+ m_register_info.name);
+ return;
+ }
+ }
+
+ void DumpToLog(IRMemoryMap &map, lldb::addr_t process_address,
+ Log *log) override {
+ StreamString dump_stream;
+
+ Error err;
+
+ const lldb::addr_t load_addr = process_address + m_offset;
+
+ dump_stream.Printf("0x%" PRIx64 ": EntityRegister (%s)\n", load_addr,
+ m_register_info.name);
+
+ {
+ dump_stream.Printf("Value:\n");
+
+ DataBufferHeap data(m_size, 0);
+
+ map.ReadMemory(data.GetBytes(), load_addr, m_size, err);
+
+ if (!err.Success()) {
+ dump_stream.Printf(" <could not be read>\n");
+ } else {
+ DataExtractor extractor(data.GetBytes(), data.GetByteSize(),
+ map.GetByteOrder(), map.GetAddressByteSize());
+
+ extractor.DumpHexBytes(&dump_stream, data.GetBytes(),
+ data.GetByteSize(), 16, load_addr);
+
+ dump_stream.PutChar('\n');
+ }
+ }
+
+ log->PutCString(dump_stream.GetData());
+ }
+
+ void Wipe(IRMemoryMap &map, lldb::addr_t process_address) override {}
+
+private:
+ RegisterInfo m_register_info;
+ lldb::DataBufferSP m_register_contents;
+};
+
+uint32_t Materializer::AddRegister(const RegisterInfo ®ister_info,
+ Error &err) {
+ EntityVector::iterator iter = m_entities.insert(m_entities.end(), EntityUP());
+ iter->reset(new EntityRegister(register_info));
+ uint32_t ret = AddStructMember(**iter);
+ (*iter)->SetOffset(ret);
+ return ret;
+}
+
+Materializer::Materializer()
+ : m_dematerializer_wp(), m_current_offset(0), m_struct_alignment(8) {}
+
+Materializer::~Materializer() {
+ DematerializerSP dematerializer_sp = m_dematerializer_wp.lock();
+
+ if (dematerializer_sp)
+ dematerializer_sp->Wipe();
}
Materializer::DematerializerSP
-Materializer::Materialize (lldb::StackFrameSP &frame_sp, IRMemoryMap &map, lldb::addr_t process_address, Error &error)
-{
- ExecutionContextScope *exe_scope = frame_sp.get();
+Materializer::Materialize(lldb::StackFrameSP &frame_sp, IRMemoryMap &map,
+ lldb::addr_t process_address, Error &error) {
+ ExecutionContextScope *exe_scope = frame_sp.get();
- if (!exe_scope)
- exe_scope = map.GetBestExecutionContextScope();
+ if (!exe_scope)
+ exe_scope = map.GetBestExecutionContextScope();
- DematerializerSP dematerializer_sp = m_dematerializer_wp.lock();
+ DematerializerSP dematerializer_sp = m_dematerializer_wp.lock();
- if (dematerializer_sp)
- {
- error.SetErrorToGenericError();
- error.SetErrorString("Couldn't materialize: already materialized");
- }
+ if (dematerializer_sp) {
+ error.SetErrorToGenericError();
+ error.SetErrorString("Couldn't materialize: already materialized");
+ }
- DematerializerSP ret(new Dematerializer(*this, frame_sp, map, process_address));
+ DematerializerSP ret(
+ new Dematerializer(*this, frame_sp, map, process_address));
- if (!exe_scope)
- {
- error.SetErrorToGenericError();
- error.SetErrorString("Couldn't materialize: target doesn't exist");
- }
+ if (!exe_scope) {
+ error.SetErrorToGenericError();
+ error.SetErrorString("Couldn't materialize: target doesn't exist");
+ }
+ for (EntityUP &entity_up : m_entities) {
+ entity_up->Materialize(frame_sp, map, process_address, error);
+
+ if (!error.Success())
+ return DematerializerSP();
+ }
+
+ if (Log *log =
+ lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS)) {
+ log->Printf(
+ "Materializer::Materialize (frame_sp = %p, process_address = 0x%" PRIx64
+ ") materialized:",
+ static_cast<void *>(frame_sp.get()), process_address);
for (EntityUP &entity_up : m_entities)
- {
- entity_up->Materialize(frame_sp, map, process_address, error);
+ entity_up->DumpToLog(map, process_address, log);
+ }
- if (!error.Success())
- return DematerializerSP();
- }
+ m_dematerializer_wp = ret;
- if (Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS))
- {
- log->Printf("Materializer::Materialize (frame_sp = %p, process_address = 0x%" PRIx64 ") materialized:",
- static_cast<void*>(frame_sp.get()), process_address);
- for (EntityUP &entity_up : m_entities)
- entity_up->DumpToLog(map, process_address, log);
- }
-
- m_dematerializer_wp = ret;
-
- return ret;
+ return ret;
}
-void
-Materializer::Dematerializer::Dematerialize (Error &error,
- lldb::addr_t frame_bottom,
- lldb::addr_t frame_top)
-{
- lldb::StackFrameSP frame_sp;
+void Materializer::Dematerializer::Dematerialize(Error &error,
+ lldb::addr_t frame_bottom,
+ lldb::addr_t frame_top) {
+ lldb::StackFrameSP frame_sp;
- lldb::ThreadSP thread_sp = m_thread_wp.lock();
- if (thread_sp)
- frame_sp = thread_sp->GetFrameWithStackID(m_stack_id);
+ lldb::ThreadSP thread_sp = m_thread_wp.lock();
+ if (thread_sp)
+ frame_sp = thread_sp->GetFrameWithStackID(m_stack_id);
- ExecutionContextScope *exe_scope = m_map->GetBestExecutionContextScope();
+ ExecutionContextScope *exe_scope = m_map->GetBestExecutionContextScope();
- if (!IsValid())
- {
- error.SetErrorToGenericError();
- error.SetErrorString("Couldn't dematerialize: invalid dematerializer");
+ if (!IsValid()) {
+ error.SetErrorToGenericError();
+ error.SetErrorString("Couldn't dematerialize: invalid dematerializer");
+ }
+
+ if (!exe_scope) {
+ error.SetErrorToGenericError();
+ error.SetErrorString("Couldn't dematerialize: target is gone");
+ } else {
+ if (Log *log =
+ lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS)) {
+ log->Printf("Materializer::Dematerialize (frame_sp = %p, process_address "
+ "= 0x%" PRIx64 ") about to dematerialize:",
+ static_cast<void *>(frame_sp.get()), m_process_address);
+ for (EntityUP &entity_up : m_materializer->m_entities)
+ entity_up->DumpToLog(*m_map, m_process_address, log);
}
- if (!exe_scope)
- {
- error.SetErrorToGenericError();
- error.SetErrorString("Couldn't dematerialize: target is gone");
+ for (EntityUP &entity_up : m_materializer->m_entities) {
+ entity_up->Dematerialize(frame_sp, *m_map, m_process_address, frame_top,
+ frame_bottom, error);
+
+ if (!error.Success())
+ break;
}
- else
- {
- if (Log *log =lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS))
- {
- log->Printf("Materializer::Dematerialize (frame_sp = %p, process_address = 0x%" PRIx64 ") about to dematerialize:",
- static_cast<void*>(frame_sp.get()), m_process_address);
- for (EntityUP &entity_up : m_materializer->m_entities)
- entity_up->DumpToLog(*m_map, m_process_address, log);
- }
+ }
- for (EntityUP &entity_up : m_materializer->m_entities)
- {
- entity_up->Dematerialize (frame_sp, *m_map, m_process_address, frame_top, frame_bottom, error);
-
- if (!error.Success())
- break;
- }
- }
-
- Wipe();
+ Wipe();
}
-void
-Materializer::Dematerializer::Wipe ()
-{
- if (!IsValid())
- return;
+void Materializer::Dematerializer::Wipe() {
+ if (!IsValid())
+ return;
- for (EntityUP &entity_up : m_materializer->m_entities)
- {
- entity_up->Wipe (*m_map, m_process_address);
- }
+ for (EntityUP &entity_up : m_materializer->m_entities) {
+ entity_up->Wipe(*m_map, m_process_address);
+ }
- m_materializer = nullptr;
- m_map = nullptr;
- m_process_address = LLDB_INVALID_ADDRESS;
+ m_materializer = nullptr;
+ m_map = nullptr;
+ m_process_address = LLDB_INVALID_ADDRESS;
}
-Materializer::PersistentVariableDelegate::~PersistentVariableDelegate() = default;
+Materializer::PersistentVariableDelegate::~PersistentVariableDelegate() =
+ default;
diff --git a/lldb/source/Expression/REPL.cpp b/lldb/source/Expression/REPL.cpp
index 5d28c43..4685b26 100644
--- a/lldb/source/Expression/REPL.cpp
+++ b/lldb/source/Expression/REPL.cpp
@@ -11,11 +11,11 @@
// C++ Includes
// Other libraries and framework includes
// Project includes
+#include "lldb/Expression/REPL.h"
#include "lldb/Core/Debugger.h"
#include "lldb/Core/PluginManager.h"
#include "lldb/Core/StreamFile.h"
#include "lldb/Expression/ExpressionVariable.h"
-#include "lldb/Expression/REPL.h"
#include "lldb/Expression/UserExpression.h"
#include "lldb/Host/HostInfo.h"
#include "lldb/Interpreter/CommandInterpreter.h"
@@ -26,625 +26,560 @@
using namespace lldb_private;
-REPL::REPL(LLVMCastKind kind, Target &target) :
- m_target(target),
- m_kind(kind)
-{
- // Make sure all option values have sane defaults
- Debugger &debugger = m_target.GetDebugger();
- auto exe_ctx = debugger.GetCommandInterpreter().GetExecutionContext();
- m_format_options.OptionParsingStarting(&exe_ctx);
- m_varobj_options.OptionParsingStarting(&exe_ctx);
- m_command_options.OptionParsingStarting(&exe_ctx);
-
- // Default certain settings for REPL regardless of the global settings.
- m_command_options.unwind_on_error = false;
- m_command_options.ignore_breakpoints = false;
- m_command_options.debug = false;
+REPL::REPL(LLVMCastKind kind, Target &target) : m_target(target), m_kind(kind) {
+ // Make sure all option values have sane defaults
+ Debugger &debugger = m_target.GetDebugger();
+ auto exe_ctx = debugger.GetCommandInterpreter().GetExecutionContext();
+ m_format_options.OptionParsingStarting(&exe_ctx);
+ m_varobj_options.OptionParsingStarting(&exe_ctx);
+ m_command_options.OptionParsingStarting(&exe_ctx);
+
+ // Default certain settings for REPL regardless of the global settings.
+ m_command_options.unwind_on_error = false;
+ m_command_options.ignore_breakpoints = false;
+ m_command_options.debug = false;
}
REPL::~REPL() = default;
-lldb::REPLSP
-REPL::Create(Error &err, lldb::LanguageType language, Debugger *debugger, Target *target, const char *repl_options)
-{
- uint32_t idx = 0;
- lldb::REPLSP ret;
-
- while (REPLCreateInstance create_instance = PluginManager::GetREPLCreateCallbackAtIndex(idx++))
- {
- ret = (*create_instance)(err, language, debugger, target, repl_options);
- if (ret)
- {
+lldb::REPLSP REPL::Create(Error &err, lldb::LanguageType language,
+ Debugger *debugger, Target *target,
+ const char *repl_options) {
+ uint32_t idx = 0;
+ lldb::REPLSP ret;
+
+ while (REPLCreateInstance create_instance =
+ PluginManager::GetREPLCreateCallbackAtIndex(idx++)) {
+ ret = (*create_instance)(err, language, debugger, target, repl_options);
+ if (ret) {
+ break;
+ }
+ }
+
+ return ret;
+}
+
+std::string REPL::GetSourcePath() {
+ ConstString file_basename = GetSourceFileBasename();
+
+ FileSpec tmpdir_file_spec;
+ if (HostInfo::GetLLDBPath(lldb::ePathTypeLLDBTempSystemDir,
+ tmpdir_file_spec)) {
+ tmpdir_file_spec.GetFilename().SetCString(file_basename.AsCString());
+ m_repl_source_path = tmpdir_file_spec.GetPath();
+ } else {
+ tmpdir_file_spec = FileSpec("/tmp", false);
+ tmpdir_file_spec.AppendPathComponent(file_basename.AsCString());
+ }
+
+ return tmpdir_file_spec.GetPath();
+}
+
+lldb::IOHandlerSP REPL::GetIOHandler() {
+ if (!m_io_handler_sp) {
+ Debugger &debugger = m_target.GetDebugger();
+ m_io_handler_sp.reset(
+ new IOHandlerEditline(debugger, IOHandler::Type::REPL,
+ "lldb-repl", // Name of input reader for history
+ "> ", // prompt
+ ". ", // Continuation prompt
+ true, // Multi-line
+ true, // The REPL prompt is always colored
+ 1, // Line number
+ *this));
+
+ // Don't exit if CTRL+C is pressed
+ static_cast<IOHandlerEditline *>(m_io_handler_sp.get())
+ ->SetInterruptExits(false);
+
+ if (m_io_handler_sp->GetIsInteractive() &&
+ m_io_handler_sp->GetIsRealTerminal()) {
+ m_indent_str.assign(debugger.GetTabSize(), ' ');
+ m_enable_auto_indent = debugger.GetAutoIndent();
+ } else {
+ m_indent_str.clear();
+ m_enable_auto_indent = false;
+ }
+ }
+ return m_io_handler_sp;
+}
+
+void REPL::IOHandlerActivated(IOHandler &io_handler) {
+ lldb::ProcessSP process_sp = m_target.GetProcessSP();
+ if (process_sp && process_sp->IsAlive())
+ return;
+ lldb::StreamFileSP error_sp(io_handler.GetErrorStreamFile());
+ error_sp->Printf("REPL requires a running target process.\n");
+ io_handler.SetIsDone(true);
+}
+
+bool REPL::IOHandlerInterrupt(IOHandler &io_handler) { return false; }
+
+void REPL::IOHandlerInputInterrupted(IOHandler &io_handler, std::string &line) {
+}
+
+const char *REPL::IOHandlerGetFixIndentationCharacters() {
+ return (m_enable_auto_indent ? GetAutoIndentCharacters() : nullptr);
+}
+
+ConstString REPL::IOHandlerGetControlSequence(char ch) {
+ if (ch == 'd')
+ return ConstString(":quit\n");
+ return ConstString();
+}
+
+const char *REPL::IOHandlerGetCommandPrefix() { return ":"; }
+
+const char *REPL::IOHandlerGetHelpPrologue() {
+ return "\nThe REPL (Read-Eval-Print-Loop) acts like an interpreter. "
+ "Valid statements, expressions, and declarations are immediately "
+ "compiled and executed.\n\n"
+ "The complete set of LLDB debugging commands are also available as "
+ "described below. Commands "
+ "must be prefixed with a colon at the REPL prompt (:quit for "
+ "example.) Typing just a colon "
+ "followed by return will switch to the LLDB prompt.\n\n";
+}
+
+bool REPL::IOHandlerIsInputComplete(IOHandler &io_handler, StringList &lines) {
+ // Check for meta command
+ const size_t num_lines = lines.GetSize();
+ if (num_lines == 1) {
+ const char *first_line = lines.GetStringAtIndex(0);
+ if (first_line[0] == ':')
+ return true; // Meta command is a single line where that starts with ':'
+ }
+
+ // Check if REPL input is done
+ std::string source_string(lines.CopyList());
+ return SourceIsComplete(source_string);
+}
+
+int REPL::CalculateActualIndentation(const StringList &lines) {
+ std::string last_line = lines[lines.GetSize() - 1];
+
+ int actual_indent = 0;
+ for (char &ch : last_line) {
+ if (ch != ' ')
+ break;
+ ++actual_indent;
+ }
+
+ return actual_indent;
+}
+
+int REPL::IOHandlerFixIndentation(IOHandler &io_handler,
+ const StringList &lines,
+ int cursor_position) {
+ if (!m_enable_auto_indent)
+ return 0;
+
+ if (!lines.GetSize()) {
+ return 0;
+ }
+
+ int tab_size = io_handler.GetDebugger().GetTabSize();
+
+ lldb::offset_t desired_indent =
+ GetDesiredIndentation(lines, cursor_position, tab_size);
+
+ int actual_indent = REPL::CalculateActualIndentation(lines);
+
+ if (desired_indent == LLDB_INVALID_OFFSET)
+ return 0;
+
+ return (int)desired_indent - actual_indent;
+}
+
+void REPL::IOHandlerInputComplete(IOHandler &io_handler, std::string &code) {
+ lldb::StreamFileSP output_sp(io_handler.GetOutputStreamFile());
+ lldb::StreamFileSP error_sp(io_handler.GetErrorStreamFile());
+ bool extra_line = false;
+ bool did_quit = false;
+
+ if (code.empty()) {
+ m_code.AppendString("");
+ static_cast<IOHandlerEditline &>(io_handler)
+ .SetBaseLineNumber(m_code.GetSize() + 1);
+ } else {
+ Debugger &debugger = m_target.GetDebugger();
+ CommandInterpreter &ci = debugger.GetCommandInterpreter();
+ extra_line = ci.GetSpaceReplPrompts();
+
+ ExecutionContext exe_ctx(m_target.GetProcessSP()
+ ->GetThreadList()
+ .GetSelectedThread()
+ ->GetSelectedFrame()
+ .get());
+
+ lldb::ProcessSP process_sp(exe_ctx.GetProcessSP());
+
+ if (code[0] == ':') {
+ // Meta command
+ // Strip the ':'
+ code.erase(0, 1);
+ if (Args::StripSpaces(code)) {
+ // "lldb" was followed by arguments, so just execute the command dump
+ // the results
+
+ // Turn off prompt on quit in case the user types ":quit"
+ const bool saved_prompt_on_quit = ci.GetPromptOnQuit();
+ if (saved_prompt_on_quit)
+ ci.SetPromptOnQuit(false);
+
+ // Execute the command
+ CommandReturnObject result;
+ result.SetImmediateOutputStream(output_sp);
+ result.SetImmediateErrorStream(error_sp);
+ ci.HandleCommand(code.c_str(), eLazyBoolNo, result);
+
+ if (saved_prompt_on_quit)
+ ci.SetPromptOnQuit(true);
+
+ if (result.GetStatus() == lldb::eReturnStatusQuit) {
+ did_quit = true;
+ io_handler.SetIsDone(true);
+ if (debugger.CheckTopIOHandlerTypes(
+ IOHandler::Type::REPL, IOHandler::Type::CommandInterpreter)) {
+ // We typed "quit" or an alias to quit so we need to check if the
+ // command interpreter is above us and tell it that it is done as
+ // well
+ // so we don't drop back into the command interpreter if we have
+ // already
+ // quit
+ lldb::IOHandlerSP io_handler_sp(ci.GetIOHandler());
+ if (io_handler_sp)
+ io_handler_sp->SetIsDone(true);
+ }
+ }
+ } else {
+ // ":" was followed by no arguments, so push the LLDB command prompt
+ if (debugger.CheckTopIOHandlerTypes(
+ IOHandler::Type::REPL, IOHandler::Type::CommandInterpreter)) {
+ // If the user wants to get back to the command interpreter and the
+ // command interpreter is what launched the REPL, then just let the
+ // REPL exit and fall back to the command interpreter.
+ io_handler.SetIsDone(true);
+ } else {
+ // The REPL wasn't launched the by the command interpreter, it is the
+ // base IOHandler, so we need to get the command interpreter and
+ lldb::IOHandlerSP io_handler_sp(ci.GetIOHandler());
+ if (io_handler_sp) {
+ io_handler_sp->SetIsDone(false);
+ debugger.PushIOHandler(ci.GetIOHandler());
+ }
+ }
+ }
+ } else {
+ // Unwind any expression we might have been running in case our REPL
+ // expression crashed and the user was looking around
+ if (m_dedicated_repl_mode) {
+ Thread *thread = exe_ctx.GetThreadPtr();
+ if (thread && thread->UnwindInnermostExpression().Success()) {
+ thread->SetSelectedFrameByIndex(0, false);
+ exe_ctx.SetFrameSP(thread->GetSelectedFrame());
+ }
+ }
+
+ const bool colorize_err = error_sp->GetFile().GetIsTerminalWithColors();
+
+ EvaluateExpressionOptions expr_options;
+ expr_options.SetCoerceToId(m_varobj_options.use_objc);
+ expr_options.SetUnwindOnError(m_command_options.unwind_on_error);
+ expr_options.SetIgnoreBreakpoints(m_command_options.ignore_breakpoints);
+ expr_options.SetKeepInMemory(true);
+ expr_options.SetUseDynamic(m_varobj_options.use_dynamic);
+ expr_options.SetTryAllThreads(m_command_options.try_all_threads);
+ expr_options.SetGenerateDebugInfo(true);
+ expr_options.SetREPLEnabled(true);
+ expr_options.SetColorizeErrors(colorize_err);
+ expr_options.SetPoundLine(m_repl_source_path.c_str(),
+ m_code.GetSize() + 1);
+ if (m_command_options.timeout > 0)
+ expr_options.SetTimeoutUsec(m_command_options.timeout);
+ else
+ expr_options.SetTimeoutUsec(0);
+
+ expr_options.SetLanguage(GetLanguage());
+
+ PersistentExpressionState *persistent_state =
+ m_target.GetPersistentExpressionStateForLanguage(GetLanguage());
+
+ const size_t var_count_before = persistent_state->GetSize();
+
+ const char *expr_prefix = nullptr;
+ lldb::ValueObjectSP result_valobj_sp;
+ Error error;
+ lldb::ModuleSP jit_module_sp;
+ lldb::ExpressionResults execution_results =
+ UserExpression::Evaluate(exe_ctx, expr_options, code.c_str(),
+ expr_prefix, result_valobj_sp, error,
+ 0, // Line offset
+ nullptr, // Fixed Expression
+ &jit_module_sp);
+
+ // CommandInterpreter &ci = debugger.GetCommandInterpreter();
+
+ if (process_sp && process_sp->IsAlive()) {
+ bool add_to_code = true;
+ bool handled = false;
+ if (result_valobj_sp) {
+ lldb::Format format = m_format_options.GetFormat();
+
+ if (result_valobj_sp->GetError().Success()) {
+ handled |= PrintOneVariable(debugger, output_sp, result_valobj_sp);
+ } else if (result_valobj_sp->GetError().GetError() ==
+ UserExpression::kNoResult) {
+ if (format != lldb::eFormatVoid && debugger.GetNotifyVoid()) {
+ error_sp->PutCString("(void)\n");
+ handled = true;
+ }
+ }
+ }
+
+ if (debugger.GetPrintDecls()) {
+ for (size_t vi = var_count_before, ve = persistent_state->GetSize();
+ vi != ve; ++vi) {
+ lldb::ExpressionVariableSP persistent_var_sp =
+ persistent_state->GetVariableAtIndex(vi);
+ lldb::ValueObjectSP valobj_sp = persistent_var_sp->GetValueObject();
+
+ PrintOneVariable(debugger, output_sp, valobj_sp,
+ persistent_var_sp.get());
+ }
+ }
+
+ if (!handled) {
+ bool useColors = error_sp->GetFile().GetIsTerminalWithColors();
+ switch (execution_results) {
+ case lldb::eExpressionSetupError:
+ case lldb::eExpressionParseError:
+ add_to_code = false;
+ LLVM_FALLTHROUGH;
+ case lldb::eExpressionDiscarded:
+ error_sp->Printf("%s\n", error.AsCString());
break;
+
+ case lldb::eExpressionCompleted:
+ break;
+ case lldb::eExpressionInterrupted:
+ if (useColors) {
+ error_sp->Printf(ANSI_ESCAPE1(ANSI_FG_COLOR_RED));
+ error_sp->Printf(ANSI_ESCAPE1(ANSI_CTRL_BOLD));
+ }
+ error_sp->Printf("Execution interrupted. ");
+ if (useColors)
+ error_sp->Printf(ANSI_ESCAPE1(ANSI_CTRL_NORMAL));
+ error_sp->Printf("Enter code to recover and continue.\nEnter LLDB "
+ "commands to investigate (type :help for "
+ "assistance.)\n");
+ break;
+
+ case lldb::eExpressionHitBreakpoint:
+ // Breakpoint was hit, drop into LLDB command interpreter
+ if (useColors) {
+ error_sp->Printf(ANSI_ESCAPE1(ANSI_FG_COLOR_RED));
+ error_sp->Printf(ANSI_ESCAPE1(ANSI_CTRL_BOLD));
+ }
+ output_sp->Printf("Execution stopped at breakpoint. ");
+ if (useColors)
+ error_sp->Printf(ANSI_ESCAPE1(ANSI_CTRL_NORMAL));
+ output_sp->Printf("Enter LLDB commands to investigate (type help "
+ "for assistance.)\n");
+ {
+ lldb::IOHandlerSP io_handler_sp(ci.GetIOHandler());
+ if (io_handler_sp) {
+ io_handler_sp->SetIsDone(false);
+ debugger.PushIOHandler(ci.GetIOHandler());
+ }
+ }
+ break;
+
+ case lldb::eExpressionTimedOut:
+ error_sp->Printf("error: timeout\n");
+ if (error.AsCString())
+ error_sp->Printf("error: %s\n", error.AsCString());
+ break;
+ case lldb::eExpressionResultUnavailable:
+ // Shoulnd't happen???
+ error_sp->Printf("error: could not fetch result -- %s\n",
+ error.AsCString());
+ break;
+ case lldb::eExpressionStoppedForDebug:
+ // Shoulnd't happen???
+ error_sp->Printf("error: stopped for debug -- %s\n",
+ error.AsCString());
+ break;
+ }
}
+
+ if (add_to_code) {
+ const uint32_t new_default_line = m_code.GetSize() + 1;
+
+ m_code.SplitIntoLines(code);
+
+ // Update our code on disk
+ if (!m_repl_source_path.empty()) {
+ lldb_private::File file(m_repl_source_path.c_str(),
+ File::eOpenOptionWrite |
+ File::eOpenOptionTruncate |
+ File::eOpenOptionCanCreate,
+ lldb::eFilePermissionsFileDefault);
+ std::string code(m_code.CopyList());
+ code.append(1, '\n');
+ size_t bytes_written = code.size();
+ file.Write(code.c_str(), bytes_written);
+ file.Close();
+
+ // Now set the default file and line to the REPL source file
+ m_target.GetSourceManager().SetDefaultFileAndLine(
+ FileSpec(m_repl_source_path.c_str(), false), new_default_line);
+ }
+ static_cast<IOHandlerEditline &>(io_handler)
+ .SetBaseLineNumber(m_code.GetSize() + 1);
+ }
+ if (extra_line) {
+ fprintf(output_sp->GetFile().GetStream(), "\n");
+ }
+ }
}
-
- return ret;
+
+ // Don't complain about the REPL process going away if we are in the process
+ // of quitting.
+ if (!did_quit && (!process_sp || !process_sp->IsAlive())) {
+ error_sp->Printf(
+ "error: REPL process is no longer alive, exiting REPL\n");
+ io_handler.SetIsDone(true);
+ }
+ }
}
-std::string
-REPL::GetSourcePath()
-{
- ConstString file_basename = GetSourceFileBasename();
-
- FileSpec tmpdir_file_spec;
- if (HostInfo::GetLLDBPath (lldb::ePathTypeLLDBTempSystemDir, tmpdir_file_spec))
- {
- tmpdir_file_spec.GetFilename().SetCString(file_basename.AsCString());
- m_repl_source_path = tmpdir_file_spec.GetPath();
+int REPL::IOHandlerComplete(IOHandler &io_handler, const char *current_line,
+ const char *cursor, const char *last_char,
+ int skip_first_n_matches, int max_matches,
+ StringList &matches) {
+ matches.Clear();
+
+ llvm::StringRef line(current_line, cursor - current_line);
+
+ // Complete an LLDB command if the first character is a colon...
+ if (!line.empty() && line[0] == ':') {
+ Debugger &debugger = m_target.GetDebugger();
+
+ // auto complete LLDB commands
+ const char *lldb_current_line = line.substr(1).data();
+ return debugger.GetCommandInterpreter().HandleCompletion(
+ lldb_current_line, cursor, last_char, skip_first_n_matches, max_matches,
+ matches);
+ }
+
+ // Strip spaces from the line and see if we had only spaces
+ line = line.ltrim();
+ if (line.empty()) {
+ // Only spaces on this line, so just indent
+ matches.AppendString(m_indent_str);
+ return 1;
+ }
+
+ std::string current_code;
+ current_code.append(m_code.CopyList());
+
+ IOHandlerEditline &editline = static_cast<IOHandlerEditline &>(io_handler);
+ const StringList *current_lines = editline.GetCurrentLines();
+ if (current_lines) {
+ const uint32_t current_line_idx = editline.GetCurrentLineIndex();
+
+ if (current_line_idx < current_lines->GetSize()) {
+ for (uint32_t i = 0; i < current_line_idx; ++i) {
+ const char *line_cstr = current_lines->GetStringAtIndex(i);
+ if (line_cstr) {
+ current_code.append("\n");
+ current_code.append(line_cstr);
+ }
+ }
}
- else
- {
- tmpdir_file_spec = FileSpec("/tmp", false);
- tmpdir_file_spec.AppendPathComponent(file_basename.AsCString());
- }
-
- return tmpdir_file_spec.GetPath();
+ }
+
+ if (cursor > current_line) {
+ current_code.append("\n");
+ current_code.append(current_line, cursor - current_line);
+ }
+
+ return CompleteCode(current_code, matches);
}
-lldb::IOHandlerSP
-REPL::GetIOHandler()
-{
- if (!m_io_handler_sp)
- {
- Debugger &debugger = m_target.GetDebugger();
- m_io_handler_sp.reset (new IOHandlerEditline (debugger,
- IOHandler::Type::REPL,
- "lldb-repl", // Name of input reader for history
- "> ", // prompt
- ". ", // Continuation prompt
- true, // Multi-line
- true, // The REPL prompt is always colored
- 1, // Line number
- *this));
-
- // Don't exit if CTRL+C is pressed
- static_cast<IOHandlerEditline *>(m_io_handler_sp.get())->SetInterruptExits(false);
-
- if (m_io_handler_sp->GetIsInteractive() && m_io_handler_sp->GetIsRealTerminal())
- {
- m_indent_str.assign (debugger.GetTabSize(), ' ');
- m_enable_auto_indent = debugger.GetAutoIndent();
- }
- else
- {
- m_indent_str.clear();
- m_enable_auto_indent = false;
- }
-
- }
- return m_io_handler_sp;
+bool QuitCommandOverrideCallback(void *baton, const char **argv) {
+ Target *target = (Target *)baton;
+ lldb::ProcessSP process_sp(target->GetProcessSP());
+ if (process_sp) {
+ process_sp->Destroy(false);
+ process_sp->GetTarget().GetDebugger().ClearIOHandlers();
+ }
+ return false;
}
-void
-REPL::IOHandlerActivated (IOHandler &io_handler)
-{
+Error REPL::RunLoop() {
+ Error error;
+
+ error = DoInitialization();
+ m_repl_source_path = GetSourcePath();
+
+ if (!error.Success())
+ return error;
+
+ Debugger &debugger = m_target.GetDebugger();
+
+ lldb::IOHandlerSP io_handler_sp(GetIOHandler());
+
+ FileSpec save_default_file;
+ uint32_t save_default_line = 0;
+
+ if (!m_repl_source_path.empty()) {
+ // Save the current default file and line
+ m_target.GetSourceManager().GetDefaultFileAndLine(save_default_file,
+ save_default_line);
+ }
+
+ debugger.PushIOHandler(io_handler_sp);
+
+ // Check if we are in dedicated REPL mode where LLDB was start with the
+ // "--repl" option
+ // from the command line. Currently we know this by checking if the debugger
+ // already
+ // has a IOHandler thread.
+ if (!debugger.HasIOHandlerThread()) {
+ // The debugger doesn't have an existing IOHandler thread, so this must be
+ // dedicated REPL mode...
+ m_dedicated_repl_mode = true;
+ debugger.StartIOHandlerThread();
+ std::string command_name_str("quit");
+ CommandObject *cmd_obj =
+ debugger.GetCommandInterpreter().GetCommandObjectForCommand(
+ command_name_str);
+ if (cmd_obj) {
+ assert(command_name_str.empty());
+ cmd_obj->SetOverrideCallback(QuitCommandOverrideCallback, &m_target);
+ }
+ }
+
+ // Wait for the REPL command interpreter to get popped
+ io_handler_sp->WaitForPop();
+
+ if (m_dedicated_repl_mode) {
+ // If we were in dedicated REPL mode we would have started the
+ // IOHandler thread, and we should kill our process
lldb::ProcessSP process_sp = m_target.GetProcessSP();
if (process_sp && process_sp->IsAlive())
- return;
- lldb::StreamFileSP error_sp(io_handler.GetErrorStreamFile());
- error_sp->Printf("REPL requires a running target process.\n");
- io_handler.SetIsDone(true);
-}
+ process_sp->Destroy(false);
-bool
-REPL::IOHandlerInterrupt (IOHandler &io_handler)
-{
- return false;
-}
+ // Wait for the IO handler thread to exit (TODO: don't do this if the IO
+ // handler thread already exists...)
+ debugger.JoinIOHandlerThread();
+ }
-void
-REPL::IOHandlerInputInterrupted (IOHandler &io_handler,
- std::string &line)
-{
-}
-
-const char *
-REPL::IOHandlerGetFixIndentationCharacters()
-{
- return (m_enable_auto_indent ? GetAutoIndentCharacters() : nullptr);
-}
-
-ConstString
-REPL::IOHandlerGetControlSequence (char ch)
-{
- if (ch == 'd')
- return ConstString(":quit\n");
- return ConstString();
-}
-
-const char *
-REPL::IOHandlerGetCommandPrefix ()
-{
- return ":";
-}
-
-const char *
-REPL::IOHandlerGetHelpPrologue ()
-{
- return "\nThe REPL (Read-Eval-Print-Loop) acts like an interpreter. "
- "Valid statements, expressions, and declarations are immediately compiled and executed.\n\n"
- "The complete set of LLDB debugging commands are also available as described below. Commands "
- "must be prefixed with a colon at the REPL prompt (:quit for example.) Typing just a colon "
- "followed by return will switch to the LLDB prompt.\n\n";
-}
-
-bool
-REPL::IOHandlerIsInputComplete (IOHandler &io_handler,
- StringList &lines)
-{
- // Check for meta command
- const size_t num_lines = lines.GetSize();
- if (num_lines == 1)
- {
- const char *first_line = lines.GetStringAtIndex(0);
- if (first_line[0] == ':')
- return true; // Meta command is a single line where that starts with ':'
- }
-
- // Check if REPL input is done
- std::string source_string (lines.CopyList());
- return SourceIsComplete(source_string);
-}
-
-int
-REPL::CalculateActualIndentation (const StringList &lines)
-{
- std::string last_line = lines[lines.GetSize() - 1];
-
- int actual_indent = 0;
- for (char &ch : last_line)
- {
- if (ch != ' ') break;
- ++actual_indent;
- }
-
- return actual_indent;
-}
-
-int
-REPL::IOHandlerFixIndentation (IOHandler &io_handler,
- const StringList &lines,
- int cursor_position)
-{
- if (!m_enable_auto_indent) return 0;
-
- if (!lines.GetSize())
- {
- return 0;
- }
-
- int tab_size = io_handler.GetDebugger().GetTabSize();
-
- lldb::offset_t desired_indent = GetDesiredIndentation(lines,
- cursor_position,
- tab_size);
-
- int actual_indent = REPL::CalculateActualIndentation(lines);
-
- if (desired_indent == LLDB_INVALID_OFFSET)
- return 0;
-
- return (int)desired_indent - actual_indent;
-}
-
-void
-REPL::IOHandlerInputComplete (IOHandler &io_handler, std::string &code)
-{
- lldb::StreamFileSP output_sp(io_handler.GetOutputStreamFile());
- lldb::StreamFileSP error_sp(io_handler.GetErrorStreamFile());
- bool extra_line = false;
- bool did_quit = false;
-
- if (code.empty())
- {
- m_code.AppendString("");
- static_cast<IOHandlerEditline &>(io_handler).SetBaseLineNumber(m_code.GetSize()+1);
- }
- else
- {
- Debugger &debugger = m_target.GetDebugger();
- CommandInterpreter &ci = debugger.GetCommandInterpreter();
- extra_line = ci.GetSpaceReplPrompts();
-
- ExecutionContext exe_ctx (m_target.GetProcessSP()->GetThreadList().GetSelectedThread()->GetSelectedFrame().get());
-
- lldb::ProcessSP process_sp(exe_ctx.GetProcessSP());
-
- if (code[0] == ':')
- {
- // Meta command
- // Strip the ':'
- code.erase(0, 1);
- if (Args::StripSpaces (code))
- {
- // "lldb" was followed by arguments, so just execute the command dump the results
-
- // Turn off prompt on quit in case the user types ":quit"
- const bool saved_prompt_on_quit = ci.GetPromptOnQuit();
- if (saved_prompt_on_quit)
- ci.SetPromptOnQuit(false);
-
- // Execute the command
- CommandReturnObject result;
- result.SetImmediateOutputStream(output_sp);
- result.SetImmediateErrorStream(error_sp);
- ci.HandleCommand(code.c_str(), eLazyBoolNo, result);
-
- if (saved_prompt_on_quit)
- ci.SetPromptOnQuit(true);
-
- if (result.GetStatus() == lldb::eReturnStatusQuit)
- {
- did_quit = true;
- io_handler.SetIsDone(true);
- if (debugger.CheckTopIOHandlerTypes(IOHandler::Type::REPL, IOHandler::Type::CommandInterpreter))
- {
- // We typed "quit" or an alias to quit so we need to check if the
- // command interpreter is above us and tell it that it is done as well
- // so we don't drop back into the command interpreter if we have already
- // quit
- lldb::IOHandlerSP io_handler_sp (ci.GetIOHandler());
- if (io_handler_sp)
- io_handler_sp->SetIsDone(true);
- }
- }
- }
- else
- {
- // ":" was followed by no arguments, so push the LLDB command prompt
- if (debugger.CheckTopIOHandlerTypes(IOHandler::Type::REPL, IOHandler::Type::CommandInterpreter))
- {
- // If the user wants to get back to the command interpreter and the
- // command interpreter is what launched the REPL, then just let the
- // REPL exit and fall back to the command interpreter.
- io_handler.SetIsDone(true);
- }
- else
- {
- // The REPL wasn't launched the by the command interpreter, it is the
- // base IOHandler, so we need to get the command interpreter and
- lldb::IOHandlerSP io_handler_sp (ci.GetIOHandler());
- if (io_handler_sp)
- {
- io_handler_sp->SetIsDone(false);
- debugger.PushIOHandler(ci.GetIOHandler());
- }
- }
- }
- }
- else
- {
- // Unwind any expression we might have been running in case our REPL
- // expression crashed and the user was looking around
- if (m_dedicated_repl_mode)
- {
- Thread *thread = exe_ctx.GetThreadPtr();
- if (thread && thread->UnwindInnermostExpression().Success())
- {
- thread->SetSelectedFrameByIndex(0, false);
- exe_ctx.SetFrameSP(thread->GetSelectedFrame());
- }
- }
-
- const bool colorize_err = error_sp->GetFile().GetIsTerminalWithColors();
-
- EvaluateExpressionOptions expr_options;
- expr_options.SetCoerceToId(m_varobj_options.use_objc);
- expr_options.SetUnwindOnError(m_command_options.unwind_on_error);
- expr_options.SetIgnoreBreakpoints (m_command_options.ignore_breakpoints);
- expr_options.SetKeepInMemory(true);
- expr_options.SetUseDynamic(m_varobj_options.use_dynamic);
- expr_options.SetTryAllThreads(m_command_options.try_all_threads);
- expr_options.SetGenerateDebugInfo(true);
- expr_options.SetREPLEnabled (true);
- expr_options.SetColorizeErrors(colorize_err);
- expr_options.SetPoundLine(m_repl_source_path.c_str(), m_code.GetSize() + 1);
- if (m_command_options.timeout > 0)
- expr_options.SetTimeoutUsec(m_command_options.timeout);
- else
- expr_options.SetTimeoutUsec(0);
-
- expr_options.SetLanguage(GetLanguage());
-
- PersistentExpressionState *persistent_state = m_target.GetPersistentExpressionStateForLanguage(GetLanguage());
-
- const size_t var_count_before = persistent_state->GetSize();
-
- const char *expr_prefix = nullptr;
- lldb::ValueObjectSP result_valobj_sp;
- Error error;
- lldb::ModuleSP jit_module_sp;
- lldb::ExpressionResults execution_results = UserExpression::Evaluate (exe_ctx,
- expr_options,
- code.c_str(),
- expr_prefix,
- result_valobj_sp,
- error,
- 0, // Line offset
- nullptr, // Fixed Expression
- &jit_module_sp);
-
- //CommandInterpreter &ci = debugger.GetCommandInterpreter();
-
- if (process_sp && process_sp->IsAlive())
- {
- bool add_to_code = true;
- bool handled = false;
- if (result_valobj_sp)
- {
- lldb::Format format = m_format_options.GetFormat();
-
- if (result_valobj_sp->GetError().Success())
- {
- handled |= PrintOneVariable(debugger, output_sp, result_valobj_sp);
- }
- else if (result_valobj_sp->GetError().GetError() == UserExpression::kNoResult)
- {
- if (format != lldb::eFormatVoid && debugger.GetNotifyVoid())
- {
- error_sp->PutCString("(void)\n");
- handled = true;
- }
- }
- }
-
- if (debugger.GetPrintDecls())
- {
- for (size_t vi = var_count_before, ve = persistent_state->GetSize();
- vi != ve;
- ++vi)
- {
- lldb::ExpressionVariableSP persistent_var_sp = persistent_state->GetVariableAtIndex(vi);
- lldb::ValueObjectSP valobj_sp = persistent_var_sp->GetValueObject();
-
- PrintOneVariable(debugger, output_sp, valobj_sp, persistent_var_sp.get());
- }
- }
-
- if (!handled)
- {
- bool useColors = error_sp->GetFile().GetIsTerminalWithColors();
- switch (execution_results)
- {
- case lldb::eExpressionSetupError:
- case lldb::eExpressionParseError:
- add_to_code = false;
- LLVM_FALLTHROUGH;
- case lldb::eExpressionDiscarded:
- error_sp->Printf("%s\n", error.AsCString());
- break;
-
- case lldb::eExpressionCompleted:
- break;
- case lldb::eExpressionInterrupted:
- if (useColors) {
- error_sp->Printf(ANSI_ESCAPE1(ANSI_FG_COLOR_RED));
- error_sp->Printf(ANSI_ESCAPE1(ANSI_CTRL_BOLD));
- }
- error_sp->Printf("Execution interrupted. ");
- if (useColors) error_sp->Printf(ANSI_ESCAPE1(ANSI_CTRL_NORMAL));
- error_sp->Printf("Enter code to recover and continue.\nEnter LLDB commands to investigate (type :help for assistance.)\n");
- break;
-
- case lldb::eExpressionHitBreakpoint:
- // Breakpoint was hit, drop into LLDB command interpreter
- if (useColors) {
- error_sp->Printf(ANSI_ESCAPE1(ANSI_FG_COLOR_RED));
- error_sp->Printf(ANSI_ESCAPE1(ANSI_CTRL_BOLD));
- }
- output_sp->Printf("Execution stopped at breakpoint. ");
- if (useColors) error_sp->Printf(ANSI_ESCAPE1(ANSI_CTRL_NORMAL));
- output_sp->Printf("Enter LLDB commands to investigate (type help for assistance.)\n");
- {
- lldb::IOHandlerSP io_handler_sp (ci.GetIOHandler());
- if (io_handler_sp)
- {
- io_handler_sp->SetIsDone(false);
- debugger.PushIOHandler(ci.GetIOHandler());
- }
- }
- break;
-
- case lldb::eExpressionTimedOut:
- error_sp->Printf("error: timeout\n");
- if (error.AsCString())
- error_sp->Printf("error: %s\n", error.AsCString());
- break;
- case lldb::eExpressionResultUnavailable:
- // Shoulnd't happen???
- error_sp->Printf("error: could not fetch result -- %s\n", error.AsCString());
- break;
- case lldb::eExpressionStoppedForDebug:
- // Shoulnd't happen???
- error_sp->Printf("error: stopped for debug -- %s\n", error.AsCString());
- break;
- }
- }
-
- if (add_to_code)
- {
- const uint32_t new_default_line = m_code.GetSize() + 1;
-
- m_code.SplitIntoLines(code);
-
- // Update our code on disk
- if (!m_repl_source_path.empty())
- {
- lldb_private::File file (m_repl_source_path.c_str(),
- File::eOpenOptionWrite | File::eOpenOptionTruncate | File::eOpenOptionCanCreate,
- lldb::eFilePermissionsFileDefault);
- std::string code (m_code.CopyList());
- code.append(1, '\n');
- size_t bytes_written = code.size();
- file.Write(code.c_str(), bytes_written);
- file.Close();
-
- // Now set the default file and line to the REPL source file
- m_target.GetSourceManager().SetDefaultFileAndLine(FileSpec(m_repl_source_path.c_str(), false), new_default_line);
- }
- static_cast<IOHandlerEditline &>(io_handler).SetBaseLineNumber(m_code.GetSize()+1);
- }
- if (extra_line)
- {
- fprintf(output_sp->GetFile().GetStream(), "\n");
- }
- }
- }
-
- // Don't complain about the REPL process going away if we are in the process of quitting.
- if (!did_quit && (!process_sp || !process_sp->IsAlive()))
- {
- error_sp->Printf("error: REPL process is no longer alive, exiting REPL\n");
- io_handler.SetIsDone(true);
- }
- }
-}
-
-int
-REPL::IOHandlerComplete (IOHandler &io_handler,
- const char *current_line,
- const char *cursor,
- const char *last_char,
- int skip_first_n_matches,
- int max_matches,
- StringList &matches)
-{
- matches.Clear();
-
- llvm::StringRef line (current_line, cursor - current_line);
-
- // Complete an LLDB command if the first character is a colon...
- if (!line.empty() && line[0] == ':')
- {
- Debugger &debugger = m_target.GetDebugger();
-
- // auto complete LLDB commands
- const char *lldb_current_line = line.substr(1).data();
- return debugger.GetCommandInterpreter().HandleCompletion (lldb_current_line,
- cursor,
- last_char,
- skip_first_n_matches,
- max_matches,
- matches);
- }
-
- // Strip spaces from the line and see if we had only spaces
- line = line.ltrim();
- if (line.empty())
- {
- // Only spaces on this line, so just indent
- matches.AppendString(m_indent_str);
- return 1;
- }
-
- std::string current_code;
- current_code.append(m_code.CopyList());
-
- IOHandlerEditline &editline = static_cast<IOHandlerEditline &>(io_handler);
- const StringList *current_lines = editline.GetCurrentLines();
- if (current_lines)
- {
- const uint32_t current_line_idx = editline.GetCurrentLineIndex();
-
- if (current_line_idx < current_lines->GetSize())
- {
- for (uint32_t i=0; i<current_line_idx; ++i)
- {
- const char *line_cstr = current_lines->GetStringAtIndex(i);
- if (line_cstr)
- {
- current_code.append("\n");
- current_code.append (line_cstr);
- }
- }
- }
- }
-
- if (cursor > current_line)
- {
- current_code.append("\n");
- current_code.append(current_line, cursor - current_line);
- }
-
- return CompleteCode(current_code, matches);
-}
-
-bool
-QuitCommandOverrideCallback(void *baton, const char **argv)
-{
- Target *target = (Target *)baton;
- lldb::ProcessSP process_sp (target->GetProcessSP());
- if (process_sp)
- {
- process_sp->Destroy(false);
- process_sp->GetTarget().GetDebugger().ClearIOHandlers();
- }
- return false;
-}
-
-Error
-REPL::RunLoop ()
-{
- Error error;
-
- error = DoInitialization();
- m_repl_source_path = GetSourcePath();
-
- if (!error.Success())
- return error;
-
- Debugger &debugger = m_target.GetDebugger();
-
- lldb::IOHandlerSP io_handler_sp (GetIOHandler());
-
- FileSpec save_default_file;
- uint32_t save_default_line = 0;
-
- if (!m_repl_source_path.empty())
- {
- // Save the current default file and line
- m_target.GetSourceManager().GetDefaultFileAndLine(save_default_file, save_default_line);
- }
-
- debugger.PushIOHandler(io_handler_sp);
-
- // Check if we are in dedicated REPL mode where LLDB was start with the "--repl" option
- // from the command line. Currently we know this by checking if the debugger already
- // has a IOHandler thread.
- if (!debugger.HasIOHandlerThread())
- {
- // The debugger doesn't have an existing IOHandler thread, so this must be
- // dedicated REPL mode...
- m_dedicated_repl_mode = true;
- debugger.StartIOHandlerThread();
- std::string command_name_str ("quit");
- CommandObject *cmd_obj = debugger.GetCommandInterpreter().GetCommandObjectForCommand(command_name_str);
- if (cmd_obj)
- {
- assert(command_name_str.empty());
- cmd_obj->SetOverrideCallback (QuitCommandOverrideCallback, &m_target);
- }
- }
-
- // Wait for the REPL command interpreter to get popped
- io_handler_sp->WaitForPop();
-
- if (m_dedicated_repl_mode)
- {
- // If we were in dedicated REPL mode we would have started the
- // IOHandler thread, and we should kill our process
- lldb::ProcessSP process_sp = m_target.GetProcessSP();
- if (process_sp && process_sp->IsAlive())
- process_sp->Destroy(false);
-
- // Wait for the IO handler thread to exit (TODO: don't do this if the IO handler thread already exists...)
- debugger.JoinIOHandlerThread();
- }
-
- // Restore the default file and line
- if (save_default_file && save_default_line != 0)
- m_target.GetSourceManager().SetDefaultFileAndLine(save_default_file, save_default_line);
- return error;
+ // Restore the default file and line
+ if (save_default_file && save_default_line != 0)
+ m_target.GetSourceManager().SetDefaultFileAndLine(save_default_file,
+ save_default_line);
+ return error;
}
diff --git a/lldb/source/Expression/UserExpression.cpp b/lldb/source/Expression/UserExpression.cpp
index 3e2e07e..f9cfaaa 100644
--- a/lldb/source/Expression/UserExpression.cpp
+++ b/lldb/source/Expression/UserExpression.cpp
@@ -9,12 +9,12 @@
#include <stdio.h>
#if HAVE_SYS_TYPES_H
-# include <sys/types.h>
+#include <sys/types.h>
#endif
#include <cstdlib>
-#include <string>
#include <map>
+#include <string>
#include "Plugins/ExpressionParser/Clang/ClangPersistentVariables.h"
#include "lldb/Core/ConstString.h"
@@ -46,359 +46,330 @@
using namespace lldb_private;
-UserExpression::UserExpression (ExecutionContextScope &exe_scope,
- const char *expr,
- const char *expr_prefix,
- lldb::LanguageType language,
- ResultType desired_type,
- const EvaluateExpressionOptions &options) :
- Expression(exe_scope),
- m_expr_text(expr),
- m_expr_prefix(expr_prefix ? expr_prefix : ""),
- m_language(language),
- m_desired_type(desired_type),
- m_options (options)
-{
+UserExpression::UserExpression(ExecutionContextScope &exe_scope,
+ const char *expr, const char *expr_prefix,
+ lldb::LanguageType language,
+ ResultType desired_type,
+ const EvaluateExpressionOptions &options)
+ : Expression(exe_scope), m_expr_text(expr),
+ m_expr_prefix(expr_prefix ? expr_prefix : ""), m_language(language),
+ m_desired_type(desired_type), m_options(options) {}
+
+UserExpression::~UserExpression() {}
+
+void UserExpression::InstallContext(ExecutionContext &exe_ctx) {
+ m_jit_process_wp = exe_ctx.GetProcessSP();
+
+ lldb::StackFrameSP frame_sp = exe_ctx.GetFrameSP();
+
+ if (frame_sp)
+ m_address = frame_sp->GetFrameCodeAddress();
}
-UserExpression::~UserExpression ()
-{
-}
+bool UserExpression::LockAndCheckContext(ExecutionContext &exe_ctx,
+ lldb::TargetSP &target_sp,
+ lldb::ProcessSP &process_sp,
+ lldb::StackFrameSP &frame_sp) {
+ lldb::ProcessSP expected_process_sp = m_jit_process_wp.lock();
+ process_sp = exe_ctx.GetProcessSP();
-void
-UserExpression::InstallContext (ExecutionContext &exe_ctx)
-{
- m_jit_process_wp = exe_ctx.GetProcessSP();
+ if (process_sp != expected_process_sp)
+ return false;
- lldb::StackFrameSP frame_sp = exe_ctx.GetFrameSP();
+ process_sp = exe_ctx.GetProcessSP();
+ target_sp = exe_ctx.GetTargetSP();
+ frame_sp = exe_ctx.GetFrameSP();
- if (frame_sp)
- m_address = frame_sp->GetFrameCodeAddress();
-}
-
-bool
-UserExpression::LockAndCheckContext (ExecutionContext &exe_ctx,
- lldb::TargetSP &target_sp,
- lldb::ProcessSP &process_sp,
- lldb::StackFrameSP &frame_sp)
-{
- lldb::ProcessSP expected_process_sp = m_jit_process_wp.lock();
- process_sp = exe_ctx.GetProcessSP();
-
- if (process_sp != expected_process_sp)
- return false;
-
- process_sp = exe_ctx.GetProcessSP();
- target_sp = exe_ctx.GetTargetSP();
- frame_sp = exe_ctx.GetFrameSP();
-
- if (m_address.IsValid())
- {
- if (!frame_sp)
- return false;
- else
- return (0 == Address::CompareLoadAddress(m_address, frame_sp->GetFrameCodeAddress(), target_sp.get()));
- }
-
- return true;
-}
-
-bool
-UserExpression::MatchesContext (ExecutionContext &exe_ctx)
-{
- lldb::TargetSP target_sp;
- lldb::ProcessSP process_sp;
- lldb::StackFrameSP frame_sp;
-
- return LockAndCheckContext(exe_ctx, target_sp, process_sp, frame_sp);
-}
-
-lldb::addr_t
-UserExpression::GetObjectPointer (lldb::StackFrameSP frame_sp,
- ConstString &object_name,
- Error &err)
-{
- err.Clear();
-
+ if (m_address.IsValid()) {
if (!frame_sp)
- {
- err.SetErrorStringWithFormat("Couldn't load '%s' because the context is incomplete", object_name.AsCString());
- return LLDB_INVALID_ADDRESS;
- }
+ return false;
+ else
+ return (0 == Address::CompareLoadAddress(m_address,
+ frame_sp->GetFrameCodeAddress(),
+ target_sp.get()));
+ }
- lldb::VariableSP var_sp;
- lldb::ValueObjectSP valobj_sp;
-
- valobj_sp = frame_sp->GetValueForVariableExpressionPath(object_name.AsCString(),
- lldb::eNoDynamicValues,
- StackFrame::eExpressionPathOptionCheckPtrVsMember |
- StackFrame::eExpressionPathOptionsNoFragileObjcIvar |
- StackFrame::eExpressionPathOptionsNoSyntheticChildren |
- StackFrame::eExpressionPathOptionsNoSyntheticArrayRange,
- var_sp,
- err);
-
- if (!err.Success() || !valobj_sp.get())
- return LLDB_INVALID_ADDRESS;
-
- lldb::addr_t ret = valobj_sp->GetValueAsUnsigned(LLDB_INVALID_ADDRESS);
-
- if (ret == LLDB_INVALID_ADDRESS)
- {
- err.SetErrorStringWithFormat("Couldn't load '%s' because its value couldn't be evaluated", object_name.AsCString());
- return LLDB_INVALID_ADDRESS;
- }
-
- return ret;
+ return true;
}
-lldb::ExpressionResults
-UserExpression::Evaluate (ExecutionContext &exe_ctx,
- const EvaluateExpressionOptions& options,
- const char *expr_cstr,
- const char *expr_prefix,
- lldb::ValueObjectSP &result_valobj_sp,
- Error &error,
- uint32_t line_offset,
- std::string *fixed_expression,
- lldb::ModuleSP *jit_module_sp_ptr)
-{
- Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_EXPRESSIONS | LIBLLDB_LOG_STEP));
+bool UserExpression::MatchesContext(ExecutionContext &exe_ctx) {
+ lldb::TargetSP target_sp;
+ lldb::ProcessSP process_sp;
+ lldb::StackFrameSP frame_sp;
- lldb_private::ExecutionPolicy execution_policy = options.GetExecutionPolicy();
- lldb::LanguageType language = options.GetLanguage();
- const ResultType desired_type = options.DoesCoerceToId() ? UserExpression::eResultTypeId : UserExpression::eResultTypeAny;
- lldb::ExpressionResults execution_results = lldb::eExpressionSetupError;
-
- Target *target = exe_ctx.GetTargetPtr();
- if (!target)
- {
- if (log)
- log->Printf("== [UserExpression::Evaluate] Passed a NULL target, can't run expressions.");
- return lldb::eExpressionSetupError;
- }
+ return LockAndCheckContext(exe_ctx, target_sp, process_sp, frame_sp);
+}
- Process *process = exe_ctx.GetProcessPtr();
+lldb::addr_t UserExpression::GetObjectPointer(lldb::StackFrameSP frame_sp,
+ ConstString &object_name,
+ Error &err) {
+ err.Clear();
- if (process == NULL || process->GetState() != lldb::eStateStopped)
- {
- if (execution_policy == eExecutionPolicyAlways)
- {
- if (log)
- log->Printf("== [UserExpression::Evaluate] Expression may not run, but is not constant ==");
+ if (!frame_sp) {
+ err.SetErrorStringWithFormat(
+ "Couldn't load '%s' because the context is incomplete",
+ object_name.AsCString());
+ return LLDB_INVALID_ADDRESS;
+ }
- error.SetErrorString ("expression needed to run but couldn't");
+ lldb::VariableSP var_sp;
+ lldb::ValueObjectSP valobj_sp;
- return execution_results;
- }
- }
+ valobj_sp = frame_sp->GetValueForVariableExpressionPath(
+ object_name.AsCString(), lldb::eNoDynamicValues,
+ StackFrame::eExpressionPathOptionCheckPtrVsMember |
+ StackFrame::eExpressionPathOptionsNoFragileObjcIvar |
+ StackFrame::eExpressionPathOptionsNoSyntheticChildren |
+ StackFrame::eExpressionPathOptionsNoSyntheticArrayRange,
+ var_sp, err);
- if (process == NULL || !process->CanJIT())
- execution_policy = eExecutionPolicyNever;
-
- // We need to set the expression execution thread here, turns out parse can call functions in the process of
- // looking up symbols, which will escape the context set by exe_ctx passed to Execute.
- lldb::ThreadSP thread_sp = exe_ctx.GetThreadSP();
- ThreadList::ExpressionExecutionThreadPusher execution_thread_pusher(thread_sp);
+ if (!err.Success() || !valobj_sp.get())
+ return LLDB_INVALID_ADDRESS;
- const char *full_prefix = NULL;
- const char *option_prefix = options.GetPrefix();
- std::string full_prefix_storage;
- if (expr_prefix && option_prefix)
- {
- full_prefix_storage.assign(expr_prefix);
- full_prefix_storage.append(option_prefix);
- if (!full_prefix_storage.empty())
- full_prefix = full_prefix_storage.c_str();
- }
- else if (expr_prefix)
- full_prefix = expr_prefix;
- else
- full_prefix = option_prefix;
+ lldb::addr_t ret = valobj_sp->GetValueAsUnsigned(LLDB_INVALID_ADDRESS);
- // If the language was not specified in the expression command,
- // set it to the language in the target's properties if
- // specified, else default to the langage for the frame.
- if (language == lldb::eLanguageTypeUnknown)
- {
- if (target->GetLanguage() != lldb::eLanguageTypeUnknown)
- language = target->GetLanguage();
- else if (StackFrame *frame = exe_ctx.GetFramePtr())
- language = frame->GetLanguage();
- }
+ if (ret == LLDB_INVALID_ADDRESS) {
+ err.SetErrorStringWithFormat(
+ "Couldn't load '%s' because its value couldn't be evaluated",
+ object_name.AsCString());
+ return LLDB_INVALID_ADDRESS;
+ }
- lldb::UserExpressionSP user_expression_sp(target->GetUserExpressionForLanguage (expr_cstr,
- full_prefix,
- language,
- desired_type,
- options,
- error));
- if (error.Fail())
- {
- if (log)
- log->Printf ("== [UserExpression::Evaluate] Getting expression: %s ==", error.AsCString());
- return lldb::eExpressionSetupError;
- }
+ return ret;
+}
+lldb::ExpressionResults UserExpression::Evaluate(
+ ExecutionContext &exe_ctx, const EvaluateExpressionOptions &options,
+ const char *expr_cstr, const char *expr_prefix,
+ lldb::ValueObjectSP &result_valobj_sp, Error &error, uint32_t line_offset,
+ std::string *fixed_expression, lldb::ModuleSP *jit_module_sp_ptr) {
+ Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_EXPRESSIONS |
+ LIBLLDB_LOG_STEP));
+
+ lldb_private::ExecutionPolicy execution_policy = options.GetExecutionPolicy();
+ lldb::LanguageType language = options.GetLanguage();
+ const ResultType desired_type = options.DoesCoerceToId()
+ ? UserExpression::eResultTypeId
+ : UserExpression::eResultTypeAny;
+ lldb::ExpressionResults execution_results = lldb::eExpressionSetupError;
+
+ Target *target = exe_ctx.GetTargetPtr();
+ if (!target) {
if (log)
- log->Printf("== [UserExpression::Evaluate] Parsing expression %s ==", expr_cstr);
+ log->Printf("== [UserExpression::Evaluate] Passed a NULL target, can't "
+ "run expressions.");
+ return lldb::eExpressionSetupError;
+ }
- const bool keep_expression_in_memory = true;
- const bool generate_debug_info = options.GetGenerateDebugInfo();
+ Process *process = exe_ctx.GetProcessPtr();
- if (options.InvokeCancelCallback (lldb::eExpressionEvaluationParse))
- {
- error.SetErrorString ("expression interrupted by callback before parse");
- result_valobj_sp = ValueObjectConstResult::Create(exe_ctx.GetBestExecutionContextScope(), error);
- return lldb::eExpressionInterrupted;
+ if (process == NULL || process->GetState() != lldb::eStateStopped) {
+ if (execution_policy == eExecutionPolicyAlways) {
+ if (log)
+ log->Printf("== [UserExpression::Evaluate] Expression may not run, but "
+ "is not constant ==");
+
+ error.SetErrorString("expression needed to run but couldn't");
+
+ return execution_results;
+ }
+ }
+
+ if (process == NULL || !process->CanJIT())
+ execution_policy = eExecutionPolicyNever;
+
+ // We need to set the expression execution thread here, turns out parse can
+ // call functions in the process of
+ // looking up symbols, which will escape the context set by exe_ctx passed to
+ // Execute.
+ lldb::ThreadSP thread_sp = exe_ctx.GetThreadSP();
+ ThreadList::ExpressionExecutionThreadPusher execution_thread_pusher(
+ thread_sp);
+
+ const char *full_prefix = NULL;
+ const char *option_prefix = options.GetPrefix();
+ std::string full_prefix_storage;
+ if (expr_prefix && option_prefix) {
+ full_prefix_storage.assign(expr_prefix);
+ full_prefix_storage.append(option_prefix);
+ if (!full_prefix_storage.empty())
+ full_prefix = full_prefix_storage.c_str();
+ } else if (expr_prefix)
+ full_prefix = expr_prefix;
+ else
+ full_prefix = option_prefix;
+
+ // If the language was not specified in the expression command,
+ // set it to the language in the target's properties if
+ // specified, else default to the langage for the frame.
+ if (language == lldb::eLanguageTypeUnknown) {
+ if (target->GetLanguage() != lldb::eLanguageTypeUnknown)
+ language = target->GetLanguage();
+ else if (StackFrame *frame = exe_ctx.GetFramePtr())
+ language = frame->GetLanguage();
+ }
+
+ lldb::UserExpressionSP user_expression_sp(
+ target->GetUserExpressionForLanguage(expr_cstr, full_prefix, language,
+ desired_type, options, error));
+ if (error.Fail()) {
+ if (log)
+ log->Printf("== [UserExpression::Evaluate] Getting expression: %s ==",
+ error.AsCString());
+ return lldb::eExpressionSetupError;
+ }
+
+ if (log)
+ log->Printf("== [UserExpression::Evaluate] Parsing expression %s ==",
+ expr_cstr);
+
+ const bool keep_expression_in_memory = true;
+ const bool generate_debug_info = options.GetGenerateDebugInfo();
+
+ if (options.InvokeCancelCallback(lldb::eExpressionEvaluationParse)) {
+ error.SetErrorString("expression interrupted by callback before parse");
+ result_valobj_sp = ValueObjectConstResult::Create(
+ exe_ctx.GetBestExecutionContextScope(), error);
+ return lldb::eExpressionInterrupted;
+ }
+
+ DiagnosticManager diagnostic_manager;
+
+ bool parse_success =
+ user_expression_sp->Parse(diagnostic_manager, exe_ctx, execution_policy,
+ keep_expression_in_memory, generate_debug_info);
+
+ // Calculate the fixed expression always, since we need it for errors.
+ std::string tmp_fixed_expression;
+ if (fixed_expression == nullptr)
+ fixed_expression = &tmp_fixed_expression;
+
+ const char *fixed_text = user_expression_sp->GetFixedText();
+ if (fixed_text != nullptr)
+ fixed_expression->append(fixed_text);
+
+ // If there is a fixed expression, try to parse it:
+ if (!parse_success) {
+ execution_results = lldb::eExpressionParseError;
+ if (fixed_expression && !fixed_expression->empty() &&
+ options.GetAutoApplyFixIts()) {
+ lldb::UserExpressionSP fixed_expression_sp(
+ target->GetUserExpressionForLanguage(fixed_expression->c_str(),
+ full_prefix, language,
+ desired_type, options, error));
+ DiagnosticManager fixed_diagnostic_manager;
+ parse_success = fixed_expression_sp->Parse(
+ fixed_diagnostic_manager, exe_ctx, execution_policy,
+ keep_expression_in_memory, generate_debug_info);
+ if (parse_success) {
+ diagnostic_manager.Clear();
+ user_expression_sp = fixed_expression_sp;
+ } else {
+ // If the fixed expression failed to parse, don't tell the user about,
+ // that won't help.
+ fixed_expression->clear();
+ }
}
- DiagnosticManager diagnostic_manager;
-
- bool parse_success = user_expression_sp->Parse(diagnostic_manager,
- exe_ctx,
- execution_policy,
- keep_expression_in_memory,
- generate_debug_info);
-
- // Calculate the fixed expression always, since we need it for errors.
- std::string tmp_fixed_expression;
- if (fixed_expression == nullptr)
- fixed_expression = &tmp_fixed_expression;
-
- const char *fixed_text = user_expression_sp->GetFixedText();
- if (fixed_text != nullptr)
- fixed_expression->append(fixed_text);
-
- // If there is a fixed expression, try to parse it:
- if (!parse_success)
- {
- execution_results = lldb::eExpressionParseError;
- if (fixed_expression && !fixed_expression->empty() && options.GetAutoApplyFixIts())
- {
- lldb::UserExpressionSP fixed_expression_sp(target->GetUserExpressionForLanguage (fixed_expression->c_str(),
- full_prefix,
- language,
- desired_type,
- options,
- error));
- DiagnosticManager fixed_diagnostic_manager;
- parse_success = fixed_expression_sp->Parse(fixed_diagnostic_manager,
- exe_ctx,
- execution_policy,
- keep_expression_in_memory,
- generate_debug_info);
- if (parse_success)
- {
- diagnostic_manager.Clear();
- user_expression_sp = fixed_expression_sp;
- }
- else
- {
- // If the fixed expression failed to parse, don't tell the user about, that won't help.
- fixed_expression->clear();
- }
- }
-
- if (!parse_success)
- {
- if (!fixed_expression->empty() && target->GetEnableNotifyAboutFixIts())
- {
- error.SetExpressionErrorWithFormat(execution_results, "expression failed to parse, fixed expression suggested:\n %s",
- fixed_expression->c_str());
- }
- else
- {
- if (!diagnostic_manager.Diagnostics().size())
- error.SetExpressionError(execution_results, "expression failed to parse, unknown error");
- else
- error.SetExpressionError(execution_results, diagnostic_manager.GetString().c_str());
- }
- }
- }
-
- if (parse_success)
- {
- // If a pointer to a lldb::ModuleSP was passed in, return the JIT'ed module if one was created
- if (jit_module_sp_ptr)
- *jit_module_sp_ptr = user_expression_sp->GetJITModule();
-
- lldb::ExpressionVariableSP expr_result;
-
- if (execution_policy == eExecutionPolicyNever &&
- !user_expression_sp->CanInterpret())
- {
- if (log)
- log->Printf("== [UserExpression::Evaluate] Expression may not run, but is not constant ==");
-
- if (!diagnostic_manager.Diagnostics().size())
- error.SetExpressionError(lldb::eExpressionSetupError, "expression needed to run but couldn't");
- }
- else if (execution_policy == eExecutionPolicyTopLevel)
- {
- error.SetError(UserExpression::kNoResult, lldb::eErrorTypeGeneric);
- return lldb::eExpressionCompleted;
- }
+ if (!parse_success) {
+ if (!fixed_expression->empty() && target->GetEnableNotifyAboutFixIts()) {
+ error.SetExpressionErrorWithFormat(
+ execution_results,
+ "expression failed to parse, fixed expression suggested:\n %s",
+ fixed_expression->c_str());
+ } else {
+ if (!diagnostic_manager.Diagnostics().size())
+ error.SetExpressionError(execution_results,
+ "expression failed to parse, unknown error");
else
- {
- if (options.InvokeCancelCallback (lldb::eExpressionEvaluationExecution))
- {
- error.SetExpressionError (lldb::eExpressionInterrupted, "expression interrupted by callback before execution");
- result_valobj_sp = ValueObjectConstResult::Create (exe_ctx.GetBestExecutionContextScope(), error);
- return lldb::eExpressionInterrupted;
- }
-
- diagnostic_manager.Clear();
-
- if (log)
- log->Printf("== [UserExpression::Evaluate] Executing expression ==");
-
- execution_results =
- user_expression_sp->Execute(diagnostic_manager, exe_ctx, options, user_expression_sp, expr_result);
-
- if (execution_results != lldb::eExpressionCompleted)
- {
- if (log)
- log->Printf("== [UserExpression::Evaluate] Execution completed abnormally ==");
-
- if (!diagnostic_manager.Diagnostics().size())
- error.SetExpressionError(execution_results, "expression failed to execute, unknown error");
- else
- error.SetExpressionError(execution_results, diagnostic_manager.GetString().c_str());
- }
- else
- {
- if (expr_result)
- {
- result_valobj_sp = expr_result->GetValueObject();
-
- if (log)
- log->Printf("== [UserExpression::Evaluate] Execution completed normally with result %s ==",
- result_valobj_sp->GetValueAsCString());
- }
- else
- {
- if (log)
- log->Printf("== [UserExpression::Evaluate] Execution completed normally with no result ==");
-
- error.SetError(UserExpression::kNoResult, lldb::eErrorTypeGeneric);
- }
- }
- }
+ error.SetExpressionError(execution_results,
+ diagnostic_manager.GetString().c_str());
+ }
}
+ }
- if (options.InvokeCancelCallback(lldb::eExpressionEvaluationComplete))
- {
- error.SetExpressionError (lldb::eExpressionInterrupted, "expression interrupted by callback after complete");
+ if (parse_success) {
+ // If a pointer to a lldb::ModuleSP was passed in, return the JIT'ed module
+ // if one was created
+ if (jit_module_sp_ptr)
+ *jit_module_sp_ptr = user_expression_sp->GetJITModule();
+
+ lldb::ExpressionVariableSP expr_result;
+
+ if (execution_policy == eExecutionPolicyNever &&
+ !user_expression_sp->CanInterpret()) {
+ if (log)
+ log->Printf("== [UserExpression::Evaluate] Expression may not run, but "
+ "is not constant ==");
+
+ if (!diagnostic_manager.Diagnostics().size())
+ error.SetExpressionError(lldb::eExpressionSetupError,
+ "expression needed to run but couldn't");
+ } else if (execution_policy == eExecutionPolicyTopLevel) {
+ error.SetError(UserExpression::kNoResult, lldb::eErrorTypeGeneric);
+ return lldb::eExpressionCompleted;
+ } else {
+ if (options.InvokeCancelCallback(lldb::eExpressionEvaluationExecution)) {
+ error.SetExpressionError(
+ lldb::eExpressionInterrupted,
+ "expression interrupted by callback before execution");
+ result_valobj_sp = ValueObjectConstResult::Create(
+ exe_ctx.GetBestExecutionContextScope(), error);
return lldb::eExpressionInterrupted;
- }
+ }
- if (result_valobj_sp.get() == NULL)
- {
- result_valobj_sp = ValueObjectConstResult::Create (exe_ctx.GetBestExecutionContextScope(), error);
- }
+ diagnostic_manager.Clear();
- return execution_results;
+ if (log)
+ log->Printf("== [UserExpression::Evaluate] Executing expression ==");
+
+ execution_results =
+ user_expression_sp->Execute(diagnostic_manager, exe_ctx, options,
+ user_expression_sp, expr_result);
+
+ if (execution_results != lldb::eExpressionCompleted) {
+ if (log)
+ log->Printf("== [UserExpression::Evaluate] Execution completed "
+ "abnormally ==");
+
+ if (!diagnostic_manager.Diagnostics().size())
+ error.SetExpressionError(
+ execution_results, "expression failed to execute, unknown error");
+ else
+ error.SetExpressionError(execution_results,
+ diagnostic_manager.GetString().c_str());
+ } else {
+ if (expr_result) {
+ result_valobj_sp = expr_result->GetValueObject();
+
+ if (log)
+ log->Printf("== [UserExpression::Evaluate] Execution completed "
+ "normally with result %s ==",
+ result_valobj_sp->GetValueAsCString());
+ } else {
+ if (log)
+ log->Printf("== [UserExpression::Evaluate] Execution completed "
+ "normally with no result ==");
+
+ error.SetError(UserExpression::kNoResult, lldb::eErrorTypeGeneric);
+ }
+ }
+ }
+ }
+
+ if (options.InvokeCancelCallback(lldb::eExpressionEvaluationComplete)) {
+ error.SetExpressionError(
+ lldb::eExpressionInterrupted,
+ "expression interrupted by callback after complete");
+ return lldb::eExpressionInterrupted;
+ }
+
+ if (result_valobj_sp.get() == NULL) {
+ result_valobj_sp = ValueObjectConstResult::Create(
+ exe_ctx.GetBestExecutionContextScope(), error);
+ }
+
+ return execution_results;
}
lldb::ExpressionResults
@@ -406,15 +377,13 @@
ExecutionContext &exe_ctx,
const EvaluateExpressionOptions &options,
lldb::UserExpressionSP &shared_ptr_to_me,
- lldb::ExpressionVariableSP &result_var)
-{
- lldb::ExpressionResults expr_result = DoExecute(diagnostic_manager, exe_ctx, options, shared_ptr_to_me, result_var);
- Target *target = exe_ctx.GetTargetPtr();
- if (options.GetResultIsInternal() && result_var && target)
- {
- target->GetPersistentExpressionStateForLanguage(m_language)->RemovePersistentVariable (result_var);
- }
- return expr_result;
+ lldb::ExpressionVariableSP &result_var) {
+ lldb::ExpressionResults expr_result = DoExecute(
+ diagnostic_manager, exe_ctx, options, shared_ptr_to_me, result_var);
+ Target *target = exe_ctx.GetTargetPtr();
+ if (options.GetResultIsInternal() && result_var && target) {
+ target->GetPersistentExpressionStateForLanguage(m_language)
+ ->RemovePersistentVariable(result_var);
+ }
+ return expr_result;
}
-
-
diff --git a/lldb/source/Expression/UtilityFunction.cpp b/lldb/source/Expression/UtilityFunction.cpp
index 2ff77f0..f279509 100644
--- a/lldb/source/Expression/UtilityFunction.cpp
+++ b/lldb/source/Expression/UtilityFunction.cpp
@@ -1,4 +1,5 @@
-//===-- ClangUserExpression.cpp -------------------------------------*- C++ -*-===//
+//===-- ClangUserExpression.cpp -------------------------------------*- C++
+//-*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -10,7 +11,7 @@
// C Includes
#include <stdio.h>
#if HAVE_SYS_TYPES_H
-# include <sys/types.h>
+#include <sys/types.h>
#endif
// C++ Includes
@@ -42,85 +43,74 @@
/// @param[in] name
/// The name of the function, as used in the text.
//------------------------------------------------------------------
-UtilityFunction::UtilityFunction (ExecutionContextScope &exe_scope,
- const char *text,
- const char *name) :
- Expression (exe_scope),
- m_execution_unit_sp (),
- m_jit_module_wp (),
- m_function_text (ExpressionSourceCode::g_expression_prefix),
- m_function_name (name)
-{
- if (text && text[0])
- m_function_text.append (text);
+UtilityFunction::UtilityFunction(ExecutionContextScope &exe_scope,
+ const char *text, const char *name)
+ : Expression(exe_scope), m_execution_unit_sp(), m_jit_module_wp(),
+ m_function_text(ExpressionSourceCode::g_expression_prefix),
+ m_function_name(name) {
+ if (text && text[0])
+ m_function_text.append(text);
}
-UtilityFunction::~UtilityFunction ()
-{
- lldb::ProcessSP process_sp (m_jit_process_wp.lock());
- if (process_sp)
- {
- lldb::ModuleSP jit_module_sp (m_jit_module_wp.lock());
- if (jit_module_sp)
- process_sp->GetTarget().GetImages().Remove(jit_module_sp);
- }
-
+UtilityFunction::~UtilityFunction() {
+ lldb::ProcessSP process_sp(m_jit_process_wp.lock());
+ if (process_sp) {
+ lldb::ModuleSP jit_module_sp(m_jit_module_wp.lock());
+ if (jit_module_sp)
+ process_sp->GetTarget().GetImages().Remove(jit_module_sp);
+ }
}
-// FIXME: We should check that every time this is called it is called with the same return type & arguments...
+// FIXME: We should check that every time this is called it is called with the
+// same return type & arguments...
-FunctionCaller *
-UtilityFunction::MakeFunctionCaller (const CompilerType &return_type, const ValueList &arg_value_list, lldb::ThreadSP thread_to_use_sp, Error &error)
-{
- if (m_caller_up)
- return m_caller_up.get();
-
- ProcessSP process_sp = m_jit_process_wp.lock();
- if (!process_sp)
- {
- error.SetErrorString("Can't make a function caller without a process.");
- return nullptr;
- }
-
- Address impl_code_address;
- impl_code_address.SetOffset(StartAddress());
- std::string name(m_function_name);
- name.append("-caller");
-
- m_caller_up.reset (process_sp->GetTarget().GetFunctionCallerForLanguage (Language(),
- return_type,
- impl_code_address,
- arg_value_list,
- name.c_str(),
- error));
- if (error.Fail())
- {
-
- return nullptr;
- }
- if (m_caller_up)
- {
- DiagnosticManager diagnostics;
-
- unsigned num_errors = m_caller_up->CompileFunction(thread_to_use_sp, diagnostics);
- if (num_errors)
- {
- error.SetErrorStringWithFormat("Error compiling %s caller function: \"%s\".", m_function_name.c_str(),
- diagnostics.GetString().c_str());
- m_caller_up.reset();
- return nullptr;
- }
-
- diagnostics.Clear();
- ExecutionContext exe_ctx(process_sp);
-
- if (!m_caller_up->WriteFunctionWrapper(exe_ctx, diagnostics))
- {
- error.SetErrorStringWithFormat("Error inserting caller function for %s: \"%s\".", m_function_name.c_str(),
- diagnostics.GetString().c_str());
- m_caller_up.reset();
- return nullptr;
- }
- }
+FunctionCaller *UtilityFunction::MakeFunctionCaller(
+ const CompilerType &return_type, const ValueList &arg_value_list,
+ lldb::ThreadSP thread_to_use_sp, Error &error) {
+ if (m_caller_up)
return m_caller_up.get();
+
+ ProcessSP process_sp = m_jit_process_wp.lock();
+ if (!process_sp) {
+ error.SetErrorString("Can't make a function caller without a process.");
+ return nullptr;
+ }
+
+ Address impl_code_address;
+ impl_code_address.SetOffset(StartAddress());
+ std::string name(m_function_name);
+ name.append("-caller");
+
+ m_caller_up.reset(process_sp->GetTarget().GetFunctionCallerForLanguage(
+ Language(), return_type, impl_code_address, arg_value_list, name.c_str(),
+ error));
+ if (error.Fail()) {
+
+ return nullptr;
+ }
+ if (m_caller_up) {
+ DiagnosticManager diagnostics;
+
+ unsigned num_errors =
+ m_caller_up->CompileFunction(thread_to_use_sp, diagnostics);
+ if (num_errors) {
+ error.SetErrorStringWithFormat(
+ "Error compiling %s caller function: \"%s\".",
+ m_function_name.c_str(), diagnostics.GetString().c_str());
+ m_caller_up.reset();
+ return nullptr;
+ }
+
+ diagnostics.Clear();
+ ExecutionContext exe_ctx(process_sp);
+
+ if (!m_caller_up->WriteFunctionWrapper(exe_ctx, diagnostics)) {
+ error.SetErrorStringWithFormat(
+ "Error inserting caller function for %s: \"%s\".",
+ m_function_name.c_str(), diagnostics.GetString().c_str());
+ m_caller_up.reset();
+ return nullptr;
+ }
+ }
+ return m_caller_up.get();
}