[Lldb-commits] [lldb] r172848 - in /lldb/trunk: include/lldb/Expression/ClangExpressionDeclMap.h source/Expression/ClangExpressionDeclMap.cpp test/lang/c/const_variables/ test/lang/c/const_variables/Makefile test/lang/c/const_variables/TestConstVariables.py test/lang/c/const_variables/functions.c test/lang/c/const_variables/main.c

Sean Callanan scallanan at apple.com
Fri Jan 18 13:20:51 PST 2013


Author: spyffe
Date: Fri Jan 18 15:20:51 2013
New Revision: 172848

URL: http://llvm.org/viewvc/llvm-project?rev=172848&view=rev
Log:
Made the expression handle variables with
DW_AT_const_value instead of a location.  Also
added a testcase covering "frame variable," "expr"
using the IR interpreter, and "expr" using the
LLVM JIT.

<rdar://problem/12978195>

Added:
    lldb/trunk/test/lang/c/const_variables/
    lldb/trunk/test/lang/c/const_variables/Makefile
    lldb/trunk/test/lang/c/const_variables/TestConstVariables.py
    lldb/trunk/test/lang/c/const_variables/functions.c
    lldb/trunk/test/lang/c/const_variables/main.c
Modified:
    lldb/trunk/include/lldb/Expression/ClangExpressionDeclMap.h
    lldb/trunk/source/Expression/ClangExpressionDeclMap.cpp

Modified: lldb/trunk/include/lldb/Expression/ClangExpressionDeclMap.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Expression/ClangExpressionDeclMap.h?rev=172848&r1=172847&r2=172848&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Expression/ClangExpressionDeclMap.h (original)
+++ lldb/trunk/include/lldb/Expression/ClangExpressionDeclMap.h Fri Jan 18 15:20:51 2013
@@ -1104,6 +1104,51 @@
                                         Error &err);
     
     //------------------------------------------------------------------
+    /// Create a temporary buffer in the target process to store the value
+    /// of a persistent variable that would otherwise not be accessible in
+    /// memory (e.g., register values or constants).
+    ///
+    /// @param[in] process
+    ///     The process to use when allocating the memory.
+    ///
+    /// @param[in] expr_var
+    ///     The variable whose live data will hold this buffer.
+    ///
+    /// @param[in] err
+    ///     An Error to populate with any messages related to
+    ///     allocating the memory.
+    ///
+    /// @return
+    ///     True on success; false otherwise.
+    //------------------------------------------------------------------
+    bool
+    CreateLiveMemoryForExpressionVariable (Process &process,
+                                           lldb::ClangExpressionVariableSP &expr_var,
+                                           Error &err);
+    
+    //------------------------------------------------------------------
+    /// Delete a temporary buffer created with
+    /// CreateLiveMemoryForExpressionVariable.
+    ///
+    /// @param[in] process
+    ///     The process to use when deallocating the memory.
+    ///
+    /// @param[in] expr_var
+    ///     The variable whose live data will hold this buffer.
+    ///
+    /// @param[in] err
+    ///     An Error to populate with any messages related to
+    ///     allocating the memory.
+    ///
+    /// @return
+    ///     True on success; false otherwise.
+    //------------------------------------------------------------------
+    bool
+    DeleteLiveMemoryForExpressionVariable (Process &process,
+                                           lldb::ClangExpressionVariableSP &expr_var,
+                                           Error &err);
+    
+    //------------------------------------------------------------------
     /// Actually do the task of materializing or dematerializing a 
     /// variable.
     ///

Modified: lldb/trunk/source/Expression/ClangExpressionDeclMap.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Expression/ClangExpressionDeclMap.cpp?rev=172848&r1=172847&r2=172848&view=diff
==============================================================================
--- lldb/trunk/source/Expression/ClangExpressionDeclMap.cpp (original)
+++ lldb/trunk/source/Expression/ClangExpressionDeclMap.cpp Fri Jan 18 15:20:51 2013
@@ -1835,13 +1835,80 @@
     return true;
 }
 
-bool 
+bool
+ClangExpressionDeclMap::CreateLiveMemoryForExpressionVariable
+(
+    Process &process,
+    ClangExpressionVariableSP &expr_var,
+    Error &err
+)
+{
+    Error allocate_error;
+    TypeFromUser type(expr_var->GetTypeFromUser());
+    const ConstString &name(expr_var->GetName());
+    
+    size_t value_bit_size = ClangASTType::GetClangTypeBitWidth(type.GetASTContext(), type.GetOpaqueQualType());
+    size_t value_byte_size = value_bit_size % 8 ? ((value_bit_size + 8) / 8) : (value_bit_size / 8);
+
+    Scalar val_addr (process.AllocateMemory (value_byte_size,
+                                             lldb::ePermissionsReadable | lldb::ePermissionsWritable,
+                                             allocate_error));
+    
+    if (val_addr.ULongLong() == LLDB_INVALID_ADDRESS)
+    {
+        err.SetErrorStringWithFormat ("Couldn't allocate a memory area to store %s: %s",
+                                      name.GetCString(),
+                                      allocate_error.AsCString());
+        return false;
+    }
+    
+    // Put the location of the spare memory into the live data of the ValueObject.
+    
+    expr_var->m_live_sp = ValueObjectConstResult::Create (m_parser_vars->m_exe_ctx.GetBestExecutionContextScope(),
+                                                          type.GetASTContext(),
+                                                          type.GetOpaqueQualType(),
+                                                          name,
+                                                          val_addr.ULongLong(),
+                                                          eAddressTypeLoad,
+                                                          value_byte_size);
+    
+    return true;
+}
+
+bool
+ClangExpressionDeclMap::DeleteLiveMemoryForExpressionVariable
+(
+    Process &process,
+    ClangExpressionVariableSP &expr_var,
+    Error &err
+)
+{
+    const ConstString &name(expr_var->GetName());
+    
+    Scalar &val_addr = expr_var->m_live_sp->GetValue().GetScalar();
+    
+    Error deallocate_error = process.DeallocateMemory(val_addr.ULongLong());
+    
+    if (!deallocate_error.Success())
+    {
+        err.SetErrorStringWithFormat ("Couldn't deallocate spare memory area for %s: %s",
+                                      name.GetCString(),
+                                      deallocate_error.AsCString());
+        return false;
+    }
+    
+    expr_var->m_live_sp.reset();
+    
+    return true;
+}
+
+bool
 ClangExpressionDeclMap::DoMaterializeOneVariable
 (
     bool dematerialize,
     const SymbolContext &sym_ctx,
     ClangExpressionVariableSP &expr_var,
-    lldb::addr_t addr, 
+    lldb::addr_t addr,
     Error &err
 )
 {
@@ -1939,6 +2006,66 @@
             return false;
         }
         break;
+    case Value::eValueTypeHostAddress:
+        {
+            if (dematerialize)
+            {
+                if (!DeleteLiveMemoryForExpressionVariable(*process, expr_var, err))
+                    return false;
+            }
+            else
+            {                
+                DataExtractor value_data_extractor;
+                
+                if (location_value->GetData(value_data_extractor))
+                {
+                    if (value_byte_size != value_data_extractor.GetByteSize())
+                    {
+                        err.SetErrorStringWithFormat ("Size mismatch for %s: %llu versus %llu",
+                                                      name.GetCString(),
+                                                      (uint64_t)value_data_extractor.GetByteSize(),
+                                                      (uint64_t)value_byte_size);
+                        return false;
+                    }
+                    
+                    if (!CreateLiveMemoryForExpressionVariable(*process, expr_var, err))
+                        return false;
+                    
+                    Scalar &buf_addr = expr_var->m_live_sp->GetValue().GetScalar();
+
+                    Error write_error;
+                    
+                    if (!process->WriteMemory(buf_addr.ULongLong(),
+                                              value_data_extractor.GetDataStart(),
+                                              value_data_extractor.GetByteSize(),
+                                              write_error))
+                    {
+                        err.SetErrorStringWithFormat ("Couldn't write %s to the target: %s",
+                                                      name.GetCString(),
+                                                      write_error.AsCString());
+                        return false;
+                    }
+                    
+                    if (!process->WriteScalarToMemory(addr,
+                                                      buf_addr,
+                                                      process->GetAddressByteSize(),
+                                                      write_error))
+                    {
+                        err.SetErrorStringWithFormat ("Couldn't write the address of %s to the target: %s",
+                                                      name.GetCString(),
+                                                      write_error.AsCString());
+                        return false;
+                    }
+                }
+                else
+                {
+                    err.SetErrorStringWithFormat ("%s is marked as a host address but doesn't contain any data",
+                                                  name.GetCString());
+                    return false;
+                }
+            }
+        }
+        break;
     case Value::eValueTypeLoadAddress:
         {
             if (!dematerialize)
@@ -2057,19 +2184,8 @@
                     return false;
                 }
                 
-                // Deallocate the spare area and clear the variable's live data.
-                
-                Error deallocate_error = process->DeallocateMemory(reg_addr.ULongLong());
-                
-                if (!deallocate_error.Success())
-                {
-                    err.SetErrorStringWithFormat ("Couldn't deallocate spare memory area for %s: %s", 
-                                                  name.GetCString(), 
-                                                  deallocate_error.AsCString());
+                if (!DeleteLiveMemoryForExpressionVariable(*process, expr_var, err))
                     return false;
-                }
-                
-                expr_var->m_live_sp.reset();
             }
             else
             {
@@ -2103,36 +2219,17 @@
                     
                     return true;
                 }
-
+                
                 // Allocate a spare memory area to place the register's contents into.  This memory area will be pointed to by the slot in the
                 // struct.
                 
-                Error allocate_error;
-                
-                Scalar reg_addr (process->AllocateMemory (value_byte_size, 
-                                                          lldb::ePermissionsReadable | lldb::ePermissionsWritable, 
-                                                          allocate_error));
-                
-                if (reg_addr.ULongLong() == LLDB_INVALID_ADDRESS)
-                {
-                    err.SetErrorStringWithFormat ("Couldn't allocate a memory area to store %s: %s", 
-                                                  name.GetCString(), 
-                                                  allocate_error.AsCString());
+                if (!CreateLiveMemoryForExpressionVariable (*process, expr_var, err))
                     return false;
-                }
                 
-                // Put the location of the spare memory into the live data of the ValueObject.
+                // Now write the location of the area into the struct.
                 
-                expr_var->m_live_sp = ValueObjectConstResult::Create (m_parser_vars->m_exe_ctx.GetBestExecutionContextScope(),
-                                                                      type.GetASTContext(),
-                                                                      type.GetOpaqueQualType(),
-                                                                      name,
-                                                                      reg_addr.ULongLong(),
-                                                                      eAddressTypeLoad,
-                                                                      value_byte_size);
+                Scalar &reg_addr = expr_var->m_live_sp->GetValue().GetScalar();
                 
-                // Now write the location of the area into the struct.
-                                
                 if (!process->WriteScalarToMemory (addr, 
                                                    reg_addr, 
                                                    process->GetAddressByteSize(), 
@@ -3055,7 +3152,23 @@
     }
     Error err;
     
-    if (!var_location_expr.Evaluate(&m_parser_vars->m_exe_ctx, ast, NULL, NULL, NULL, loclist_base_load_addr, NULL, *var_location.get(), &err))
+    if (var->GetLocationIsConstantValueData())
+    {
+        DataExtractor const_value_extractor;
+        
+        if (var_location_expr.GetExpressionData(const_value_extractor))
+        {
+            var_location->operator=(Value(const_value_extractor.GetDataStart(), const_value_extractor.GetByteSize()));
+            var_location->SetValueType(Value::eValueTypeHostAddress);
+        }
+        else
+        {
+            if (log)
+                log->Printf("Error evaluating constant variable: %s", err.AsCString());
+            return NULL;
+        }
+    }
+    else if (!var_location_expr.Evaluate(&m_parser_vars->m_exe_ctx, ast, NULL, NULL, NULL, loclist_base_load_addr, NULL, *var_location.get(), &err))
     {
         if (log)
             log->Printf("Error evaluating location: %s", err.AsCString());

Added: lldb/trunk/test/lang/c/const_variables/Makefile
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/test/lang/c/const_variables/Makefile?rev=172848&view=auto
==============================================================================
--- lldb/trunk/test/lang/c/const_variables/Makefile (added)
+++ lldb/trunk/test/lang/c/const_variables/Makefile Fri Jan 18 15:20:51 2013
@@ -0,0 +1,7 @@
+LEVEL = ../../../make
+
+C_SOURCES := main.c functions.c
+
+CFLAGS ?= -arch $(ARCH) -gdwarf-2 -O3
+
+include $(LEVEL)/Makefile.rules

Added: lldb/trunk/test/lang/c/const_variables/TestConstVariables.py
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/test/lang/c/const_variables/TestConstVariables.py?rev=172848&view=auto
==============================================================================
--- lldb/trunk/test/lang/c/const_variables/TestConstVariables.py (added)
+++ lldb/trunk/test/lang/c/const_variables/TestConstVariables.py Fri Jan 18 15:20:51 2013
@@ -0,0 +1,66 @@
+"""Check that compiler-generated constant values work correctly"""
+
+import os, time
+import unittest2
+import lldb
+from lldbtest import *
+import lldbutil
+
+class ConstVariableTestCase(TestBase):
+
+    mydir = os.path.join("lang", "c", "const_variables")
+
+    @dsym_test
+    def test_with_dsym_and_run_command(self):
+        """Test interpreted and JITted expressions on constant values."""
+        self.buildDsym()
+        self.const_variable()
+
+    @dwarf_test
+    def test_with_dwarf_and_run_command(self):
+        """Test interpreted and JITted expressions on constant values."""
+        self.buildDwarf()
+        self.const_variable()
+
+    def setUp(self):
+        # Call super's setUp().
+        TestBase.setUp(self)
+
+    def const_variable(self):
+        """Test interpreted and JITted expressions on constant values."""
+        exe = os.path.join(os.getcwd(), "a.out")
+        self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET)
+
+        # Break inside the main.
+        lldbutil.run_break_set_by_symbol (self, "main", num_expected_locations=1)
+
+        self.runCmd("run", RUN_SUCCEEDED)
+
+        # The stop reason of the thread should be breakpoint.
+        self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT,
+            substrs = ['stopped',
+                       'stop reason = breakpoint'])
+
+        # The breakpoint should have a hit count of 1.
+        self.expect("breakpoint list -f", BREAKPOINT_HIT_ONCE,
+            substrs = [' resolved, hit count = 1'])
+
+        # Try frame variable.
+        self.expect("frame variable index", VARIABLES_DISPLAYED_CORRECTLY,
+            substrs = ['(int32_t) index = 512'])
+
+        # Try an interpreted expression.
+        self.expect("expr (index + 512)", VARIABLES_DISPLAYED_CORRECTLY,
+            substrs = ['(int) $0 = 1024'])
+
+        # Try a JITted expression.
+        self.expect("expr (int)getpid(); (index - 256)", VARIABLES_DISPLAYED_CORRECTLY,
+            substrs = ['(int) $1 = 256'])
+
+        self.runCmd("kill")
+
+if __name__ == '__main__':
+    import atexit
+    lldb.SBDebugger.Initialize()
+    atexit.register(lambda: lldb.SBDebugger.Terminate())
+    unittest2.main()

Added: lldb/trunk/test/lang/c/const_variables/functions.c
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/test/lang/c/const_variables/functions.c?rev=172848&view=auto
==============================================================================
--- lldb/trunk/test/lang/c/const_variables/functions.c (added)
+++ lldb/trunk/test/lang/c/const_variables/functions.c Fri Jan 18 15:20:51 2013
@@ -0,0 +1,18 @@
+#include <stdio.h>
+
+void foo()
+{
+  printf("foo()\n");
+}
+
+int bar()
+{
+  int ret = 3;
+  printf("bar()->%d\n", ret);
+  return ret;
+}
+
+void baaz(int i)
+{
+  printf("baaz(%d)\n", i);
+}

Added: lldb/trunk/test/lang/c/const_variables/main.c
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/test/lang/c/const_variables/main.c?rev=172848&view=auto
==============================================================================
--- lldb/trunk/test/lang/c/const_variables/main.c (added)
+++ lldb/trunk/test/lang/c/const_variables/main.c Fri Jan 18 15:20:51 2013
@@ -0,0 +1,19 @@
+#include <stdint.h>
+
+extern int foo();
+extern int bar();
+extern int baaz(int i);
+
+int main()
+{
+  int32_t index;
+
+  foo();
+
+  index = 512;
+
+  if (bar())
+    index = 256;
+
+  baaz(index);
+}





More information about the lldb-commits mailing list