blob: 8fb75289d35683e9ca119f74bdd09df3c9de4b1e [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{
Enrico Granata1f9df782013-02-15 00:06:04 +00001178 lldb::ValueObjectSP valobj_sp;
Enrico Granatadb054912012-10-29 21:18:03 +00001179
Enrico Granata1f9df782013-02-15 00:06:04 +00001180 if (!valobj.GetClangAST())
Enrico Granatadb054912012-10-29 21:18:03 +00001181 return false;
Enrico Granata1f9df782013-02-15 00:06:04 +00001182 void* char_opaque_type = valobj.GetClangAST()->CharTy.getAsOpaquePtr();
1183 if (!char_opaque_type)
1184 return false;
1185 ClangASTType charstar(valobj.GetClangAST(),ClangASTType::GetPointerType(valobj.GetClangAST(), char_opaque_type));
1186
Enrico Granatadb054912012-10-29 21:18:03 +00001187 ExecutionContext exe_ctx(valobj.GetExecutionContextRef());
1188
Enrico Granata1f9df782013-02-15 00:06:04 +00001189 if (is_sel_ptr)
1190 {
1191 lldb::addr_t data_address = valobj.GetValueAsUnsigned(LLDB_INVALID_ADDRESS);
1192 if (data_address == LLDB_INVALID_ADDRESS)
1193 return false;
1194 valobj_sp = ValueObject::CreateValueObjectFromAddress("text", data_address, exe_ctx, charstar);
1195 }
1196 else
1197 {
1198 DataExtractor data;
1199 valobj.GetData(data);
1200 valobj_sp = ValueObject::CreateValueObjectFromData("text", data, exe_ctx, charstar);
1201 }
Enrico Granatadb054912012-10-29 21:18:03 +00001202
Enrico Granata1f9df782013-02-15 00:06:04 +00001203 if (!valobj_sp)
1204 return false;
Enrico Granatadb054912012-10-29 21:18:03 +00001205
1206 stream.Printf("%s",valobj_sp->GetSummaryAsCString());
1207 return true;
1208}
1209
Enrico Granataf91e78f2012-09-13 18:27:09 +00001210lldb_private::formatters::NSArrayMSyntheticFrontEnd::NSArrayMSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp) :
1211SyntheticChildrenFrontEnd(*valobj_sp.get()),
1212m_exe_ctx_ref(),
1213m_ptr_size(8),
1214m_data_32(NULL),
1215m_data_64(NULL)
1216{
Enrico Granata247da332012-10-04 21:04:46 +00001217 if (valobj_sp)
Enrico Granataf91e78f2012-09-13 18:27:09 +00001218 {
Enrico Granata247da332012-10-04 21:04:46 +00001219 m_id_type = ClangASTType(valobj_sp->GetClangAST(),valobj_sp->GetClangAST()->ObjCBuiltinIdTy.getAsOpaquePtr());
1220 Update();
Enrico Granataf91e78f2012-09-13 18:27:09 +00001221 }
Enrico Granataf91e78f2012-09-13 18:27:09 +00001222}
1223
Greg Clayton36da2aa2013-01-25 18:06:21 +00001224size_t
Enrico Granataf91e78f2012-09-13 18:27:09 +00001225lldb_private::formatters::NSArrayMSyntheticFrontEnd::CalculateNumChildren ()
1226{
1227 if (m_data_32)
1228 return m_data_32->_used;
1229 if (m_data_64)
1230 return m_data_64->_used;
1231 return 0;
1232}
1233
1234lldb::ValueObjectSP
Greg Clayton36da2aa2013-01-25 18:06:21 +00001235lldb_private::formatters::NSArrayMSyntheticFrontEnd::GetChildAtIndex (size_t idx)
Enrico Granataf91e78f2012-09-13 18:27:09 +00001236{
1237 if (!m_data_32 && !m_data_64)
1238 return lldb::ValueObjectSP();
1239 if (idx >= CalculateNumChildren())
1240 return lldb::ValueObjectSP();
1241 lldb::addr_t object_at_idx = (m_data_32 ? m_data_32->_data : m_data_64->_data);
1242 object_at_idx += (idx * m_ptr_size);
1243 StreamString idx_name;
Greg Clayton36da2aa2013-01-25 18:06:21 +00001244 idx_name.Printf("[%zu]",idx);
Enrico Granataf91e78f2012-09-13 18:27:09 +00001245 lldb::ValueObjectSP retval_sp = ValueObject::CreateValueObjectFromAddress(idx_name.GetData(),
1246 object_at_idx,
1247 m_exe_ctx_ref,
1248 m_id_type);
1249 m_children.push_back(retval_sp);
1250 return retval_sp;
1251}
1252
1253bool
1254lldb_private::formatters::NSArrayMSyntheticFrontEnd::Update()
1255{
1256 m_children.clear();
Enrico Granata247da332012-10-04 21:04:46 +00001257 ValueObjectSP valobj_sp = m_backend.GetSP();
1258 m_ptr_size = 0;
1259 delete m_data_32;
1260 m_data_32 = NULL;
1261 delete m_data_64;
1262 m_data_64 = NULL;
1263 if (valobj_sp->IsDynamic())
1264 valobj_sp = valobj_sp->GetStaticValue();
1265 if (!valobj_sp)
1266 return false;
1267 m_exe_ctx_ref = valobj_sp->GetExecutionContextRef();
1268 Error error;
1269 if (valobj_sp->IsPointerType())
1270 {
1271 valobj_sp = valobj_sp->Dereference(error);
1272 if (error.Fail() || !valobj_sp)
1273 return false;
1274 }
1275 error.Clear();
1276 lldb::ProcessSP process_sp(valobj_sp->GetProcessSP());
1277 if (!process_sp)
1278 return false;
1279 m_ptr_size = process_sp->GetAddressByteSize();
1280 uint64_t data_location = valobj_sp->GetAddressOf() + m_ptr_size;
1281 if (m_ptr_size == 4)
1282 {
1283 m_data_32 = new DataDescriptor_32();
1284 process_sp->ReadMemory (data_location, m_data_32, sizeof(DataDescriptor_32), error);
1285 }
1286 else
1287 {
1288 m_data_64 = new DataDescriptor_64();
1289 process_sp->ReadMemory (data_location, m_data_64, sizeof(DataDescriptor_64), error);
1290 }
1291 if (error.Fail())
1292 return false;
Enrico Granataf91e78f2012-09-13 18:27:09 +00001293 return false;
1294}
1295
Enrico Granata800332c2012-10-23 19:54:09 +00001296bool
1297lldb_private::formatters::NSArrayMSyntheticFrontEnd::MightHaveChildren ()
1298{
Enrico Granataf3c10482012-12-10 19:55:53 +00001299 return true;
Enrico Granata800332c2012-10-23 19:54:09 +00001300}
1301
Enrico Granataf91e78f2012-09-13 18:27:09 +00001302static uint32_t
1303ExtractIndexFromString (const char* item_name)
1304{
1305 if (!item_name || !*item_name)
1306 return UINT32_MAX;
1307 if (*item_name != '[')
1308 return UINT32_MAX;
1309 item_name++;
1310 uint32_t idx = 0;
1311 while(*item_name)
1312 {
1313 char x = *item_name;
1314 if (x == ']')
1315 break;
1316 if (x < '0' || x > '9')
1317 return UINT32_MAX;
1318 idx = 10*idx + (x-'0');
1319 item_name++;
1320 }
1321 return idx;
1322}
1323
Enrico Granataf509c5e2013-01-28 23:47:25 +00001324size_t
Enrico Granataf91e78f2012-09-13 18:27:09 +00001325lldb_private::formatters::NSArrayMSyntheticFrontEnd::GetIndexOfChildWithName (const ConstString &name)
1326{
1327 if (!m_data_32 && !m_data_64)
1328 return UINT32_MAX;
1329 const char* item_name = name.GetCString();
1330 uint32_t idx = ExtractIndexFromString(item_name);
1331 if (idx < UINT32_MAX && idx >= CalculateNumChildren())
1332 return UINT32_MAX;
1333 return idx;
1334}
1335
1336lldb_private::formatters::NSArrayMSyntheticFrontEnd::~NSArrayMSyntheticFrontEnd ()
1337{
1338 delete m_data_32;
1339 m_data_32 = NULL;
1340 delete m_data_64;
1341 m_data_64 = NULL;
1342}
1343
1344lldb_private::formatters::NSArrayISyntheticFrontEnd::NSArrayISyntheticFrontEnd (lldb::ValueObjectSP valobj_sp) :
1345SyntheticChildrenFrontEnd(*valobj_sp.get()),
1346m_exe_ctx_ref(),
1347m_ptr_size(8),
1348m_items(0),
1349m_data_ptr(0)
1350{
Enrico Granata247da332012-10-04 21:04:46 +00001351 if (valobj_sp)
Enrico Granataf91e78f2012-09-13 18:27:09 +00001352 {
Enrico Granata247da332012-10-04 21:04:46 +00001353 m_id_type = ClangASTType(valobj_sp->GetClangAST(),valobj_sp->GetClangAST()->ObjCBuiltinIdTy.getAsOpaquePtr());
1354 Update();
Enrico Granataf91e78f2012-09-13 18:27:09 +00001355 }
Enrico Granataf91e78f2012-09-13 18:27:09 +00001356}
1357
1358lldb_private::formatters::NSArrayISyntheticFrontEnd::~NSArrayISyntheticFrontEnd ()
1359{
1360}
1361
Enrico Granataf509c5e2013-01-28 23:47:25 +00001362size_t
Enrico Granataf91e78f2012-09-13 18:27:09 +00001363lldb_private::formatters::NSArrayISyntheticFrontEnd::GetIndexOfChildWithName (const ConstString &name)
1364{
1365 const char* item_name = name.GetCString();
1366 uint32_t idx = ExtractIndexFromString(item_name);
1367 if (idx < UINT32_MAX && idx >= CalculateNumChildren())
1368 return UINT32_MAX;
1369 return idx;
1370}
1371
Greg Clayton36da2aa2013-01-25 18:06:21 +00001372size_t
Enrico Granataf91e78f2012-09-13 18:27:09 +00001373lldb_private::formatters::NSArrayISyntheticFrontEnd::CalculateNumChildren ()
1374{
1375 return m_items;
1376}
1377
1378bool
1379lldb_private::formatters::NSArrayISyntheticFrontEnd::Update()
1380{
Enrico Granata247da332012-10-04 21:04:46 +00001381 m_ptr_size = 0;
1382 m_items = 0;
1383 m_data_ptr = 0;
Enrico Granataf91e78f2012-09-13 18:27:09 +00001384 m_children.clear();
Enrico Granata247da332012-10-04 21:04:46 +00001385 ValueObjectSP valobj_sp = m_backend.GetSP();
1386 if (valobj_sp->IsDynamic())
1387 valobj_sp = valobj_sp->GetStaticValue();
1388 if (!valobj_sp)
1389 return false;
1390 m_exe_ctx_ref = valobj_sp->GetExecutionContextRef();
1391 Error error;
1392 if (valobj_sp->IsPointerType())
1393 {
1394 valobj_sp = valobj_sp->Dereference(error);
1395 if (error.Fail() || !valobj_sp)
1396 return false;
1397 }
1398 error.Clear();
1399 lldb::ProcessSP process_sp(valobj_sp->GetProcessSP());
1400 if (!process_sp)
1401 return false;
1402 m_ptr_size = process_sp->GetAddressByteSize();
1403 uint64_t data_location = valobj_sp->GetAddressOf() + m_ptr_size;
1404 m_items = process_sp->ReadPointerFromMemory(data_location, error);
1405 if (error.Fail())
1406 return false;
1407 m_data_ptr = data_location+m_ptr_size;
Enrico Granataf91e78f2012-09-13 18:27:09 +00001408 return false;
1409}
1410
Enrico Granata800332c2012-10-23 19:54:09 +00001411bool
1412lldb_private::formatters::NSArrayISyntheticFrontEnd::MightHaveChildren ()
1413{
Enrico Granataf3c10482012-12-10 19:55:53 +00001414 return true;
Enrico Granata800332c2012-10-23 19:54:09 +00001415}
1416
Enrico Granataf91e78f2012-09-13 18:27:09 +00001417lldb::ValueObjectSP
Greg Clayton36da2aa2013-01-25 18:06:21 +00001418lldb_private::formatters::NSArrayISyntheticFrontEnd::GetChildAtIndex (size_t idx)
Enrico Granataf91e78f2012-09-13 18:27:09 +00001419{
1420 if (idx >= CalculateNumChildren())
1421 return lldb::ValueObjectSP();
1422 lldb::addr_t object_at_idx = m_data_ptr;
1423 object_at_idx += (idx * m_ptr_size);
1424 ProcessSP process_sp = m_exe_ctx_ref.GetProcessSP();
1425 if (!process_sp)
1426 return lldb::ValueObjectSP();
1427 Error error;
1428 object_at_idx = process_sp->ReadPointerFromMemory(object_at_idx, error);
1429 if (error.Fail())
1430 return lldb::ValueObjectSP();
1431 StreamString expr;
Daniel Malea5f35a4b2012-11-29 21:49:15 +00001432 expr.Printf("(id)%" PRIu64,object_at_idx);
Enrico Granataf91e78f2012-09-13 18:27:09 +00001433 StreamString idx_name;
Greg Clayton36da2aa2013-01-25 18:06:21 +00001434 idx_name.Printf("[%zu]",idx);
Enrico Granataf91e78f2012-09-13 18:27:09 +00001435 lldb::ValueObjectSP retval_sp = ValueObject::CreateValueObjectFromExpression(idx_name.GetData(), expr.GetData(), m_exe_ctx_ref);
1436 m_children.push_back(retval_sp);
1437 return retval_sp;
1438}
1439
1440SyntheticChildrenFrontEnd* lldb_private::formatters::NSArraySyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP valobj_sp)
1441{
1442 lldb::ProcessSP process_sp (valobj_sp->GetProcessSP());
1443 if (!process_sp)
1444 return NULL;
1445 ObjCLanguageRuntime *runtime = (ObjCLanguageRuntime*)process_sp->GetLanguageRuntime(lldb::eLanguageTypeObjC);
1446 if (!runtime)
1447 return NULL;
1448
1449 if (!valobj_sp->IsPointerType())
1450 {
1451 Error error;
1452 valobj_sp = valobj_sp->AddressOf(error);
1453 if (error.Fail() || !valobj_sp)
1454 return NULL;
1455 }
1456
1457 ObjCLanguageRuntime::ClassDescriptorSP descriptor(runtime->GetClassDescriptor(*valobj_sp.get()));
1458
1459 if (!descriptor.get() || !descriptor->IsValid())
1460 return NULL;
1461
1462 const char* class_name = descriptor->GetClassName().GetCString();
Enrico Granata7685a562012-09-29 00:47:43 +00001463
1464 if (!class_name || !*class_name)
1465 return NULL;
1466
Enrico Granataf91e78f2012-09-13 18:27:09 +00001467 if (!strcmp(class_name,"__NSArrayI"))
1468 {
1469 return (new NSArrayISyntheticFrontEnd(valobj_sp));
1470 }
1471 else if (!strcmp(class_name,"__NSArrayM"))
1472 {
1473 return (new NSArrayMSyntheticFrontEnd(valobj_sp));
1474 }
1475 else
1476 {
1477 return (new NSArrayCodeRunningSyntheticFrontEnd(valobj_sp));
1478 }
1479}
1480
1481lldb_private::formatters::NSArrayCodeRunningSyntheticFrontEnd::NSArrayCodeRunningSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp) :
1482SyntheticChildrenFrontEnd(*valobj_sp.get())
1483{}
1484
Greg Clayton36da2aa2013-01-25 18:06:21 +00001485size_t
Enrico Granataf91e78f2012-09-13 18:27:09 +00001486lldb_private::formatters::NSArrayCodeRunningSyntheticFrontEnd::CalculateNumChildren ()
1487{
Enrico Granataf91e78f2012-09-13 18:27:09 +00001488 uint64_t count = 0;
1489 if (ExtractValueFromObjCExpression(m_backend, "int", "count", count))
1490 return count;
1491 return 0;
1492}
1493
1494lldb::ValueObjectSP
Greg Clayton36da2aa2013-01-25 18:06:21 +00001495lldb_private::formatters::NSArrayCodeRunningSyntheticFrontEnd::GetChildAtIndex (size_t idx)
Enrico Granataf91e78f2012-09-13 18:27:09 +00001496{
1497 StreamString idx_name;
Greg Clayton36da2aa2013-01-25 18:06:21 +00001498 idx_name.Printf("[%zu]",idx);
Enrico Granataf91e78f2012-09-13 18:27:09 +00001499 lldb::ValueObjectSP valobj_sp = CallSelectorOnObject(m_backend,"id","objectAtIndex:",idx);
1500 if (valobj_sp)
1501 valobj_sp->SetName(ConstString(idx_name.GetData()));
1502 return valobj_sp;
1503}
1504
1505bool
1506lldb_private::formatters::NSArrayCodeRunningSyntheticFrontEnd::Update()
1507{
1508 return false;
1509}
1510
Enrico Granata800332c2012-10-23 19:54:09 +00001511bool
1512lldb_private::formatters::NSArrayCodeRunningSyntheticFrontEnd::MightHaveChildren ()
1513{
Enrico Granataf3c10482012-12-10 19:55:53 +00001514 return true;
Enrico Granata800332c2012-10-23 19:54:09 +00001515}
1516
Enrico Granataf509c5e2013-01-28 23:47:25 +00001517size_t
Enrico Granataf91e78f2012-09-13 18:27:09 +00001518lldb_private::formatters::NSArrayCodeRunningSyntheticFrontEnd::GetIndexOfChildWithName (const ConstString &name)
1519{
1520 return 0;
1521}
1522
1523lldb_private::formatters::NSArrayCodeRunningSyntheticFrontEnd::~NSArrayCodeRunningSyntheticFrontEnd ()
1524{}
1525
Enrico Granata3a08fd12012-09-18 17:43:16 +00001526SyntheticChildrenFrontEnd* lldb_private::formatters::NSDictionarySyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP valobj_sp)
1527{
1528
1529 lldb::ProcessSP process_sp (valobj_sp->GetProcessSP());
1530 if (!process_sp)
1531 return NULL;
1532 ObjCLanguageRuntime *runtime = (ObjCLanguageRuntime*)process_sp->GetLanguageRuntime(lldb::eLanguageTypeObjC);
1533 if (!runtime)
1534 return NULL;
1535
1536 if (!valobj_sp->IsPointerType())
1537 {
1538 Error error;
1539 valobj_sp = valobj_sp->AddressOf(error);
1540 if (error.Fail() || !valobj_sp)
1541 return NULL;
1542 }
1543
1544 ObjCLanguageRuntime::ClassDescriptorSP descriptor(runtime->GetClassDescriptor(*valobj_sp.get()));
1545
1546 if (!descriptor.get() || !descriptor->IsValid())
1547 return NULL;
1548
1549 const char* class_name = descriptor->GetClassName().GetCString();
Enrico Granata7685a562012-09-29 00:47:43 +00001550
1551 if (!class_name || !*class_name)
1552 return NULL;
1553
Enrico Granata3a08fd12012-09-18 17:43:16 +00001554 if (!strcmp(class_name,"__NSDictionaryI"))
1555 {
1556 return (new NSDictionaryISyntheticFrontEnd(valobj_sp));
1557 }
1558 else if (!strcmp(class_name,"__NSDictionaryM"))
1559 {
1560 return (new NSDictionaryMSyntheticFrontEnd(valobj_sp));
1561 }
1562 else
1563 {
1564 return (new NSDictionaryCodeRunningSyntheticFrontEnd(valobj_sp));
1565 }
1566}
1567
1568lldb_private::formatters::NSDictionaryCodeRunningSyntheticFrontEnd::NSDictionaryCodeRunningSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp) :
1569SyntheticChildrenFrontEnd(*valobj_sp.get())
1570{}
1571
Greg Clayton36da2aa2013-01-25 18:06:21 +00001572size_t
Enrico Granata3a08fd12012-09-18 17:43:16 +00001573lldb_private::formatters::NSDictionaryCodeRunningSyntheticFrontEnd::CalculateNumChildren ()
1574{
1575 uint64_t count = 0;
1576 if (ExtractValueFromObjCExpression(m_backend, "int", "count", count))
1577 return count;
1578 return 0;
1579}
1580
1581lldb::ValueObjectSP
Greg Clayton36da2aa2013-01-25 18:06:21 +00001582lldb_private::formatters::NSDictionaryCodeRunningSyntheticFrontEnd::GetChildAtIndex (size_t idx)
Enrico Granata3a08fd12012-09-18 17:43:16 +00001583{
1584 StreamString idx_name;
Greg Clayton36da2aa2013-01-25 18:06:21 +00001585 idx_name.Printf("[%zu]",idx);
Enrico Granata3a08fd12012-09-18 17:43:16 +00001586 StreamString valobj_expr_path;
1587 m_backend.GetExpressionPath(valobj_expr_path, false);
1588 StreamString key_fetcher_expr;
Greg Clayton36da2aa2013-01-25 18:06:21 +00001589 key_fetcher_expr.Printf("(id)[(NSArray*)[%s allKeys] objectAtIndex:%zu]",valobj_expr_path.GetData(),idx);
Enrico Granata3a08fd12012-09-18 17:43:16 +00001590 StreamString value_fetcher_expr;
1591 value_fetcher_expr.Printf("(id)[%s objectForKey:%s]",valobj_expr_path.GetData(),key_fetcher_expr.GetData());
1592 StreamString object_fetcher_expr;
Enrico Granatafd3d28d2012-10-01 21:49:10 +00001593 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 +00001594 lldb::ValueObjectSP child_sp;
1595 m_backend.GetTargetSP()->EvaluateExpression(object_fetcher_expr.GetData(), m_backend.GetFrameSP().get(), child_sp,
Jim Ingham47beabb2012-10-16 21:41:58 +00001596 EvaluateExpressionOptions().SetKeepInMemory(true));
Enrico Granata3a08fd12012-09-18 17:43:16 +00001597 if (child_sp)
1598 child_sp->SetName(ConstString(idx_name.GetData()));
1599 return child_sp;
1600}
1601
1602bool
1603lldb_private::formatters::NSDictionaryCodeRunningSyntheticFrontEnd::Update()
1604{
1605 return false;
1606}
1607
Enrico Granata800332c2012-10-23 19:54:09 +00001608bool
1609lldb_private::formatters::NSDictionaryCodeRunningSyntheticFrontEnd::MightHaveChildren ()
1610{
Enrico Granataf3c10482012-12-10 19:55:53 +00001611 return true;
Enrico Granata800332c2012-10-23 19:54:09 +00001612}
1613
Enrico Granataf509c5e2013-01-28 23:47:25 +00001614size_t
Enrico Granata3a08fd12012-09-18 17:43:16 +00001615lldb_private::formatters::NSDictionaryCodeRunningSyntheticFrontEnd::GetIndexOfChildWithName (const ConstString &name)
1616{
1617 return 0;
1618}
1619
1620lldb_private::formatters::NSDictionaryCodeRunningSyntheticFrontEnd::~NSDictionaryCodeRunningSyntheticFrontEnd ()
1621{}
1622
1623lldb_private::formatters::NSDictionaryISyntheticFrontEnd::NSDictionaryISyntheticFrontEnd (lldb::ValueObjectSP valobj_sp) :
1624 SyntheticChildrenFrontEnd(*valobj_sp.get()),
1625 m_exe_ctx_ref(),
1626 m_ptr_size(8),
1627 m_data_32(NULL),
1628 m_data_64(NULL)
1629{
Enrico Granataa787c1a2012-10-04 21:46:06 +00001630 if (valobj_sp)
1631 Update();
Enrico Granata3a08fd12012-09-18 17:43:16 +00001632}
1633
1634lldb_private::formatters::NSDictionaryISyntheticFrontEnd::~NSDictionaryISyntheticFrontEnd ()
1635{
1636 delete m_data_32;
1637 m_data_32 = NULL;
1638 delete m_data_64;
1639 m_data_64 = NULL;
1640}
1641
Enrico Granataf509c5e2013-01-28 23:47:25 +00001642size_t
Enrico Granata3a08fd12012-09-18 17:43:16 +00001643lldb_private::formatters::NSDictionaryISyntheticFrontEnd::GetIndexOfChildWithName (const ConstString &name)
1644{
1645 const char* item_name = name.GetCString();
1646 uint32_t idx = ExtractIndexFromString(item_name);
1647 if (idx < UINT32_MAX && idx >= CalculateNumChildren())
1648 return UINT32_MAX;
1649 return idx;
1650}
1651
Greg Clayton36da2aa2013-01-25 18:06:21 +00001652size_t
Enrico Granata3a08fd12012-09-18 17:43:16 +00001653lldb_private::formatters::NSDictionaryISyntheticFrontEnd::CalculateNumChildren ()
1654{
1655 if (!m_data_32 && !m_data_64)
1656 return 0;
1657 return (m_data_32 ? m_data_32->_used : m_data_64->_used);
1658}
1659
1660bool
1661lldb_private::formatters::NSDictionaryISyntheticFrontEnd::Update()
1662{
1663 m_children.clear();
Enrico Granataa787c1a2012-10-04 21:46:06 +00001664 delete m_data_32;
1665 m_data_32 = NULL;
1666 delete m_data_64;
1667 m_data_64 = NULL;
1668 m_ptr_size = 0;
1669 ValueObjectSP valobj_sp = m_backend.GetSP();
1670 if (!valobj_sp)
1671 return false;
1672 if (valobj_sp->IsDynamic())
1673 valobj_sp = valobj_sp->GetStaticValue();
1674 if (!valobj_sp)
1675 return false;
1676 m_exe_ctx_ref = valobj_sp->GetExecutionContextRef();
1677 Error error;
1678 if (valobj_sp->IsPointerType())
1679 {
1680 valobj_sp = valobj_sp->Dereference(error);
1681 if (error.Fail() || !valobj_sp)
1682 return false;
1683 }
1684 error.Clear();
1685 lldb::ProcessSP process_sp(valobj_sp->GetProcessSP());
1686 if (!process_sp)
1687 return false;
1688 m_ptr_size = process_sp->GetAddressByteSize();
1689 uint64_t data_location = valobj_sp->GetAddressOf() + m_ptr_size;
1690 if (m_ptr_size == 4)
1691 {
1692 m_data_32 = new DataDescriptor_32();
1693 process_sp->ReadMemory (data_location, m_data_32, sizeof(DataDescriptor_32), error);
1694 }
1695 else
1696 {
1697 m_data_64 = new DataDescriptor_64();
1698 process_sp->ReadMemory (data_location, m_data_64, sizeof(DataDescriptor_64), error);
1699 }
1700 if (error.Fail())
1701 return false;
1702 m_data_ptr = data_location + m_ptr_size;
Enrico Granata3a08fd12012-09-18 17:43:16 +00001703 return false;
1704}
1705
Enrico Granata800332c2012-10-23 19:54:09 +00001706bool
1707lldb_private::formatters::NSDictionaryISyntheticFrontEnd::MightHaveChildren ()
1708{
Enrico Granataf3c10482012-12-10 19:55:53 +00001709 return true;
Enrico Granata800332c2012-10-23 19:54:09 +00001710}
1711
Enrico Granata3a08fd12012-09-18 17:43:16 +00001712lldb::ValueObjectSP
Greg Clayton36da2aa2013-01-25 18:06:21 +00001713lldb_private::formatters::NSDictionaryISyntheticFrontEnd::GetChildAtIndex (size_t idx)
Enrico Granata3a08fd12012-09-18 17:43:16 +00001714{
1715 uint32_t num_children = CalculateNumChildren();
1716
1717 if (idx >= num_children)
1718 return lldb::ValueObjectSP();
1719
1720 if (m_children.empty())
1721 {
1722 // do the scan phase
1723 lldb::addr_t key_at_idx = 0, val_at_idx = 0;
1724
1725 uint32_t tries = 0;
1726 uint32_t test_idx = 0;
1727
1728 while(tries < num_children)
1729 {
1730 key_at_idx = m_data_ptr + (2*test_idx * m_ptr_size);
1731 val_at_idx = key_at_idx + m_ptr_size;
1732 ProcessSP process_sp = m_exe_ctx_ref.GetProcessSP();
1733 if (!process_sp)
1734 return lldb::ValueObjectSP();
1735 Error error;
1736 key_at_idx = process_sp->ReadPointerFromMemory(key_at_idx, error);
1737 if (error.Fail())
1738 return lldb::ValueObjectSP();
1739 val_at_idx = process_sp->ReadPointerFromMemory(val_at_idx, error);
1740 if (error.Fail())
1741 return lldb::ValueObjectSP();
1742
1743 test_idx++;
1744
1745 if (!key_at_idx || !val_at_idx)
1746 continue;
1747 tries++;
1748
1749 DictionaryItemDescriptor descriptor = {key_at_idx,val_at_idx,lldb::ValueObjectSP()};
1750
1751 m_children.push_back(descriptor);
1752 }
1753 }
1754
1755 if (idx >= m_children.size()) // should never happen
1756 return lldb::ValueObjectSP();
1757
1758 DictionaryItemDescriptor &dict_item = m_children[idx];
1759 if (!dict_item.valobj_sp)
1760 {
1761 // make the new ValueObject
1762 StreamString expr;
Daniel Malea5f35a4b2012-11-29 21:49:15 +00001763 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 +00001764 StreamString idx_name;
Greg Clayton36da2aa2013-01-25 18:06:21 +00001765 idx_name.Printf("[%zu]",idx);
Enrico Granata3a08fd12012-09-18 17:43:16 +00001766 dict_item.valobj_sp = ValueObject::CreateValueObjectFromExpression(idx_name.GetData(), expr.GetData(), m_exe_ctx_ref);
1767 }
1768 return dict_item.valobj_sp;
1769}
1770
1771lldb_private::formatters::NSDictionaryMSyntheticFrontEnd::NSDictionaryMSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp) :
1772 SyntheticChildrenFrontEnd(*valobj_sp.get()),
1773 m_exe_ctx_ref(),
1774 m_ptr_size(8),
1775 m_data_32(NULL),
1776 m_data_64(NULL)
1777{
Enrico Granataa787c1a2012-10-04 21:46:06 +00001778 if (valobj_sp)
1779 Update ();
Enrico Granata3a08fd12012-09-18 17:43:16 +00001780}
1781
1782lldb_private::formatters::NSDictionaryMSyntheticFrontEnd::~NSDictionaryMSyntheticFrontEnd ()
1783{
1784 delete m_data_32;
1785 m_data_32 = NULL;
1786 delete m_data_64;
1787 m_data_64 = NULL;
1788}
1789
Enrico Granataf509c5e2013-01-28 23:47:25 +00001790size_t
Enrico Granata3a08fd12012-09-18 17:43:16 +00001791lldb_private::formatters::NSDictionaryMSyntheticFrontEnd::GetIndexOfChildWithName (const ConstString &name)
1792{
1793 const char* item_name = name.GetCString();
1794 uint32_t idx = ExtractIndexFromString(item_name);
1795 if (idx < UINT32_MAX && idx >= CalculateNumChildren())
1796 return UINT32_MAX;
1797 return idx;
1798}
1799
Greg Clayton36da2aa2013-01-25 18:06:21 +00001800size_t
Enrico Granata3a08fd12012-09-18 17:43:16 +00001801lldb_private::formatters::NSDictionaryMSyntheticFrontEnd::CalculateNumChildren ()
1802{
1803 if (!m_data_32 && !m_data_64)
1804 return 0;
1805 return (m_data_32 ? m_data_32->_used : m_data_64->_used);
1806}
1807
1808bool
1809lldb_private::formatters::NSDictionaryMSyntheticFrontEnd::Update()
1810{
1811 m_children.clear();
Enrico Granataa787c1a2012-10-04 21:46:06 +00001812 ValueObjectSP valobj_sp = m_backend.GetSP();
1813 m_ptr_size = 0;
1814 delete m_data_32;
1815 m_data_32 = NULL;
1816 delete m_data_64;
1817 m_data_64 = NULL;
1818 if (!valobj_sp)
1819 return false;
1820 if (valobj_sp->IsDynamic())
1821 valobj_sp = valobj_sp->GetStaticValue();
1822 if (!valobj_sp)
1823 return false;
1824 m_exe_ctx_ref = valobj_sp->GetExecutionContextRef();
1825 Error error;
1826 if (valobj_sp->IsPointerType())
1827 {
1828 valobj_sp = valobj_sp->Dereference(error);
1829 if (error.Fail() || !valobj_sp)
1830 return false;
1831 }
1832 error.Clear();
1833 lldb::ProcessSP process_sp(valobj_sp->GetProcessSP());
1834 if (!process_sp)
1835 return false;
1836 m_ptr_size = process_sp->GetAddressByteSize();
1837 uint64_t data_location = valobj_sp->GetAddressOf() + m_ptr_size;
1838 if (m_ptr_size == 4)
1839 {
1840 m_data_32 = new DataDescriptor_32();
1841 process_sp->ReadMemory (data_location, m_data_32, sizeof(DataDescriptor_32), error);
1842 }
1843 else
1844 {
1845 m_data_64 = new DataDescriptor_64();
1846 process_sp->ReadMemory (data_location, m_data_64, sizeof(DataDescriptor_64), error);
1847 }
1848 if (error.Fail())
1849 return false;
Enrico Granata3a08fd12012-09-18 17:43:16 +00001850 return false;
1851}
1852
Enrico Granata800332c2012-10-23 19:54:09 +00001853bool
1854lldb_private::formatters::NSDictionaryMSyntheticFrontEnd::MightHaveChildren ()
1855{
Enrico Granataf3c10482012-12-10 19:55:53 +00001856 return true;
Enrico Granata800332c2012-10-23 19:54:09 +00001857}
1858
Enrico Granata3a08fd12012-09-18 17:43:16 +00001859lldb::ValueObjectSP
Greg Clayton36da2aa2013-01-25 18:06:21 +00001860lldb_private::formatters::NSDictionaryMSyntheticFrontEnd::GetChildAtIndex (size_t idx)
Enrico Granata3a08fd12012-09-18 17:43:16 +00001861{
1862 lldb::addr_t m_keys_ptr = (m_data_32 ? m_data_32->_keys_addr : m_data_64->_keys_addr);
1863 lldb::addr_t m_values_ptr = (m_data_32 ? m_data_32->_objs_addr : m_data_64->_objs_addr);
1864
1865 uint32_t num_children = CalculateNumChildren();
1866
1867 if (idx >= num_children)
1868 return lldb::ValueObjectSP();
1869
1870 if (m_children.empty())
1871 {
1872 // do the scan phase
1873 lldb::addr_t key_at_idx = 0, val_at_idx = 0;
1874
1875 uint32_t tries = 0;
1876 uint32_t test_idx = 0;
1877
1878 while(tries < num_children)
1879 {
1880 key_at_idx = m_keys_ptr + (test_idx * m_ptr_size);
1881 val_at_idx = m_values_ptr + (test_idx * m_ptr_size);;
1882 ProcessSP process_sp = m_exe_ctx_ref.GetProcessSP();
1883 if (!process_sp)
1884 return lldb::ValueObjectSP();
1885 Error error;
1886 key_at_idx = process_sp->ReadPointerFromMemory(key_at_idx, error);
1887 if (error.Fail())
1888 return lldb::ValueObjectSP();
1889 val_at_idx = process_sp->ReadPointerFromMemory(val_at_idx, error);
1890 if (error.Fail())
1891 return lldb::ValueObjectSP();
1892
1893 test_idx++;
1894
1895 if (!key_at_idx || !val_at_idx)
1896 continue;
1897 tries++;
1898
1899 DictionaryItemDescriptor descriptor = {key_at_idx,val_at_idx,lldb::ValueObjectSP()};
1900
1901 m_children.push_back(descriptor);
1902 }
1903 }
1904
1905 if (idx >= m_children.size()) // should never happen
1906 return lldb::ValueObjectSP();
1907
1908 DictionaryItemDescriptor &dict_item = m_children[idx];
1909 if (!dict_item.valobj_sp)
1910 {
1911 // make the new ValueObject
1912 StreamString expr;
Daniel Malea5f35a4b2012-11-29 21:49:15 +00001913 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 +00001914 StreamString idx_name;
Greg Clayton36da2aa2013-01-25 18:06:21 +00001915 idx_name.Printf("[%zu]",idx);
Enrico Granata3a08fd12012-09-18 17:43:16 +00001916 dict_item.valobj_sp = ValueObject::CreateValueObjectFromExpression(idx_name.GetData(), expr.GetData(), m_exe_ctx_ref);
1917 }
1918 return dict_item.valobj_sp;
1919}
Enrico Granatacaaf0102012-09-04 18:48:21 +00001920
Enrico Granata689696c2013-02-04 22:54:42 +00001921lldb_private::formatters::LibcxxVectorBoolSyntheticFrontEnd::LibcxxVectorBoolSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp) :
1922 SyntheticChildrenFrontEnd(*valobj_sp.get()),
1923 m_exe_ctx_ref(),
1924 m_count(0),
1925 m_base_data_address(0),
1926 m_options()
1927 {
1928 if (valobj_sp)
1929 Update();
1930 m_options.SetCoerceToId(false)
1931 .SetUnwindOnError(true)
1932 .SetKeepInMemory(true)
1933 .SetUseDynamic(lldb::eDynamicCanRunTarget);
1934 }
1935
1936size_t
1937lldb_private::formatters::LibcxxVectorBoolSyntheticFrontEnd::CalculateNumChildren ()
1938{
1939 return m_count;
1940}
1941
1942lldb::ValueObjectSP
1943lldb_private::formatters::LibcxxVectorBoolSyntheticFrontEnd::GetChildAtIndex (size_t idx)
1944{
1945 if (idx >= m_count)
1946 return ValueObjectSP();
1947 if (m_base_data_address == 0 || m_count == 0)
1948 return ValueObjectSP();
1949 size_t byte_idx = (idx >> 3); // divide by 8 to get byte index
1950 size_t bit_index = (idx & 7); // efficient idx % 8 for bit index
1951 lldb::addr_t byte_location = m_base_data_address + byte_idx;
1952 ProcessSP process_sp(m_exe_ctx_ref.GetProcessSP());
1953 if (!process_sp)
1954 return ValueObjectSP();
1955 uint8_t byte = 0;
1956 uint8_t mask = 0;
1957 Error err;
1958 size_t bytes_read = process_sp->ReadMemory(byte_location, &byte, 1, err);
1959 if (err.Fail() || bytes_read == 0)
1960 return ValueObjectSP();
1961 switch (bit_index)
1962 {
1963 case 0:
1964 mask = 1; break;
1965 case 1:
1966 mask = 2; break;
1967 case 2:
1968 mask = 4; break;
1969 case 3:
1970 mask = 8; break;
1971 case 4:
1972 mask = 16; break;
1973 case 5:
1974 mask = 32; break;
1975 case 6:
1976 mask = 64; break;
1977 case 7:
1978 mask = 128; break;
1979 default:
1980 return ValueObjectSP();
1981 }
1982 bool bit_set = ((byte & mask) != 0);
1983 Target& target(process_sp->GetTarget());
1984 ValueObjectSP retval_sp;
1985 if (bit_set)
1986 target.EvaluateExpression("(bool)true", NULL, retval_sp);
1987 else
1988 target.EvaluateExpression("(bool)false", NULL, retval_sp);
1989 StreamString name; name.Printf("[%zu]",idx);
1990 if (retval_sp)
1991 retval_sp->SetName(ConstString(name.GetData()));
1992 return retval_sp;
1993}
1994
1995/*(std::__1::vector<std::__1::allocator<bool> >) vBool = {
1996 __begin_ = 0x00000001001000e0
1997 __size_ = 56
1998 __cap_alloc_ = {
1999 std::__1::__libcpp_compressed_pair_imp<unsigned long, std::__1::allocator<unsigned long> > = {
2000 __first_ = 1
2001 }
2002 }
2003}*/
2004
2005bool
2006lldb_private::formatters::LibcxxVectorBoolSyntheticFrontEnd::Update()
2007{
2008 ValueObjectSP valobj_sp = m_backend.GetSP();
2009 if (!valobj_sp)
2010 return false;
2011 if (valobj_sp->IsDynamic())
2012 valobj_sp = valobj_sp->GetStaticValue();
2013 if (!valobj_sp)
2014 return false;
2015 m_exe_ctx_ref = valobj_sp->GetExecutionContextRef();
2016 ValueObjectSP size_sp(valobj_sp->GetChildMemberWithName(ConstString("__size_"), true));
2017 if (!size_sp)
2018 return false;
2019 m_count = size_sp->GetValueAsUnsigned(0);
2020 if (!m_count)
2021 return true;
2022 ValueObjectSP begin_sp(valobj_sp->GetChildMemberWithName(ConstString("__begin_"), true));
2023 if (!begin_sp)
2024 {
2025 m_count = 0;
2026 return false;
2027 }
2028 m_base_data_address = begin_sp->GetValueAsUnsigned(0);
2029 if (!m_base_data_address)
2030 {
2031 m_count = 0;
2032 return false;
2033 }
2034 return true;
2035}
2036
2037bool
2038lldb_private::formatters::LibcxxVectorBoolSyntheticFrontEnd::MightHaveChildren ()
2039{
2040 return true;
2041}
2042
2043size_t
2044lldb_private::formatters::LibcxxVectorBoolSyntheticFrontEnd::GetIndexOfChildWithName (const ConstString &name)
2045{
2046 if (!m_count || !m_base_data_address)
2047 return UINT32_MAX;
2048 const char* item_name = name.GetCString();
2049 uint32_t idx = ExtractIndexFromString(item_name);
2050 if (idx < UINT32_MAX && idx >= CalculateNumChildren())
2051 return UINT32_MAX;
2052 return idx;
2053}
2054
2055lldb_private::formatters::LibcxxVectorBoolSyntheticFrontEnd::~LibcxxVectorBoolSyntheticFrontEnd ()
2056{}
2057
2058SyntheticChildrenFrontEnd*
2059lldb_private::formatters::LibcxxVectorBoolSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP valobj_sp)
2060{
2061 if (!valobj_sp)
2062 return NULL;
2063 return (new LibcxxVectorBoolSyntheticFrontEnd(valobj_sp));
2064}
2065
2066lldb_private::formatters::LibstdcppVectorBoolSyntheticFrontEnd::LibstdcppVectorBoolSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp) :
2067SyntheticChildrenFrontEnd(*valobj_sp.get()),
2068m_exe_ctx_ref(),
2069m_count(0),
2070m_base_data_address(0),
2071m_options()
2072{
2073 if (valobj_sp)
2074 Update();
2075 m_options.SetCoerceToId(false)
2076 .SetUnwindOnError(true)
2077 .SetKeepInMemory(true)
2078 .SetUseDynamic(lldb::eDynamicCanRunTarget);
2079}
2080
2081size_t
2082lldb_private::formatters::LibstdcppVectorBoolSyntheticFrontEnd::CalculateNumChildren ()
2083{
2084 return m_count;
2085}
2086
2087lldb::ValueObjectSP
2088lldb_private::formatters::LibstdcppVectorBoolSyntheticFrontEnd::GetChildAtIndex (size_t idx)
2089{
2090 if (idx >= m_count)
2091 return ValueObjectSP();
2092 if (m_base_data_address == 0 || m_count == 0)
2093 return ValueObjectSP();
2094 size_t byte_idx = (idx >> 3); // divide by 8 to get byte index
2095 size_t bit_index = (idx & 7); // efficient idx % 8 for bit index
2096 lldb::addr_t byte_location = m_base_data_address + byte_idx;
2097 ProcessSP process_sp(m_exe_ctx_ref.GetProcessSP());
2098 if (!process_sp)
2099 return ValueObjectSP();
2100 uint8_t byte = 0;
2101 uint8_t mask = 0;
2102 Error err;
2103 size_t bytes_read = process_sp->ReadMemory(byte_location, &byte, 1, err);
2104 if (err.Fail() || bytes_read == 0)
2105 return ValueObjectSP();
2106 switch (bit_index)
2107 {
2108 case 0:
2109 mask = 1; break;
2110 case 1:
2111 mask = 2; break;
2112 case 2:
2113 mask = 4; break;
2114 case 3:
2115 mask = 8; break;
2116 case 4:
2117 mask = 16; break;
2118 case 5:
2119 mask = 32; break;
2120 case 6:
2121 mask = 64; break;
2122 case 7:
2123 mask = 128; break;
2124 default:
2125 return ValueObjectSP();
2126 }
2127 bool bit_set = ((byte & mask) != 0);
2128 Target& target(process_sp->GetTarget());
2129 ValueObjectSP retval_sp;
2130 if (bit_set)
2131 target.EvaluateExpression("(bool)true", NULL, retval_sp);
2132 else
2133 target.EvaluateExpression("(bool)false", NULL, retval_sp);
2134 StreamString name; name.Printf("[%zu]",idx);
2135 if (retval_sp)
2136 retval_sp->SetName(ConstString(name.GetData()));
2137 return retval_sp;
2138}
2139
2140/*((std::vector<std::allocator<bool> >) vBool = {
2141 (std::_Bvector_base<std::allocator<bool> >) std::_Bvector_base<std::allocator<bool> > = {
2142 (std::_Bvector_base<std::allocator<bool> >::_Bvector_impl) _M_impl = {
2143 (std::_Bit_iterator) _M_start = {
2144 (std::_Bit_iterator_base) std::_Bit_iterator_base = {
2145 (_Bit_type *) _M_p = 0x0016b160
2146 (unsigned int) _M_offset = 0
2147 }
2148 }
2149 (std::_Bit_iterator) _M_finish = {
2150 (std::_Bit_iterator_base) std::_Bit_iterator_base = {
2151 (_Bit_type *) _M_p = 0x0016b16c
2152 (unsigned int) _M_offset = 16
2153 }
2154 }
2155 (_Bit_type *) _M_end_of_storage = 0x0016b170
2156 }
2157 }
2158 }
2159*/
2160
2161bool
2162lldb_private::formatters::LibstdcppVectorBoolSyntheticFrontEnd::Update()
2163{
2164 ValueObjectSP valobj_sp = m_backend.GetSP();
2165 if (!valobj_sp)
2166 return false;
2167 if (valobj_sp->IsDynamic())
2168 valobj_sp = valobj_sp->GetStaticValue();
2169 if (!valobj_sp)
2170 return false;
2171 m_exe_ctx_ref = valobj_sp->GetExecutionContextRef();
2172
2173 ValueObjectSP m_impl_sp(valobj_sp->GetChildMemberWithName(ConstString("_M_impl"), true));
2174 if (!m_impl_sp)
2175 return false;
2176
2177 ValueObjectSP m_start_sp(m_impl_sp->GetChildMemberWithName(ConstString("_M_start"), true));
2178 ValueObjectSP m_finish_sp(m_impl_sp->GetChildMemberWithName(ConstString("_M_finish"), true));
2179
2180 ValueObjectSP start_p_sp, finish_p_sp, finish_offset_sp;
2181
2182 if (!m_start_sp || !m_finish_sp)
2183 return false;
2184
2185 start_p_sp = m_start_sp->GetChildMemberWithName(ConstString("_M_p"), true);
2186 finish_p_sp = m_finish_sp->GetChildMemberWithName(ConstString("_M_p"), true);
2187 finish_offset_sp = m_finish_sp->GetChildMemberWithName(ConstString("_M_offset"), true);
2188
2189 if (!start_p_sp || !finish_offset_sp || !finish_p_sp)
2190 return false;
2191
2192 m_base_data_address = start_p_sp->GetValueAsUnsigned(0);
2193 if (!m_base_data_address)
2194 return false;
2195
2196 lldb::addr_t end_data_address(finish_p_sp->GetValueAsUnsigned(0));
2197 if (!end_data_address)
2198 return false;
2199
2200 if (end_data_address < m_base_data_address)
2201 return false;
2202 else
2203 m_count = finish_offset_sp->GetValueAsUnsigned(0) + (end_data_address-m_base_data_address)*8;
2204
2205 return true;
2206}
2207
2208bool
2209lldb_private::formatters::LibstdcppVectorBoolSyntheticFrontEnd::MightHaveChildren ()
2210{
2211 return true;
2212}
2213
2214size_t
2215lldb_private::formatters::LibstdcppVectorBoolSyntheticFrontEnd::GetIndexOfChildWithName (const ConstString &name)
2216{
2217 if (!m_count || !m_base_data_address)
2218 return UINT32_MAX;
2219 const char* item_name = name.GetCString();
2220 uint32_t idx = ExtractIndexFromString(item_name);
2221 if (idx < UINT32_MAX && idx >= CalculateNumChildren())
2222 return UINT32_MAX;
2223 return idx;
2224}
2225
2226lldb_private::formatters::LibstdcppVectorBoolSyntheticFrontEnd::~LibstdcppVectorBoolSyntheticFrontEnd ()
2227{}
2228
2229SyntheticChildrenFrontEnd*
2230lldb_private::formatters::LibstdcppVectorBoolSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP valobj_sp)
2231{
2232 if (!valobj_sp)
2233 return NULL;
2234 return (new LibstdcppVectorBoolSyntheticFrontEnd(valobj_sp));
2235}
2236
Enrico Granatacaaf0102012-09-04 18:48:21 +00002237template bool
Enrico Granataf91e78f2012-09-13 18:27:09 +00002238lldb_private::formatters::NSDictionarySummaryProvider<true> (ValueObject&, Stream&) ;
Enrico Granatacaaf0102012-09-04 18:48:21 +00002239
2240template bool
Enrico Granataf91e78f2012-09-13 18:27:09 +00002241lldb_private::formatters::NSDictionarySummaryProvider<false> (ValueObject&, Stream&) ;
Enrico Granatacaaf0102012-09-04 18:48:21 +00002242
2243template bool
Enrico Granataf91e78f2012-09-13 18:27:09 +00002244lldb_private::formatters::NSDataSummaryProvider<true> (ValueObject&, Stream&) ;
2245
2246template bool
2247lldb_private::formatters::NSDataSummaryProvider<false> (ValueObject&, Stream&) ;
Enrico Granatadb054912012-10-29 21:18:03 +00002248
2249template bool
2250lldb_private::formatters::ObjCSELSummaryProvider<true> (ValueObject&, Stream&) ;
2251
2252template bool
2253lldb_private::formatters::ObjCSELSummaryProvider<false> (ValueObject&, Stream&) ;