blob: 93115957e329a45e5c578d83d76b3cf4ddabff3b [file] [log] [blame]
Eugene Zelenko8d15f332015-10-20 01:10:59 +00001//===-- NSSet.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// Other libraries and framework includes
13// Project includes
Enrico Granata7de855c2015-10-02 20:59:58 +000014#include "NSSet.h"
Enrico Granataf615b802013-02-15 23:38:37 +000015
Enrico Granataf615b802013-02-15 23:38:37 +000016#include "lldb/Core/DataBufferHeap.h"
17#include "lldb/Core/Error.h"
18#include "lldb/Core/Stream.h"
19#include "lldb/Core/ValueObject.h"
20#include "lldb/Core/ValueObjectConstResult.h"
Enrico Granata419d7912015-09-04 00:33:51 +000021#include "lldb/DataFormatters/FormattersHelpers.h"
Enrico Granataf615b802013-02-15 23:38:37 +000022#include "lldb/Host/Endian.h"
23#include "lldb/Symbol/ClangASTContext.h"
Enrico Granata675f49b2015-10-07 18:36:53 +000024#include "lldb/Target/Language.h"
Enrico Granataf615b802013-02-15 23:38:37 +000025#include "lldb/Target/ObjCLanguageRuntime.h"
26#include "lldb/Target/Target.h"
27
28using namespace lldb;
29using namespace lldb_private;
30using namespace lldb_private::formatters;
31
Enrico Granata7de855c2015-10-02 20:59:58 +000032std::map<ConstString, CXXFunctionSummaryFormat::Callback>&
33NSSet_Additionals::GetAdditionalSummaries ()
34{
35 static std::map<ConstString, CXXFunctionSummaryFormat::Callback> g_map;
36 return g_map;
37}
38
39std::map<ConstString, CXXSyntheticChildren::CreateFrontEndCallback>&
40NSSet_Additionals::GetAdditionalSynthetics ()
41{
42 static std::map<ConstString, CXXSyntheticChildren::CreateFrontEndCallback> g_map;
43 return g_map;
44}
45
Enrico Granata6714a0f2014-10-22 21:47:27 +000046namespace lldb_private {
47 namespace formatters {
48 class NSSetISyntheticFrontEnd : public SyntheticChildrenFrontEnd
49 {
Eugene Zelenko8d15f332015-10-20 01:10:59 +000050 public:
51 NSSetISyntheticFrontEnd (lldb::ValueObjectSP valobj_sp);
52
53 ~NSSetISyntheticFrontEnd() override;
54
55 size_t
56 CalculateNumChildren() override;
57
58 lldb::ValueObjectSP
59 GetChildAtIndex(size_t idx) override;
60
61 bool
62 Update() override;
63
64 bool
65 MightHaveChildren() override;
66
67 size_t
68 GetIndexOfChildWithName(const ConstString &name) override;
69
Enrico Granata6714a0f2014-10-22 21:47:27 +000070 private:
71 struct DataDescriptor_32
72 {
73 uint32_t _used : 26;
74 uint32_t _szidx : 6;
75 };
Eugene Zelenko8d15f332015-10-20 01:10:59 +000076
Enrico Granata6714a0f2014-10-22 21:47:27 +000077 struct DataDescriptor_64
78 {
79 uint64_t _used : 58;
80 uint32_t _szidx : 6;
81 };
Eugene Zelenko8d15f332015-10-20 01:10:59 +000082
Enrico Granata6714a0f2014-10-22 21:47:27 +000083 struct SetItemDescriptor
84 {
85 lldb::addr_t item_ptr;
86 lldb::ValueObjectSP valobj_sp;
87 };
Eugene Zelenko8d15f332015-10-20 01:10:59 +000088
Enrico Granata6714a0f2014-10-22 21:47:27 +000089 ExecutionContextRef m_exe_ctx_ref;
90 uint8_t m_ptr_size;
91 DataDescriptor_32 *m_data_32;
92 DataDescriptor_64 *m_data_64;
93 lldb::addr_t m_data_ptr;
94 std::vector<SetItemDescriptor> m_children;
95 };
96
97 class NSOrderedSetSyntheticFrontEnd : public SyntheticChildrenFrontEnd
98 {
Enrico Granata6714a0f2014-10-22 21:47:27 +000099 public:
100 NSOrderedSetSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp);
Eugene Zelenko8d15f332015-10-20 01:10:59 +0000101
102 ~NSOrderedSetSyntheticFrontEnd() override = default;
103
104 size_t
105 CalculateNumChildren() override;
Enrico Granata6714a0f2014-10-22 21:47:27 +0000106
Eugene Zelenko8d15f332015-10-20 01:10:59 +0000107 lldb::ValueObjectSP
108 GetChildAtIndex(size_t idx) override;
Enrico Granata6714a0f2014-10-22 21:47:27 +0000109
Eugene Zelenko8d15f332015-10-20 01:10:59 +0000110 bool
111 Update() override;
Enrico Granata6714a0f2014-10-22 21:47:27 +0000112
Eugene Zelenko8d15f332015-10-20 01:10:59 +0000113 bool
114 MightHaveChildren() override;
Enrico Granata6714a0f2014-10-22 21:47:27 +0000115
Eugene Zelenko8d15f332015-10-20 01:10:59 +0000116 size_t
117 GetIndexOfChildWithName(const ConstString &name) override;
118
Enrico Granata6714a0f2014-10-22 21:47:27 +0000119 private:
120 uint32_t m_count;
121 std::map<uint32_t,lldb::ValueObjectSP> m_children;
122 };
123
124 class NSSetMSyntheticFrontEnd : public SyntheticChildrenFrontEnd
125 {
Eugene Zelenko8d15f332015-10-20 01:10:59 +0000126 public:
127 NSSetMSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp);
128
129 ~NSSetMSyntheticFrontEnd() override;
130
131 size_t
132 CalculateNumChildren() override;
133
134 lldb::ValueObjectSP
135 GetChildAtIndex(size_t idx) override;
136
137 bool
138 Update() override;
139
140 bool
141 MightHaveChildren() override;
142
143 size_t
144 GetIndexOfChildWithName(const ConstString &name) override;
145
Enrico Granata6714a0f2014-10-22 21:47:27 +0000146 private:
147 struct DataDescriptor_32
148 {
149 uint32_t _used : 26;
150 uint32_t _size;
151 uint32_t _mutations;
152 uint32_t _objs_addr;
153 };
Eugene Zelenko8d15f332015-10-20 01:10:59 +0000154
Enrico Granata6714a0f2014-10-22 21:47:27 +0000155 struct DataDescriptor_64
156 {
157 uint64_t _used : 58;
158 uint64_t _size;
159 uint64_t _mutations;
160 uint64_t _objs_addr;
161 };
Eugene Zelenko8d15f332015-10-20 01:10:59 +0000162
Enrico Granata6714a0f2014-10-22 21:47:27 +0000163 struct SetItemDescriptor
164 {
165 lldb::addr_t item_ptr;
166 lldb::ValueObjectSP valobj_sp;
167 };
Eugene Zelenko8d15f332015-10-20 01:10:59 +0000168
Enrico Granata6714a0f2014-10-22 21:47:27 +0000169 ExecutionContextRef m_exe_ctx_ref;
170 uint8_t m_ptr_size;
171 DataDescriptor_32 *m_data_32;
172 DataDescriptor_64 *m_data_64;
173 std::vector<SetItemDescriptor> m_children;
174 };
175
176 class NSSetCodeRunningSyntheticFrontEnd : public SyntheticChildrenFrontEnd
177 {
178 public:
179 NSSetCodeRunningSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp);
Eugene Zelenko8d15f332015-10-20 01:10:59 +0000180
181 ~NSSetCodeRunningSyntheticFrontEnd() override;
182
183 size_t
184 CalculateNumChildren() override;
Enrico Granata6714a0f2014-10-22 21:47:27 +0000185
Eugene Zelenko8d15f332015-10-20 01:10:59 +0000186 lldb::ValueObjectSP
187 GetChildAtIndex(size_t idx) override;
Enrico Granata6714a0f2014-10-22 21:47:27 +0000188
Eugene Zelenko8d15f332015-10-20 01:10:59 +0000189 bool
190 Update() override;
Enrico Granata6714a0f2014-10-22 21:47:27 +0000191
Eugene Zelenko8d15f332015-10-20 01:10:59 +0000192 bool
193 MightHaveChildren() override;
Enrico Granata6714a0f2014-10-22 21:47:27 +0000194
Eugene Zelenko8d15f332015-10-20 01:10:59 +0000195 size_t
196 GetIndexOfChildWithName(const ConstString &name) override;
Enrico Granata6714a0f2014-10-22 21:47:27 +0000197 };
Eugene Zelenko8d15f332015-10-20 01:10:59 +0000198 } // namespace formatters
199} // namespace lldb_private
Enrico Granata6714a0f2014-10-22 21:47:27 +0000200
Enrico Granataf615b802013-02-15 23:38:37 +0000201template<bool cf_style>
202bool
Enrico Granataf35bc632014-11-06 21:55:30 +0000203lldb_private::formatters::NSSetSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options)
Enrico Granataf615b802013-02-15 23:38:37 +0000204{
Enrico Granata675f49b2015-10-07 18:36:53 +0000205 static ConstString g_TypeHint("NSSet");
206
Enrico Granataf615b802013-02-15 23:38:37 +0000207 ProcessSP process_sp = valobj.GetProcessSP();
208 if (!process_sp)
209 return false;
210
211 ObjCLanguageRuntime* runtime = (ObjCLanguageRuntime*)process_sp->GetLanguageRuntime(lldb::eLanguageTypeObjC);
212
213 if (!runtime)
214 return false;
215
216 ObjCLanguageRuntime::ClassDescriptorSP descriptor(runtime->GetClassDescriptor(valobj));
217
218 if (!descriptor.get() || !descriptor->IsValid())
219 return false;
220
221 uint32_t ptr_size = process_sp->GetAddressByteSize();
222 bool is_64bit = (ptr_size == 8);
223
224 lldb::addr_t valobj_addr = valobj.GetValueAsUnsigned(0);
225
226 if (!valobj_addr)
227 return false;
228
229 uint64_t value = 0;
230
Enrico Granata7de855c2015-10-02 20:59:58 +0000231 ConstString class_name_cs = descriptor->GetClassName();
232 const char* class_name = class_name_cs.GetCString();
Enrico Granataf615b802013-02-15 23:38:37 +0000233
234 if (!class_name || !*class_name)
235 return false;
236
237 if (!strcmp(class_name,"__NSSetI"))
238 {
239 Error error;
240 value = process_sp->ReadUnsignedIntegerFromMemory(valobj_addr + ptr_size, ptr_size, 0, error);
241 if (error.Fail())
242 return false;
243 value &= (is_64bit ? ~0xFC00000000000000UL : ~0xFC000000U);
244 }
245 else if (!strcmp(class_name,"__NSSetM"))
246 {
247 Error error;
248 value = process_sp->ReadUnsignedIntegerFromMemory(valobj_addr + ptr_size, ptr_size, 0, error);
249 if (error.Fail())
250 return false;
251 value &= (is_64bit ? ~0xFC00000000000000UL : ~0xFC000000U);
252 }
Enrico Granataea9f9e82013-07-15 23:17:32 +0000253 /*else if (!strcmp(class_name,"__NSCFSet"))
Enrico Granata675f49b2015-10-07 18:36:53 +0000254 {
255 Error error;
256 value = process_sp->ReadUnsignedIntegerFromMemory(valobj_addr + (is_64bit ? 20 : 12), 4, 0, error);
257 if (error.Fail())
258 return false;
259 if (is_64bit)
260 value &= ~0x1fff000000000000UL;
261 }
262 else if (!strcmp(class_name,"NSCountedSet"))
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 = process_sp->ReadUnsignedIntegerFromMemory(value + (is_64bit ? 20 : 12), 4, 0, error);
269 if (error.Fail())
270 return false;
271 if (is_64bit)
272 value &= ~0x1fff000000000000UL;
273 }*/
Enrico Granataf615b802013-02-15 23:38:37 +0000274 else
275 {
Enrico Granata7de855c2015-10-02 20:59:58 +0000276 auto& map(NSSet_Additionals::GetAdditionalSummaries());
277 auto iter = map.find(class_name_cs), end = map.end();
278 if (iter != end)
279 return iter->second(valobj, stream, options);
Enrico Granataf615b802013-02-15 23:38:37 +0000280 if (!ExtractValueFromObjCExpression(valobj, "int", "count", value))
281 return false;
282 }
283
Enrico Granata675f49b2015-10-07 18:36:53 +0000284 std::string prefix,suffix;
285 if (Language* language = Language::FindPlugin(options.GetLanguage()))
286 {
287 if (!language->GetFormatterPrefixSuffix(valobj, g_TypeHint, prefix, suffix))
288 {
289 prefix.clear();
290 suffix.clear();
291 }
292 }
293
294 stream.Printf("%s%" PRIu64 " %s%s%s",
295 prefix.c_str(),
Enrico Granataf615b802013-02-15 23:38:37 +0000296 value,
Enrico Granata675f49b2015-10-07 18:36:53 +0000297 "element",
298 value == 1 ? "" : "s",
299 suffix.c_str());
Enrico Granataf615b802013-02-15 23:38:37 +0000300 return true;
301}
302
Enrico Granata7de855c2015-10-02 20:59:58 +0000303SyntheticChildrenFrontEnd* lldb_private::formatters::NSSetSyntheticFrontEndCreator (CXXSyntheticChildren* synth, lldb::ValueObjectSP valobj_sp)
Enrico Granata9f02e092013-02-18 23:16:23 +0000304{
305 lldb::ProcessSP process_sp (valobj_sp->GetProcessSP());
306 if (!process_sp)
307 return NULL;
308 ObjCLanguageRuntime *runtime = (ObjCLanguageRuntime*)process_sp->GetLanguageRuntime(lldb::eLanguageTypeObjC);
309 if (!runtime)
310 return NULL;
311
Enrico Granata675f49b2015-10-07 18:36:53 +0000312 CompilerType valobj_type(valobj_sp->GetCompilerType());
313 Flags flags(valobj_type.GetTypeInfo());
314
315 if (flags.IsClear(eTypeIsPointer))
Enrico Granata9f02e092013-02-18 23:16:23 +0000316 {
317 Error error;
318 valobj_sp = valobj_sp->AddressOf(error);
319 if (error.Fail() || !valobj_sp)
320 return NULL;
321 }
322
323 ObjCLanguageRuntime::ClassDescriptorSP descriptor(runtime->GetClassDescriptor(*valobj_sp.get()));
324
325 if (!descriptor.get() || !descriptor->IsValid())
326 return NULL;
327
Enrico Granata7de855c2015-10-02 20:59:58 +0000328 ConstString class_name_cs = descriptor->GetClassName();
329 const char* class_name = class_name_cs.GetCString();
Enrico Granata9f02e092013-02-18 23:16:23 +0000330
331 if (!class_name || !*class_name)
332 return NULL;
333
334 if (!strcmp(class_name,"__NSSetI"))
335 {
336 return (new NSSetISyntheticFrontEnd(valobj_sp));
337 }
338 else if (!strcmp(class_name,"__NSSetM"))
339 {
340 return (new NSSetMSyntheticFrontEnd(valobj_sp));
341 }
Enrico Granatacd67f972013-04-27 00:27:20 +0000342 else if ((!strcmp(class_name,"__NSOrderedSetI")) || (!strcmp(class_name,"__NSOrderedSetM")))
343 {
344 return new NSOrderedSetSyntheticFrontEnd(valobj_sp); // this runs code
345 }
Enrico Granata9f02e092013-02-18 23:16:23 +0000346 else
347 {
Enrico Granata7de855c2015-10-02 20:59:58 +0000348 auto& map(NSSet_Additionals::GetAdditionalSynthetics());
349 auto iter = map.find(class_name_cs), end = map.end();
350 if (iter != end)
351 return iter->second(synth, valobj_sp);
Enrico Granata9f02e092013-02-18 23:16:23 +0000352 return /*(new NSSetCodeRunningSyntheticFrontEnd(valobj_sp))*/ NULL;
353 }
354}
355
356lldb_private::formatters::NSSetISyntheticFrontEnd::NSSetISyntheticFrontEnd (lldb::ValueObjectSP valobj_sp) :
357SyntheticChildrenFrontEnd(*valobj_sp.get()),
358m_exe_ctx_ref(),
359m_ptr_size(8),
360m_data_32(NULL),
361m_data_64(NULL)
362{
363 if (valobj_sp)
364 Update();
365}
366
367lldb_private::formatters::NSSetISyntheticFrontEnd::~NSSetISyntheticFrontEnd ()
368{
369 delete m_data_32;
370 m_data_32 = NULL;
371 delete m_data_64;
372 m_data_64 = NULL;
373}
374
375size_t
376lldb_private::formatters::NSSetISyntheticFrontEnd::GetIndexOfChildWithName (const ConstString &name)
377{
378 const char* item_name = name.GetCString();
379 uint32_t idx = ExtractIndexFromString(item_name);
380 if (idx < UINT32_MAX && idx >= CalculateNumChildren())
381 return UINT32_MAX;
382 return idx;
383}
384
385size_t
386lldb_private::formatters::NSSetISyntheticFrontEnd::CalculateNumChildren ()
387{
388 if (!m_data_32 && !m_data_64)
389 return 0;
390 return (m_data_32 ? m_data_32->_used : m_data_64->_used);
391}
392
393bool
394lldb_private::formatters::NSSetISyntheticFrontEnd::Update()
395{
396 m_children.clear();
397 delete m_data_32;
398 m_data_32 = NULL;
399 delete m_data_64;
400 m_data_64 = NULL;
401 m_ptr_size = 0;
402 ValueObjectSP valobj_sp = m_backend.GetSP();
403 if (!valobj_sp)
404 return false;
Enrico Granata9f02e092013-02-18 23:16:23 +0000405 if (!valobj_sp)
406 return false;
407 m_exe_ctx_ref = valobj_sp->GetExecutionContextRef();
408 Error error;
409 if (valobj_sp->IsPointerType())
410 {
411 valobj_sp = valobj_sp->Dereference(error);
412 if (error.Fail() || !valobj_sp)
413 return false;
414 }
415 error.Clear();
416 lldb::ProcessSP process_sp(valobj_sp->GetProcessSP());
417 if (!process_sp)
418 return false;
419 m_ptr_size = process_sp->GetAddressByteSize();
420 uint64_t data_location = valobj_sp->GetAddressOf() + m_ptr_size;
421 if (m_ptr_size == 4)
422 {
423 m_data_32 = new DataDescriptor_32();
424 process_sp->ReadMemory (data_location, m_data_32, sizeof(DataDescriptor_32), error);
425 }
426 else
427 {
428 m_data_64 = new DataDescriptor_64();
429 process_sp->ReadMemory (data_location, m_data_64, sizeof(DataDescriptor_64), error);
430 }
431 if (error.Fail())
432 return false;
433 m_data_ptr = data_location + m_ptr_size;
434 return false;
435}
436
437bool
438lldb_private::formatters::NSSetISyntheticFrontEnd::MightHaveChildren ()
439{
440 return true;
441}
442
443lldb::ValueObjectSP
444lldb_private::formatters::NSSetISyntheticFrontEnd::GetChildAtIndex (size_t idx)
445{
446 uint32_t num_children = CalculateNumChildren();
447
448 if (idx >= num_children)
449 return lldb::ValueObjectSP();
450
Enrico Granata5383e812013-11-21 01:08:05 +0000451 ProcessSP process_sp = m_exe_ctx_ref.GetProcessSP();
452 if (!process_sp)
453 return lldb::ValueObjectSP();
454
Enrico Granata9f02e092013-02-18 23:16:23 +0000455 if (m_children.empty())
456 {
457 // do the scan phase
458 lldb::addr_t obj_at_idx = 0;
459
460 uint32_t tries = 0;
461 uint32_t test_idx = 0;
462
463 while(tries < num_children)
464 {
465 obj_at_idx = m_data_ptr + (test_idx * m_ptr_size);
Enrico Granata9f02e092013-02-18 23:16:23 +0000466 if (!process_sp)
467 return lldb::ValueObjectSP();
468 Error error;
469 obj_at_idx = process_sp->ReadPointerFromMemory(obj_at_idx, error);
470 if (error.Fail())
471 return lldb::ValueObjectSP();
472
473 test_idx++;
474
475 if (!obj_at_idx)
476 continue;
477 tries++;
478
479 SetItemDescriptor descriptor = {obj_at_idx,lldb::ValueObjectSP()};
480
481 m_children.push_back(descriptor);
482 }
483 }
484
485 if (idx >= m_children.size()) // should never happen
486 return lldb::ValueObjectSP();
487
488 SetItemDescriptor &set_item = m_children[idx];
489 if (!set_item.valobj_sp)
490 {
Enrico Granata5383e812013-11-21 01:08:05 +0000491 auto ptr_size = process_sp->GetAddressByteSize();
492 DataBufferHeap buffer(ptr_size,0);
493 switch (ptr_size)
494 {
495 case 0: // architecture has no clue?? - fail
496 return lldb::ValueObjectSP();
497 case 4:
498 *((uint32_t*)buffer.GetBytes()) = (uint32_t)set_item.item_ptr;
499 break;
500 case 8:
501 *((uint64_t*)buffer.GetBytes()) = (uint64_t)set_item.item_ptr;
502 break;
503 default:
504 assert(false && "pointer size is not 4 nor 8 - get out of here ASAP");
505 }
Enrico Granata9f02e092013-02-18 23:16:23 +0000506 StreamString idx_name;
Deepak Panickal99fbc072014-03-03 15:39:47 +0000507 idx_name.Printf("[%" PRIu64 "]", (uint64_t)idx);
Enrico Granata5383e812013-11-21 01:08:05 +0000508
509 DataExtractor data(buffer.GetBytes(),
510 buffer.GetByteSize(),
511 process_sp->GetByteOrder(),
512 process_sp->GetAddressByteSize());
513
514 set_item.valobj_sp =
Enrico Granata675f49b2015-10-07 18:36:53 +0000515 CreateValueObjectFromData(idx_name.GetData(),
516 data,
517 m_exe_ctx_ref,
518 m_backend.GetCompilerType().GetBasicTypeFromAST(lldb::eBasicTypeObjCID));
Enrico Granata9f02e092013-02-18 23:16:23 +0000519 }
520 return set_item.valobj_sp;
521}
522
523lldb_private::formatters::NSSetMSyntheticFrontEnd::NSSetMSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp) :
524SyntheticChildrenFrontEnd(*valobj_sp.get()),
525m_exe_ctx_ref(),
526m_ptr_size(8),
527m_data_32(NULL),
528m_data_64(NULL)
529{
530 if (valobj_sp)
531 Update ();
532}
533
534lldb_private::formatters::NSSetMSyntheticFrontEnd::~NSSetMSyntheticFrontEnd ()
535{
536 delete m_data_32;
537 m_data_32 = NULL;
538 delete m_data_64;
539 m_data_64 = NULL;
540}
541
542size_t
543lldb_private::formatters::NSSetMSyntheticFrontEnd::GetIndexOfChildWithName (const ConstString &name)
544{
545 const char* item_name = name.GetCString();
546 uint32_t idx = ExtractIndexFromString(item_name);
547 if (idx < UINT32_MAX && idx >= CalculateNumChildren())
548 return UINT32_MAX;
549 return idx;
550}
551
552size_t
553lldb_private::formatters::NSSetMSyntheticFrontEnd::CalculateNumChildren ()
554{
555 if (!m_data_32 && !m_data_64)
556 return 0;
557 return (m_data_32 ? m_data_32->_used : m_data_64->_used);
558}
559
560bool
561lldb_private::formatters::NSSetMSyntheticFrontEnd::Update()
562{
563 m_children.clear();
564 ValueObjectSP valobj_sp = m_backend.GetSP();
565 m_ptr_size = 0;
566 delete m_data_32;
567 m_data_32 = NULL;
568 delete m_data_64;
569 m_data_64 = NULL;
570 if (!valobj_sp)
571 return false;
Enrico Granata9f02e092013-02-18 23:16:23 +0000572 if (!valobj_sp)
573 return false;
574 m_exe_ctx_ref = valobj_sp->GetExecutionContextRef();
575 Error error;
576 if (valobj_sp->IsPointerType())
577 {
578 valobj_sp = valobj_sp->Dereference(error);
579 if (error.Fail() || !valobj_sp)
580 return false;
581 }
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 uint64_t data_location = valobj_sp->GetAddressOf() + m_ptr_size;
588 if (m_ptr_size == 4)
589 {
590 m_data_32 = new DataDescriptor_32();
591 process_sp->ReadMemory (data_location, m_data_32, sizeof(DataDescriptor_32), error);
592 }
593 else
594 {
595 m_data_64 = new DataDescriptor_64();
596 process_sp->ReadMemory (data_location, m_data_64, sizeof(DataDescriptor_64), error);
597 }
598 if (error.Fail())
599 return false;
600 return false;
601}
602
603bool
604lldb_private::formatters::NSSetMSyntheticFrontEnd::MightHaveChildren ()
605{
606 return true;
607}
608
609lldb::ValueObjectSP
610lldb_private::formatters::NSSetMSyntheticFrontEnd::GetChildAtIndex (size_t idx)
611{
612 lldb::addr_t m_objs_addr = (m_data_32 ? m_data_32->_objs_addr : m_data_64->_objs_addr);
Enrico Granata675f49b2015-10-07 18:36:53 +0000613
Enrico Granata9f02e092013-02-18 23:16:23 +0000614 uint32_t num_children = CalculateNumChildren();
615
616 if (idx >= num_children)
617 return lldb::ValueObjectSP();
618
Enrico Granata5383e812013-11-21 01:08:05 +0000619 ProcessSP process_sp = m_exe_ctx_ref.GetProcessSP();
620 if (!process_sp)
621 return lldb::ValueObjectSP();
622
Enrico Granata9f02e092013-02-18 23:16:23 +0000623 if (m_children.empty())
624 {
625 // do the scan phase
626 lldb::addr_t obj_at_idx = 0;
627
628 uint32_t tries = 0;
629 uint32_t test_idx = 0;
630
631 while(tries < num_children)
632 {
633 obj_at_idx = m_objs_addr + (test_idx * m_ptr_size);
Enrico Granata9f02e092013-02-18 23:16:23 +0000634 if (!process_sp)
635 return lldb::ValueObjectSP();
636 Error error;
637 obj_at_idx = process_sp->ReadPointerFromMemory(obj_at_idx, error);
638 if (error.Fail())
639 return lldb::ValueObjectSP();
640
641 test_idx++;
642
643 if (!obj_at_idx)
644 continue;
645 tries++;
646
647 SetItemDescriptor descriptor = {obj_at_idx,lldb::ValueObjectSP()};
648
649 m_children.push_back(descriptor);
650 }
651 }
652
653 if (idx >= m_children.size()) // should never happen
654 return lldb::ValueObjectSP();
655
656 SetItemDescriptor &set_item = m_children[idx];
657 if (!set_item.valobj_sp)
658 {
Enrico Granata5383e812013-11-21 01:08:05 +0000659 auto ptr_size = process_sp->GetAddressByteSize();
660 DataBufferHeap buffer(ptr_size,0);
661 switch (ptr_size)
662 {
663 case 0: // architecture has no clue?? - fail
664 return lldb::ValueObjectSP();
665 case 4:
666 *((uint32_t*)buffer.GetBytes()) = (uint32_t)set_item.item_ptr;
667 break;
668 case 8:
669 *((uint64_t*)buffer.GetBytes()) = (uint64_t)set_item.item_ptr;
670 break;
671 default:
672 assert(false && "pointer size is not 4 nor 8 - get out of here ASAP");
673 }
Enrico Granata9f02e092013-02-18 23:16:23 +0000674 StreamString idx_name;
Deepak Panickal99fbc072014-03-03 15:39:47 +0000675 idx_name.Printf("[%" PRIu64 "]", (uint64_t)idx);
Enrico Granata5383e812013-11-21 01:08:05 +0000676
677 DataExtractor data(buffer.GetBytes(),
678 buffer.GetByteSize(),
679 process_sp->GetByteOrder(),
680 process_sp->GetAddressByteSize());
681
682 set_item.valobj_sp =
Enrico Granata675f49b2015-10-07 18:36:53 +0000683 CreateValueObjectFromData(idx_name.GetData(),
684 data,
685 m_exe_ctx_ref,
686 m_backend.GetCompilerType().GetBasicTypeFromAST(lldb::eBasicTypeObjCID));
Enrico Granata9f02e092013-02-18 23:16:23 +0000687 }
688 return set_item.valobj_sp;
689}
690
Enrico Granatacd67f972013-04-27 00:27:20 +0000691lldb_private::formatters::NSOrderedSetSyntheticFrontEnd::NSOrderedSetSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp) :
692SyntheticChildrenFrontEnd(*valobj_sp.get()),
693m_count(UINT32_MAX),
694m_children()
695{}
696
697size_t
698lldb_private::formatters::NSOrderedSetSyntheticFrontEnd::CalculateNumChildren ()
699{
700 if (m_count != UINT32_MAX)
701 return m_count;
702 uint64_t count_temp;
703 if (ExtractValueFromObjCExpression(m_backend,"unsigned int","count",count_temp))
704 return (m_count = count_temp);
705 return (m_count = 0);
706}
707
708lldb::ValueObjectSP
709lldb_private::formatters::NSOrderedSetSyntheticFrontEnd::GetChildAtIndex (size_t idx)
710{
711 auto iter = m_children.find(idx);
712 if (iter == m_children.end())
713 {
714 lldb::ValueObjectSP retval_sp;
715 if (idx <= m_count)
716 {
717 retval_sp = CallSelectorOnObject(m_backend, "id", "objectAtIndex", idx);
718 if (retval_sp)
719 {
720 StreamString idx_name;
Deepak Panickal99fbc072014-03-03 15:39:47 +0000721 idx_name.Printf("[%" PRIu64 "]", (uint64_t)idx);
Enrico Granatacd67f972013-04-27 00:27:20 +0000722 retval_sp->SetName(ConstString(idx_name.GetData()));
723 }
724 m_children[idx] = retval_sp;
725 }
726 return retval_sp;
727 }
728 else
729 return iter->second;
730}
731
732bool
733lldb_private::formatters::NSOrderedSetSyntheticFrontEnd::Update()
734{
735 return false;
736}
737
738bool
739lldb_private::formatters::NSOrderedSetSyntheticFrontEnd::MightHaveChildren ()
740{
741 return true;
742}
743
744size_t
745lldb_private::formatters::NSOrderedSetSyntheticFrontEnd::GetIndexOfChildWithName (const ConstString &name)
746{
747 const char* item_name = name.GetCString();
748 uint32_t idx = ExtractIndexFromString(item_name);
749 if (idx < UINT32_MAX && idx >= CalculateNumChildren())
750 return UINT32_MAX;
751 return idx;
752}
753
Enrico Granataf615b802013-02-15 23:38:37 +0000754template bool
Enrico Granataf35bc632014-11-06 21:55:30 +0000755lldb_private::formatters::NSSetSummaryProvider<true> (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options);
Enrico Granataf615b802013-02-15 23:38:37 +0000756
757template bool
Enrico Granataf35bc632014-11-06 21:55:30 +0000758lldb_private::formatters::NSSetSummaryProvider<false> (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options);