178a685aaSJim Ingham //===-- ValueObjectDynamicValue.cpp ---------------------------------*- C++ -*-===// 278a685aaSJim Ingham // 378a685aaSJim Ingham // The LLVM Compiler Infrastructure 478a685aaSJim Ingham // 578a685aaSJim Ingham // This file is distributed under the University of Illinois Open Source 678a685aaSJim Ingham // License. See LICENSE.TXT for details. 778a685aaSJim Ingham // 878a685aaSJim Ingham //===----------------------------------------------------------------------===// 978a685aaSJim Ingham 1078a685aaSJim Ingham 1178a685aaSJim Ingham #include "lldb/Core/ValueObjectDynamicValue.h" 1278a685aaSJim Ingham 1378a685aaSJim Ingham // C Includes 1478a685aaSJim Ingham // C++ Includes 1578a685aaSJim Ingham // Other libraries and framework includes 1678a685aaSJim Ingham // Project includes 17d228483dSEnrico Granata #include "lldb/Core/Log.h" 1878a685aaSJim Ingham #include "lldb/Core/Module.h" 1978a685aaSJim Ingham #include "lldb/Core/ValueObjectList.h" 2078a685aaSJim Ingham #include "lldb/Core/Value.h" 2178a685aaSJim Ingham #include "lldb/Core/ValueObject.h" 2278a685aaSJim Ingham 2321fd13f9SEnrico Granata #include "lldb/Symbol/ClangASTType.h" 2478a685aaSJim Ingham #include "lldb/Symbol/ObjectFile.h" 2578a685aaSJim Ingham #include "lldb/Symbol/SymbolContext.h" 2678a685aaSJim Ingham #include "lldb/Symbol/Type.h" 2778a685aaSJim Ingham #include "lldb/Symbol/Variable.h" 2878a685aaSJim Ingham 2978a685aaSJim Ingham #include "lldb/Target/ExecutionContext.h" 3078a685aaSJim Ingham #include "lldb/Target/LanguageRuntime.h" 3178a685aaSJim Ingham #include "lldb/Target/Process.h" 3278a685aaSJim Ingham #include "lldb/Target/RegisterContext.h" 3378a685aaSJim Ingham #include "lldb/Target/Target.h" 3478a685aaSJim Ingham #include "lldb/Target/Thread.h" 3578a685aaSJim Ingham 3678a685aaSJim Ingham using namespace lldb_private; 3778a685aaSJim Ingham 382837b766SJim Ingham ValueObjectDynamicValue::ValueObjectDynamicValue (ValueObject &parent, lldb::DynamicValueType use_dynamic) : 3978a685aaSJim Ingham ValueObject(parent), 4078a685aaSJim Ingham m_address (), 41f7b1a34eSEnrico Granata m_dynamic_type_info(), 422837b766SJim Ingham m_use_dynamic (use_dynamic) 4378a685aaSJim Ingham { 446f3533fbSEnrico Granata SetName (parent.GetName()); 4578a685aaSJim Ingham } 4678a685aaSJim Ingham 4778a685aaSJim Ingham ValueObjectDynamicValue::~ValueObjectDynamicValue() 4878a685aaSJim Ingham { 4978a685aaSJim Ingham m_owning_valobj_sp.reset(); 5078a685aaSJim Ingham } 5178a685aaSJim Ingham 5257ee3067SGreg Clayton ClangASTType 537277284fSSean Callanan ValueObjectDynamicValue::GetClangTypeImpl () 5478a685aaSJim Ingham { 55dc4db5a6SEnrico Granata const bool success = UpdateValueIfNeeded(false); 56dc4db5a6SEnrico Granata if (success) 57dc4db5a6SEnrico Granata { 58dc4db5a6SEnrico Granata if (m_dynamic_type_info.HasType()) 5978a685aaSJim Ingham return m_value.GetClangType(); 6078a685aaSJim Ingham else 6178a685aaSJim Ingham return m_parent->GetClangType(); 6278a685aaSJim Ingham } 63dc4db5a6SEnrico Granata return m_parent->GetClangType(); 64dc4db5a6SEnrico Granata } 6578a685aaSJim Ingham 6678a685aaSJim Ingham ConstString 6778a685aaSJim Ingham ValueObjectDynamicValue::GetTypeName() 6878a685aaSJim Ingham { 69c3e320a7SEnrico Granata const bool success = UpdateValueIfNeeded(false); 70f7b1a34eSEnrico Granata if (success) 71f7b1a34eSEnrico Granata { 72f7b1a34eSEnrico Granata if (m_dynamic_type_info.HasName()) 73f7b1a34eSEnrico Granata return m_dynamic_type_info.GetName(); 74*fcf0c4e3SEnrico Granata if (m_dynamic_type_info.HasType()) 75*fcf0c4e3SEnrico Granata return GetClangType().GetConstTypeName(); 76f7b1a34eSEnrico Granata } 77f7b1a34eSEnrico Granata return m_parent->GetTypeName(); 78f7b1a34eSEnrico Granata } 79f7b1a34eSEnrico Granata 80dc4db5a6SEnrico Granata TypeImpl 81dc4db5a6SEnrico Granata ValueObjectDynamicValue::GetTypeImpl () 82dc4db5a6SEnrico Granata { 83dc4db5a6SEnrico Granata const bool success = UpdateValueIfNeeded(false); 84df7c7f99SEnrico Granata if (success && m_type_impl.IsValid()) 85dc4db5a6SEnrico Granata { 86dc4db5a6SEnrico Granata return m_type_impl; 87dc4db5a6SEnrico Granata } 88dc4db5a6SEnrico Granata return m_parent->GetTypeImpl(); 89dc4db5a6SEnrico Granata } 90dc4db5a6SEnrico Granata 91f7b1a34eSEnrico Granata ConstString 92f7b1a34eSEnrico Granata ValueObjectDynamicValue::GetQualifiedTypeName() 93f7b1a34eSEnrico Granata { 94f7b1a34eSEnrico Granata const bool success = UpdateValueIfNeeded(false); 95f7b1a34eSEnrico Granata if (success) 96f7b1a34eSEnrico Granata { 97f7b1a34eSEnrico Granata if (m_dynamic_type_info.HasName()) 98f7b1a34eSEnrico Granata return m_dynamic_type_info.GetName(); 99*fcf0c4e3SEnrico Granata if (m_dynamic_type_info.HasType()) 100*fcf0c4e3SEnrico Granata return GetClangType().GetConstQualifiedTypeName (); 101f7b1a34eSEnrico Granata } 10278a685aaSJim Ingham return m_parent->GetTypeName(); 10378a685aaSJim Ingham } 10478a685aaSJim Ingham 105c7bece56SGreg Clayton size_t 10678a685aaSJim Ingham ValueObjectDynamicValue::CalculateNumChildren() 10778a685aaSJim Ingham { 108c3e320a7SEnrico Granata const bool success = UpdateValueIfNeeded(false); 109dc4db5a6SEnrico Granata if (success && m_dynamic_type_info.HasType()) 11057ee3067SGreg Clayton return GetClangType().GetNumChildren (true); 11178a685aaSJim Ingham else 11278a685aaSJim Ingham return m_parent->GetNumChildren(); 11378a685aaSJim Ingham } 11478a685aaSJim Ingham 115faac1118SGreg Clayton uint64_t 11678a685aaSJim Ingham ValueObjectDynamicValue::GetByteSize() 11778a685aaSJim Ingham { 118c3e320a7SEnrico Granata const bool success = UpdateValueIfNeeded(false); 119dc4db5a6SEnrico Granata if (success && m_dynamic_type_info.HasType()) 12057ee3067SGreg Clayton return m_value.GetValueByteSize(NULL); 12178a685aaSJim Ingham else 12278a685aaSJim Ingham return m_parent->GetByteSize(); 12378a685aaSJim Ingham } 12478a685aaSJim Ingham 12578a685aaSJim Ingham lldb::ValueType 12678a685aaSJim Ingham ValueObjectDynamicValue::GetValueType() const 12778a685aaSJim Ingham { 12878a685aaSJim Ingham return m_parent->GetValueType(); 12978a685aaSJim Ingham } 13078a685aaSJim Ingham 131dc4db5a6SEnrico Granata 132dc4db5a6SEnrico Granata static TypeAndOrName 133dc4db5a6SEnrico Granata FixupTypeAndOrName (const TypeAndOrName& type_andor_name, 134dc4db5a6SEnrico Granata ValueObject& parent) 135dc4db5a6SEnrico Granata { 136dc4db5a6SEnrico Granata TypeAndOrName ret(type_andor_name); 137dc4db5a6SEnrico Granata if (type_andor_name.HasType()) 138dc4db5a6SEnrico Granata { 139dc4db5a6SEnrico Granata // The type will always be the type of the dynamic object. If our parent's type was a pointer, 140dc4db5a6SEnrico Granata // then our type should be a pointer to the type of the dynamic object. If a reference, then the original type 141dc4db5a6SEnrico Granata // should be okay... 142dc4db5a6SEnrico Granata ClangASTType orig_type = type_andor_name.GetClangASTType(); 143dc4db5a6SEnrico Granata ClangASTType corrected_type = orig_type; 144dc4db5a6SEnrico Granata if (parent.IsPointerType()) 145dc4db5a6SEnrico Granata corrected_type = orig_type.GetPointerType (); 146dc4db5a6SEnrico Granata else if (parent.IsPointerOrReferenceType()) 147dc4db5a6SEnrico Granata corrected_type = orig_type.GetLValueReferenceType (); 148dc4db5a6SEnrico Granata ret.SetClangASTType(corrected_type); 149dc4db5a6SEnrico Granata } 150dc4db5a6SEnrico Granata else /*if (m_dynamic_type_info.HasName())*/ 151dc4db5a6SEnrico Granata { 152dc4db5a6SEnrico Granata // If we are here we need to adjust our dynamic type name to include the correct & or * symbol 153dc4db5a6SEnrico Granata std::string corrected_name (type_andor_name.GetName().GetCString()); 154dc4db5a6SEnrico Granata if (parent.IsPointerType()) 155dc4db5a6SEnrico Granata corrected_name.append(" *"); 156dc4db5a6SEnrico Granata else if (parent.IsPointerOrReferenceType()) 157dc4db5a6SEnrico Granata corrected_name.append(" &"); 158*fcf0c4e3SEnrico Granata // the parent type should be a correctly pointer'ed or referenc'ed type 159*fcf0c4e3SEnrico Granata ret.SetClangASTType(parent.GetClangType()); 160dc4db5a6SEnrico Granata ret.SetName(corrected_name.c_str()); 161dc4db5a6SEnrico Granata } 162dc4db5a6SEnrico Granata return ret; 163dc4db5a6SEnrico Granata } 164dc4db5a6SEnrico Granata 16578a685aaSJim Ingham bool 16678a685aaSJim Ingham ValueObjectDynamicValue::UpdateValue () 16778a685aaSJim Ingham { 16878a685aaSJim Ingham SetValueIsValid (false); 16978a685aaSJim Ingham m_error.Clear(); 17078a685aaSJim Ingham 171c3e320a7SEnrico Granata if (!m_parent->UpdateValueIfNeeded(false)) 17278a685aaSJim Ingham { 173007d5be6SGreg Clayton // The dynamic value failed to get an error, pass the error along 174007d5be6SGreg Clayton if (m_error.Success() && m_parent->GetError().Fail()) 175007d5be6SGreg Clayton m_error = m_parent->GetError(); 17678a685aaSJim Ingham return false; 17778a685aaSJim Ingham } 17878a685aaSJim Ingham 1792837b766SJim Ingham // Setting our type_sp to NULL will route everything back through our 1802837b766SJim Ingham // parent which is equivalent to not using dynamic values. 1812837b766SJim Ingham if (m_use_dynamic == lldb::eNoDynamicValues) 1822837b766SJim Ingham { 183f7b1a34eSEnrico Granata m_dynamic_type_info.Clear(); 1842837b766SJim Ingham return true; 1852837b766SJim Ingham } 1862837b766SJim Ingham 187cc4d0146SGreg Clayton ExecutionContext exe_ctx (GetExecutionContextRef()); 188c14ee32dSGreg Clayton Target *target = exe_ctx.GetTargetPtr(); 189c14ee32dSGreg Clayton if (target) 19078a685aaSJim Ingham { 191c14ee32dSGreg Clayton m_data.SetByteOrder(target->GetArchitecture().GetByteOrder()); 192c14ee32dSGreg Clayton m_data.SetAddressByteSize(target->GetArchitecture().GetAddressByteSize()); 19378a685aaSJim Ingham } 19478a685aaSJim Ingham 19578a685aaSJim Ingham // First make sure our Type and/or Address haven't changed: 196cc4d0146SGreg Clayton Process *process = exe_ctx.GetProcessPtr(); 19778a685aaSJim Ingham if (!process) 19878a685aaSJim Ingham return false; 19978a685aaSJim Ingham 20061be0903SJim Ingham TypeAndOrName class_type_or_name; 20178a685aaSJim Ingham Address dynamic_address; 20278a685aaSJim Ingham bool found_dynamic_type = false; 20378a685aaSJim Ingham 20478a685aaSJim Ingham lldb::LanguageType known_type = m_parent->GetObjectRuntimeLanguage(); 20578a685aaSJim Ingham if (known_type != lldb::eLanguageTypeUnknown && known_type != lldb::eLanguageTypeC) 20678a685aaSJim Ingham { 20778a685aaSJim Ingham LanguageRuntime *runtime = process->GetLanguageRuntime (known_type); 20878a685aaSJim Ingham if (runtime) 2092837b766SJim Ingham found_dynamic_type = runtime->GetDynamicTypeAndAddress (*m_parent, m_use_dynamic, class_type_or_name, dynamic_address); 21078a685aaSJim Ingham } 21178a685aaSJim Ingham else 21278a685aaSJim Ingham { 21378a685aaSJim Ingham LanguageRuntime *cpp_runtime = process->GetLanguageRuntime (lldb::eLanguageTypeC_plus_plus); 21478a685aaSJim Ingham if (cpp_runtime) 2152837b766SJim Ingham found_dynamic_type = cpp_runtime->GetDynamicTypeAndAddress (*m_parent, m_use_dynamic, class_type_or_name, dynamic_address); 21678a685aaSJim Ingham 21778a685aaSJim Ingham if (!found_dynamic_type) 21878a685aaSJim Ingham { 21978a685aaSJim Ingham LanguageRuntime *objc_runtime = process->GetLanguageRuntime (lldb::eLanguageTypeObjC); 22078a685aaSJim Ingham if (objc_runtime) 2219910bc85SEnrico Granata found_dynamic_type = objc_runtime->GetDynamicTypeAndAddress (*m_parent, m_use_dynamic, class_type_or_name, dynamic_address); 22278a685aaSJim Ingham } 22378a685aaSJim Ingham } 22478a685aaSJim Ingham 22561be0903SJim Ingham // Getting the dynamic value may have run the program a bit, and so marked us as needing updating, but we really 22661be0903SJim Ingham // don't... 22761be0903SJim Ingham 22861be0903SJim Ingham m_update_point.SetUpdated(); 22961be0903SJim Ingham 230df7c7f99SEnrico Granata if (found_dynamic_type) 231df7c7f99SEnrico Granata { 232df7c7f99SEnrico Granata if (class_type_or_name.HasType()) 233df7c7f99SEnrico Granata { 234df7c7f99SEnrico Granata // TypeSP are always generated from debug info 235df7c7f99SEnrico Granata if (!class_type_or_name.HasTypeSP() && class_type_or_name.GetClangASTType().IsRuntimeGeneratedType()) 236dc4db5a6SEnrico Granata { 237dc4db5a6SEnrico Granata m_type_impl = TypeImpl(m_parent->GetClangType(),FixupTypeAndOrName(class_type_or_name, *m_parent).GetClangASTType()); 238dc4db5a6SEnrico Granata class_type_or_name.SetClangASTType(ClangASTType()); 239dc4db5a6SEnrico Granata } 240df7c7f99SEnrico Granata else 241df7c7f99SEnrico Granata { 242df7c7f99SEnrico Granata m_type_impl = TypeImpl(FixupTypeAndOrName(class_type_or_name, *m_parent).GetClangASTType()); 243df7c7f99SEnrico Granata } 244df7c7f99SEnrico Granata } 245df7c7f99SEnrico Granata else 246df7c7f99SEnrico Granata { 247df7c7f99SEnrico Granata m_type_impl.Clear(); 248df7c7f99SEnrico Granata } 249df7c7f99SEnrico Granata } 250df7c7f99SEnrico Granata else 251df7c7f99SEnrico Granata { 252df7c7f99SEnrico Granata m_type_impl.Clear(); 253df7c7f99SEnrico Granata } 254dc4db5a6SEnrico Granata 25578a685aaSJim Ingham // If we don't have a dynamic type, then make ourselves just a echo of our parent. 25678a685aaSJim Ingham // Or we could return false, and make ourselves an echo of our parent? 25778a685aaSJim Ingham if (!found_dynamic_type) 25878a685aaSJim Ingham { 259f7b1a34eSEnrico Granata if (m_dynamic_type_info) 26075badc46SEnrico Granata SetValueDidChange(true); 261bd83b87dSEnrico Granata ClearDynamicTypeInformation(); 262f7b1a34eSEnrico Granata m_dynamic_type_info.Clear(); 26378a685aaSJim Ingham m_value = m_parent->GetValue(); 26457ee3067SGreg Clayton m_error = m_value.GetValueAsData (&exe_ctx, m_data, 0, GetModule().get()); 26578a685aaSJim Ingham return m_error.Success(); 26678a685aaSJim Ingham } 26778a685aaSJim Ingham 26878a685aaSJim Ingham Value old_value(m_value); 26978a685aaSJim Ingham 2705160ce5cSGreg Clayton Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_TYPES)); 271d228483dSEnrico Granata 272e3e91517SEnrico Granata bool has_changed_type = false; 273e3e91517SEnrico Granata 274f7b1a34eSEnrico Granata if (!m_dynamic_type_info) 27578a685aaSJim Ingham { 276f7b1a34eSEnrico Granata m_dynamic_type_info = class_type_or_name; 277e3e91517SEnrico Granata has_changed_type = true; 27878a685aaSJim Ingham } 279f7b1a34eSEnrico Granata else if (class_type_or_name != m_dynamic_type_info) 28078a685aaSJim Ingham { 28178a685aaSJim Ingham // We are another type, we need to tear down our children... 282f7b1a34eSEnrico Granata m_dynamic_type_info = class_type_or_name; 28378a685aaSJim Ingham SetValueDidChange (true); 284e3e91517SEnrico Granata has_changed_type = true; 28578a685aaSJim Ingham } 28678a685aaSJim Ingham 287e3e91517SEnrico Granata if (has_changed_type) 288e3e91517SEnrico Granata ClearDynamicTypeInformation (); 289e3e91517SEnrico Granata 29078a685aaSJim Ingham if (!m_address.IsValid() || m_address != dynamic_address) 29178a685aaSJim Ingham { 29278a685aaSJim Ingham if (m_address.IsValid()) 29378a685aaSJim Ingham SetValueDidChange (true); 29478a685aaSJim Ingham 29578a685aaSJim Ingham // We've moved, so we should be fine... 29678a685aaSJim Ingham m_address = dynamic_address; 297cc4d0146SGreg Clayton lldb::TargetSP target_sp (GetTargetSP()); 298cc4d0146SGreg Clayton lldb::addr_t load_address = m_address.GetLoadAddress(target_sp.get()); 29978a685aaSJim Ingham m_value.GetScalar() = load_address; 30078a685aaSJim Ingham } 30178a685aaSJim Ingham 302dc4db5a6SEnrico Granata m_dynamic_type_info = FixupTypeAndOrName(m_dynamic_type_info, *m_parent); 30378a685aaSJim Ingham 30457ee3067SGreg Clayton //m_value.SetContext (Value::eContextTypeClangType, corrected_type); 305dc4db5a6SEnrico Granata m_value.SetClangType (m_dynamic_type_info.GetClangASTType()); 30678a685aaSJim Ingham 30778a685aaSJim Ingham // Our address is the location of the dynamic type stored in memory. It isn't a load address, 30878a685aaSJim Ingham // because we aren't pointing to the LOCATION that stores the pointer to us, we're pointing to us... 30978a685aaSJim Ingham m_value.SetValueType(Value::eValueTypeScalar); 31078a685aaSJim Ingham 311e3e91517SEnrico Granata if (has_changed_type && log) 312e3e91517SEnrico Granata log->Printf("[%s %p] has a new dynamic type %s", 313e3e91517SEnrico Granata GetName().GetCString(), 314e3e91517SEnrico Granata this, 315e3e91517SEnrico Granata GetTypeName().GetCString()); 316e3e91517SEnrico Granata 317f7b1a34eSEnrico Granata if (m_address.IsValid() && m_dynamic_type_info) 31878a685aaSJim Ingham { 31978a685aaSJim Ingham // The variable value is in the Scalar value inside the m_value. 32078a685aaSJim Ingham // We can point our m_data right to it. 32157ee3067SGreg Clayton m_error = m_value.GetValueAsData (&exe_ctx, m_data, 0, GetModule().get()); 32278a685aaSJim Ingham if (m_error.Success()) 32378a685aaSJim Ingham { 32457ee3067SGreg Clayton if (GetClangType().IsAggregateType ()) 32578a685aaSJim Ingham { 32678a685aaSJim Ingham // this value object represents an aggregate type whose 32778a685aaSJim Ingham // children have values, but this object does not. So we 32878a685aaSJim Ingham // say we are changed if our location has changed. 32978a685aaSJim Ingham SetValueDidChange (m_value.GetValueType() != old_value.GetValueType() || m_value.GetScalar() != old_value.GetScalar()); 33078a685aaSJim Ingham } 33178a685aaSJim Ingham 33278a685aaSJim Ingham SetValueIsValid (true); 33378a685aaSJim Ingham return true; 33478a685aaSJim Ingham } 33578a685aaSJim Ingham } 33678a685aaSJim Ingham 33778a685aaSJim Ingham // We get here if we've failed above... 33878a685aaSJim Ingham SetValueIsValid (false); 33978a685aaSJim Ingham return false; 34078a685aaSJim Ingham } 34178a685aaSJim Ingham 34278a685aaSJim Ingham 34378a685aaSJim Ingham 34478a685aaSJim Ingham bool 34578a685aaSJim Ingham ValueObjectDynamicValue::IsInScope () 34678a685aaSJim Ingham { 34778a685aaSJim Ingham return m_parent->IsInScope(); 34878a685aaSJim Ingham } 34978a685aaSJim Ingham 35007a4ac22SEnrico Granata bool 35107a4ac22SEnrico Granata ValueObjectDynamicValue::SetValueFromCString (const char *value_str, Error& error) 35207a4ac22SEnrico Granata { 35307a4ac22SEnrico Granata if (!UpdateValueIfNeeded(false)) 35407a4ac22SEnrico Granata { 35507a4ac22SEnrico Granata error.SetErrorString("unable to read value"); 35607a4ac22SEnrico Granata return false; 35707a4ac22SEnrico Granata } 35807a4ac22SEnrico Granata 35907a4ac22SEnrico Granata uint64_t my_value = GetValueAsUnsigned(UINT64_MAX); 36007a4ac22SEnrico Granata uint64_t parent_value = m_parent->GetValueAsUnsigned(UINT64_MAX); 36107a4ac22SEnrico Granata 36207a4ac22SEnrico Granata if (my_value == UINT64_MAX || parent_value == UINT64_MAX) 36307a4ac22SEnrico Granata { 36407a4ac22SEnrico Granata error.SetErrorString("unable to read value"); 36507a4ac22SEnrico Granata return false; 36607a4ac22SEnrico Granata } 36707a4ac22SEnrico Granata 36807a4ac22SEnrico Granata // if we are at an offset from our parent, in order to set ourselves correctly we would need 36907a4ac22SEnrico Granata // to change the new value so that it refers to the correct dynamic type. we choose not to deal 37007a4ac22SEnrico Granata // with that - if anything more than a value overwrite is required, you should be using the 37107a4ac22SEnrico Granata // expression parser instead of the value editing facility 37207a4ac22SEnrico Granata if (my_value != parent_value) 37307a4ac22SEnrico Granata { 37407a4ac22SEnrico Granata // but NULL'ing out a value should always be allowed 37507a4ac22SEnrico Granata if (strcmp(value_str,"0")) 37607a4ac22SEnrico Granata { 37707a4ac22SEnrico Granata error.SetErrorString("unable to modify dynamic value, use 'expression' command"); 37807a4ac22SEnrico Granata return false; 37907a4ac22SEnrico Granata } 38007a4ac22SEnrico Granata } 38107a4ac22SEnrico Granata 38207a4ac22SEnrico Granata bool ret_val = m_parent->SetValueFromCString(value_str,error); 38307a4ac22SEnrico Granata SetNeedsUpdate(); 38407a4ac22SEnrico Granata return ret_val; 38507a4ac22SEnrico Granata } 386389823e9SSean Callanan 387389823e9SSean Callanan bool 388389823e9SSean Callanan ValueObjectDynamicValue::SetData (DataExtractor &data, Error &error) 389389823e9SSean Callanan { 390389823e9SSean Callanan if (!UpdateValueIfNeeded(false)) 391389823e9SSean Callanan { 392389823e9SSean Callanan error.SetErrorString("unable to read value"); 393389823e9SSean Callanan return false; 394389823e9SSean Callanan } 395389823e9SSean Callanan 396389823e9SSean Callanan uint64_t my_value = GetValueAsUnsigned(UINT64_MAX); 397389823e9SSean Callanan uint64_t parent_value = m_parent->GetValueAsUnsigned(UINT64_MAX); 398389823e9SSean Callanan 399389823e9SSean Callanan if (my_value == UINT64_MAX || parent_value == UINT64_MAX) 400389823e9SSean Callanan { 401389823e9SSean Callanan error.SetErrorString("unable to read value"); 402389823e9SSean Callanan return false; 403389823e9SSean Callanan } 404389823e9SSean Callanan 405389823e9SSean Callanan // if we are at an offset from our parent, in order to set ourselves correctly we would need 406389823e9SSean Callanan // to change the new value so that it refers to the correct dynamic type. we choose not to deal 407389823e9SSean Callanan // with that - if anything more than a value overwrite is required, you should be using the 408389823e9SSean Callanan // expression parser instead of the value editing facility 409389823e9SSean Callanan if (my_value != parent_value) 410389823e9SSean Callanan { 411389823e9SSean Callanan // but NULL'ing out a value should always be allowed 412389823e9SSean Callanan lldb::offset_t offset = 0; 413389823e9SSean Callanan 414389823e9SSean Callanan if (data.GetPointer(&offset) != 0) 415389823e9SSean Callanan { 416389823e9SSean Callanan error.SetErrorString("unable to modify dynamic value, use 'expression' command"); 417389823e9SSean Callanan return false; 418389823e9SSean Callanan } 419389823e9SSean Callanan } 420389823e9SSean Callanan 421389823e9SSean Callanan bool ret_val = m_parent->SetData(data, error); 422389823e9SSean Callanan SetNeedsUpdate(); 423389823e9SSean Callanan return ret_val; 424389823e9SSean Callanan } 425