[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 ®_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