[llvm-branch-commits] [lldb] 4e5d04d - [lldb/Dwarf] Improve DW_OP_bit_piece support (WIP)
Med Ismail Bennani via llvm-branch-commits
llvm-branch-commits at lists.llvm.org
Fri Mar 20 13:09:07 PDT 2020
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.bennani at 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)));
}
More information about the llvm-branch-commits
mailing list