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