1 //===-- NSDictionary.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 "NSDictionary.h" 11 12 #include "lldb/Core/DataBufferHeap.h" 13 #include "lldb/Core/Error.h" 14 #include "lldb/Core/Stream.h" 15 #include "lldb/Core/ValueObject.h" 16 #include "lldb/Core/ValueObjectConstResult.h" 17 #include "lldb/DataFormatters/FormattersHelpers.h" 18 #include "lldb/Host/Endian.h" 19 #include "lldb/Symbol/ClangASTContext.h" 20 #include "lldb/Target/ObjCLanguageRuntime.h" 21 #include "lldb/Target/Target.h" 22 23 #include "clang/AST/DeclCXX.h" 24 25 #include <mutex> 26 27 using namespace lldb; 28 using namespace lldb_private; 29 using namespace lldb_private::formatters; 30 31 std::map<ConstString, CXXFunctionSummaryFormat::Callback>& 32 NSDictionary_Additionals::GetAdditionalSummaries () 33 { 34 static std::map<ConstString, CXXFunctionSummaryFormat::Callback> g_map; 35 return g_map; 36 } 37 38 std::map<ConstString, CXXSyntheticChildren::CreateFrontEndCallback>& 39 NSDictionary_Additionals::GetAdditionalSynthetics () 40 { 41 static std::map<ConstString, CXXSyntheticChildren::CreateFrontEndCallback> g_map; 42 return g_map; 43 } 44 45 static CompilerType 46 GetLLDBNSPairType (TargetSP target_sp) 47 { 48 CompilerType compiler_type; 49 50 ClangASTContext *target_ast_context = target_sp->GetScratchClangASTContext(); 51 52 if (target_ast_context) 53 { 54 ConstString g___lldb_autogen_nspair("__lldb_autogen_nspair"); 55 56 compiler_type = target_ast_context->GetTypeForIdentifier<clang::CXXRecordDecl>(g___lldb_autogen_nspair); 57 58 if (!compiler_type) 59 { 60 compiler_type = target_ast_context->CreateRecordType(NULL, lldb::eAccessPublic, g___lldb_autogen_nspair.GetCString(), clang::TTK_Struct, lldb::eLanguageTypeC); 61 62 if (compiler_type) 63 { 64 ClangASTContext::StartTagDeclarationDefinition(compiler_type); 65 CompilerType id_compiler_type = target_ast_context->GetBasicType (eBasicTypeObjCID); 66 ClangASTContext::AddFieldToRecordType(compiler_type, "key", id_compiler_type, lldb::eAccessPublic, 0); 67 ClangASTContext::AddFieldToRecordType(compiler_type, "value", id_compiler_type, lldb::eAccessPublic, 0); 68 ClangASTContext::CompleteTagDeclarationDefinition(compiler_type); 69 } 70 } 71 } 72 return compiler_type; 73 } 74 75 namespace lldb_private { 76 namespace formatters { 77 class NSDictionaryISyntheticFrontEnd : public SyntheticChildrenFrontEnd 78 { 79 private: 80 struct DataDescriptor_32 81 { 82 uint32_t _used : 26; 83 uint32_t _szidx : 6; 84 }; 85 struct DataDescriptor_64 86 { 87 uint64_t _used : 58; 88 uint32_t _szidx : 6; 89 }; 90 91 struct DictionaryItemDescriptor 92 { 93 lldb::addr_t key_ptr; 94 lldb::addr_t val_ptr; 95 lldb::ValueObjectSP valobj_sp; 96 }; 97 98 public: 99 NSDictionaryISyntheticFrontEnd (lldb::ValueObjectSP valobj_sp); 100 101 virtual size_t 102 CalculateNumChildren (); 103 104 virtual lldb::ValueObjectSP 105 GetChildAtIndex (size_t idx); 106 107 virtual bool 108 Update(); 109 110 virtual bool 111 MightHaveChildren (); 112 113 virtual size_t 114 GetIndexOfChildWithName (const ConstString &name); 115 116 virtual 117 ~NSDictionaryISyntheticFrontEnd (); 118 private: 119 ExecutionContextRef m_exe_ctx_ref; 120 uint8_t m_ptr_size; 121 lldb::ByteOrder m_order; 122 DataDescriptor_32 *m_data_32; 123 DataDescriptor_64 *m_data_64; 124 lldb::addr_t m_data_ptr; 125 CompilerType m_pair_type; 126 std::vector<DictionaryItemDescriptor> m_children; 127 }; 128 129 class NSDictionaryMSyntheticFrontEnd : public SyntheticChildrenFrontEnd 130 { 131 private: 132 struct DataDescriptor_32 133 { 134 uint32_t _used : 26; 135 uint32_t _kvo : 1; 136 uint32_t _size; 137 uint32_t _mutations; 138 uint32_t _objs_addr; 139 uint32_t _keys_addr; 140 }; 141 struct DataDescriptor_64 142 { 143 uint64_t _used : 58; 144 uint32_t _kvo : 1; 145 uint64_t _size; 146 uint64_t _mutations; 147 uint64_t _objs_addr; 148 uint64_t _keys_addr; 149 }; 150 struct DictionaryItemDescriptor 151 { 152 lldb::addr_t key_ptr; 153 lldb::addr_t val_ptr; 154 lldb::ValueObjectSP valobj_sp; 155 }; 156 public: 157 NSDictionaryMSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp); 158 159 virtual size_t 160 CalculateNumChildren (); 161 162 virtual lldb::ValueObjectSP 163 GetChildAtIndex (size_t idx); 164 165 virtual bool 166 Update(); 167 168 virtual bool 169 MightHaveChildren (); 170 171 virtual size_t 172 GetIndexOfChildWithName (const ConstString &name); 173 174 virtual 175 ~NSDictionaryMSyntheticFrontEnd (); 176 private: 177 ExecutionContextRef m_exe_ctx_ref; 178 uint8_t m_ptr_size; 179 lldb::ByteOrder m_order; 180 DataDescriptor_32 *m_data_32; 181 DataDescriptor_64 *m_data_64; 182 CompilerType m_pair_type; 183 std::vector<DictionaryItemDescriptor> m_children; 184 }; 185 186 class NSDictionaryCodeRunningSyntheticFrontEnd : public SyntheticChildrenFrontEnd 187 { 188 public: 189 NSDictionaryCodeRunningSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp); 190 191 virtual size_t 192 CalculateNumChildren (); 193 194 virtual lldb::ValueObjectSP 195 GetChildAtIndex (size_t idx); 196 197 virtual bool 198 Update(); 199 200 virtual bool 201 MightHaveChildren (); 202 203 virtual size_t 204 GetIndexOfChildWithName (const ConstString &name); 205 206 virtual 207 ~NSDictionaryCodeRunningSyntheticFrontEnd (); 208 }; 209 } 210 } 211 212 template<bool name_entries> 213 bool 214 lldb_private::formatters::NSDictionarySummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options) 215 { 216 ProcessSP process_sp = valobj.GetProcessSP(); 217 if (!process_sp) 218 return false; 219 220 ObjCLanguageRuntime* runtime = (ObjCLanguageRuntime*)process_sp->GetLanguageRuntime(lldb::eLanguageTypeObjC); 221 222 if (!runtime) 223 return false; 224 225 ObjCLanguageRuntime::ClassDescriptorSP descriptor(runtime->GetClassDescriptor(valobj)); 226 227 if (!descriptor.get() || !descriptor->IsValid()) 228 return false; 229 230 uint32_t ptr_size = process_sp->GetAddressByteSize(); 231 bool is_64bit = (ptr_size == 8); 232 233 lldb::addr_t valobj_addr = valobj.GetValueAsUnsigned(0); 234 235 if (!valobj_addr) 236 return false; 237 238 uint64_t value = 0; 239 240 ConstString class_name_cs = descriptor->GetClassName(); 241 const char* class_name = class_name_cs.GetCString(); 242 243 if (!class_name || !*class_name) 244 return false; 245 246 if (!strcmp(class_name,"__NSDictionaryI")) 247 { 248 Error error; 249 value = process_sp->ReadUnsignedIntegerFromMemory(valobj_addr + ptr_size, ptr_size, 0, error); 250 if (error.Fail()) 251 return false; 252 value &= (is_64bit ? ~0xFC00000000000000UL : ~0xFC000000U); 253 } 254 else if (!strcmp(class_name,"__NSDictionaryM")) 255 { 256 Error error; 257 value = process_sp->ReadUnsignedIntegerFromMemory(valobj_addr + ptr_size, ptr_size, 0, error); 258 if (error.Fail()) 259 return false; 260 value &= (is_64bit ? ~0xFC00000000000000UL : ~0xFC000000U); 261 } 262 /*else if (!strcmp(class_name,"__NSCFDictionary")) 263 { 264 Error error; 265 value = process_sp->ReadUnsignedIntegerFromMemory(valobj_addr + (is_64bit ? 20 : 12), 4, 0, error); 266 if (error.Fail()) 267 return false; 268 if (is_64bit) 269 value &= ~0x0f1f000000000000UL; 270 }*/ 271 else 272 { 273 auto& map(NSDictionary_Additionals::GetAdditionalSummaries()); 274 auto iter = map.find(class_name_cs), end = map.end(); 275 if (iter != end) 276 return iter->second(valobj, stream, options); 277 if (!ExtractValueFromObjCExpression(valobj, "int", "count", value)) 278 return false; 279 } 280 281 stream.Printf("%s%" PRIu64 " %s%s", 282 (name_entries ? "@\"" : ""), 283 value, 284 (name_entries ? (value == 1 ? "entry" : "entries") : (value == 1 ? "key/value pair" : "key/value pairs")), 285 (name_entries ? "\"" : "")); 286 return true; 287 } 288 289 SyntheticChildrenFrontEnd* lldb_private::formatters::NSDictionarySyntheticFrontEndCreator (CXXSyntheticChildren* synth, lldb::ValueObjectSP valobj_sp) 290 { 291 lldb::ProcessSP process_sp (valobj_sp->GetProcessSP()); 292 if (!process_sp) 293 return NULL; 294 ObjCLanguageRuntime *runtime = (ObjCLanguageRuntime*)process_sp->GetLanguageRuntime(lldb::eLanguageTypeObjC); 295 if (!runtime) 296 return NULL; 297 298 if (!valobj_sp->IsPointerType()) 299 { 300 Error error; 301 valobj_sp = valobj_sp->AddressOf(error); 302 if (error.Fail() || !valobj_sp) 303 return NULL; 304 } 305 306 ObjCLanguageRuntime::ClassDescriptorSP descriptor(runtime->GetClassDescriptor(*valobj_sp.get())); 307 308 if (!descriptor.get() || !descriptor->IsValid()) 309 return NULL; 310 311 ConstString class_name_cs = descriptor->GetClassName(); 312 const char* class_name = class_name_cs.GetCString(); 313 314 if (!class_name || !*class_name) 315 return NULL; 316 317 if (!strcmp(class_name,"__NSDictionaryI")) 318 { 319 return (new NSDictionaryISyntheticFrontEnd(valobj_sp)); 320 } 321 else if (!strcmp(class_name,"__NSDictionaryM")) 322 { 323 return (new NSDictionaryMSyntheticFrontEnd(valobj_sp)); 324 } 325 else 326 { 327 auto& map(NSDictionary_Additionals::GetAdditionalSynthetics()); 328 auto iter = map.find(class_name_cs), end = map.end(); 329 if (iter != end) 330 return iter->second(synth, valobj_sp); 331 return (new NSDictionaryCodeRunningSyntheticFrontEnd(valobj_sp)); 332 } 333 } 334 335 lldb_private::formatters::NSDictionaryCodeRunningSyntheticFrontEnd::NSDictionaryCodeRunningSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp) : 336 SyntheticChildrenFrontEnd(*valobj_sp.get()) 337 {} 338 339 size_t 340 lldb_private::formatters::NSDictionaryCodeRunningSyntheticFrontEnd::CalculateNumChildren () 341 { 342 uint64_t count = 0; 343 if (ExtractValueFromObjCExpression(m_backend, "int", "count", count)) 344 return count; 345 return 0; 346 } 347 348 lldb::ValueObjectSP 349 lldb_private::formatters::NSDictionaryCodeRunningSyntheticFrontEnd::GetChildAtIndex (size_t idx) 350 { 351 StreamString idx_name; 352 idx_name.Printf("[%" PRIu64 "]", (uint64_t)idx); 353 StreamString key_fetcher_expr; 354 key_fetcher_expr.Printf("(id)[(NSArray*)[(id)0x%" PRIx64 " allKeys] objectAtIndex:%" PRIu64 "]", m_backend.GetPointerValue(), (uint64_t)idx); 355 StreamString value_fetcher_expr; 356 value_fetcher_expr.Printf("(id)[(id)0x%" PRIx64 " objectForKey:(%s)]",m_backend.GetPointerValue(),key_fetcher_expr.GetData()); 357 StreamString object_fetcher_expr; 358 object_fetcher_expr.Printf("struct __lldb_autogen_nspair { id key; id value; } _lldb_valgen_item; _lldb_valgen_item.key = %s; _lldb_valgen_item.value = %s; _lldb_valgen_item;",key_fetcher_expr.GetData(),value_fetcher_expr.GetData()); 359 lldb::ValueObjectSP child_sp; 360 EvaluateExpressionOptions options; 361 options.SetKeepInMemory(true); 362 m_backend.GetTargetSP()->EvaluateExpression(object_fetcher_expr.GetData(), 363 GetViableFrame(m_backend.GetTargetSP().get()), 364 child_sp, 365 options); 366 if (child_sp) 367 child_sp->SetName(ConstString(idx_name.GetData())); 368 return child_sp; 369 } 370 371 bool 372 lldb_private::formatters::NSDictionaryCodeRunningSyntheticFrontEnd::Update() 373 { 374 return false; 375 } 376 377 bool 378 lldb_private::formatters::NSDictionaryCodeRunningSyntheticFrontEnd::MightHaveChildren () 379 { 380 return true; 381 } 382 383 size_t 384 lldb_private::formatters::NSDictionaryCodeRunningSyntheticFrontEnd::GetIndexOfChildWithName (const ConstString &name) 385 { 386 return 0; 387 } 388 389 lldb_private::formatters::NSDictionaryCodeRunningSyntheticFrontEnd::~NSDictionaryCodeRunningSyntheticFrontEnd () 390 {} 391 392 lldb_private::formatters::NSDictionaryISyntheticFrontEnd::NSDictionaryISyntheticFrontEnd (lldb::ValueObjectSP valobj_sp) : 393 SyntheticChildrenFrontEnd(*valobj_sp.get()), 394 m_exe_ctx_ref(), 395 m_ptr_size(8), 396 m_order(lldb::eByteOrderInvalid), 397 m_data_32(NULL), 398 m_data_64(NULL), 399 m_pair_type() 400 { 401 } 402 403 lldb_private::formatters::NSDictionaryISyntheticFrontEnd::~NSDictionaryISyntheticFrontEnd () 404 { 405 delete m_data_32; 406 m_data_32 = NULL; 407 delete m_data_64; 408 m_data_64 = NULL; 409 } 410 411 size_t 412 lldb_private::formatters::NSDictionaryISyntheticFrontEnd::GetIndexOfChildWithName (const ConstString &name) 413 { 414 const char* item_name = name.GetCString(); 415 uint32_t idx = ExtractIndexFromString(item_name); 416 if (idx < UINT32_MAX && idx >= CalculateNumChildren()) 417 return UINT32_MAX; 418 return idx; 419 } 420 421 size_t 422 lldb_private::formatters::NSDictionaryISyntheticFrontEnd::CalculateNumChildren () 423 { 424 if (!m_data_32 && !m_data_64) 425 return 0; 426 return (m_data_32 ? m_data_32->_used : m_data_64->_used); 427 } 428 429 bool 430 lldb_private::formatters::NSDictionaryISyntheticFrontEnd::Update() 431 { 432 m_children.clear(); 433 delete m_data_32; 434 m_data_32 = NULL; 435 delete m_data_64; 436 m_data_64 = NULL; 437 m_ptr_size = 0; 438 ValueObjectSP valobj_sp = m_backend.GetSP(); 439 if (!valobj_sp) 440 return false; 441 m_exe_ctx_ref = valobj_sp->GetExecutionContextRef(); 442 Error error; 443 error.Clear(); 444 lldb::ProcessSP process_sp(valobj_sp->GetProcessSP()); 445 if (!process_sp) 446 return false; 447 m_ptr_size = process_sp->GetAddressByteSize(); 448 m_order = process_sp->GetByteOrder(); 449 uint64_t data_location = valobj_sp->GetValueAsUnsigned(0) + m_ptr_size; 450 if (m_ptr_size == 4) 451 { 452 m_data_32 = new DataDescriptor_32(); 453 process_sp->ReadMemory (data_location, m_data_32, sizeof(DataDescriptor_32), error); 454 } 455 else 456 { 457 m_data_64 = new DataDescriptor_64(); 458 process_sp->ReadMemory (data_location, m_data_64, sizeof(DataDescriptor_64), error); 459 } 460 if (error.Fail()) 461 return false; 462 m_data_ptr = data_location + m_ptr_size; 463 return false; 464 } 465 466 bool 467 lldb_private::formatters::NSDictionaryISyntheticFrontEnd::MightHaveChildren () 468 { 469 return true; 470 } 471 472 lldb::ValueObjectSP 473 lldb_private::formatters::NSDictionaryISyntheticFrontEnd::GetChildAtIndex (size_t idx) 474 { 475 uint32_t num_children = CalculateNumChildren(); 476 477 if (idx >= num_children) 478 return lldb::ValueObjectSP(); 479 480 if (m_children.empty()) 481 { 482 // do the scan phase 483 lldb::addr_t key_at_idx = 0, val_at_idx = 0; 484 485 uint32_t tries = 0; 486 uint32_t test_idx = 0; 487 488 while(tries < num_children) 489 { 490 key_at_idx = m_data_ptr + (2*test_idx * m_ptr_size); 491 val_at_idx = key_at_idx + m_ptr_size; 492 ProcessSP process_sp = m_exe_ctx_ref.GetProcessSP(); 493 if (!process_sp) 494 return lldb::ValueObjectSP(); 495 Error error; 496 key_at_idx = process_sp->ReadPointerFromMemory(key_at_idx, error); 497 if (error.Fail()) 498 return lldb::ValueObjectSP(); 499 val_at_idx = process_sp->ReadPointerFromMemory(val_at_idx, error); 500 if (error.Fail()) 501 return lldb::ValueObjectSP(); 502 503 test_idx++; 504 505 if (!key_at_idx || !val_at_idx) 506 continue; 507 tries++; 508 509 DictionaryItemDescriptor descriptor = {key_at_idx,val_at_idx,lldb::ValueObjectSP()}; 510 511 m_children.push_back(descriptor); 512 } 513 } 514 515 if (idx >= m_children.size()) // should never happen 516 return lldb::ValueObjectSP(); 517 518 DictionaryItemDescriptor &dict_item = m_children[idx]; 519 if (!dict_item.valobj_sp) 520 { 521 if (!m_pair_type.IsValid()) 522 { 523 TargetSP target_sp(m_backend.GetTargetSP()); 524 if (!target_sp) 525 return ValueObjectSP(); 526 m_pair_type = GetLLDBNSPairType(target_sp); 527 } 528 if (!m_pair_type.IsValid()) 529 return ValueObjectSP(); 530 531 DataBufferSP buffer_sp(new DataBufferHeap(2*m_ptr_size,0)); 532 533 if (m_ptr_size == 8) 534 { 535 uint64_t *data_ptr = (uint64_t *)buffer_sp->GetBytes(); 536 *data_ptr = dict_item.key_ptr; 537 *(data_ptr+1) = dict_item.val_ptr; 538 } 539 else 540 { 541 uint32_t *data_ptr = (uint32_t *)buffer_sp->GetBytes(); 542 *data_ptr = dict_item.key_ptr; 543 *(data_ptr+1) = dict_item.val_ptr; 544 } 545 546 StreamString idx_name; 547 idx_name.Printf("[%" PRIu64 "]", (uint64_t)idx); 548 DataExtractor data(buffer_sp, m_order, m_ptr_size); 549 dict_item.valobj_sp = CreateValueObjectFromData(idx_name.GetData(), 550 data, 551 m_exe_ctx_ref, 552 m_pair_type); 553 } 554 return dict_item.valobj_sp; 555 } 556 557 lldb_private::formatters::NSDictionaryMSyntheticFrontEnd::NSDictionaryMSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp) : 558 SyntheticChildrenFrontEnd(*valobj_sp.get()), 559 m_exe_ctx_ref(), 560 m_ptr_size(8), 561 m_order(lldb::eByteOrderInvalid), 562 m_data_32(NULL), 563 m_data_64(NULL), 564 m_pair_type() 565 { 566 } 567 568 lldb_private::formatters::NSDictionaryMSyntheticFrontEnd::~NSDictionaryMSyntheticFrontEnd () 569 { 570 delete m_data_32; 571 m_data_32 = NULL; 572 delete m_data_64; 573 m_data_64 = NULL; 574 } 575 576 size_t 577 lldb_private::formatters::NSDictionaryMSyntheticFrontEnd::GetIndexOfChildWithName (const ConstString &name) 578 { 579 const char* item_name = name.GetCString(); 580 uint32_t idx = ExtractIndexFromString(item_name); 581 if (idx < UINT32_MAX && idx >= CalculateNumChildren()) 582 return UINT32_MAX; 583 return idx; 584 } 585 586 size_t 587 lldb_private::formatters::NSDictionaryMSyntheticFrontEnd::CalculateNumChildren () 588 { 589 if (!m_data_32 && !m_data_64) 590 return 0; 591 return (m_data_32 ? m_data_32->_used : m_data_64->_used); 592 } 593 594 bool 595 lldb_private::formatters::NSDictionaryMSyntheticFrontEnd::Update() 596 { 597 m_children.clear(); 598 ValueObjectSP valobj_sp = m_backend.GetSP(); 599 m_ptr_size = 0; 600 delete m_data_32; 601 m_data_32 = NULL; 602 delete m_data_64; 603 m_data_64 = NULL; 604 if (!valobj_sp) 605 return false; 606 m_exe_ctx_ref = valobj_sp->GetExecutionContextRef(); 607 Error error; 608 error.Clear(); 609 lldb::ProcessSP process_sp(valobj_sp->GetProcessSP()); 610 if (!process_sp) 611 return false; 612 m_ptr_size = process_sp->GetAddressByteSize(); 613 m_order = process_sp->GetByteOrder(); 614 uint64_t data_location = valobj_sp->GetValueAsUnsigned(0) + m_ptr_size; 615 if (m_ptr_size == 4) 616 { 617 m_data_32 = new DataDescriptor_32(); 618 process_sp->ReadMemory (data_location, m_data_32, sizeof(DataDescriptor_32), error); 619 } 620 else 621 { 622 m_data_64 = new DataDescriptor_64(); 623 process_sp->ReadMemory (data_location, m_data_64, sizeof(DataDescriptor_64), error); 624 } 625 if (error.Fail()) 626 return false; 627 return false; 628 } 629 630 bool 631 lldb_private::formatters::NSDictionaryMSyntheticFrontEnd::MightHaveChildren () 632 { 633 return true; 634 } 635 636 lldb::ValueObjectSP 637 lldb_private::formatters::NSDictionaryMSyntheticFrontEnd::GetChildAtIndex (size_t idx) 638 { 639 lldb::addr_t m_keys_ptr = (m_data_32 ? m_data_32->_keys_addr : m_data_64->_keys_addr); 640 lldb::addr_t m_values_ptr = (m_data_32 ? m_data_32->_objs_addr : m_data_64->_objs_addr); 641 642 uint32_t num_children = CalculateNumChildren(); 643 644 if (idx >= num_children) 645 return lldb::ValueObjectSP(); 646 647 if (m_children.empty()) 648 { 649 // do the scan phase 650 lldb::addr_t key_at_idx = 0, val_at_idx = 0; 651 652 uint32_t tries = 0; 653 uint32_t test_idx = 0; 654 655 while(tries < num_children) 656 { 657 key_at_idx = m_keys_ptr + (test_idx * m_ptr_size); 658 val_at_idx = m_values_ptr + (test_idx * m_ptr_size);; 659 ProcessSP process_sp = m_exe_ctx_ref.GetProcessSP(); 660 if (!process_sp) 661 return lldb::ValueObjectSP(); 662 Error error; 663 key_at_idx = process_sp->ReadPointerFromMemory(key_at_idx, error); 664 if (error.Fail()) 665 return lldb::ValueObjectSP(); 666 val_at_idx = process_sp->ReadPointerFromMemory(val_at_idx, error); 667 if (error.Fail()) 668 return lldb::ValueObjectSP(); 669 670 test_idx++; 671 672 if (!key_at_idx || !val_at_idx) 673 continue; 674 tries++; 675 676 DictionaryItemDescriptor descriptor = {key_at_idx,val_at_idx,lldb::ValueObjectSP()}; 677 678 m_children.push_back(descriptor); 679 } 680 } 681 682 if (idx >= m_children.size()) // should never happen 683 return lldb::ValueObjectSP(); 684 685 DictionaryItemDescriptor &dict_item = m_children[idx]; 686 if (!dict_item.valobj_sp) 687 { 688 if (!m_pair_type.IsValid()) 689 { 690 TargetSP target_sp(m_backend.GetTargetSP()); 691 if (!target_sp) 692 return ValueObjectSP(); 693 m_pair_type = GetLLDBNSPairType(target_sp); 694 } 695 if (!m_pair_type.IsValid()) 696 return ValueObjectSP(); 697 698 DataBufferSP buffer_sp(new DataBufferHeap(2*m_ptr_size,0)); 699 700 if (m_ptr_size == 8) 701 { 702 uint64_t *data_ptr = (uint64_t *)buffer_sp->GetBytes(); 703 *data_ptr = dict_item.key_ptr; 704 *(data_ptr+1) = dict_item.val_ptr; 705 } 706 else 707 { 708 uint32_t *data_ptr = (uint32_t *)buffer_sp->GetBytes(); 709 *data_ptr = dict_item.key_ptr; 710 *(data_ptr+1) = dict_item.val_ptr; 711 } 712 713 StreamString idx_name; 714 idx_name.Printf("[%" PRIu64 "]", (uint64_t)idx); 715 DataExtractor data(buffer_sp, m_order, m_ptr_size); 716 dict_item.valobj_sp = CreateValueObjectFromData(idx_name.GetData(), 717 data, 718 m_exe_ctx_ref, 719 m_pair_type); 720 } 721 return dict_item.valobj_sp; 722 } 723 724 template bool 725 lldb_private::formatters::NSDictionarySummaryProvider<true> (ValueObject&, Stream&, const TypeSummaryOptions&) ; 726 727 template bool 728 lldb_private::formatters::NSDictionarySummaryProvider<false> (ValueObject&, Stream&, const TypeSummaryOptions&) ; 729