Add support for "dynamic values" for C++ classes. This currently only works for "frame var" and for the
expressions that are simple enough to get passed to the "frame var" underpinnings. The parser code will
have to be changed to also query for the dynamic types & offsets as it is looking up variables.
The behavior of "frame var" is controlled in two ways. You can pass "-d {true/false} to the frame var
command to get the dynamic or static value of the variables you are printing.
There's also a general setting:
target.prefer-dynamic-value (boolean) = 'true'
which is consulted if you call "frame var" without supplying a value for the -d option.
git-svn-id: https://llvm.org/svn/llvm-project/llvdb/trunk@129623 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/source/Target/Process.cpp b/source/Target/Process.cpp
index 26d84b9..a492e47 100644
--- a/source/Target/Process.cpp
+++ b/source/Target/Process.cpp
@@ -1902,6 +1902,12 @@
if (buf == NULL || size == 0)
return 0;
+
+ // Need to bump the stop ID after writing so that ValueObjects will know to re-read themselves.
+ // FUTURE: Doing this should be okay, but if anybody else gets upset about the stop_id changing when
+ // the target hasn't run, then we will need to add a "memory generation" as well as a stop_id...
+ m_stop_id++;
+
// We need to write any data that would go where any current software traps
// (enabled software breakpoints) any software traps (breakpoints) that we
// may have placed in our tasks memory.
@@ -1962,7 +1968,7 @@
ubuf + bytes_written,
size - bytes_written,
error);
-
+
return bytes_written;
}
diff --git a/source/Target/StackFrame.cpp b/source/Target/StackFrame.cpp
index 0d0c0e8..a5df928 100644
--- a/source/Target/StackFrame.cpp
+++ b/source/Target/StackFrame.cpp
@@ -493,6 +493,7 @@
{
const bool check_ptr_vs_member = (options & eExpressionPathOptionCheckPtrVsMember) != 0;
const bool no_fragile_ivar = (options & eExpressionPathOptionsNoFragileObjcIvar) != 0;
+ const bool dynamic_value = (options & eExpressionPathOptionsDynamicValue) != 0;
error.Clear();
bool deref = false;
bool address_of = false;
@@ -528,8 +529,10 @@
VariableSP var_sp (variable_list->FindVariable(name_const_string));
if (var_sp)
{
- valobj_sp = GetValueObjectForFrameVariable (var_sp);
-
+ valobj_sp = GetValueObjectForFrameVariable (var_sp, dynamic_value);
+ if (!valobj_sp)
+ return valobj_sp;
+
var_path.erase (0, name_const_string.GetLength ());
// We are dumping at least one child
while (separator_idx != std::string::npos)
@@ -600,7 +603,6 @@
return ValueObjectSP();
}
}
-
child_valobj_sp = valobj_sp->GetChildMemberWithName (child_name, true);
if (!child_valobj_sp)
{
@@ -624,6 +626,12 @@
}
// Remove the child name from the path
var_path.erase(0, child_name.GetLength());
+ if (dynamic_value)
+ {
+ ValueObjectSP dynamic_value_sp(child_valobj_sp->GetDynamicValue(true, child_valobj_sp));
+ if (dynamic_value_sp)
+ child_valobj_sp = dynamic_value_sp;
+ }
}
break;
@@ -650,6 +658,8 @@
}
else if (ClangASTContext::IsArrayType (valobj_sp->GetClangType(), NULL, NULL))
{
+ // Pass false to dynamic_value here so we can tell the difference between
+ // no dynamic value and no member of this type...
child_valobj_sp = valobj_sp->GetChildAtIndex (child_index, true);
if (!child_valobj_sp)
{
@@ -678,7 +688,12 @@
// %i is the array index
var_path.erase(0, (end - var_path.c_str()) + 1);
separator_idx = var_path.find_first_of(".-[");
-
+ if (dynamic_value)
+ {
+ ValueObjectSP dynamic_value_sp(child_valobj_sp->GetDynamicValue(true, child_valobj_sp));
+ if (dynamic_value_sp)
+ child_valobj_sp = dynamic_value_sp;
+ }
// Break out early from the switch since we were
// able to find the child member
break;
@@ -794,7 +809,7 @@
ValueObjectSP
-StackFrame::GetValueObjectForFrameVariable (const VariableSP &variable_sp)
+StackFrame::GetValueObjectForFrameVariable (const VariableSP &variable_sp, bool use_dynamic)
{
ValueObjectSP valobj_sp;
VariableList *var_list = GetVariableList (true);
@@ -815,14 +830,20 @@
}
}
}
+ if (use_dynamic && valobj_sp)
+ {
+ ValueObjectSP dynamic_sp = valobj_sp->GetDynamicValue (true, valobj_sp);
+ if (dynamic_sp)
+ return dynamic_sp;
+ }
return valobj_sp;
}
ValueObjectSP
-StackFrame::TrackGlobalVariable (const VariableSP &variable_sp)
+StackFrame::TrackGlobalVariable (const VariableSP &variable_sp, bool use_dynamic)
{
// Check to make sure we aren't already tracking this variable?
- ValueObjectSP valobj_sp (GetValueObjectForFrameVariable (variable_sp));
+ ValueObjectSP valobj_sp (GetValueObjectForFrameVariable (variable_sp, use_dynamic));
if (!valobj_sp)
{
// We aren't already tracking this global
@@ -835,7 +856,7 @@
m_variable_list_sp->AddVariable (variable_sp);
// Now make a value object for it so we can track its changes
- valobj_sp = GetValueObjectForFrameVariable (variable_sp);
+ valobj_sp = GetValueObjectForFrameVariable (variable_sp, use_dynamic);
}
return valobj_sp;
}
diff --git a/source/Target/Target.cpp b/source/Target/Target.cpp
index 2ade9e6..d08a0fe 100644
--- a/source/Target/Target.cpp
+++ b/source/Target/Target.cpp
@@ -887,6 +887,7 @@
StackFrame *frame,
bool unwind_on_error,
bool keep_in_memory,
+ bool fetch_dynamic_value,
lldb::ValueObjectSP &result_valobj_sp
)
{
@@ -927,7 +928,16 @@
const_valobj_sp->SetName (persistent_variable_name);
}
else
+ {
+ if (fetch_dynamic_value)
+ {
+ ValueObjectSP dynamic_sp = result_valobj_sp->GetDynamicValue(true, result_valobj_sp);
+ if (dynamic_sp)
+ result_valobj_sp = dynamic_sp;
+ }
+
const_valobj_sp = result_valobj_sp->CreateConstantValue (persistent_variable_name);
+ }
lldb::ValueObjectSP live_valobj_sp = result_valobj_sp;
@@ -1277,11 +1287,12 @@
}
-#define TSC_DEFAULT_ARCH "default-arch"
-#define TSC_EXPR_PREFIX "expr-prefix"
-#define TSC_EXEC_LEVEL "execution-level"
-#define TSC_EXEC_MODE "execution-mode"
-#define TSC_EXEC_OS_TYPE "execution-os-type"
+#define TSC_DEFAULT_ARCH "default-arch"
+#define TSC_EXPR_PREFIX "expr-prefix"
+#define TSC_EXEC_LEVEL "execution-level"
+#define TSC_EXEC_MODE "execution-mode"
+#define TSC_EXEC_OS_TYPE "execution-os-type"
+#define TSC_PREFER_DYNAMIC "prefer-dynamic-value"
static const ConstString &
@@ -1320,6 +1331,13 @@
return g_const_string;
}
+static const ConstString &
+GetSettingNameForPreferDynamicValue ()
+{
+ static ConstString g_const_string (TSC_PREFER_DYNAMIC);
+ return g_const_string;
+}
+
bool
Target::SettingsController::SetGlobalVariable (const ConstString &var_name,
@@ -1369,7 +1387,8 @@
) :
InstanceSettings (owner, name ? name : InstanceSettings::InvalidName().AsCString(), live_instance),
m_expr_prefix_path (),
- m_expr_prefix_contents ()
+ m_expr_prefix_contents (),
+ m_prefer_dynamic_value (true)
{
// CopyInstanceSettings is a pure virtual function in InstanceSettings; it therefore cannot be called
// until the vtables for TargetInstanceSettings are properly set up, i.e. AFTER all the initializers.
@@ -1467,6 +1486,39 @@
return;
}
}
+ else if (var_name == GetSettingNameForPreferDynamicValue())
+ {
+ switch (op)
+ {
+ default:
+ err.SetErrorToGenericError ();
+ err.SetErrorString ("Unrecognized operation. Cannot update value.\n");
+ return;
+ case eVarSetOperationAssign:
+ {
+ bool success;
+ bool result = Args::StringToBoolean(value, false, &success);
+
+ if (success)
+ {
+ m_prefer_dynamic_value = result;
+ }
+ else
+ {
+ err.SetErrorStringWithFormat ("Bad value \"%s\" for %s, should be Boolean.",
+ value,
+ GetSettingNameForPreferDynamicValue().AsCString());
+ }
+ return;
+ }
+ case eVarSetOperationClear:
+ m_prefer_dynamic_value = true;
+ case eVarSetOperationAppend:
+ err.SetErrorToGenericError ();
+ err.SetErrorString ("Cannot append to a bool.\n");
+ return;
+ }
+ }
}
void
@@ -1479,6 +1531,7 @@
m_expr_prefix_path = new_settings_ptr->m_expr_prefix_path;
m_expr_prefix_contents = new_settings_ptr->m_expr_prefix_contents;
+ m_prefer_dynamic_value = new_settings_ptr->m_prefer_dynamic_value;
}
bool
@@ -1491,6 +1544,13 @@
{
value.AppendString (m_expr_prefix_path.c_str(), m_expr_prefix_path.size());
}
+ else if (var_name == GetSettingNameForPreferDynamicValue())
+ {
+ if (m_prefer_dynamic_value)
+ value.AppendString ("true");
+ else
+ value.AppendString ("false");
+ }
else
{
if (err)
@@ -1533,5 +1593,6 @@
// var-name var-type default enum init'd hidden help-text
// ================= ================== =========== ==== ====== ====== =========================================================================
{ TSC_EXPR_PREFIX , eSetVarTypeString , NULL , NULL, false, false, "Path to a file containing expressions to be prepended to all expressions." },
+ { TSC_PREFER_DYNAMIC, eSetVarTypeBoolean ,"true" , NULL, false, false, "Should printed values be shown as their dynamic value." },
{ NULL , eSetVarTypeNone , NULL , NULL, false, false, NULL }
};
diff --git a/source/Target/ThreadPlanTestCondition.cpp b/source/Target/ThreadPlanTestCondition.cpp
index 9facfdc..1349e9e 100644
--- a/source/Target/ThreadPlanTestCondition.cpp
+++ b/source/Target/ThreadPlanTestCondition.cpp
@@ -84,8 +84,8 @@
if (result_sp)
{
// FIXME: This is not the right answer, we should have a "GetValueAsBoolean..."
- Scalar scalar_value = result_sp->GetValue().ResolveValue (&m_exe_ctx, result_sp->GetClangAST());
- if (scalar_value.IsValid())
+ Scalar scalar_value;
+ if (result_sp->ResolveValue (scalar_value))
{
if (scalar_value.ULongLong(1) == 0)
m_did_stop = false;