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