Author: Med Ismail Bennani Date: 2020-03-20T16:31:11+01:00 New Revision: 4e5d04da4990dbc01dd6dfa1c564a552c6b473d8
URL: https://github.com/llvm/llvm-project/commit/4e5d04da4990dbc01dd6dfa1c564a552c6b473d8 DIFF: https://github.com/llvm/llvm-project/commit/4e5d04da4990dbc01dd6dfa1c564a552c6b473d8.diff LOG: [lldb/Dwarf] Improve DW_OP_bit_piece support (WIP) Signed-off-by: Med Ismail Bennani <medismail.benn...@gmail.com> Added: Modified: lldb/include/lldb/Core/Value.h lldb/source/Core/Value.cpp lldb/source/Expression/DWARFExpression.cpp lldb/unittests/Expression/DWARFExpressionTest.cpp Removed: ################################################################################ diff --git a/lldb/include/lldb/Core/Value.h b/lldb/include/lldb/Core/Value.h index 641a64a3bbbe..8ecff57179df 100644 --- a/lldb/include/lldb/Core/Value.h +++ b/lldb/include/lldb/Core/Value.h @@ -128,6 +128,8 @@ class Value { void SetBytes(const void *bytes, int len); void AppendBytes(const void *bytes, int len); + + void AppendBits(const Value &rhs, int len); Value &operator=(const Value &rhs); diff --git a/lldb/source/Core/Value.cpp b/lldb/source/Core/Value.cpp index 63467644cdef..f3de421dc36a 100644 --- a/lldb/source/Core/Value.cpp +++ b/lldb/source/Core/Value.cpp @@ -104,6 +104,18 @@ void Value::AppendBytes(const void *bytes, int len) { m_value = (uintptr_t)m_data_buffer.GetBytes(); } +void Value::AppendBits(const Value& rhs, int len) { + m_value_type = eValueTypeHostAddress; + + llvm::APInt fail_value(1, 0, false); + llvm::APInt ap_int = GetScalar().UInt128(fail_value); + llvm::APInt rhs_int = rhs.GetScalar().UInt128(fail_value); + rhs_int = rhs_int << len; + ap_int |= rhs_int; + memcpy(m_data_buffer.GetBytes(), ap_int.getRawData(), ceil(ap_int.getBitWidth() / 8.0)); + m_value = (uintptr_t)m_data_buffer.GetBytes(); +} + void Value::Dump(Stream *strm) { m_value.GetValue(strm, true); strm->Printf(", value_type = %s, context = %p, context_type = %s", diff --git a/lldb/source/Expression/DWARFExpression.cpp b/lldb/source/Expression/DWARFExpression.cpp index 09df9b789bab..a4cda94a3ee8 100644 --- a/lldb/source/Expression/DWARFExpression.cpp +++ b/lldb/source/Expression/DWARFExpression.cpp @@ -933,6 +933,8 @@ bool DWARFExpression::Evaluate( uint32_t reg_num; /// Insertion point for evaluating multi-piece expression. +// uint64_t op_piece_offset = 0; +// Value pieces; // Used for DW_OP_piece and DW_OP_bit_piece llvm::BitVector bit_pieces; llvm::BitVector bit_mask; @@ -2164,31 +2166,85 @@ bool DWARFExpression::Evaluate( curr_scalar = curr_scalar << curr_width; bit_pieces.resize(curr_width + piece_byte_size * 8); bit_pieces.setBitsInMask(&curr_scalar); + // If this is the second or later piece there should be a value on + // the stack. +// if (op_piece_offset) { +// 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; +// } +// } +// +// 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; +// } } +// 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; + // 0x9d ULEB128 bit size, ULEB128 bit offset (DWARF3); + case DW_OP_bit_piece: { + Value curr_bit_piece; + + const uint64_t piece_bit_size = opcodes.GetULEB128(&offset); + const uint64_t piece_bit_offset = opcodes.GetULEB128(&offset); + + const uint64_t piece_byte_size = ceil(piece_bit_size / 8.0); + + + if (stack.empty()) { + // For unknown location, set bits in mask at the right offset. + bit_mask.resize(bit_mask.size() + piece_bit_size); + bit_mask.set(bit_mask.size() + piece_bit_offset, piece_bit_offset + piece_bit_size); + + + + // 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_bit_piece.ResizeData(piece_byte_size); +// // Note that "0" is not a correct value for the unknown bits. +// // It would be better to also return a mask of valid bits together +// // with the expression result, so the debugger can print missing +// // members as "<optimized out>" or something. +// ::memset(curr_bit_piece.GetBuffer().GetBytes(), 0, piece_byte_size); +// pieces.AppendBits(curr_bit_piece, piece_bit_size); } else { - const uint64_t piece_bit_size = opcodes.GetULEB128(&offset); - const uint64_t piece_bit_offset = opcodes.GetULEB128(&offset); - switch (stack.back().GetValueType()) { + // Extract the current piece into "curr_bit_piece" + Value curr_bit_piece_source_value(stack.back()); + stack.pop_back(); + + switch (curr_bit_piece_source_value.GetValueType()) { case Value::eValueTypeScalar: { - if (!stack.back().GetScalar().ExtractBitfield(piece_bit_size, - piece_bit_offset)) { + Scalar &scalar = curr_bit_piece_source_value.GetScalar(); + if (!scalar.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)); + (uint64_t)(scalar.GetByteSize() * 8)); return false; } + + // Create curr_bit_piece with piece_bit_size. By default Scalar + // grows to the nearest host integer type. + llvm::APInt fail_value(1, 0, false); + llvm::APInt ap_int = scalar.UInt128(fail_value); + assert(ap_int.getBitWidth() >= piece_bit_size); + llvm::ArrayRef<uint64_t> buf{ap_int.getRawData(), + ap_int.getNumWords()}; + curr_bit_piece.GetScalar() = Scalar(llvm::APInt(piece_bit_size, buf)); } break; case Value::eValueTypeFileAddress: @@ -2211,8 +2267,31 @@ bool DWARFExpression::Evaluate( } return false; } + + // If this is the second or later piece there should be a value on + // the stack. +// if (op_piece_offset) { +// 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; +// } +// } +// +// // 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_bit_piece) == 0) { +// if (error_ptr) +// error_ptr->SetErrorString("failed to append piece data"); +// return false; +// } } - break; +// op_piece_offset += piece_byte_size; + } break; // OPCODE: DW_OP_push_object_address // OPERANDS: none diff --git a/lldb/unittests/Expression/DWARFExpressionTest.cpp b/lldb/unittests/Expression/DWARFExpressionTest.cpp index 64755a9066de..7db52406d0ed 100644 --- a/lldb/unittests/Expression/DWARFExpressionTest.cpp +++ b/lldb/unittests/Expression/DWARFExpressionTest.cpp @@ -243,4 +243,17 @@ TEST(DWARFExpression, DW_OP_piece) { // Note that the "00" should really be "undef", but we can't // represent that yet. llvm::HasValue(GetScalar(16, 0xff00, true))); + EXPECT_THAT_EXPECTED( + Evaluate({DW_OP_const1u, 0b10, DW_OP_stack_value, DW_OP_bit_piece, 1, 1}), + llvm::HasValue(GetScalar(8, 0b1, true))); + EXPECT_THAT_EXPECTED( + Evaluate({DW_OP_const1u, 0b0110, DW_OP_stack_value, DW_OP_bit_piece, 2, 1, + DW_OP_bit_piece, 2, 0, + DW_OP_const1u, 0b1, DW_OP_stack_value, DW_OP_bit_piece, 1, 0}), + llvm::HasValue(GetScalar(24, 0b10011, true))); + EXPECT_THAT_EXPECTED( + Evaluate({DW_OP_const1u, 0b0110, DW_OP_stack_value, DW_OP_bit_piece, 2, 1, + DW_OP_bit_piece, 6, 0, + DW_OP_const1u, 0xff, DW_OP_piece, 1}), + llvm::HasValue(GetScalar(32, 0xff03, true))); } _______________________________________________ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits