Index: include/lldb/Expression/DWARFExpression.h =================================================================== --- include/lldb/Expression/DWARFExpression.h +++ include/lldb/Expression/DWARFExpression.h @@ -285,6 +285,10 @@ /// A value to put on top of the interpreter stack before evaluating /// the expression, if the expression is parametrized. Can be NULL. /// + /// \param[in] stack + /// interpreter stack for evaluation of dwarf expression. It is shared + /// between calls in case of adding/removing entries from stack. + /// /// \param[in] result /// A value into which the result of evaluating the expression is /// to be placed. @@ -301,7 +305,9 @@ const lldb::offset_t length, const lldb::RegisterKind reg_set, const Value *initial_value_ptr, - const Value *object_address_ptr, Value &result, + const Value *object_address_ptr, + std::vector &stack, + Value &result, Status *error_ptr); bool GetExpressionData(DataExtractor &data) const { Index: source/Expression/DWARFExpression.cpp =================================================================== --- source/Expression/DWARFExpression.cpp +++ source/Expression/DWARFExpression.cpp @@ -1248,6 +1248,7 @@ const Value *object_address_ptr, Value &result, Status *error_ptr) const { ModuleSP module_sp = m_module_wp.lock(); + std::vector stack; if (IsLocationList()) { lldb::offset_t offset = 0; @@ -1293,7 +1294,7 @@ if (length > 0 && lo_pc <= pc && pc < hi_pc) { return DWARFExpression::Evaluate( exe_ctx, reg_ctx, module_sp, m_data, m_dwarf_cu, offset, length, - m_reg_kind, initial_value_ptr, object_address_ptr, result, + m_reg_kind, initial_value_ptr, object_address_ptr, stack, result, error_ptr); } offset += length; @@ -1307,7 +1308,8 @@ // Not a location list, just a single expression. return DWARFExpression::Evaluate( exe_ctx, 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); + m_reg_kind, initial_value_ptr, object_address_ptr, stack, result, + error_ptr); } bool DWARFExpression::Evaluate( @@ -1316,7 +1318,7 @@ DWARFUnit *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, Status *error_ptr) { + std::vector &stack, Value &result, Status *error_ptr) { if (opcodes_length == 0) { if (error_ptr) @@ -1324,7 +1326,6 @@ "no location, value may have been optimized out"); return false; } - std::vector stack; Process *process = NULL; StackFrame *frame = NULL; @@ -2690,10 +2691,38 @@ // 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; + case DW_OP_call2: { + dw_offset_t die_ref_offset = opcodes.GetU16(&offset); + const DWARFDIE ref_die = dwarf_cu->GetDIE(die_ref_offset); + if (!ref_die.IsValid()) { + if (error_ptr) + error_ptr->SetErrorString("opcode DW_OP_call2 reference not found"); + return false; + } + + DWARFAttributes attributes; + const size_t num_attrib = ref_die.GetAttributes(attributes); + if (num_attrib == 0) + break; + + const uint32_t attr_index = attributes.FindAttributeIndex(DW_AT_location); + if (attr_index == UINT32_MAX) + break; + + DWARFFormValue form_value; + attributes.ExtractFormValueAtIndex(attr_index, form_value); + + const DWARFDataExtractor &ref_debug_info_data = ref_die.GetData(); + uint32_t location_offset = + form_value.BlockData() - ref_debug_info_data.GetDataStart(); + uint32_t location_length = form_value.Unsigned(); + Value memberOffset(0); + Evaluate(nullptr, nullptr, module_sp, ref_debug_info_data, + dwarf_cu, location_offset, location_length, + eRegisterKindDWARF, nullptr, nullptr, stack, memberOffset, + nullptr); + } break; + // OPCODE: DW_OP_call4 // OPERANDS: 1 // uint32_t compile unit relative offset of a DIE @@ -2713,10 +2742,37 @@ // 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; + case DW_OP_call4: { + dw_offset_t die_ref_offset = opcodes.GetU32(&offset); + const DWARFDIE ref_die = dwarf_cu->GetDIE(die_ref_offset); + if (!ref_die.IsValid()) { + if (error_ptr) + error_ptr->SetErrorString("opcode DW_OP_call4 reference not found"); + return false; + } + + DWARFAttributes attributes; + const size_t num_attrib = ref_die.GetAttributes(attributes); + if (num_attrib == 0) + break; + + const uint32_t attr_index = attributes.FindAttributeIndex(DW_AT_location); + if (attr_index == UINT32_MAX) + break; + + DWARFFormValue form_value; + attributes.ExtractFormValueAtIndex(attr_index, form_value); + + const DWARFDataExtractor &ref_debug_info_data = ref_die.GetData(); + uint32_t location_offset = + form_value.BlockData() - ref_debug_info_data.GetDataStart(); + uint32_t location_length = form_value.Unsigned(); + Value memberOffset(0); + Evaluate(nullptr, nullptr, module_sp, ref_debug_info_data, + dwarf_cu, location_offset, location_length, + eRegisterKindDWARF, nullptr, nullptr, stack, memberOffset, + nullptr); + } break; // OPCODE: DW_OP_stack_value // OPERANDS: None Index: source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp =================================================================== --- source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp +++ source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp @@ -2780,12 +2780,13 @@ uint32_t block_length = form_value.Unsigned(); uint32_t block_offset = form_value.BlockData() - debug_info_data.GetDataStart(); + std::vector stack; if (DWARFExpression::Evaluate( nullptr, // ExecutionContext * nullptr, // RegisterContext * module_sp, debug_info_data, die.GetCU(), block_offset, block_length, eRegisterKindDWARF, &initialValue, - nullptr, memberOffset, nullptr)) { + nullptr, stack, memberOffset, nullptr)) { member_byte_offset = memberOffset.ResolveValue(NULL).UInt(); } } else { @@ -3229,6 +3230,7 @@ Value initialValue(0); Value memberOffset(0); const DWARFDataExtractor &debug_info_data = die.GetData(); + std::vector stack; uint32_t block_length = form_value.Unsigned(); uint32_t block_offset = form_value.BlockData() - debug_info_data.GetDataStart(); @@ -3236,7 +3238,8 @@ debug_info_data, die.GetCU(), block_offset, block_length, eRegisterKindDWARF, &initialValue, - nullptr, memberOffset, nullptr)) { + nullptr, stack, memberOffset, + nullptr)) { member_byte_offset = memberOffset.ResolveValue(NULL).UInt(); } } else { Index: source/Target/RegisterContext.cpp =================================================================== --- source/Target/RegisterContext.cpp +++ source/Target/RegisterContext.cpp @@ -87,9 +87,10 @@ Value result; Status error; const lldb::offset_t offset = 0; + std::vector stack; if (dwarf_expr.Evaluate(&exe_ctx, this, opcode_ctx, dwarf_data, nullptr, offset, dwarf_opcode_len, eRegisterKindDWARF, nullptr, - nullptr, result, &error)) { + nullptr, stack, result, &error)) { expr_result = result.GetScalar().SInt(-1); switch (expr_result) { case 0: Index: unittests/Expression/DWARFExpressionTest.cpp =================================================================== --- unittests/Expression/DWARFExpressionTest.cpp +++ unittests/Expression/DWARFExpressionTest.cpp @@ -22,11 +22,12 @@ Value result; Status status; + std::vector stack; if (!DWARFExpression::Evaluate( /*exe_ctx*/ nullptr, /*reg_ctx*/ nullptr, /*opcode_ctx*/ nullptr, extractor, /*dwarf_cu*/ nullptr, /*offset*/ 0, expr.size(), lldb::eRegisterKindLLDB, /*initial_value_ptr*/ nullptr, - /*object_address_ptr*/ nullptr, result, &status)) + /*object_address_ptr*/ nullptr, stack, result, &status)) return status.ToError(); return result.GetScalar();