blob: d03d76156a0f1098f07a12cb7aaac3dd1a8ff4c4 [file] [log] [blame]
Enrico Granatacaaf0102012-09-04 18:48:21 +00001//===-- CXXFormatterFunctions.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
Daniel Malead891f9b2012-12-05 00:20:57 +000010#include "lldb/lldb-python.h"
11
Enrico Granataf509c5e2013-01-28 23:47:25 +000012#include "lldb/DataFormatters/CXXFormatterFunctions.h"
Enrico Granatacaaf0102012-09-04 18:48:21 +000013
Dmitri Gribenko2a64f9a2013-01-30 15:05:59 +000014#include "llvm/Support/ConvertUTF.h"
Enrico Granatacaaf0102012-09-04 18:48:21 +000015
Enrico Granataf91e78f2012-09-13 18:27:09 +000016#include "lldb/Core/DataBufferHeap.h"
17#include "lldb/Core/Error.h"
Enrico Granatacaaf0102012-09-04 18:48:21 +000018#include "lldb/Core/Stream.h"
19#include "lldb/Core/ValueObject.h"
Enrico Granataf91e78f2012-09-13 18:27:09 +000020#include "lldb/Core/ValueObjectConstResult.h"
21#include "lldb/Host/Endian.h"
Enrico Granatadb054912012-10-29 21:18:03 +000022#include "lldb/Symbol/ClangASTContext.h"
Enrico Granatacaaf0102012-09-04 18:48:21 +000023#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
30bool
Enrico Granataf91e78f2012-09-13 18:27:09 +000031lldb_private::formatters::ExtractValueFromObjCExpression (ValueObject &valobj,
32 const char* target_type,
33 const char* selector,
34 uint64_t &value)
Enrico Granatacaaf0102012-09-04 18:48:21 +000035{
36 if (!target_type || !*target_type)
37 return false;
38 if (!selector || !*selector)
39 return false;
Enrico Granatacaaf0102012-09-04 18:48:21 +000040 StreamString expr;
Daniel Maleab9db9d52012-12-07 22:21:08 +000041 expr.Printf("(%s)[(id)0x%" PRIx64 " %s]",target_type,valobj.GetPointerValue(),selector);
Enrico Granatacaaf0102012-09-04 18:48:21 +000042 ExecutionContext exe_ctx (valobj.GetExecutionContextRef());
43 lldb::ValueObjectSP result_sp;
44 Target* target = exe_ctx.GetTargetPtr();
45 StackFrame* stack_frame = exe_ctx.GetFramePtr();
46 if (!target || !stack_frame)
47 return false;
Enrico Granatad27026e2012-09-05 20:41:26 +000048
Jim Ingham47beabb2012-10-16 21:41:58 +000049 EvaluateExpressionOptions options;
Enrico Granatad27026e2012-09-05 20:41:26 +000050 options.SetCoerceToId(false)
51 .SetUnwindOnError(true)
Sean Callanan99611fe2012-12-04 20:56:04 +000052 .SetKeepInMemory(true);
Enrico Granatad27026e2012-09-05 20:41:26 +000053
Enrico Granatacaaf0102012-09-04 18:48:21 +000054 target->EvaluateExpression(expr.GetData(),
55 stack_frame,
Enrico Granatad27026e2012-09-05 20:41:26 +000056 result_sp,
57 options);
Enrico Granatacaaf0102012-09-04 18:48:21 +000058 if (!result_sp)
59 return false;
60 value = result_sp->GetValueAsUnsigned(0);
61 return true;
62}
63
Enrico Granataf91e78f2012-09-13 18:27:09 +000064lldb::ValueObjectSP
65lldb_private::formatters::CallSelectorOnObject (ValueObject &valobj,
66 const char* return_type,
67 const char* selector,
68 uint64_t index)
69{
70 lldb::ValueObjectSP valobj_sp;
71 if (!return_type || !*return_type)
72 return valobj_sp;
73 if (!selector || !*selector)
74 return valobj_sp;
75 StreamString expr_path_stream;
76 valobj.GetExpressionPath(expr_path_stream, false);
77 StreamString expr;
Daniel Malea5f35a4b2012-11-29 21:49:15 +000078 expr.Printf("(%s)[%s %s:%" PRId64 "]",return_type,expr_path_stream.GetData(),selector,index);
Enrico Granataf91e78f2012-09-13 18:27:09 +000079 ExecutionContext exe_ctx (valobj.GetExecutionContextRef());
80 lldb::ValueObjectSP result_sp;
81 Target* target = exe_ctx.GetTargetPtr();
82 StackFrame* stack_frame = exe_ctx.GetFramePtr();
83 if (!target || !stack_frame)
84 return valobj_sp;
85
Jim Ingham47beabb2012-10-16 21:41:58 +000086 EvaluateExpressionOptions options;
Enrico Granataf91e78f2012-09-13 18:27:09 +000087 options.SetCoerceToId(false)
88 .SetUnwindOnError(true)
89 .SetKeepInMemory(true)
90 .SetUseDynamic(lldb::eDynamicCanRunTarget);
91
92 target->EvaluateExpression(expr.GetData(),
93 stack_frame,
94 valobj_sp,
95 options);
96 return valobj_sp;
97}
98
99lldb::ValueObjectSP
100lldb_private::formatters::CallSelectorOnObject (ValueObject &valobj,
101 const char* return_type,
102 const char* selector,
103 const char* key)
104{
105 lldb::ValueObjectSP valobj_sp;
106 if (!return_type || !*return_type)
107 return valobj_sp;
108 if (!selector || !*selector)
109 return valobj_sp;
110 if (!key || !*key)
111 return valobj_sp;
112 StreamString expr_path_stream;
113 valobj.GetExpressionPath(expr_path_stream, false);
114 StreamString expr;
115 expr.Printf("(%s)[%s %s:%s]",return_type,expr_path_stream.GetData(),selector,key);
116 ExecutionContext exe_ctx (valobj.GetExecutionContextRef());
117 lldb::ValueObjectSP result_sp;
118 Target* target = exe_ctx.GetTargetPtr();
119 StackFrame* stack_frame = exe_ctx.GetFramePtr();
120 if (!target || !stack_frame)
121 return valobj_sp;
122
Jim Ingham47beabb2012-10-16 21:41:58 +0000123 EvaluateExpressionOptions options;
Enrico Granataf91e78f2012-09-13 18:27:09 +0000124 options.SetCoerceToId(false)
125 .SetUnwindOnError(true)
126 .SetKeepInMemory(true)
127 .SetUseDynamic(lldb::eDynamicCanRunTarget);
128
129 target->EvaluateExpression(expr.GetData(),
130 stack_frame,
131 valobj_sp,
132 options);
133 return valobj_sp;
134}
135
Enrico Granatacd8cd612013-01-14 23:53:26 +0000136// use this call if you already have an LLDB-side buffer for the data
137template<typename SourceDataType>
Enrico Granataf5545f92013-01-10 22:08:35 +0000138static bool
Enrico Granatacd8cd612013-01-14 23:53:26 +0000139DumpUTFBufferToStream (ConversionResult (*ConvertFunction) (const SourceDataType**,
140 const SourceDataType*,
141 UTF8**,
142 UTF8*,
143 ConversionFlags),
144 DataExtractor& data,
145 Stream& stream,
146 char prefix_token = '@',
147 char quote = '"',
148 int sourceSize = 0)
Enrico Granataf5545f92013-01-10 22:08:35 +0000149{
Enrico Granatacd8cd612013-01-14 23:53:26 +0000150 if (prefix_token != 0)
151 stream.Printf("%c",prefix_token);
152 if (quote != 0)
153 stream.Printf("%c",quote);
154 if (data.GetByteSize() && data.GetDataStart() && data.GetDataEnd())
Enrico Granataf5545f92013-01-10 22:08:35 +0000155 {
Enrico Granatacd8cd612013-01-14 23:53:26 +0000156 const int bufferSPSize = data.GetByteSize();
157 if (sourceSize == 0)
158 {
159 const int origin_encoding = 8*sizeof(SourceDataType);
Greg Clayton0cd33402013-02-08 21:59:34 +0000160 sourceSize = bufferSPSize/(origin_encoding / 4);
Enrico Granatacd8cd612013-01-14 23:53:26 +0000161 }
162
163 SourceDataType *data_ptr = (SourceDataType*)data.GetDataStart();
Enrico Granataf5545f92013-01-10 22:08:35 +0000164 SourceDataType *data_end_ptr = data_ptr + sourceSize;
165
166 while (data_ptr < data_end_ptr)
167 {
168 if (!*data_ptr)
169 {
170 data_end_ptr = data_ptr;
171 break;
172 }
173 data_ptr++;
174 }
175
Enrico Granatacd8cd612013-01-14 23:53:26 +0000176 data_ptr = (SourceDataType*)data.GetDataStart();
Enrico Granataf5545f92013-01-10 22:08:35 +0000177
Enrico Granata06d58b02013-01-11 02:44:00 +0000178 lldb::DataBufferSP utf8_data_buffer_sp;
179 UTF8* utf8_data_ptr = nullptr;
180 UTF8* utf8_data_end_ptr = nullptr;
Enrico Granatacd8cd612013-01-14 23:53:26 +0000181
Enrico Granataf5545f92013-01-10 22:08:35 +0000182 if (ConvertFunction)
Enrico Granata06d58b02013-01-11 02:44:00 +0000183 {
184 utf8_data_buffer_sp.reset(new DataBufferHeap(bufferSPSize,0));
185 utf8_data_ptr = (UTF8*)utf8_data_buffer_sp->GetBytes();
186 utf8_data_end_ptr = utf8_data_ptr + bufferSPSize;
Enrico Granataf5545f92013-01-10 22:08:35 +0000187 ConvertFunction ( (const SourceDataType**)&data_ptr, data_end_ptr, &utf8_data_ptr, utf8_data_end_ptr, lenientConversion );
Enrico Granata06d58b02013-01-11 02:44:00 +0000188 utf8_data_ptr = (UTF8*)utf8_data_buffer_sp->GetBytes(); // needed because the ConvertFunction will change the value of the data_ptr
189 }
Enrico Granataf5545f92013-01-10 22:08:35 +0000190 else
191 {
192 // just copy the pointers - the cast is necessary to make the compiler happy
193 // but this should only happen if we are reading UTF8 data
194 utf8_data_ptr = (UTF8*)data_ptr;
195 utf8_data_end_ptr = (UTF8*)data_end_ptr;
196 }
197
Enrico Granatab6985792013-01-12 01:00:22 +0000198 // since we tend to accept partial data (and even partially malformed data)
199 // we might end up with no NULL terminator before the end_ptr
200 // hence we need to take a slower route and ensure we stay within boundaries
Enrico Granataf5545f92013-01-10 22:08:35 +0000201 for (;utf8_data_ptr != utf8_data_end_ptr; utf8_data_ptr++)
202 {
203 if (!*utf8_data_ptr)
204 break;
205 stream.Printf("%c",*utf8_data_ptr);
206 }
Enrico Granatacd8cd612013-01-14 23:53:26 +0000207 }
208 if (quote != 0)
209 stream.Printf("%c",quote);
210 return true;
211}
212
213template<typename SourceDataType>
214static bool
215ReadUTFBufferAndDumpToStream (ConversionResult (*ConvertFunction) (const SourceDataType**,
216 const SourceDataType*,
217 UTF8**,
218 UTF8*,
219 ConversionFlags),
220 uint64_t location,
221 const ProcessSP& process_sp,
222 Stream& stream,
223 char prefix_token = '@',
224 char quote = '"',
225 int sourceSize = 0)
226{
227 if (location == 0 || location == LLDB_INVALID_ADDRESS)
228 return false;
229 if (!process_sp)
230 return false;
231
232 const int origin_encoding = 8*sizeof(SourceDataType);
233 if (origin_encoding != 8 && origin_encoding != 16 && origin_encoding != 32)
234 return false;
235 // if not UTF8, I need a conversion function to return proper UTF8
236 if (origin_encoding != 8 && !ConvertFunction)
237 return false;
238
239 if (sourceSize == 0)
240 sourceSize = process_sp->GetTarget().GetMaximumSizeOfStringSummary();
241 const int bufferSPSize = sourceSize * (origin_encoding >> 2);
242
243 Error error;
244 lldb::DataBufferSP buffer_sp(new DataBufferHeap(bufferSPSize,0));
245
246 if (!buffer_sp->GetBytes())
247 return false;
248
249 size_t data_read = process_sp->ReadMemoryFromInferior(location, (char*)buffer_sp->GetBytes(), bufferSPSize, error);
250 if (error.Fail() || data_read == 0)
251 {
252 stream.Printf("unable to read data");
Enrico Granataf5545f92013-01-10 22:08:35 +0000253 return true;
254 }
Enrico Granatacd8cd612013-01-14 23:53:26 +0000255
256 DataExtractor data(buffer_sp, process_sp->GetByteOrder(), process_sp->GetAddressByteSize());
257
258 return DumpUTFBufferToStream(ConvertFunction, data, stream, prefix_token, quote, sourceSize);
Enrico Granataf5545f92013-01-10 22:08:35 +0000259}
260
261bool
262lldb_private::formatters::Char16StringSummaryProvider (ValueObject& valobj, Stream& stream)
263{
264 ProcessSP process_sp = valobj.GetProcessSP();
265 if (!process_sp)
266 return false;
267
268 lldb::addr_t valobj_addr = valobj.GetValueAsUnsigned(0);
269
270 if (!valobj_addr)
271 return false;
272
Enrico Granatacd8cd612013-01-14 23:53:26 +0000273 if (!ReadUTFBufferAndDumpToStream<UTF16>(ConvertUTF16toUTF8,valobj_addr,
Enrico Granataf5545f92013-01-10 22:08:35 +0000274 process_sp,
275 stream,
Enrico Granatacd8cd612013-01-14 23:53:26 +0000276 'u'))
Enrico Granataf5545f92013-01-10 22:08:35 +0000277 {
278 stream.Printf("Summary Unavailable");
279 return true;
280 }
281
282 return true;
283}
284
285bool
286lldb_private::formatters::Char32StringSummaryProvider (ValueObject& valobj, Stream& stream)
287{
288 ProcessSP process_sp = valobj.GetProcessSP();
289 if (!process_sp)
290 return false;
291
292 lldb::addr_t valobj_addr = valobj.GetValueAsUnsigned(0);
293
294 if (!valobj_addr)
295 return false;
296
Enrico Granatacd8cd612013-01-14 23:53:26 +0000297 if (!ReadUTFBufferAndDumpToStream<UTF32>(ConvertUTF32toUTF8,valobj_addr,
Enrico Granataf5545f92013-01-10 22:08:35 +0000298 process_sp,
299 stream,
Enrico Granatacd8cd612013-01-14 23:53:26 +0000300 'U'))
Enrico Granataf5545f92013-01-10 22:08:35 +0000301 {
302 stream.Printf("Summary Unavailable");
303 return true;
304 }
305
306 return true;
307}
308
309bool
310lldb_private::formatters::WCharStringSummaryProvider (ValueObject& valobj, Stream& stream)
311{
Enrico Granata06d58b02013-01-11 02:44:00 +0000312 ProcessSP process_sp = valobj.GetProcessSP();
313 if (!process_sp)
314 return false;
315
Enrico Granatab6985792013-01-12 01:00:22 +0000316 lldb::addr_t data_addr = 0;
317
318 if (valobj.IsPointerType())
319 data_addr = valobj.GetValueAsUnsigned(0);
320 else if (valobj.IsArrayType())
321 data_addr = valobj.GetAddressOf();
Enrico Granata06d58b02013-01-11 02:44:00 +0000322
Enrico Granatab6985792013-01-12 01:00:22 +0000323 if (data_addr == 0 || data_addr == LLDB_INVALID_ADDRESS)
Enrico Granata06d58b02013-01-11 02:44:00 +0000324 return false;
325
326 clang::ASTContext* ast = valobj.GetClangAST();
327
328 if (!ast)
329 return false;
330
331 uint32_t wchar_size = ClangASTType::GetClangTypeBitWidth(ast, ClangASTType::GetBasicType(ast, lldb::eBasicTypeWChar).GetOpaqueQualType());
332
333 switch (wchar_size)
334 {
335 case 8:
336 // utf 8
Enrico Granatacd8cd612013-01-14 23:53:26 +0000337 return ReadUTFBufferAndDumpToStream<UTF8>(nullptr, data_addr,
Enrico Granata06d58b02013-01-11 02:44:00 +0000338 process_sp,
339 stream,
Enrico Granatacd8cd612013-01-14 23:53:26 +0000340 'L');
Enrico Granata06d58b02013-01-11 02:44:00 +0000341 case 16:
342 // utf 16
Enrico Granatacd8cd612013-01-14 23:53:26 +0000343 return ReadUTFBufferAndDumpToStream<UTF16>(ConvertUTF16toUTF8, data_addr,
Enrico Granata06d58b02013-01-11 02:44:00 +0000344 process_sp,
345 stream,
Enrico Granatacd8cd612013-01-14 23:53:26 +0000346 'L');
Enrico Granata06d58b02013-01-11 02:44:00 +0000347 case 32:
348 // utf 32
Enrico Granatacd8cd612013-01-14 23:53:26 +0000349 return ReadUTFBufferAndDumpToStream<UTF32>(ConvertUTF32toUTF8, data_addr,
Enrico Granata06d58b02013-01-11 02:44:00 +0000350 process_sp,
351 stream,
Enrico Granatacd8cd612013-01-14 23:53:26 +0000352 'L');
353 default:
354 stream.Printf("size for wchar_t is not valid");
355 return true;
356 }
357 return true;
358}
359
360bool
361lldb_private::formatters::Char16SummaryProvider (ValueObject& valobj, Stream& stream)
362{
363 DataExtractor data;
364 valobj.GetData(data);
365
366 std::string value;
367 valobj.GetValueAsCString(lldb::eFormatUnicode16, value);
368 if (!value.empty())
369 stream.Printf("%s ", value.c_str());
370
371 return DumpUTFBufferToStream<UTF16>(ConvertUTF16toUTF8,data,stream, 'u','\'',1);
372}
373
374bool
375lldb_private::formatters::Char32SummaryProvider (ValueObject& valobj, Stream& stream)
376{
377 DataExtractor data;
378 valobj.GetData(data);
379
380 std::string value;
381 valobj.GetValueAsCString(lldb::eFormatUnicode32, value);
382 if (!value.empty())
383 stream.Printf("%s ", value.c_str());
384
385 return DumpUTFBufferToStream<UTF32>(ConvertUTF32toUTF8,data,stream, 'U','\'',1);
386}
387
388bool
389lldb_private::formatters::WCharSummaryProvider (ValueObject& valobj, Stream& stream)
390{
391 DataExtractor data;
392 valobj.GetData(data);
393
394 clang::ASTContext* ast = valobj.GetClangAST();
395
396 if (!ast)
397 return false;
398
399 std::string value;
400
401 uint32_t wchar_size = ClangASTType::GetClangTypeBitWidth(ast, ClangASTType::GetBasicType(ast, lldb::eBasicTypeWChar).GetOpaqueQualType());
402
403 switch (wchar_size)
404 {
405 case 8:
406 // utf 8
407 valobj.GetValueAsCString(lldb::eFormatChar, value);
408 if (!value.empty())
409 stream.Printf("%s ", value.c_str());
410 return DumpUTFBufferToStream<UTF8>(nullptr,
411 data,
412 stream,
413 'L',
414 '\'',
415 1);
416 case 16:
417 // utf 16
418 valobj.GetValueAsCString(lldb::eFormatUnicode16, value);
419 if (!value.empty())
420 stream.Printf("%s ", value.c_str());
421 return DumpUTFBufferToStream<UTF16>(ConvertUTF16toUTF8,
422 data,
423 stream,
424 'L',
425 '\'',
426 1);
427 case 32:
428 // utf 32
429 valobj.GetValueAsCString(lldb::eFormatUnicode32, value);
430 if (!value.empty())
431 stream.Printf("%s ", value.c_str());
432 return DumpUTFBufferToStream<UTF32>(ConvertUTF32toUTF8,
433 data,
434 stream,
435 'L',
436 '\'',
437 1);
Enrico Granata06d58b02013-01-11 02:44:00 +0000438 default:
439 stream.Printf("size for wchar_t is not valid");
440 return true;
441 }
442 return true;
Enrico Granataf5545f92013-01-10 22:08:35 +0000443}
444
Enrico Granatab6985792013-01-12 01:00:22 +0000445// this function extracts information from a libcxx std::basic_string<>
446// irregardless of template arguments. it reports the size (in item count not bytes)
447// and the location in memory where the string data can be found
448static bool
449ExtractLibcxxStringInfo (ValueObject& valobj,
450 ValueObjectSP &location_sp,
451 uint64_t& size)
452{
453 ValueObjectSP D(valobj.GetChildAtIndexPath({0,0,0,0}));
454 if (!D)
455 return false;
456
457 ValueObjectSP size_mode(D->GetChildAtIndexPath({1,0,0}));
458 if (!size_mode)
459 return false;
460
461 uint64_t size_mode_value(size_mode->GetValueAsUnsigned(0));
462
463 if ((size_mode_value & 1) == 0) // this means the string is in short-mode and the data is stored inline
464 {
465 ValueObjectSP s(D->GetChildAtIndex(1, true));
466 if (!s)
467 return false;
468 size = ((size_mode_value >> 1) % 256);
469 location_sp = s->GetChildAtIndex(1, true);
470 return (location_sp.get() != nullptr);
471 }
472 else
473 {
474 ValueObjectSP l(D->GetChildAtIndex(0, true));
475 if (!l)
476 return false;
477 location_sp = l->GetChildAtIndex(2, true);
478 ValueObjectSP size_vo(l->GetChildAtIndex(1, true));
479 if (!size_vo || !location_sp)
480 return false;
481 size = size_vo->GetValueAsUnsigned(0);
482 return true;
483 }
484}
485
486bool
487lldb_private::formatters::LibcxxWStringSummaryProvider (ValueObject& valobj, Stream& stream)
488{
489 uint64_t size = 0;
490 ValueObjectSP location_sp((ValueObject*)nullptr);
491 if (!ExtractLibcxxStringInfo(valobj, location_sp, size))
492 return false;
493 if (size == 0)
494 {
495 stream.Printf("L\"\"");
496 return true;
497 }
498 if (!location_sp)
499 return false;
500 return WCharStringSummaryProvider(*location_sp.get(), stream);
501}
502
503bool
504lldb_private::formatters::LibcxxStringSummaryProvider (ValueObject& valobj, Stream& stream)
505{
506 uint64_t size = 0;
507 ValueObjectSP location_sp((ValueObject*)nullptr);
508 if (!ExtractLibcxxStringInfo(valobj, location_sp, size))
509 return false;
510 if (size == 0)
511 {
512 stream.Printf("\"\"");
513 return true;
514 }
515 if (!location_sp)
516 return false;
517 Error error;
518 location_sp->ReadPointedString(stream,
519 error,
520 0, // max length is decided by the settings
521 false); // do not honor array (terminates on first 0 byte even for a char[])
522 return error.Success();
523}
524
Enrico Granatacaaf0102012-09-04 18:48:21 +0000525template<bool name_entries>
526bool
Enrico Granataf91e78f2012-09-13 18:27:09 +0000527lldb_private::formatters::NSDictionarySummaryProvider (ValueObject& valobj, Stream& stream)
Enrico Granatacaaf0102012-09-04 18:48:21 +0000528{
529 ProcessSP process_sp = valobj.GetProcessSP();
530 if (!process_sp)
531 return false;
532
533 ObjCLanguageRuntime* runtime = (ObjCLanguageRuntime*)process_sp->GetLanguageRuntime(lldb::eLanguageTypeObjC);
534
535 if (!runtime)
536 return false;
537
538 ObjCLanguageRuntime::ClassDescriptorSP descriptor(runtime->GetClassDescriptor(valobj));
539
540 if (!descriptor.get() || !descriptor->IsValid())
541 return false;
542
543 uint32_t ptr_size = process_sp->GetAddressByteSize();
544 bool is_64bit = (ptr_size == 8);
545
546 lldb::addr_t valobj_addr = valobj.GetValueAsUnsigned(0);
547
548 if (!valobj_addr)
549 return false;
550
551 uint64_t value = 0;
552
553 const char* class_name = descriptor->GetClassName().GetCString();
Enrico Granata7685a562012-09-29 00:47:43 +0000554
555 if (!class_name || !*class_name)
556 return false;
557
Enrico Granatacaaf0102012-09-04 18:48:21 +0000558 if (!strcmp(class_name,"__NSDictionaryI"))
559 {
560 Error error;
561 value = process_sp->ReadUnsignedIntegerFromMemory(valobj_addr + ptr_size, ptr_size, 0, error);
562 if (error.Fail())
563 return false;
564 value &= (is_64bit ? ~0xFC00000000000000UL : ~0xFC000000U);
565 }
566 else if (!strcmp(class_name,"__NSDictionaryM"))
567 {
568 Error error;
569 value = process_sp->ReadUnsignedIntegerFromMemory(valobj_addr + ptr_size, ptr_size, 0, error);
570 if (error.Fail())
571 return false;
572 value &= (is_64bit ? ~0xFC00000000000000UL : ~0xFC000000U);
573 }
574 else if (!strcmp(class_name,"__NSCFDictionary"))
575 {
576 Error error;
577 value = process_sp->ReadUnsignedIntegerFromMemory(valobj_addr + (is_64bit ? 20 : 12), ptr_size, 0, error);
578 if (error.Fail())
579 return false;
580 if (is_64bit)
581 value &= ~0x0f1f000000000000UL;
Enrico Granata06d58b02013-01-11 02:44:00 +0000582 }
Enrico Granatacaaf0102012-09-04 18:48:21 +0000583 else
584 {
Enrico Granataf91e78f2012-09-13 18:27:09 +0000585 if (!ExtractValueFromObjCExpression(valobj, "int", "count", value))
Enrico Granatacaaf0102012-09-04 18:48:21 +0000586 return false;
587 }
588
Daniel Malea5f35a4b2012-11-29 21:49:15 +0000589 stream.Printf("%s%" PRIu64 " %s%s",
Enrico Granatacaaf0102012-09-04 18:48:21 +0000590 (name_entries ? "@\"" : ""),
591 value,
592 (name_entries ? (value == 1 ? "entry" : "entries") : (value == 1 ? "key/value pair" : "key/value pairs")),
593 (name_entries ? "\"" : ""));
594 return true;
595}
596
597bool
Enrico Granataf91e78f2012-09-13 18:27:09 +0000598lldb_private::formatters::NSArraySummaryProvider (ValueObject& valobj, Stream& stream)
Enrico Granatacaaf0102012-09-04 18:48:21 +0000599{
600 ProcessSP process_sp = valobj.GetProcessSP();
601 if (!process_sp)
602 return false;
603
604 ObjCLanguageRuntime* runtime = (ObjCLanguageRuntime*)process_sp->GetLanguageRuntime(lldb::eLanguageTypeObjC);
605
606 if (!runtime)
607 return false;
608
609 ObjCLanguageRuntime::ClassDescriptorSP descriptor(runtime->GetClassDescriptor(valobj));
610
611 if (!descriptor.get() || !descriptor->IsValid())
612 return false;
613
614 uint32_t ptr_size = process_sp->GetAddressByteSize();
615
616 lldb::addr_t valobj_addr = valobj.GetValueAsUnsigned(0);
617
618 if (!valobj_addr)
619 return false;
620
621 uint64_t value = 0;
622
623 const char* class_name = descriptor->GetClassName().GetCString();
Enrico Granata7685a562012-09-29 00:47:43 +0000624
625 if (!class_name || !*class_name)
626 return false;
627
Enrico Granatacaaf0102012-09-04 18:48:21 +0000628 if (!strcmp(class_name,"__NSArrayI"))
629 {
630 Error error;
631 value = process_sp->ReadUnsignedIntegerFromMemory(valobj_addr + ptr_size, ptr_size, 0, error);
632 if (error.Fail())
633 return false;
634 }
635 else if (!strcmp(class_name,"__NSArrayM"))
636 {
637 Error error;
638 value = process_sp->ReadUnsignedIntegerFromMemory(valobj_addr + ptr_size, ptr_size, 0, error);
639 if (error.Fail())
640 return false;
641 }
642 else if (!strcmp(class_name,"__NSCFArray"))
643 {
644 Error error;
645 value = process_sp->ReadUnsignedIntegerFromMemory(valobj_addr + 2 * ptr_size, ptr_size, 0, error);
646 if (error.Fail())
647 return false;
648 }
649 else
650 {
Enrico Granataf91e78f2012-09-13 18:27:09 +0000651 if (!ExtractValueFromObjCExpression(valobj, "int", "count", value))
Enrico Granatacaaf0102012-09-04 18:48:21 +0000652 return false;
653 }
654
Daniel Malea5f35a4b2012-11-29 21:49:15 +0000655 stream.Printf("@\"%" PRIu64 " object%s\"",
Enrico Granatacaaf0102012-09-04 18:48:21 +0000656 value,
657 value == 1 ? "" : "s");
658 return true;
659}
660
661template<bool needs_at>
662bool
Enrico Granataf91e78f2012-09-13 18:27:09 +0000663lldb_private::formatters::NSDataSummaryProvider (ValueObject& valobj, Stream& stream)
Enrico Granatacaaf0102012-09-04 18:48:21 +0000664{
665 ProcessSP process_sp = valobj.GetProcessSP();
666 if (!process_sp)
667 return false;
668
669 ObjCLanguageRuntime* runtime = (ObjCLanguageRuntime*)process_sp->GetLanguageRuntime(lldb::eLanguageTypeObjC);
670
671 if (!runtime)
672 return false;
673
674 ObjCLanguageRuntime::ClassDescriptorSP descriptor(runtime->GetClassDescriptor(valobj));
675
676 if (!descriptor.get() || !descriptor->IsValid())
677 return false;
678
679 bool is_64bit = (process_sp->GetAddressByteSize() == 8);
680 lldb::addr_t valobj_addr = valobj.GetValueAsUnsigned(0);
681
682 if (!valobj_addr)
683 return false;
684
685 uint64_t value = 0;
686
687 const char* class_name = descriptor->GetClassName().GetCString();
Enrico Granata7685a562012-09-29 00:47:43 +0000688
689 if (!class_name || !*class_name)
690 return false;
691
Enrico Granatacaaf0102012-09-04 18:48:21 +0000692 if (!strcmp(class_name,"NSConcreteData") ||
693 !strcmp(class_name,"NSConcreteMutableData") ||
694 !strcmp(class_name,"__NSCFData"))
695 {
696 uint32_t offset = (is_64bit ? 16 : 8);
697 Error error;
698 value = process_sp->ReadUnsignedIntegerFromMemory(valobj_addr + offset, is_64bit ? 8 : 4, 0, error);
699 if (error.Fail())
700 return false;
701 }
702 else
703 {
Enrico Granataf91e78f2012-09-13 18:27:09 +0000704 if (!ExtractValueFromObjCExpression(valobj, "int", "length", value))
Enrico Granatacaaf0102012-09-04 18:48:21 +0000705 return false;
706 }
707
Daniel Malea5f35a4b2012-11-29 21:49:15 +0000708 stream.Printf("%s%" PRIu64 " byte%s%s",
Enrico Granatacaaf0102012-09-04 18:48:21 +0000709 (needs_at ? "@\"" : ""),
710 value,
711 (value > 1 ? "s" : ""),
712 (needs_at ? "\"" : ""));
713
714 return true;
715}
716
717bool
Enrico Granataf91e78f2012-09-13 18:27:09 +0000718lldb_private::formatters::NSNumberSummaryProvider (ValueObject& valobj, Stream& stream)
Enrico Granatacaaf0102012-09-04 18:48:21 +0000719{
720 ProcessSP process_sp = valobj.GetProcessSP();
721 if (!process_sp)
722 return false;
723
724 ObjCLanguageRuntime* runtime = (ObjCLanguageRuntime*)process_sp->GetLanguageRuntime(lldb::eLanguageTypeObjC);
725
726 if (!runtime)
727 return false;
728
729 ObjCLanguageRuntime::ClassDescriptorSP descriptor(runtime->GetClassDescriptor(valobj));
730
731 if (!descriptor.get() || !descriptor->IsValid())
732 return false;
733
734 uint32_t ptr_size = process_sp->GetAddressByteSize();
735
736 lldb::addr_t valobj_addr = valobj.GetValueAsUnsigned(0);
737
738 if (!valobj_addr)
739 return false;
740
741 const char* class_name = descriptor->GetClassName().GetCString();
742
Enrico Granata7685a562012-09-29 00:47:43 +0000743 if (!class_name || !*class_name)
744 return false;
745
Enrico Granatacaaf0102012-09-04 18:48:21 +0000746 if (!strcmp(class_name,"NSNumber") || !strcmp(class_name,"__NSCFNumber"))
747 {
748 if (descriptor->IsTagged())
749 {
750 // we have a call to get info and value bits in the tagged descriptor. but we prefer not to cast and replicate them
751 int64_t value = (valobj_addr & ~0x0000000000000000FFL) >> 8;
752 uint64_t i_bits = (valobj_addr & 0xF0) >> 4;
753
754 switch (i_bits)
755 {
756 case 0:
757 stream.Printf("(char)%hhd",(char)value);
758 break;
759 case 4:
760 stream.Printf("(short)%hd",(short)value);
761 break;
762 case 8:
763 stream.Printf("(int)%d",(int)value);
764 break;
765 case 12:
Daniel Malea5f35a4b2012-11-29 21:49:15 +0000766 stream.Printf("(long)%" PRId64,value);
Enrico Granatacaaf0102012-09-04 18:48:21 +0000767 break;
768 default:
Enrico Granata3ca24b42012-12-10 19:23:00 +0000769 stream.Printf("unexpected value:(info=%" PRIu64 ", value=%" PRIu64,i_bits,value);
Enrico Granatacaaf0102012-09-04 18:48:21 +0000770 break;
771 }
772 return true;
773 }
774 else
775 {
776 Error error;
777 uint8_t data_type = (process_sp->ReadUnsignedIntegerFromMemory(valobj_addr + ptr_size, 1, 0, error) & 0x1F);
778 uint64_t data_location = valobj_addr + 2*ptr_size;
779 uint64_t value = 0;
780 if (error.Fail())
781 return false;
782 switch (data_type)
783 {
784 case 1: // 0B00001
785 value = process_sp->ReadUnsignedIntegerFromMemory(data_location, 1, 0, error);
786 if (error.Fail())
787 return false;
788 stream.Printf("(char)%hhd",(char)value);
789 break;
790 case 2: // 0B0010
791 value = process_sp->ReadUnsignedIntegerFromMemory(data_location, 2, 0, error);
792 if (error.Fail())
793 return false;
794 stream.Printf("(short)%hd",(short)value);
795 break;
796 case 3: // 0B0011
797 value = process_sp->ReadUnsignedIntegerFromMemory(data_location, 4, 0, error);
798 if (error.Fail())
799 return false;
800 stream.Printf("(int)%d",(int)value);
801 break;
802 case 17: // 0B10001
803 data_location += 8;
804 case 4: // 0B0100
805 value = process_sp->ReadUnsignedIntegerFromMemory(data_location, 8, 0, error);
806 if (error.Fail())
807 return false;
Daniel Malea5f35a4b2012-11-29 21:49:15 +0000808 stream.Printf("(long)%" PRId64,value);
Enrico Granatacaaf0102012-09-04 18:48:21 +0000809 break;
810 case 5: // 0B0101
811 {
812 uint32_t flt_as_int = process_sp->ReadUnsignedIntegerFromMemory(data_location, 4, 0, error);
813 if (error.Fail())
814 return false;
815 float flt_value = *((float*)&flt_as_int);
816 stream.Printf("(float)%f",flt_value);
817 break;
818 }
819 case 6: // 0B0110
820 {
821 uint64_t dbl_as_lng = process_sp->ReadUnsignedIntegerFromMemory(data_location, 8, 0, error);
822 if (error.Fail())
823 return false;
824 double dbl_value = *((double*)&dbl_as_lng);
825 stream.Printf("(double)%g",dbl_value);
826 break;
827 }
828 default:
829 stream.Printf("absurd: dt=%d",data_type);
830 break;
831 }
832 return true;
833 }
834 }
835 else
836 {
Enrico Granataf91e78f2012-09-13 18:27:09 +0000837 // similar to ExtractValueFromObjCExpression but uses summary instead of value
Enrico Granatacaaf0102012-09-04 18:48:21 +0000838 StreamString expr_path_stream;
839 valobj.GetExpressionPath(expr_path_stream, false);
840 StreamString expr;
841 expr.Printf("(NSString*)[%s stringValue]",expr_path_stream.GetData());
842 ExecutionContext exe_ctx (valobj.GetExecutionContextRef());
843 lldb::ValueObjectSP result_sp;
844 Target* target = exe_ctx.GetTargetPtr();
845 StackFrame* stack_frame = exe_ctx.GetFramePtr();
846 if (!target || !stack_frame)
847 return false;
Enrico Granatad27026e2012-09-05 20:41:26 +0000848
Jim Ingham47beabb2012-10-16 21:41:58 +0000849 EvaluateExpressionOptions options;
Enrico Granatad27026e2012-09-05 20:41:26 +0000850 options.SetCoerceToId(false)
851 .SetUnwindOnError(true)
852 .SetKeepInMemory(true)
853 .SetUseDynamic(lldb::eDynamicCanRunTarget);
854
Enrico Granatacaaf0102012-09-04 18:48:21 +0000855 target->EvaluateExpression(expr.GetData(),
856 stack_frame,
Enrico Granatad27026e2012-09-05 20:41:26 +0000857 result_sp,
858 options);
Enrico Granatacaaf0102012-09-04 18:48:21 +0000859 if (!result_sp)
860 return false;
861 stream.Printf("%s",result_sp->GetSummaryAsCString());
862 return true;
863 }
864}
865
866bool
Enrico Granataf91e78f2012-09-13 18:27:09 +0000867lldb_private::formatters::NSStringSummaryProvider (ValueObject& valobj, Stream& stream)
Enrico Granatacaaf0102012-09-04 18:48:21 +0000868{
869 ProcessSP process_sp = valobj.GetProcessSP();
870 if (!process_sp)
871 return false;
872
873 ObjCLanguageRuntime* runtime = (ObjCLanguageRuntime*)process_sp->GetLanguageRuntime(lldb::eLanguageTypeObjC);
874
875 if (!runtime)
876 return false;
877
878 ObjCLanguageRuntime::ClassDescriptorSP descriptor(runtime->GetClassDescriptor(valobj));
879
880 if (!descriptor.get() || !descriptor->IsValid())
881 return false;
882
883 uint32_t ptr_size = process_sp->GetAddressByteSize();
884
885 lldb::addr_t valobj_addr = valobj.GetValueAsUnsigned(0);
886
887 if (!valobj_addr)
888 return false;
889
890 const char* class_name = descriptor->GetClassName().GetCString();
891
Enrico Granata25c9ade2012-09-29 00:45:53 +0000892 if (!class_name || !*class_name)
893 return false;
894
Enrico Granatacaaf0102012-09-04 18:48:21 +0000895 uint64_t info_bits_location = valobj_addr + ptr_size;
896 if (process_sp->GetByteOrder() != lldb::eByteOrderLittle)
897 info_bits_location += 3;
898
899 Error error;
900
901 uint8_t info_bits = process_sp->ReadUnsignedIntegerFromMemory(info_bits_location, 1, 0, error);
902 if (error.Fail())
903 return false;
904
905 bool is_mutable = (info_bits & 1) == 1;
906 bool is_inline = (info_bits & 0x60) == 0;
907 bool has_explicit_length = (info_bits & (1 | 4)) != 4;
908 bool is_unicode = (info_bits & 0x10) == 0x10;
909 bool is_special = strcmp(class_name,"NSPathStore2") == 0;
910
911 if (strcmp(class_name,"NSString") &&
912 strcmp(class_name,"CFStringRef") &&
913 strcmp(class_name,"CFMutableStringRef") &&
914 strcmp(class_name,"__NSCFConstantString") &&
915 strcmp(class_name,"__NSCFString") &&
916 strcmp(class_name,"NSCFConstantString") &&
917 strcmp(class_name,"NSCFString") &&
918 strcmp(class_name,"NSPathStore2"))
919 {
920 // probably not one of us - bail out
921 return false;
922 }
923
924 if (is_mutable)
925 {
926 uint64_t location = 2 * ptr_size + valobj_addr;
927 location = process_sp->ReadPointerFromMemory(location, error);
928 if (error.Fail())
929 return false;
930 if (has_explicit_length and is_unicode)
Enrico Granatacd8cd612013-01-14 23:53:26 +0000931 return ReadUTFBufferAndDumpToStream<UTF16> (ConvertUTF16toUTF8,location, process_sp, stream, '@');
Enrico Granatacaaf0102012-09-04 18:48:21 +0000932 else
933 {
934 location++;
935 lldb::DataBufferSP buffer_sp(new DataBufferHeap(1024,0));
936 size_t data_read = process_sp->ReadCStringFromMemory(location, (char*)buffer_sp->GetBytes(), 1024, error);
937 if (error.Fail())
938 return false;
939 if (data_read)
940 stream.Printf("@\"%s\"",(char*)buffer_sp->GetBytes());
941 return true;
942 }
943 }
944 else if (is_inline && has_explicit_length && !is_unicode && !is_special && !is_mutable)
945 {
946 uint64_t location = 3 * ptr_size + valobj_addr;
947 lldb::DataBufferSP buffer_sp(new DataBufferHeap(1024,0));
948 size_t data_read = process_sp->ReadCStringFromMemory(location, (char*)buffer_sp->GetBytes(), 1024, error);
949 if (error.Fail())
950 return false;
951 if (data_read)
952 stream.Printf("@\"%s\"",(char*)buffer_sp->GetBytes());
953 return true;
954 }
955 else if (is_unicode)
956 {
957 uint64_t location = valobj_addr + ptr_size + 4 + (ptr_size == 8 ? 4 : 0);
958 if (is_inline)
959 {
960 if (!has_explicit_length)
961 {
962 stream.Printf("found new combo");
963 return true;
964 }
965 else
966 location += ptr_size;
967 }
968 else
969 {
970 location = process_sp->ReadPointerFromMemory(location, error);
971 if (error.Fail())
972 return false;
973 }
Enrico Granatacd8cd612013-01-14 23:53:26 +0000974 return ReadUTFBufferAndDumpToStream<UTF16> (ConvertUTF16toUTF8, location, process_sp, stream, '@');
Enrico Granatacaaf0102012-09-04 18:48:21 +0000975 }
976 else if (is_special)
977 {
978 uint64_t location = valobj_addr + (ptr_size == 8 ? 12 : 8);
Enrico Granatacd8cd612013-01-14 23:53:26 +0000979 return ReadUTFBufferAndDumpToStream<UTF16> (ConvertUTF16toUTF8, location, process_sp, stream, '@');
Enrico Granatacaaf0102012-09-04 18:48:21 +0000980 }
981 else if (is_inline)
982 {
983 uint64_t location = valobj_addr + ptr_size + 4 + (ptr_size == 8 ? 4 : 0);
984 if (!has_explicit_length)
985 location++;
986 lldb::DataBufferSP buffer_sp(new DataBufferHeap(1024,0));
987 size_t data_read = process_sp->ReadCStringFromMemory(location, (char*)buffer_sp->GetBytes(), 1024, error);
988 if (error.Fail())
989 return false;
990 if (data_read)
991 stream.Printf("@\"%s\"",(char*)buffer_sp->GetBytes());
992 return true;
993 }
994 else
995 {
996 uint64_t location = valobj_addr + ptr_size + 4 + (ptr_size == 8 ? 4 : 0);
997 location = process_sp->ReadPointerFromMemory(location, error);
998 if (error.Fail())
999 return false;
1000 lldb::DataBufferSP buffer_sp(new DataBufferHeap(1024,0));
1001 size_t data_read = process_sp->ReadCStringFromMemory(location, (char*)buffer_sp->GetBytes(), 1024, error);
1002 if (error.Fail())
1003 return false;
1004 if (data_read)
1005 stream.Printf("@\"%s\"",(char*)buffer_sp->GetBytes());
1006 return true;
1007 }
1008
1009 stream.Printf("class name = %s",class_name);
1010 return true;
1011
1012}
1013
Enrico Granata9abbfba2012-10-03 23:53:45 +00001014bool
Enrico Granatadcffc1a2013-02-08 01:55:46 +00001015lldb_private::formatters::NSAttributedStringSummaryProvider (ValueObject& valobj, Stream& stream)
1016{
1017 TargetSP target_sp(valobj.GetTargetSP());
1018 if (!target_sp)
1019 return false;
1020 uint32_t addr_size = target_sp->GetArchitecture().GetAddressByteSize();
1021 uint64_t pointee = valobj.GetValueAsUnsigned(0);
1022 if (!pointee)
1023 return false;
1024 pointee += addr_size;
1025 ClangASTType type(valobj.GetClangAST(),valobj.GetClangType());
1026 ExecutionContext exe_ctx(target_sp,false);
1027 ValueObjectSP child_ptr_sp(valobj.CreateValueObjectFromAddress("string_ptr", pointee, exe_ctx, type));
1028 if (!child_ptr_sp)
1029 return false;
1030 DataExtractor data;
1031 child_ptr_sp->GetData(data);
1032 ValueObjectSP child_sp(child_ptr_sp->CreateValueObjectFromData("string_data", data, exe_ctx, type));
1033 child_sp->GetValueAsUnsigned(0);
1034 if (child_sp)
1035 return NSStringSummaryProvider(*child_sp, stream);
1036 return false;
1037}
1038
1039bool
1040lldb_private::formatters::NSMutableAttributedStringSummaryProvider (ValueObject& valobj, Stream& stream)
1041{
1042 return NSAttributedStringSummaryProvider(valobj, stream);
1043}
1044
1045bool
Enrico Granata9abbfba2012-10-03 23:53:45 +00001046lldb_private::formatters::RuntimeSpecificDescriptionSummaryProvider (ValueObject& valobj, Stream& stream)
1047{
1048 stream.Printf("%s",valobj.GetObjectDescription());
1049 return true;
1050}
1051
Enrico Granatadb054912012-10-29 21:18:03 +00001052bool
Enrico Granata979c4b52013-02-08 19:28:04 +00001053lldb_private::formatters::NSURLSummaryProvider (ValueObject& valobj, Stream& stream)
1054{
1055 ProcessSP process_sp = valobj.GetProcessSP();
1056 if (!process_sp)
1057 return false;
1058
1059 ObjCLanguageRuntime* runtime = (ObjCLanguageRuntime*)process_sp->GetLanguageRuntime(lldb::eLanguageTypeObjC);
1060
1061 if (!runtime)
1062 return false;
1063
1064 ObjCLanguageRuntime::ClassDescriptorSP descriptor(runtime->GetClassDescriptor(valobj));
1065
1066 if (!descriptor.get() || !descriptor->IsValid())
1067 return false;
1068
1069 uint32_t ptr_size = process_sp->GetAddressByteSize();
1070
1071 lldb::addr_t valobj_addr = valobj.GetValueAsUnsigned(0);
1072
1073 if (!valobj_addr)
1074 return false;
1075
1076 const char* class_name = descriptor->GetClassName().GetCString();
1077
1078 if (!class_name || !*class_name)
1079 return false;
1080
1081 if (strcmp(class_name, "NSURL") == 0)
1082 {
1083 uint64_t offset_text = ptr_size + ptr_size + 8; // ISA + pointer + 8 bytes of data (even on 32bit)
1084 uint64_t offset_base = offset_text + ptr_size;
1085 ClangASTType type(valobj.GetClangAST(),valobj.GetClangType());
1086 ValueObjectSP text(valobj.GetSyntheticChildAtOffset(offset_text, type, true));
1087 ValueObjectSP base(valobj.GetSyntheticChildAtOffset(offset_base, type, true));
Enrico Granata2fd26152013-02-08 23:54:46 +00001088 if (!text)
Enrico Granata979c4b52013-02-08 19:28:04 +00001089 return false;
1090 if (text->GetValueAsUnsigned(0) == 0)
1091 return false;
1092 StreamString summary;
1093 if (!NSStringSummaryProvider(*text, summary))
1094 return false;
Enrico Granata2fd26152013-02-08 23:54:46 +00001095 if (base && base->GetValueAsUnsigned(0))
Enrico Granata979c4b52013-02-08 19:28:04 +00001096 {
1097 if (summary.GetSize() > 0)
1098 summary.GetString().resize(summary.GetSize()-1);
1099 summary.Printf(" -- ");
1100 StreamString base_summary;
Enrico Granata2fd26152013-02-08 23:54:46 +00001101 if (NSURLSummaryProvider(*base, base_summary) && base_summary.GetSize() > 0)
Enrico Granata979c4b52013-02-08 19:28:04 +00001102 summary.Printf("%s",base_summary.GetSize() > 2 ? base_summary.GetData() + 2 : base_summary.GetData());
1103 }
1104 if (summary.GetSize())
1105 {
1106 stream.Printf("%s",summary.GetData());
1107 return true;
1108 }
1109 }
1110 else
1111 {
1112 // similar to ExtractValueFromObjCExpression but uses summary instead of value
1113 StreamString expr_path_stream;
1114 valobj.GetExpressionPath(expr_path_stream, false);
1115 StreamString expr;
1116 expr.Printf("(NSString*)[%s description]",expr_path_stream.GetData());
1117 ExecutionContext exe_ctx (valobj.GetExecutionContextRef());
1118 lldb::ValueObjectSP result_sp;
1119 Target* target = exe_ctx.GetTargetPtr();
1120 StackFrame* stack_frame = exe_ctx.GetFramePtr();
1121 if (!target || !stack_frame)
1122 return false;
1123
1124 EvaluateExpressionOptions options;
1125 options.SetCoerceToId(false)
1126 .SetUnwindOnError(true)
1127 .SetKeepInMemory(true)
1128 .SetUseDynamic(lldb::eDynamicCanRunTarget);
1129
1130 target->EvaluateExpression(expr.GetData(),
1131 stack_frame,
1132 result_sp,
1133 options);
1134 if (!result_sp)
1135 return false;
1136 stream.Printf("%s",result_sp->GetSummaryAsCString());
1137 return true;
1138 }
1139 return false;
1140}
1141
1142bool
Enrico Granatadb054912012-10-29 21:18:03 +00001143lldb_private::formatters::ObjCBOOLSummaryProvider (ValueObject& valobj, Stream& stream)
1144{
1145 const uint32_t type_info = ClangASTContext::GetTypeInfo(valobj.GetClangType(),
1146 valobj.GetClangAST(),
1147 NULL);
1148
1149 ValueObjectSP real_guy_sp = valobj.GetSP();
1150
1151 if (type_info & ClangASTContext::eTypeIsPointer)
1152 {
1153 Error err;
1154 real_guy_sp = valobj.Dereference(err);
1155 if (err.Fail() || !real_guy_sp)
1156 return false;
1157 }
1158 else if (type_info & ClangASTContext::eTypeIsReference)
1159 {
1160 real_guy_sp = valobj.GetChildAtIndex(0, true);
1161 if (!real_guy_sp)
1162 return false;
1163 }
1164 uint64_t value = real_guy_sp->GetValueAsUnsigned(0);
1165 if (value == 0)
1166 {
1167 stream.Printf("NO");
1168 return true;
1169 }
1170 stream.Printf("YES");
1171 return true;
1172}
1173
1174template <bool is_sel_ptr>
1175bool
1176lldb_private::formatters::ObjCSELSummaryProvider (ValueObject& valobj, Stream& stream)
1177{
1178 lldb::addr_t data_address = LLDB_INVALID_ADDRESS;
1179
1180 if (is_sel_ptr)
1181 data_address = valobj.GetValueAsUnsigned(LLDB_INVALID_ADDRESS);
1182 else
1183 data_address = valobj.GetAddressOf();
1184
1185 if (data_address == LLDB_INVALID_ADDRESS)
1186 return false;
1187
1188 ExecutionContext exe_ctx(valobj.GetExecutionContextRef());
1189
1190 void* char_opaque_type = valobj.GetClangAST()->CharTy.getAsOpaquePtr();
1191 ClangASTType charstar(valobj.GetClangAST(),ClangASTType::GetPointerType(valobj.GetClangAST(), char_opaque_type));
1192
1193 ValueObjectSP valobj_sp(ValueObject::CreateValueObjectFromAddress("text", data_address, exe_ctx, charstar));
1194
1195 stream.Printf("%s",valobj_sp->GetSummaryAsCString());
1196 return true;
1197}
1198
Enrico Granataf91e78f2012-09-13 18:27:09 +00001199lldb_private::formatters::NSArrayMSyntheticFrontEnd::NSArrayMSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp) :
1200SyntheticChildrenFrontEnd(*valobj_sp.get()),
1201m_exe_ctx_ref(),
1202m_ptr_size(8),
1203m_data_32(NULL),
1204m_data_64(NULL)
1205{
Enrico Granata247da332012-10-04 21:04:46 +00001206 if (valobj_sp)
Enrico Granataf91e78f2012-09-13 18:27:09 +00001207 {
Enrico Granata247da332012-10-04 21:04:46 +00001208 m_id_type = ClangASTType(valobj_sp->GetClangAST(),valobj_sp->GetClangAST()->ObjCBuiltinIdTy.getAsOpaquePtr());
1209 Update();
Enrico Granataf91e78f2012-09-13 18:27:09 +00001210 }
Enrico Granataf91e78f2012-09-13 18:27:09 +00001211}
1212
Greg Clayton36da2aa2013-01-25 18:06:21 +00001213size_t
Enrico Granataf91e78f2012-09-13 18:27:09 +00001214lldb_private::formatters::NSArrayMSyntheticFrontEnd::CalculateNumChildren ()
1215{
1216 if (m_data_32)
1217 return m_data_32->_used;
1218 if (m_data_64)
1219 return m_data_64->_used;
1220 return 0;
1221}
1222
1223lldb::ValueObjectSP
Greg Clayton36da2aa2013-01-25 18:06:21 +00001224lldb_private::formatters::NSArrayMSyntheticFrontEnd::GetChildAtIndex (size_t idx)
Enrico Granataf91e78f2012-09-13 18:27:09 +00001225{
1226 if (!m_data_32 && !m_data_64)
1227 return lldb::ValueObjectSP();
1228 if (idx >= CalculateNumChildren())
1229 return lldb::ValueObjectSP();
1230 lldb::addr_t object_at_idx = (m_data_32 ? m_data_32->_data : m_data_64->_data);
1231 object_at_idx += (idx * m_ptr_size);
1232 StreamString idx_name;
Greg Clayton36da2aa2013-01-25 18:06:21 +00001233 idx_name.Printf("[%zu]",idx);
Enrico Granataf91e78f2012-09-13 18:27:09 +00001234 lldb::ValueObjectSP retval_sp = ValueObject::CreateValueObjectFromAddress(idx_name.GetData(),
1235 object_at_idx,
1236 m_exe_ctx_ref,
1237 m_id_type);
1238 m_children.push_back(retval_sp);
1239 return retval_sp;
1240}
1241
1242bool
1243lldb_private::formatters::NSArrayMSyntheticFrontEnd::Update()
1244{
1245 m_children.clear();
Enrico Granata247da332012-10-04 21:04:46 +00001246 ValueObjectSP valobj_sp = m_backend.GetSP();
1247 m_ptr_size = 0;
1248 delete m_data_32;
1249 m_data_32 = NULL;
1250 delete m_data_64;
1251 m_data_64 = NULL;
1252 if (valobj_sp->IsDynamic())
1253 valobj_sp = valobj_sp->GetStaticValue();
1254 if (!valobj_sp)
1255 return false;
1256 m_exe_ctx_ref = valobj_sp->GetExecutionContextRef();
1257 Error error;
1258 if (valobj_sp->IsPointerType())
1259 {
1260 valobj_sp = valobj_sp->Dereference(error);
1261 if (error.Fail() || !valobj_sp)
1262 return false;
1263 }
1264 error.Clear();
1265 lldb::ProcessSP process_sp(valobj_sp->GetProcessSP());
1266 if (!process_sp)
1267 return false;
1268 m_ptr_size = process_sp->GetAddressByteSize();
1269 uint64_t data_location = valobj_sp->GetAddressOf() + m_ptr_size;
1270 if (m_ptr_size == 4)
1271 {
1272 m_data_32 = new DataDescriptor_32();
1273 process_sp->ReadMemory (data_location, m_data_32, sizeof(DataDescriptor_32), error);
1274 }
1275 else
1276 {
1277 m_data_64 = new DataDescriptor_64();
1278 process_sp->ReadMemory (data_location, m_data_64, sizeof(DataDescriptor_64), error);
1279 }
1280 if (error.Fail())
1281 return false;
Enrico Granataf91e78f2012-09-13 18:27:09 +00001282 return false;
1283}
1284
Enrico Granata800332c2012-10-23 19:54:09 +00001285bool
1286lldb_private::formatters::NSArrayMSyntheticFrontEnd::MightHaveChildren ()
1287{
Enrico Granataf3c10482012-12-10 19:55:53 +00001288 return true;
Enrico Granata800332c2012-10-23 19:54:09 +00001289}
1290
Enrico Granataf91e78f2012-09-13 18:27:09 +00001291static uint32_t
1292ExtractIndexFromString (const char* item_name)
1293{
1294 if (!item_name || !*item_name)
1295 return UINT32_MAX;
1296 if (*item_name != '[')
1297 return UINT32_MAX;
1298 item_name++;
1299 uint32_t idx = 0;
1300 while(*item_name)
1301 {
1302 char x = *item_name;
1303 if (x == ']')
1304 break;
1305 if (x < '0' || x > '9')
1306 return UINT32_MAX;
1307 idx = 10*idx + (x-'0');
1308 item_name++;
1309 }
1310 return idx;
1311}
1312
Enrico Granataf509c5e2013-01-28 23:47:25 +00001313size_t
Enrico Granataf91e78f2012-09-13 18:27:09 +00001314lldb_private::formatters::NSArrayMSyntheticFrontEnd::GetIndexOfChildWithName (const ConstString &name)
1315{
1316 if (!m_data_32 && !m_data_64)
1317 return UINT32_MAX;
1318 const char* item_name = name.GetCString();
1319 uint32_t idx = ExtractIndexFromString(item_name);
1320 if (idx < UINT32_MAX && idx >= CalculateNumChildren())
1321 return UINT32_MAX;
1322 return idx;
1323}
1324
1325lldb_private::formatters::NSArrayMSyntheticFrontEnd::~NSArrayMSyntheticFrontEnd ()
1326{
1327 delete m_data_32;
1328 m_data_32 = NULL;
1329 delete m_data_64;
1330 m_data_64 = NULL;
1331}
1332
1333lldb_private::formatters::NSArrayISyntheticFrontEnd::NSArrayISyntheticFrontEnd (lldb::ValueObjectSP valobj_sp) :
1334SyntheticChildrenFrontEnd(*valobj_sp.get()),
1335m_exe_ctx_ref(),
1336m_ptr_size(8),
1337m_items(0),
1338m_data_ptr(0)
1339{
Enrico Granata247da332012-10-04 21:04:46 +00001340 if (valobj_sp)
Enrico Granataf91e78f2012-09-13 18:27:09 +00001341 {
Enrico Granata247da332012-10-04 21:04:46 +00001342 m_id_type = ClangASTType(valobj_sp->GetClangAST(),valobj_sp->GetClangAST()->ObjCBuiltinIdTy.getAsOpaquePtr());
1343 Update();
Enrico Granataf91e78f2012-09-13 18:27:09 +00001344 }
Enrico Granataf91e78f2012-09-13 18:27:09 +00001345}
1346
1347lldb_private::formatters::NSArrayISyntheticFrontEnd::~NSArrayISyntheticFrontEnd ()
1348{
1349}
1350
Enrico Granataf509c5e2013-01-28 23:47:25 +00001351size_t
Enrico Granataf91e78f2012-09-13 18:27:09 +00001352lldb_private::formatters::NSArrayISyntheticFrontEnd::GetIndexOfChildWithName (const ConstString &name)
1353{
1354 const char* item_name = name.GetCString();
1355 uint32_t idx = ExtractIndexFromString(item_name);
1356 if (idx < UINT32_MAX && idx >= CalculateNumChildren())
1357 return UINT32_MAX;
1358 return idx;
1359}
1360
Greg Clayton36da2aa2013-01-25 18:06:21 +00001361size_t
Enrico Granataf91e78f2012-09-13 18:27:09 +00001362lldb_private::formatters::NSArrayISyntheticFrontEnd::CalculateNumChildren ()
1363{
1364 return m_items;
1365}
1366
1367bool
1368lldb_private::formatters::NSArrayISyntheticFrontEnd::Update()
1369{
Enrico Granata247da332012-10-04 21:04:46 +00001370 m_ptr_size = 0;
1371 m_items = 0;
1372 m_data_ptr = 0;
Enrico Granataf91e78f2012-09-13 18:27:09 +00001373 m_children.clear();
Enrico Granata247da332012-10-04 21:04:46 +00001374 ValueObjectSP valobj_sp = m_backend.GetSP();
1375 if (valobj_sp->IsDynamic())
1376 valobj_sp = valobj_sp->GetStaticValue();
1377 if (!valobj_sp)
1378 return false;
1379 m_exe_ctx_ref = valobj_sp->GetExecutionContextRef();
1380 Error error;
1381 if (valobj_sp->IsPointerType())
1382 {
1383 valobj_sp = valobj_sp->Dereference(error);
1384 if (error.Fail() || !valobj_sp)
1385 return false;
1386 }
1387 error.Clear();
1388 lldb::ProcessSP process_sp(valobj_sp->GetProcessSP());
1389 if (!process_sp)
1390 return false;
1391 m_ptr_size = process_sp->GetAddressByteSize();
1392 uint64_t data_location = valobj_sp->GetAddressOf() + m_ptr_size;
1393 m_items = process_sp->ReadPointerFromMemory(data_location, error);
1394 if (error.Fail())
1395 return false;
1396 m_data_ptr = data_location+m_ptr_size;
Enrico Granataf91e78f2012-09-13 18:27:09 +00001397 return false;
1398}
1399
Enrico Granata800332c2012-10-23 19:54:09 +00001400bool
1401lldb_private::formatters::NSArrayISyntheticFrontEnd::MightHaveChildren ()
1402{
Enrico Granataf3c10482012-12-10 19:55:53 +00001403 return true;
Enrico Granata800332c2012-10-23 19:54:09 +00001404}
1405
Enrico Granataf91e78f2012-09-13 18:27:09 +00001406lldb::ValueObjectSP
Greg Clayton36da2aa2013-01-25 18:06:21 +00001407lldb_private::formatters::NSArrayISyntheticFrontEnd::GetChildAtIndex (size_t idx)
Enrico Granataf91e78f2012-09-13 18:27:09 +00001408{
1409 if (idx >= CalculateNumChildren())
1410 return lldb::ValueObjectSP();
1411 lldb::addr_t object_at_idx = m_data_ptr;
1412 object_at_idx += (idx * m_ptr_size);
1413 ProcessSP process_sp = m_exe_ctx_ref.GetProcessSP();
1414 if (!process_sp)
1415 return lldb::ValueObjectSP();
1416 Error error;
1417 object_at_idx = process_sp->ReadPointerFromMemory(object_at_idx, error);
1418 if (error.Fail())
1419 return lldb::ValueObjectSP();
1420 StreamString expr;
Daniel Malea5f35a4b2012-11-29 21:49:15 +00001421 expr.Printf("(id)%" PRIu64,object_at_idx);
Enrico Granataf91e78f2012-09-13 18:27:09 +00001422 StreamString idx_name;
Greg Clayton36da2aa2013-01-25 18:06:21 +00001423 idx_name.Printf("[%zu]",idx);
Enrico Granataf91e78f2012-09-13 18:27:09 +00001424 lldb::ValueObjectSP retval_sp = ValueObject::CreateValueObjectFromExpression(idx_name.GetData(), expr.GetData(), m_exe_ctx_ref);
1425 m_children.push_back(retval_sp);
1426 return retval_sp;
1427}
1428
1429SyntheticChildrenFrontEnd* lldb_private::formatters::NSArraySyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP valobj_sp)
1430{
1431 lldb::ProcessSP process_sp (valobj_sp->GetProcessSP());
1432 if (!process_sp)
1433 return NULL;
1434 ObjCLanguageRuntime *runtime = (ObjCLanguageRuntime*)process_sp->GetLanguageRuntime(lldb::eLanguageTypeObjC);
1435 if (!runtime)
1436 return NULL;
1437
1438 if (!valobj_sp->IsPointerType())
1439 {
1440 Error error;
1441 valobj_sp = valobj_sp->AddressOf(error);
1442 if (error.Fail() || !valobj_sp)
1443 return NULL;
1444 }
1445
1446 ObjCLanguageRuntime::ClassDescriptorSP descriptor(runtime->GetClassDescriptor(*valobj_sp.get()));
1447
1448 if (!descriptor.get() || !descriptor->IsValid())
1449 return NULL;
1450
1451 const char* class_name = descriptor->GetClassName().GetCString();
Enrico Granata7685a562012-09-29 00:47:43 +00001452
1453 if (!class_name || !*class_name)
1454 return NULL;
1455
Enrico Granataf91e78f2012-09-13 18:27:09 +00001456 if (!strcmp(class_name,"__NSArrayI"))
1457 {
1458 return (new NSArrayISyntheticFrontEnd(valobj_sp));
1459 }
1460 else if (!strcmp(class_name,"__NSArrayM"))
1461 {
1462 return (new NSArrayMSyntheticFrontEnd(valobj_sp));
1463 }
1464 else
1465 {
1466 return (new NSArrayCodeRunningSyntheticFrontEnd(valobj_sp));
1467 }
1468}
1469
1470lldb_private::formatters::NSArrayCodeRunningSyntheticFrontEnd::NSArrayCodeRunningSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp) :
1471SyntheticChildrenFrontEnd(*valobj_sp.get())
1472{}
1473
Greg Clayton36da2aa2013-01-25 18:06:21 +00001474size_t
Enrico Granataf91e78f2012-09-13 18:27:09 +00001475lldb_private::formatters::NSArrayCodeRunningSyntheticFrontEnd::CalculateNumChildren ()
1476{
Enrico Granataf91e78f2012-09-13 18:27:09 +00001477 uint64_t count = 0;
1478 if (ExtractValueFromObjCExpression(m_backend, "int", "count", count))
1479 return count;
1480 return 0;
1481}
1482
1483lldb::ValueObjectSP
Greg Clayton36da2aa2013-01-25 18:06:21 +00001484lldb_private::formatters::NSArrayCodeRunningSyntheticFrontEnd::GetChildAtIndex (size_t idx)
Enrico Granataf91e78f2012-09-13 18:27:09 +00001485{
1486 StreamString idx_name;
Greg Clayton36da2aa2013-01-25 18:06:21 +00001487 idx_name.Printf("[%zu]",idx);
Enrico Granataf91e78f2012-09-13 18:27:09 +00001488 lldb::ValueObjectSP valobj_sp = CallSelectorOnObject(m_backend,"id","objectAtIndex:",idx);
1489 if (valobj_sp)
1490 valobj_sp->SetName(ConstString(idx_name.GetData()));
1491 return valobj_sp;
1492}
1493
1494bool
1495lldb_private::formatters::NSArrayCodeRunningSyntheticFrontEnd::Update()
1496{
1497 return false;
1498}
1499
Enrico Granata800332c2012-10-23 19:54:09 +00001500bool
1501lldb_private::formatters::NSArrayCodeRunningSyntheticFrontEnd::MightHaveChildren ()
1502{
Enrico Granataf3c10482012-12-10 19:55:53 +00001503 return true;
Enrico Granata800332c2012-10-23 19:54:09 +00001504}
1505
Enrico Granataf509c5e2013-01-28 23:47:25 +00001506size_t
Enrico Granataf91e78f2012-09-13 18:27:09 +00001507lldb_private::formatters::NSArrayCodeRunningSyntheticFrontEnd::GetIndexOfChildWithName (const ConstString &name)
1508{
1509 return 0;
1510}
1511
1512lldb_private::formatters::NSArrayCodeRunningSyntheticFrontEnd::~NSArrayCodeRunningSyntheticFrontEnd ()
1513{}
1514
Enrico Granata3a08fd12012-09-18 17:43:16 +00001515SyntheticChildrenFrontEnd* lldb_private::formatters::NSDictionarySyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP valobj_sp)
1516{
1517
1518 lldb::ProcessSP process_sp (valobj_sp->GetProcessSP());
1519 if (!process_sp)
1520 return NULL;
1521 ObjCLanguageRuntime *runtime = (ObjCLanguageRuntime*)process_sp->GetLanguageRuntime(lldb::eLanguageTypeObjC);
1522 if (!runtime)
1523 return NULL;
1524
1525 if (!valobj_sp->IsPointerType())
1526 {
1527 Error error;
1528 valobj_sp = valobj_sp->AddressOf(error);
1529 if (error.Fail() || !valobj_sp)
1530 return NULL;
1531 }
1532
1533 ObjCLanguageRuntime::ClassDescriptorSP descriptor(runtime->GetClassDescriptor(*valobj_sp.get()));
1534
1535 if (!descriptor.get() || !descriptor->IsValid())
1536 return NULL;
1537
1538 const char* class_name = descriptor->GetClassName().GetCString();
Enrico Granata7685a562012-09-29 00:47:43 +00001539
1540 if (!class_name || !*class_name)
1541 return NULL;
1542
Enrico Granata3a08fd12012-09-18 17:43:16 +00001543 if (!strcmp(class_name,"__NSDictionaryI"))
1544 {
1545 return (new NSDictionaryISyntheticFrontEnd(valobj_sp));
1546 }
1547 else if (!strcmp(class_name,"__NSDictionaryM"))
1548 {
1549 return (new NSDictionaryMSyntheticFrontEnd(valobj_sp));
1550 }
1551 else
1552 {
1553 return (new NSDictionaryCodeRunningSyntheticFrontEnd(valobj_sp));
1554 }
1555}
1556
1557lldb_private::formatters::NSDictionaryCodeRunningSyntheticFrontEnd::NSDictionaryCodeRunningSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp) :
1558SyntheticChildrenFrontEnd(*valobj_sp.get())
1559{}
1560
Greg Clayton36da2aa2013-01-25 18:06:21 +00001561size_t
Enrico Granata3a08fd12012-09-18 17:43:16 +00001562lldb_private::formatters::NSDictionaryCodeRunningSyntheticFrontEnd::CalculateNumChildren ()
1563{
1564 uint64_t count = 0;
1565 if (ExtractValueFromObjCExpression(m_backend, "int", "count", count))
1566 return count;
1567 return 0;
1568}
1569
1570lldb::ValueObjectSP
Greg Clayton36da2aa2013-01-25 18:06:21 +00001571lldb_private::formatters::NSDictionaryCodeRunningSyntheticFrontEnd::GetChildAtIndex (size_t idx)
Enrico Granata3a08fd12012-09-18 17:43:16 +00001572{
1573 StreamString idx_name;
Greg Clayton36da2aa2013-01-25 18:06:21 +00001574 idx_name.Printf("[%zu]",idx);
Enrico Granata3a08fd12012-09-18 17:43:16 +00001575 StreamString valobj_expr_path;
1576 m_backend.GetExpressionPath(valobj_expr_path, false);
1577 StreamString key_fetcher_expr;
Greg Clayton36da2aa2013-01-25 18:06:21 +00001578 key_fetcher_expr.Printf("(id)[(NSArray*)[%s allKeys] objectAtIndex:%zu]",valobj_expr_path.GetData(),idx);
Enrico Granata3a08fd12012-09-18 17:43:16 +00001579 StreamString value_fetcher_expr;
1580 value_fetcher_expr.Printf("(id)[%s objectForKey:%s]",valobj_expr_path.GetData(),key_fetcher_expr.GetData());
1581 StreamString object_fetcher_expr;
Enrico Granatafd3d28d2012-10-01 21:49:10 +00001582 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());
Enrico Granata3a08fd12012-09-18 17:43:16 +00001583 lldb::ValueObjectSP child_sp;
1584 m_backend.GetTargetSP()->EvaluateExpression(object_fetcher_expr.GetData(), m_backend.GetFrameSP().get(), child_sp,
Jim Ingham47beabb2012-10-16 21:41:58 +00001585 EvaluateExpressionOptions().SetKeepInMemory(true));
Enrico Granata3a08fd12012-09-18 17:43:16 +00001586 if (child_sp)
1587 child_sp->SetName(ConstString(idx_name.GetData()));
1588 return child_sp;
1589}
1590
1591bool
1592lldb_private::formatters::NSDictionaryCodeRunningSyntheticFrontEnd::Update()
1593{
1594 return false;
1595}
1596
Enrico Granata800332c2012-10-23 19:54:09 +00001597bool
1598lldb_private::formatters::NSDictionaryCodeRunningSyntheticFrontEnd::MightHaveChildren ()
1599{
Enrico Granataf3c10482012-12-10 19:55:53 +00001600 return true;
Enrico Granata800332c2012-10-23 19:54:09 +00001601}
1602
Enrico Granataf509c5e2013-01-28 23:47:25 +00001603size_t
Enrico Granata3a08fd12012-09-18 17:43:16 +00001604lldb_private::formatters::NSDictionaryCodeRunningSyntheticFrontEnd::GetIndexOfChildWithName (const ConstString &name)
1605{
1606 return 0;
1607}
1608
1609lldb_private::formatters::NSDictionaryCodeRunningSyntheticFrontEnd::~NSDictionaryCodeRunningSyntheticFrontEnd ()
1610{}
1611
1612lldb_private::formatters::NSDictionaryISyntheticFrontEnd::NSDictionaryISyntheticFrontEnd (lldb::ValueObjectSP valobj_sp) :
1613 SyntheticChildrenFrontEnd(*valobj_sp.get()),
1614 m_exe_ctx_ref(),
1615 m_ptr_size(8),
1616 m_data_32(NULL),
1617 m_data_64(NULL)
1618{
Enrico Granataa787c1a2012-10-04 21:46:06 +00001619 if (valobj_sp)
1620 Update();
Enrico Granata3a08fd12012-09-18 17:43:16 +00001621}
1622
1623lldb_private::formatters::NSDictionaryISyntheticFrontEnd::~NSDictionaryISyntheticFrontEnd ()
1624{
1625 delete m_data_32;
1626 m_data_32 = NULL;
1627 delete m_data_64;
1628 m_data_64 = NULL;
1629}
1630
Enrico Granataf509c5e2013-01-28 23:47:25 +00001631size_t
Enrico Granata3a08fd12012-09-18 17:43:16 +00001632lldb_private::formatters::NSDictionaryISyntheticFrontEnd::GetIndexOfChildWithName (const ConstString &name)
1633{
1634 const char* item_name = name.GetCString();
1635 uint32_t idx = ExtractIndexFromString(item_name);
1636 if (idx < UINT32_MAX && idx >= CalculateNumChildren())
1637 return UINT32_MAX;
1638 return idx;
1639}
1640
Greg Clayton36da2aa2013-01-25 18:06:21 +00001641size_t
Enrico Granata3a08fd12012-09-18 17:43:16 +00001642lldb_private::formatters::NSDictionaryISyntheticFrontEnd::CalculateNumChildren ()
1643{
1644 if (!m_data_32 && !m_data_64)
1645 return 0;
1646 return (m_data_32 ? m_data_32->_used : m_data_64->_used);
1647}
1648
1649bool
1650lldb_private::formatters::NSDictionaryISyntheticFrontEnd::Update()
1651{
1652 m_children.clear();
Enrico Granataa787c1a2012-10-04 21:46:06 +00001653 delete m_data_32;
1654 m_data_32 = NULL;
1655 delete m_data_64;
1656 m_data_64 = NULL;
1657 m_ptr_size = 0;
1658 ValueObjectSP valobj_sp = m_backend.GetSP();
1659 if (!valobj_sp)
1660 return false;
1661 if (valobj_sp->IsDynamic())
1662 valobj_sp = valobj_sp->GetStaticValue();
1663 if (!valobj_sp)
1664 return false;
1665 m_exe_ctx_ref = valobj_sp->GetExecutionContextRef();
1666 Error error;
1667 if (valobj_sp->IsPointerType())
1668 {
1669 valobj_sp = valobj_sp->Dereference(error);
1670 if (error.Fail() || !valobj_sp)
1671 return false;
1672 }
1673 error.Clear();
1674 lldb::ProcessSP process_sp(valobj_sp->GetProcessSP());
1675 if (!process_sp)
1676 return false;
1677 m_ptr_size = process_sp->GetAddressByteSize();
1678 uint64_t data_location = valobj_sp->GetAddressOf() + m_ptr_size;
1679 if (m_ptr_size == 4)
1680 {
1681 m_data_32 = new DataDescriptor_32();
1682 process_sp->ReadMemory (data_location, m_data_32, sizeof(DataDescriptor_32), error);
1683 }
1684 else
1685 {
1686 m_data_64 = new DataDescriptor_64();
1687 process_sp->ReadMemory (data_location, m_data_64, sizeof(DataDescriptor_64), error);
1688 }
1689 if (error.Fail())
1690 return false;
1691 m_data_ptr = data_location + m_ptr_size;
Enrico Granata3a08fd12012-09-18 17:43:16 +00001692 return false;
1693}
1694
Enrico Granata800332c2012-10-23 19:54:09 +00001695bool
1696lldb_private::formatters::NSDictionaryISyntheticFrontEnd::MightHaveChildren ()
1697{
Enrico Granataf3c10482012-12-10 19:55:53 +00001698 return true;
Enrico Granata800332c2012-10-23 19:54:09 +00001699}
1700
Enrico Granata3a08fd12012-09-18 17:43:16 +00001701lldb::ValueObjectSP
Greg Clayton36da2aa2013-01-25 18:06:21 +00001702lldb_private::formatters::NSDictionaryISyntheticFrontEnd::GetChildAtIndex (size_t idx)
Enrico Granata3a08fd12012-09-18 17:43:16 +00001703{
1704 uint32_t num_children = CalculateNumChildren();
1705
1706 if (idx >= num_children)
1707 return lldb::ValueObjectSP();
1708
1709 if (m_children.empty())
1710 {
1711 // do the scan phase
1712 lldb::addr_t key_at_idx = 0, val_at_idx = 0;
1713
1714 uint32_t tries = 0;
1715 uint32_t test_idx = 0;
1716
1717 while(tries < num_children)
1718 {
1719 key_at_idx = m_data_ptr + (2*test_idx * m_ptr_size);
1720 val_at_idx = key_at_idx + m_ptr_size;
1721 ProcessSP process_sp = m_exe_ctx_ref.GetProcessSP();
1722 if (!process_sp)
1723 return lldb::ValueObjectSP();
1724 Error error;
1725 key_at_idx = process_sp->ReadPointerFromMemory(key_at_idx, error);
1726 if (error.Fail())
1727 return lldb::ValueObjectSP();
1728 val_at_idx = process_sp->ReadPointerFromMemory(val_at_idx, error);
1729 if (error.Fail())
1730 return lldb::ValueObjectSP();
1731
1732 test_idx++;
1733
1734 if (!key_at_idx || !val_at_idx)
1735 continue;
1736 tries++;
1737
1738 DictionaryItemDescriptor descriptor = {key_at_idx,val_at_idx,lldb::ValueObjectSP()};
1739
1740 m_children.push_back(descriptor);
1741 }
1742 }
1743
1744 if (idx >= m_children.size()) // should never happen
1745 return lldb::ValueObjectSP();
1746
1747 DictionaryItemDescriptor &dict_item = m_children[idx];
1748 if (!dict_item.valobj_sp)
1749 {
1750 // make the new ValueObject
1751 StreamString expr;
Daniel Malea5f35a4b2012-11-29 21:49:15 +00001752 expr.Printf("struct __lldb_autogen_nspair { id key; id value; } _lldb_valgen_item; _lldb_valgen_item.key = (id)%" PRIu64 " ; _lldb_valgen_item.value = (id)%" PRIu64 "; _lldb_valgen_item;",dict_item.key_ptr,dict_item.val_ptr);
Enrico Granata3a08fd12012-09-18 17:43:16 +00001753 StreamString idx_name;
Greg Clayton36da2aa2013-01-25 18:06:21 +00001754 idx_name.Printf("[%zu]",idx);
Enrico Granata3a08fd12012-09-18 17:43:16 +00001755 dict_item.valobj_sp = ValueObject::CreateValueObjectFromExpression(idx_name.GetData(), expr.GetData(), m_exe_ctx_ref);
1756 }
1757 return dict_item.valobj_sp;
1758}
1759
1760lldb_private::formatters::NSDictionaryMSyntheticFrontEnd::NSDictionaryMSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp) :
1761 SyntheticChildrenFrontEnd(*valobj_sp.get()),
1762 m_exe_ctx_ref(),
1763 m_ptr_size(8),
1764 m_data_32(NULL),
1765 m_data_64(NULL)
1766{
Enrico Granataa787c1a2012-10-04 21:46:06 +00001767 if (valobj_sp)
1768 Update ();
Enrico Granata3a08fd12012-09-18 17:43:16 +00001769}
1770
1771lldb_private::formatters::NSDictionaryMSyntheticFrontEnd::~NSDictionaryMSyntheticFrontEnd ()
1772{
1773 delete m_data_32;
1774 m_data_32 = NULL;
1775 delete m_data_64;
1776 m_data_64 = NULL;
1777}
1778
Enrico Granataf509c5e2013-01-28 23:47:25 +00001779size_t
Enrico Granata3a08fd12012-09-18 17:43:16 +00001780lldb_private::formatters::NSDictionaryMSyntheticFrontEnd::GetIndexOfChildWithName (const ConstString &name)
1781{
1782 const char* item_name = name.GetCString();
1783 uint32_t idx = ExtractIndexFromString(item_name);
1784 if (idx < UINT32_MAX && idx >= CalculateNumChildren())
1785 return UINT32_MAX;
1786 return idx;
1787}
1788
Greg Clayton36da2aa2013-01-25 18:06:21 +00001789size_t
Enrico Granata3a08fd12012-09-18 17:43:16 +00001790lldb_private::formatters::NSDictionaryMSyntheticFrontEnd::CalculateNumChildren ()
1791{
1792 if (!m_data_32 && !m_data_64)
1793 return 0;
1794 return (m_data_32 ? m_data_32->_used : m_data_64->_used);
1795}
1796
1797bool
1798lldb_private::formatters::NSDictionaryMSyntheticFrontEnd::Update()
1799{
1800 m_children.clear();
Enrico Granataa787c1a2012-10-04 21:46:06 +00001801 ValueObjectSP valobj_sp = m_backend.GetSP();
1802 m_ptr_size = 0;
1803 delete m_data_32;
1804 m_data_32 = NULL;
1805 delete m_data_64;
1806 m_data_64 = NULL;
1807 if (!valobj_sp)
1808 return false;
1809 if (valobj_sp->IsDynamic())
1810 valobj_sp = valobj_sp->GetStaticValue();
1811 if (!valobj_sp)
1812 return false;
1813 m_exe_ctx_ref = valobj_sp->GetExecutionContextRef();
1814 Error error;
1815 if (valobj_sp->IsPointerType())
1816 {
1817 valobj_sp = valobj_sp->Dereference(error);
1818 if (error.Fail() || !valobj_sp)
1819 return false;
1820 }
1821 error.Clear();
1822 lldb::ProcessSP process_sp(valobj_sp->GetProcessSP());
1823 if (!process_sp)
1824 return false;
1825 m_ptr_size = process_sp->GetAddressByteSize();
1826 uint64_t data_location = valobj_sp->GetAddressOf() + m_ptr_size;
1827 if (m_ptr_size == 4)
1828 {
1829 m_data_32 = new DataDescriptor_32();
1830 process_sp->ReadMemory (data_location, m_data_32, sizeof(DataDescriptor_32), error);
1831 }
1832 else
1833 {
1834 m_data_64 = new DataDescriptor_64();
1835 process_sp->ReadMemory (data_location, m_data_64, sizeof(DataDescriptor_64), error);
1836 }
1837 if (error.Fail())
1838 return false;
Enrico Granata3a08fd12012-09-18 17:43:16 +00001839 return false;
1840}
1841
Enrico Granata800332c2012-10-23 19:54:09 +00001842bool
1843lldb_private::formatters::NSDictionaryMSyntheticFrontEnd::MightHaveChildren ()
1844{
Enrico Granataf3c10482012-12-10 19:55:53 +00001845 return true;
Enrico Granata800332c2012-10-23 19:54:09 +00001846}
1847
Enrico Granata3a08fd12012-09-18 17:43:16 +00001848lldb::ValueObjectSP
Greg Clayton36da2aa2013-01-25 18:06:21 +00001849lldb_private::formatters::NSDictionaryMSyntheticFrontEnd::GetChildAtIndex (size_t idx)
Enrico Granata3a08fd12012-09-18 17:43:16 +00001850{
1851 lldb::addr_t m_keys_ptr = (m_data_32 ? m_data_32->_keys_addr : m_data_64->_keys_addr);
1852 lldb::addr_t m_values_ptr = (m_data_32 ? m_data_32->_objs_addr : m_data_64->_objs_addr);
1853
1854 uint32_t num_children = CalculateNumChildren();
1855
1856 if (idx >= num_children)
1857 return lldb::ValueObjectSP();
1858
1859 if (m_children.empty())
1860 {
1861 // do the scan phase
1862 lldb::addr_t key_at_idx = 0, val_at_idx = 0;
1863
1864 uint32_t tries = 0;
1865 uint32_t test_idx = 0;
1866
1867 while(tries < num_children)
1868 {
1869 key_at_idx = m_keys_ptr + (test_idx * m_ptr_size);
1870 val_at_idx = m_values_ptr + (test_idx * m_ptr_size);;
1871 ProcessSP process_sp = m_exe_ctx_ref.GetProcessSP();
1872 if (!process_sp)
1873 return lldb::ValueObjectSP();
1874 Error error;
1875 key_at_idx = process_sp->ReadPointerFromMemory(key_at_idx, error);
1876 if (error.Fail())
1877 return lldb::ValueObjectSP();
1878 val_at_idx = process_sp->ReadPointerFromMemory(val_at_idx, error);
1879 if (error.Fail())
1880 return lldb::ValueObjectSP();
1881
1882 test_idx++;
1883
1884 if (!key_at_idx || !val_at_idx)
1885 continue;
1886 tries++;
1887
1888 DictionaryItemDescriptor descriptor = {key_at_idx,val_at_idx,lldb::ValueObjectSP()};
1889
1890 m_children.push_back(descriptor);
1891 }
1892 }
1893
1894 if (idx >= m_children.size()) // should never happen
1895 return lldb::ValueObjectSP();
1896
1897 DictionaryItemDescriptor &dict_item = m_children[idx];
1898 if (!dict_item.valobj_sp)
1899 {
1900 // make the new ValueObject
1901 StreamString expr;
Daniel Malea5f35a4b2012-11-29 21:49:15 +00001902 expr.Printf("struct __lldb_autogen_nspair { id key; id value; } _lldb_valgen_item; _lldb_valgen_item.key = (id)%" PRIu64 " ; _lldb_valgen_item.value = (id)%" PRIu64 "; _lldb_valgen_item;",dict_item.key_ptr,dict_item.val_ptr);
Enrico Granata3a08fd12012-09-18 17:43:16 +00001903 StreamString idx_name;
Greg Clayton36da2aa2013-01-25 18:06:21 +00001904 idx_name.Printf("[%zu]",idx);
Enrico Granata3a08fd12012-09-18 17:43:16 +00001905 dict_item.valobj_sp = ValueObject::CreateValueObjectFromExpression(idx_name.GetData(), expr.GetData(), m_exe_ctx_ref);
1906 }
1907 return dict_item.valobj_sp;
1908}
Enrico Granatacaaf0102012-09-04 18:48:21 +00001909
Enrico Granata689696c2013-02-04 22:54:42 +00001910lldb_private::formatters::LibcxxVectorBoolSyntheticFrontEnd::LibcxxVectorBoolSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp) :
1911 SyntheticChildrenFrontEnd(*valobj_sp.get()),
1912 m_exe_ctx_ref(),
1913 m_count(0),
1914 m_base_data_address(0),
1915 m_options()
1916 {
1917 if (valobj_sp)
1918 Update();
1919 m_options.SetCoerceToId(false)
1920 .SetUnwindOnError(true)
1921 .SetKeepInMemory(true)
1922 .SetUseDynamic(lldb::eDynamicCanRunTarget);
1923 }
1924
1925size_t
1926lldb_private::formatters::LibcxxVectorBoolSyntheticFrontEnd::CalculateNumChildren ()
1927{
1928 return m_count;
1929}
1930
1931lldb::ValueObjectSP
1932lldb_private::formatters::LibcxxVectorBoolSyntheticFrontEnd::GetChildAtIndex (size_t idx)
1933{
1934 if (idx >= m_count)
1935 return ValueObjectSP();
1936 if (m_base_data_address == 0 || m_count == 0)
1937 return ValueObjectSP();
1938 size_t byte_idx = (idx >> 3); // divide by 8 to get byte index
1939 size_t bit_index = (idx & 7); // efficient idx % 8 for bit index
1940 lldb::addr_t byte_location = m_base_data_address + byte_idx;
1941 ProcessSP process_sp(m_exe_ctx_ref.GetProcessSP());
1942 if (!process_sp)
1943 return ValueObjectSP();
1944 uint8_t byte = 0;
1945 uint8_t mask = 0;
1946 Error err;
1947 size_t bytes_read = process_sp->ReadMemory(byte_location, &byte, 1, err);
1948 if (err.Fail() || bytes_read == 0)
1949 return ValueObjectSP();
1950 switch (bit_index)
1951 {
1952 case 0:
1953 mask = 1; break;
1954 case 1:
1955 mask = 2; break;
1956 case 2:
1957 mask = 4; break;
1958 case 3:
1959 mask = 8; break;
1960 case 4:
1961 mask = 16; break;
1962 case 5:
1963 mask = 32; break;
1964 case 6:
1965 mask = 64; break;
1966 case 7:
1967 mask = 128; break;
1968 default:
1969 return ValueObjectSP();
1970 }
1971 bool bit_set = ((byte & mask) != 0);
1972 Target& target(process_sp->GetTarget());
1973 ValueObjectSP retval_sp;
1974 if (bit_set)
1975 target.EvaluateExpression("(bool)true", NULL, retval_sp);
1976 else
1977 target.EvaluateExpression("(bool)false", NULL, retval_sp);
1978 StreamString name; name.Printf("[%zu]",idx);
1979 if (retval_sp)
1980 retval_sp->SetName(ConstString(name.GetData()));
1981 return retval_sp;
1982}
1983
1984/*(std::__1::vector<std::__1::allocator<bool> >) vBool = {
1985 __begin_ = 0x00000001001000e0
1986 __size_ = 56
1987 __cap_alloc_ = {
1988 std::__1::__libcpp_compressed_pair_imp<unsigned long, std::__1::allocator<unsigned long> > = {
1989 __first_ = 1
1990 }
1991 }
1992}*/
1993
1994bool
1995lldb_private::formatters::LibcxxVectorBoolSyntheticFrontEnd::Update()
1996{
1997 ValueObjectSP valobj_sp = m_backend.GetSP();
1998 if (!valobj_sp)
1999 return false;
2000 if (valobj_sp->IsDynamic())
2001 valobj_sp = valobj_sp->GetStaticValue();
2002 if (!valobj_sp)
2003 return false;
2004 m_exe_ctx_ref = valobj_sp->GetExecutionContextRef();
2005 ValueObjectSP size_sp(valobj_sp->GetChildMemberWithName(ConstString("__size_"), true));
2006 if (!size_sp)
2007 return false;
2008 m_count = size_sp->GetValueAsUnsigned(0);
2009 if (!m_count)
2010 return true;
2011 ValueObjectSP begin_sp(valobj_sp->GetChildMemberWithName(ConstString("__begin_"), true));
2012 if (!begin_sp)
2013 {
2014 m_count = 0;
2015 return false;
2016 }
2017 m_base_data_address = begin_sp->GetValueAsUnsigned(0);
2018 if (!m_base_data_address)
2019 {
2020 m_count = 0;
2021 return false;
2022 }
2023 return true;
2024}
2025
2026bool
2027lldb_private::formatters::LibcxxVectorBoolSyntheticFrontEnd::MightHaveChildren ()
2028{
2029 return true;
2030}
2031
2032size_t
2033lldb_private::formatters::LibcxxVectorBoolSyntheticFrontEnd::GetIndexOfChildWithName (const ConstString &name)
2034{
2035 if (!m_count || !m_base_data_address)
2036 return UINT32_MAX;
2037 const char* item_name = name.GetCString();
2038 uint32_t idx = ExtractIndexFromString(item_name);
2039 if (idx < UINT32_MAX && idx >= CalculateNumChildren())
2040 return UINT32_MAX;
2041 return idx;
2042}
2043
2044lldb_private::formatters::LibcxxVectorBoolSyntheticFrontEnd::~LibcxxVectorBoolSyntheticFrontEnd ()
2045{}
2046
2047SyntheticChildrenFrontEnd*
2048lldb_private::formatters::LibcxxVectorBoolSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP valobj_sp)
2049{
2050 if (!valobj_sp)
2051 return NULL;
2052 return (new LibcxxVectorBoolSyntheticFrontEnd(valobj_sp));
2053}
2054
2055lldb_private::formatters::LibstdcppVectorBoolSyntheticFrontEnd::LibstdcppVectorBoolSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp) :
2056SyntheticChildrenFrontEnd(*valobj_sp.get()),
2057m_exe_ctx_ref(),
2058m_count(0),
2059m_base_data_address(0),
2060m_options()
2061{
2062 if (valobj_sp)
2063 Update();
2064 m_options.SetCoerceToId(false)
2065 .SetUnwindOnError(true)
2066 .SetKeepInMemory(true)
2067 .SetUseDynamic(lldb::eDynamicCanRunTarget);
2068}
2069
2070size_t
2071lldb_private::formatters::LibstdcppVectorBoolSyntheticFrontEnd::CalculateNumChildren ()
2072{
2073 return m_count;
2074}
2075
2076lldb::ValueObjectSP
2077lldb_private::formatters::LibstdcppVectorBoolSyntheticFrontEnd::GetChildAtIndex (size_t idx)
2078{
2079 if (idx >= m_count)
2080 return ValueObjectSP();
2081 if (m_base_data_address == 0 || m_count == 0)
2082 return ValueObjectSP();
2083 size_t byte_idx = (idx >> 3); // divide by 8 to get byte index
2084 size_t bit_index = (idx & 7); // efficient idx % 8 for bit index
2085 lldb::addr_t byte_location = m_base_data_address + byte_idx;
2086 ProcessSP process_sp(m_exe_ctx_ref.GetProcessSP());
2087 if (!process_sp)
2088 return ValueObjectSP();
2089 uint8_t byte = 0;
2090 uint8_t mask = 0;
2091 Error err;
2092 size_t bytes_read = process_sp->ReadMemory(byte_location, &byte, 1, err);
2093 if (err.Fail() || bytes_read == 0)
2094 return ValueObjectSP();
2095 switch (bit_index)
2096 {
2097 case 0:
2098 mask = 1; break;
2099 case 1:
2100 mask = 2; break;
2101 case 2:
2102 mask = 4; break;
2103 case 3:
2104 mask = 8; break;
2105 case 4:
2106 mask = 16; break;
2107 case 5:
2108 mask = 32; break;
2109 case 6:
2110 mask = 64; break;
2111 case 7:
2112 mask = 128; break;
2113 default:
2114 return ValueObjectSP();
2115 }
2116 bool bit_set = ((byte & mask) != 0);
2117 Target& target(process_sp->GetTarget());
2118 ValueObjectSP retval_sp;
2119 if (bit_set)
2120 target.EvaluateExpression("(bool)true", NULL, retval_sp);
2121 else
2122 target.EvaluateExpression("(bool)false", NULL, retval_sp);
2123 StreamString name; name.Printf("[%zu]",idx);
2124 if (retval_sp)
2125 retval_sp->SetName(ConstString(name.GetData()));
2126 return retval_sp;
2127}
2128
2129/*((std::vector<std::allocator<bool> >) vBool = {
2130 (std::_Bvector_base<std::allocator<bool> >) std::_Bvector_base<std::allocator<bool> > = {
2131 (std::_Bvector_base<std::allocator<bool> >::_Bvector_impl) _M_impl = {
2132 (std::_Bit_iterator) _M_start = {
2133 (std::_Bit_iterator_base) std::_Bit_iterator_base = {
2134 (_Bit_type *) _M_p = 0x0016b160
2135 (unsigned int) _M_offset = 0
2136 }
2137 }
2138 (std::_Bit_iterator) _M_finish = {
2139 (std::_Bit_iterator_base) std::_Bit_iterator_base = {
2140 (_Bit_type *) _M_p = 0x0016b16c
2141 (unsigned int) _M_offset = 16
2142 }
2143 }
2144 (_Bit_type *) _M_end_of_storage = 0x0016b170
2145 }
2146 }
2147 }
2148*/
2149
2150bool
2151lldb_private::formatters::LibstdcppVectorBoolSyntheticFrontEnd::Update()
2152{
2153 ValueObjectSP valobj_sp = m_backend.GetSP();
2154 if (!valobj_sp)
2155 return false;
2156 if (valobj_sp->IsDynamic())
2157 valobj_sp = valobj_sp->GetStaticValue();
2158 if (!valobj_sp)
2159 return false;
2160 m_exe_ctx_ref = valobj_sp->GetExecutionContextRef();
2161
2162 ValueObjectSP m_impl_sp(valobj_sp->GetChildMemberWithName(ConstString("_M_impl"), true));
2163 if (!m_impl_sp)
2164 return false;
2165
2166 ValueObjectSP m_start_sp(m_impl_sp->GetChildMemberWithName(ConstString("_M_start"), true));
2167 ValueObjectSP m_finish_sp(m_impl_sp->GetChildMemberWithName(ConstString("_M_finish"), true));
2168
2169 ValueObjectSP start_p_sp, finish_p_sp, finish_offset_sp;
2170
2171 if (!m_start_sp || !m_finish_sp)
2172 return false;
2173
2174 start_p_sp = m_start_sp->GetChildMemberWithName(ConstString("_M_p"), true);
2175 finish_p_sp = m_finish_sp->GetChildMemberWithName(ConstString("_M_p"), true);
2176 finish_offset_sp = m_finish_sp->GetChildMemberWithName(ConstString("_M_offset"), true);
2177
2178 if (!start_p_sp || !finish_offset_sp || !finish_p_sp)
2179 return false;
2180
2181 m_base_data_address = start_p_sp->GetValueAsUnsigned(0);
2182 if (!m_base_data_address)
2183 return false;
2184
2185 lldb::addr_t end_data_address(finish_p_sp->GetValueAsUnsigned(0));
2186 if (!end_data_address)
2187 return false;
2188
2189 if (end_data_address < m_base_data_address)
2190 return false;
2191 else
2192 m_count = finish_offset_sp->GetValueAsUnsigned(0) + (end_data_address-m_base_data_address)*8;
2193
2194 return true;
2195}
2196
2197bool
2198lldb_private::formatters::LibstdcppVectorBoolSyntheticFrontEnd::MightHaveChildren ()
2199{
2200 return true;
2201}
2202
2203size_t
2204lldb_private::formatters::LibstdcppVectorBoolSyntheticFrontEnd::GetIndexOfChildWithName (const ConstString &name)
2205{
2206 if (!m_count || !m_base_data_address)
2207 return UINT32_MAX;
2208 const char* item_name = name.GetCString();
2209 uint32_t idx = ExtractIndexFromString(item_name);
2210 if (idx < UINT32_MAX && idx >= CalculateNumChildren())
2211 return UINT32_MAX;
2212 return idx;
2213}
2214
2215lldb_private::formatters::LibstdcppVectorBoolSyntheticFrontEnd::~LibstdcppVectorBoolSyntheticFrontEnd ()
2216{}
2217
2218SyntheticChildrenFrontEnd*
2219lldb_private::formatters::LibstdcppVectorBoolSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP valobj_sp)
2220{
2221 if (!valobj_sp)
2222 return NULL;
2223 return (new LibstdcppVectorBoolSyntheticFrontEnd(valobj_sp));
2224}
2225
Enrico Granatacaaf0102012-09-04 18:48:21 +00002226template bool
Enrico Granataf91e78f2012-09-13 18:27:09 +00002227lldb_private::formatters::NSDictionarySummaryProvider<true> (ValueObject&, Stream&) ;
Enrico Granatacaaf0102012-09-04 18:48:21 +00002228
2229template bool
Enrico Granataf91e78f2012-09-13 18:27:09 +00002230lldb_private::formatters::NSDictionarySummaryProvider<false> (ValueObject&, Stream&) ;
Enrico Granatacaaf0102012-09-04 18:48:21 +00002231
2232template bool
Enrico Granataf91e78f2012-09-13 18:27:09 +00002233lldb_private::formatters::NSDataSummaryProvider<true> (ValueObject&, Stream&) ;
2234
2235template bool
2236lldb_private::formatters::NSDataSummaryProvider<false> (ValueObject&, Stream&) ;
Enrico Granatadb054912012-10-29 21:18:03 +00002237
2238template bool
2239lldb_private::formatters::ObjCSELSummaryProvider<true> (ValueObject&, Stream&) ;
2240
2241template bool
2242lldb_private::formatters::ObjCSELSummaryProvider<false> (ValueObject&, Stream&) ;