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