ValueObject.cpp revision b66cd074ec097b5b0a6f2ce292f5072aa1217ca6
1//===-- ValueObject.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/ValueObject.h" 11 12// C Includes 13#include <stdlib.h> 14 15// C++ Includes 16// Other libraries and framework includes 17#include "llvm/Support/raw_ostream.h" 18#include "clang/AST/Type.h" 19 20// Project includes 21#include "lldb/Core/DataBufferHeap.h" 22#include "lldb/Core/StreamString.h" 23#include "lldb/Core/ValueObjectChild.h" 24#include "lldb/Core/ValueObjectList.h" 25 26#include "lldb/Symbol/ClangASTType.h" 27#include "lldb/Symbol/ClangASTContext.h" 28#include "lldb/Symbol/Type.h" 29 30#include "lldb/Target/ExecutionContext.h" 31#include "lldb/Target/LanguageRuntime.h" 32#include "lldb/Target/Process.h" 33#include "lldb/Target/RegisterContext.h" 34#include "lldb/Target/Target.h" 35#include "lldb/Target/Thread.h" 36 37using namespace lldb; 38using namespace lldb_private; 39 40static lldb::user_id_t g_value_obj_uid = 0; 41 42//---------------------------------------------------------------------- 43// ValueObject constructor 44//---------------------------------------------------------------------- 45ValueObject::ValueObject () : 46 UserID (++g_value_obj_uid), // Unique identifier for every value object 47 m_update_id (0), // Value object lists always start at 1, value objects start at zero 48 m_name (), 49 m_data (), 50 m_value (), 51 m_error (), 52 m_value_str (), 53 m_old_value_str (), 54 m_location_str (), 55 m_summary_str (), 56 m_object_desc_str (), 57 m_children (), 58 m_synthetic_children (), 59 m_value_is_valid (false), 60 m_value_did_change (false), 61 m_children_count_valid (false), 62 m_old_value_valid (false) 63{ 64} 65 66//---------------------------------------------------------------------- 67// Destructor 68//---------------------------------------------------------------------- 69ValueObject::~ValueObject () 70{ 71} 72 73user_id_t 74ValueObject::GetUpdateID() const 75{ 76 return m_update_id; 77} 78 79bool 80ValueObject::UpdateValueIfNeeded (ExecutionContextScope *exe_scope) 81{ 82 if (exe_scope) 83 { 84 Process *process = exe_scope->CalculateProcess(); 85 if (process) 86 { 87 const user_id_t stop_id = process->GetStopID(); 88 if (m_update_id != stop_id) 89 { 90 bool first_update = m_update_id == 0; 91 // Save the old value using swap to avoid a string copy which 92 // also will clear our m_value_str 93 if (m_value_str.empty()) 94 { 95 m_old_value_valid = false; 96 } 97 else 98 { 99 m_old_value_valid = true; 100 m_old_value_str.swap (m_value_str); 101 m_value_str.clear(); 102 } 103 m_location_str.clear(); 104 m_summary_str.clear(); 105 m_object_desc_str.clear(); 106 107 const bool value_was_valid = GetValueIsValid(); 108 SetValueDidChange (false); 109 110 m_error.Clear(); 111 112 // Call the pure virtual function to update the value 113 UpdateValue (exe_scope); 114 115 // Update the fact that we tried to update the value for this 116 // value object whether or not we succeed 117 m_update_id = stop_id; 118 bool success = m_error.Success(); 119 SetValueIsValid (success); 120 121 if (first_update) 122 SetValueDidChange (false); 123 else if (!m_value_did_change && success == false) 124 { 125 // The value wasn't gotten successfully, so we mark this 126 // as changed if the value used to be valid and now isn't 127 SetValueDidChange (value_was_valid); 128 } 129 } 130 } 131 } 132 return m_error.Success(); 133} 134 135const DataExtractor & 136ValueObject::GetDataExtractor () const 137{ 138 return m_data; 139} 140 141DataExtractor & 142ValueObject::GetDataExtractor () 143{ 144 return m_data; 145} 146 147const Error & 148ValueObject::GetError() const 149{ 150 return m_error; 151} 152 153const ConstString & 154ValueObject::GetName() const 155{ 156 return m_name; 157} 158 159const char * 160ValueObject::GetLocationAsCString (ExecutionContextScope *exe_scope) 161{ 162 if (UpdateValueIfNeeded(exe_scope)) 163 { 164 if (m_location_str.empty()) 165 { 166 StreamString sstr; 167 168 switch (m_value.GetValueType()) 169 { 170 default: 171 break; 172 173 case Value::eValueTypeScalar: 174 if (m_value.GetContextType() == Value::eContextTypeDCRegisterInfo) 175 { 176 RegisterInfo *reg_info = m_value.GetRegisterInfo(); 177 if (reg_info) 178 { 179 if (reg_info->name) 180 m_location_str = reg_info->name; 181 else if (reg_info->alt_name) 182 m_location_str = reg_info->alt_name; 183 break; 184 } 185 } 186 m_location_str = "scalar"; 187 break; 188 189 case Value::eValueTypeLoadAddress: 190 case Value::eValueTypeFileAddress: 191 case Value::eValueTypeHostAddress: 192 { 193 uint32_t addr_nibble_size = m_data.GetAddressByteSize() * 2; 194 sstr.Printf("0x%*.*llx", addr_nibble_size, addr_nibble_size, m_value.GetScalar().ULongLong(LLDB_INVALID_ADDRESS)); 195 m_location_str.swap(sstr.GetString()); 196 } 197 break; 198 } 199 } 200 } 201 return m_location_str.c_str(); 202} 203 204Value & 205ValueObject::GetValue() 206{ 207 return m_value; 208} 209 210const Value & 211ValueObject::GetValue() const 212{ 213 return m_value; 214} 215 216bool 217ValueObject::GetValueIsValid () const 218{ 219 return m_value_is_valid; 220} 221 222 223void 224ValueObject::SetValueIsValid (bool b) 225{ 226 m_value_is_valid = b; 227} 228 229bool 230ValueObject::GetValueDidChange (ExecutionContextScope *exe_scope) 231{ 232 GetValueAsCString (exe_scope); 233 return m_value_did_change; 234} 235 236void 237ValueObject::SetValueDidChange (bool value_changed) 238{ 239 m_value_did_change = value_changed; 240} 241 242ValueObjectSP 243ValueObject::GetChildAtIndex (uint32_t idx, bool can_create) 244{ 245 ValueObjectSP child_sp; 246 if (idx < GetNumChildren()) 247 { 248 // Check if we have already made the child value object? 249 if (can_create && m_children[idx].get() == NULL) 250 { 251 // No we haven't created the child at this index, so lets have our 252 // subclass do it and cache the result for quick future access. 253 m_children[idx] = CreateChildAtIndex (idx, false, 0); 254 } 255 256 child_sp = m_children[idx]; 257 } 258 return child_sp; 259} 260 261uint32_t 262ValueObject::GetIndexOfChildWithName (const ConstString &name) 263{ 264 bool omit_empty_base_classes = true; 265 return ClangASTContext::GetIndexOfChildWithName (GetClangAST(), 266 GetOpaqueClangQualType(), 267 name.AsCString(), 268 omit_empty_base_classes); 269} 270 271ValueObjectSP 272ValueObject::GetChildMemberWithName (const ConstString &name, bool can_create) 273{ 274 // when getting a child by name, it could be burried inside some base 275 // classes (which really aren't part of the expression path), so we 276 // need a vector of indexes that can get us down to the correct child 277 std::vector<uint32_t> child_indexes; 278 clang::ASTContext *clang_ast = GetClangAST(); 279 void *clang_type = GetOpaqueClangQualType(); 280 bool omit_empty_base_classes = true; 281 const size_t num_child_indexes = ClangASTContext::GetIndexOfChildMemberWithName (clang_ast, 282 clang_type, 283 name.AsCString(), 284 omit_empty_base_classes, 285 child_indexes); 286 ValueObjectSP child_sp; 287 if (num_child_indexes > 0) 288 { 289 std::vector<uint32_t>::const_iterator pos = child_indexes.begin (); 290 std::vector<uint32_t>::const_iterator end = child_indexes.end (); 291 292 child_sp = GetChildAtIndex(*pos, can_create); 293 for (++pos; pos != end; ++pos) 294 { 295 if (child_sp) 296 { 297 ValueObjectSP new_child_sp(child_sp->GetChildAtIndex (*pos, can_create)); 298 child_sp = new_child_sp; 299 } 300 else 301 { 302 child_sp.reset(); 303 } 304 305 } 306 } 307 return child_sp; 308} 309 310 311uint32_t 312ValueObject::GetNumChildren () 313{ 314 if (!m_children_count_valid) 315 { 316 SetNumChildren (CalculateNumChildren()); 317 } 318 return m_children.size(); 319} 320void 321ValueObject::SetNumChildren (uint32_t num_children) 322{ 323 m_children_count_valid = true; 324 m_children.resize(num_children); 325} 326 327void 328ValueObject::SetName (const char *name) 329{ 330 m_name.SetCString(name); 331} 332 333void 334ValueObject::SetName (const ConstString &name) 335{ 336 m_name = name; 337} 338 339ValueObjectSP 340ValueObject::CreateChildAtIndex (uint32_t idx, bool synthetic_array_member, int32_t synthetic_index) 341{ 342 ValueObjectSP valobj_sp; 343 bool omit_empty_base_classes = true; 344 345 std::string child_name_str; 346 uint32_t child_byte_size = 0; 347 int32_t child_byte_offset = 0; 348 uint32_t child_bitfield_bit_size = 0; 349 uint32_t child_bitfield_bit_offset = 0; 350 const bool transparent_pointers = synthetic_array_member == false; 351 clang::ASTContext *clang_ast = GetClangAST(); 352 void *clang_type = GetOpaqueClangQualType(); 353 void *child_clang_type; 354 child_clang_type = ClangASTContext::GetChildClangTypeAtIndex (clang_ast, 355 GetName().AsCString(), 356 clang_type, 357 idx, 358 transparent_pointers, 359 omit_empty_base_classes, 360 child_name_str, 361 child_byte_size, 362 child_byte_offset, 363 child_bitfield_bit_size, 364 child_bitfield_bit_offset); 365 if (child_clang_type) 366 { 367 if (synthetic_index) 368 child_byte_offset += child_byte_size * synthetic_index; 369 370 ConstString child_name; 371 if (!child_name_str.empty()) 372 child_name.SetCString (child_name_str.c_str()); 373 374 valobj_sp.reset (new ValueObjectChild (this, 375 clang_ast, 376 child_clang_type, 377 child_name, 378 child_byte_size, 379 child_byte_offset, 380 child_bitfield_bit_size, 381 child_bitfield_bit_offset)); 382 } 383 return valobj_sp; 384} 385 386const char * 387ValueObject::GetSummaryAsCString (ExecutionContextScope *exe_scope) 388{ 389 if (UpdateValueIfNeeded (exe_scope)) 390 { 391 if (m_summary_str.empty()) 392 { 393 void *clang_type = GetOpaqueClangQualType(); 394 395 // See if this is a pointer to a C string? 396 uint32_t fixed_length = 0; 397 if (clang_type) 398 { 399 StreamString sstr; 400 401 if (ClangASTContext::IsCStringType (clang_type, fixed_length)) 402 { 403 Process *process = exe_scope->CalculateProcess(); 404 if (process != NULL) 405 { 406 lldb::AddressType cstr_address_type = eAddressTypeInvalid; 407 lldb::addr_t cstr_address = GetPointerValue (cstr_address_type, true); 408 409 if (cstr_address != LLDB_INVALID_ADDRESS) 410 { 411 DataExtractor data; 412 size_t bytes_read = 0; 413 std::vector<char> data_buffer; 414 std::vector<char> cstr_buffer; 415 size_t cstr_length; 416 Error error; 417 if (fixed_length > 0) 418 { 419 data_buffer.resize(fixed_length); 420 // Resize the formatted buffer in case every character 421 // uses the "\xXX" format and one extra byte for a NULL 422 cstr_buffer.resize(data_buffer.size() * 4 + 1); 423 data.SetData (&data_buffer.front(), data_buffer.size(), eByteOrderHost); 424 bytes_read = process->ReadMemory (cstr_address, &data_buffer.front(), fixed_length, error); 425 if (bytes_read > 0) 426 { 427 sstr << '"'; 428 cstr_length = data.Dump (&sstr, 429 0, // Start offset in "data" 430 eFormatChar, // Print as characters 431 1, // Size of item (1 byte for a char!) 432 bytes_read, // How many bytes to print? 433 UINT32_MAX, // num per line 434 LLDB_INVALID_ADDRESS,// base address 435 0, // bitfield bit size 436 0); // bitfield bit offset 437 sstr << '"'; 438 } 439 } 440 else 441 { 442 const size_t k_max_buf_size = 256; 443 data_buffer.resize (k_max_buf_size + 1); 444 // NULL terminate in case we don't get the entire C string 445 data_buffer.back() = '\0'; 446 // Make a formatted buffer that can contain take 4 447 // bytes per character in case each byte uses the 448 // "\xXX" format and one extra byte for a NULL 449 cstr_buffer.resize (k_max_buf_size * 4 + 1); 450 451 data.SetData (&data_buffer.front(), data_buffer.size(), eByteOrderHost); 452 size_t total_cstr_len = 0; 453 while ((bytes_read = process->ReadMemory (cstr_address, &data_buffer.front(), k_max_buf_size, error)) > 0) 454 { 455 size_t len = strlen(&data_buffer.front()); 456 if (len == 0) 457 break; 458 if (len > bytes_read) 459 len = bytes_read; 460 if (sstr.GetSize() == 0) 461 sstr << '"'; 462 463 cstr_length = data.Dump (&sstr, 464 0, // Start offset in "data" 465 eFormatChar, // Print as characters 466 1, // Size of item (1 byte for a char!) 467 len, // How many bytes to print? 468 UINT32_MAX, // num per line 469 LLDB_INVALID_ADDRESS,// base address 470 0, // bitfield bit size 471 0); // bitfield bit offset 472 473 if (len < k_max_buf_size) 474 break; 475 cstr_address += total_cstr_len; 476 } 477 if (sstr.GetSize() > 0) 478 sstr << '"'; 479 } 480 } 481 } 482 483 if (sstr.GetSize() > 0) 484 m_summary_str.assign (sstr.GetData(), sstr.GetSize()); 485 } 486 else if (ClangASTContext::IsFunctionPointerType (clang_type)) 487 { 488 lldb::AddressType func_ptr_address_type = eAddressTypeInvalid; 489 lldb::addr_t func_ptr_address = GetPointerValue (func_ptr_address_type, true); 490 491 if (func_ptr_address != 0 && func_ptr_address != LLDB_INVALID_ADDRESS) 492 { 493 switch (func_ptr_address_type) 494 { 495 case eAddressTypeInvalid: 496 case eAddressTypeFile: 497 break; 498 499 case eAddressTypeLoad: 500 { 501 Address so_addr; 502 Target *target = exe_scope->CalculateTarget(); 503 if (target && target->GetSectionLoadList().IsEmpty() == false) 504 { 505 if (target->GetSectionLoadList().ResolveLoadAddress(func_ptr_address, so_addr)) 506 { 507 so_addr.Dump (&sstr, 508 exe_scope, 509 Address::DumpStyleResolvedDescription, 510 Address::DumpStyleSectionNameOffset); 511 } 512 } 513 } 514 break; 515 516 case eAddressTypeHost: 517 break; 518 } 519 } 520 if (sstr.GetSize() > 0) 521 { 522 m_summary_str.assign (1, '('); 523 m_summary_str.append (sstr.GetData(), sstr.GetSize()); 524 m_summary_str.append (1, ')'); 525 } 526 } 527 } 528 } 529 } 530 if (m_summary_str.empty()) 531 return NULL; 532 return m_summary_str.c_str(); 533} 534 535const char * 536ValueObject::GetObjectDescription (ExecutionContextScope *exe_scope) 537{ 538 if (!m_object_desc_str.empty()) 539 return m_object_desc_str.c_str(); 540 541 if (!GetValueIsValid()) 542 return NULL; 543 544 Process *process = exe_scope->CalculateProcess(); 545 if (process == NULL) 546 return NULL; 547 548 StreamString s; 549 550 lldb::LanguageType language = GetObjectRuntimeLanguage(); 551 LanguageRuntime *runtime = process->GetLanguageRuntime(language); 552 553 if (runtime && runtime->GetObjectDescription(s, *this, exe_scope)) 554 { 555 m_object_desc_str.append (s.GetData()); 556 } 557 return m_object_desc_str.c_str(); 558} 559 560const char * 561ValueObject::GetValueAsCString (ExecutionContextScope *exe_scope) 562{ 563 // If our byte size is zero this is an aggregate type that has children 564 if (ClangASTContext::IsAggregateType (GetOpaqueClangQualType()) == false) 565 { 566 if (UpdateValueIfNeeded(exe_scope)) 567 { 568 if (m_value_str.empty()) 569 { 570 const Value::ContextType context_type = m_value.GetContextType(); 571 572 switch (context_type) 573 { 574 case Value::eContextTypeOpaqueClangQualType: 575 case Value::eContextTypeDCType: 576 case Value::eContextTypeDCVariable: 577 { 578 void *clang_type = GetOpaqueClangQualType (); 579 if (clang_type) 580 { 581 StreamString sstr; 582 lldb::Format format = ClangASTType::GetFormat(clang_type); 583 if (ClangASTType::DumpTypeValue(GetClangAST(), // The clang AST 584 clang_type, // The clang type to display 585 &sstr, 586 format, // Format to display this type with 587 m_data, // Data to extract from 588 0, // Byte offset into "m_data" 589 GetByteSize(), // Byte size of item in "m_data" 590 GetBitfieldBitSize(), // Bitfield bit size 591 GetBitfieldBitOffset())) // Bitfield bit offset 592 m_value_str.swap(sstr.GetString()); 593 else 594 m_value_str.clear(); 595 } 596 } 597 break; 598 599 case Value::eContextTypeDCRegisterInfo: 600 { 601 const RegisterInfo *reg_info = m_value.GetRegisterInfo(); 602 if (reg_info) 603 { 604 StreamString reg_sstr; 605 m_data.Dump(®_sstr, 0, reg_info->format, reg_info->byte_size, 1, UINT32_MAX, LLDB_INVALID_ADDRESS, 0, 0); 606 m_value_str.swap(reg_sstr.GetString()); 607 } 608 } 609 break; 610 611 default: 612 break; 613 } 614 } 615 616 if (!m_value_did_change && m_old_value_valid) 617 { 618 // The value was gotten successfully, so we consider the 619 // value as changed if the value string differs 620 SetValueDidChange (m_old_value_str != m_value_str); 621 } 622 } 623 } 624 if (m_value_str.empty()) 625 return NULL; 626 return m_value_str.c_str(); 627} 628 629addr_t 630ValueObject::GetPointerValue (lldb::AddressType &address_type, bool scalar_is_load_address) 631{ 632 lldb::addr_t address = LLDB_INVALID_ADDRESS; 633 address_type = eAddressTypeInvalid; 634 switch (GetValue().GetValueType()) 635 { 636 case Value::eValueTypeScalar: 637 if (scalar_is_load_address) 638 { 639 address = m_value.GetScalar().ULongLong(LLDB_INVALID_ADDRESS); 640 address_type = eAddressTypeLoad; 641 } 642 break; 643 644 case Value::eValueTypeLoadAddress: 645 case Value::eValueTypeFileAddress: 646 case Value::eValueTypeHostAddress: 647 { 648 uint32_t data_offset = 0; 649 address = m_data.GetPointer(&data_offset); 650 address_type = m_value.GetValueAddressType(); 651 if (address_type == eAddressTypeInvalid) 652 address_type = eAddressTypeLoad; 653 } 654 break; 655 } 656 return address; 657} 658 659bool 660ValueObject::SetValueFromCString (ExecutionContextScope *exe_scope, const char *value_str) 661{ 662 // Make sure our value is up to date first so that our location and location 663 // type is valid. 664 if (!UpdateValueIfNeeded(exe_scope)) 665 return false; 666 667 uint32_t count = 0; 668 lldb::Encoding encoding = ClangASTType::GetEncoding (GetOpaqueClangQualType(), count); 669 670 char *end = NULL; 671 const size_t byte_size = GetByteSize(); 672 switch (encoding) 673 { 674 case eEncodingInvalid: 675 return false; 676 677 case eEncodingUint: 678 if (byte_size > sizeof(unsigned long long)) 679 { 680 return false; 681 } 682 else 683 { 684 unsigned long long ull_val = strtoull(value_str, &end, 0); 685 if (end && *end != '\0') 686 return false; 687 m_value = ull_val; 688 // Limit the bytes in our m_data appropriately. 689 m_value.GetScalar().GetData (m_data, byte_size); 690 } 691 break; 692 693 case eEncodingSint: 694 if (byte_size > sizeof(long long)) 695 { 696 return false; 697 } 698 else 699 { 700 long long sll_val = strtoll(value_str, &end, 0); 701 if (end && *end != '\0') 702 return false; 703 m_value = sll_val; 704 // Limit the bytes in our m_data appropriately. 705 m_value.GetScalar().GetData (m_data, byte_size); 706 } 707 break; 708 709 case eEncodingIEEE754: 710 { 711 const off_t byte_offset = GetByteOffset(); 712 uint8_t *dst = const_cast<uint8_t *>(m_data.PeekData(byte_offset, byte_size)); 713 if (dst != NULL) 714 { 715 // We are decoding a float into host byte order below, so make 716 // sure m_data knows what it contains. 717 m_data.SetByteOrder(eByteOrderHost); 718 const size_t converted_byte_size = ClangASTContext::ConvertStringToFloatValue ( 719 GetClangAST(), 720 GetOpaqueClangQualType(), 721 value_str, 722 dst, 723 byte_size); 724 725 if (converted_byte_size == byte_size) 726 { 727 } 728 } 729 } 730 break; 731 732 case eEncodingVector: 733 return false; 734 735 default: 736 return false; 737 } 738 739 // If we have made it here the value is in m_data and we should write it 740 // out to the target 741 return Write (); 742} 743 744bool 745ValueObject::Write () 746{ 747 // Clear the update ID so the next time we try and read the value 748 // we try and read it again. 749 m_update_id = 0; 750 751 // TODO: when Value has a method to write a value back, call it from here. 752 return false; 753 754} 755 756lldb::LanguageType 757ValueObject::GetObjectRuntimeLanguage () 758{ 759 void *opaque_qual_type = GetOpaqueClangQualType(); 760 if (opaque_qual_type == NULL) 761 return lldb::eLanguageTypeC; 762 763 // If the type is a reference, then resolve it to what it refers to first: 764 clang::QualType qual_type (clang::QualType::getFromOpaquePtr(opaque_qual_type).getNonReferenceType()); 765 if (qual_type->isAnyPointerType()) 766 { 767 if (qual_type->isObjCObjectPointerType()) 768 return lldb::eLanguageTypeObjC; 769 770 clang::QualType pointee_type (qual_type->getPointeeType()); 771 if (pointee_type->getCXXRecordDeclForPointerType() != NULL) 772 return lldb::eLanguageTypeC_plus_plus; 773 if (pointee_type->isObjCObjectOrInterfaceType()) 774 return lldb::eLanguageTypeObjC; 775 if (pointee_type->isObjCClassType()) 776 return lldb::eLanguageTypeObjC; 777 } 778 else 779 { 780 if (ClangASTContext::IsObjCClassType (opaque_qual_type)) 781 return lldb::eLanguageTypeObjC; 782 if (ClangASTContext::IsCXXClassType (opaque_qual_type)); 783 return lldb::eLanguageTypeC_plus_plus; 784 } 785 786 return lldb::eLanguageTypeC; 787} 788 789void 790ValueObject::AddSyntheticChild (const ConstString &key, ValueObjectSP& valobj_sp) 791{ 792 m_synthetic_children[key] = valobj_sp; 793} 794 795ValueObjectSP 796ValueObject::GetSyntheticChild (const ConstString &key) const 797{ 798 ValueObjectSP synthetic_child_sp; 799 std::map<ConstString, ValueObjectSP>::const_iterator pos = m_synthetic_children.find (key); 800 if (pos != m_synthetic_children.end()) 801 synthetic_child_sp = pos->second; 802 return synthetic_child_sp; 803} 804 805bool 806ValueObject::IsPointerType () 807{ 808 return ClangASTContext::IsPointerType (GetOpaqueClangQualType()); 809} 810 811bool 812ValueObject::IsPointerOrReferenceType () 813{ 814 return ClangASTContext::IsPointerOrReferenceType(GetOpaqueClangQualType()); 815} 816 817ValueObjectSP 818ValueObject::GetSyntheticArrayMemberFromPointer (int32_t index, bool can_create) 819{ 820 ValueObjectSP synthetic_child_sp; 821 if (IsPointerType ()) 822 { 823 char index_str[64]; 824 snprintf(index_str, sizeof(index_str), "[%i]", index); 825 ConstString index_const_str(index_str); 826 // Check if we have already created a synthetic array member in this 827 // valid object. If we have we will re-use it. 828 synthetic_child_sp = GetSyntheticChild (index_const_str); 829 if (!synthetic_child_sp) 830 { 831 // We haven't made a synthetic array member for INDEX yet, so 832 // lets make one and cache it for any future reference. 833 synthetic_child_sp = CreateChildAtIndex(0, true, index); 834 835 // Cache the value if we got one back... 836 if (synthetic_child_sp) 837 AddSyntheticChild(index_const_str, synthetic_child_sp); 838 } 839 } 840 return synthetic_child_sp; 841} 842 843bool 844ValueObject::SetDynamicValue () 845{ 846 if (!IsPointerOrReferenceType()) 847 return false; 848 849 // Check that the runtime class is correct for determining the most specific class. 850 // If it is a C++ class, see if it is dynamic: 851 852 return true; 853} 854