1 //===-- ValueObjectDynamicValue.cpp ---------------------------------------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #include "lldb/Core/ValueObjectDynamicValue.h" 10 #include "lldb/Core/Value.h" 11 #include "lldb/Core/ValueObject.h" 12 #include "lldb/Symbol/CompilerType.h" 13 #include "lldb/Symbol/Type.h" 14 #include "lldb/Target/ExecutionContext.h" 15 #include "lldb/Target/LanguageRuntime.h" 16 #include "lldb/Target/Process.h" 17 #include "lldb/Target/Target.h" 18 #include "lldb/Utility/DataExtractor.h" 19 #include "lldb/Utility/LLDBLog.h" 20 #include "lldb/Utility/Log.h" 21 #include "lldb/Utility/Scalar.h" 22 #include "lldb/Utility/Status.h" 23 #include "lldb/lldb-types.h" 24 25 #include <cstring> 26 namespace lldb_private { 27 class Declaration; 28 } 29 30 using namespace lldb_private; 31 32 ValueObjectDynamicValue::ValueObjectDynamicValue( 33 ValueObject &parent, lldb::DynamicValueType use_dynamic) 34 : ValueObject(parent), m_address(), m_dynamic_type_info(), 35 m_use_dynamic(use_dynamic) { 36 SetName(parent.GetName()); 37 } 38 39 CompilerType ValueObjectDynamicValue::GetCompilerTypeImpl() { 40 const bool success = UpdateValueIfNeeded(false); 41 if (success) { 42 if (m_dynamic_type_info.HasType()) 43 return m_value.GetCompilerType(); 44 else 45 return m_parent->GetCompilerType(); 46 } 47 return m_parent->GetCompilerType(); 48 } 49 50 ConstString ValueObjectDynamicValue::GetTypeName() { 51 const bool success = UpdateValueIfNeeded(false); 52 if (success) { 53 if (m_dynamic_type_info.HasName()) 54 return m_dynamic_type_info.GetName(); 55 } 56 return m_parent->GetTypeName(); 57 } 58 59 TypeImpl ValueObjectDynamicValue::GetTypeImpl() { 60 const bool success = UpdateValueIfNeeded(false); 61 if (success && m_type_impl.IsValid()) { 62 return m_type_impl; 63 } 64 return m_parent->GetTypeImpl(); 65 } 66 67 ConstString ValueObjectDynamicValue::GetQualifiedTypeName() { 68 const bool success = UpdateValueIfNeeded(false); 69 if (success) { 70 if (m_dynamic_type_info.HasName()) 71 return m_dynamic_type_info.GetName(); 72 } 73 return m_parent->GetQualifiedTypeName(); 74 } 75 76 ConstString ValueObjectDynamicValue::GetDisplayTypeName() { 77 const bool success = UpdateValueIfNeeded(false); 78 if (success) { 79 if (m_dynamic_type_info.HasType()) 80 return GetCompilerType().GetDisplayTypeName(); 81 if (m_dynamic_type_info.HasName()) 82 return m_dynamic_type_info.GetName(); 83 } 84 return m_parent->GetDisplayTypeName(); 85 } 86 87 size_t ValueObjectDynamicValue::CalculateNumChildren(uint32_t max) { 88 const bool success = UpdateValueIfNeeded(false); 89 if (success && m_dynamic_type_info.HasType()) { 90 ExecutionContext exe_ctx(GetExecutionContextRef()); 91 auto children_count = GetCompilerType().GetNumChildren(true, &exe_ctx); 92 return children_count <= max ? children_count : max; 93 } else 94 return m_parent->GetNumChildren(max); 95 } 96 97 llvm::Optional<uint64_t> ValueObjectDynamicValue::GetByteSize() { 98 const bool success = UpdateValueIfNeeded(false); 99 if (success && m_dynamic_type_info.HasType()) { 100 ExecutionContext exe_ctx(GetExecutionContextRef()); 101 return m_value.GetValueByteSize(nullptr, &exe_ctx); 102 } else 103 return m_parent->GetByteSize(); 104 } 105 106 lldb::ValueType ValueObjectDynamicValue::GetValueType() const { 107 return m_parent->GetValueType(); 108 } 109 110 bool ValueObjectDynamicValue::UpdateValue() { 111 SetValueIsValid(false); 112 m_error.Clear(); 113 114 if (!m_parent->UpdateValueIfNeeded(false)) { 115 // The dynamic value failed to get an error, pass the error along 116 if (m_error.Success() && m_parent->GetError().Fail()) 117 m_error = m_parent->GetError(); 118 return false; 119 } 120 121 // Setting our type_sp to NULL will route everything back through our parent 122 // which is equivalent to not using dynamic values. 123 if (m_use_dynamic == lldb::eNoDynamicValues) { 124 m_dynamic_type_info.Clear(); 125 return true; 126 } 127 128 ExecutionContext exe_ctx(GetExecutionContextRef()); 129 Target *target = exe_ctx.GetTargetPtr(); 130 if (target) { 131 m_data.SetByteOrder(target->GetArchitecture().GetByteOrder()); 132 m_data.SetAddressByteSize(target->GetArchitecture().GetAddressByteSize()); 133 } 134 135 // First make sure our Type and/or Address haven't changed: 136 Process *process = exe_ctx.GetProcessPtr(); 137 if (!process) 138 return false; 139 140 TypeAndOrName class_type_or_name; 141 Address dynamic_address; 142 bool found_dynamic_type = false; 143 Value::ValueType value_type; 144 145 LanguageRuntime *runtime = nullptr; 146 147 lldb::LanguageType known_type = m_parent->GetObjectRuntimeLanguage(); 148 if (known_type != lldb::eLanguageTypeUnknown && 149 known_type != lldb::eLanguageTypeC) { 150 runtime = process->GetLanguageRuntime(known_type); 151 if (runtime) 152 found_dynamic_type = runtime->GetDynamicTypeAndAddress( 153 *m_parent, m_use_dynamic, class_type_or_name, dynamic_address, 154 value_type); 155 } else { 156 runtime = process->GetLanguageRuntime(lldb::eLanguageTypeC_plus_plus); 157 if (runtime) 158 found_dynamic_type = runtime->GetDynamicTypeAndAddress( 159 *m_parent, m_use_dynamic, class_type_or_name, dynamic_address, 160 value_type); 161 162 if (!found_dynamic_type) { 163 runtime = process->GetLanguageRuntime(lldb::eLanguageTypeObjC); 164 if (runtime) 165 found_dynamic_type = runtime->GetDynamicTypeAndAddress( 166 *m_parent, m_use_dynamic, class_type_or_name, dynamic_address, 167 value_type); 168 } 169 } 170 171 // Getting the dynamic value may have run the program a bit, and so marked us 172 // as needing updating, but we really don't... 173 174 m_update_point.SetUpdated(); 175 176 if (runtime && found_dynamic_type) { 177 if (class_type_or_name.HasType()) { 178 m_type_impl = 179 TypeImpl(m_parent->GetCompilerType(), 180 runtime->FixUpDynamicType(class_type_or_name, *m_parent) 181 .GetCompilerType()); 182 } else { 183 m_type_impl.Clear(); 184 } 185 } else { 186 m_type_impl.Clear(); 187 } 188 189 // If we don't have a dynamic type, then make ourselves just a echo of our 190 // parent. Or we could return false, and make ourselves an echo of our 191 // parent? 192 if (!found_dynamic_type) { 193 if (m_dynamic_type_info) 194 SetValueDidChange(true); 195 ClearDynamicTypeInformation(); 196 m_dynamic_type_info.Clear(); 197 m_value = m_parent->GetValue(); 198 m_error = m_value.GetValueAsData(&exe_ctx, m_data, GetModule().get()); 199 return m_error.Success(); 200 } 201 202 Value old_value(m_value); 203 204 Log *log = GetLog(LLDBLog::Types); 205 206 bool has_changed_type = false; 207 208 if (!m_dynamic_type_info) { 209 m_dynamic_type_info = class_type_or_name; 210 has_changed_type = true; 211 } else if (class_type_or_name != m_dynamic_type_info) { 212 // We are another type, we need to tear down our children... 213 m_dynamic_type_info = class_type_or_name; 214 SetValueDidChange(true); 215 has_changed_type = true; 216 } 217 218 if (has_changed_type) 219 ClearDynamicTypeInformation(); 220 221 if (!m_address.IsValid() || m_address != dynamic_address) { 222 if (m_address.IsValid()) 223 SetValueDidChange(true); 224 225 // We've moved, so we should be fine... 226 m_address = dynamic_address; 227 lldb::TargetSP target_sp(GetTargetSP()); 228 lldb::addr_t load_address = m_address.GetLoadAddress(target_sp.get()); 229 m_value.GetScalar() = load_address; 230 } 231 232 if (runtime) 233 m_dynamic_type_info = 234 runtime->FixUpDynamicType(m_dynamic_type_info, *m_parent); 235 236 m_value.SetCompilerType(m_dynamic_type_info.GetCompilerType()); 237 238 m_value.SetValueType(value_type); 239 240 if (has_changed_type && log) 241 LLDB_LOGF(log, "[%s %p] has a new dynamic type %s", GetName().GetCString(), 242 static_cast<void *>(this), GetTypeName().GetCString()); 243 244 if (m_address.IsValid() && m_dynamic_type_info) { 245 // The variable value is in the Scalar value inside the m_value. We can 246 // point our m_data right to it. 247 m_error = m_value.GetValueAsData(&exe_ctx, m_data, GetModule().get()); 248 if (m_error.Success()) { 249 if (!CanProvideValue()) { 250 // this value object represents an aggregate type whose children have 251 // values, but this object does not. So we say we are changed if our 252 // location has changed. 253 SetValueDidChange(m_value.GetValueType() != old_value.GetValueType() || 254 m_value.GetScalar() != old_value.GetScalar()); 255 } 256 257 SetValueIsValid(true); 258 return true; 259 } 260 } 261 262 // We get here if we've failed above... 263 SetValueIsValid(false); 264 return false; 265 } 266 267 bool ValueObjectDynamicValue::IsInScope() { return m_parent->IsInScope(); } 268 269 bool ValueObjectDynamicValue::SetValueFromCString(const char *value_str, 270 Status &error) { 271 if (!UpdateValueIfNeeded(false)) { 272 error.SetErrorString("unable to read value"); 273 return false; 274 } 275 276 uint64_t my_value = GetValueAsUnsigned(UINT64_MAX); 277 uint64_t parent_value = m_parent->GetValueAsUnsigned(UINT64_MAX); 278 279 if (my_value == UINT64_MAX || parent_value == UINT64_MAX) { 280 error.SetErrorString("unable to read value"); 281 return false; 282 } 283 284 // if we are at an offset from our parent, in order to set ourselves 285 // correctly we would need to change the new value so that it refers to the 286 // correct dynamic type. we choose not to deal with that - if anything more 287 // than a value overwrite is required, you should be using the expression 288 // parser instead of the value editing facility 289 if (my_value != parent_value) { 290 // but NULL'ing out a value should always be allowed 291 if (strcmp(value_str, "0")) { 292 error.SetErrorString( 293 "unable to modify dynamic value, use 'expression' command"); 294 return false; 295 } 296 } 297 298 bool ret_val = m_parent->SetValueFromCString(value_str, error); 299 SetNeedsUpdate(); 300 return ret_val; 301 } 302 303 bool ValueObjectDynamicValue::SetData(DataExtractor &data, Status &error) { 304 if (!UpdateValueIfNeeded(false)) { 305 error.SetErrorString("unable to read value"); 306 return false; 307 } 308 309 uint64_t my_value = GetValueAsUnsigned(UINT64_MAX); 310 uint64_t parent_value = m_parent->GetValueAsUnsigned(UINT64_MAX); 311 312 if (my_value == UINT64_MAX || parent_value == UINT64_MAX) { 313 error.SetErrorString("unable to read value"); 314 return false; 315 } 316 317 // if we are at an offset from our parent, in order to set ourselves 318 // correctly we would need to change the new value so that it refers to the 319 // correct dynamic type. we choose not to deal with that - if anything more 320 // than a value overwrite is required, you should be using the expression 321 // parser instead of the value editing facility 322 if (my_value != parent_value) { 323 // but NULL'ing out a value should always be allowed 324 lldb::offset_t offset = 0; 325 326 if (data.GetAddress(&offset) != 0) { 327 error.SetErrorString( 328 "unable to modify dynamic value, use 'expression' command"); 329 return false; 330 } 331 } 332 333 bool ret_val = m_parent->SetData(data, error); 334 SetNeedsUpdate(); 335 return ret_val; 336 } 337 338 void ValueObjectDynamicValue::SetPreferredDisplayLanguage( 339 lldb::LanguageType lang) { 340 this->ValueObject::SetPreferredDisplayLanguage(lang); 341 if (m_parent) 342 m_parent->SetPreferredDisplayLanguage(lang); 343 } 344 345 lldb::LanguageType ValueObjectDynamicValue::GetPreferredDisplayLanguage() { 346 if (m_preferred_display_language == lldb::eLanguageTypeUnknown) { 347 if (m_parent) 348 return m_parent->GetPreferredDisplayLanguage(); 349 return lldb::eLanguageTypeUnknown; 350 } else 351 return m_preferred_display_language; 352 } 353 354 bool ValueObjectDynamicValue::IsSyntheticChildrenGenerated() { 355 if (m_parent) 356 return m_parent->IsSyntheticChildrenGenerated(); 357 return false; 358 } 359 360 void ValueObjectDynamicValue::SetSyntheticChildrenGenerated(bool b) { 361 if (m_parent) 362 m_parent->SetSyntheticChildrenGenerated(b); 363 this->ValueObject::SetSyntheticChildrenGenerated(b); 364 } 365 366 bool ValueObjectDynamicValue::GetDeclaration(Declaration &decl) { 367 if (m_parent) 368 return m_parent->GetDeclaration(decl); 369 370 return ValueObject::GetDeclaration(decl); 371 } 372 373 uint64_t ValueObjectDynamicValue::GetLanguageFlags() { 374 if (m_parent) 375 return m_parent->GetLanguageFlags(); 376 return this->ValueObject::GetLanguageFlags(); 377 } 378 379 void ValueObjectDynamicValue::SetLanguageFlags(uint64_t flags) { 380 if (m_parent) 381 m_parent->SetLanguageFlags(flags); 382 else 383 this->ValueObject::SetLanguageFlags(flags); 384 } 385