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