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