[Lldb-commits] [lldb] r119885 - in /lldb/trunk: include/lldb/Expression/DWARFExpression.h include/lldb/Symbol/UnwindPlan.h source/Core/ValueObjectVariable.cpp source/Expression/ClangExpressionDeclMap.cpp source/Expression/DWARFExpression.cpp source/Plugins/Process/Utility/RegisterContextLLDB.cpp source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp source/Target/StackFrame.cpp

Jason Molenda jmolenda at apple.com
Fri Nov 19 17:28:30 PST 2010


Author: jmolenda
Date: Fri Nov 19 19:28:30 2010
New Revision: 119885

URL: http://llvm.org/viewvc/llvm-project?rev=119885&view=rev
Log:
Change the DWARFExpression::Evaluate methods to take an optional
RegisterContext* - normally this is retrieved from the ExecutionContext's
StackFrame but when we need to evaluate an expression while creating
the stack frame list this can be a little tricky.

Add DW_OP_deref_size, needed for the _sigtramp FDE expression.

Add support for processing DWARF expressions in RegisterContextLLDB.

Update callers to DWARFExpression::Evaluate.


Modified:
    lldb/trunk/include/lldb/Expression/DWARFExpression.h
    lldb/trunk/include/lldb/Symbol/UnwindPlan.h
    lldb/trunk/source/Core/ValueObjectVariable.cpp
    lldb/trunk/source/Expression/ClangExpressionDeclMap.cpp
    lldb/trunk/source/Expression/DWARFExpression.cpp
    lldb/trunk/source/Plugins/Process/Utility/RegisterContextLLDB.cpp
    lldb/trunk/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
    lldb/trunk/source/Target/StackFrame.cpp

Modified: lldb/trunk/include/lldb/Expression/DWARFExpression.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Expression/DWARFExpression.h?rev=119885&r1=119884&r2=119885&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Expression/DWARFExpression.h (original)
+++ lldb/trunk/include/lldb/Expression/DWARFExpression.h Fri Nov 19 19:28:30 2010
@@ -201,6 +201,7 @@
     bool
     Evaluate (ExecutionContext *exe_ctx,
               clang::ASTContext *ast_context,
+              RegisterContext *reg_ctx,
               lldb::addr_t loclist_base_load_addr,
               const Value* initial_value_ptr,
               Value& result,
@@ -234,6 +235,13 @@
     ///     expression.  Can be NULL if the location expression uses no
     ///     external variables.
     ///
+    ///  @param[in] reg_ctx
+    ///     An optional parameter which provides a RegisterContext for use
+    ///     when evaluating the expression (i.e. for fetching register values).
+    ///     Normally this will come from the ExecutionContext's StackFrame but
+    ///     in the case where an expression needs to be evaluated while building
+    ///     the stack frame list, this short-cut is available.
+    ///
     /// @param[in] offset
     ///     The offset of the location expression in the data extractor.
     ///
@@ -264,6 +272,7 @@
               const DataExtractor& opcodes,
               ClangExpressionVariableList *expr_locals,
               ClangExpressionDeclMap *decl_map,
+              RegisterContext *reg_ctx,
               const uint32_t offset,
               const uint32_t length,
               const uint32_t reg_set,

Modified: lldb/trunk/include/lldb/Symbol/UnwindPlan.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Symbol/UnwindPlan.h?rev=119885&r1=119884&r2=119885&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Symbol/UnwindPlan.h (original)
+++ lldb/trunk/include/lldb/Symbol/UnwindPlan.h Fri Nov 19 19:28:30 2010
@@ -104,6 +104,12 @@
             void
             SetIsDWARFExpression (const uint8_t *opcodes, uint32_t len);
 
+            const uint8_t *
+            GetDWARFExpressionBytes () { return m_location.expr.opcodes; }
+
+            int
+            GetDWARFExpressionLength () { return m_location.expr.length; }
+
             void
             Dump (Stream &s) const;
 

Modified: lldb/trunk/source/Core/ValueObjectVariable.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Core/ValueObjectVariable.cpp?rev=119885&r1=119884&r2=119885&view=diff
==============================================================================
--- lldb/trunk/source/Core/ValueObjectVariable.cpp (original)
+++ lldb/trunk/source/Core/ValueObjectVariable.cpp Fri Nov 19 19:28:30 2010
@@ -118,7 +118,7 @@
             loclist_base_load_addr = sc.function->GetAddressRange().GetBaseAddress().GetLoadAddress (exe_ctx.target);
     }
     Value old_value(m_value);
-    if (expr.Evaluate (&exe_ctx, GetClangAST(), loclist_base_load_addr, NULL, m_value, &m_error))
+    if (expr.Evaluate (&exe_ctx, GetClangAST(), NULL, loclist_base_load_addr, NULL, m_value, &m_error))
     {
         m_value.SetContext(Value::eContextTypeVariable, variable);
 

Modified: lldb/trunk/source/Expression/ClangExpressionDeclMap.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Expression/ClangExpressionDeclMap.cpp?rev=119885&r1=119884&r2=119885&view=diff
==============================================================================
--- lldb/trunk/source/Expression/ClangExpressionDeclMap.cpp (original)
+++ lldb/trunk/source/Expression/ClangExpressionDeclMap.cpp Fri Nov 19 19:28:30 2010
@@ -1205,7 +1205,7 @@
     }
     Error err;
     
-    if (!var_location_expr.Evaluate(&exe_ctx, exe_ast_ctx, loclist_base_load_addr, NULL, *var_location.get(), &err))
+    if (!var_location_expr.Evaluate(&exe_ctx, exe_ast_ctx, NULL, loclist_base_load_addr, NULL, *var_location.get(), &err))
     {
         if (log)
             log->Printf("Error evaluating location: %s", err.AsCString());

Modified: lldb/trunk/source/Expression/DWARFExpression.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Expression/DWARFExpression.cpp?rev=119885&r1=119884&r2=119885&view=diff
==============================================================================
--- lldb/trunk/source/Expression/DWARFExpression.cpp (original)
+++ lldb/trunk/source/Expression/DWARFExpression.cpp Fri Nov 19 19:28:30 2010
@@ -631,48 +631,38 @@
 static bool
 ReadRegisterValueAsScalar
 (
-    ExecutionContext *exe_ctx,
+    RegisterContext *reg_context,
     uint32_t reg_kind,
     uint32_t reg_num,
     Error *error_ptr,
     Value &value
 )
 {
-    if (exe_ctx && exe_ctx->frame)
+    if (reg_context == NULL)
     {
-        RegisterContext *reg_context = exe_ctx->frame->GetRegisterContext();
-
-        if (reg_context == NULL)
+        if (error_ptr)
+            error_ptr->SetErrorStringWithFormat("No register context in frame.\n");
+    }
+    else
+    {
+        uint32_t native_reg = reg_context->ConvertRegisterKindToRegisterNumber(reg_kind, reg_num);
+        if (native_reg == LLDB_INVALID_REGNUM)
         {
             if (error_ptr)
-                error_ptr->SetErrorStringWithFormat("No register context in frame.\n");
+                error_ptr->SetErrorStringWithFormat("Unable to convert register kind=%u reg_num=%u to a native register number.\n", reg_kind, reg_num);
         }
         else
         {
-            uint32_t native_reg = reg_context->ConvertRegisterKindToRegisterNumber(reg_kind, reg_num);
-            if (native_reg == LLDB_INVALID_REGNUM)
-            {
-                if (error_ptr)
-                    error_ptr->SetErrorStringWithFormat("Unable to convert register kind=%u reg_num=%u to a native register number.\n", reg_kind, reg_num);
-            }
-            else
-            {
-                value.SetValueType (Value::eValueTypeScalar);
-                value.SetContext (Value::eContextTypeRegisterInfo, const_cast<RegisterInfo *>(reg_context->GetRegisterInfoAtIndex(native_reg)));
+            value.SetValueType (Value::eValueTypeScalar);
+            value.SetContext (Value::eContextTypeRegisterInfo, const_cast<RegisterInfo *>(reg_context->GetRegisterInfoAtIndex(native_reg)));
 
-                if (reg_context->ReadRegisterValue (native_reg, value.GetScalar()))
-                    return true;
+            if (reg_context->ReadRegisterValue (native_reg, value.GetScalar()))
+                return true;
 
-                if (error_ptr)
-                    error_ptr->SetErrorStringWithFormat("Failed to read register %u.\n", native_reg);
-            }
+            if (error_ptr)
+                error_ptr->SetErrorStringWithFormat("Failed to read register %u.\n", native_reg);
         }
     }
-    else
-    {
-        if (error_ptr)
-            error_ptr->SetErrorStringWithFormat("Invalid frame in execution context.\n");
-    }
     return false;
 }
 
@@ -766,7 +756,7 @@
 ) const
 {
     ExecutionContext exe_ctx (exe_scope);
-    return Evaluate(&exe_ctx, ast_context, loclist_base_load_addr, initial_value_ptr, result, error_ptr);
+    return Evaluate(&exe_ctx, ast_context, NULL, loclist_base_load_addr, initial_value_ptr, result, error_ptr);
 }
 
 bool
@@ -774,6 +764,7 @@
 (
     ExecutionContext *exe_ctx,
     clang::ASTContext *ast_context,
+    RegisterContext *reg_ctx,
     lldb::addr_t loclist_base_load_addr,
     const Value* initial_value_ptr,
     Value& result,
@@ -783,7 +774,11 @@
     if (IsLocationList())
     {
         uint32_t offset = 0;
-        addr_t pc = exe_ctx->frame->GetRegisterContext()->GetPC();
+        addr_t pc;
+        if (reg_ctx)
+            pc = reg_ctx->GetPC();
+        else
+            pc = exe_ctx->frame->GetRegisterContext()->GetPC();
 
         if (loclist_base_load_addr != LLDB_INVALID_ADDRESS)
         {
@@ -814,7 +809,7 @@
 
                     if (length > 0 && lo_pc <= pc && pc < hi_pc)
                     {
-                        return DWARFExpression::Evaluate (exe_ctx, ast_context, m_data, m_expr_locals, m_decl_map, offset, length, m_reg_kind, initial_value_ptr, result, error_ptr);
+                        return DWARFExpression::Evaluate (exe_ctx, ast_context, m_data, m_expr_locals, m_decl_map, reg_ctx, offset, length, m_reg_kind, initial_value_ptr, result, error_ptr);
                     }
                     offset += length;
                 }
@@ -826,7 +821,7 @@
     }
 
     // Not a location list, just a single expression.
-    return DWARFExpression::Evaluate (exe_ctx, ast_context, m_data, m_expr_locals, m_decl_map, 0, m_data.GetByteSize(), m_reg_kind, initial_value_ptr, result, error_ptr);
+    return DWARFExpression::Evaluate (exe_ctx, ast_context, m_data, m_expr_locals, m_decl_map, reg_ctx, 0, m_data.GetByteSize(), m_reg_kind, initial_value_ptr, result, error_ptr);
 }
 
 
@@ -839,6 +834,7 @@
     const DataExtractor& opcodes,
     ClangExpressionVariableList *expr_locals,
     ClangExpressionDeclMap *decl_map,
+    RegisterContext *reg_ctx,
     const uint32_t opcodes_offset,
     const uint32_t opcodes_length,
     const uint32_t reg_kind,
@@ -849,6 +845,9 @@
 {
     std::vector<Value> stack;
 
+    if (reg_ctx == NULL && exe_ctx && exe_ctx->frame)
+        reg_ctx = exe_ctx->frame->GetRegisterContext();
+
     if (initial_value_ptr)
         stack.push_back(*initial_value_ptr);
 
@@ -1015,9 +1014,86 @@
         // on the expression stack.
         //----------------------------------------------------------------------
         case DW_OP_deref_size:
-            if (error_ptr)
-                error_ptr->SetErrorString("Unimplemented opcode: DW_OP_deref_size.");
-            return false;
+            {
+                uint8_t size = opcodes.GetU8(&offset);
+                Value::ValueType value_type = stack.back().GetValueType();
+                switch (value_type)
+                {
+                case Value::eValueTypeHostAddress:
+                    {
+                        void *src = (void *)stack.back().GetScalar().ULongLong();
+                        intptr_t ptr;
+                        ::memcpy (&ptr, src, sizeof(void *));
+                        // I can't decide whether the size operand should apply to the bytes in their
+                        // lldb-host endianness or the target endianness.. I doubt this'll ever come up
+                        // but I'll opt for assuming big endian regardless.
+                        switch (size)
+                        {
+                            case 1: ptr = ptr & 0xff; break;
+                            case 2: ptr = ptr & 0xffff; break;
+                            case 3: ptr = ptr & 0xffffff; break;
+                            case 4: ptr = ptr & 0xffffffff; break;
+                            case 5: ptr = ptr & 0xffffffffff; break;
+                            case 6: ptr = ptr & 0xffffffffffff; break;
+                            case 7: ptr = ptr & 0xffffffffffffff; break;
+                            default: break;
+                        }
+                        stack.back().GetScalar() = ptr;
+                        stack.back().ClearContext();
+                    }
+                    break;
+                case Value::eValueTypeLoadAddress:
+                    if (exe_ctx)
+                    {
+                        if (exe_ctx->process)
+                        {
+                            lldb::addr_t pointer_addr = stack.back().GetScalar().ULongLong(LLDB_INVALID_ADDRESS);
+                            uint8_t addr_bytes[sizeof(lldb::addr_t)];
+                            Error error;
+                            if (exe_ctx->process->ReadMemory(pointer_addr, &addr_bytes, size, error) == size)
+                            {
+                                DataExtractor addr_data(addr_bytes, sizeof(addr_bytes), exe_ctx->process->GetByteOrder(), size);
+                                uint32_t addr_data_offset = 0;
+                                switch (size)
+                                {
+                                    case 1: stack.back().GetScalar() = addr_data.GetU8(&addr_data_offset); break;
+                                    case 2: stack.back().GetScalar() = addr_data.GetU16(&addr_data_offset); break;
+                                    case 4: stack.back().GetScalar() = addr_data.GetU32(&addr_data_offset); break;
+                                    case 8: stack.back().GetScalar() = addr_data.GetU64(&addr_data_offset); break;
+                                    default: stack.back().GetScalar() = addr_data.GetPointer(&addr_data_offset);
+                                }
+                                stack.back().ClearContext();
+                            }
+                            else
+                            {
+                                if (error_ptr)
+                                    error_ptr->SetErrorStringWithFormat ("Failed to dereference pointer from 0x%llx for DW_OP_deref: %s\n", 
+                                                                         pointer_addr,
+                                                                         error.AsCString());
+                                return false;
+                            }
+                        }
+                        else
+                        {
+                            if (error_ptr)
+                                error_ptr->SetErrorStringWithFormat ("NULL process for DW_OP_deref.\n");
+                            return false;
+                        }
+                    }
+                    else
+                    {
+                        if (error_ptr)
+                            error_ptr->SetErrorStringWithFormat ("NULL execution context for DW_OP_deref.\n");
+                        return false;
+                    }
+                    break;
+
+                default:
+                    break;
+                }
+
+            }
+            break;
 
         //----------------------------------------------------------------------
         // OPCODE: DW_OP_xderef_size
@@ -1837,7 +1913,7 @@
             {
                 reg_num = op - DW_OP_reg0;
 
-                if (ReadRegisterValueAsScalar (exe_ctx, reg_kind, reg_num, error_ptr, tmp))
+                if (ReadRegisterValueAsScalar (reg_ctx, reg_kind, reg_num, error_ptr, tmp))
                     stack.push_back(tmp);
                 else
                     return false;
@@ -1852,7 +1928,7 @@
         case DW_OP_regx:
             {
                 reg_num = opcodes.GetULEB128(&offset);
-                if (ReadRegisterValueAsScalar (exe_ctx, reg_kind, reg_num, error_ptr, tmp))
+                if (ReadRegisterValueAsScalar (reg_ctx, reg_kind, reg_num, error_ptr, tmp))
                     stack.push_back(tmp);
                 else
                     return false;
@@ -1901,7 +1977,7 @@
             {
                 reg_num = op - DW_OP_breg0;
 
-                if (ReadRegisterValueAsScalar (exe_ctx, reg_kind, reg_num, error_ptr, tmp))
+                if (ReadRegisterValueAsScalar (reg_ctx, reg_kind, reg_num, error_ptr, tmp))
                 {
                     int64_t breg_offset = opcodes.GetSLEB128(&offset);
                     tmp.ResolveValue(exe_ctx, ast_context) += (uint64_t)breg_offset;
@@ -1924,7 +2000,7 @@
             {
                 reg_num = opcodes.GetULEB128(&offset);
 
-                if (ReadRegisterValueAsScalar (exe_ctx, reg_kind, reg_num, error_ptr, tmp))
+                if (ReadRegisterValueAsScalar (reg_ctx, reg_kind, reg_num, error_ptr, tmp))
                 {
                     int64_t breg_offset = opcodes.GetSLEB128(&offset);
                     tmp.ResolveValue(exe_ctx, ast_context) += (uint64_t)breg_offset;

Modified: lldb/trunk/source/Plugins/Process/Utility/RegisterContextLLDB.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/Utility/RegisterContextLLDB.cpp?rev=119885&r1=119884&r2=119885&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/Utility/RegisterContextLLDB.cpp (original)
+++ lldb/trunk/source/Plugins/Process/Utility/RegisterContextLLDB.cpp Fri Nov 19 19:28:30 2010
@@ -22,6 +22,10 @@
 #include "lldb/Core/DataBufferHeap.h"
 #include "lldb/Utility/ArchVolatileRegs.h"
 #include "lldb/Core/Log.h"
+#include "lldb/Expression/DWARFExpression.h"
+#include "lldb/Core/Value.h"
+#include "lldb/Target/ExecutionContext.h"
+#include "lldb/Target/StackFrame.h"
 
 using namespace lldb;
 using namespace lldb_private;
@@ -814,7 +818,7 @@
 
     UnwindPlan::Row::RegisterLocation unwindplan_regloc;
     bool have_unwindplan_regloc = false;
-    int unwindplan_registerkind;
+    int unwindplan_registerkind = -1;
 
     if (m_fast_unwind_plan)
     {
@@ -995,6 +999,44 @@
         return true;
     }
 
+    if (unwindplan_regloc.IsDWARFExpression() || unwindplan_regloc.IsAtDWARFExpression())
+    {
+        DataExtractor dwarfdata (unwindplan_regloc.GetDWARFExpressionBytes(), 
+                                 unwindplan_regloc.GetDWARFExpressionLength(), 
+                                 m_thread.GetProcess().GetByteOrder(), m_thread.GetProcess().GetAddressByteSize());
+        DWARFExpression dwarfexpr (dwarfdata, 0, unwindplan_regloc.GetDWARFExpressionLength());
+        dwarfexpr.SetRegisterKind (unwindplan_registerkind);
+        ExecutionContext exe_ctx (&m_thread.GetProcess(), &m_thread, NULL);
+        Value result;
+        Error error;
+        if (dwarfexpr.Evaluate (&exe_ctx, NULL, this, 0, NULL, result, &error))
+        {
+            addr_t val;
+            val = result.GetScalar().ULongLong();
+            if (unwindplan_regloc.IsDWARFExpression())
+             {
+                regloc.type = eRegisterValueInferred;
+                regloc.location.register_value = val;
+                m_registers[lldb_regnum] = regloc;
+                return true;
+            }
+            else
+            {
+               regloc.type = eRegisterSavedAtMemoryLocation;
+               regloc.location.target_memory_location = val;
+               m_registers[lldb_regnum] = regloc;
+               return true;
+            }
+        }
+        if (log)
+        {
+            log->Printf("%*sFrame %d tried to use IsDWARFExpression or IsAtDWARFExpression for reg %d but failed",
+                        m_frame_number < 100 ? m_frame_number : 100, "", m_frame_number,
+                        lldb_regnum);
+        }
+        return false;
+    }
+
     if (log)
     {
         log->Printf("%*sFrame %d could not supply caller's reg %d location",

Modified: lldb/trunk/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp?rev=119885&r1=119884&r2=119885&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp (original)
+++ lldb/trunk/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp Fri Nov 19 19:28:30 2010
@@ -1225,6 +1225,7 @@
                                                                    debug_info_data, 
                                                                    NULL, 
                                                                    NULL, 
+                                                                   NULL,
                                                                    block_offset, 
                                                                    block_length, 
                                                                    eRegisterKindDWARF, 

Modified: lldb/trunk/source/Target/StackFrame.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Target/StackFrame.cpp?rev=119885&r1=119884&r2=119885&view=diff
==============================================================================
--- lldb/trunk/source/Target/StackFrame.cpp (original)
+++ lldb/trunk/source/Target/StackFrame.cpp Fri Nov 19 19:28:30 2010
@@ -496,7 +496,7 @@
             if (m_sc.function->GetFrameBaseExpression().IsLocationList())
                 loclist_base_addr = m_sc.function->GetAddressRange().GetBaseAddress().GetLoadAddress (&m_thread.GetProcess().GetTarget());
 
-            if (m_sc.function->GetFrameBaseExpression().Evaluate(&exe_ctx, NULL, loclist_base_addr, NULL, expr_value, &m_frame_base_error) == false)
+            if (m_sc.function->GetFrameBaseExpression().Evaluate(&exe_ctx, NULL, NULL, loclist_base_addr, NULL, expr_value, &m_frame_base_error) == false)
             {
                 // We should really have an error if evaluate returns, but in case
                 // we don't, lets set the error to something at least.





More information about the lldb-commits mailing list