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