1321369Sdim//===-- ValueObjectDynamicValue.cpp ------------------------------*- C++-*-===// 2254721Semaste// 3353358Sdim// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4353358Sdim// See https://llvm.org/LICENSE.txt for license information. 5353358Sdim// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6254721Semaste// 7254721Semaste//===----------------------------------------------------------------------===// 8254721Semaste 9254721Semaste#include "lldb/Core/ValueObjectDynamicValue.h" 10254721Semaste#include "lldb/Core/Value.h" 11254721Semaste#include "lldb/Core/ValueObject.h" 12296417Sdim#include "lldb/Symbol/CompilerType.h" 13254721Semaste#include "lldb/Symbol/Type.h" 14254721Semaste#include "lldb/Target/ExecutionContext.h" 15254721Semaste#include "lldb/Target/LanguageRuntime.h" 16254721Semaste#include "lldb/Target/Process.h" 17254721Semaste#include "lldb/Target/Target.h" 18344779Sdim#include "lldb/Utility/DataExtractor.h" 19321369Sdim#include "lldb/Utility/Log.h" 20344779Sdim#include "lldb/Utility/Logging.h" 21344779Sdim#include "lldb/Utility/Scalar.h" 22344779Sdim#include "lldb/Utility/Status.h" 23344779Sdim#include "lldb/lldb-types.h" 24254721Semaste 25344779Sdim#include <string.h> 26321369Sdimnamespace lldb_private { 27321369Sdimclass Declaration; 28321369Sdim} 29321369Sdim 30254721Semasteusing namespace lldb_private; 31254721Semaste 32314564SdimValueObjectDynamicValue::ValueObjectDynamicValue( 33314564Sdim ValueObject &parent, lldb::DynamicValueType use_dynamic) 34314564Sdim : ValueObject(parent), m_address(), m_dynamic_type_info(), 35314564Sdim m_use_dynamic(use_dynamic) { 36314564Sdim SetName(parent.GetName()); 37254721Semaste} 38254721Semaste 39314564SdimValueObjectDynamicValue::~ValueObjectDynamicValue() { 40314564Sdim m_owning_valobj_sp.reset(); 41254721Semaste} 42254721Semaste 43314564SdimCompilerType ValueObjectDynamicValue::GetCompilerTypeImpl() { 44314564Sdim const bool success = UpdateValueIfNeeded(false); 45314564Sdim if (success) { 46314564Sdim if (m_dynamic_type_info.HasType()) 47314564Sdim return m_value.GetCompilerType(); 48314564Sdim else 49314564Sdim return m_parent->GetCompilerType(); 50314564Sdim } 51314564Sdim return m_parent->GetCompilerType(); 52254721Semaste} 53254721Semaste 54314564SdimConstString ValueObjectDynamicValue::GetTypeName() { 55314564Sdim const bool success = UpdateValueIfNeeded(false); 56314564Sdim if (success) { 57314564Sdim if (m_dynamic_type_info.HasName()) 58314564Sdim return m_dynamic_type_info.GetName(); 59314564Sdim } 60314564Sdim return m_parent->GetTypeName(); 61254721Semaste} 62254721Semaste 63314564SdimTypeImpl ValueObjectDynamicValue::GetTypeImpl() { 64314564Sdim const bool success = UpdateValueIfNeeded(false); 65314564Sdim if (success && m_type_impl.IsValid()) { 66314564Sdim return m_type_impl; 67314564Sdim } 68314564Sdim return m_parent->GetTypeImpl(); 69258054Semaste} 70258054Semaste 71314564SdimConstString ValueObjectDynamicValue::GetQualifiedTypeName() { 72314564Sdim const bool success = UpdateValueIfNeeded(false); 73314564Sdim if (success) { 74314564Sdim if (m_dynamic_type_info.HasName()) 75314564Sdim return m_dynamic_type_info.GetName(); 76314564Sdim } 77314564Sdim return m_parent->GetQualifiedTypeName(); 78276479Sdim} 79276479Sdim 80314564SdimConstString ValueObjectDynamicValue::GetDisplayTypeName() { 81314564Sdim const bool success = UpdateValueIfNeeded(false); 82314564Sdim if (success) { 83314564Sdim if (m_dynamic_type_info.HasType()) 84314564Sdim return GetCompilerType().GetDisplayTypeName(); 85314564Sdim if (m_dynamic_type_info.HasName()) 86314564Sdim return m_dynamic_type_info.GetName(); 87314564Sdim } 88314564Sdim return m_parent->GetDisplayTypeName(); 89254721Semaste} 90254721Semaste 91314564Sdimsize_t ValueObjectDynamicValue::CalculateNumChildren(uint32_t max) { 92314564Sdim const bool success = UpdateValueIfNeeded(false); 93314564Sdim if (success && m_dynamic_type_info.HasType()) { 94344779Sdim ExecutionContext exe_ctx(GetExecutionContextRef()); 95344779Sdim auto children_count = GetCompilerType().GetNumChildren(true, &exe_ctx); 96314564Sdim return children_count <= max ? children_count : max; 97314564Sdim } else 98314564Sdim return m_parent->GetNumChildren(max); 99254721Semaste} 100254721Semaste 101314564Sdimuint64_t ValueObjectDynamicValue::GetByteSize() { 102314564Sdim const bool success = UpdateValueIfNeeded(false); 103314564Sdim if (success && m_dynamic_type_info.HasType()) { 104314564Sdim ExecutionContext exe_ctx(GetExecutionContextRef()); 105314564Sdim return m_value.GetValueByteSize(nullptr, &exe_ctx); 106314564Sdim } else 107314564Sdim return m_parent->GetByteSize(); 108254721Semaste} 109254721Semaste 110314564Sdimlldb::ValueType ValueObjectDynamicValue::GetValueType() const { 111314564Sdim return m_parent->GetValueType(); 112254721Semaste} 113254721Semaste 114314564Sdimbool ValueObjectDynamicValue::UpdateValue() { 115314564Sdim SetValueIsValid(false); 116314564Sdim m_error.Clear(); 117254721Semaste 118314564Sdim if (!m_parent->UpdateValueIfNeeded(false)) { 119314564Sdim // The dynamic value failed to get an error, pass the error along 120314564Sdim if (m_error.Success() && m_parent->GetError().Fail()) 121314564Sdim m_error = m_parent->GetError(); 122314564Sdim return false; 123314564Sdim } 124276479Sdim 125341825Sdim // Setting our type_sp to NULL will route everything back through our parent 126341825Sdim // which is equivalent to not using dynamic values. 127314564Sdim if (m_use_dynamic == lldb::eNoDynamicValues) { 128314564Sdim m_dynamic_type_info.Clear(); 129314564Sdim return true; 130314564Sdim } 131276479Sdim 132314564Sdim ExecutionContext exe_ctx(GetExecutionContextRef()); 133314564Sdim Target *target = exe_ctx.GetTargetPtr(); 134314564Sdim if (target) { 135314564Sdim m_data.SetByteOrder(target->GetArchitecture().GetByteOrder()); 136314564Sdim m_data.SetAddressByteSize(target->GetArchitecture().GetAddressByteSize()); 137314564Sdim } 138276479Sdim 139314564Sdim // First make sure our Type and/or Address haven't changed: 140314564Sdim Process *process = exe_ctx.GetProcessPtr(); 141314564Sdim if (!process) 142314564Sdim return false; 143276479Sdim 144314564Sdim TypeAndOrName class_type_or_name; 145314564Sdim Address dynamic_address; 146314564Sdim bool found_dynamic_type = false; 147314564Sdim Value::ValueType value_type; 148276479Sdim 149314564Sdim LanguageRuntime *runtime = nullptr; 150276479Sdim 151314564Sdim lldb::LanguageType known_type = m_parent->GetObjectRuntimeLanguage(); 152314564Sdim if (known_type != lldb::eLanguageTypeUnknown && 153314564Sdim known_type != lldb::eLanguageTypeC) { 154314564Sdim runtime = process->GetLanguageRuntime(known_type); 155314564Sdim if (runtime) 156314564Sdim found_dynamic_type = runtime->GetDynamicTypeAndAddress( 157314564Sdim *m_parent, m_use_dynamic, class_type_or_name, dynamic_address, 158314564Sdim value_type); 159314564Sdim } else { 160314564Sdim runtime = process->GetLanguageRuntime(lldb::eLanguageTypeC_plus_plus); 161314564Sdim if (runtime) 162314564Sdim found_dynamic_type = runtime->GetDynamicTypeAndAddress( 163314564Sdim *m_parent, m_use_dynamic, class_type_or_name, dynamic_address, 164314564Sdim value_type); 165314564Sdim 166314564Sdim if (!found_dynamic_type) { 167314564Sdim runtime = process->GetLanguageRuntime(lldb::eLanguageTypeObjC); 168314564Sdim if (runtime) 169314564Sdim found_dynamic_type = runtime->GetDynamicTypeAndAddress( 170314564Sdim *m_parent, m_use_dynamic, class_type_or_name, dynamic_address, 171314564Sdim value_type); 172254721Semaste } 173314564Sdim } 174276479Sdim 175314564Sdim // Getting the dynamic value may have run the program a bit, and so marked us 176341825Sdim // as needing updating, but we really don't... 177276479Sdim 178314564Sdim m_update_point.SetUpdated(); 179258054Semaste 180314564Sdim if (runtime && found_dynamic_type) { 181314564Sdim if (class_type_or_name.HasType()) { 182314564Sdim m_type_impl = 183314564Sdim TypeImpl(m_parent->GetCompilerType(), 184314564Sdim runtime->FixUpDynamicType(class_type_or_name, *m_parent) 185314564Sdim .GetCompilerType()); 186314564Sdim } else { 187314564Sdim m_type_impl.Clear(); 188258054Semaste } 189314564Sdim } else { 190314564Sdim m_type_impl.Clear(); 191314564Sdim } 192276479Sdim 193314564Sdim // If we don't have a dynamic type, then make ourselves just a echo of our 194341825Sdim // parent. Or we could return false, and make ourselves an echo of our 195341825Sdim // parent? 196314564Sdim if (!found_dynamic_type) { 197314564Sdim if (m_dynamic_type_info) 198314564Sdim SetValueDidChange(true); 199314564Sdim ClearDynamicTypeInformation(); 200314564Sdim m_dynamic_type_info.Clear(); 201314564Sdim m_value = m_parent->GetValue(); 202360784Sdim m_error = m_value.GetValueAsData(&exe_ctx, m_data, GetModule().get()); 203314564Sdim return m_error.Success(); 204314564Sdim } 205276479Sdim 206314564Sdim Value old_value(m_value); 207254721Semaste 208314564Sdim Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_TYPES)); 209276479Sdim 210314564Sdim bool has_changed_type = false; 211276479Sdim 212314564Sdim if (!m_dynamic_type_info) { 213314564Sdim m_dynamic_type_info = class_type_or_name; 214314564Sdim has_changed_type = true; 215314564Sdim } else if (class_type_or_name != m_dynamic_type_info) { 216314564Sdim // We are another type, we need to tear down our children... 217314564Sdim m_dynamic_type_info = class_type_or_name; 218314564Sdim SetValueDidChange(true); 219314564Sdim has_changed_type = true; 220314564Sdim } 221276479Sdim 222314564Sdim if (has_changed_type) 223314564Sdim ClearDynamicTypeInformation(); 224276479Sdim 225314564Sdim if (!m_address.IsValid() || m_address != dynamic_address) { 226314564Sdim if (m_address.IsValid()) 227314564Sdim SetValueDidChange(true); 228276479Sdim 229314564Sdim // We've moved, so we should be fine... 230314564Sdim m_address = dynamic_address; 231314564Sdim lldb::TargetSP target_sp(GetTargetSP()); 232314564Sdim lldb::addr_t load_address = m_address.GetLoadAddress(target_sp.get()); 233314564Sdim m_value.GetScalar() = load_address; 234314564Sdim } 235276479Sdim 236314564Sdim if (runtime) 237314564Sdim m_dynamic_type_info = 238314564Sdim runtime->FixUpDynamicType(m_dynamic_type_info, *m_parent); 239276479Sdim 240314564Sdim // m_value.SetContext (Value::eContextTypeClangType, corrected_type); 241314564Sdim m_value.SetCompilerType(m_dynamic_type_info.GetCompilerType()); 242276479Sdim 243314564Sdim m_value.SetValueType(value_type); 244254721Semaste 245314564Sdim if (has_changed_type && log) 246360784Sdim LLDB_LOGF(log, "[%s %p] has a new dynamic type %s", GetName().GetCString(), 247360784Sdim static_cast<void *>(this), GetTypeName().GetCString()); 248276479Sdim 249314564Sdim if (m_address.IsValid() && m_dynamic_type_info) { 250341825Sdim // The variable value is in the Scalar value inside the m_value. We can 251341825Sdim // point our m_data right to it. 252360784Sdim m_error = m_value.GetValueAsData(&exe_ctx, m_data, GetModule().get()); 253314564Sdim if (m_error.Success()) { 254314564Sdim if (!CanProvideValue()) { 255341825Sdim // this value object represents an aggregate type whose children have 256341825Sdim // values, but this object does not. So we say we are changed if our 257341825Sdim // location has changed. 258314564Sdim SetValueDidChange(m_value.GetValueType() != old_value.GetValueType() || 259314564Sdim m_value.GetScalar() != old_value.GetScalar()); 260314564Sdim } 261254721Semaste 262314564Sdim SetValueIsValid(true); 263314564Sdim return true; 264254721Semaste } 265314564Sdim } 266276479Sdim 267314564Sdim // We get here if we've failed above... 268314564Sdim SetValueIsValid(false); 269314564Sdim return false; 270254721Semaste} 271254721Semaste 272314564Sdimbool ValueObjectDynamicValue::IsInScope() { return m_parent->IsInScope(); } 273254721Semaste 274314564Sdimbool ValueObjectDynamicValue::SetValueFromCString(const char *value_str, 275321369Sdim Status &error) { 276314564Sdim if (!UpdateValueIfNeeded(false)) { 277314564Sdim error.SetErrorString("unable to read value"); 278314564Sdim return false; 279314564Sdim } 280254721Semaste 281314564Sdim uint64_t my_value = GetValueAsUnsigned(UINT64_MAX); 282314564Sdim uint64_t parent_value = m_parent->GetValueAsUnsigned(UINT64_MAX); 283254721Semaste 284314564Sdim if (my_value == UINT64_MAX || parent_value == UINT64_MAX) { 285314564Sdim error.SetErrorString("unable to read value"); 286314564Sdim return false; 287314564Sdim } 288314564Sdim 289341825Sdim // if we are at an offset from our parent, in order to set ourselves 290341825Sdim // correctly we would need to change the new value so that it refers to the 291341825Sdim // correct dynamic type. we choose not to deal with that - if anything more 292341825Sdim // than a value overwrite is required, you should be using the expression 293341825Sdim // parser instead of the value editing facility 294314564Sdim if (my_value != parent_value) { 295314564Sdim // but NULL'ing out a value should always be allowed 296314564Sdim if (strcmp(value_str, "0")) { 297314564Sdim error.SetErrorString( 298314564Sdim "unable to modify dynamic value, use 'expression' command"); 299314564Sdim return false; 300254721Semaste } 301314564Sdim } 302314564Sdim 303314564Sdim bool ret_val = m_parent->SetValueFromCString(value_str, error); 304314564Sdim SetNeedsUpdate(); 305314564Sdim return ret_val; 306254721Semaste} 307254721Semaste 308321369Sdimbool ValueObjectDynamicValue::SetData(DataExtractor &data, Status &error) { 309314564Sdim if (!UpdateValueIfNeeded(false)) { 310314564Sdim error.SetErrorString("unable to read value"); 311314564Sdim return false; 312314564Sdim } 313314564Sdim 314314564Sdim uint64_t my_value = GetValueAsUnsigned(UINT64_MAX); 315314564Sdim uint64_t parent_value = m_parent->GetValueAsUnsigned(UINT64_MAX); 316314564Sdim 317314564Sdim if (my_value == UINT64_MAX || parent_value == UINT64_MAX) { 318314564Sdim error.SetErrorString("unable to read value"); 319314564Sdim return false; 320314564Sdim } 321314564Sdim 322341825Sdim // if we are at an offset from our parent, in order to set ourselves 323341825Sdim // correctly we would need to change the new value so that it refers to the 324341825Sdim // correct dynamic type. we choose not to deal with that - if anything more 325341825Sdim // than a value overwrite is required, you should be using the expression 326341825Sdim // parser instead of the value editing facility 327314564Sdim if (my_value != parent_value) { 328314564Sdim // but NULL'ing out a value should always be allowed 329314564Sdim lldb::offset_t offset = 0; 330314564Sdim 331314564Sdim if (data.GetPointer(&offset) != 0) { 332314564Sdim error.SetErrorString( 333314564Sdim "unable to modify dynamic value, use 'expression' command"); 334314564Sdim return false; 335254721Semaste } 336314564Sdim } 337296417Sdim 338314564Sdim bool ret_val = m_parent->SetData(data, error); 339314564Sdim SetNeedsUpdate(); 340314564Sdim return ret_val; 341296417Sdim} 342296417Sdim 343314564Sdimvoid ValueObjectDynamicValue::SetPreferredDisplayLanguage( 344314564Sdim lldb::LanguageType lang) { 345314564Sdim this->ValueObject::SetPreferredDisplayLanguage(lang); 346314564Sdim if (m_parent) 347314564Sdim m_parent->SetPreferredDisplayLanguage(lang); 348296417Sdim} 349296417Sdim 350314564Sdimlldb::LanguageType ValueObjectDynamicValue::GetPreferredDisplayLanguage() { 351314564Sdim if (m_preferred_display_language == lldb::eLanguageTypeUnknown) { 352309124Sdim if (m_parent) 353314564Sdim return m_parent->GetPreferredDisplayLanguage(); 354314564Sdim return lldb::eLanguageTypeUnknown; 355314564Sdim } else 356314564Sdim return m_preferred_display_language; 357309124Sdim} 358309124Sdim 359314564Sdimbool ValueObjectDynamicValue::IsSyntheticChildrenGenerated() { 360314564Sdim if (m_parent) 361314564Sdim return m_parent->IsSyntheticChildrenGenerated(); 362314564Sdim return false; 363309124Sdim} 364309124Sdim 365314564Sdimvoid ValueObjectDynamicValue::SetSyntheticChildrenGenerated(bool b) { 366314564Sdim if (m_parent) 367314564Sdim m_parent->SetSyntheticChildrenGenerated(b); 368314564Sdim this->ValueObject::SetSyntheticChildrenGenerated(b); 369314564Sdim} 370296417Sdim 371314564Sdimbool ValueObjectDynamicValue::GetDeclaration(Declaration &decl) { 372314564Sdim if (m_parent) 373314564Sdim return m_parent->GetDeclaration(decl); 374314564Sdim 375314564Sdim return ValueObject::GetDeclaration(decl); 376296417Sdim} 377296417Sdim 378314564Sdimuint64_t ValueObjectDynamicValue::GetLanguageFlags() { 379314564Sdim if (m_parent) 380314564Sdim return m_parent->GetLanguageFlags(); 381314564Sdim return this->ValueObject::GetLanguageFlags(); 382296417Sdim} 383296417Sdim 384314564Sdimvoid ValueObjectDynamicValue::SetLanguageFlags(uint64_t flags) { 385314564Sdim if (m_parent) 386314564Sdim m_parent->SetLanguageFlags(flags); 387314564Sdim else 388314564Sdim this->ValueObject::SetLanguageFlags(flags); 389296417Sdim} 390