diff options
| author | Greg Clayton <gclayton@apple.com> | 2014-07-12 00:24:33 +0000 |
|---|---|---|
| committer | Greg Clayton <gclayton@apple.com> | 2014-07-12 00:24:33 +0000 |
| commit | 2740787dc952e673647610a0ee3f18abbc269e15 (patch) | |
| tree | 38e7dde329a22a76adcbbe6b0a82067bec067bb6 /lldb/source/Expression/DWARFExpression.cpp | |
| parent | 345c287da9bc502d7be580686c6273a16afcdfe7 (diff) | |
| download | bcm5719-llvm-2740787dc952e673647610a0ee3f18abbc269e15.tar.gz bcm5719-llvm-2740787dc952e673647610a0ee3f18abbc269e15.zip | |
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
Diffstat (limited to 'lldb/source/Expression/DWARFExpression.cpp')
| -rw-r--r-- | lldb/source/Expression/DWARFExpression.cpp | 78 |
1 files changed, 76 insertions, 2 deletions
diff --git a/lldb/source/Expression/DWARFExpression.cpp b/lldb/source/Expression/DWARFExpression.cpp index eb0b0215fc7..e3e3bb35367 100644 --- a/lldb/source/Expression/DWARFExpression.cpp +++ b/lldb/source/Expression/DWARFExpression.cpp @@ -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; |

