ValueObjectDynamicValue.cpp revision 263363
11539Srgrimes//===-- ValueObjectDynamicValue.cpp ---------------------------------*- C++ -*-===// 21539Srgrimes// 31539Srgrimes// The LLVM Compiler Infrastructure 41539Srgrimes// 51539Srgrimes// This file is distributed under the University of Illinois Open Source 61539Srgrimes// License. See LICENSE.TXT for details. 71539Srgrimes// 81539Srgrimes//===----------------------------------------------------------------------===// 91539Srgrimes 101539Srgrimes 111539Srgrimes#include "lldb/Core/ValueObjectDynamicValue.h" 121539Srgrimes 131539Srgrimes// C Includes 141539Srgrimes// C++ Includes 151539Srgrimes// Other libraries and framework includes 161539Srgrimes// Project includes 171539Srgrimes#include "lldb/Core/Log.h" 181539Srgrimes#include "lldb/Core/Module.h" 191539Srgrimes#include "lldb/Core/ValueObjectList.h" 201539Srgrimes#include "lldb/Core/Value.h" 211539Srgrimes#include "lldb/Core/ValueObject.h" 221539Srgrimes 231539Srgrimes#include "lldb/Symbol/ClangASTType.h" 241539Srgrimes#include "lldb/Symbol/ObjectFile.h" 251539Srgrimes#include "lldb/Symbol/SymbolContext.h" 261539Srgrimes#include "lldb/Symbol/Type.h" 271539Srgrimes#include "lldb/Symbol/Variable.h" 281539Srgrimes 291539Srgrimes#include "lldb/Target/ExecutionContext.h" 301539Srgrimes#include "lldb/Target/LanguageRuntime.h" 311539Srgrimes#include "lldb/Target/Process.h" 321539Srgrimes#include "lldb/Target/RegisterContext.h" 331539Srgrimes#include "lldb/Target/Target.h" 3451794Smarcel#include "lldb/Target/Thread.h" 3551794Smarcel 361539Srgrimesusing namespace lldb_private; 371539Srgrimes 389343SbdeValueObjectDynamicValue::ValueObjectDynamicValue (ValueObject &parent, lldb::DynamicValueType use_dynamic) : 399343Sbde ValueObject(parent), 401539Srgrimes m_address (), 411539Srgrimes m_dynamic_type_info(), 4234925Sdufault m_use_dynamic (use_dynamic) 43102227Smike{ 441539Srgrimes SetName (parent.GetName()); 4551794Smarcel} 461539Srgrimes 471539SrgrimesValueObjectDynamicValue::~ValueObjectDynamicValue() 481539Srgrimes{ 491539Srgrimes m_owning_valobj_sp.reset(); 5047289Speter} 511539Srgrimes 521539SrgrimesClangASTType 531539SrgrimesValueObjectDynamicValue::GetClangTypeImpl () 5493032Simp{ 551539Srgrimes const bool success = UpdateValueIfNeeded(false); 56102227Smike if (success) 5793032Simp { 5893032Simp if (m_dynamic_type_info.HasType()) 5993032Simp return m_value.GetClangType(); 6093032Simp else 6193032Simp return m_parent->GetClangType(); 6293032Simp } 6393032Simp return m_parent->GetClangType(); 6493032Simp} 6593032Simp 6693032SimpConstString 6734319SdufaultValueObjectDynamicValue::GetTypeName() 6834319Sdufault{ 6934925Sdufault const bool success = UpdateValueIfNeeded(false); 7034319Sdufault if (success) 7134319Sdufault { 72102227Smike if (m_dynamic_type_info.HasName()) 7393032Simp return m_dynamic_type_info.GetName(); 7493032Simp if (m_dynamic_type_info.HasType()) 7534319Sdufault return GetClangType().GetConstTypeName(); 7634319Sdufault } 7734030Sdufault return m_parent->GetTypeName(); 781539Srgrimes} 79102227Smike 8093032SimpTypeImpl 8193032SimpValueObjectDynamicValue::GetTypeImpl () 8293032Simp{ 8393032Simp const bool success = UpdateValueIfNeeded(false); 8493032Simp if (success && m_type_impl.IsValid()) 8593032Simp { 8693032Simp return m_type_impl; 8793032Simp } 8893032Simp return m_parent->GetTypeImpl(); 899343Sbde} 909343Sbde 911539SrgrimesConstString 921539SrgrimesValueObjectDynamicValue::GetQualifiedTypeName() 939343Sbde{ 94 const bool success = UpdateValueIfNeeded(false); 95 if (success) 96 { 97 if (m_dynamic_type_info.HasName()) 98 return m_dynamic_type_info.GetName(); 99 if (m_dynamic_type_info.HasType()) 100 return GetClangType().GetConstQualifiedTypeName (); 101 } 102 return m_parent->GetTypeName(); 103} 104 105size_t 106ValueObjectDynamicValue::CalculateNumChildren() 107{ 108 const bool success = UpdateValueIfNeeded(false); 109 if (success && m_dynamic_type_info.HasType()) 110 return GetClangType().GetNumChildren (true); 111 else 112 return m_parent->GetNumChildren(); 113} 114 115uint64_t 116ValueObjectDynamicValue::GetByteSize() 117{ 118 const bool success = UpdateValueIfNeeded(false); 119 if (success && m_dynamic_type_info.HasType()) 120 return m_value.GetValueByteSize(NULL); 121 else 122 return m_parent->GetByteSize(); 123} 124 125lldb::ValueType 126ValueObjectDynamicValue::GetValueType() const 127{ 128 return m_parent->GetValueType(); 129} 130 131 132static TypeAndOrName 133FixupTypeAndOrName (const TypeAndOrName& type_andor_name, 134 ValueObject& parent) 135{ 136 TypeAndOrName ret(type_andor_name); 137 if (type_andor_name.HasType()) 138 { 139 // The type will always be the type of the dynamic object. If our parent's type was a pointer, 140 // then our type should be a pointer to the type of the dynamic object. If a reference, then the original type 141 // should be okay... 142 ClangASTType orig_type = type_andor_name.GetClangASTType(); 143 ClangASTType corrected_type = orig_type; 144 if (parent.IsPointerType()) 145 corrected_type = orig_type.GetPointerType (); 146 else if (parent.IsPointerOrReferenceType()) 147 corrected_type = orig_type.GetLValueReferenceType (); 148 ret.SetClangASTType(corrected_type); 149 } 150 else /*if (m_dynamic_type_info.HasName())*/ 151 { 152 // If we are here we need to adjust our dynamic type name to include the correct & or * symbol 153 std::string corrected_name (type_andor_name.GetName().GetCString()); 154 if (parent.IsPointerType()) 155 corrected_name.append(" *"); 156 else if (parent.IsPointerOrReferenceType()) 157 corrected_name.append(" &"); 158 // the parent type should be a correctly pointer'ed or referenc'ed type 159 ret.SetClangASTType(parent.GetClangType()); 160 ret.SetName(corrected_name.c_str()); 161 } 162 return ret; 163} 164 165bool 166ValueObjectDynamicValue::UpdateValue () 167{ 168 SetValueIsValid (false); 169 m_error.Clear(); 170 171 if (!m_parent->UpdateValueIfNeeded(false)) 172 { 173 // The dynamic value failed to get an error, pass the error along 174 if (m_error.Success() && m_parent->GetError().Fail()) 175 m_error = m_parent->GetError(); 176 return false; 177 } 178 179 // Setting our type_sp to NULL will route everything back through our 180 // parent which is equivalent to not using dynamic values. 181 if (m_use_dynamic == lldb::eNoDynamicValues) 182 { 183 m_dynamic_type_info.Clear(); 184 return true; 185 } 186 187 ExecutionContext exe_ctx (GetExecutionContextRef()); 188 Target *target = exe_ctx.GetTargetPtr(); 189 if (target) 190 { 191 m_data.SetByteOrder(target->GetArchitecture().GetByteOrder()); 192 m_data.SetAddressByteSize(target->GetArchitecture().GetAddressByteSize()); 193 } 194 195 // First make sure our Type and/or Address haven't changed: 196 Process *process = exe_ctx.GetProcessPtr(); 197 if (!process) 198 return false; 199 200 TypeAndOrName class_type_or_name; 201 Address dynamic_address; 202 bool found_dynamic_type = false; 203 204 lldb::LanguageType known_type = m_parent->GetObjectRuntimeLanguage(); 205 if (known_type != lldb::eLanguageTypeUnknown && known_type != lldb::eLanguageTypeC) 206 { 207 LanguageRuntime *runtime = process->GetLanguageRuntime (known_type); 208 if (runtime) 209 found_dynamic_type = runtime->GetDynamicTypeAndAddress (*m_parent, m_use_dynamic, class_type_or_name, dynamic_address); 210 } 211 else 212 { 213 LanguageRuntime *cpp_runtime = process->GetLanguageRuntime (lldb::eLanguageTypeC_plus_plus); 214 if (cpp_runtime) 215 found_dynamic_type = cpp_runtime->GetDynamicTypeAndAddress (*m_parent, m_use_dynamic, class_type_or_name, dynamic_address); 216 217 if (!found_dynamic_type) 218 { 219 LanguageRuntime *objc_runtime = process->GetLanguageRuntime (lldb::eLanguageTypeObjC); 220 if (objc_runtime) 221 found_dynamic_type = objc_runtime->GetDynamicTypeAndAddress (*m_parent, m_use_dynamic, class_type_or_name, dynamic_address); 222 } 223 } 224 225 // Getting the dynamic value may have run the program a bit, and so marked us as needing updating, but we really 226 // don't... 227 228 m_update_point.SetUpdated(); 229 230 if (found_dynamic_type) 231 { 232 if (class_type_or_name.HasType()) 233 { 234 // TypeSP are always generated from debug info 235 if (!class_type_or_name.HasTypeSP() && class_type_or_name.GetClangASTType().IsRuntimeGeneratedType()) 236 { 237 m_type_impl = TypeImpl(m_parent->GetClangType(),FixupTypeAndOrName(class_type_or_name, *m_parent).GetClangASTType()); 238 class_type_or_name.SetClangASTType(ClangASTType()); 239 } 240 else 241 { 242 m_type_impl = TypeImpl(FixupTypeAndOrName(class_type_or_name, *m_parent).GetClangASTType()); 243 } 244 } 245 else 246 { 247 m_type_impl.Clear(); 248 } 249 } 250 else 251 { 252 m_type_impl.Clear(); 253 } 254 255 // If we don't have a dynamic type, then make ourselves just a echo of our parent. 256 // Or we could return false, and make ourselves an echo of our parent? 257 if (!found_dynamic_type) 258 { 259 if (m_dynamic_type_info) 260 SetValueDidChange(true); 261 ClearDynamicTypeInformation(); 262 m_dynamic_type_info.Clear(); 263 m_value = m_parent->GetValue(); 264 m_error = m_value.GetValueAsData (&exe_ctx, m_data, 0, GetModule().get()); 265 return m_error.Success(); 266 } 267 268 Value old_value(m_value); 269 270 Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_TYPES)); 271 272 bool has_changed_type = false; 273 274 if (!m_dynamic_type_info) 275 { 276 m_dynamic_type_info = class_type_or_name; 277 has_changed_type = true; 278 } 279 else if (class_type_or_name != m_dynamic_type_info) 280 { 281 // We are another type, we need to tear down our children... 282 m_dynamic_type_info = class_type_or_name; 283 SetValueDidChange (true); 284 has_changed_type = true; 285 } 286 287 if (has_changed_type) 288 ClearDynamicTypeInformation (); 289 290 if (!m_address.IsValid() || m_address != dynamic_address) 291 { 292 if (m_address.IsValid()) 293 SetValueDidChange (true); 294 295 // We've moved, so we should be fine... 296 m_address = dynamic_address; 297 lldb::TargetSP target_sp (GetTargetSP()); 298 lldb::addr_t load_address = m_address.GetLoadAddress(target_sp.get()); 299 m_value.GetScalar() = load_address; 300 } 301 302 m_dynamic_type_info = FixupTypeAndOrName(m_dynamic_type_info, *m_parent); 303 304 //m_value.SetContext (Value::eContextTypeClangType, corrected_type); 305 m_value.SetClangType (m_dynamic_type_info.GetClangASTType()); 306 307 // Our address is the location of the dynamic type stored in memory. It isn't a load address, 308 // because we aren't pointing to the LOCATION that stores the pointer to us, we're pointing to us... 309 m_value.SetValueType(Value::eValueTypeScalar); 310 311 if (has_changed_type && log) 312 log->Printf("[%s %p] has a new dynamic type %s", 313 GetName().GetCString(), 314 this, 315 GetTypeName().GetCString()); 316 317 if (m_address.IsValid() && m_dynamic_type_info) 318 { 319 // The variable value is in the Scalar value inside the m_value. 320 // We can point our m_data right to it. 321 m_error = m_value.GetValueAsData (&exe_ctx, m_data, 0, GetModule().get()); 322 if (m_error.Success()) 323 { 324 if (GetClangType().IsAggregateType ()) 325 { 326 // this value object represents an aggregate type whose 327 // children have values, but this object does not. So we 328 // say we are changed if our location has changed. 329 SetValueDidChange (m_value.GetValueType() != old_value.GetValueType() || m_value.GetScalar() != old_value.GetScalar()); 330 } 331 332 SetValueIsValid (true); 333 return true; 334 } 335 } 336 337 // We get here if we've failed above... 338 SetValueIsValid (false); 339 return false; 340} 341 342 343 344bool 345ValueObjectDynamicValue::IsInScope () 346{ 347 return m_parent->IsInScope(); 348} 349 350bool 351ValueObjectDynamicValue::SetValueFromCString (const char *value_str, Error& error) 352{ 353 if (!UpdateValueIfNeeded(false)) 354 { 355 error.SetErrorString("unable to read value"); 356 return false; 357 } 358 359 uint64_t my_value = GetValueAsUnsigned(UINT64_MAX); 360 uint64_t parent_value = m_parent->GetValueAsUnsigned(UINT64_MAX); 361 362 if (my_value == UINT64_MAX || parent_value == UINT64_MAX) 363 { 364 error.SetErrorString("unable to read value"); 365 return false; 366 } 367 368 // if we are at an offset from our parent, in order to set ourselves correctly we would need 369 // to change the new value so that it refers to the correct dynamic type. we choose not to deal 370 // with that - if anything more than a value overwrite is required, you should be using the 371 // expression parser instead of the value editing facility 372 if (my_value != parent_value) 373 { 374 // but NULL'ing out a value should always be allowed 375 if (strcmp(value_str,"0")) 376 { 377 error.SetErrorString("unable to modify dynamic value, use 'expression' command"); 378 return false; 379 } 380 } 381 382 bool ret_val = m_parent->SetValueFromCString(value_str,error); 383 SetNeedsUpdate(); 384 return ret_val; 385} 386 387bool 388ValueObjectDynamicValue::SetData (DataExtractor &data, Error &error) 389{ 390 if (!UpdateValueIfNeeded(false)) 391 { 392 error.SetErrorString("unable to read value"); 393 return false; 394 } 395 396 uint64_t my_value = GetValueAsUnsigned(UINT64_MAX); 397 uint64_t parent_value = m_parent->GetValueAsUnsigned(UINT64_MAX); 398 399 if (my_value == UINT64_MAX || parent_value == UINT64_MAX) 400 { 401 error.SetErrorString("unable to read value"); 402 return false; 403 } 404 405 // if we are at an offset from our parent, in order to set ourselves correctly we would need 406 // to change the new value so that it refers to the correct dynamic type. we choose not to deal 407 // with that - if anything more than a value overwrite is required, you should be using the 408 // expression parser instead of the value editing facility 409 if (my_value != parent_value) 410 { 411 // but NULL'ing out a value should always be allowed 412 lldb::offset_t offset = 0; 413 414 if (data.GetPointer(&offset) != 0) 415 { 416 error.SetErrorString("unable to modify dynamic value, use 'expression' command"); 417 return false; 418 } 419 } 420 421 bool ret_val = m_parent->SetData(data, error); 422 SetNeedsUpdate(); 423 return ret_val; 424} 425