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