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