blob: e17a78ddd595b7ff7c67492f25c87620168b5d69 [file] [log] [blame]
Enrico Granataf615b802013-02-15 23:38:37 +00001//===-- NSSet.cpp ------------------------------------------------*- C++ -*-===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
10#include "lldb/lldb-python.h"
11
12#include "lldb/DataFormatters/CXXFormatterFunctions.h"
13
14#include "llvm/Support/ConvertUTF.h"
15
16#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"
21#include "lldb/Host/Endian.h"
22#include "lldb/Symbol/ClangASTContext.h"
23#include "lldb/Target/ObjCLanguageRuntime.h"
24#include "lldb/Target/Target.h"
25
26using namespace lldb;
27using namespace lldb_private;
28using namespace lldb_private::formatters;
29
30template<bool cf_style>
31bool
32lldb_private::formatters::NSSetSummaryProvider (ValueObject& valobj, Stream& stream)
33{
34 ProcessSP process_sp = valobj.GetProcessSP();
35 if (!process_sp)
36 return false;
37
38 ObjCLanguageRuntime* runtime = (ObjCLanguageRuntime*)process_sp->GetLanguageRuntime(lldb::eLanguageTypeObjC);
39
40 if (!runtime)
41 return false;
42
43 ObjCLanguageRuntime::ClassDescriptorSP descriptor(runtime->GetClassDescriptor(valobj));
44
45 if (!descriptor.get() || !descriptor->IsValid())
46 return false;
47
48 uint32_t ptr_size = process_sp->GetAddressByteSize();
49 bool is_64bit = (ptr_size == 8);
50
51 lldb::addr_t valobj_addr = valobj.GetValueAsUnsigned(0);
52
53 if (!valobj_addr)
54 return false;
55
56 uint64_t value = 0;
57
58 const char* class_name = descriptor->GetClassName().GetCString();
59
60 if (!class_name || !*class_name)
61 return false;
62
63 if (!strcmp(class_name,"__NSSetI"))
64 {
65 Error error;
66 value = process_sp->ReadUnsignedIntegerFromMemory(valobj_addr + ptr_size, ptr_size, 0, error);
67 if (error.Fail())
68 return false;
69 value &= (is_64bit ? ~0xFC00000000000000UL : ~0xFC000000U);
70 }
71 else if (!strcmp(class_name,"__NSSetM"))
72 {
73 Error error;
74 value = process_sp->ReadUnsignedIntegerFromMemory(valobj_addr + ptr_size, ptr_size, 0, error);
75 if (error.Fail())
76 return false;
77 value &= (is_64bit ? ~0xFC00000000000000UL : ~0xFC000000U);
78 }
79 else if (!strcmp(class_name,"__NSCFSet"))
80 {
81 Error error;
82 value = process_sp->ReadUnsignedIntegerFromMemory(valobj_addr + (is_64bit ? 20 : 12), ptr_size, 0, error);
83 if (error.Fail())
84 return false;
85 if (is_64bit)
86 value &= ~0x1fff000000000000UL;
87 }
88 else if (!strcmp(class_name,"NSCountedSet"))
89 {
90 Error error;
91 value = process_sp->ReadUnsignedIntegerFromMemory(valobj_addr + ptr_size, ptr_size, 0, error);
92 if (error.Fail())
93 return false;
94 value = process_sp->ReadUnsignedIntegerFromMemory(value + (is_64bit ? 20 : 12), ptr_size, 0, error);
95 if (error.Fail())
96 return false;
97 if (is_64bit)
98 value &= ~0x1fff000000000000UL;
99 }
100 else
101 {
102 if (!ExtractValueFromObjCExpression(valobj, "int", "count", value))
103 return false;
104 }
105
106 stream.Printf("%s%" PRIu64 " %s%s",
107 (cf_style ? "@\"" : ""),
108 value,
109 (cf_style ? (value == 1 ? "value" : "values") : (value == 1 ? "object" : "objects")),
110 (cf_style ? "\"" : ""));
111 return true;
112}
113
Enrico Granata9f02e092013-02-18 23:16:23 +0000114SyntheticChildrenFrontEnd* lldb_private::formatters::NSSetSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP valobj_sp)
115{
116 lldb::ProcessSP process_sp (valobj_sp->GetProcessSP());
117 if (!process_sp)
118 return NULL;
119 ObjCLanguageRuntime *runtime = (ObjCLanguageRuntime*)process_sp->GetLanguageRuntime(lldb::eLanguageTypeObjC);
120 if (!runtime)
121 return NULL;
122
123 if (!valobj_sp->IsPointerType())
124 {
125 Error error;
126 valobj_sp = valobj_sp->AddressOf(error);
127 if (error.Fail() || !valobj_sp)
128 return NULL;
129 }
130
131 ObjCLanguageRuntime::ClassDescriptorSP descriptor(runtime->GetClassDescriptor(*valobj_sp.get()));
132
133 if (!descriptor.get() || !descriptor->IsValid())
134 return NULL;
135
136 const char* class_name = descriptor->GetClassName().GetCString();
137
138 if (!class_name || !*class_name)
139 return NULL;
140
141 if (!strcmp(class_name,"__NSSetI"))
142 {
143 return (new NSSetISyntheticFrontEnd(valobj_sp));
144 }
145 else if (!strcmp(class_name,"__NSSetM"))
146 {
147 return (new NSSetMSyntheticFrontEnd(valobj_sp));
148 }
149 else
150 {
151 return /*(new NSSetCodeRunningSyntheticFrontEnd(valobj_sp))*/ NULL;
152 }
153}
154
155lldb_private::formatters::NSSetISyntheticFrontEnd::NSSetISyntheticFrontEnd (lldb::ValueObjectSP valobj_sp) :
156SyntheticChildrenFrontEnd(*valobj_sp.get()),
157m_exe_ctx_ref(),
158m_ptr_size(8),
159m_data_32(NULL),
160m_data_64(NULL)
161{
162 if (valobj_sp)
163 Update();
164}
165
166lldb_private::formatters::NSSetISyntheticFrontEnd::~NSSetISyntheticFrontEnd ()
167{
168 delete m_data_32;
169 m_data_32 = NULL;
170 delete m_data_64;
171 m_data_64 = NULL;
172}
173
174size_t
175lldb_private::formatters::NSSetISyntheticFrontEnd::GetIndexOfChildWithName (const ConstString &name)
176{
177 const char* item_name = name.GetCString();
178 uint32_t idx = ExtractIndexFromString(item_name);
179 if (idx < UINT32_MAX && idx >= CalculateNumChildren())
180 return UINT32_MAX;
181 return idx;
182}
183
184size_t
185lldb_private::formatters::NSSetISyntheticFrontEnd::CalculateNumChildren ()
186{
187 if (!m_data_32 && !m_data_64)
188 return 0;
189 return (m_data_32 ? m_data_32->_used : m_data_64->_used);
190}
191
192bool
193lldb_private::formatters::NSSetISyntheticFrontEnd::Update()
194{
195 m_children.clear();
196 delete m_data_32;
197 m_data_32 = NULL;
198 delete m_data_64;
199 m_data_64 = NULL;
200 m_ptr_size = 0;
201 ValueObjectSP valobj_sp = m_backend.GetSP();
202 if (!valobj_sp)
203 return false;
204 if (valobj_sp->IsDynamic())
205 valobj_sp = valobj_sp->GetStaticValue();
206 if (!valobj_sp)
207 return false;
208 m_exe_ctx_ref = valobj_sp->GetExecutionContextRef();
209 Error error;
210 if (valobj_sp->IsPointerType())
211 {
212 valobj_sp = valobj_sp->Dereference(error);
213 if (error.Fail() || !valobj_sp)
214 return false;
215 }
216 error.Clear();
217 lldb::ProcessSP process_sp(valobj_sp->GetProcessSP());
218 if (!process_sp)
219 return false;
220 m_ptr_size = process_sp->GetAddressByteSize();
221 uint64_t data_location = valobj_sp->GetAddressOf() + m_ptr_size;
222 if (m_ptr_size == 4)
223 {
224 m_data_32 = new DataDescriptor_32();
225 process_sp->ReadMemory (data_location, m_data_32, sizeof(DataDescriptor_32), error);
226 }
227 else
228 {
229 m_data_64 = new DataDescriptor_64();
230 process_sp->ReadMemory (data_location, m_data_64, sizeof(DataDescriptor_64), error);
231 }
232 if (error.Fail())
233 return false;
234 m_data_ptr = data_location + m_ptr_size;
235 return false;
236}
237
238bool
239lldb_private::formatters::NSSetISyntheticFrontEnd::MightHaveChildren ()
240{
241 return true;
242}
243
244lldb::ValueObjectSP
245lldb_private::formatters::NSSetISyntheticFrontEnd::GetChildAtIndex (size_t idx)
246{
247 uint32_t num_children = CalculateNumChildren();
248
249 if (idx >= num_children)
250 return lldb::ValueObjectSP();
251
252 if (m_children.empty())
253 {
254 // do the scan phase
255 lldb::addr_t obj_at_idx = 0;
256
257 uint32_t tries = 0;
258 uint32_t test_idx = 0;
259
260 while(tries < num_children)
261 {
262 obj_at_idx = m_data_ptr + (test_idx * m_ptr_size);
263 ProcessSP process_sp = m_exe_ctx_ref.GetProcessSP();
264 if (!process_sp)
265 return lldb::ValueObjectSP();
266 Error error;
267 obj_at_idx = process_sp->ReadPointerFromMemory(obj_at_idx, error);
268 if (error.Fail())
269 return lldb::ValueObjectSP();
270
271 test_idx++;
272
273 if (!obj_at_idx)
274 continue;
275 tries++;
276
277 SetItemDescriptor descriptor = {obj_at_idx,lldb::ValueObjectSP()};
278
279 m_children.push_back(descriptor);
280 }
281 }
282
283 if (idx >= m_children.size()) // should never happen
284 return lldb::ValueObjectSP();
285
286 SetItemDescriptor &set_item = m_children[idx];
287 if (!set_item.valobj_sp)
288 {
289 // make the new ValueObject
290 StreamString expr;
291 expr.Printf("(id)%" PRIu64,set_item.item_ptr);
292 StreamString idx_name;
293 idx_name.Printf("[%zu]",idx);
294 set_item.valobj_sp = ValueObject::CreateValueObjectFromExpression(idx_name.GetData(), expr.GetData(), m_exe_ctx_ref);
295 }
296 return set_item.valobj_sp;
297}
298
299lldb_private::formatters::NSSetMSyntheticFrontEnd::NSSetMSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp) :
300SyntheticChildrenFrontEnd(*valobj_sp.get()),
301m_exe_ctx_ref(),
302m_ptr_size(8),
303m_data_32(NULL),
304m_data_64(NULL)
305{
306 if (valobj_sp)
307 Update ();
308}
309
310lldb_private::formatters::NSSetMSyntheticFrontEnd::~NSSetMSyntheticFrontEnd ()
311{
312 delete m_data_32;
313 m_data_32 = NULL;
314 delete m_data_64;
315 m_data_64 = NULL;
316}
317
318size_t
319lldb_private::formatters::NSSetMSyntheticFrontEnd::GetIndexOfChildWithName (const ConstString &name)
320{
321 const char* item_name = name.GetCString();
322 uint32_t idx = ExtractIndexFromString(item_name);
323 if (idx < UINT32_MAX && idx >= CalculateNumChildren())
324 return UINT32_MAX;
325 return idx;
326}
327
328size_t
329lldb_private::formatters::NSSetMSyntheticFrontEnd::CalculateNumChildren ()
330{
331 if (!m_data_32 && !m_data_64)
332 return 0;
333 return (m_data_32 ? m_data_32->_used : m_data_64->_used);
334}
335
336bool
337lldb_private::formatters::NSSetMSyntheticFrontEnd::Update()
338{
339 m_children.clear();
340 ValueObjectSP valobj_sp = m_backend.GetSP();
341 m_ptr_size = 0;
342 delete m_data_32;
343 m_data_32 = NULL;
344 delete m_data_64;
345 m_data_64 = NULL;
346 if (!valobj_sp)
347 return false;
348 if (valobj_sp->IsDynamic())
349 valobj_sp = valobj_sp->GetStaticValue();
350 if (!valobj_sp)
351 return false;
352 m_exe_ctx_ref = valobj_sp->GetExecutionContextRef();
353 Error error;
354 if (valobj_sp->IsPointerType())
355 {
356 valobj_sp = valobj_sp->Dereference(error);
357 if (error.Fail() || !valobj_sp)
358 return false;
359 }
360 error.Clear();
361 lldb::ProcessSP process_sp(valobj_sp->GetProcessSP());
362 if (!process_sp)
363 return false;
364 m_ptr_size = process_sp->GetAddressByteSize();
365 uint64_t data_location = valobj_sp->GetAddressOf() + m_ptr_size;
366 if (m_ptr_size == 4)
367 {
368 m_data_32 = new DataDescriptor_32();
369 process_sp->ReadMemory (data_location, m_data_32, sizeof(DataDescriptor_32), error);
370 }
371 else
372 {
373 m_data_64 = new DataDescriptor_64();
374 process_sp->ReadMemory (data_location, m_data_64, sizeof(DataDescriptor_64), error);
375 }
376 if (error.Fail())
377 return false;
378 return false;
379}
380
381bool
382lldb_private::formatters::NSSetMSyntheticFrontEnd::MightHaveChildren ()
383{
384 return true;
385}
386
387lldb::ValueObjectSP
388lldb_private::formatters::NSSetMSyntheticFrontEnd::GetChildAtIndex (size_t idx)
389{
390 lldb::addr_t m_objs_addr = (m_data_32 ? m_data_32->_objs_addr : m_data_64->_objs_addr);
391
392 uint32_t num_children = CalculateNumChildren();
393
394 if (idx >= num_children)
395 return lldb::ValueObjectSP();
396
397 if (m_children.empty())
398 {
399 // do the scan phase
400 lldb::addr_t obj_at_idx = 0;
401
402 uint32_t tries = 0;
403 uint32_t test_idx = 0;
404
405 while(tries < num_children)
406 {
407 obj_at_idx = m_objs_addr + (test_idx * m_ptr_size);
408 ProcessSP process_sp = m_exe_ctx_ref.GetProcessSP();
409 if (!process_sp)
410 return lldb::ValueObjectSP();
411 Error error;
412 obj_at_idx = process_sp->ReadPointerFromMemory(obj_at_idx, error);
413 if (error.Fail())
414 return lldb::ValueObjectSP();
415
416 test_idx++;
417
418 if (!obj_at_idx)
419 continue;
420 tries++;
421
422 SetItemDescriptor descriptor = {obj_at_idx,lldb::ValueObjectSP()};
423
424 m_children.push_back(descriptor);
425 }
426 }
427
428 if (idx >= m_children.size()) // should never happen
429 return lldb::ValueObjectSP();
430
431 SetItemDescriptor &set_item = m_children[idx];
432 if (!set_item.valobj_sp)
433 {
434 // make the new ValueObject
435 StreamString expr;
436 expr.Printf("(id)%" PRIu64,set_item.item_ptr);
437 StreamString idx_name;
438 idx_name.Printf("[%zu]",idx);
439 set_item.valobj_sp = ValueObject::CreateValueObjectFromExpression(idx_name.GetData(), expr.GetData(), m_exe_ctx_ref);
440 }
441 return set_item.valobj_sp;
442}
443
Enrico Granataf615b802013-02-15 23:38:37 +0000444template bool
445lldb_private::formatters::NSSetSummaryProvider<true> (ValueObject& valobj, Stream& stream);
446
447template bool
448lldb_private::formatters::NSSetSummaryProvider<false> (ValueObject& valobj, Stream& stream);