[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