blob: fdac05192c467c66681178320b6fff0733edcab0 [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
Matt Kopec676a4872013-02-21 23:55:31 +000010#include "lldb/lldb-python.h"
11
Enrico Granataf615b802013-02-15 23:38:37 +000012#include "lldb/DataFormatters/CXXFormatterFunctions.h"
13
Enrico Granataf615b802013-02-15 23:38:37 +000014#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
Jason Molendac01e1b72013-04-03 20:32:17 +000024#include "clang/AST/DeclCXX.h"
25
Enrico Granataf615b802013-02-15 23:38:37 +000026using namespace lldb;
27using namespace lldb_private;
28using namespace lldb_private::formatters;
29
Enrico Granataeb8bd922013-04-03 01:25:29 +000030static ClangASTType
31GetLLDBNSPairType (TargetSP target_sp)
32{
Greg Clayton57ee3062013-07-11 22:46:58 +000033 ClangASTType clang_type;
Enrico Granataeb8bd922013-04-03 01:25:29 +000034
35 ClangASTContext *target_ast_context = target_sp->GetScratchClangASTContext();
36
Greg Clayton57ee3062013-07-11 22:46:58 +000037 if (target_ast_context)
Enrico Granataeb8bd922013-04-03 01:25:29 +000038 {
Enrico Granata0e478f52014-10-17 17:56:59 +000039 ConstString g___lldb_autogen_nspair("__lldb_autogen_nspair");
Greg Clayton57ee3062013-07-11 22:46:58 +000040
Enrico Granata0e478f52014-10-17 17:56:59 +000041 clang_type = target_ast_context->GetTypeForIdentifier<clang::CXXRecordDecl>(g___lldb_autogen_nspair);
42
43 if (!clang_type)
Enrico Granataeb8bd922013-04-03 01:25:29 +000044 {
Enrico Granata0e478f52014-10-17 17:56:59 +000045 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 +000046
Enrico Granata0e478f52014-10-17 17:56:59 +000047 if (clang_type)
Greg Clayton57ee3062013-07-11 22:46:58 +000048 {
Enrico Granata0e478f52014-10-17 17:56:59 +000049 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();
Greg Clayton57ee3062013-07-11 22:46:58 +000054 }
Enrico Granataeb8bd922013-04-03 01:25:29 +000055 }
56 }
Enrico Granataeb8bd922013-04-03 01:25:29 +000057 return clang_type;
58}
59
Enrico Granata6714a0f2014-10-22 21:47:27 +000060namespace 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
Enrico Granataf615b802013-02-15 23:38:37 +0000197template<bool name_entries>
198bool
Enrico Granataf35bc632014-11-06 21:55:30 +0000199lldb_private::formatters::NSDictionarySummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options)
Enrico Granataf615b802013-02-15 23:38:37 +0000200{
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 }
Enrico Granataf68f7322013-03-15 18:44:08 +0000246 /*else if (!strcmp(class_name,"__NSCFDictionary"))
Enrico Granataf615b802013-02-15 23:38:37 +0000247 {
248 Error error;
Enrico Granataf68f7322013-03-15 18:44:08 +0000249 value = process_sp->ReadUnsignedIntegerFromMemory(valobj_addr + (is_64bit ? 20 : 12), 4, 0, error);
Enrico Granataf615b802013-02-15 23:38:37 +0000250 if (error.Fail())
251 return false;
252 if (is_64bit)
253 value &= ~0x0f1f000000000000UL;
Enrico Granataf68f7322013-03-15 18:44:08 +0000254 }*/
Enrico Granataf615b802013-02-15 23:38:37 +0000255 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
269SyntheticChildrenFrontEnd* 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
311lldb_private::formatters::NSDictionaryCodeRunningSyntheticFrontEnd::NSDictionaryCodeRunningSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp) :
312SyntheticChildrenFrontEnd(*valobj_sp.get())
313{}
314
315size_t
316lldb_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
324lldb::ValueObjectSP
325lldb_private::formatters::NSDictionaryCodeRunningSyntheticFrontEnd::GetChildAtIndex (size_t idx)
326{
327 StreamString idx_name;
Deepak Panickal99fbc072014-03-03 15:39:47 +0000328 idx_name.Printf("[%" PRIu64 "]", (uint64_t)idx);
Enrico Granataf615b802013-02-15 23:38:37 +0000329 StreamString key_fetcher_expr;
Deepak Panickal99fbc072014-03-03 15:39:47 +0000330 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 +0000331 StreamString value_fetcher_expr;
Enrico Granataa221e4e2013-02-25 19:44:39 +0000332 value_fetcher_expr.Printf("(id)[(id)0x%" PRIx64 " objectForKey:(%s)]",m_backend.GetPointerValue(),key_fetcher_expr.GetData());
Enrico Granataf615b802013-02-15 23:38:37 +0000333 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;
Jim Ingham6fbc48b2013-11-07 00:11:47 +0000336 EvaluateExpressionOptions options;
337 options.SetKeepInMemory(true);
Enrico Granataba8eb122014-07-30 21:07:50 +0000338 m_backend.GetTargetSP()->EvaluateExpression(object_fetcher_expr.GetData(),
339 GetViableFrame(m_backend.GetTargetSP().get()),
340 child_sp,
Jim Ingham6fbc48b2013-11-07 00:11:47 +0000341 options);
Enrico Granataf615b802013-02-15 23:38:37 +0000342 if (child_sp)
343 child_sp->SetName(ConstString(idx_name.GetData()));
344 return child_sp;
345}
346
347bool
348lldb_private::formatters::NSDictionaryCodeRunningSyntheticFrontEnd::Update()
349{
350 return false;
351}
352
353bool
354lldb_private::formatters::NSDictionaryCodeRunningSyntheticFrontEnd::MightHaveChildren ()
355{
356 return true;
357}
358
359size_t
360lldb_private::formatters::NSDictionaryCodeRunningSyntheticFrontEnd::GetIndexOfChildWithName (const ConstString &name)
361{
362 return 0;
363}
364
365lldb_private::formatters::NSDictionaryCodeRunningSyntheticFrontEnd::~NSDictionaryCodeRunningSyntheticFrontEnd ()
366{}
367
368lldb_private::formatters::NSDictionaryISyntheticFrontEnd::NSDictionaryISyntheticFrontEnd (lldb::ValueObjectSP valobj_sp) :
369SyntheticChildrenFrontEnd(*valobj_sp.get()),
370m_exe_ctx_ref(),
371m_ptr_size(8),
Enrico Granataeb8bd922013-04-03 01:25:29 +0000372m_order(lldb::eByteOrderInvalid),
Enrico Granataf615b802013-02-15 23:38:37 +0000373m_data_32(NULL),
Enrico Granataeb8bd922013-04-03 01:25:29 +0000374m_data_64(NULL),
375m_pair_type()
Enrico Granataf615b802013-02-15 23:38:37 +0000376{
Enrico Granataf615b802013-02-15 23:38:37 +0000377}
378
379lldb_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
387size_t
388lldb_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
397size_t
398lldb_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
405bool
406lldb_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;
Enrico Granataf615b802013-02-15 23:38:37 +0000417 m_exe_ctx_ref = valobj_sp->GetExecutionContextRef();
418 Error error;
Enrico Granataf615b802013-02-15 23:38:37 +0000419 error.Clear();
420 lldb::ProcessSP process_sp(valobj_sp->GetProcessSP());
421 if (!process_sp)
422 return false;
423 m_ptr_size = process_sp->GetAddressByteSize();
Enrico Granataeb8bd922013-04-03 01:25:29 +0000424 m_order = process_sp->GetByteOrder();
Enrico Granata723e1292013-04-23 01:13:50 +0000425 uint64_t data_location = valobj_sp->GetValueAsUnsigned(0) + m_ptr_size;
Enrico Granataf615b802013-02-15 23:38:37 +0000426 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
442bool
443lldb_private::formatters::NSDictionaryISyntheticFrontEnd::MightHaveChildren ()
444{
445 return true;
446}
447
448lldb::ValueObjectSP
449lldb_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 {
Enrico Granataeb8bd922013-04-03 01:25:29 +0000497 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
Enrico Granataf615b802013-02-15 23:38:37 +0000522 StreamString idx_name;
Deepak Panickal99fbc072014-03-03 15:39:47 +0000523 idx_name.Printf("[%" PRIu64 "]", (uint64_t)idx);
Enrico Granataeb8bd922013-04-03 01:25:29 +0000524 DataExtractor data(buffer_sp, m_order, m_ptr_size);
Enrico Granatae29df232014-12-09 19:51:20 +0000525 dict_item.valobj_sp = CreateValueObjectFromData(idx_name.GetData(),
526 data,
527 m_exe_ctx_ref,
528 m_pair_type);
Enrico Granataf615b802013-02-15 23:38:37 +0000529 }
530 return dict_item.valobj_sp;
531}
532
533lldb_private::formatters::NSDictionaryMSyntheticFrontEnd::NSDictionaryMSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp) :
534SyntheticChildrenFrontEnd(*valobj_sp.get()),
535m_exe_ctx_ref(),
536m_ptr_size(8),
Enrico Granataeb8bd922013-04-03 01:25:29 +0000537m_order(lldb::eByteOrderInvalid),
Enrico Granataf615b802013-02-15 23:38:37 +0000538m_data_32(NULL),
Enrico Granataeb8bd922013-04-03 01:25:29 +0000539m_data_64(NULL),
540m_pair_type()
Enrico Granataf615b802013-02-15 23:38:37 +0000541{
Enrico Granataf615b802013-02-15 23:38:37 +0000542}
543
544lldb_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
552size_t
553lldb_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
562size_t
563lldb_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
570bool
571lldb_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;
Enrico Granataf615b802013-02-15 23:38:37 +0000582 m_exe_ctx_ref = valobj_sp->GetExecutionContextRef();
583 Error error;
Enrico Granataf615b802013-02-15 23:38:37 +0000584 error.Clear();
585 lldb::ProcessSP process_sp(valobj_sp->GetProcessSP());
586 if (!process_sp)
587 return false;
588 m_ptr_size = process_sp->GetAddressByteSize();
Enrico Granataeb8bd922013-04-03 01:25:29 +0000589 m_order = process_sp->GetByteOrder();
Enrico Granata723e1292013-04-23 01:13:50 +0000590 uint64_t data_location = valobj_sp->GetValueAsUnsigned(0) + m_ptr_size;
Enrico Granataf615b802013-02-15 23:38:37 +0000591 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
606bool
607lldb_private::formatters::NSDictionaryMSyntheticFrontEnd::MightHaveChildren ()
608{
609 return true;
610}
611
612lldb::ValueObjectSP
613lldb_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 {
Enrico Granataeb8bd922013-04-03 01:25:29 +0000664 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
Enrico Granataf615b802013-02-15 23:38:37 +0000689 StreamString idx_name;
Deepak Panickal99fbc072014-03-03 15:39:47 +0000690 idx_name.Printf("[%" PRIu64 "]", (uint64_t)idx);
Enrico Granataeb8bd922013-04-03 01:25:29 +0000691 DataExtractor data(buffer_sp, m_order, m_ptr_size);
Enrico Granatae29df232014-12-09 19:51:20 +0000692 dict_item.valobj_sp = CreateValueObjectFromData(idx_name.GetData(),
693 data,
694 m_exe_ctx_ref,
695 m_pair_type);
Enrico Granataf615b802013-02-15 23:38:37 +0000696 }
697 return dict_item.valobj_sp;
698}
699
700template bool
Enrico Granataf35bc632014-11-06 21:55:30 +0000701lldb_private::formatters::NSDictionarySummaryProvider<true> (ValueObject&, Stream&, const TypeSummaryOptions&) ;
Enrico Granataf615b802013-02-15 23:38:37 +0000702
703template bool
Enrico Granataf35bc632014-11-06 21:55:30 +0000704lldb_private::formatters::NSDictionarySummaryProvider<false> (ValueObject&, Stream&, const TypeSummaryOptions&) ;