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
GetLLDBNSPairType(TargetSP target_sp)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
NSDictionarySummaryProvider(ValueObject & valobj,Stream & stream,const TypeSummaryOptions & options)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
NSDictionarySyntheticFrontEndCreator(CXXSyntheticChildren *,lldb::ValueObjectSP valobj_sp)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
NSDictionaryCodeRunningSyntheticFrontEnd(lldb::ValueObjectSP valobj_sp)309 lldb_private::formatters::NSDictionaryCodeRunningSyntheticFrontEnd::NSDictionaryCodeRunningSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp) :
310 SyntheticChildrenFrontEnd(*valobj_sp.get())
311 {}
312
313 size_t
CalculateNumChildren()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
GetChildAtIndex(size_t idx)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
Update()346 lldb_private::formatters::NSDictionaryCodeRunningSyntheticFrontEnd::Update()
347 {
348 return false;
349 }
350
351 bool
MightHaveChildren()352 lldb_private::formatters::NSDictionaryCodeRunningSyntheticFrontEnd::MightHaveChildren ()
353 {
354 return true;
355 }
356
357 size_t
GetIndexOfChildWithName(const ConstString & name)358 lldb_private::formatters::NSDictionaryCodeRunningSyntheticFrontEnd::GetIndexOfChildWithName (const ConstString &name)
359 {
360 return 0;
361 }
362
~NSDictionaryCodeRunningSyntheticFrontEnd()363 lldb_private::formatters::NSDictionaryCodeRunningSyntheticFrontEnd::~NSDictionaryCodeRunningSyntheticFrontEnd ()
364 {}
365
NSDictionaryISyntheticFrontEnd(lldb::ValueObjectSP valobj_sp)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
~NSDictionaryISyntheticFrontEnd()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
GetIndexOfChildWithName(const ConstString & name)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
CalculateNumChildren()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
Update()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
MightHaveChildren()441 lldb_private::formatters::NSDictionaryISyntheticFrontEnd::MightHaveChildren ()
442 {
443 return true;
444 }
445
446 lldb::ValueObjectSP
GetChildAtIndex(size_t idx)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
NSDictionaryMSyntheticFrontEnd(lldb::ValueObjectSP valobj_sp)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
~NSDictionaryMSyntheticFrontEnd()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
GetIndexOfChildWithName(const ConstString & name)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
CalculateNumChildren()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
Update()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
MightHaveChildren()605 lldb_private::formatters::NSDictionaryMSyntheticFrontEnd::MightHaveChildren ()
606 {
607 return true;
608 }
609
610 lldb::ValueObjectSP
GetChildAtIndex(size_t idx)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&) ;
703