[Lldb-commits] [lldb] r214415 - Rewrote the initial DW_OP_piece support to be able to support opcodes like:
Greg Clayton
gclayton at apple.com
Thu Jul 31 11:19:29 PDT 2014
Author: gclayton
Date: Thu Jul 31 13:19:28 2014
New Revision: 214415
URL: http://llvm.org/viewvc/llvm-project?rev=214415&view=rev
Log:
Rewrote the initial DW_OP_piece support to be able to support opcodes like:
DW_OP_fbreg(N) DW_OP_piece(4) DW_OP_fbreg(M) DW_OP_piece(8)
DW_OP_fbreg(N) DW_OP_piece(4) DW_OP_piece(8)
The first grabs 4 bytes from FP+N followed by 8 bytes from FP+M, the second grabs 4 bytes from FP+N followed by zero filling 8 bytes which are unavailable. Of course regiters are stuff supported:
DW_OP_reg3 DW_OP_piece(4) DW_OP_reg8 DW_OP_piece(8)
The fix does the following:
1 - don't push the full piece value onto the stack, keep it on the side
2 - fill zeros for DW_OP_piece(N) opcodes that have nothing on the stack (instead of previously consuming the full piece that was pushed onto the stack)
3 - simplify the logic
<rdar://problem/16930524>
Modified:
lldb/trunk/include/lldb/Core/Value.h
lldb/trunk/source/Core/Value.cpp
lldb/trunk/source/Expression/DWARFExpression.cpp
Modified: lldb/trunk/include/lldb/Core/Value.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Core/Value.h?rev=214415&r1=214414&r2=214415&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Core/Value.h (original)
+++ lldb/trunk/include/lldb/Core/Value.h Thu Jul 31 13:19:28 2014
@@ -238,8 +238,11 @@ public:
return false;
}
- void
+ size_t
ResizeData(size_t len);
+
+ size_t
+ AppendDataToHostBuffer (const Value &rhs);
DataBufferHeap &
GetBuffer ()
Modified: lldb/trunk/source/Core/Value.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Core/Value.cpp?rev=214415&r1=214414&r2=214415&view=diff
==============================================================================
--- lldb/trunk/source/Core/Value.cpp (original)
+++ lldb/trunk/source/Core/Value.cpp Thu Jul 31 13:19:28 2014
@@ -172,12 +172,74 @@ Value::GetType()
return NULL;
}
-void
+size_t
+Value::AppendDataToHostBuffer (const Value &rhs)
+{
+ size_t curr_size = m_data_buffer.GetByteSize();
+ Error error;
+ switch (rhs.GetValueType())
+ {
+ case eValueTypeScalar:
+ {
+ const size_t scalar_size = rhs.m_value.GetByteSize();
+ if (scalar_size > 0)
+ {
+ const size_t new_size = curr_size + scalar_size;
+ if (ResizeData(new_size) == new_size)
+ {
+ rhs.m_value.GetAsMemoryData (m_data_buffer.GetBytes() + curr_size,
+ scalar_size,
+ lldb::endian::InlHostByteOrder(),
+ error);
+ return scalar_size;
+ }
+ }
+ }
+ break;
+ case eValueTypeVector:
+ {
+ const size_t vector_size = rhs.m_vector.length;
+ if (vector_size > 0)
+ {
+ const size_t new_size = curr_size + vector_size;
+ if (ResizeData(new_size) == new_size)
+ {
+ ::memcpy (m_data_buffer.GetBytes() + curr_size,
+ rhs.m_vector.bytes,
+ vector_size);
+ return vector_size;
+ }
+ }
+ }
+ break;
+ case eValueTypeFileAddress:
+ case eValueTypeLoadAddress:
+ case eValueTypeHostAddress:
+ {
+ const uint8_t *src = rhs.GetBuffer().GetBytes();
+ const size_t src_len = rhs.GetBuffer().GetByteSize();
+ if (src && src_len > 0)
+ {
+ const size_t new_size = curr_size + src_len;
+ if (ResizeData(new_size) == new_size)
+ {
+ ::memcpy (m_data_buffer.GetBytes() + curr_size, src, src_len);
+ return src_len;
+ }
+ }
+ }
+ break;
+ }
+ return 0;
+}
+
+size_t
Value::ResizeData(size_t len)
{
m_value_type = eValueTypeHostAddress;
m_data_buffer.SetByteSize(len);
m_value = (uintptr_t)m_data_buffer.GetBytes();
+ return m_data_buffer.GetByteSize();
}
bool
Modified: lldb/trunk/source/Expression/DWARFExpression.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Expression/DWARFExpression.cpp?rev=214415&r1=214414&r2=214415&view=diff
==============================================================================
--- lldb/trunk/source/Expression/DWARFExpression.cpp (original)
+++ lldb/trunk/source/Expression/DWARFExpression.cpp Thu Jul 31 13:19:28 2014
@@ -1347,6 +1347,7 @@ DWARFExpression::Evaluate
/// 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))
@@ -2574,116 +2575,134 @@ DWARFExpression::Evaluate
// variable a particular DWARF expression refers to.
//----------------------------------------------------------------------
case DW_OP_piece:
- if (stack.size() < 1 ||
- (op_piece_offset > 0 && stack.size() < 2))
- {
- // In a multi-piece expression, this means that the current piece is not available.
- // We don't have a way to signal partial availabilty.
- if (error_ptr)
- error_ptr->SetErrorString("Partially unavailable DW_OP_piece expressions are not yet supported.");
- return false;
- }
- else
{
const uint64_t piece_byte_size = opcodes.GetULEB128(&offset);
- switch (stack.back().GetValueType())
+
+ if (piece_byte_size > 0)
{
- case Value::eValueTypeScalar:
- case Value::eValueTypeFileAddress:
- case Value::eValueTypeLoadAddress:
- case Value::eValueTypeHostAddress:
+ 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)
{
- uint32_t bit_size = piece_byte_size * 8;
- uint32_t bit_offset = 0;
- if (!stack.back().GetScalar().ExtractBitfield (bit_size, bit_offset))
+ case Value::eValueTypeLoadAddress:
+ if (process)
{
- if (error_ptr)
- error_ptr->SetErrorStringWithFormat("unable to extract %" PRIu64 " bytes from a %" PRIu64 " byte scalar value.", piece_byte_size, (uint64_t)stack.back().GetScalar().GetByteSize());
- return false;
+ 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;
- // Multiple pieces of a large value are assembled in a memory buffer value.
- if (op_piece_offset)
+ case Value::eValueTypeScalar:
{
- Error error;
- Scalar cur_piece = stack.back().GetScalar();
- stack.pop_back();
+ 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;
- switch (stack.back().GetValueType())
+ case Value::eValueTypeVector:
+ {
+ if (curr_piece_source_value.GetVector().length >= piece_byte_size)
+ curr_piece_source_value.GetVector().length = piece_byte_size;
+ else
{
- case Value::eValueTypeScalar:
- {
- // We already have something on the stack that will becomes the first
- // bytes of our buffer, we need to populate these bytes into the buffer
- // and then we will add the current bytes to it.
-
- // Promote top of stack to a memory buffer.
- Scalar prev_piece = stack.back().GetScalar();
- stack.pop_back();
- stack.push_back(Value());
- Value &piece_value = stack.back();
- piece_value.ResizeData(op_piece_offset);
- prev_piece.GetAsMemoryData(piece_value.GetBuffer().GetBytes(), op_piece_offset, lldb::endian::InlHostByteOrder(), error);
- if (error.Fail())
- {
- if (error_ptr)
- error_ptr->SetErrorString(error.AsCString());
- return false;
- }
- }
- // Fall through to host address case...
-
- case Value::eValueTypeHostAddress:
- {
- if (stack.back().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,
- stack.back().GetBuffer().GetByteSize());
- return false;
- }
-
- // Append the current piece to the buffer.
- size_t len = op_piece_offset + piece_byte_size;
- stack.back().ResizeData(len);
- cur_piece.GetAsMemoryData (stack.back().GetBuffer().GetBytes() + op_piece_offset,
- piece_byte_size,
- lldb::endian::InlHostByteOrder(),
- error);
- if (error.Fail())
- {
- if (error_ptr)
- error_ptr->SetErrorString(error.AsCString());
- return false;
- }
- }
- break;
-
- default:
- // Expect top of stack to be a memory buffer.
- if (error_ptr)
- error_ptr->SetErrorStringWithFormat("DW_OP_piece for offset %" PRIu64 ": top of stack is not a piece", op_piece_offset);
- return false;
+ 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;
}
-
}
- op_piece_offset += piece_byte_size;
+ break;
+
+ default:
+ if (error_ptr)
+ error_ptr->SetErrorStringWithFormat ("unhandled value typpe for DW_OP_piece(%" PRIu64 ")", piece_byte_size);
+ return false;
+
}
- break;
- case Value::eValueTypeVector:
+ // Check if this is the first piece?
+ if (op_piece_offset == 0)
{
- if (stack.back().GetVector().length >= piece_byte_size)
- stack.back().GetVector().length = piece_byte_size;
- else
+ // 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 (!stack.empty())
+ {
+ // 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->SetErrorStringWithFormat("unable to extract %" PRIu64 " bytes from a %" PRIu64 " byte vector value.", piece_byte_size, (uint64_t)stack.back().GetVector().length);
+ error_ptr->SetErrorString("failed to append piece data");
return false;
}
}
- break;
+ op_piece_offset += piece_byte_size;
+ }
}
}
break;
@@ -2702,9 +2721,6 @@ DWARFExpression::Evaluate
switch (stack.back().GetValueType())
{
case Value::eValueTypeScalar:
- case Value::eValueTypeFileAddress:
- case Value::eValueTypeLoadAddress:
- case Value::eValueTypeHostAddress:
{
if (!stack.back().GetScalar().ExtractBitfield (piece_bit_size, piece_bit_offset))
{
@@ -2717,11 +2733,22 @@ DWARFExpression::Evaluate
}
}
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 %" PRIu64 " bit value with %" PRIu64 " bit offset from a vector value.",
+ 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);
}
@@ -2896,24 +2923,34 @@ DWARFExpression::Evaluate
if (stack.empty())
{
- if (error_ptr)
- error_ptr->SetErrorString ("Stack empty after evaluation.");
- return false;
+ // 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())
+ else
{
- size_t count = stack.size();
- log->Printf("Stack after operation has %" PRIu64 " values:", (uint64_t)count);
- for (size_t i=0; i<count; ++i)
+ if (log && log->GetVerbose())
{
- StreamString new_value;
- new_value.Printf("[%" PRIu64 "]", (uint64_t)i);
- stack[i].Dump(&new_value);
- log->Printf(" %s", new_value.GetData());
+ 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();
}
-
- result = stack.back();
return true; // Return true on success
}
More information about the lldb-commits
mailing list