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 (), 412837b766SJim Ingham m_type_sp(), 422837b766SJim Ingham m_use_dynamic (use_dynamic) 4378a685aaSJim Ingham { 44d8b5fce2SEnrico Granata m_last_format_mgr_dynamic = use_dynamic; 456f3533fbSEnrico Granata SetName (parent.GetName()); 4678a685aaSJim Ingham } 4778a685aaSJim Ingham 4878a685aaSJim Ingham ValueObjectDynamicValue::~ValueObjectDynamicValue() 4978a685aaSJim Ingham { 5078a685aaSJim Ingham m_owning_valobj_sp.reset(); 5178a685aaSJim Ingham } 5278a685aaSJim Ingham 5378a685aaSJim Ingham lldb::clang_type_t 547277284fSSean Callanan ValueObjectDynamicValue::GetClangTypeImpl () 5578a685aaSJim Ingham { 5678a685aaSJim Ingham if (m_type_sp) 5778a685aaSJim Ingham return m_value.GetClangType(); 5878a685aaSJim Ingham else 5978a685aaSJim Ingham return m_parent->GetClangType(); 6078a685aaSJim Ingham } 6178a685aaSJim Ingham 6278a685aaSJim Ingham ConstString 6378a685aaSJim Ingham ValueObjectDynamicValue::GetTypeName() 6478a685aaSJim Ingham { 65c3e320a7SEnrico Granata const bool success = UpdateValueIfNeeded(false); 665ad63941SGreg Clayton if (success && m_type_sp) 6784db9105SGreg Clayton return ClangASTType::GetConstTypeName (GetClangAST(), GetClangType()); 6878a685aaSJim Ingham else 6978a685aaSJim Ingham return m_parent->GetTypeName(); 7078a685aaSJim Ingham } 7178a685aaSJim Ingham 7278a685aaSJim Ingham uint32_t 7378a685aaSJim Ingham ValueObjectDynamicValue::CalculateNumChildren() 7478a685aaSJim Ingham { 75c3e320a7SEnrico Granata const bool success = UpdateValueIfNeeded(false); 765ad63941SGreg Clayton if (success && m_type_sp) 7778a685aaSJim Ingham return ClangASTContext::GetNumChildren (GetClangAST (), GetClangType(), true); 7878a685aaSJim Ingham else 7978a685aaSJim Ingham return m_parent->GetNumChildren(); 8078a685aaSJim Ingham } 8178a685aaSJim Ingham 8278a685aaSJim Ingham clang::ASTContext * 837277284fSSean Callanan ValueObjectDynamicValue::GetClangASTImpl () 8478a685aaSJim Ingham { 850a3958e0SEnrico Granata const bool success = UpdateValueIfNeeded(false); 865ad63941SGreg Clayton if (success && m_type_sp) 8778a685aaSJim Ingham return m_type_sp->GetClangAST(); 8878a685aaSJim Ingham else 8978a685aaSJim Ingham return m_parent->GetClangAST (); 9078a685aaSJim Ingham } 9178a685aaSJim Ingham 9278a685aaSJim Ingham size_t 9378a685aaSJim Ingham ValueObjectDynamicValue::GetByteSize() 9478a685aaSJim Ingham { 95c3e320a7SEnrico Granata const bool success = UpdateValueIfNeeded(false); 965ad63941SGreg Clayton if (success && m_type_sp) 9778a685aaSJim Ingham return m_value.GetValueByteSize(GetClangAST(), NULL); 9878a685aaSJim Ingham else 9978a685aaSJim Ingham return m_parent->GetByteSize(); 10078a685aaSJim Ingham } 10178a685aaSJim Ingham 10278a685aaSJim Ingham lldb::ValueType 10378a685aaSJim Ingham ValueObjectDynamicValue::GetValueType() const 10478a685aaSJim Ingham { 10578a685aaSJim Ingham return m_parent->GetValueType(); 10678a685aaSJim Ingham } 10778a685aaSJim Ingham 10878a685aaSJim Ingham bool 10978a685aaSJim Ingham ValueObjectDynamicValue::UpdateValue () 11078a685aaSJim Ingham { 11178a685aaSJim Ingham SetValueIsValid (false); 11278a685aaSJim Ingham m_error.Clear(); 11378a685aaSJim Ingham 114c3e320a7SEnrico Granata if (!m_parent->UpdateValueIfNeeded(false)) 11578a685aaSJim Ingham { 116007d5be6SGreg Clayton // The dynamic value failed to get an error, pass the error along 117007d5be6SGreg Clayton if (m_error.Success() && m_parent->GetError().Fail()) 118007d5be6SGreg Clayton m_error = m_parent->GetError(); 11978a685aaSJim Ingham return false; 12078a685aaSJim Ingham } 12178a685aaSJim Ingham 1222837b766SJim Ingham // Setting our type_sp to NULL will route everything back through our 1232837b766SJim Ingham // parent which is equivalent to not using dynamic values. 1242837b766SJim Ingham if (m_use_dynamic == lldb::eNoDynamicValues) 1252837b766SJim Ingham { 1262837b766SJim Ingham m_type_sp.reset(); 1272837b766SJim Ingham return true; 1282837b766SJim Ingham } 1292837b766SJim Ingham 130cc4d0146SGreg Clayton ExecutionContext exe_ctx (GetExecutionContextRef()); 131c14ee32dSGreg Clayton Target *target = exe_ctx.GetTargetPtr(); 132c14ee32dSGreg Clayton if (target) 13378a685aaSJim Ingham { 134c14ee32dSGreg Clayton m_data.SetByteOrder(target->GetArchitecture().GetByteOrder()); 135c14ee32dSGreg Clayton m_data.SetAddressByteSize(target->GetArchitecture().GetAddressByteSize()); 13678a685aaSJim Ingham } 13778a685aaSJim Ingham 13878a685aaSJim Ingham // First make sure our Type and/or Address haven't changed: 139cc4d0146SGreg Clayton Process *process = exe_ctx.GetProcessPtr(); 14078a685aaSJim Ingham if (!process) 14178a685aaSJim Ingham return false; 14278a685aaSJim Ingham 14361be0903SJim Ingham TypeAndOrName class_type_or_name; 14478a685aaSJim Ingham Address dynamic_address; 14578a685aaSJim Ingham bool found_dynamic_type = false; 14678a685aaSJim Ingham 14778a685aaSJim Ingham lldb::LanguageType known_type = m_parent->GetObjectRuntimeLanguage(); 14878a685aaSJim Ingham if (known_type != lldb::eLanguageTypeUnknown && known_type != lldb::eLanguageTypeC) 14978a685aaSJim Ingham { 15078a685aaSJim Ingham LanguageRuntime *runtime = process->GetLanguageRuntime (known_type); 15178a685aaSJim Ingham if (runtime) 1522837b766SJim Ingham found_dynamic_type = runtime->GetDynamicTypeAndAddress (*m_parent, m_use_dynamic, class_type_or_name, dynamic_address); 15378a685aaSJim Ingham } 15478a685aaSJim Ingham else 15578a685aaSJim Ingham { 15678a685aaSJim Ingham LanguageRuntime *cpp_runtime = process->GetLanguageRuntime (lldb::eLanguageTypeC_plus_plus); 15778a685aaSJim Ingham if (cpp_runtime) 1582837b766SJim Ingham found_dynamic_type = cpp_runtime->GetDynamicTypeAndAddress (*m_parent, m_use_dynamic, class_type_or_name, dynamic_address); 15978a685aaSJim Ingham 16078a685aaSJim Ingham if (!found_dynamic_type) 16178a685aaSJim Ingham { 16278a685aaSJim Ingham LanguageRuntime *objc_runtime = process->GetLanguageRuntime (lldb::eLanguageTypeObjC); 16378a685aaSJim Ingham if (objc_runtime) 1649910bc85SEnrico Granata found_dynamic_type = objc_runtime->GetDynamicTypeAndAddress (*m_parent, m_use_dynamic, class_type_or_name, dynamic_address); 16578a685aaSJim Ingham } 16678a685aaSJim Ingham } 16778a685aaSJim Ingham 16861be0903SJim Ingham lldb::TypeSP dynamic_type_sp = class_type_or_name.GetTypeSP(); 16961be0903SJim Ingham 17061be0903SJim Ingham // Getting the dynamic value may have run the program a bit, and so marked us as needing updating, but we really 17161be0903SJim Ingham // don't... 17261be0903SJim Ingham 17361be0903SJim Ingham m_update_point.SetUpdated(); 17461be0903SJim Ingham 17578a685aaSJim Ingham // If we don't have a dynamic type, then make ourselves just a echo of our parent. 17678a685aaSJim Ingham // Or we could return false, and make ourselves an echo of our parent? 17778a685aaSJim Ingham if (!found_dynamic_type) 17878a685aaSJim Ingham { 179*bd83b87dSEnrico Granata ClearDynamicTypeInformation(); 180*bd83b87dSEnrico Granata m_type_sp.reset(); 18178a685aaSJim Ingham SetValueDidChange(true); 18278a685aaSJim Ingham m_value = m_parent->GetValue(); 183e72dfb32SGreg Clayton m_error = m_value.GetValueAsData (&exe_ctx, GetClangAST(), m_data, 0, GetModule().get()); 18478a685aaSJim Ingham return m_error.Success(); 18578a685aaSJim Ingham } 18678a685aaSJim Ingham 18778a685aaSJim Ingham Value old_value(m_value); 18878a685aaSJim Ingham 189d228483dSEnrico Granata lldb::LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_TYPES)); 190d228483dSEnrico Granata 191e3e91517SEnrico Granata bool has_changed_type = false; 192e3e91517SEnrico Granata 19378a685aaSJim Ingham if (!m_type_sp) 19478a685aaSJim Ingham { 19578a685aaSJim Ingham m_type_sp = dynamic_type_sp; 196e3e91517SEnrico Granata has_changed_type = true; 19778a685aaSJim Ingham } 19878a685aaSJim Ingham else if (dynamic_type_sp != m_type_sp) 19978a685aaSJim Ingham { 20078a685aaSJim Ingham // We are another type, we need to tear down our children... 20178a685aaSJim Ingham m_type_sp = dynamic_type_sp; 20278a685aaSJim Ingham SetValueDidChange (true); 203e3e91517SEnrico Granata has_changed_type = true; 20478a685aaSJim Ingham } 20578a685aaSJim Ingham 206e3e91517SEnrico Granata if (has_changed_type) 207e3e91517SEnrico Granata ClearDynamicTypeInformation (); 208e3e91517SEnrico Granata 20978a685aaSJim Ingham if (!m_address.IsValid() || m_address != dynamic_address) 21078a685aaSJim Ingham { 21178a685aaSJim Ingham if (m_address.IsValid()) 21278a685aaSJim Ingham SetValueDidChange (true); 21378a685aaSJim Ingham 21478a685aaSJim Ingham // We've moved, so we should be fine... 21578a685aaSJim Ingham m_address = dynamic_address; 216cc4d0146SGreg Clayton lldb::TargetSP target_sp (GetTargetSP()); 217cc4d0146SGreg Clayton lldb::addr_t load_address = m_address.GetLoadAddress(target_sp.get()); 21878a685aaSJim Ingham m_value.GetScalar() = load_address; 21978a685aaSJim Ingham } 22078a685aaSJim Ingham 22178a685aaSJim Ingham // The type will always be the type of the dynamic object. If our parent's type was a pointer, 22278a685aaSJim Ingham // then our type should be a pointer to the type of the dynamic object. If a reference, then the original type 22378a685aaSJim Ingham // should be okay... 22478a685aaSJim Ingham lldb::clang_type_t orig_type = m_type_sp->GetClangForwardType(); 22578a685aaSJim Ingham lldb::clang_type_t corrected_type = orig_type; 22678a685aaSJim Ingham if (m_parent->IsPointerType()) 22778a685aaSJim Ingham corrected_type = ClangASTContext::CreatePointerType (m_type_sp->GetClangAST(), orig_type); 22878a685aaSJim Ingham else if (m_parent->IsPointerOrReferenceType()) 22978a685aaSJim Ingham corrected_type = ClangASTContext::CreateLValueReferenceType (m_type_sp->GetClangAST(), orig_type); 23078a685aaSJim Ingham 23178a685aaSJim Ingham m_value.SetContext (Value::eContextTypeClangType, corrected_type); 23278a685aaSJim Ingham 23378a685aaSJim Ingham // Our address is the location of the dynamic type stored in memory. It isn't a load address, 23478a685aaSJim Ingham // because we aren't pointing to the LOCATION that stores the pointer to us, we're pointing to us... 23578a685aaSJim Ingham m_value.SetValueType(Value::eValueTypeScalar); 23678a685aaSJim Ingham 237e3e91517SEnrico Granata if (has_changed_type && log) 238e3e91517SEnrico Granata log->Printf("[%s %p] has a new dynamic type %s", 239e3e91517SEnrico Granata GetName().GetCString(), 240e3e91517SEnrico Granata this, 241e3e91517SEnrico Granata GetTypeName().GetCString()); 242e3e91517SEnrico Granata 24378a685aaSJim Ingham if (m_address.IsValid() && m_type_sp) 24478a685aaSJim Ingham { 24578a685aaSJim Ingham // The variable value is in the Scalar value inside the m_value. 24678a685aaSJim Ingham // We can point our m_data right to it. 247e72dfb32SGreg Clayton m_error = m_value.GetValueAsData (&exe_ctx, GetClangAST(), m_data, 0, GetModule().get()); 24878a685aaSJim Ingham if (m_error.Success()) 24978a685aaSJim Ingham { 25078a685aaSJim Ingham if (ClangASTContext::IsAggregateType (GetClangType())) 25178a685aaSJim Ingham { 25278a685aaSJim Ingham // this value object represents an aggregate type whose 25378a685aaSJim Ingham // children have values, but this object does not. So we 25478a685aaSJim Ingham // say we are changed if our location has changed. 25578a685aaSJim Ingham SetValueDidChange (m_value.GetValueType() != old_value.GetValueType() || m_value.GetScalar() != old_value.GetScalar()); 25678a685aaSJim Ingham } 25778a685aaSJim Ingham 25878a685aaSJim Ingham SetValueIsValid (true); 25978a685aaSJim Ingham return true; 26078a685aaSJim Ingham } 26178a685aaSJim Ingham } 26278a685aaSJim Ingham 26378a685aaSJim Ingham // We get here if we've failed above... 26478a685aaSJim Ingham SetValueIsValid (false); 26578a685aaSJim Ingham return false; 26678a685aaSJim Ingham } 26778a685aaSJim Ingham 26878a685aaSJim Ingham 26978a685aaSJim Ingham 27078a685aaSJim Ingham bool 27178a685aaSJim Ingham ValueObjectDynamicValue::IsInScope () 27278a685aaSJim Ingham { 27378a685aaSJim Ingham return m_parent->IsInScope(); 27478a685aaSJim Ingham } 27578a685aaSJim Ingham 27607a4ac22SEnrico Granata bool 27707a4ac22SEnrico Granata ValueObjectDynamicValue::SetValueFromCString (const char *value_str, Error& error) 27807a4ac22SEnrico Granata { 27907a4ac22SEnrico Granata if (!UpdateValueIfNeeded(false)) 28007a4ac22SEnrico Granata { 28107a4ac22SEnrico Granata error.SetErrorString("unable to read value"); 28207a4ac22SEnrico Granata return false; 28307a4ac22SEnrico Granata } 28407a4ac22SEnrico Granata 28507a4ac22SEnrico Granata uint64_t my_value = GetValueAsUnsigned(UINT64_MAX); 28607a4ac22SEnrico Granata uint64_t parent_value = m_parent->GetValueAsUnsigned(UINT64_MAX); 28707a4ac22SEnrico Granata 28807a4ac22SEnrico Granata if (my_value == UINT64_MAX || parent_value == UINT64_MAX) 28907a4ac22SEnrico Granata { 29007a4ac22SEnrico Granata error.SetErrorString("unable to read value"); 29107a4ac22SEnrico Granata return false; 29207a4ac22SEnrico Granata } 29307a4ac22SEnrico Granata 29407a4ac22SEnrico Granata // if we are at an offset from our parent, in order to set ourselves correctly we would need 29507a4ac22SEnrico Granata // to change the new value so that it refers to the correct dynamic type. we choose not to deal 29607a4ac22SEnrico Granata // with that - if anything more than a value overwrite is required, you should be using the 29707a4ac22SEnrico Granata // expression parser instead of the value editing facility 29807a4ac22SEnrico Granata if (my_value != parent_value) 29907a4ac22SEnrico Granata { 30007a4ac22SEnrico Granata // but NULL'ing out a value should always be allowed 30107a4ac22SEnrico Granata if (strcmp(value_str,"0")) 30207a4ac22SEnrico Granata { 30307a4ac22SEnrico Granata error.SetErrorString("unable to modify dynamic value, use 'expression' command"); 30407a4ac22SEnrico Granata return false; 30507a4ac22SEnrico Granata } 30607a4ac22SEnrico Granata } 30707a4ac22SEnrico Granata 30807a4ac22SEnrico Granata bool ret_val = m_parent->SetValueFromCString(value_str,error); 30907a4ac22SEnrico Granata SetNeedsUpdate(); 31007a4ac22SEnrico Granata return ret_val; 31107a4ac22SEnrico Granata } 312