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