lldb needs to support DW_op_piece masks for values in subregister and also to be able to piece together a value that is spread across multiple registers.

Patch from Adrian Prantl.

<rdar://problem/16040521> 

llvm-svn: 212867
This commit is contained in:
Greg Clayton 2014-07-12 00:24:33 +00:00
parent 345c287da9
commit 2740787dc9
6 changed files with 124 additions and 6 deletions

View File

@ -121,6 +121,9 @@ public:
void
CopyData (const void *src, lldb::offset_t src_len);
void
AppendData (const void *src, uint64_t src_len);
void
Clear();

View File

@ -124,9 +124,15 @@ public:
Value();
Value(const Scalar& scalar);
Value(const Vector& vector);
Value(const uint8_t *bytes, int len);
Value(const void *bytes, int len);
Value(const Value &rhs);
void
SetBytes (const void *bytes, int len);
void
AppendBytes (const void *bytes, int len);
Value &
operator=(const Value &rhs);
@ -235,6 +241,18 @@ public:
void
ResizeData(size_t len);
DataBufferHeap &
GetBuffer ()
{
return m_data_buffer;
}
const DataBufferHeap &
GetBuffer () const
{
return m_data_buffer;
}
bool
ValueOf(ExecutionContext *exe_ctx);

View File

@ -103,6 +103,12 @@ DataBufferHeap::CopyData (const void *src, uint64_t src_len)
m_data.clear();
}
void
DataBufferHeap::AppendData (const void *src, uint64_t src_len)
{
m_data.insert(m_data.end(), (uint8_t *)src, (uint8_t *)src + src_len);
}
void
DataBufferHeap::Clear()
{

View File

@ -55,7 +55,7 @@ Value::Value(const Scalar& scalar) :
}
Value::Value(const uint8_t *bytes, int len) :
Value::Value(const void *bytes, int len) :
m_value (),
m_vector (),
m_clang_type (),
@ -64,8 +64,7 @@ Value::Value(const uint8_t *bytes, int len) :
m_context_type (eContextTypeInvalid),
m_data_buffer ()
{
m_data_buffer.CopyData(bytes, len);
m_value = (uintptr_t)m_data_buffer.GetBytes();
SetBytes(bytes, len);
}
Value::Value(const Value &v) :
@ -110,6 +109,22 @@ Value::operator=(const Value &rhs)
return *this;
}
void
Value::SetBytes (const void *bytes, int len)
{
m_value_type = eValueTypeHostAddress;
m_data_buffer.CopyData(bytes, len);
m_value = (uintptr_t)m_data_buffer.GetBytes();
}
void
Value::AppendBytes (const void *bytes, int len)
{
m_value_type = eValueTypeHostAddress;
m_data_buffer.AppendData (bytes, len);
m_value = (uintptr_t)m_data_buffer.GetBytes();
}
void
Value::Dump (Stream* strm)
{

View File

@ -1345,6 +1345,9 @@ DWARFExpression::Evaluate
Value tmp;
uint32_t reg_num;
/// Insertion point for evaluating multi-piece expression.
uint64_t op_piece_offset = 0;
// Make sure all of the data is available in opcodes.
if (!opcodes.ValidOffsetForDataOfSize(opcodes_offset, opcodes_length))
{
@ -2574,10 +2577,13 @@ DWARFExpression::Evaluate
// variable a particular DWARF expression refers to.
//----------------------------------------------------------------------
case DW_OP_piece:
if (stack.size() < 1)
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("Expression stack needs at least 1 item for DW_OP_piece.");
error_ptr->SetErrorString("Partially unavailable DW_OP_piece expressions are not yet supported.");
return false;
}
else
@ -2598,6 +2604,74 @@ DWARFExpression::Evaluate
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;
}
// Multiple pieces of a large value are assembled in a memory buffer value.
if (op_piece_offset)
{
Error error;
Scalar cur_piece = stack.back().GetScalar();
stack.pop_back();
switch (stack.back().GetValueType())
{
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;
}
}
op_piece_offset += piece_byte_size;
}
break;

View File

@ -83,6 +83,8 @@ Rotl32 (uint32_t bits, uint32_t amt)
static inline uint64_t
MaskUpToBit (const uint64_t bit)
{
if (bit >= 63)
return -1ll;
return (1ull << (bit + 1ull)) - 1ull;
}