blob: e4a7425329f589ecbcf8a6d4de57c7104167f2f4 [file] [log] [blame]
Eugene Zelenko8d15f332015-10-20 01:10:59 +00001//===-- NSDictionary.cpp ----------------------------------------*- C++ -*-===//
Enrico Granataf615b802013-02-15 23:38:37 +00002//
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
Eugene Zelenko8d15f332015-10-20 01:10:59 +000010// C Includes
11// C++ Includes
12#include <mutex>
13
14// Other libraries and framework includes
15#include "clang/AST/DeclCXX.h"
16
17// Project includes
Enrico Granata7de855c2015-10-02 20:59:58 +000018#include "NSDictionary.h"
Enrico Granataf615b802013-02-15 23:38:37 +000019
Enrico Granataf615b802013-02-15 23:38:37 +000020#include "lldb/Core/DataBufferHeap.h"
21#include "lldb/Core/Error.h"
22#include "lldb/Core/Stream.h"
23#include "lldb/Core/ValueObject.h"
24#include "lldb/Core/ValueObjectConstResult.h"
Enrico Granata419d7912015-09-04 00:33:51 +000025#include "lldb/DataFormatters/FormattersHelpers.h"
Enrico Granataf615b802013-02-15 23:38:37 +000026#include "lldb/Host/Endian.h"
27#include "lldb/Symbol/ClangASTContext.h"
Enrico Granata675f49b2015-10-07 18:36:53 +000028#include "lldb/Target/Language.h"
Enrico Granataf615b802013-02-15 23:38:37 +000029#include "lldb/Target/ObjCLanguageRuntime.h"
Jim Inghama309efe2015-10-28 22:23:17 +000030#include "lldb/Target/StackFrame.h"
Enrico Granataf615b802013-02-15 23:38:37 +000031#include "lldb/Target/Target.h"
32
33using namespace lldb;
34using namespace lldb_private;
35using namespace lldb_private::formatters;
36
Enrico Granata7de855c2015-10-02 20:59:58 +000037std::map<ConstString, CXXFunctionSummaryFormat::Callback>&
38NSDictionary_Additionals::GetAdditionalSummaries ()
39{
40 static std::map<ConstString, CXXFunctionSummaryFormat::Callback> g_map;
41 return g_map;
42}
43
44std::map<ConstString, CXXSyntheticChildren::CreateFrontEndCallback>&
45NSDictionary_Additionals::GetAdditionalSynthetics ()
46{
47 static std::map<ConstString, CXXSyntheticChildren::CreateFrontEndCallback> g_map;
48 return g_map;
49}
50
Greg Claytona1e5dc82015-08-11 22:53:00 +000051static CompilerType
Enrico Granataeb8bd922013-04-03 01:25:29 +000052GetLLDBNSPairType (TargetSP target_sp)
53{
Bruce Mitchener3ad353f2015-09-24 03:54:50 +000054 CompilerType compiler_type;
Enrico Granata675f49b2015-10-07 18:36:53 +000055
Enrico Granataeb8bd922013-04-03 01:25:29 +000056 ClangASTContext *target_ast_context = target_sp->GetScratchClangASTContext();
Enrico Granata675f49b2015-10-07 18:36:53 +000057
Greg Clayton57ee3062013-07-11 22:46:58 +000058 if (target_ast_context)
Enrico Granataeb8bd922013-04-03 01:25:29 +000059 {
Enrico Granata0e478f52014-10-17 17:56:59 +000060 ConstString g___lldb_autogen_nspair("__lldb_autogen_nspair");
Enrico Granata675f49b2015-10-07 18:36:53 +000061
Bruce Mitchener3ad353f2015-09-24 03:54:50 +000062 compiler_type = target_ast_context->GetTypeForIdentifier<clang::CXXRecordDecl>(g___lldb_autogen_nspair);
Enrico Granata0e478f52014-10-17 17:56:59 +000063
Bruce Mitchener3ad353f2015-09-24 03:54:50 +000064 if (!compiler_type)
Enrico Granataeb8bd922013-04-03 01:25:29 +000065 {
Bruce Mitchener3ad353f2015-09-24 03:54:50 +000066 compiler_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 +000067
Bruce Mitchener3ad353f2015-09-24 03:54:50 +000068 if (compiler_type)
Greg Clayton57ee3062013-07-11 22:46:58 +000069 {
Bruce Mitchener3ad353f2015-09-24 03:54:50 +000070 ClangASTContext::StartTagDeclarationDefinition(compiler_type);
71 CompilerType id_compiler_type = target_ast_context->GetBasicType (eBasicTypeObjCID);
72 ClangASTContext::AddFieldToRecordType(compiler_type, "key", id_compiler_type, lldb::eAccessPublic, 0);
73 ClangASTContext::AddFieldToRecordType(compiler_type, "value", id_compiler_type, lldb::eAccessPublic, 0);
74 ClangASTContext::CompleteTagDeclarationDefinition(compiler_type);
Greg Clayton57ee3062013-07-11 22:46:58 +000075 }
Enrico Granataeb8bd922013-04-03 01:25:29 +000076 }
77 }
Bruce Mitchener3ad353f2015-09-24 03:54:50 +000078 return compiler_type;
Enrico Granataeb8bd922013-04-03 01:25:29 +000079}
80
Enrico Granata6714a0f2014-10-22 21:47:27 +000081namespace lldb_private {
82 namespace formatters {
83 class NSDictionaryISyntheticFrontEnd : public SyntheticChildrenFrontEnd
84 {
Eugene Zelenko8d15f332015-10-20 01:10:59 +000085 public:
86 NSDictionaryISyntheticFrontEnd (lldb::ValueObjectSP valobj_sp);
87
88 ~NSDictionaryISyntheticFrontEnd() override;
89
90 size_t
91 CalculateNumChildren() override;
92
93 lldb::ValueObjectSP
94 GetChildAtIndex(size_t idx) override;
95
96 bool
97 Update() override;
98
99 bool
100 MightHaveChildren() override;
101
102 size_t
103 GetIndexOfChildWithName(const ConstString &name) override;
104
Enrico Granata6714a0f2014-10-22 21:47:27 +0000105 private:
106 struct DataDescriptor_32
107 {
108 uint32_t _used : 26;
109 uint32_t _szidx : 6;
110 };
Eugene Zelenko8d15f332015-10-20 01:10:59 +0000111
Enrico Granata6714a0f2014-10-22 21:47:27 +0000112 struct DataDescriptor_64
113 {
114 uint64_t _used : 58;
115 uint32_t _szidx : 6;
116 };
Eugene Zelenko8d15f332015-10-20 01:10:59 +0000117
Enrico Granata6714a0f2014-10-22 21:47:27 +0000118 struct DictionaryItemDescriptor
119 {
120 lldb::addr_t key_ptr;
121 lldb::addr_t val_ptr;
122 lldb::ValueObjectSP valobj_sp;
123 };
Eugene Zelenko8d15f332015-10-20 01:10:59 +0000124
Enrico Granata6714a0f2014-10-22 21:47:27 +0000125 ExecutionContextRef m_exe_ctx_ref;
126 uint8_t m_ptr_size;
127 lldb::ByteOrder m_order;
128 DataDescriptor_32 *m_data_32;
129 DataDescriptor_64 *m_data_64;
130 lldb::addr_t m_data_ptr;
Greg Claytona1e5dc82015-08-11 22:53:00 +0000131 CompilerType m_pair_type;
Enrico Granata6714a0f2014-10-22 21:47:27 +0000132 std::vector<DictionaryItemDescriptor> m_children;
133 };
134
135 class NSDictionaryMSyntheticFrontEnd : public SyntheticChildrenFrontEnd
136 {
Eugene Zelenko8d15f332015-10-20 01:10:59 +0000137 public:
138 NSDictionaryMSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp);
139
140 ~NSDictionaryMSyntheticFrontEnd() override;
141
142 size_t
143 CalculateNumChildren() override;
144
145 lldb::ValueObjectSP
146 GetChildAtIndex(size_t idx) override;
147
148 bool
149 Update() override;
150
151 bool
152 MightHaveChildren() override;
153
154 size_t
155 GetIndexOfChildWithName(const ConstString &name) override;
156
Enrico Granata6714a0f2014-10-22 21:47:27 +0000157 private:
158 struct DataDescriptor_32
159 {
160 uint32_t _used : 26;
161 uint32_t _kvo : 1;
162 uint32_t _size;
163 uint32_t _mutations;
164 uint32_t _objs_addr;
165 uint32_t _keys_addr;
166 };
Eugene Zelenko8d15f332015-10-20 01:10:59 +0000167
Enrico Granata6714a0f2014-10-22 21:47:27 +0000168 struct DataDescriptor_64
169 {
170 uint64_t _used : 58;
171 uint32_t _kvo : 1;
172 uint64_t _size;
173 uint64_t _mutations;
174 uint64_t _objs_addr;
175 uint64_t _keys_addr;
176 };
Eugene Zelenko8d15f332015-10-20 01:10:59 +0000177
Enrico Granata6714a0f2014-10-22 21:47:27 +0000178 struct DictionaryItemDescriptor
179 {
180 lldb::addr_t key_ptr;
181 lldb::addr_t val_ptr;
182 lldb::ValueObjectSP valobj_sp;
183 };
Eugene Zelenko8d15f332015-10-20 01:10:59 +0000184
Enrico Granata6714a0f2014-10-22 21:47:27 +0000185 ExecutionContextRef m_exe_ctx_ref;
186 uint8_t m_ptr_size;
187 lldb::ByteOrder m_order;
188 DataDescriptor_32 *m_data_32;
189 DataDescriptor_64 *m_data_64;
Greg Claytona1e5dc82015-08-11 22:53:00 +0000190 CompilerType m_pair_type;
Enrico Granata6714a0f2014-10-22 21:47:27 +0000191 std::vector<DictionaryItemDescriptor> m_children;
192 };
193
194 class NSDictionaryCodeRunningSyntheticFrontEnd : public SyntheticChildrenFrontEnd
195 {
196 public:
197 NSDictionaryCodeRunningSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp);
Eugene Zelenko8d15f332015-10-20 01:10:59 +0000198
199 ~NSDictionaryCodeRunningSyntheticFrontEnd() override = default;
200
201 size_t
202 CalculateNumChildren() override;
Enrico Granata6714a0f2014-10-22 21:47:27 +0000203
Eugene Zelenko8d15f332015-10-20 01:10:59 +0000204 lldb::ValueObjectSP
205 GetChildAtIndex(size_t idx) override;
Enrico Granata6714a0f2014-10-22 21:47:27 +0000206
Eugene Zelenko8d15f332015-10-20 01:10:59 +0000207 bool
208 Update() override;
Enrico Granata6714a0f2014-10-22 21:47:27 +0000209
Eugene Zelenko8d15f332015-10-20 01:10:59 +0000210 bool
211 MightHaveChildren() override;
Enrico Granata6714a0f2014-10-22 21:47:27 +0000212
Eugene Zelenko8d15f332015-10-20 01:10:59 +0000213 size_t
214 GetIndexOfChildWithName(const ConstString &name) override;
Enrico Granata6714a0f2014-10-22 21:47:27 +0000215 };
Eugene Zelenko8d15f332015-10-20 01:10:59 +0000216 } // namespace formatters
217} // namespace lldb_private
Enrico Granata6714a0f2014-10-22 21:47:27 +0000218
Enrico Granataf615b802013-02-15 23:38:37 +0000219template<bool name_entries>
220bool
Enrico Granataf35bc632014-11-06 21:55:30 +0000221lldb_private::formatters::NSDictionarySummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options)
Enrico Granataf615b802013-02-15 23:38:37 +0000222{
Enrico Granata675f49b2015-10-07 18:36:53 +0000223 static ConstString g_TypeHint("NSDictionary");
Enrico Granataf615b802013-02-15 23:38:37 +0000224 ProcessSP process_sp = valobj.GetProcessSP();
225 if (!process_sp)
226 return false;
227
228 ObjCLanguageRuntime* runtime = (ObjCLanguageRuntime*)process_sp->GetLanguageRuntime(lldb::eLanguageTypeObjC);
229
230 if (!runtime)
231 return false;
232
233 ObjCLanguageRuntime::ClassDescriptorSP descriptor(runtime->GetClassDescriptor(valobj));
234
235 if (!descriptor.get() || !descriptor->IsValid())
236 return false;
237
238 uint32_t ptr_size = process_sp->GetAddressByteSize();
239 bool is_64bit = (ptr_size == 8);
240
241 lldb::addr_t valobj_addr = valobj.GetValueAsUnsigned(0);
242
243 if (!valobj_addr)
244 return false;
245
246 uint64_t value = 0;
247
Enrico Granata7de855c2015-10-02 20:59:58 +0000248 ConstString class_name_cs = descriptor->GetClassName();
249 const char* class_name = class_name_cs.GetCString();
Enrico Granataf615b802013-02-15 23:38:37 +0000250
251 if (!class_name || !*class_name)
252 return false;
253
254 if (!strcmp(class_name,"__NSDictionaryI"))
255 {
256 Error error;
257 value = process_sp->ReadUnsignedIntegerFromMemory(valobj_addr + ptr_size, ptr_size, 0, error);
258 if (error.Fail())
259 return false;
260 value &= (is_64bit ? ~0xFC00000000000000UL : ~0xFC000000U);
261 }
262 else if (!strcmp(class_name,"__NSDictionaryM"))
263 {
264 Error error;
265 value = process_sp->ReadUnsignedIntegerFromMemory(valobj_addr + ptr_size, ptr_size, 0, error);
266 if (error.Fail())
267 return false;
268 value &= (is_64bit ? ~0xFC00000000000000UL : ~0xFC000000U);
269 }
Enrico Granataf68f7322013-03-15 18:44:08 +0000270 /*else if (!strcmp(class_name,"__NSCFDictionary"))
Enrico Granata675f49b2015-10-07 18:36:53 +0000271 {
272 Error error;
273 value = process_sp->ReadUnsignedIntegerFromMemory(valobj_addr + (is_64bit ? 20 : 12), 4, 0, error);
274 if (error.Fail())
275 return false;
276 if (is_64bit)
277 value &= ~0x0f1f000000000000UL;
278 }*/
Enrico Granataf615b802013-02-15 23:38:37 +0000279 else
280 {
Enrico Granata7de855c2015-10-02 20:59:58 +0000281 auto& map(NSDictionary_Additionals::GetAdditionalSummaries());
282 auto iter = map.find(class_name_cs), end = map.end();
283 if (iter != end)
284 return iter->second(valobj, stream, options);
Enrico Granataf615b802013-02-15 23:38:37 +0000285 if (!ExtractValueFromObjCExpression(valobj, "int", "count", value))
286 return false;
287 }
288
Enrico Granata675f49b2015-10-07 18:36:53 +0000289 std::string prefix,suffix;
290 if (Language* language = Language::FindPlugin(options.GetLanguage()))
291 {
292 if (!language->GetFormatterPrefixSuffix(valobj, g_TypeHint, prefix, suffix))
293 {
294 prefix.clear();
295 suffix.clear();
296 }
297 }
298
299 stream.Printf("%s%" PRIu64 " %s%s%s",
300 prefix.c_str(),
Enrico Granataf615b802013-02-15 23:38:37 +0000301 value,
Enrico Granata675f49b2015-10-07 18:36:53 +0000302 "key/value pair",
303 value == 1 ? "" : "s",
304 suffix.c_str());
Enrico Granataf615b802013-02-15 23:38:37 +0000305 return true;
306}
307
Enrico Granata7de855c2015-10-02 20:59:58 +0000308SyntheticChildrenFrontEnd* lldb_private::formatters::NSDictionarySyntheticFrontEndCreator (CXXSyntheticChildren* synth, lldb::ValueObjectSP valobj_sp)
Enrico Granataf615b802013-02-15 23:38:37 +0000309{
Enrico Granataf615b802013-02-15 23:38:37 +0000310 lldb::ProcessSP process_sp (valobj_sp->GetProcessSP());
311 if (!process_sp)
312 return NULL;
313 ObjCLanguageRuntime *runtime = (ObjCLanguageRuntime*)process_sp->GetLanguageRuntime(lldb::eLanguageTypeObjC);
314 if (!runtime)
315 return NULL;
316
Enrico Granata675f49b2015-10-07 18:36:53 +0000317 CompilerType valobj_type(valobj_sp->GetCompilerType());
318 Flags flags(valobj_type.GetTypeInfo());
319
320 if (flags.IsClear(eTypeIsPointer))
Enrico Granataf615b802013-02-15 23:38:37 +0000321 {
322 Error error;
323 valobj_sp = valobj_sp->AddressOf(error);
324 if (error.Fail() || !valobj_sp)
325 return NULL;
326 }
327
328 ObjCLanguageRuntime::ClassDescriptorSP descriptor(runtime->GetClassDescriptor(*valobj_sp.get()));
329
330 if (!descriptor.get() || !descriptor->IsValid())
331 return NULL;
332
Enrico Granata7de855c2015-10-02 20:59:58 +0000333 ConstString class_name_cs = descriptor->GetClassName();
334 const char* class_name = class_name_cs.GetCString();
Enrico Granataf615b802013-02-15 23:38:37 +0000335
336 if (!class_name || !*class_name)
337 return NULL;
338
339 if (!strcmp(class_name,"__NSDictionaryI"))
340 {
341 return (new NSDictionaryISyntheticFrontEnd(valobj_sp));
342 }
343 else if (!strcmp(class_name,"__NSDictionaryM"))
344 {
345 return (new NSDictionaryMSyntheticFrontEnd(valobj_sp));
346 }
347 else
348 {
Enrico Granata7de855c2015-10-02 20:59:58 +0000349 auto& map(NSDictionary_Additionals::GetAdditionalSynthetics());
350 auto iter = map.find(class_name_cs), end = map.end();
351 if (iter != end)
352 return iter->second(synth, valobj_sp);
Enrico Granataf615b802013-02-15 23:38:37 +0000353 return (new NSDictionaryCodeRunningSyntheticFrontEnd(valobj_sp));
354 }
355}
356
357lldb_private::formatters::NSDictionaryCodeRunningSyntheticFrontEnd::NSDictionaryCodeRunningSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp) :
358SyntheticChildrenFrontEnd(*valobj_sp.get())
359{}
360
361size_t
362lldb_private::formatters::NSDictionaryCodeRunningSyntheticFrontEnd::CalculateNumChildren ()
363{
364 uint64_t count = 0;
365 if (ExtractValueFromObjCExpression(m_backend, "int", "count", count))
366 return count;
367 return 0;
368}
369
370lldb::ValueObjectSP
371lldb_private::formatters::NSDictionaryCodeRunningSyntheticFrontEnd::GetChildAtIndex (size_t idx)
372{
373 StreamString idx_name;
Deepak Panickal99fbc072014-03-03 15:39:47 +0000374 idx_name.Printf("[%" PRIu64 "]", (uint64_t)idx);
Enrico Granataf615b802013-02-15 23:38:37 +0000375 StreamString key_fetcher_expr;
Deepak Panickal99fbc072014-03-03 15:39:47 +0000376 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 +0000377 StreamString value_fetcher_expr;
Enrico Granataa221e4e2013-02-25 19:44:39 +0000378 value_fetcher_expr.Printf("(id)[(id)0x%" PRIx64 " objectForKey:(%s)]",m_backend.GetPointerValue(),key_fetcher_expr.GetData());
Enrico Granataf615b802013-02-15 23:38:37 +0000379 StreamString object_fetcher_expr;
380 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());
381 lldb::ValueObjectSP child_sp;
Jim Ingham6fbc48b2013-11-07 00:11:47 +0000382 EvaluateExpressionOptions options;
383 options.SetKeepInMemory(true);
Enrico Granata675f49b2015-10-07 18:36:53 +0000384 options.SetLanguage(lldb::eLanguageTypeObjC_plus_plus);
385 options.SetResultIsInternal(true);
Enrico Granataba8eb122014-07-30 21:07:50 +0000386 m_backend.GetTargetSP()->EvaluateExpression(object_fetcher_expr.GetData(),
387 GetViableFrame(m_backend.GetTargetSP().get()),
388 child_sp,
Jim Ingham6fbc48b2013-11-07 00:11:47 +0000389 options);
Enrico Granataf615b802013-02-15 23:38:37 +0000390 if (child_sp)
391 child_sp->SetName(ConstString(idx_name.GetData()));
392 return child_sp;
393}
394
395bool
396lldb_private::formatters::NSDictionaryCodeRunningSyntheticFrontEnd::Update()
397{
398 return false;
399}
400
401bool
402lldb_private::formatters::NSDictionaryCodeRunningSyntheticFrontEnd::MightHaveChildren ()
403{
404 return true;
405}
406
407size_t
408lldb_private::formatters::NSDictionaryCodeRunningSyntheticFrontEnd::GetIndexOfChildWithName (const ConstString &name)
409{
410 return 0;
411}
412
Enrico Granataf615b802013-02-15 23:38:37 +0000413lldb_private::formatters::NSDictionaryISyntheticFrontEnd::NSDictionaryISyntheticFrontEnd (lldb::ValueObjectSP valobj_sp) :
414SyntheticChildrenFrontEnd(*valobj_sp.get()),
415m_exe_ctx_ref(),
416m_ptr_size(8),
Enrico Granataeb8bd922013-04-03 01:25:29 +0000417m_order(lldb::eByteOrderInvalid),
Enrico Granataf615b802013-02-15 23:38:37 +0000418m_data_32(NULL),
Enrico Granataeb8bd922013-04-03 01:25:29 +0000419m_data_64(NULL),
420m_pair_type()
Enrico Granataf615b802013-02-15 23:38:37 +0000421{
Enrico Granataf615b802013-02-15 23:38:37 +0000422}
423
424lldb_private::formatters::NSDictionaryISyntheticFrontEnd::~NSDictionaryISyntheticFrontEnd ()
425{
426 delete m_data_32;
427 m_data_32 = NULL;
428 delete m_data_64;
429 m_data_64 = NULL;
430}
431
432size_t
433lldb_private::formatters::NSDictionaryISyntheticFrontEnd::GetIndexOfChildWithName (const ConstString &name)
434{
435 const char* item_name = name.GetCString();
436 uint32_t idx = ExtractIndexFromString(item_name);
437 if (idx < UINT32_MAX && idx >= CalculateNumChildren())
438 return UINT32_MAX;
439 return idx;
440}
441
442size_t
443lldb_private::formatters::NSDictionaryISyntheticFrontEnd::CalculateNumChildren ()
444{
445 if (!m_data_32 && !m_data_64)
446 return 0;
447 return (m_data_32 ? m_data_32->_used : m_data_64->_used);
448}
449
450bool
451lldb_private::formatters::NSDictionaryISyntheticFrontEnd::Update()
452{
453 m_children.clear();
454 delete m_data_32;
455 m_data_32 = NULL;
456 delete m_data_64;
457 m_data_64 = NULL;
458 m_ptr_size = 0;
459 ValueObjectSP valobj_sp = m_backend.GetSP();
460 if (!valobj_sp)
461 return false;
Enrico Granataf615b802013-02-15 23:38:37 +0000462 m_exe_ctx_ref = valobj_sp->GetExecutionContextRef();
463 Error error;
Enrico Granataf615b802013-02-15 23:38:37 +0000464 error.Clear();
465 lldb::ProcessSP process_sp(valobj_sp->GetProcessSP());
466 if (!process_sp)
467 return false;
468 m_ptr_size = process_sp->GetAddressByteSize();
Enrico Granataeb8bd922013-04-03 01:25:29 +0000469 m_order = process_sp->GetByteOrder();
Enrico Granata723e1292013-04-23 01:13:50 +0000470 uint64_t data_location = valobj_sp->GetValueAsUnsigned(0) + m_ptr_size;
Enrico Granataf615b802013-02-15 23:38:37 +0000471 if (m_ptr_size == 4)
472 {
473 m_data_32 = new DataDescriptor_32();
474 process_sp->ReadMemory (data_location, m_data_32, sizeof(DataDescriptor_32), error);
475 }
476 else
477 {
478 m_data_64 = new DataDescriptor_64();
479 process_sp->ReadMemory (data_location, m_data_64, sizeof(DataDescriptor_64), error);
480 }
481 if (error.Fail())
482 return false;
483 m_data_ptr = data_location + m_ptr_size;
484 return false;
485}
486
487bool
488lldb_private::formatters::NSDictionaryISyntheticFrontEnd::MightHaveChildren ()
489{
490 return true;
491}
492
493lldb::ValueObjectSP
494lldb_private::formatters::NSDictionaryISyntheticFrontEnd::GetChildAtIndex (size_t idx)
495{
496 uint32_t num_children = CalculateNumChildren();
497
498 if (idx >= num_children)
499 return lldb::ValueObjectSP();
500
501 if (m_children.empty())
502 {
503 // do the scan phase
504 lldb::addr_t key_at_idx = 0, val_at_idx = 0;
505
506 uint32_t tries = 0;
507 uint32_t test_idx = 0;
508
509 while(tries < num_children)
510 {
511 key_at_idx = m_data_ptr + (2*test_idx * m_ptr_size);
512 val_at_idx = key_at_idx + m_ptr_size;
513 ProcessSP process_sp = m_exe_ctx_ref.GetProcessSP();
514 if (!process_sp)
515 return lldb::ValueObjectSP();
516 Error error;
517 key_at_idx = process_sp->ReadPointerFromMemory(key_at_idx, error);
518 if (error.Fail())
519 return lldb::ValueObjectSP();
520 val_at_idx = process_sp->ReadPointerFromMemory(val_at_idx, error);
521 if (error.Fail())
522 return lldb::ValueObjectSP();
523
524 test_idx++;
525
526 if (!key_at_idx || !val_at_idx)
527 continue;
528 tries++;
529
530 DictionaryItemDescriptor descriptor = {key_at_idx,val_at_idx,lldb::ValueObjectSP()};
531
532 m_children.push_back(descriptor);
533 }
534 }
535
536 if (idx >= m_children.size()) // should never happen
537 return lldb::ValueObjectSP();
538
539 DictionaryItemDescriptor &dict_item = m_children[idx];
540 if (!dict_item.valobj_sp)
541 {
Enrico Granataeb8bd922013-04-03 01:25:29 +0000542 if (!m_pair_type.IsValid())
543 {
544 TargetSP target_sp(m_backend.GetTargetSP());
545 if (!target_sp)
546 return ValueObjectSP();
547 m_pair_type = GetLLDBNSPairType(target_sp);
548 }
549 if (!m_pair_type.IsValid())
550 return ValueObjectSP();
551
552 DataBufferSP buffer_sp(new DataBufferHeap(2*m_ptr_size,0));
553
554 if (m_ptr_size == 8)
555 {
556 uint64_t *data_ptr = (uint64_t *)buffer_sp->GetBytes();
557 *data_ptr = dict_item.key_ptr;
558 *(data_ptr+1) = dict_item.val_ptr;
559 }
560 else
561 {
562 uint32_t *data_ptr = (uint32_t *)buffer_sp->GetBytes();
563 *data_ptr = dict_item.key_ptr;
564 *(data_ptr+1) = dict_item.val_ptr;
565 }
566
Enrico Granataf615b802013-02-15 23:38:37 +0000567 StreamString idx_name;
Deepak Panickal99fbc072014-03-03 15:39:47 +0000568 idx_name.Printf("[%" PRIu64 "]", (uint64_t)idx);
Enrico Granataeb8bd922013-04-03 01:25:29 +0000569 DataExtractor data(buffer_sp, m_order, m_ptr_size);
Enrico Granatae29df232014-12-09 19:51:20 +0000570 dict_item.valobj_sp = CreateValueObjectFromData(idx_name.GetData(),
571 data,
572 m_exe_ctx_ref,
573 m_pair_type);
Enrico Granataf615b802013-02-15 23:38:37 +0000574 }
575 return dict_item.valobj_sp;
576}
577
578lldb_private::formatters::NSDictionaryMSyntheticFrontEnd::NSDictionaryMSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp) :
579SyntheticChildrenFrontEnd(*valobj_sp.get()),
580m_exe_ctx_ref(),
581m_ptr_size(8),
Enrico Granataeb8bd922013-04-03 01:25:29 +0000582m_order(lldb::eByteOrderInvalid),
Enrico Granataf615b802013-02-15 23:38:37 +0000583m_data_32(NULL),
Enrico Granataeb8bd922013-04-03 01:25:29 +0000584m_data_64(NULL),
585m_pair_type()
Enrico Granataf615b802013-02-15 23:38:37 +0000586{
Enrico Granataf615b802013-02-15 23:38:37 +0000587}
588
589lldb_private::formatters::NSDictionaryMSyntheticFrontEnd::~NSDictionaryMSyntheticFrontEnd ()
590{
591 delete m_data_32;
592 m_data_32 = NULL;
593 delete m_data_64;
594 m_data_64 = NULL;
595}
596
597size_t
598lldb_private::formatters::NSDictionaryMSyntheticFrontEnd::GetIndexOfChildWithName (const ConstString &name)
599{
600 const char* item_name = name.GetCString();
601 uint32_t idx = ExtractIndexFromString(item_name);
602 if (idx < UINT32_MAX && idx >= CalculateNumChildren())
603 return UINT32_MAX;
604 return idx;
605}
606
607size_t
608lldb_private::formatters::NSDictionaryMSyntheticFrontEnd::CalculateNumChildren ()
609{
610 if (!m_data_32 && !m_data_64)
611 return 0;
612 return (m_data_32 ? m_data_32->_used : m_data_64->_used);
613}
614
615bool
616lldb_private::formatters::NSDictionaryMSyntheticFrontEnd::Update()
617{
618 m_children.clear();
619 ValueObjectSP valobj_sp = m_backend.GetSP();
620 m_ptr_size = 0;
621 delete m_data_32;
622 m_data_32 = NULL;
623 delete m_data_64;
624 m_data_64 = NULL;
625 if (!valobj_sp)
626 return false;
Enrico Granataf615b802013-02-15 23:38:37 +0000627 m_exe_ctx_ref = valobj_sp->GetExecutionContextRef();
628 Error error;
Enrico Granataf615b802013-02-15 23:38:37 +0000629 error.Clear();
630 lldb::ProcessSP process_sp(valobj_sp->GetProcessSP());
631 if (!process_sp)
632 return false;
633 m_ptr_size = process_sp->GetAddressByteSize();
Enrico Granataeb8bd922013-04-03 01:25:29 +0000634 m_order = process_sp->GetByteOrder();
Enrico Granata723e1292013-04-23 01:13:50 +0000635 uint64_t data_location = valobj_sp->GetValueAsUnsigned(0) + m_ptr_size;
Enrico Granataf615b802013-02-15 23:38:37 +0000636 if (m_ptr_size == 4)
637 {
638 m_data_32 = new DataDescriptor_32();
639 process_sp->ReadMemory (data_location, m_data_32, sizeof(DataDescriptor_32), error);
640 }
641 else
642 {
643 m_data_64 = new DataDescriptor_64();
644 process_sp->ReadMemory (data_location, m_data_64, sizeof(DataDescriptor_64), error);
645 }
646 if (error.Fail())
647 return false;
648 return false;
649}
650
651bool
652lldb_private::formatters::NSDictionaryMSyntheticFrontEnd::MightHaveChildren ()
653{
654 return true;
655}
656
657lldb::ValueObjectSP
658lldb_private::formatters::NSDictionaryMSyntheticFrontEnd::GetChildAtIndex (size_t idx)
659{
660 lldb::addr_t m_keys_ptr = (m_data_32 ? m_data_32->_keys_addr : m_data_64->_keys_addr);
661 lldb::addr_t m_values_ptr = (m_data_32 ? m_data_32->_objs_addr : m_data_64->_objs_addr);
662
663 uint32_t num_children = CalculateNumChildren();
664
665 if (idx >= num_children)
666 return lldb::ValueObjectSP();
667
668 if (m_children.empty())
669 {
670 // do the scan phase
671 lldb::addr_t key_at_idx = 0, val_at_idx = 0;
672
673 uint32_t tries = 0;
674 uint32_t test_idx = 0;
675
676 while(tries < num_children)
677 {
678 key_at_idx = m_keys_ptr + (test_idx * m_ptr_size);
679 val_at_idx = m_values_ptr + (test_idx * m_ptr_size);;
680 ProcessSP process_sp = m_exe_ctx_ref.GetProcessSP();
681 if (!process_sp)
682 return lldb::ValueObjectSP();
683 Error error;
684 key_at_idx = process_sp->ReadPointerFromMemory(key_at_idx, error);
685 if (error.Fail())
686 return lldb::ValueObjectSP();
687 val_at_idx = process_sp->ReadPointerFromMemory(val_at_idx, error);
688 if (error.Fail())
689 return lldb::ValueObjectSP();
690
691 test_idx++;
692
693 if (!key_at_idx || !val_at_idx)
694 continue;
695 tries++;
696
697 DictionaryItemDescriptor descriptor = {key_at_idx,val_at_idx,lldb::ValueObjectSP()};
698
699 m_children.push_back(descriptor);
700 }
701 }
702
703 if (idx >= m_children.size()) // should never happen
704 return lldb::ValueObjectSP();
705
706 DictionaryItemDescriptor &dict_item = m_children[idx];
707 if (!dict_item.valobj_sp)
708 {
Enrico Granataeb8bd922013-04-03 01:25:29 +0000709 if (!m_pair_type.IsValid())
710 {
711 TargetSP target_sp(m_backend.GetTargetSP());
712 if (!target_sp)
713 return ValueObjectSP();
714 m_pair_type = GetLLDBNSPairType(target_sp);
715 }
716 if (!m_pair_type.IsValid())
717 return ValueObjectSP();
718
719 DataBufferSP buffer_sp(new DataBufferHeap(2*m_ptr_size,0));
720
721 if (m_ptr_size == 8)
722 {
723 uint64_t *data_ptr = (uint64_t *)buffer_sp->GetBytes();
724 *data_ptr = dict_item.key_ptr;
725 *(data_ptr+1) = dict_item.val_ptr;
726 }
727 else
728 {
729 uint32_t *data_ptr = (uint32_t *)buffer_sp->GetBytes();
730 *data_ptr = dict_item.key_ptr;
731 *(data_ptr+1) = dict_item.val_ptr;
732 }
733
Enrico Granataf615b802013-02-15 23:38:37 +0000734 StreamString idx_name;
Deepak Panickal99fbc072014-03-03 15:39:47 +0000735 idx_name.Printf("[%" PRIu64 "]", (uint64_t)idx);
Enrico Granataeb8bd922013-04-03 01:25:29 +0000736 DataExtractor data(buffer_sp, m_order, m_ptr_size);
Enrico Granatae29df232014-12-09 19:51:20 +0000737 dict_item.valobj_sp = CreateValueObjectFromData(idx_name.GetData(),
738 data,
739 m_exe_ctx_ref,
740 m_pair_type);
Enrico Granataf615b802013-02-15 23:38:37 +0000741 }
742 return dict_item.valobj_sp;
743}
744
745template bool
Eugene Zelenko8d15f332015-10-20 01:10:59 +0000746lldb_private::formatters::NSDictionarySummaryProvider<true> (ValueObject&, Stream&, const TypeSummaryOptions&);
Enrico Granataf615b802013-02-15 23:38:37 +0000747
748template bool
Eugene Zelenko8d15f332015-10-20 01:10:59 +0000749lldb_private::formatters::NSDictionarySummaryProvider<false> (ValueObject&, Stream&, const TypeSummaryOptions&);