blob: 30bc3acfbec7528d0e4538639492f14c03c7eb5f [file] [log] [blame]
Enrico Granataf615b802013-02-15 23:38:37 +00001//===-- 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
Enrico Granataf615b802013-02-15 23:38:37 +000010#include "lldb/DataFormatters/CXXFormatterFunctions.h"
11
Enrico Granataf615b802013-02-15 23:38:37 +000012#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
Jason Molendac01e1b72013-04-03 20:32:17 +000022#include "clang/AST/DeclCXX.h"
23
Enrico Granataf615b802013-02-15 23:38:37 +000024using namespace lldb;
25using namespace lldb_private;
26using namespace lldb_private::formatters;
27
Enrico Granataeb8bd922013-04-03 01:25:29 +000028static ClangASTType
29GetLLDBNSPairType (TargetSP target_sp)
30{
Greg Clayton57ee3062013-07-11 22:46:58 +000031 ClangASTType clang_type;
Enrico Granataeb8bd922013-04-03 01:25:29 +000032
33 ClangASTContext *target_ast_context = target_sp->GetScratchClangASTContext();
34
Greg Clayton57ee3062013-07-11 22:46:58 +000035 if (target_ast_context)
Enrico Granataeb8bd922013-04-03 01:25:29 +000036 {
Enrico Granata0e478f52014-10-17 17:56:59 +000037 ConstString g___lldb_autogen_nspair("__lldb_autogen_nspair");
Greg Clayton57ee3062013-07-11 22:46:58 +000038
Enrico Granata0e478f52014-10-17 17:56:59 +000039 clang_type = target_ast_context->GetTypeForIdentifier<clang::CXXRecordDecl>(g___lldb_autogen_nspair);
40
41 if (!clang_type)
Enrico Granataeb8bd922013-04-03 01:25:29 +000042 {
Enrico Granata0e478f52014-10-17 17:56:59 +000043 clang_type = target_ast_context->CreateRecordType(NULL, lldb::eAccessPublic, g___lldb_autogen_nspair.GetCString(), clang::TTK_Struct, lldb::eLanguageTypeC);
Greg Clayton57ee3062013-07-11 22:46:58 +000044
Enrico Granata0e478f52014-10-17 17:56:59 +000045 if (clang_type)
Greg Clayton57ee3062013-07-11 22:46:58 +000046 {
Enrico Granata0e478f52014-10-17 17:56:59 +000047 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();
Greg Clayton57ee3062013-07-11 22:46:58 +000052 }
Enrico Granataeb8bd922013-04-03 01:25:29 +000053 }
54 }
Enrico Granataeb8bd922013-04-03 01:25:29 +000055 return clang_type;
56}
57
Enrico Granata6714a0f2014-10-22 21:47:27 +000058namespace 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
Enrico Granataf615b802013-02-15 23:38:37 +0000195template<bool name_entries>
196bool
Enrico Granataf35bc632014-11-06 21:55:30 +0000197lldb_private::formatters::NSDictionarySummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options)
Enrico Granataf615b802013-02-15 23:38:37 +0000198{
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 }
Enrico Granataf68f7322013-03-15 18:44:08 +0000244 /*else if (!strcmp(class_name,"__NSCFDictionary"))
Enrico Granataf615b802013-02-15 23:38:37 +0000245 {
246 Error error;
Enrico Granataf68f7322013-03-15 18:44:08 +0000247 value = process_sp->ReadUnsignedIntegerFromMemory(valobj_addr + (is_64bit ? 20 : 12), 4, 0, error);
Enrico Granataf615b802013-02-15 23:38:37 +0000248 if (error.Fail())
249 return false;
250 if (is_64bit)
251 value &= ~0x0f1f000000000000UL;
Enrico Granataf68f7322013-03-15 18:44:08 +0000252 }*/
Enrico Granataf615b802013-02-15 23:38:37 +0000253 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
267SyntheticChildrenFrontEnd* 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
309lldb_private::formatters::NSDictionaryCodeRunningSyntheticFrontEnd::NSDictionaryCodeRunningSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp) :
310SyntheticChildrenFrontEnd(*valobj_sp.get())
311{}
312
313size_t
314lldb_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
322lldb::ValueObjectSP
323lldb_private::formatters::NSDictionaryCodeRunningSyntheticFrontEnd::GetChildAtIndex (size_t idx)
324{
325 StreamString idx_name;
Deepak Panickal99fbc072014-03-03 15:39:47 +0000326 idx_name.Printf("[%" PRIu64 "]", (uint64_t)idx);
Enrico Granataf615b802013-02-15 23:38:37 +0000327 StreamString key_fetcher_expr;
Deepak Panickal99fbc072014-03-03 15:39:47 +0000328 key_fetcher_expr.Printf("(id)[(NSArray*)[(id)0x%" PRIx64 " allKeys] objectAtIndex:%" PRIu64 "]", m_backend.GetPointerValue(), (uint64_t)idx);
Enrico Granataf615b802013-02-15 23:38:37 +0000329 StreamString value_fetcher_expr;
Enrico Granataa221e4e2013-02-25 19:44:39 +0000330 value_fetcher_expr.Printf("(id)[(id)0x%" PRIx64 " objectForKey:(%s)]",m_backend.GetPointerValue(),key_fetcher_expr.GetData());
Enrico Granataf615b802013-02-15 23:38:37 +0000331 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;
Jim Ingham6fbc48b2013-11-07 00:11:47 +0000334 EvaluateExpressionOptions options;
335 options.SetKeepInMemory(true);
Enrico Granataba8eb122014-07-30 21:07:50 +0000336 m_backend.GetTargetSP()->EvaluateExpression(object_fetcher_expr.GetData(),
337 GetViableFrame(m_backend.GetTargetSP().get()),
338 child_sp,
Jim Ingham6fbc48b2013-11-07 00:11:47 +0000339 options);
Enrico Granataf615b802013-02-15 23:38:37 +0000340 if (child_sp)
341 child_sp->SetName(ConstString(idx_name.GetData()));
342 return child_sp;
343}
344
345bool
346lldb_private::formatters::NSDictionaryCodeRunningSyntheticFrontEnd::Update()
347{
348 return false;
349}
350
351bool
352lldb_private::formatters::NSDictionaryCodeRunningSyntheticFrontEnd::MightHaveChildren ()
353{
354 return true;
355}
356
357size_t
358lldb_private::formatters::NSDictionaryCodeRunningSyntheticFrontEnd::GetIndexOfChildWithName (const ConstString &name)
359{
360 return 0;
361}
362
363lldb_private::formatters::NSDictionaryCodeRunningSyntheticFrontEnd::~NSDictionaryCodeRunningSyntheticFrontEnd ()
364{}
365
366lldb_private::formatters::NSDictionaryISyntheticFrontEnd::NSDictionaryISyntheticFrontEnd (lldb::ValueObjectSP valobj_sp) :
367SyntheticChildrenFrontEnd(*valobj_sp.get()),
368m_exe_ctx_ref(),
369m_ptr_size(8),
Enrico Granataeb8bd922013-04-03 01:25:29 +0000370m_order(lldb::eByteOrderInvalid),
Enrico Granataf615b802013-02-15 23:38:37 +0000371m_data_32(NULL),
Enrico Granataeb8bd922013-04-03 01:25:29 +0000372m_data_64(NULL),
373m_pair_type()
Enrico Granataf615b802013-02-15 23:38:37 +0000374{
Enrico Granataf615b802013-02-15 23:38:37 +0000375}
376
377lldb_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
385size_t
386lldb_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
395size_t
396lldb_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
403bool
404lldb_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;
Enrico Granataf615b802013-02-15 23:38:37 +0000415 m_exe_ctx_ref = valobj_sp->GetExecutionContextRef();
416 Error error;
Enrico Granataf615b802013-02-15 23:38:37 +0000417 error.Clear();
418 lldb::ProcessSP process_sp(valobj_sp->GetProcessSP());
419 if (!process_sp)
420 return false;
421 m_ptr_size = process_sp->GetAddressByteSize();
Enrico Granataeb8bd922013-04-03 01:25:29 +0000422 m_order = process_sp->GetByteOrder();
Enrico Granata723e1292013-04-23 01:13:50 +0000423 uint64_t data_location = valobj_sp->GetValueAsUnsigned(0) + m_ptr_size;
Enrico Granataf615b802013-02-15 23:38:37 +0000424 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
440bool
441lldb_private::formatters::NSDictionaryISyntheticFrontEnd::MightHaveChildren ()
442{
443 return true;
444}
445
446lldb::ValueObjectSP
447lldb_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 {
Enrico Granataeb8bd922013-04-03 01:25:29 +0000495 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
Enrico Granataf615b802013-02-15 23:38:37 +0000520 StreamString idx_name;
Deepak Panickal99fbc072014-03-03 15:39:47 +0000521 idx_name.Printf("[%" PRIu64 "]", (uint64_t)idx);
Enrico Granataeb8bd922013-04-03 01:25:29 +0000522 DataExtractor data(buffer_sp, m_order, m_ptr_size);
Enrico Granatae29df232014-12-09 19:51:20 +0000523 dict_item.valobj_sp = CreateValueObjectFromData(idx_name.GetData(),
524 data,
525 m_exe_ctx_ref,
526 m_pair_type);
Enrico Granataf615b802013-02-15 23:38:37 +0000527 }
528 return dict_item.valobj_sp;
529}
530
531lldb_private::formatters::NSDictionaryMSyntheticFrontEnd::NSDictionaryMSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp) :
532SyntheticChildrenFrontEnd(*valobj_sp.get()),
533m_exe_ctx_ref(),
534m_ptr_size(8),
Enrico Granataeb8bd922013-04-03 01:25:29 +0000535m_order(lldb::eByteOrderInvalid),
Enrico Granataf615b802013-02-15 23:38:37 +0000536m_data_32(NULL),
Enrico Granataeb8bd922013-04-03 01:25:29 +0000537m_data_64(NULL),
538m_pair_type()
Enrico Granataf615b802013-02-15 23:38:37 +0000539{
Enrico Granataf615b802013-02-15 23:38:37 +0000540}
541
542lldb_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
550size_t
551lldb_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
560size_t
561lldb_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
568bool
569lldb_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;
Enrico Granataf615b802013-02-15 23:38:37 +0000580 m_exe_ctx_ref = valobj_sp->GetExecutionContextRef();
581 Error error;
Enrico Granataf615b802013-02-15 23:38:37 +0000582 error.Clear();
583 lldb::ProcessSP process_sp(valobj_sp->GetProcessSP());
584 if (!process_sp)
585 return false;
586 m_ptr_size = process_sp->GetAddressByteSize();
Enrico Granataeb8bd922013-04-03 01:25:29 +0000587 m_order = process_sp->GetByteOrder();
Enrico Granata723e1292013-04-23 01:13:50 +0000588 uint64_t data_location = valobj_sp->GetValueAsUnsigned(0) + m_ptr_size;
Enrico Granataf615b802013-02-15 23:38:37 +0000589 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
604bool
605lldb_private::formatters::NSDictionaryMSyntheticFrontEnd::MightHaveChildren ()
606{
607 return true;
608}
609
610lldb::ValueObjectSP
611lldb_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 {
Enrico Granataeb8bd922013-04-03 01:25:29 +0000662 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
Enrico Granataf615b802013-02-15 23:38:37 +0000687 StreamString idx_name;
Deepak Panickal99fbc072014-03-03 15:39:47 +0000688 idx_name.Printf("[%" PRIu64 "]", (uint64_t)idx);
Enrico Granataeb8bd922013-04-03 01:25:29 +0000689 DataExtractor data(buffer_sp, m_order, m_ptr_size);
Enrico Granatae29df232014-12-09 19:51:20 +0000690 dict_item.valobj_sp = CreateValueObjectFromData(idx_name.GetData(),
691 data,
692 m_exe_ctx_ref,
693 m_pair_type);
Enrico Granataf615b802013-02-15 23:38:37 +0000694 }
695 return dict_item.valobj_sp;
696}
697
698template bool
Enrico Granataf35bc632014-11-06 21:55:30 +0000699lldb_private::formatters::NSDictionarySummaryProvider<true> (ValueObject&, Stream&, const TypeSummaryOptions&) ;
Enrico Granataf615b802013-02-15 23:38:37 +0000700
701template bool
Enrico Granataf35bc632014-11-06 21:55:30 +0000702lldb_private::formatters::NSDictionarySummaryProvider<false> (ValueObject&, Stream&, const TypeSummaryOptions&) ;