xref: /freebsd-src/contrib/llvm-project/lldb/source/Core/ValueObjectDynamicValue.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
15ffd83dbSDimitry Andric //===-- ValueObjectDynamicValue.cpp ---------------------------------------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric 
90b57cec5SDimitry Andric #include "lldb/Core/ValueObjectDynamicValue.h"
100b57cec5SDimitry Andric #include "lldb/Core/Value.h"
110b57cec5SDimitry Andric #include "lldb/Core/ValueObject.h"
120b57cec5SDimitry Andric #include "lldb/Symbol/CompilerType.h"
130b57cec5SDimitry Andric #include "lldb/Symbol/Type.h"
140b57cec5SDimitry Andric #include "lldb/Target/ExecutionContext.h"
150b57cec5SDimitry Andric #include "lldb/Target/LanguageRuntime.h"
160b57cec5SDimitry Andric #include "lldb/Target/Process.h"
170b57cec5SDimitry Andric #include "lldb/Target/Target.h"
180b57cec5SDimitry Andric #include "lldb/Utility/DataExtractor.h"
1981ad6265SDimitry Andric #include "lldb/Utility/LLDBLog.h"
200b57cec5SDimitry Andric #include "lldb/Utility/Log.h"
210b57cec5SDimitry Andric #include "lldb/Utility/Scalar.h"
220b57cec5SDimitry Andric #include "lldb/Utility/Status.h"
230b57cec5SDimitry Andric #include "lldb/lldb-types.h"
240b57cec5SDimitry Andric 
25fe6060f1SDimitry Andric #include <cstring>
26bdd1243dSDimitry Andric #include <optional>
270b57cec5SDimitry Andric namespace lldb_private {
280b57cec5SDimitry Andric class Declaration;
290b57cec5SDimitry Andric }
300b57cec5SDimitry Andric 
310b57cec5SDimitry Andric using namespace lldb_private;
320b57cec5SDimitry Andric 
330b57cec5SDimitry Andric ValueObjectDynamicValue::ValueObjectDynamicValue(
340b57cec5SDimitry Andric     ValueObject &parent, lldb::DynamicValueType use_dynamic)
350b57cec5SDimitry Andric     : ValueObject(parent), m_address(), m_dynamic_type_info(),
360b57cec5SDimitry Andric       m_use_dynamic(use_dynamic) {
370b57cec5SDimitry Andric   SetName(parent.GetName());
380b57cec5SDimitry Andric }
390b57cec5SDimitry Andric 
400b57cec5SDimitry Andric CompilerType ValueObjectDynamicValue::GetCompilerTypeImpl() {
410b57cec5SDimitry Andric   const bool success = UpdateValueIfNeeded(false);
420b57cec5SDimitry Andric   if (success) {
430b57cec5SDimitry Andric     if (m_dynamic_type_info.HasType())
440b57cec5SDimitry Andric       return m_value.GetCompilerType();
450b57cec5SDimitry Andric     else
460b57cec5SDimitry Andric       return m_parent->GetCompilerType();
470b57cec5SDimitry Andric   }
480b57cec5SDimitry Andric   return m_parent->GetCompilerType();
490b57cec5SDimitry Andric }
500b57cec5SDimitry Andric 
510b57cec5SDimitry Andric ConstString ValueObjectDynamicValue::GetTypeName() {
520b57cec5SDimitry Andric   const bool success = UpdateValueIfNeeded(false);
530b57cec5SDimitry Andric   if (success) {
540b57cec5SDimitry Andric     if (m_dynamic_type_info.HasName())
550b57cec5SDimitry Andric       return m_dynamic_type_info.GetName();
560b57cec5SDimitry Andric   }
570b57cec5SDimitry Andric   return m_parent->GetTypeName();
580b57cec5SDimitry Andric }
590b57cec5SDimitry Andric 
600b57cec5SDimitry Andric TypeImpl ValueObjectDynamicValue::GetTypeImpl() {
610b57cec5SDimitry Andric   const bool success = UpdateValueIfNeeded(false);
620b57cec5SDimitry Andric   if (success && m_type_impl.IsValid()) {
630b57cec5SDimitry Andric     return m_type_impl;
640b57cec5SDimitry Andric   }
650b57cec5SDimitry Andric   return m_parent->GetTypeImpl();
660b57cec5SDimitry Andric }
670b57cec5SDimitry Andric 
680b57cec5SDimitry Andric ConstString ValueObjectDynamicValue::GetQualifiedTypeName() {
690b57cec5SDimitry Andric   const bool success = UpdateValueIfNeeded(false);
700b57cec5SDimitry Andric   if (success) {
710b57cec5SDimitry Andric     if (m_dynamic_type_info.HasName())
720b57cec5SDimitry Andric       return m_dynamic_type_info.GetName();
730b57cec5SDimitry Andric   }
740b57cec5SDimitry Andric   return m_parent->GetQualifiedTypeName();
750b57cec5SDimitry Andric }
760b57cec5SDimitry Andric 
770b57cec5SDimitry Andric ConstString ValueObjectDynamicValue::GetDisplayTypeName() {
780b57cec5SDimitry Andric   const bool success = UpdateValueIfNeeded(false);
790b57cec5SDimitry Andric   if (success) {
800b57cec5SDimitry Andric     if (m_dynamic_type_info.HasType())
810b57cec5SDimitry Andric       return GetCompilerType().GetDisplayTypeName();
820b57cec5SDimitry Andric     if (m_dynamic_type_info.HasName())
830b57cec5SDimitry Andric       return m_dynamic_type_info.GetName();
840b57cec5SDimitry Andric   }
850b57cec5SDimitry Andric   return m_parent->GetDisplayTypeName();
860b57cec5SDimitry Andric }
870b57cec5SDimitry Andric 
88*0fca6ea1SDimitry Andric llvm::Expected<uint32_t>
89*0fca6ea1SDimitry Andric ValueObjectDynamicValue::CalculateNumChildren(uint32_t max) {
900b57cec5SDimitry Andric   const bool success = UpdateValueIfNeeded(false);
910b57cec5SDimitry Andric   if (success && m_dynamic_type_info.HasType()) {
920b57cec5SDimitry Andric     ExecutionContext exe_ctx(GetExecutionContextRef());
930b57cec5SDimitry Andric     auto children_count = GetCompilerType().GetNumChildren(true, &exe_ctx);
94*0fca6ea1SDimitry Andric     if (!children_count)
95*0fca6ea1SDimitry Andric       return children_count;
96*0fca6ea1SDimitry Andric     return *children_count <= max ? *children_count : max;
970b57cec5SDimitry Andric   } else
980b57cec5SDimitry Andric     return m_parent->GetNumChildren(max);
990b57cec5SDimitry Andric }
1000b57cec5SDimitry Andric 
101bdd1243dSDimitry Andric std::optional<uint64_t> ValueObjectDynamicValue::GetByteSize() {
1020b57cec5SDimitry Andric   const bool success = UpdateValueIfNeeded(false);
1030b57cec5SDimitry Andric   if (success && m_dynamic_type_info.HasType()) {
1040b57cec5SDimitry Andric     ExecutionContext exe_ctx(GetExecutionContextRef());
1050b57cec5SDimitry Andric     return m_value.GetValueByteSize(nullptr, &exe_ctx);
1060b57cec5SDimitry Andric   } else
1070b57cec5SDimitry Andric     return m_parent->GetByteSize();
1080b57cec5SDimitry Andric }
1090b57cec5SDimitry Andric 
1100b57cec5SDimitry Andric lldb::ValueType ValueObjectDynamicValue::GetValueType() const {
1110b57cec5SDimitry Andric   return m_parent->GetValueType();
1120b57cec5SDimitry Andric }
1130b57cec5SDimitry Andric 
1140b57cec5SDimitry Andric bool ValueObjectDynamicValue::UpdateValue() {
1150b57cec5SDimitry Andric   SetValueIsValid(false);
1160b57cec5SDimitry Andric   m_error.Clear();
1170b57cec5SDimitry Andric 
1180b57cec5SDimitry Andric   if (!m_parent->UpdateValueIfNeeded(false)) {
1190b57cec5SDimitry Andric     // The dynamic value failed to get an error, pass the error along
1200b57cec5SDimitry Andric     if (m_error.Success() && m_parent->GetError().Fail())
1210b57cec5SDimitry Andric       m_error = m_parent->GetError();
1220b57cec5SDimitry Andric     return false;
1230b57cec5SDimitry Andric   }
1240b57cec5SDimitry Andric 
1250b57cec5SDimitry Andric   // Setting our type_sp to NULL will route everything back through our parent
1260b57cec5SDimitry Andric   // which is equivalent to not using dynamic values.
1270b57cec5SDimitry Andric   if (m_use_dynamic == lldb::eNoDynamicValues) {
1280b57cec5SDimitry Andric     m_dynamic_type_info.Clear();
1290b57cec5SDimitry Andric     return true;
1300b57cec5SDimitry Andric   }
1310b57cec5SDimitry Andric 
1320b57cec5SDimitry Andric   ExecutionContext exe_ctx(GetExecutionContextRef());
1330b57cec5SDimitry Andric   Target *target = exe_ctx.GetTargetPtr();
1340b57cec5SDimitry Andric   if (target) {
1350b57cec5SDimitry Andric     m_data.SetByteOrder(target->GetArchitecture().GetByteOrder());
1360b57cec5SDimitry Andric     m_data.SetAddressByteSize(target->GetArchitecture().GetAddressByteSize());
1370b57cec5SDimitry Andric   }
1380b57cec5SDimitry Andric 
1390b57cec5SDimitry Andric   // First make sure our Type and/or Address haven't changed:
1400b57cec5SDimitry Andric   Process *process = exe_ctx.GetProcessPtr();
1410b57cec5SDimitry Andric   if (!process)
1420b57cec5SDimitry Andric     return false;
1430b57cec5SDimitry Andric 
1440b57cec5SDimitry Andric   TypeAndOrName class_type_or_name;
1450b57cec5SDimitry Andric   Address dynamic_address;
1460b57cec5SDimitry Andric   bool found_dynamic_type = false;
1470b57cec5SDimitry Andric   Value::ValueType value_type;
1480b57cec5SDimitry Andric 
1490b57cec5SDimitry Andric   LanguageRuntime *runtime = nullptr;
1500b57cec5SDimitry Andric 
1510b57cec5SDimitry Andric   lldb::LanguageType known_type = m_parent->GetObjectRuntimeLanguage();
1520b57cec5SDimitry Andric   if (known_type != lldb::eLanguageTypeUnknown &&
1530b57cec5SDimitry Andric       known_type != lldb::eLanguageTypeC) {
1540b57cec5SDimitry Andric     runtime = process->GetLanguageRuntime(known_type);
15506c3fb27SDimitry Andric     if (auto *preferred_runtime =
15606c3fb27SDimitry Andric             runtime->GetPreferredLanguageRuntime(*m_parent)) {
15706c3fb27SDimitry Andric       // Try the preferred runtime first.
15806c3fb27SDimitry Andric       found_dynamic_type = preferred_runtime->GetDynamicTypeAndAddress(
15906c3fb27SDimitry Andric           *m_parent, m_use_dynamic, class_type_or_name, dynamic_address,
16006c3fb27SDimitry Andric           value_type);
16106c3fb27SDimitry Andric       if (found_dynamic_type)
16206c3fb27SDimitry Andric         // Set the operative `runtime` for later use in this function.
16306c3fb27SDimitry Andric         runtime = preferred_runtime;
16406c3fb27SDimitry Andric     }
16506c3fb27SDimitry Andric     if (!found_dynamic_type)
16606c3fb27SDimitry Andric       // Fallback to the runtime for `known_type`.
1670b57cec5SDimitry Andric       found_dynamic_type = runtime->GetDynamicTypeAndAddress(
1680b57cec5SDimitry Andric           *m_parent, m_use_dynamic, class_type_or_name, dynamic_address,
1690b57cec5SDimitry Andric           value_type);
1700b57cec5SDimitry Andric   } else {
1710b57cec5SDimitry Andric     runtime = process->GetLanguageRuntime(lldb::eLanguageTypeC_plus_plus);
1720b57cec5SDimitry Andric     if (runtime)
1730b57cec5SDimitry Andric       found_dynamic_type = runtime->GetDynamicTypeAndAddress(
1740b57cec5SDimitry Andric           *m_parent, m_use_dynamic, class_type_or_name, dynamic_address,
1750b57cec5SDimitry Andric           value_type);
1760b57cec5SDimitry Andric 
1770b57cec5SDimitry Andric     if (!found_dynamic_type) {
1780b57cec5SDimitry Andric       runtime = process->GetLanguageRuntime(lldb::eLanguageTypeObjC);
1790b57cec5SDimitry Andric       if (runtime)
1800b57cec5SDimitry Andric         found_dynamic_type = runtime->GetDynamicTypeAndAddress(
1810b57cec5SDimitry Andric             *m_parent, m_use_dynamic, class_type_or_name, dynamic_address,
1820b57cec5SDimitry Andric             value_type);
1830b57cec5SDimitry Andric     }
1840b57cec5SDimitry Andric   }
1850b57cec5SDimitry Andric 
1860b57cec5SDimitry Andric   // Getting the dynamic value may have run the program a bit, and so marked us
1870b57cec5SDimitry Andric   // as needing updating, but we really don't...
1880b57cec5SDimitry Andric 
1890b57cec5SDimitry Andric   m_update_point.SetUpdated();
1900b57cec5SDimitry Andric 
1910b57cec5SDimitry Andric   if (runtime && found_dynamic_type) {
1920b57cec5SDimitry Andric     if (class_type_or_name.HasType()) {
1930b57cec5SDimitry Andric       m_type_impl =
1940b57cec5SDimitry Andric           TypeImpl(m_parent->GetCompilerType(),
1950b57cec5SDimitry Andric                    runtime->FixUpDynamicType(class_type_or_name, *m_parent)
1960b57cec5SDimitry Andric                        .GetCompilerType());
1970b57cec5SDimitry Andric     } else {
1980b57cec5SDimitry Andric       m_type_impl.Clear();
1990b57cec5SDimitry Andric     }
2000b57cec5SDimitry Andric   } else {
2010b57cec5SDimitry Andric     m_type_impl.Clear();
2020b57cec5SDimitry Andric   }
2030b57cec5SDimitry Andric 
20406c3fb27SDimitry Andric   // If we don't have a dynamic type, set ourselves to be invalid and return
20506c3fb27SDimitry Andric   // false.  We used to try to produce a dynamic ValueObject that behaved "like"
20606c3fb27SDimitry Andric   // its parent, but that failed for ValueObjectConstResult, which is too
20706c3fb27SDimitry Andric   // complex a beast to try to emulate.  If we return an invalid ValueObject,
20806c3fb27SDimitry Andric   // clients will end up getting the static value instead, which behaves
20906c3fb27SDimitry Andric   // correctly.
2100b57cec5SDimitry Andric   if (!found_dynamic_type) {
2110b57cec5SDimitry Andric     if (m_dynamic_type_info)
2120b57cec5SDimitry Andric       SetValueDidChange(true);
2130b57cec5SDimitry Andric     ClearDynamicTypeInformation();
2140b57cec5SDimitry Andric     m_dynamic_type_info.Clear();
21506c3fb27SDimitry Andric     m_error.SetErrorString("no dynamic type found");
21606c3fb27SDimitry Andric     return false;
2170b57cec5SDimitry Andric   }
2180b57cec5SDimitry Andric 
2190b57cec5SDimitry Andric   Value old_value(m_value);
2200b57cec5SDimitry Andric 
22181ad6265SDimitry Andric   Log *log = GetLog(LLDBLog::Types);
2220b57cec5SDimitry Andric 
2230b57cec5SDimitry Andric   bool has_changed_type = false;
2240b57cec5SDimitry Andric 
2250b57cec5SDimitry Andric   if (!m_dynamic_type_info) {
2260b57cec5SDimitry Andric     m_dynamic_type_info = class_type_or_name;
2270b57cec5SDimitry Andric     has_changed_type = true;
2280b57cec5SDimitry Andric   } else if (class_type_or_name != m_dynamic_type_info) {
2290b57cec5SDimitry Andric     // We are another type, we need to tear down our children...
2300b57cec5SDimitry Andric     m_dynamic_type_info = class_type_or_name;
2310b57cec5SDimitry Andric     SetValueDidChange(true);
2320b57cec5SDimitry Andric     has_changed_type = true;
2330b57cec5SDimitry Andric   }
2340b57cec5SDimitry Andric 
2350b57cec5SDimitry Andric   if (has_changed_type)
2360b57cec5SDimitry Andric     ClearDynamicTypeInformation();
2370b57cec5SDimitry Andric 
2380b57cec5SDimitry Andric   if (!m_address.IsValid() || m_address != dynamic_address) {
2390b57cec5SDimitry Andric     if (m_address.IsValid())
2400b57cec5SDimitry Andric       SetValueDidChange(true);
2410b57cec5SDimitry Andric 
2420b57cec5SDimitry Andric     // We've moved, so we should be fine...
2430b57cec5SDimitry Andric     m_address = dynamic_address;
2440b57cec5SDimitry Andric     lldb::TargetSP target_sp(GetTargetSP());
2450b57cec5SDimitry Andric     lldb::addr_t load_address = m_address.GetLoadAddress(target_sp.get());
2460b57cec5SDimitry Andric     m_value.GetScalar() = load_address;
2470b57cec5SDimitry Andric   }
2480b57cec5SDimitry Andric 
2490b57cec5SDimitry Andric   if (runtime)
2500b57cec5SDimitry Andric     m_dynamic_type_info =
2510b57cec5SDimitry Andric         runtime->FixUpDynamicType(m_dynamic_type_info, *m_parent);
2520b57cec5SDimitry Andric 
2530b57cec5SDimitry Andric   m_value.SetCompilerType(m_dynamic_type_info.GetCompilerType());
2540b57cec5SDimitry Andric 
2550b57cec5SDimitry Andric   m_value.SetValueType(value_type);
2560b57cec5SDimitry Andric 
2570b57cec5SDimitry Andric   if (has_changed_type && log)
2589dba64beSDimitry Andric     LLDB_LOGF(log, "[%s %p] has a new dynamic type %s", GetName().GetCString(),
2590b57cec5SDimitry Andric               static_cast<void *>(this), GetTypeName().GetCString());
2600b57cec5SDimitry Andric 
2610b57cec5SDimitry Andric   if (m_address.IsValid() && m_dynamic_type_info) {
2620b57cec5SDimitry Andric     // The variable value is in the Scalar value inside the m_value. We can
2630b57cec5SDimitry Andric     // point our m_data right to it.
2649dba64beSDimitry Andric     m_error = m_value.GetValueAsData(&exe_ctx, m_data, GetModule().get());
2650b57cec5SDimitry Andric     if (m_error.Success()) {
2660b57cec5SDimitry Andric       if (!CanProvideValue()) {
2670b57cec5SDimitry Andric         // this value object represents an aggregate type whose children have
2680b57cec5SDimitry Andric         // values, but this object does not. So we say we are changed if our
2690b57cec5SDimitry Andric         // location has changed.
2700b57cec5SDimitry Andric         SetValueDidChange(m_value.GetValueType() != old_value.GetValueType() ||
2710b57cec5SDimitry Andric                           m_value.GetScalar() != old_value.GetScalar());
2720b57cec5SDimitry Andric       }
2730b57cec5SDimitry Andric 
2740b57cec5SDimitry Andric       SetValueIsValid(true);
2750b57cec5SDimitry Andric       return true;
2760b57cec5SDimitry Andric     }
2770b57cec5SDimitry Andric   }
2780b57cec5SDimitry Andric 
2790b57cec5SDimitry Andric   // We get here if we've failed above...
2800b57cec5SDimitry Andric   SetValueIsValid(false);
2810b57cec5SDimitry Andric   return false;
2820b57cec5SDimitry Andric }
2830b57cec5SDimitry Andric 
2840b57cec5SDimitry Andric bool ValueObjectDynamicValue::IsInScope() { return m_parent->IsInScope(); }
2850b57cec5SDimitry Andric 
2860b57cec5SDimitry Andric bool ValueObjectDynamicValue::SetValueFromCString(const char *value_str,
2870b57cec5SDimitry Andric                                                   Status &error) {
2880b57cec5SDimitry Andric   if (!UpdateValueIfNeeded(false)) {
2890b57cec5SDimitry Andric     error.SetErrorString("unable to read value");
2900b57cec5SDimitry Andric     return false;
2910b57cec5SDimitry Andric   }
2920b57cec5SDimitry Andric 
2930b57cec5SDimitry Andric   uint64_t my_value = GetValueAsUnsigned(UINT64_MAX);
2940b57cec5SDimitry Andric   uint64_t parent_value = m_parent->GetValueAsUnsigned(UINT64_MAX);
2950b57cec5SDimitry Andric 
2960b57cec5SDimitry Andric   if (my_value == UINT64_MAX || parent_value == UINT64_MAX) {
2970b57cec5SDimitry Andric     error.SetErrorString("unable to read value");
2980b57cec5SDimitry Andric     return false;
2990b57cec5SDimitry Andric   }
3000b57cec5SDimitry Andric 
3010b57cec5SDimitry Andric   // if we are at an offset from our parent, in order to set ourselves
3020b57cec5SDimitry Andric   // correctly we would need to change the new value so that it refers to the
3030b57cec5SDimitry Andric   // correct dynamic type. we choose not to deal with that - if anything more
3040b57cec5SDimitry Andric   // than a value overwrite is required, you should be using the expression
3050b57cec5SDimitry Andric   // parser instead of the value editing facility
3060b57cec5SDimitry Andric   if (my_value != parent_value) {
3070b57cec5SDimitry Andric     // but NULL'ing out a value should always be allowed
3080b57cec5SDimitry Andric     if (strcmp(value_str, "0")) {
3090b57cec5SDimitry Andric       error.SetErrorString(
3100b57cec5SDimitry Andric           "unable to modify dynamic value, use 'expression' command");
3110b57cec5SDimitry Andric       return false;
3120b57cec5SDimitry Andric     }
3130b57cec5SDimitry Andric   }
3140b57cec5SDimitry Andric 
3150b57cec5SDimitry Andric   bool ret_val = m_parent->SetValueFromCString(value_str, error);
3160b57cec5SDimitry Andric   SetNeedsUpdate();
3170b57cec5SDimitry Andric   return ret_val;
3180b57cec5SDimitry Andric }
3190b57cec5SDimitry Andric 
3200b57cec5SDimitry Andric bool ValueObjectDynamicValue::SetData(DataExtractor &data, Status &error) {
3210b57cec5SDimitry Andric   if (!UpdateValueIfNeeded(false)) {
3220b57cec5SDimitry Andric     error.SetErrorString("unable to read value");
3230b57cec5SDimitry Andric     return false;
3240b57cec5SDimitry Andric   }
3250b57cec5SDimitry Andric 
3260b57cec5SDimitry Andric   uint64_t my_value = GetValueAsUnsigned(UINT64_MAX);
3270b57cec5SDimitry Andric   uint64_t parent_value = m_parent->GetValueAsUnsigned(UINT64_MAX);
3280b57cec5SDimitry Andric 
3290b57cec5SDimitry Andric   if (my_value == UINT64_MAX || parent_value == UINT64_MAX) {
3300b57cec5SDimitry Andric     error.SetErrorString("unable to read value");
3310b57cec5SDimitry Andric     return false;
3320b57cec5SDimitry Andric   }
3330b57cec5SDimitry Andric 
3340b57cec5SDimitry Andric   // if we are at an offset from our parent, in order to set ourselves
3350b57cec5SDimitry Andric   // correctly we would need to change the new value so that it refers to the
3360b57cec5SDimitry Andric   // correct dynamic type. we choose not to deal with that - if anything more
3370b57cec5SDimitry Andric   // than a value overwrite is required, you should be using the expression
3380b57cec5SDimitry Andric   // parser instead of the value editing facility
3390b57cec5SDimitry Andric   if (my_value != parent_value) {
3400b57cec5SDimitry Andric     // but NULL'ing out a value should always be allowed
3410b57cec5SDimitry Andric     lldb::offset_t offset = 0;
3420b57cec5SDimitry Andric 
3435ffd83dbSDimitry Andric     if (data.GetAddress(&offset) != 0) {
3440b57cec5SDimitry Andric       error.SetErrorString(
3450b57cec5SDimitry Andric           "unable to modify dynamic value, use 'expression' command");
3460b57cec5SDimitry Andric       return false;
3470b57cec5SDimitry Andric     }
3480b57cec5SDimitry Andric   }
3490b57cec5SDimitry Andric 
3500b57cec5SDimitry Andric   bool ret_val = m_parent->SetData(data, error);
3510b57cec5SDimitry Andric   SetNeedsUpdate();
3520b57cec5SDimitry Andric   return ret_val;
3530b57cec5SDimitry Andric }
3540b57cec5SDimitry Andric 
3550b57cec5SDimitry Andric void ValueObjectDynamicValue::SetPreferredDisplayLanguage(
3560b57cec5SDimitry Andric     lldb::LanguageType lang) {
3570b57cec5SDimitry Andric   this->ValueObject::SetPreferredDisplayLanguage(lang);
3580b57cec5SDimitry Andric   if (m_parent)
3590b57cec5SDimitry Andric     m_parent->SetPreferredDisplayLanguage(lang);
3600b57cec5SDimitry Andric }
3610b57cec5SDimitry Andric 
3620b57cec5SDimitry Andric lldb::LanguageType ValueObjectDynamicValue::GetPreferredDisplayLanguage() {
3630b57cec5SDimitry Andric   if (m_preferred_display_language == lldb::eLanguageTypeUnknown) {
3640b57cec5SDimitry Andric     if (m_parent)
3650b57cec5SDimitry Andric       return m_parent->GetPreferredDisplayLanguage();
3660b57cec5SDimitry Andric     return lldb::eLanguageTypeUnknown;
3670b57cec5SDimitry Andric   } else
3680b57cec5SDimitry Andric     return m_preferred_display_language;
3690b57cec5SDimitry Andric }
3700b57cec5SDimitry Andric 
3710b57cec5SDimitry Andric bool ValueObjectDynamicValue::IsSyntheticChildrenGenerated() {
3720b57cec5SDimitry Andric   if (m_parent)
3730b57cec5SDimitry Andric     return m_parent->IsSyntheticChildrenGenerated();
3740b57cec5SDimitry Andric   return false;
3750b57cec5SDimitry Andric }
3760b57cec5SDimitry Andric 
3770b57cec5SDimitry Andric void ValueObjectDynamicValue::SetSyntheticChildrenGenerated(bool b) {
3780b57cec5SDimitry Andric   if (m_parent)
3790b57cec5SDimitry Andric     m_parent->SetSyntheticChildrenGenerated(b);
3800b57cec5SDimitry Andric   this->ValueObject::SetSyntheticChildrenGenerated(b);
3810b57cec5SDimitry Andric }
3820b57cec5SDimitry Andric 
3830b57cec5SDimitry Andric bool ValueObjectDynamicValue::GetDeclaration(Declaration &decl) {
3840b57cec5SDimitry Andric   if (m_parent)
3850b57cec5SDimitry Andric     return m_parent->GetDeclaration(decl);
3860b57cec5SDimitry Andric 
3870b57cec5SDimitry Andric   return ValueObject::GetDeclaration(decl);
3880b57cec5SDimitry Andric }
3890b57cec5SDimitry Andric 
3900b57cec5SDimitry Andric uint64_t ValueObjectDynamicValue::GetLanguageFlags() {
3910b57cec5SDimitry Andric   if (m_parent)
3920b57cec5SDimitry Andric     return m_parent->GetLanguageFlags();
3930b57cec5SDimitry Andric   return this->ValueObject::GetLanguageFlags();
3940b57cec5SDimitry Andric }
3950b57cec5SDimitry Andric 
3960b57cec5SDimitry Andric void ValueObjectDynamicValue::SetLanguageFlags(uint64_t flags) {
3970b57cec5SDimitry Andric   if (m_parent)
3980b57cec5SDimitry Andric     m_parent->SetLanguageFlags(flags);
3990b57cec5SDimitry Andric   else
4000b57cec5SDimitry Andric     this->ValueObject::SetLanguageFlags(flags);
4010b57cec5SDimitry Andric }
402