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