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