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