1254721Semaste//===-- NSDictionary.cpp ------------------------------------------*- C++ -*-===// 2254721Semaste// 3254721Semaste// The LLVM Compiler Infrastructure 4254721Semaste// 5254721Semaste// This file is distributed under the University of Illinois Open Source 6254721Semaste// License. See LICENSE.TXT for details. 7254721Semaste// 8254721Semaste//===----------------------------------------------------------------------===// 9254721Semaste 10254721Semaste#include "lldb/lldb-python.h" 11254721Semaste 12254721Semaste#include "lldb/DataFormatters/CXXFormatterFunctions.h" 13254721Semaste 14254721Semaste#include "lldb/Core/DataBufferHeap.h" 15254721Semaste#include "lldb/Core/Error.h" 16254721Semaste#include "lldb/Core/Stream.h" 17254721Semaste#include "lldb/Core/ValueObject.h" 18254721Semaste#include "lldb/Core/ValueObjectConstResult.h" 19254721Semaste#include "lldb/Host/Endian.h" 20254721Semaste#include "lldb/Symbol/ClangASTContext.h" 21254721Semaste#include "lldb/Target/ObjCLanguageRuntime.h" 22254721Semaste#include "lldb/Target/Target.h" 23254721Semaste 24254721Semaste#include "clang/AST/DeclCXX.h" 25254721Semaste 26254721Semasteusing namespace lldb; 27254721Semasteusing namespace lldb_private; 28254721Semasteusing namespace lldb_private::formatters; 29254721Semaste 30254721Semastestatic ClangASTType 31254721SemasteGetLLDBNSPairType (TargetSP target_sp) 32254721Semaste{ 33254721Semaste ClangASTType clang_type; 34254721Semaste 35254721Semaste ClangASTContext *target_ast_context = target_sp->GetScratchClangASTContext(); 36254721Semaste 37254721Semaste if (target_ast_context) 38254721Semaste { 39254721Semaste clang::ASTContext *ast = target_ast_context->getASTContext(); 40254721Semaste 41254721Semaste if (ast) 42254721Semaste { 43254721Semaste const char* type_name = "__lldb_autogen_nspair"; 44254721Semaste 45254721Semaste clang::IdentifierInfo &myIdent = ast->Idents.get(type_name); 46254721Semaste clang::DeclarationName myName = ast->DeclarationNames.getIdentifier(&myIdent); 47254721Semaste 48254721Semaste clang::DeclContext::lookup_const_result result = ast->getTranslationUnitDecl()->lookup(myName); 49254721Semaste 50254721Semaste for (clang::NamedDecl *named_decl : result) 51254721Semaste { 52254721Semaste if (const clang::CXXRecordDecl *record_decl = llvm::dyn_cast<clang::CXXRecordDecl>(named_decl)) 53254721Semaste { 54254721Semaste clang_type.SetClangType(ast, clang::QualType(record_decl->getTypeForDecl(), 0)); 55254721Semaste break; 56254721Semaste } 57254721Semaste else 58254721Semaste { 59254721Semaste // somebody else (the user?) has defined a type with the magic name already - fail!!! 60254721Semaste return clang_type; 61254721Semaste } 62254721Semaste } 63254721Semaste 64254721Semaste if (!clang_type) 65254721Semaste { 66254721Semaste clang_type = target_ast_context->CreateRecordType(NULL, lldb::eAccessPublic, type_name, clang::TTK_Struct, lldb::eLanguageTypeC); 67254721Semaste 68254721Semaste if (clang_type) 69254721Semaste { 70254721Semaste clang_type.StartTagDeclarationDefinition(); 71254721Semaste ClangASTType id_clang_type = target_ast_context->GetBasicType (eBasicTypeObjCID); 72254721Semaste clang_type.AddFieldToRecordType("key", id_clang_type, lldb::eAccessPublic, 0); 73254721Semaste clang_type.AddFieldToRecordType("value", id_clang_type, lldb::eAccessPublic, 0); 74254721Semaste clang_type.CompleteTagDeclarationDefinition(); 75254721Semaste } 76254721Semaste } 77254721Semaste } 78254721Semaste } 79254721Semaste return clang_type; 80254721Semaste} 81254721Semaste 82254721Semastetemplate<bool name_entries> 83254721Semastebool 84254721Semastelldb_private::formatters::NSDictionarySummaryProvider (ValueObject& valobj, Stream& stream) 85254721Semaste{ 86254721Semaste ProcessSP process_sp = valobj.GetProcessSP(); 87254721Semaste if (!process_sp) 88254721Semaste return false; 89254721Semaste 90254721Semaste ObjCLanguageRuntime* runtime = (ObjCLanguageRuntime*)process_sp->GetLanguageRuntime(lldb::eLanguageTypeObjC); 91254721Semaste 92254721Semaste if (!runtime) 93254721Semaste return false; 94254721Semaste 95254721Semaste ObjCLanguageRuntime::ClassDescriptorSP descriptor(runtime->GetClassDescriptor(valobj)); 96254721Semaste 97254721Semaste if (!descriptor.get() || !descriptor->IsValid()) 98254721Semaste return false; 99254721Semaste 100254721Semaste uint32_t ptr_size = process_sp->GetAddressByteSize(); 101254721Semaste bool is_64bit = (ptr_size == 8); 102254721Semaste 103254721Semaste lldb::addr_t valobj_addr = valobj.GetValueAsUnsigned(0); 104254721Semaste 105254721Semaste if (!valobj_addr) 106254721Semaste return false; 107254721Semaste 108254721Semaste uint64_t value = 0; 109254721Semaste 110254721Semaste const char* class_name = descriptor->GetClassName().GetCString(); 111254721Semaste 112254721Semaste if (!class_name || !*class_name) 113254721Semaste return false; 114254721Semaste 115254721Semaste if (!strcmp(class_name,"__NSDictionaryI")) 116254721Semaste { 117254721Semaste Error error; 118254721Semaste value = process_sp->ReadUnsignedIntegerFromMemory(valobj_addr + ptr_size, ptr_size, 0, error); 119254721Semaste if (error.Fail()) 120254721Semaste return false; 121254721Semaste value &= (is_64bit ? ~0xFC00000000000000UL : ~0xFC000000U); 122254721Semaste } 123254721Semaste else if (!strcmp(class_name,"__NSDictionaryM")) 124254721Semaste { 125254721Semaste Error error; 126254721Semaste value = process_sp->ReadUnsignedIntegerFromMemory(valobj_addr + ptr_size, ptr_size, 0, error); 127254721Semaste if (error.Fail()) 128254721Semaste return false; 129254721Semaste value &= (is_64bit ? ~0xFC00000000000000UL : ~0xFC000000U); 130254721Semaste } 131254721Semaste /*else if (!strcmp(class_name,"__NSCFDictionary")) 132254721Semaste { 133254721Semaste Error error; 134254721Semaste value = process_sp->ReadUnsignedIntegerFromMemory(valobj_addr + (is_64bit ? 20 : 12), 4, 0, error); 135254721Semaste if (error.Fail()) 136254721Semaste return false; 137254721Semaste if (is_64bit) 138254721Semaste value &= ~0x0f1f000000000000UL; 139254721Semaste }*/ 140254721Semaste else 141254721Semaste { 142254721Semaste if (!ExtractValueFromObjCExpression(valobj, "int", "count", value)) 143254721Semaste return false; 144254721Semaste } 145254721Semaste 146254721Semaste stream.Printf("%s%" PRIu64 " %s%s", 147254721Semaste (name_entries ? "@\"" : ""), 148254721Semaste value, 149254721Semaste (name_entries ? (value == 1 ? "entry" : "entries") : (value == 1 ? "key/value pair" : "key/value pairs")), 150254721Semaste (name_entries ? "\"" : "")); 151254721Semaste return true; 152254721Semaste} 153254721Semaste 154254721SemasteSyntheticChildrenFrontEnd* lldb_private::formatters::NSDictionarySyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP valobj_sp) 155254721Semaste{ 156254721Semaste 157254721Semaste lldb::ProcessSP process_sp (valobj_sp->GetProcessSP()); 158254721Semaste if (!process_sp) 159254721Semaste return NULL; 160254721Semaste ObjCLanguageRuntime *runtime = (ObjCLanguageRuntime*)process_sp->GetLanguageRuntime(lldb::eLanguageTypeObjC); 161254721Semaste if (!runtime) 162254721Semaste return NULL; 163254721Semaste 164254721Semaste if (!valobj_sp->IsPointerType()) 165254721Semaste { 166254721Semaste Error error; 167254721Semaste valobj_sp = valobj_sp->AddressOf(error); 168254721Semaste if (error.Fail() || !valobj_sp) 169254721Semaste return NULL; 170254721Semaste } 171254721Semaste 172254721Semaste ObjCLanguageRuntime::ClassDescriptorSP descriptor(runtime->GetClassDescriptor(*valobj_sp.get())); 173254721Semaste 174254721Semaste if (!descriptor.get() || !descriptor->IsValid()) 175254721Semaste return NULL; 176254721Semaste 177254721Semaste const char* class_name = descriptor->GetClassName().GetCString(); 178254721Semaste 179254721Semaste if (!class_name || !*class_name) 180254721Semaste return NULL; 181254721Semaste 182254721Semaste if (!strcmp(class_name,"__NSDictionaryI")) 183254721Semaste { 184254721Semaste return (new NSDictionaryISyntheticFrontEnd(valobj_sp)); 185254721Semaste } 186254721Semaste else if (!strcmp(class_name,"__NSDictionaryM")) 187254721Semaste { 188254721Semaste return (new NSDictionaryMSyntheticFrontEnd(valobj_sp)); 189254721Semaste } 190254721Semaste else 191254721Semaste { 192254721Semaste return (new NSDictionaryCodeRunningSyntheticFrontEnd(valobj_sp)); 193254721Semaste } 194254721Semaste} 195254721Semaste 196254721Semastelldb_private::formatters::NSDictionaryCodeRunningSyntheticFrontEnd::NSDictionaryCodeRunningSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp) : 197254721SemasteSyntheticChildrenFrontEnd(*valobj_sp.get()) 198254721Semaste{} 199254721Semaste 200254721Semastesize_t 201254721Semastelldb_private::formatters::NSDictionaryCodeRunningSyntheticFrontEnd::CalculateNumChildren () 202254721Semaste{ 203254721Semaste uint64_t count = 0; 204254721Semaste if (ExtractValueFromObjCExpression(m_backend, "int", "count", count)) 205254721Semaste return count; 206254721Semaste return 0; 207254721Semaste} 208254721Semaste 209254721Semastelldb::ValueObjectSP 210254721Semastelldb_private::formatters::NSDictionaryCodeRunningSyntheticFrontEnd::GetChildAtIndex (size_t idx) 211254721Semaste{ 212254721Semaste StreamString idx_name; 213254721Semaste idx_name.Printf("[%zu]",idx); 214254721Semaste StreamString key_fetcher_expr; 215254721Semaste key_fetcher_expr.Printf("(id)[(NSArray*)[(id)0x%" PRIx64 " allKeys] objectAtIndex:%zu]",m_backend.GetPointerValue(),idx); 216254721Semaste StreamString value_fetcher_expr; 217254721Semaste value_fetcher_expr.Printf("(id)[(id)0x%" PRIx64 " objectForKey:(%s)]",m_backend.GetPointerValue(),key_fetcher_expr.GetData()); 218254721Semaste StreamString object_fetcher_expr; 219254721Semaste 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()); 220254721Semaste lldb::ValueObjectSP child_sp; 221263367Semaste EvaluateExpressionOptions options; 222263367Semaste options.SetKeepInMemory(true); 223254721Semaste m_backend.GetTargetSP()->EvaluateExpression(object_fetcher_expr.GetData(), m_backend.GetFrameSP().get(), child_sp, 224263367Semaste options); 225254721Semaste if (child_sp) 226254721Semaste child_sp->SetName(ConstString(idx_name.GetData())); 227254721Semaste return child_sp; 228254721Semaste} 229254721Semaste 230254721Semastebool 231254721Semastelldb_private::formatters::NSDictionaryCodeRunningSyntheticFrontEnd::Update() 232254721Semaste{ 233254721Semaste return false; 234254721Semaste} 235254721Semaste 236254721Semastebool 237254721Semastelldb_private::formatters::NSDictionaryCodeRunningSyntheticFrontEnd::MightHaveChildren () 238254721Semaste{ 239254721Semaste return true; 240254721Semaste} 241254721Semaste 242254721Semastesize_t 243254721Semastelldb_private::formatters::NSDictionaryCodeRunningSyntheticFrontEnd::GetIndexOfChildWithName (const ConstString &name) 244254721Semaste{ 245254721Semaste return 0; 246254721Semaste} 247254721Semaste 248254721Semastelldb_private::formatters::NSDictionaryCodeRunningSyntheticFrontEnd::~NSDictionaryCodeRunningSyntheticFrontEnd () 249254721Semaste{} 250254721Semaste 251254721Semastelldb_private::formatters::NSDictionaryISyntheticFrontEnd::NSDictionaryISyntheticFrontEnd (lldb::ValueObjectSP valobj_sp) : 252254721SemasteSyntheticChildrenFrontEnd(*valobj_sp.get()), 253254721Semastem_exe_ctx_ref(), 254254721Semastem_ptr_size(8), 255254721Semastem_order(lldb::eByteOrderInvalid), 256254721Semastem_data_32(NULL), 257254721Semastem_data_64(NULL), 258254721Semastem_pair_type() 259254721Semaste{ 260254721Semaste} 261254721Semaste 262254721Semastelldb_private::formatters::NSDictionaryISyntheticFrontEnd::~NSDictionaryISyntheticFrontEnd () 263254721Semaste{ 264254721Semaste delete m_data_32; 265254721Semaste m_data_32 = NULL; 266254721Semaste delete m_data_64; 267254721Semaste m_data_64 = NULL; 268254721Semaste} 269254721Semaste 270254721Semastesize_t 271254721Semastelldb_private::formatters::NSDictionaryISyntheticFrontEnd::GetIndexOfChildWithName (const ConstString &name) 272254721Semaste{ 273254721Semaste const char* item_name = name.GetCString(); 274254721Semaste uint32_t idx = ExtractIndexFromString(item_name); 275254721Semaste if (idx < UINT32_MAX && idx >= CalculateNumChildren()) 276254721Semaste return UINT32_MAX; 277254721Semaste return idx; 278254721Semaste} 279254721Semaste 280254721Semastesize_t 281254721Semastelldb_private::formatters::NSDictionaryISyntheticFrontEnd::CalculateNumChildren () 282254721Semaste{ 283254721Semaste if (!m_data_32 && !m_data_64) 284254721Semaste return 0; 285254721Semaste return (m_data_32 ? m_data_32->_used : m_data_64->_used); 286254721Semaste} 287254721Semaste 288254721Semastebool 289254721Semastelldb_private::formatters::NSDictionaryISyntheticFrontEnd::Update() 290254721Semaste{ 291254721Semaste m_children.clear(); 292254721Semaste delete m_data_32; 293254721Semaste m_data_32 = NULL; 294254721Semaste delete m_data_64; 295254721Semaste m_data_64 = NULL; 296254721Semaste m_ptr_size = 0; 297254721Semaste ValueObjectSP valobj_sp = m_backend.GetSP(); 298254721Semaste if (!valobj_sp) 299254721Semaste return false; 300254721Semaste m_exe_ctx_ref = valobj_sp->GetExecutionContextRef(); 301254721Semaste Error error; 302254721Semaste error.Clear(); 303254721Semaste lldb::ProcessSP process_sp(valobj_sp->GetProcessSP()); 304254721Semaste if (!process_sp) 305254721Semaste return false; 306254721Semaste m_ptr_size = process_sp->GetAddressByteSize(); 307254721Semaste m_order = process_sp->GetByteOrder(); 308254721Semaste uint64_t data_location = valobj_sp->GetValueAsUnsigned(0) + m_ptr_size; 309254721Semaste if (m_ptr_size == 4) 310254721Semaste { 311254721Semaste m_data_32 = new DataDescriptor_32(); 312254721Semaste process_sp->ReadMemory (data_location, m_data_32, sizeof(DataDescriptor_32), error); 313254721Semaste } 314254721Semaste else 315254721Semaste { 316254721Semaste m_data_64 = new DataDescriptor_64(); 317254721Semaste process_sp->ReadMemory (data_location, m_data_64, sizeof(DataDescriptor_64), error); 318254721Semaste } 319254721Semaste if (error.Fail()) 320254721Semaste return false; 321254721Semaste m_data_ptr = data_location + m_ptr_size; 322254721Semaste return false; 323254721Semaste} 324254721Semaste 325254721Semastebool 326254721Semastelldb_private::formatters::NSDictionaryISyntheticFrontEnd::MightHaveChildren () 327254721Semaste{ 328254721Semaste return true; 329254721Semaste} 330254721Semaste 331254721Semastelldb::ValueObjectSP 332254721Semastelldb_private::formatters::NSDictionaryISyntheticFrontEnd::GetChildAtIndex (size_t idx) 333254721Semaste{ 334254721Semaste uint32_t num_children = CalculateNumChildren(); 335254721Semaste 336254721Semaste if (idx >= num_children) 337254721Semaste return lldb::ValueObjectSP(); 338254721Semaste 339254721Semaste if (m_children.empty()) 340254721Semaste { 341254721Semaste // do the scan phase 342254721Semaste lldb::addr_t key_at_idx = 0, val_at_idx = 0; 343254721Semaste 344254721Semaste uint32_t tries = 0; 345254721Semaste uint32_t test_idx = 0; 346254721Semaste 347254721Semaste while(tries < num_children) 348254721Semaste { 349254721Semaste key_at_idx = m_data_ptr + (2*test_idx * m_ptr_size); 350254721Semaste val_at_idx = key_at_idx + m_ptr_size; 351254721Semaste ProcessSP process_sp = m_exe_ctx_ref.GetProcessSP(); 352254721Semaste if (!process_sp) 353254721Semaste return lldb::ValueObjectSP(); 354254721Semaste Error error; 355254721Semaste key_at_idx = process_sp->ReadPointerFromMemory(key_at_idx, error); 356254721Semaste if (error.Fail()) 357254721Semaste return lldb::ValueObjectSP(); 358254721Semaste val_at_idx = process_sp->ReadPointerFromMemory(val_at_idx, error); 359254721Semaste if (error.Fail()) 360254721Semaste return lldb::ValueObjectSP(); 361254721Semaste 362254721Semaste test_idx++; 363254721Semaste 364254721Semaste if (!key_at_idx || !val_at_idx) 365254721Semaste continue; 366254721Semaste tries++; 367254721Semaste 368254721Semaste DictionaryItemDescriptor descriptor = {key_at_idx,val_at_idx,lldb::ValueObjectSP()}; 369254721Semaste 370254721Semaste m_children.push_back(descriptor); 371254721Semaste } 372254721Semaste } 373254721Semaste 374254721Semaste if (idx >= m_children.size()) // should never happen 375254721Semaste return lldb::ValueObjectSP(); 376254721Semaste 377254721Semaste DictionaryItemDescriptor &dict_item = m_children[idx]; 378254721Semaste if (!dict_item.valobj_sp) 379254721Semaste { 380254721Semaste if (!m_pair_type.IsValid()) 381254721Semaste { 382254721Semaste TargetSP target_sp(m_backend.GetTargetSP()); 383254721Semaste if (!target_sp) 384254721Semaste return ValueObjectSP(); 385254721Semaste m_pair_type = GetLLDBNSPairType(target_sp); 386254721Semaste } 387254721Semaste if (!m_pair_type.IsValid()) 388254721Semaste return ValueObjectSP(); 389254721Semaste 390254721Semaste DataBufferSP buffer_sp(new DataBufferHeap(2*m_ptr_size,0)); 391254721Semaste 392254721Semaste if (m_ptr_size == 8) 393254721Semaste { 394254721Semaste uint64_t *data_ptr = (uint64_t *)buffer_sp->GetBytes(); 395254721Semaste *data_ptr = dict_item.key_ptr; 396254721Semaste *(data_ptr+1) = dict_item.val_ptr; 397254721Semaste } 398254721Semaste else 399254721Semaste { 400254721Semaste uint32_t *data_ptr = (uint32_t *)buffer_sp->GetBytes(); 401254721Semaste *data_ptr = dict_item.key_ptr; 402254721Semaste *(data_ptr+1) = dict_item.val_ptr; 403254721Semaste } 404254721Semaste 405254721Semaste StreamString idx_name; 406254721Semaste idx_name.Printf("[%zu]",idx); 407254721Semaste DataExtractor data(buffer_sp, m_order, m_ptr_size); 408254721Semaste dict_item.valobj_sp = ValueObject::CreateValueObjectFromData(idx_name.GetData(), data, m_exe_ctx_ref, m_pair_type); 409254721Semaste } 410254721Semaste return dict_item.valobj_sp; 411254721Semaste} 412254721Semaste 413254721Semastelldb_private::formatters::NSDictionaryMSyntheticFrontEnd::NSDictionaryMSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp) : 414254721SemasteSyntheticChildrenFrontEnd(*valobj_sp.get()), 415254721Semastem_exe_ctx_ref(), 416254721Semastem_ptr_size(8), 417254721Semastem_order(lldb::eByteOrderInvalid), 418254721Semastem_data_32(NULL), 419254721Semastem_data_64(NULL), 420254721Semastem_pair_type() 421254721Semaste{ 422254721Semaste} 423254721Semaste 424254721Semastelldb_private::formatters::NSDictionaryMSyntheticFrontEnd::~NSDictionaryMSyntheticFrontEnd () 425254721Semaste{ 426254721Semaste delete m_data_32; 427254721Semaste m_data_32 = NULL; 428254721Semaste delete m_data_64; 429254721Semaste m_data_64 = NULL; 430254721Semaste} 431254721Semaste 432254721Semastesize_t 433254721Semastelldb_private::formatters::NSDictionaryMSyntheticFrontEnd::GetIndexOfChildWithName (const ConstString &name) 434254721Semaste{ 435254721Semaste const char* item_name = name.GetCString(); 436254721Semaste uint32_t idx = ExtractIndexFromString(item_name); 437254721Semaste if (idx < UINT32_MAX && idx >= CalculateNumChildren()) 438254721Semaste return UINT32_MAX; 439254721Semaste return idx; 440254721Semaste} 441254721Semaste 442254721Semastesize_t 443254721Semastelldb_private::formatters::NSDictionaryMSyntheticFrontEnd::CalculateNumChildren () 444254721Semaste{ 445254721Semaste if (!m_data_32 && !m_data_64) 446254721Semaste return 0; 447254721Semaste return (m_data_32 ? m_data_32->_used : m_data_64->_used); 448254721Semaste} 449254721Semaste 450254721Semastebool 451254721Semastelldb_private::formatters::NSDictionaryMSyntheticFrontEnd::Update() 452254721Semaste{ 453254721Semaste m_children.clear(); 454254721Semaste ValueObjectSP valobj_sp = m_backend.GetSP(); 455254721Semaste m_ptr_size = 0; 456254721Semaste delete m_data_32; 457254721Semaste m_data_32 = NULL; 458254721Semaste delete m_data_64; 459254721Semaste m_data_64 = NULL; 460254721Semaste if (!valobj_sp) 461254721Semaste return false; 462254721Semaste m_exe_ctx_ref = valobj_sp->GetExecutionContextRef(); 463254721Semaste Error error; 464254721Semaste error.Clear(); 465254721Semaste lldb::ProcessSP process_sp(valobj_sp->GetProcessSP()); 466254721Semaste if (!process_sp) 467254721Semaste return false; 468254721Semaste m_ptr_size = process_sp->GetAddressByteSize(); 469254721Semaste m_order = process_sp->GetByteOrder(); 470254721Semaste uint64_t data_location = valobj_sp->GetValueAsUnsigned(0) + m_ptr_size; 471254721Semaste if (m_ptr_size == 4) 472254721Semaste { 473254721Semaste m_data_32 = new DataDescriptor_32(); 474254721Semaste process_sp->ReadMemory (data_location, m_data_32, sizeof(DataDescriptor_32), error); 475254721Semaste } 476254721Semaste else 477254721Semaste { 478254721Semaste m_data_64 = new DataDescriptor_64(); 479254721Semaste process_sp->ReadMemory (data_location, m_data_64, sizeof(DataDescriptor_64), error); 480254721Semaste } 481254721Semaste if (error.Fail()) 482254721Semaste return false; 483254721Semaste return false; 484254721Semaste} 485254721Semaste 486254721Semastebool 487254721Semastelldb_private::formatters::NSDictionaryMSyntheticFrontEnd::MightHaveChildren () 488254721Semaste{ 489254721Semaste return true; 490254721Semaste} 491254721Semaste 492254721Semastelldb::ValueObjectSP 493254721Semastelldb_private::formatters::NSDictionaryMSyntheticFrontEnd::GetChildAtIndex (size_t idx) 494254721Semaste{ 495254721Semaste lldb::addr_t m_keys_ptr = (m_data_32 ? m_data_32->_keys_addr : m_data_64->_keys_addr); 496254721Semaste lldb::addr_t m_values_ptr = (m_data_32 ? m_data_32->_objs_addr : m_data_64->_objs_addr); 497254721Semaste 498254721Semaste uint32_t num_children = CalculateNumChildren(); 499254721Semaste 500254721Semaste if (idx >= num_children) 501254721Semaste return lldb::ValueObjectSP(); 502254721Semaste 503254721Semaste if (m_children.empty()) 504254721Semaste { 505254721Semaste // do the scan phase 506254721Semaste lldb::addr_t key_at_idx = 0, val_at_idx = 0; 507254721Semaste 508254721Semaste uint32_t tries = 0; 509254721Semaste uint32_t test_idx = 0; 510254721Semaste 511254721Semaste while(tries < num_children) 512254721Semaste { 513254721Semaste key_at_idx = m_keys_ptr + (test_idx * m_ptr_size); 514254721Semaste val_at_idx = m_values_ptr + (test_idx * m_ptr_size);; 515254721Semaste ProcessSP process_sp = m_exe_ctx_ref.GetProcessSP(); 516254721Semaste if (!process_sp) 517254721Semaste return lldb::ValueObjectSP(); 518254721Semaste Error error; 519254721Semaste key_at_idx = process_sp->ReadPointerFromMemory(key_at_idx, error); 520254721Semaste if (error.Fail()) 521254721Semaste return lldb::ValueObjectSP(); 522254721Semaste val_at_idx = process_sp->ReadPointerFromMemory(val_at_idx, error); 523254721Semaste if (error.Fail()) 524254721Semaste return lldb::ValueObjectSP(); 525254721Semaste 526254721Semaste test_idx++; 527254721Semaste 528254721Semaste if (!key_at_idx || !val_at_idx) 529254721Semaste continue; 530254721Semaste tries++; 531254721Semaste 532254721Semaste DictionaryItemDescriptor descriptor = {key_at_idx,val_at_idx,lldb::ValueObjectSP()}; 533254721Semaste 534254721Semaste m_children.push_back(descriptor); 535254721Semaste } 536254721Semaste } 537254721Semaste 538254721Semaste if (idx >= m_children.size()) // should never happen 539254721Semaste return lldb::ValueObjectSP(); 540254721Semaste 541254721Semaste DictionaryItemDescriptor &dict_item = m_children[idx]; 542254721Semaste if (!dict_item.valobj_sp) 543254721Semaste { 544254721Semaste if (!m_pair_type.IsValid()) 545254721Semaste { 546254721Semaste TargetSP target_sp(m_backend.GetTargetSP()); 547254721Semaste if (!target_sp) 548254721Semaste return ValueObjectSP(); 549254721Semaste m_pair_type = GetLLDBNSPairType(target_sp); 550254721Semaste } 551254721Semaste if (!m_pair_type.IsValid()) 552254721Semaste return ValueObjectSP(); 553254721Semaste 554254721Semaste DataBufferSP buffer_sp(new DataBufferHeap(2*m_ptr_size,0)); 555254721Semaste 556254721Semaste if (m_ptr_size == 8) 557254721Semaste { 558254721Semaste uint64_t *data_ptr = (uint64_t *)buffer_sp->GetBytes(); 559254721Semaste *data_ptr = dict_item.key_ptr; 560254721Semaste *(data_ptr+1) = dict_item.val_ptr; 561254721Semaste } 562254721Semaste else 563254721Semaste { 564254721Semaste uint32_t *data_ptr = (uint32_t *)buffer_sp->GetBytes(); 565254721Semaste *data_ptr = dict_item.key_ptr; 566254721Semaste *(data_ptr+1) = dict_item.val_ptr; 567254721Semaste } 568254721Semaste 569254721Semaste StreamString idx_name; 570254721Semaste idx_name.Printf("[%zu]",idx); 571254721Semaste DataExtractor data(buffer_sp, m_order, m_ptr_size); 572254721Semaste dict_item.valobj_sp = ValueObject::CreateValueObjectFromData(idx_name.GetData(), data, m_exe_ctx_ref, m_pair_type); 573254721Semaste } 574254721Semaste return dict_item.valobj_sp; 575254721Semaste} 576254721Semaste 577254721Semastetemplate bool 578254721Semastelldb_private::formatters::NSDictionarySummaryProvider<true> (ValueObject&, Stream&) ; 579254721Semaste 580254721Semastetemplate bool 581254721Semastelldb_private::formatters::NSDictionarySummaryProvider<false> (ValueObject&, Stream&) ; 582