blob: dd49a9dd1cce1b88e2b9ad1e40bcff71be0142b7 [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);
160 sourceSize = bufferSPSize/(origin_encoding >> 2);
161 }
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
176 *data_ptr = 0;
Enrico Granatacd8cd612013-01-14 23:53:26 +0000177 data_ptr = (SourceDataType*)data.GetDataStart();
Enrico Granataf5545f92013-01-10 22:08:35 +0000178
Enrico Granata06d58b02013-01-11 02:44:00 +0000179 lldb::DataBufferSP utf8_data_buffer_sp;
180 UTF8* utf8_data_ptr = nullptr;
181 UTF8* utf8_data_end_ptr = nullptr;
Enrico Granatacd8cd612013-01-14 23:53:26 +0000182
Enrico Granataf5545f92013-01-10 22:08:35 +0000183 if (ConvertFunction)
Enrico Granata06d58b02013-01-11 02:44:00 +0000184 {
185 utf8_data_buffer_sp.reset(new DataBufferHeap(bufferSPSize,0));
186 utf8_data_ptr = (UTF8*)utf8_data_buffer_sp->GetBytes();
187 utf8_data_end_ptr = utf8_data_ptr + bufferSPSize;
Enrico Granataf5545f92013-01-10 22:08:35 +0000188 ConvertFunction ( (const SourceDataType**)&data_ptr, data_end_ptr, &utf8_data_ptr, utf8_data_end_ptr, lenientConversion );
Enrico Granata06d58b02013-01-11 02:44:00 +0000189 utf8_data_ptr = (UTF8*)utf8_data_buffer_sp->GetBytes(); // needed because the ConvertFunction will change the value of the data_ptr
190 }
Enrico Granataf5545f92013-01-10 22:08:35 +0000191 else
192 {
193 // just copy the pointers - the cast is necessary to make the compiler happy
194 // but this should only happen if we are reading UTF8 data
195 utf8_data_ptr = (UTF8*)data_ptr;
196 utf8_data_end_ptr = (UTF8*)data_end_ptr;
197 }
198
Enrico Granatab6985792013-01-12 01:00:22 +0000199 // since we tend to accept partial data (and even partially malformed data)
200 // we might end up with no NULL terminator before the end_ptr
201 // hence we need to take a slower route and ensure we stay within boundaries
Enrico Granataf5545f92013-01-10 22:08:35 +0000202 for (;utf8_data_ptr != utf8_data_end_ptr; utf8_data_ptr++)
203 {
204 if (!*utf8_data_ptr)
205 break;
206 stream.Printf("%c",*utf8_data_ptr);
207 }
Enrico Granatacd8cd612013-01-14 23:53:26 +0000208 }
209 if (quote != 0)
210 stream.Printf("%c",quote);
211 return true;
212}
213
214template<typename SourceDataType>
215static bool
216ReadUTFBufferAndDumpToStream (ConversionResult (*ConvertFunction) (const SourceDataType**,
217 const SourceDataType*,
218 UTF8**,
219 UTF8*,
220 ConversionFlags),
221 uint64_t location,
222 const ProcessSP& process_sp,
223 Stream& stream,
224 char prefix_token = '@',
225 char quote = '"',
226 int sourceSize = 0)
227{
228 if (location == 0 || location == LLDB_INVALID_ADDRESS)
229 return false;
230 if (!process_sp)
231 return false;
232
233 const int origin_encoding = 8*sizeof(SourceDataType);
234 if (origin_encoding != 8 && origin_encoding != 16 && origin_encoding != 32)
235 return false;
236 // if not UTF8, I need a conversion function to return proper UTF8
237 if (origin_encoding != 8 && !ConvertFunction)
238 return false;
239
240 if (sourceSize == 0)
241 sourceSize = process_sp->GetTarget().GetMaximumSizeOfStringSummary();
242 const int bufferSPSize = sourceSize * (origin_encoding >> 2);
243
244 Error error;
245 lldb::DataBufferSP buffer_sp(new DataBufferHeap(bufferSPSize,0));
246
247 if (!buffer_sp->GetBytes())
248 return false;
249
250 size_t data_read = process_sp->ReadMemoryFromInferior(location, (char*)buffer_sp->GetBytes(), bufferSPSize, error);
251 if (error.Fail() || data_read == 0)
252 {
253 stream.Printf("unable to read data");
Enrico Granataf5545f92013-01-10 22:08:35 +0000254 return true;
255 }
Enrico Granatacd8cd612013-01-14 23:53:26 +0000256
257 DataExtractor data(buffer_sp, process_sp->GetByteOrder(), process_sp->GetAddressByteSize());
258
259 return DumpUTFBufferToStream(ConvertFunction, data, stream, prefix_token, quote, sourceSize);
Enrico Granataf5545f92013-01-10 22:08:35 +0000260}
261
262bool
263lldb_private::formatters::Char16StringSummaryProvider (ValueObject& valobj, Stream& stream)
264{
265 ProcessSP process_sp = valobj.GetProcessSP();
266 if (!process_sp)
267 return false;
268
269 lldb::addr_t valobj_addr = valobj.GetValueAsUnsigned(0);
270
271 if (!valobj_addr)
272 return false;
273
Enrico Granatacd8cd612013-01-14 23:53:26 +0000274 if (!ReadUTFBufferAndDumpToStream<UTF16>(ConvertUTF16toUTF8,valobj_addr,
Enrico Granataf5545f92013-01-10 22:08:35 +0000275 process_sp,
276 stream,
Enrico Granatacd8cd612013-01-14 23:53:26 +0000277 'u'))
Enrico Granataf5545f92013-01-10 22:08:35 +0000278 {
279 stream.Printf("Summary Unavailable");
280 return true;
281 }
282
283 return true;
284}
285
286bool
287lldb_private::formatters::Char32StringSummaryProvider (ValueObject& valobj, Stream& stream)
288{
289 ProcessSP process_sp = valobj.GetProcessSP();
290 if (!process_sp)
291 return false;
292
293 lldb::addr_t valobj_addr = valobj.GetValueAsUnsigned(0);
294
295 if (!valobj_addr)
296 return false;
297
Enrico Granatacd8cd612013-01-14 23:53:26 +0000298 if (!ReadUTFBufferAndDumpToStream<UTF32>(ConvertUTF32toUTF8,valobj_addr,
Enrico Granataf5545f92013-01-10 22:08:35 +0000299 process_sp,
300 stream,
Enrico Granatacd8cd612013-01-14 23:53:26 +0000301 'U'))
Enrico Granataf5545f92013-01-10 22:08:35 +0000302 {
303 stream.Printf("Summary Unavailable");
304 return true;
305 }
306
307 return true;
308}
309
310bool
311lldb_private::formatters::WCharStringSummaryProvider (ValueObject& valobj, Stream& stream)
312{
Enrico Granata06d58b02013-01-11 02:44:00 +0000313 ProcessSP process_sp = valobj.GetProcessSP();
314 if (!process_sp)
315 return false;
316
Enrico Granatab6985792013-01-12 01:00:22 +0000317 lldb::addr_t data_addr = 0;
318
319 if (valobj.IsPointerType())
320 data_addr = valobj.GetValueAsUnsigned(0);
321 else if (valobj.IsArrayType())
322 data_addr = valobj.GetAddressOf();
Enrico Granata06d58b02013-01-11 02:44:00 +0000323
Enrico Granatab6985792013-01-12 01:00:22 +0000324 if (data_addr == 0 || data_addr == LLDB_INVALID_ADDRESS)
Enrico Granata06d58b02013-01-11 02:44:00 +0000325 return false;
326
327 clang::ASTContext* ast = valobj.GetClangAST();
328
329 if (!ast)
330 return false;
331
332 uint32_t wchar_size = ClangASTType::GetClangTypeBitWidth(ast, ClangASTType::GetBasicType(ast, lldb::eBasicTypeWChar).GetOpaqueQualType());
333
334 switch (wchar_size)
335 {
336 case 8:
337 // utf 8
Enrico Granatacd8cd612013-01-14 23:53:26 +0000338 return ReadUTFBufferAndDumpToStream<UTF8>(nullptr, data_addr,
Enrico Granata06d58b02013-01-11 02:44:00 +0000339 process_sp,
340 stream,
Enrico Granatacd8cd612013-01-14 23:53:26 +0000341 'L');
Enrico Granata06d58b02013-01-11 02:44:00 +0000342 case 16:
343 // utf 16
Enrico Granatacd8cd612013-01-14 23:53:26 +0000344 return ReadUTFBufferAndDumpToStream<UTF16>(ConvertUTF16toUTF8, data_addr,
Enrico Granata06d58b02013-01-11 02:44:00 +0000345 process_sp,
346 stream,
Enrico Granatacd8cd612013-01-14 23:53:26 +0000347 'L');
Enrico Granata06d58b02013-01-11 02:44:00 +0000348 case 32:
349 // utf 32
Enrico Granatacd8cd612013-01-14 23:53:26 +0000350 return ReadUTFBufferAndDumpToStream<UTF32>(ConvertUTF32toUTF8, data_addr,
Enrico Granata06d58b02013-01-11 02:44:00 +0000351 process_sp,
352 stream,
Enrico Granatacd8cd612013-01-14 23:53:26 +0000353 'L');
354 default:
355 stream.Printf("size for wchar_t is not valid");
356 return true;
357 }
358 return true;
359}
360
361bool
362lldb_private::formatters::Char16SummaryProvider (ValueObject& valobj, Stream& stream)
363{
364 DataExtractor data;
365 valobj.GetData(data);
366
367 std::string value;
368 valobj.GetValueAsCString(lldb::eFormatUnicode16, value);
369 if (!value.empty())
370 stream.Printf("%s ", value.c_str());
371
372 return DumpUTFBufferToStream<UTF16>(ConvertUTF16toUTF8,data,stream, 'u','\'',1);
373}
374
375bool
376lldb_private::formatters::Char32SummaryProvider (ValueObject& valobj, Stream& stream)
377{
378 DataExtractor data;
379 valobj.GetData(data);
380
381 std::string value;
382 valobj.GetValueAsCString(lldb::eFormatUnicode32, value);
383 if (!value.empty())
384 stream.Printf("%s ", value.c_str());
385
386 return DumpUTFBufferToStream<UTF32>(ConvertUTF32toUTF8,data,stream, 'U','\'',1);
387}
388
389bool
390lldb_private::formatters::WCharSummaryProvider (ValueObject& valobj, Stream& stream)
391{
392 DataExtractor data;
393 valobj.GetData(data);
394
395 clang::ASTContext* ast = valobj.GetClangAST();
396
397 if (!ast)
398 return false;
399
400 std::string value;
401
402 uint32_t wchar_size = ClangASTType::GetClangTypeBitWidth(ast, ClangASTType::GetBasicType(ast, lldb::eBasicTypeWChar).GetOpaqueQualType());
403
404 switch (wchar_size)
405 {
406 case 8:
407 // utf 8
408 valobj.GetValueAsCString(lldb::eFormatChar, value);
409 if (!value.empty())
410 stream.Printf("%s ", value.c_str());
411 return DumpUTFBufferToStream<UTF8>(nullptr,
412 data,
413 stream,
414 'L',
415 '\'',
416 1);
417 case 16:
418 // utf 16
419 valobj.GetValueAsCString(lldb::eFormatUnicode16, value);
420 if (!value.empty())
421 stream.Printf("%s ", value.c_str());
422 return DumpUTFBufferToStream<UTF16>(ConvertUTF16toUTF8,
423 data,
424 stream,
425 'L',
426 '\'',
427 1);
428 case 32:
429 // utf 32
430 valobj.GetValueAsCString(lldb::eFormatUnicode32, value);
431 if (!value.empty())
432 stream.Printf("%s ", value.c_str());
433 return DumpUTFBufferToStream<UTF32>(ConvertUTF32toUTF8,
434 data,
435 stream,
436 'L',
437 '\'',
438 1);
Enrico Granata06d58b02013-01-11 02:44:00 +0000439 default:
440 stream.Printf("size for wchar_t is not valid");
441 return true;
442 }
443 return true;
Enrico Granataf5545f92013-01-10 22:08:35 +0000444}
445
Enrico Granatab6985792013-01-12 01:00:22 +0000446// this function extracts information from a libcxx std::basic_string<>
447// irregardless of template arguments. it reports the size (in item count not bytes)
448// and the location in memory where the string data can be found
449static bool
450ExtractLibcxxStringInfo (ValueObject& valobj,
451 ValueObjectSP &location_sp,
452 uint64_t& size)
453{
454 ValueObjectSP D(valobj.GetChildAtIndexPath({0,0,0,0}));
455 if (!D)
456 return false;
457
458 ValueObjectSP size_mode(D->GetChildAtIndexPath({1,0,0}));
459 if (!size_mode)
460 return false;
461
462 uint64_t size_mode_value(size_mode->GetValueAsUnsigned(0));
463
464 if ((size_mode_value & 1) == 0) // this means the string is in short-mode and the data is stored inline
465 {
466 ValueObjectSP s(D->GetChildAtIndex(1, true));
467 if (!s)
468 return false;
469 size = ((size_mode_value >> 1) % 256);
470 location_sp = s->GetChildAtIndex(1, true);
471 return (location_sp.get() != nullptr);
472 }
473 else
474 {
475 ValueObjectSP l(D->GetChildAtIndex(0, true));
476 if (!l)
477 return false;
478 location_sp = l->GetChildAtIndex(2, true);
479 ValueObjectSP size_vo(l->GetChildAtIndex(1, true));
480 if (!size_vo || !location_sp)
481 return false;
482 size = size_vo->GetValueAsUnsigned(0);
483 return true;
484 }
485}
486
487bool
488lldb_private::formatters::LibcxxWStringSummaryProvider (ValueObject& valobj, Stream& stream)
489{
490 uint64_t size = 0;
491 ValueObjectSP location_sp((ValueObject*)nullptr);
492 if (!ExtractLibcxxStringInfo(valobj, location_sp, size))
493 return false;
494 if (size == 0)
495 {
496 stream.Printf("L\"\"");
497 return true;
498 }
499 if (!location_sp)
500 return false;
501 return WCharStringSummaryProvider(*location_sp.get(), stream);
502}
503
504bool
505lldb_private::formatters::LibcxxStringSummaryProvider (ValueObject& valobj, Stream& stream)
506{
507 uint64_t size = 0;
508 ValueObjectSP location_sp((ValueObject*)nullptr);
509 if (!ExtractLibcxxStringInfo(valobj, location_sp, size))
510 return false;
511 if (size == 0)
512 {
513 stream.Printf("\"\"");
514 return true;
515 }
516 if (!location_sp)
517 return false;
518 Error error;
519 location_sp->ReadPointedString(stream,
520 error,
521 0, // max length is decided by the settings
522 false); // do not honor array (terminates on first 0 byte even for a char[])
523 return error.Success();
524}
525
Enrico Granatacaaf0102012-09-04 18:48:21 +0000526template<bool name_entries>
527bool
Enrico Granataf91e78f2012-09-13 18:27:09 +0000528lldb_private::formatters::NSDictionarySummaryProvider (ValueObject& valobj, Stream& stream)
Enrico Granatacaaf0102012-09-04 18:48:21 +0000529{
530 ProcessSP process_sp = valobj.GetProcessSP();
531 if (!process_sp)
532 return false;
533
534 ObjCLanguageRuntime* runtime = (ObjCLanguageRuntime*)process_sp->GetLanguageRuntime(lldb::eLanguageTypeObjC);
535
536 if (!runtime)
537 return false;
538
539 ObjCLanguageRuntime::ClassDescriptorSP descriptor(runtime->GetClassDescriptor(valobj));
540
541 if (!descriptor.get() || !descriptor->IsValid())
542 return false;
543
544 uint32_t ptr_size = process_sp->GetAddressByteSize();
545 bool is_64bit = (ptr_size == 8);
546
547 lldb::addr_t valobj_addr = valobj.GetValueAsUnsigned(0);
548
549 if (!valobj_addr)
550 return false;
551
552 uint64_t value = 0;
553
554 const char* class_name = descriptor->GetClassName().GetCString();
Enrico Granata7685a562012-09-29 00:47:43 +0000555
556 if (!class_name || !*class_name)
557 return false;
558
Enrico Granatacaaf0102012-09-04 18:48:21 +0000559 if (!strcmp(class_name,"__NSDictionaryI"))
560 {
561 Error error;
562 value = process_sp->ReadUnsignedIntegerFromMemory(valobj_addr + ptr_size, ptr_size, 0, error);
563 if (error.Fail())
564 return false;
565 value &= (is_64bit ? ~0xFC00000000000000UL : ~0xFC000000U);
566 }
567 else if (!strcmp(class_name,"__NSDictionaryM"))
568 {
569 Error error;
570 value = process_sp->ReadUnsignedIntegerFromMemory(valobj_addr + ptr_size, ptr_size, 0, error);
571 if (error.Fail())
572 return false;
573 value &= (is_64bit ? ~0xFC00000000000000UL : ~0xFC000000U);
574 }
575 else if (!strcmp(class_name,"__NSCFDictionary"))
576 {
577 Error error;
578 value = process_sp->ReadUnsignedIntegerFromMemory(valobj_addr + (is_64bit ? 20 : 12), ptr_size, 0, error);
579 if (error.Fail())
580 return false;
581 if (is_64bit)
582 value &= ~0x0f1f000000000000UL;
Enrico Granata06d58b02013-01-11 02:44:00 +0000583 }
Enrico Granatacaaf0102012-09-04 18:48:21 +0000584 else
585 {
Enrico Granataf91e78f2012-09-13 18:27:09 +0000586 if (!ExtractValueFromObjCExpression(valobj, "int", "count", value))
Enrico Granatacaaf0102012-09-04 18:48:21 +0000587 return false;
588 }
589
Daniel Malea5f35a4b2012-11-29 21:49:15 +0000590 stream.Printf("%s%" PRIu64 " %s%s",
Enrico Granatacaaf0102012-09-04 18:48:21 +0000591 (name_entries ? "@\"" : ""),
592 value,
593 (name_entries ? (value == 1 ? "entry" : "entries") : (value == 1 ? "key/value pair" : "key/value pairs")),
594 (name_entries ? "\"" : ""));
595 return true;
596}
597
598bool
Enrico Granataf91e78f2012-09-13 18:27:09 +0000599lldb_private::formatters::NSArraySummaryProvider (ValueObject& valobj, Stream& stream)
Enrico Granatacaaf0102012-09-04 18:48:21 +0000600{
601 ProcessSP process_sp = valobj.GetProcessSP();
602 if (!process_sp)
603 return false;
604
605 ObjCLanguageRuntime* runtime = (ObjCLanguageRuntime*)process_sp->GetLanguageRuntime(lldb::eLanguageTypeObjC);
606
607 if (!runtime)
608 return false;
609
610 ObjCLanguageRuntime::ClassDescriptorSP descriptor(runtime->GetClassDescriptor(valobj));
611
612 if (!descriptor.get() || !descriptor->IsValid())
613 return false;
614
615 uint32_t ptr_size = process_sp->GetAddressByteSize();
616
617 lldb::addr_t valobj_addr = valobj.GetValueAsUnsigned(0);
618
619 if (!valobj_addr)
620 return false;
621
622 uint64_t value = 0;
623
624 const char* class_name = descriptor->GetClassName().GetCString();
Enrico Granata7685a562012-09-29 00:47:43 +0000625
626 if (!class_name || !*class_name)
627 return false;
628
Enrico Granatacaaf0102012-09-04 18:48:21 +0000629 if (!strcmp(class_name,"__NSArrayI"))
630 {
631 Error error;
632 value = process_sp->ReadUnsignedIntegerFromMemory(valobj_addr + ptr_size, ptr_size, 0, error);
633 if (error.Fail())
634 return false;
635 }
636 else if (!strcmp(class_name,"__NSArrayM"))
637 {
638 Error error;
639 value = process_sp->ReadUnsignedIntegerFromMemory(valobj_addr + ptr_size, ptr_size, 0, error);
640 if (error.Fail())
641 return false;
642 }
643 else if (!strcmp(class_name,"__NSCFArray"))
644 {
645 Error error;
646 value = process_sp->ReadUnsignedIntegerFromMemory(valobj_addr + 2 * ptr_size, ptr_size, 0, error);
647 if (error.Fail())
648 return false;
649 }
650 else
651 {
Enrico Granataf91e78f2012-09-13 18:27:09 +0000652 if (!ExtractValueFromObjCExpression(valobj, "int", "count", value))
Enrico Granatacaaf0102012-09-04 18:48:21 +0000653 return false;
654 }
655
Daniel Malea5f35a4b2012-11-29 21:49:15 +0000656 stream.Printf("@\"%" PRIu64 " object%s\"",
Enrico Granatacaaf0102012-09-04 18:48:21 +0000657 value,
658 value == 1 ? "" : "s");
659 return true;
660}
661
662template<bool needs_at>
663bool
Enrico Granataf91e78f2012-09-13 18:27:09 +0000664lldb_private::formatters::NSDataSummaryProvider (ValueObject& valobj, Stream& stream)
Enrico Granatacaaf0102012-09-04 18:48:21 +0000665{
666 ProcessSP process_sp = valobj.GetProcessSP();
667 if (!process_sp)
668 return false;
669
670 ObjCLanguageRuntime* runtime = (ObjCLanguageRuntime*)process_sp->GetLanguageRuntime(lldb::eLanguageTypeObjC);
671
672 if (!runtime)
673 return false;
674
675 ObjCLanguageRuntime::ClassDescriptorSP descriptor(runtime->GetClassDescriptor(valobj));
676
677 if (!descriptor.get() || !descriptor->IsValid())
678 return false;
679
680 bool is_64bit = (process_sp->GetAddressByteSize() == 8);
681 lldb::addr_t valobj_addr = valobj.GetValueAsUnsigned(0);
682
683 if (!valobj_addr)
684 return false;
685
686 uint64_t value = 0;
687
688 const char* class_name = descriptor->GetClassName().GetCString();
Enrico Granata7685a562012-09-29 00:47:43 +0000689
690 if (!class_name || !*class_name)
691 return false;
692
Enrico Granatacaaf0102012-09-04 18:48:21 +0000693 if (!strcmp(class_name,"NSConcreteData") ||
694 !strcmp(class_name,"NSConcreteMutableData") ||
695 !strcmp(class_name,"__NSCFData"))
696 {
697 uint32_t offset = (is_64bit ? 16 : 8);
698 Error error;
699 value = process_sp->ReadUnsignedIntegerFromMemory(valobj_addr + offset, is_64bit ? 8 : 4, 0, error);
700 if (error.Fail())
701 return false;
702 }
703 else
704 {
Enrico Granataf91e78f2012-09-13 18:27:09 +0000705 if (!ExtractValueFromObjCExpression(valobj, "int", "length", value))
Enrico Granatacaaf0102012-09-04 18:48:21 +0000706 return false;
707 }
708
Daniel Malea5f35a4b2012-11-29 21:49:15 +0000709 stream.Printf("%s%" PRIu64 " byte%s%s",
Enrico Granatacaaf0102012-09-04 18:48:21 +0000710 (needs_at ? "@\"" : ""),
711 value,
712 (value > 1 ? "s" : ""),
713 (needs_at ? "\"" : ""));
714
715 return true;
716}
717
718bool
Enrico Granataf91e78f2012-09-13 18:27:09 +0000719lldb_private::formatters::NSNumberSummaryProvider (ValueObject& valobj, Stream& stream)
Enrico Granatacaaf0102012-09-04 18:48:21 +0000720{
721 ProcessSP process_sp = valobj.GetProcessSP();
722 if (!process_sp)
723 return false;
724
725 ObjCLanguageRuntime* runtime = (ObjCLanguageRuntime*)process_sp->GetLanguageRuntime(lldb::eLanguageTypeObjC);
726
727 if (!runtime)
728 return false;
729
730 ObjCLanguageRuntime::ClassDescriptorSP descriptor(runtime->GetClassDescriptor(valobj));
731
732 if (!descriptor.get() || !descriptor->IsValid())
733 return false;
734
735 uint32_t ptr_size = process_sp->GetAddressByteSize();
736
737 lldb::addr_t valobj_addr = valobj.GetValueAsUnsigned(0);
738
739 if (!valobj_addr)
740 return false;
741
742 const char* class_name = descriptor->GetClassName().GetCString();
743
Enrico Granata7685a562012-09-29 00:47:43 +0000744 if (!class_name || !*class_name)
745 return false;
746
Enrico Granatacaaf0102012-09-04 18:48:21 +0000747 if (!strcmp(class_name,"NSNumber") || !strcmp(class_name,"__NSCFNumber"))
748 {
749 if (descriptor->IsTagged())
750 {
751 // we have a call to get info and value bits in the tagged descriptor. but we prefer not to cast and replicate them
752 int64_t value = (valobj_addr & ~0x0000000000000000FFL) >> 8;
753 uint64_t i_bits = (valobj_addr & 0xF0) >> 4;
754
755 switch (i_bits)
756 {
757 case 0:
758 stream.Printf("(char)%hhd",(char)value);
759 break;
760 case 4:
761 stream.Printf("(short)%hd",(short)value);
762 break;
763 case 8:
764 stream.Printf("(int)%d",(int)value);
765 break;
766 case 12:
Daniel Malea5f35a4b2012-11-29 21:49:15 +0000767 stream.Printf("(long)%" PRId64,value);
Enrico Granatacaaf0102012-09-04 18:48:21 +0000768 break;
769 default:
Enrico Granata3ca24b42012-12-10 19:23:00 +0000770 stream.Printf("unexpected value:(info=%" PRIu64 ", value=%" PRIu64,i_bits,value);
Enrico Granatacaaf0102012-09-04 18:48:21 +0000771 break;
772 }
773 return true;
774 }
775 else
776 {
777 Error error;
778 uint8_t data_type = (process_sp->ReadUnsignedIntegerFromMemory(valobj_addr + ptr_size, 1, 0, error) & 0x1F);
779 uint64_t data_location = valobj_addr + 2*ptr_size;
780 uint64_t value = 0;
781 if (error.Fail())
782 return false;
783 switch (data_type)
784 {
785 case 1: // 0B00001
786 value = process_sp->ReadUnsignedIntegerFromMemory(data_location, 1, 0, error);
787 if (error.Fail())
788 return false;
789 stream.Printf("(char)%hhd",(char)value);
790 break;
791 case 2: // 0B0010
792 value = process_sp->ReadUnsignedIntegerFromMemory(data_location, 2, 0, error);
793 if (error.Fail())
794 return false;
795 stream.Printf("(short)%hd",(short)value);
796 break;
797 case 3: // 0B0011
798 value = process_sp->ReadUnsignedIntegerFromMemory(data_location, 4, 0, error);
799 if (error.Fail())
800 return false;
801 stream.Printf("(int)%d",(int)value);
802 break;
803 case 17: // 0B10001
804 data_location += 8;
805 case 4: // 0B0100
806 value = process_sp->ReadUnsignedIntegerFromMemory(data_location, 8, 0, error);
807 if (error.Fail())
808 return false;
Daniel Malea5f35a4b2012-11-29 21:49:15 +0000809 stream.Printf("(long)%" PRId64,value);
Enrico Granatacaaf0102012-09-04 18:48:21 +0000810 break;
811 case 5: // 0B0101
812 {
813 uint32_t flt_as_int = process_sp->ReadUnsignedIntegerFromMemory(data_location, 4, 0, error);
814 if (error.Fail())
815 return false;
816 float flt_value = *((float*)&flt_as_int);
817 stream.Printf("(float)%f",flt_value);
818 break;
819 }
820 case 6: // 0B0110
821 {
822 uint64_t dbl_as_lng = process_sp->ReadUnsignedIntegerFromMemory(data_location, 8, 0, error);
823 if (error.Fail())
824 return false;
825 double dbl_value = *((double*)&dbl_as_lng);
826 stream.Printf("(double)%g",dbl_value);
827 break;
828 }
829 default:
830 stream.Printf("absurd: dt=%d",data_type);
831 break;
832 }
833 return true;
834 }
835 }
836 else
837 {
Enrico Granataf91e78f2012-09-13 18:27:09 +0000838 // similar to ExtractValueFromObjCExpression but uses summary instead of value
Enrico Granatacaaf0102012-09-04 18:48:21 +0000839 StreamString expr_path_stream;
840 valobj.GetExpressionPath(expr_path_stream, false);
841 StreamString expr;
842 expr.Printf("(NSString*)[%s stringValue]",expr_path_stream.GetData());
843 ExecutionContext exe_ctx (valobj.GetExecutionContextRef());
844 lldb::ValueObjectSP result_sp;
845 Target* target = exe_ctx.GetTargetPtr();
846 StackFrame* stack_frame = exe_ctx.GetFramePtr();
847 if (!target || !stack_frame)
848 return false;
Enrico Granatad27026e2012-09-05 20:41:26 +0000849
Jim Ingham47beabb2012-10-16 21:41:58 +0000850 EvaluateExpressionOptions options;
Enrico Granatad27026e2012-09-05 20:41:26 +0000851 options.SetCoerceToId(false)
852 .SetUnwindOnError(true)
853 .SetKeepInMemory(true)
854 .SetUseDynamic(lldb::eDynamicCanRunTarget);
855
Enrico Granatacaaf0102012-09-04 18:48:21 +0000856 target->EvaluateExpression(expr.GetData(),
857 stack_frame,
Enrico Granatad27026e2012-09-05 20:41:26 +0000858 result_sp,
859 options);
Enrico Granatacaaf0102012-09-04 18:48:21 +0000860 if (!result_sp)
861 return false;
862 stream.Printf("%s",result_sp->GetSummaryAsCString());
863 return true;
864 }
865}
866
867bool
Enrico Granataf91e78f2012-09-13 18:27:09 +0000868lldb_private::formatters::NSStringSummaryProvider (ValueObject& valobj, Stream& stream)
Enrico Granatacaaf0102012-09-04 18:48:21 +0000869{
870 ProcessSP process_sp = valobj.GetProcessSP();
871 if (!process_sp)
872 return false;
873
874 ObjCLanguageRuntime* runtime = (ObjCLanguageRuntime*)process_sp->GetLanguageRuntime(lldb::eLanguageTypeObjC);
875
876 if (!runtime)
877 return false;
878
879 ObjCLanguageRuntime::ClassDescriptorSP descriptor(runtime->GetClassDescriptor(valobj));
880
881 if (!descriptor.get() || !descriptor->IsValid())
882 return false;
883
884 uint32_t ptr_size = process_sp->GetAddressByteSize();
885
886 lldb::addr_t valobj_addr = valobj.GetValueAsUnsigned(0);
887
888 if (!valobj_addr)
889 return false;
890
891 const char* class_name = descriptor->GetClassName().GetCString();
892
Enrico Granata25c9ade2012-09-29 00:45:53 +0000893 if (!class_name || !*class_name)
894 return false;
895
Enrico Granatacaaf0102012-09-04 18:48:21 +0000896 uint64_t info_bits_location = valobj_addr + ptr_size;
897 if (process_sp->GetByteOrder() != lldb::eByteOrderLittle)
898 info_bits_location += 3;
899
900 Error error;
901
902 uint8_t info_bits = process_sp->ReadUnsignedIntegerFromMemory(info_bits_location, 1, 0, error);
903 if (error.Fail())
904 return false;
905
906 bool is_mutable = (info_bits & 1) == 1;
907 bool is_inline = (info_bits & 0x60) == 0;
908 bool has_explicit_length = (info_bits & (1 | 4)) != 4;
909 bool is_unicode = (info_bits & 0x10) == 0x10;
910 bool is_special = strcmp(class_name,"NSPathStore2") == 0;
911
912 if (strcmp(class_name,"NSString") &&
913 strcmp(class_name,"CFStringRef") &&
914 strcmp(class_name,"CFMutableStringRef") &&
915 strcmp(class_name,"__NSCFConstantString") &&
916 strcmp(class_name,"__NSCFString") &&
917 strcmp(class_name,"NSCFConstantString") &&
918 strcmp(class_name,"NSCFString") &&
919 strcmp(class_name,"NSPathStore2"))
920 {
921 // probably not one of us - bail out
922 return false;
923 }
924
925 if (is_mutable)
926 {
927 uint64_t location = 2 * ptr_size + valobj_addr;
928 location = process_sp->ReadPointerFromMemory(location, error);
929 if (error.Fail())
930 return false;
931 if (has_explicit_length and is_unicode)
Enrico Granatacd8cd612013-01-14 23:53:26 +0000932 return ReadUTFBufferAndDumpToStream<UTF16> (ConvertUTF16toUTF8,location, process_sp, stream, '@');
Enrico Granatacaaf0102012-09-04 18:48:21 +0000933 else
934 {
935 location++;
936 lldb::DataBufferSP buffer_sp(new DataBufferHeap(1024,0));
937 size_t data_read = process_sp->ReadCStringFromMemory(location, (char*)buffer_sp->GetBytes(), 1024, error);
938 if (error.Fail())
939 return false;
940 if (data_read)
941 stream.Printf("@\"%s\"",(char*)buffer_sp->GetBytes());
942 return true;
943 }
944 }
945 else if (is_inline && has_explicit_length && !is_unicode && !is_special && !is_mutable)
946 {
947 uint64_t location = 3 * ptr_size + valobj_addr;
948 lldb::DataBufferSP buffer_sp(new DataBufferHeap(1024,0));
949 size_t data_read = process_sp->ReadCStringFromMemory(location, (char*)buffer_sp->GetBytes(), 1024, error);
950 if (error.Fail())
951 return false;
952 if (data_read)
953 stream.Printf("@\"%s\"",(char*)buffer_sp->GetBytes());
954 return true;
955 }
956 else if (is_unicode)
957 {
958 uint64_t location = valobj_addr + ptr_size + 4 + (ptr_size == 8 ? 4 : 0);
959 if (is_inline)
960 {
961 if (!has_explicit_length)
962 {
963 stream.Printf("found new combo");
964 return true;
965 }
966 else
967 location += ptr_size;
968 }
969 else
970 {
971 location = process_sp->ReadPointerFromMemory(location, error);
972 if (error.Fail())
973 return false;
974 }
Enrico Granatacd8cd612013-01-14 23:53:26 +0000975 return ReadUTFBufferAndDumpToStream<UTF16> (ConvertUTF16toUTF8, location, process_sp, stream, '@');
Enrico Granatacaaf0102012-09-04 18:48:21 +0000976 }
977 else if (is_special)
978 {
979 uint64_t location = valobj_addr + (ptr_size == 8 ? 12 : 8);
Enrico Granatacd8cd612013-01-14 23:53:26 +0000980 return ReadUTFBufferAndDumpToStream<UTF16> (ConvertUTF16toUTF8, location, process_sp, stream, '@');
Enrico Granatacaaf0102012-09-04 18:48:21 +0000981 }
982 else if (is_inline)
983 {
984 uint64_t location = valobj_addr + ptr_size + 4 + (ptr_size == 8 ? 4 : 0);
985 if (!has_explicit_length)
986 location++;
987 lldb::DataBufferSP buffer_sp(new DataBufferHeap(1024,0));
988 size_t data_read = process_sp->ReadCStringFromMemory(location, (char*)buffer_sp->GetBytes(), 1024, error);
989 if (error.Fail())
990 return false;
991 if (data_read)
992 stream.Printf("@\"%s\"",(char*)buffer_sp->GetBytes());
993 return true;
994 }
995 else
996 {
997 uint64_t location = valobj_addr + ptr_size + 4 + (ptr_size == 8 ? 4 : 0);
998 location = process_sp->ReadPointerFromMemory(location, error);
999 if (error.Fail())
1000 return false;
1001 lldb::DataBufferSP buffer_sp(new DataBufferHeap(1024,0));
1002 size_t data_read = process_sp->ReadCStringFromMemory(location, (char*)buffer_sp->GetBytes(), 1024, error);
1003 if (error.Fail())
1004 return false;
1005 if (data_read)
1006 stream.Printf("@\"%s\"",(char*)buffer_sp->GetBytes());
1007 return true;
1008 }
1009
1010 stream.Printf("class name = %s",class_name);
1011 return true;
1012
1013}
1014
Enrico Granata9abbfba2012-10-03 23:53:45 +00001015bool
Enrico Granatadcffc1a2013-02-08 01:55:46 +00001016lldb_private::formatters::NSAttributedStringSummaryProvider (ValueObject& valobj, Stream& stream)
1017{
1018 TargetSP target_sp(valobj.GetTargetSP());
1019 if (!target_sp)
1020 return false;
1021 uint32_t addr_size = target_sp->GetArchitecture().GetAddressByteSize();
1022 uint64_t pointee = valobj.GetValueAsUnsigned(0);
1023 if (!pointee)
1024 return false;
1025 pointee += addr_size;
1026 ClangASTType type(valobj.GetClangAST(),valobj.GetClangType());
1027 ExecutionContext exe_ctx(target_sp,false);
1028 ValueObjectSP child_ptr_sp(valobj.CreateValueObjectFromAddress("string_ptr", pointee, exe_ctx, type));
1029 if (!child_ptr_sp)
1030 return false;
1031 DataExtractor data;
1032 child_ptr_sp->GetData(data);
1033 ValueObjectSP child_sp(child_ptr_sp->CreateValueObjectFromData("string_data", data, exe_ctx, type));
1034 child_sp->GetValueAsUnsigned(0);
1035 if (child_sp)
1036 return NSStringSummaryProvider(*child_sp, stream);
1037 return false;
1038}
1039
1040bool
1041lldb_private::formatters::NSMutableAttributedStringSummaryProvider (ValueObject& valobj, Stream& stream)
1042{
1043 return NSAttributedStringSummaryProvider(valobj, stream);
1044}
1045
1046bool
Enrico Granata9abbfba2012-10-03 23:53:45 +00001047lldb_private::formatters::RuntimeSpecificDescriptionSummaryProvider (ValueObject& valobj, Stream& stream)
1048{
1049 stream.Printf("%s",valobj.GetObjectDescription());
1050 return true;
1051}
1052
Enrico Granatadb054912012-10-29 21:18:03 +00001053bool
1054lldb_private::formatters::ObjCBOOLSummaryProvider (ValueObject& valobj, Stream& stream)
1055{
1056 const uint32_t type_info = ClangASTContext::GetTypeInfo(valobj.GetClangType(),
1057 valobj.GetClangAST(),
1058 NULL);
1059
1060 ValueObjectSP real_guy_sp = valobj.GetSP();
1061
1062 if (type_info & ClangASTContext::eTypeIsPointer)
1063 {
1064 Error err;
1065 real_guy_sp = valobj.Dereference(err);
1066 if (err.Fail() || !real_guy_sp)
1067 return false;
1068 }
1069 else if (type_info & ClangASTContext::eTypeIsReference)
1070 {
1071 real_guy_sp = valobj.GetChildAtIndex(0, true);
1072 if (!real_guy_sp)
1073 return false;
1074 }
1075 uint64_t value = real_guy_sp->GetValueAsUnsigned(0);
1076 if (value == 0)
1077 {
1078 stream.Printf("NO");
1079 return true;
1080 }
1081 stream.Printf("YES");
1082 return true;
1083}
1084
1085template <bool is_sel_ptr>
1086bool
1087lldb_private::formatters::ObjCSELSummaryProvider (ValueObject& valobj, Stream& stream)
1088{
1089 lldb::addr_t data_address = LLDB_INVALID_ADDRESS;
1090
1091 if (is_sel_ptr)
1092 data_address = valobj.GetValueAsUnsigned(LLDB_INVALID_ADDRESS);
1093 else
1094 data_address = valobj.GetAddressOf();
1095
1096 if (data_address == LLDB_INVALID_ADDRESS)
1097 return false;
1098
1099 ExecutionContext exe_ctx(valobj.GetExecutionContextRef());
1100
1101 void* char_opaque_type = valobj.GetClangAST()->CharTy.getAsOpaquePtr();
1102 ClangASTType charstar(valobj.GetClangAST(),ClangASTType::GetPointerType(valobj.GetClangAST(), char_opaque_type));
1103
1104 ValueObjectSP valobj_sp(ValueObject::CreateValueObjectFromAddress("text", data_address, exe_ctx, charstar));
1105
1106 stream.Printf("%s",valobj_sp->GetSummaryAsCString());
1107 return true;
1108}
1109
Enrico Granataf91e78f2012-09-13 18:27:09 +00001110lldb_private::formatters::NSArrayMSyntheticFrontEnd::NSArrayMSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp) :
1111SyntheticChildrenFrontEnd(*valobj_sp.get()),
1112m_exe_ctx_ref(),
1113m_ptr_size(8),
1114m_data_32(NULL),
1115m_data_64(NULL)
1116{
Enrico Granata247da332012-10-04 21:04:46 +00001117 if (valobj_sp)
Enrico Granataf91e78f2012-09-13 18:27:09 +00001118 {
Enrico Granata247da332012-10-04 21:04:46 +00001119 m_id_type = ClangASTType(valobj_sp->GetClangAST(),valobj_sp->GetClangAST()->ObjCBuiltinIdTy.getAsOpaquePtr());
1120 Update();
Enrico Granataf91e78f2012-09-13 18:27:09 +00001121 }
Enrico Granataf91e78f2012-09-13 18:27:09 +00001122}
1123
Greg Clayton36da2aa2013-01-25 18:06:21 +00001124size_t
Enrico Granataf91e78f2012-09-13 18:27:09 +00001125lldb_private::formatters::NSArrayMSyntheticFrontEnd::CalculateNumChildren ()
1126{
1127 if (m_data_32)
1128 return m_data_32->_used;
1129 if (m_data_64)
1130 return m_data_64->_used;
1131 return 0;
1132}
1133
1134lldb::ValueObjectSP
Greg Clayton36da2aa2013-01-25 18:06:21 +00001135lldb_private::formatters::NSArrayMSyntheticFrontEnd::GetChildAtIndex (size_t idx)
Enrico Granataf91e78f2012-09-13 18:27:09 +00001136{
1137 if (!m_data_32 && !m_data_64)
1138 return lldb::ValueObjectSP();
1139 if (idx >= CalculateNumChildren())
1140 return lldb::ValueObjectSP();
1141 lldb::addr_t object_at_idx = (m_data_32 ? m_data_32->_data : m_data_64->_data);
1142 object_at_idx += (idx * m_ptr_size);
1143 StreamString idx_name;
Greg Clayton36da2aa2013-01-25 18:06:21 +00001144 idx_name.Printf("[%zu]",idx);
Enrico Granataf91e78f2012-09-13 18:27:09 +00001145 lldb::ValueObjectSP retval_sp = ValueObject::CreateValueObjectFromAddress(idx_name.GetData(),
1146 object_at_idx,
1147 m_exe_ctx_ref,
1148 m_id_type);
1149 m_children.push_back(retval_sp);
1150 return retval_sp;
1151}
1152
1153bool
1154lldb_private::formatters::NSArrayMSyntheticFrontEnd::Update()
1155{
1156 m_children.clear();
Enrico Granata247da332012-10-04 21:04:46 +00001157 ValueObjectSP valobj_sp = m_backend.GetSP();
1158 m_ptr_size = 0;
1159 delete m_data_32;
1160 m_data_32 = NULL;
1161 delete m_data_64;
1162 m_data_64 = NULL;
1163 if (valobj_sp->IsDynamic())
1164 valobj_sp = valobj_sp->GetStaticValue();
1165 if (!valobj_sp)
1166 return false;
1167 m_exe_ctx_ref = valobj_sp->GetExecutionContextRef();
1168 Error error;
1169 if (valobj_sp->IsPointerType())
1170 {
1171 valobj_sp = valobj_sp->Dereference(error);
1172 if (error.Fail() || !valobj_sp)
1173 return false;
1174 }
1175 error.Clear();
1176 lldb::ProcessSP process_sp(valobj_sp->GetProcessSP());
1177 if (!process_sp)
1178 return false;
1179 m_ptr_size = process_sp->GetAddressByteSize();
1180 uint64_t data_location = valobj_sp->GetAddressOf() + m_ptr_size;
1181 if (m_ptr_size == 4)
1182 {
1183 m_data_32 = new DataDescriptor_32();
1184 process_sp->ReadMemory (data_location, m_data_32, sizeof(DataDescriptor_32), error);
1185 }
1186 else
1187 {
1188 m_data_64 = new DataDescriptor_64();
1189 process_sp->ReadMemory (data_location, m_data_64, sizeof(DataDescriptor_64), error);
1190 }
1191 if (error.Fail())
1192 return false;
Enrico Granataf91e78f2012-09-13 18:27:09 +00001193 return false;
1194}
1195
Enrico Granata800332c2012-10-23 19:54:09 +00001196bool
1197lldb_private::formatters::NSArrayMSyntheticFrontEnd::MightHaveChildren ()
1198{
Enrico Granataf3c10482012-12-10 19:55:53 +00001199 return true;
Enrico Granata800332c2012-10-23 19:54:09 +00001200}
1201
Enrico Granataf91e78f2012-09-13 18:27:09 +00001202static uint32_t
1203ExtractIndexFromString (const char* item_name)
1204{
1205 if (!item_name || !*item_name)
1206 return UINT32_MAX;
1207 if (*item_name != '[')
1208 return UINT32_MAX;
1209 item_name++;
1210 uint32_t idx = 0;
1211 while(*item_name)
1212 {
1213 char x = *item_name;
1214 if (x == ']')
1215 break;
1216 if (x < '0' || x > '9')
1217 return UINT32_MAX;
1218 idx = 10*idx + (x-'0');
1219 item_name++;
1220 }
1221 return idx;
1222}
1223
Enrico Granataf509c5e2013-01-28 23:47:25 +00001224size_t
Enrico Granataf91e78f2012-09-13 18:27:09 +00001225lldb_private::formatters::NSArrayMSyntheticFrontEnd::GetIndexOfChildWithName (const ConstString &name)
1226{
1227 if (!m_data_32 && !m_data_64)
1228 return UINT32_MAX;
1229 const char* item_name = name.GetCString();
1230 uint32_t idx = ExtractIndexFromString(item_name);
1231 if (idx < UINT32_MAX && idx >= CalculateNumChildren())
1232 return UINT32_MAX;
1233 return idx;
1234}
1235
1236lldb_private::formatters::NSArrayMSyntheticFrontEnd::~NSArrayMSyntheticFrontEnd ()
1237{
1238 delete m_data_32;
1239 m_data_32 = NULL;
1240 delete m_data_64;
1241 m_data_64 = NULL;
1242}
1243
1244lldb_private::formatters::NSArrayISyntheticFrontEnd::NSArrayISyntheticFrontEnd (lldb::ValueObjectSP valobj_sp) :
1245SyntheticChildrenFrontEnd(*valobj_sp.get()),
1246m_exe_ctx_ref(),
1247m_ptr_size(8),
1248m_items(0),
1249m_data_ptr(0)
1250{
Enrico Granata247da332012-10-04 21:04:46 +00001251 if (valobj_sp)
Enrico Granataf91e78f2012-09-13 18:27:09 +00001252 {
Enrico Granata247da332012-10-04 21:04:46 +00001253 m_id_type = ClangASTType(valobj_sp->GetClangAST(),valobj_sp->GetClangAST()->ObjCBuiltinIdTy.getAsOpaquePtr());
1254 Update();
Enrico Granataf91e78f2012-09-13 18:27:09 +00001255 }
Enrico Granataf91e78f2012-09-13 18:27:09 +00001256}
1257
1258lldb_private::formatters::NSArrayISyntheticFrontEnd::~NSArrayISyntheticFrontEnd ()
1259{
1260}
1261
Enrico Granataf509c5e2013-01-28 23:47:25 +00001262size_t
Enrico Granataf91e78f2012-09-13 18:27:09 +00001263lldb_private::formatters::NSArrayISyntheticFrontEnd::GetIndexOfChildWithName (const ConstString &name)
1264{
1265 const char* item_name = name.GetCString();
1266 uint32_t idx = ExtractIndexFromString(item_name);
1267 if (idx < UINT32_MAX && idx >= CalculateNumChildren())
1268 return UINT32_MAX;
1269 return idx;
1270}
1271
Greg Clayton36da2aa2013-01-25 18:06:21 +00001272size_t
Enrico Granataf91e78f2012-09-13 18:27:09 +00001273lldb_private::formatters::NSArrayISyntheticFrontEnd::CalculateNumChildren ()
1274{
1275 return m_items;
1276}
1277
1278bool
1279lldb_private::formatters::NSArrayISyntheticFrontEnd::Update()
1280{
Enrico Granata247da332012-10-04 21:04:46 +00001281 m_ptr_size = 0;
1282 m_items = 0;
1283 m_data_ptr = 0;
Enrico Granataf91e78f2012-09-13 18:27:09 +00001284 m_children.clear();
Enrico Granata247da332012-10-04 21:04:46 +00001285 ValueObjectSP valobj_sp = m_backend.GetSP();
1286 if (valobj_sp->IsDynamic())
1287 valobj_sp = valobj_sp->GetStaticValue();
1288 if (!valobj_sp)
1289 return false;
1290 m_exe_ctx_ref = valobj_sp->GetExecutionContextRef();
1291 Error error;
1292 if (valobj_sp->IsPointerType())
1293 {
1294 valobj_sp = valobj_sp->Dereference(error);
1295 if (error.Fail() || !valobj_sp)
1296 return false;
1297 }
1298 error.Clear();
1299 lldb::ProcessSP process_sp(valobj_sp->GetProcessSP());
1300 if (!process_sp)
1301 return false;
1302 m_ptr_size = process_sp->GetAddressByteSize();
1303 uint64_t data_location = valobj_sp->GetAddressOf() + m_ptr_size;
1304 m_items = process_sp->ReadPointerFromMemory(data_location, error);
1305 if (error.Fail())
1306 return false;
1307 m_data_ptr = data_location+m_ptr_size;
Enrico Granataf91e78f2012-09-13 18:27:09 +00001308 return false;
1309}
1310
Enrico Granata800332c2012-10-23 19:54:09 +00001311bool
1312lldb_private::formatters::NSArrayISyntheticFrontEnd::MightHaveChildren ()
1313{
Enrico Granataf3c10482012-12-10 19:55:53 +00001314 return true;
Enrico Granata800332c2012-10-23 19:54:09 +00001315}
1316
Enrico Granataf91e78f2012-09-13 18:27:09 +00001317lldb::ValueObjectSP
Greg Clayton36da2aa2013-01-25 18:06:21 +00001318lldb_private::formatters::NSArrayISyntheticFrontEnd::GetChildAtIndex (size_t idx)
Enrico Granataf91e78f2012-09-13 18:27:09 +00001319{
1320 if (idx >= CalculateNumChildren())
1321 return lldb::ValueObjectSP();
1322 lldb::addr_t object_at_idx = m_data_ptr;
1323 object_at_idx += (idx * m_ptr_size);
1324 ProcessSP process_sp = m_exe_ctx_ref.GetProcessSP();
1325 if (!process_sp)
1326 return lldb::ValueObjectSP();
1327 Error error;
1328 object_at_idx = process_sp->ReadPointerFromMemory(object_at_idx, error);
1329 if (error.Fail())
1330 return lldb::ValueObjectSP();
1331 StreamString expr;
Daniel Malea5f35a4b2012-11-29 21:49:15 +00001332 expr.Printf("(id)%" PRIu64,object_at_idx);
Enrico Granataf91e78f2012-09-13 18:27:09 +00001333 StreamString idx_name;
Greg Clayton36da2aa2013-01-25 18:06:21 +00001334 idx_name.Printf("[%zu]",idx);
Enrico Granataf91e78f2012-09-13 18:27:09 +00001335 lldb::ValueObjectSP retval_sp = ValueObject::CreateValueObjectFromExpression(idx_name.GetData(), expr.GetData(), m_exe_ctx_ref);
1336 m_children.push_back(retval_sp);
1337 return retval_sp;
1338}
1339
1340SyntheticChildrenFrontEnd* lldb_private::formatters::NSArraySyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP valobj_sp)
1341{
1342 lldb::ProcessSP process_sp (valobj_sp->GetProcessSP());
1343 if (!process_sp)
1344 return NULL;
1345 ObjCLanguageRuntime *runtime = (ObjCLanguageRuntime*)process_sp->GetLanguageRuntime(lldb::eLanguageTypeObjC);
1346 if (!runtime)
1347 return NULL;
1348
1349 if (!valobj_sp->IsPointerType())
1350 {
1351 Error error;
1352 valobj_sp = valobj_sp->AddressOf(error);
1353 if (error.Fail() || !valobj_sp)
1354 return NULL;
1355 }
1356
1357 ObjCLanguageRuntime::ClassDescriptorSP descriptor(runtime->GetClassDescriptor(*valobj_sp.get()));
1358
1359 if (!descriptor.get() || !descriptor->IsValid())
1360 return NULL;
1361
1362 const char* class_name = descriptor->GetClassName().GetCString();
Enrico Granata7685a562012-09-29 00:47:43 +00001363
1364 if (!class_name || !*class_name)
1365 return NULL;
1366
Enrico Granataf91e78f2012-09-13 18:27:09 +00001367 if (!strcmp(class_name,"__NSArrayI"))
1368 {
1369 return (new NSArrayISyntheticFrontEnd(valobj_sp));
1370 }
1371 else if (!strcmp(class_name,"__NSArrayM"))
1372 {
1373 return (new NSArrayMSyntheticFrontEnd(valobj_sp));
1374 }
1375 else
1376 {
1377 return (new NSArrayCodeRunningSyntheticFrontEnd(valobj_sp));
1378 }
1379}
1380
1381lldb_private::formatters::NSArrayCodeRunningSyntheticFrontEnd::NSArrayCodeRunningSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp) :
1382SyntheticChildrenFrontEnd(*valobj_sp.get())
1383{}
1384
Greg Clayton36da2aa2013-01-25 18:06:21 +00001385size_t
Enrico Granataf91e78f2012-09-13 18:27:09 +00001386lldb_private::formatters::NSArrayCodeRunningSyntheticFrontEnd::CalculateNumChildren ()
1387{
Enrico Granataf91e78f2012-09-13 18:27:09 +00001388 uint64_t count = 0;
1389 if (ExtractValueFromObjCExpression(m_backend, "int", "count", count))
1390 return count;
1391 return 0;
1392}
1393
1394lldb::ValueObjectSP
Greg Clayton36da2aa2013-01-25 18:06:21 +00001395lldb_private::formatters::NSArrayCodeRunningSyntheticFrontEnd::GetChildAtIndex (size_t idx)
Enrico Granataf91e78f2012-09-13 18:27:09 +00001396{
1397 StreamString idx_name;
Greg Clayton36da2aa2013-01-25 18:06:21 +00001398 idx_name.Printf("[%zu]",idx);
Enrico Granataf91e78f2012-09-13 18:27:09 +00001399 lldb::ValueObjectSP valobj_sp = CallSelectorOnObject(m_backend,"id","objectAtIndex:",idx);
1400 if (valobj_sp)
1401 valobj_sp->SetName(ConstString(idx_name.GetData()));
1402 return valobj_sp;
1403}
1404
1405bool
1406lldb_private::formatters::NSArrayCodeRunningSyntheticFrontEnd::Update()
1407{
1408 return false;
1409}
1410
Enrico Granata800332c2012-10-23 19:54:09 +00001411bool
1412lldb_private::formatters::NSArrayCodeRunningSyntheticFrontEnd::MightHaveChildren ()
1413{
Enrico Granataf3c10482012-12-10 19:55:53 +00001414 return true;
Enrico Granata800332c2012-10-23 19:54:09 +00001415}
1416
Enrico Granataf509c5e2013-01-28 23:47:25 +00001417size_t
Enrico Granataf91e78f2012-09-13 18:27:09 +00001418lldb_private::formatters::NSArrayCodeRunningSyntheticFrontEnd::GetIndexOfChildWithName (const ConstString &name)
1419{
1420 return 0;
1421}
1422
1423lldb_private::formatters::NSArrayCodeRunningSyntheticFrontEnd::~NSArrayCodeRunningSyntheticFrontEnd ()
1424{}
1425
Enrico Granata3a08fd12012-09-18 17:43:16 +00001426SyntheticChildrenFrontEnd* lldb_private::formatters::NSDictionarySyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP valobj_sp)
1427{
1428
1429 lldb::ProcessSP process_sp (valobj_sp->GetProcessSP());
1430 if (!process_sp)
1431 return NULL;
1432 ObjCLanguageRuntime *runtime = (ObjCLanguageRuntime*)process_sp->GetLanguageRuntime(lldb::eLanguageTypeObjC);
1433 if (!runtime)
1434 return NULL;
1435
1436 if (!valobj_sp->IsPointerType())
1437 {
1438 Error error;
1439 valobj_sp = valobj_sp->AddressOf(error);
1440 if (error.Fail() || !valobj_sp)
1441 return NULL;
1442 }
1443
1444 ObjCLanguageRuntime::ClassDescriptorSP descriptor(runtime->GetClassDescriptor(*valobj_sp.get()));
1445
1446 if (!descriptor.get() || !descriptor->IsValid())
1447 return NULL;
1448
1449 const char* class_name = descriptor->GetClassName().GetCString();
Enrico Granata7685a562012-09-29 00:47:43 +00001450
1451 if (!class_name || !*class_name)
1452 return NULL;
1453
Enrico Granata3a08fd12012-09-18 17:43:16 +00001454 if (!strcmp(class_name,"__NSDictionaryI"))
1455 {
1456 return (new NSDictionaryISyntheticFrontEnd(valobj_sp));
1457 }
1458 else if (!strcmp(class_name,"__NSDictionaryM"))
1459 {
1460 return (new NSDictionaryMSyntheticFrontEnd(valobj_sp));
1461 }
1462 else
1463 {
1464 return (new NSDictionaryCodeRunningSyntheticFrontEnd(valobj_sp));
1465 }
1466}
1467
1468lldb_private::formatters::NSDictionaryCodeRunningSyntheticFrontEnd::NSDictionaryCodeRunningSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp) :
1469SyntheticChildrenFrontEnd(*valobj_sp.get())
1470{}
1471
Greg Clayton36da2aa2013-01-25 18:06:21 +00001472size_t
Enrico Granata3a08fd12012-09-18 17:43:16 +00001473lldb_private::formatters::NSDictionaryCodeRunningSyntheticFrontEnd::CalculateNumChildren ()
1474{
1475 uint64_t count = 0;
1476 if (ExtractValueFromObjCExpression(m_backend, "int", "count", count))
1477 return count;
1478 return 0;
1479}
1480
1481lldb::ValueObjectSP
Greg Clayton36da2aa2013-01-25 18:06:21 +00001482lldb_private::formatters::NSDictionaryCodeRunningSyntheticFrontEnd::GetChildAtIndex (size_t idx)
Enrico Granata3a08fd12012-09-18 17:43:16 +00001483{
1484 StreamString idx_name;
Greg Clayton36da2aa2013-01-25 18:06:21 +00001485 idx_name.Printf("[%zu]",idx);
Enrico Granata3a08fd12012-09-18 17:43:16 +00001486 StreamString valobj_expr_path;
1487 m_backend.GetExpressionPath(valobj_expr_path, false);
1488 StreamString key_fetcher_expr;
Greg Clayton36da2aa2013-01-25 18:06:21 +00001489 key_fetcher_expr.Printf("(id)[(NSArray*)[%s allKeys] objectAtIndex:%zu]",valobj_expr_path.GetData(),idx);
Enrico Granata3a08fd12012-09-18 17:43:16 +00001490 StreamString value_fetcher_expr;
1491 value_fetcher_expr.Printf("(id)[%s objectForKey:%s]",valobj_expr_path.GetData(),key_fetcher_expr.GetData());
1492 StreamString object_fetcher_expr;
Enrico Granatafd3d28d2012-10-01 21:49:10 +00001493 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 +00001494 lldb::ValueObjectSP child_sp;
1495 m_backend.GetTargetSP()->EvaluateExpression(object_fetcher_expr.GetData(), m_backend.GetFrameSP().get(), child_sp,
Jim Ingham47beabb2012-10-16 21:41:58 +00001496 EvaluateExpressionOptions().SetKeepInMemory(true));
Enrico Granata3a08fd12012-09-18 17:43:16 +00001497 if (child_sp)
1498 child_sp->SetName(ConstString(idx_name.GetData()));
1499 return child_sp;
1500}
1501
1502bool
1503lldb_private::formatters::NSDictionaryCodeRunningSyntheticFrontEnd::Update()
1504{
1505 return false;
1506}
1507
Enrico Granata800332c2012-10-23 19:54:09 +00001508bool
1509lldb_private::formatters::NSDictionaryCodeRunningSyntheticFrontEnd::MightHaveChildren ()
1510{
Enrico Granataf3c10482012-12-10 19:55:53 +00001511 return true;
Enrico Granata800332c2012-10-23 19:54:09 +00001512}
1513
Enrico Granataf509c5e2013-01-28 23:47:25 +00001514size_t
Enrico Granata3a08fd12012-09-18 17:43:16 +00001515lldb_private::formatters::NSDictionaryCodeRunningSyntheticFrontEnd::GetIndexOfChildWithName (const ConstString &name)
1516{
1517 return 0;
1518}
1519
1520lldb_private::formatters::NSDictionaryCodeRunningSyntheticFrontEnd::~NSDictionaryCodeRunningSyntheticFrontEnd ()
1521{}
1522
1523lldb_private::formatters::NSDictionaryISyntheticFrontEnd::NSDictionaryISyntheticFrontEnd (lldb::ValueObjectSP valobj_sp) :
1524 SyntheticChildrenFrontEnd(*valobj_sp.get()),
1525 m_exe_ctx_ref(),
1526 m_ptr_size(8),
1527 m_data_32(NULL),
1528 m_data_64(NULL)
1529{
Enrico Granataa787c1a2012-10-04 21:46:06 +00001530 if (valobj_sp)
1531 Update();
Enrico Granata3a08fd12012-09-18 17:43:16 +00001532}
1533
1534lldb_private::formatters::NSDictionaryISyntheticFrontEnd::~NSDictionaryISyntheticFrontEnd ()
1535{
1536 delete m_data_32;
1537 m_data_32 = NULL;
1538 delete m_data_64;
1539 m_data_64 = NULL;
1540}
1541
Enrico Granataf509c5e2013-01-28 23:47:25 +00001542size_t
Enrico Granata3a08fd12012-09-18 17:43:16 +00001543lldb_private::formatters::NSDictionaryISyntheticFrontEnd::GetIndexOfChildWithName (const ConstString &name)
1544{
1545 const char* item_name = name.GetCString();
1546 uint32_t idx = ExtractIndexFromString(item_name);
1547 if (idx < UINT32_MAX && idx >= CalculateNumChildren())
1548 return UINT32_MAX;
1549 return idx;
1550}
1551
Greg Clayton36da2aa2013-01-25 18:06:21 +00001552size_t
Enrico Granata3a08fd12012-09-18 17:43:16 +00001553lldb_private::formatters::NSDictionaryISyntheticFrontEnd::CalculateNumChildren ()
1554{
1555 if (!m_data_32 && !m_data_64)
1556 return 0;
1557 return (m_data_32 ? m_data_32->_used : m_data_64->_used);
1558}
1559
1560bool
1561lldb_private::formatters::NSDictionaryISyntheticFrontEnd::Update()
1562{
1563 m_children.clear();
Enrico Granataa787c1a2012-10-04 21:46:06 +00001564 delete m_data_32;
1565 m_data_32 = NULL;
1566 delete m_data_64;
1567 m_data_64 = NULL;
1568 m_ptr_size = 0;
1569 ValueObjectSP valobj_sp = m_backend.GetSP();
1570 if (!valobj_sp)
1571 return false;
1572 if (valobj_sp->IsDynamic())
1573 valobj_sp = valobj_sp->GetStaticValue();
1574 if (!valobj_sp)
1575 return false;
1576 m_exe_ctx_ref = valobj_sp->GetExecutionContextRef();
1577 Error error;
1578 if (valobj_sp->IsPointerType())
1579 {
1580 valobj_sp = valobj_sp->Dereference(error);
1581 if (error.Fail() || !valobj_sp)
1582 return false;
1583 }
1584 error.Clear();
1585 lldb::ProcessSP process_sp(valobj_sp->GetProcessSP());
1586 if (!process_sp)
1587 return false;
1588 m_ptr_size = process_sp->GetAddressByteSize();
1589 uint64_t data_location = valobj_sp->GetAddressOf() + m_ptr_size;
1590 if (m_ptr_size == 4)
1591 {
1592 m_data_32 = new DataDescriptor_32();
1593 process_sp->ReadMemory (data_location, m_data_32, sizeof(DataDescriptor_32), error);
1594 }
1595 else
1596 {
1597 m_data_64 = new DataDescriptor_64();
1598 process_sp->ReadMemory (data_location, m_data_64, sizeof(DataDescriptor_64), error);
1599 }
1600 if (error.Fail())
1601 return false;
1602 m_data_ptr = data_location + m_ptr_size;
Enrico Granata3a08fd12012-09-18 17:43:16 +00001603 return false;
1604}
1605
Enrico Granata800332c2012-10-23 19:54:09 +00001606bool
1607lldb_private::formatters::NSDictionaryISyntheticFrontEnd::MightHaveChildren ()
1608{
Enrico Granataf3c10482012-12-10 19:55:53 +00001609 return true;
Enrico Granata800332c2012-10-23 19:54:09 +00001610}
1611
Enrico Granata3a08fd12012-09-18 17:43:16 +00001612lldb::ValueObjectSP
Greg Clayton36da2aa2013-01-25 18:06:21 +00001613lldb_private::formatters::NSDictionaryISyntheticFrontEnd::GetChildAtIndex (size_t idx)
Enrico Granata3a08fd12012-09-18 17:43:16 +00001614{
1615 uint32_t num_children = CalculateNumChildren();
1616
1617 if (idx >= num_children)
1618 return lldb::ValueObjectSP();
1619
1620 if (m_children.empty())
1621 {
1622 // do the scan phase
1623 lldb::addr_t key_at_idx = 0, val_at_idx = 0;
1624
1625 uint32_t tries = 0;
1626 uint32_t test_idx = 0;
1627
1628 while(tries < num_children)
1629 {
1630 key_at_idx = m_data_ptr + (2*test_idx * m_ptr_size);
1631 val_at_idx = key_at_idx + m_ptr_size;
1632 ProcessSP process_sp = m_exe_ctx_ref.GetProcessSP();
1633 if (!process_sp)
1634 return lldb::ValueObjectSP();
1635 Error error;
1636 key_at_idx = process_sp->ReadPointerFromMemory(key_at_idx, error);
1637 if (error.Fail())
1638 return lldb::ValueObjectSP();
1639 val_at_idx = process_sp->ReadPointerFromMemory(val_at_idx, error);
1640 if (error.Fail())
1641 return lldb::ValueObjectSP();
1642
1643 test_idx++;
1644
1645 if (!key_at_idx || !val_at_idx)
1646 continue;
1647 tries++;
1648
1649 DictionaryItemDescriptor descriptor = {key_at_idx,val_at_idx,lldb::ValueObjectSP()};
1650
1651 m_children.push_back(descriptor);
1652 }
1653 }
1654
1655 if (idx >= m_children.size()) // should never happen
1656 return lldb::ValueObjectSP();
1657
1658 DictionaryItemDescriptor &dict_item = m_children[idx];
1659 if (!dict_item.valobj_sp)
1660 {
1661 // make the new ValueObject
1662 StreamString expr;
Daniel Malea5f35a4b2012-11-29 21:49:15 +00001663 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 +00001664 StreamString idx_name;
Greg Clayton36da2aa2013-01-25 18:06:21 +00001665 idx_name.Printf("[%zu]",idx);
Enrico Granata3a08fd12012-09-18 17:43:16 +00001666 dict_item.valobj_sp = ValueObject::CreateValueObjectFromExpression(idx_name.GetData(), expr.GetData(), m_exe_ctx_ref);
1667 }
1668 return dict_item.valobj_sp;
1669}
1670
1671lldb_private::formatters::NSDictionaryMSyntheticFrontEnd::NSDictionaryMSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp) :
1672 SyntheticChildrenFrontEnd(*valobj_sp.get()),
1673 m_exe_ctx_ref(),
1674 m_ptr_size(8),
1675 m_data_32(NULL),
1676 m_data_64(NULL)
1677{
Enrico Granataa787c1a2012-10-04 21:46:06 +00001678 if (valobj_sp)
1679 Update ();
Enrico Granata3a08fd12012-09-18 17:43:16 +00001680}
1681
1682lldb_private::formatters::NSDictionaryMSyntheticFrontEnd::~NSDictionaryMSyntheticFrontEnd ()
1683{
1684 delete m_data_32;
1685 m_data_32 = NULL;
1686 delete m_data_64;
1687 m_data_64 = NULL;
1688}
1689
Enrico Granataf509c5e2013-01-28 23:47:25 +00001690size_t
Enrico Granata3a08fd12012-09-18 17:43:16 +00001691lldb_private::formatters::NSDictionaryMSyntheticFrontEnd::GetIndexOfChildWithName (const ConstString &name)
1692{
1693 const char* item_name = name.GetCString();
1694 uint32_t idx = ExtractIndexFromString(item_name);
1695 if (idx < UINT32_MAX && idx >= CalculateNumChildren())
1696 return UINT32_MAX;
1697 return idx;
1698}
1699
Greg Clayton36da2aa2013-01-25 18:06:21 +00001700size_t
Enrico Granata3a08fd12012-09-18 17:43:16 +00001701lldb_private::formatters::NSDictionaryMSyntheticFrontEnd::CalculateNumChildren ()
1702{
1703 if (!m_data_32 && !m_data_64)
1704 return 0;
1705 return (m_data_32 ? m_data_32->_used : m_data_64->_used);
1706}
1707
1708bool
1709lldb_private::formatters::NSDictionaryMSyntheticFrontEnd::Update()
1710{
1711 m_children.clear();
Enrico Granataa787c1a2012-10-04 21:46:06 +00001712 ValueObjectSP valobj_sp = m_backend.GetSP();
1713 m_ptr_size = 0;
1714 delete m_data_32;
1715 m_data_32 = NULL;
1716 delete m_data_64;
1717 m_data_64 = NULL;
1718 if (!valobj_sp)
1719 return false;
1720 if (valobj_sp->IsDynamic())
1721 valobj_sp = valobj_sp->GetStaticValue();
1722 if (!valobj_sp)
1723 return false;
1724 m_exe_ctx_ref = valobj_sp->GetExecutionContextRef();
1725 Error error;
1726 if (valobj_sp->IsPointerType())
1727 {
1728 valobj_sp = valobj_sp->Dereference(error);
1729 if (error.Fail() || !valobj_sp)
1730 return false;
1731 }
1732 error.Clear();
1733 lldb::ProcessSP process_sp(valobj_sp->GetProcessSP());
1734 if (!process_sp)
1735 return false;
1736 m_ptr_size = process_sp->GetAddressByteSize();
1737 uint64_t data_location = valobj_sp->GetAddressOf() + m_ptr_size;
1738 if (m_ptr_size == 4)
1739 {
1740 m_data_32 = new DataDescriptor_32();
1741 process_sp->ReadMemory (data_location, m_data_32, sizeof(DataDescriptor_32), error);
1742 }
1743 else
1744 {
1745 m_data_64 = new DataDescriptor_64();
1746 process_sp->ReadMemory (data_location, m_data_64, sizeof(DataDescriptor_64), error);
1747 }
1748 if (error.Fail())
1749 return false;
Enrico Granata3a08fd12012-09-18 17:43:16 +00001750 return false;
1751}
1752
Enrico Granata800332c2012-10-23 19:54:09 +00001753bool
1754lldb_private::formatters::NSDictionaryMSyntheticFrontEnd::MightHaveChildren ()
1755{
Enrico Granataf3c10482012-12-10 19:55:53 +00001756 return true;
Enrico Granata800332c2012-10-23 19:54:09 +00001757}
1758
Enrico Granata3a08fd12012-09-18 17:43:16 +00001759lldb::ValueObjectSP
Greg Clayton36da2aa2013-01-25 18:06:21 +00001760lldb_private::formatters::NSDictionaryMSyntheticFrontEnd::GetChildAtIndex (size_t idx)
Enrico Granata3a08fd12012-09-18 17:43:16 +00001761{
1762 lldb::addr_t m_keys_ptr = (m_data_32 ? m_data_32->_keys_addr : m_data_64->_keys_addr);
1763 lldb::addr_t m_values_ptr = (m_data_32 ? m_data_32->_objs_addr : m_data_64->_objs_addr);
1764
1765 uint32_t num_children = CalculateNumChildren();
1766
1767 if (idx >= num_children)
1768 return lldb::ValueObjectSP();
1769
1770 if (m_children.empty())
1771 {
1772 // do the scan phase
1773 lldb::addr_t key_at_idx = 0, val_at_idx = 0;
1774
1775 uint32_t tries = 0;
1776 uint32_t test_idx = 0;
1777
1778 while(tries < num_children)
1779 {
1780 key_at_idx = m_keys_ptr + (test_idx * m_ptr_size);
1781 val_at_idx = m_values_ptr + (test_idx * m_ptr_size);;
1782 ProcessSP process_sp = m_exe_ctx_ref.GetProcessSP();
1783 if (!process_sp)
1784 return lldb::ValueObjectSP();
1785 Error error;
1786 key_at_idx = process_sp->ReadPointerFromMemory(key_at_idx, error);
1787 if (error.Fail())
1788 return lldb::ValueObjectSP();
1789 val_at_idx = process_sp->ReadPointerFromMemory(val_at_idx, error);
1790 if (error.Fail())
1791 return lldb::ValueObjectSP();
1792
1793 test_idx++;
1794
1795 if (!key_at_idx || !val_at_idx)
1796 continue;
1797 tries++;
1798
1799 DictionaryItemDescriptor descriptor = {key_at_idx,val_at_idx,lldb::ValueObjectSP()};
1800
1801 m_children.push_back(descriptor);
1802 }
1803 }
1804
1805 if (idx >= m_children.size()) // should never happen
1806 return lldb::ValueObjectSP();
1807
1808 DictionaryItemDescriptor &dict_item = m_children[idx];
1809 if (!dict_item.valobj_sp)
1810 {
1811 // make the new ValueObject
1812 StreamString expr;
Daniel Malea5f35a4b2012-11-29 21:49:15 +00001813 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 +00001814 StreamString idx_name;
Greg Clayton36da2aa2013-01-25 18:06:21 +00001815 idx_name.Printf("[%zu]",idx);
Enrico Granata3a08fd12012-09-18 17:43:16 +00001816 dict_item.valobj_sp = ValueObject::CreateValueObjectFromExpression(idx_name.GetData(), expr.GetData(), m_exe_ctx_ref);
1817 }
1818 return dict_item.valobj_sp;
1819}
Enrico Granatacaaf0102012-09-04 18:48:21 +00001820
Enrico Granata689696c2013-02-04 22:54:42 +00001821lldb_private::formatters::LibcxxVectorBoolSyntheticFrontEnd::LibcxxVectorBoolSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp) :
1822 SyntheticChildrenFrontEnd(*valobj_sp.get()),
1823 m_exe_ctx_ref(),
1824 m_count(0),
1825 m_base_data_address(0),
1826 m_options()
1827 {
1828 if (valobj_sp)
1829 Update();
1830 m_options.SetCoerceToId(false)
1831 .SetUnwindOnError(true)
1832 .SetKeepInMemory(true)
1833 .SetUseDynamic(lldb::eDynamicCanRunTarget);
1834 }
1835
1836size_t
1837lldb_private::formatters::LibcxxVectorBoolSyntheticFrontEnd::CalculateNumChildren ()
1838{
1839 return m_count;
1840}
1841
1842lldb::ValueObjectSP
1843lldb_private::formatters::LibcxxVectorBoolSyntheticFrontEnd::GetChildAtIndex (size_t idx)
1844{
1845 if (idx >= m_count)
1846 return ValueObjectSP();
1847 if (m_base_data_address == 0 || m_count == 0)
1848 return ValueObjectSP();
1849 size_t byte_idx = (idx >> 3); // divide by 8 to get byte index
1850 size_t bit_index = (idx & 7); // efficient idx % 8 for bit index
1851 lldb::addr_t byte_location = m_base_data_address + byte_idx;
1852 ProcessSP process_sp(m_exe_ctx_ref.GetProcessSP());
1853 if (!process_sp)
1854 return ValueObjectSP();
1855 uint8_t byte = 0;
1856 uint8_t mask = 0;
1857 Error err;
1858 size_t bytes_read = process_sp->ReadMemory(byte_location, &byte, 1, err);
1859 if (err.Fail() || bytes_read == 0)
1860 return ValueObjectSP();
1861 switch (bit_index)
1862 {
1863 case 0:
1864 mask = 1; break;
1865 case 1:
1866 mask = 2; break;
1867 case 2:
1868 mask = 4; break;
1869 case 3:
1870 mask = 8; break;
1871 case 4:
1872 mask = 16; break;
1873 case 5:
1874 mask = 32; break;
1875 case 6:
1876 mask = 64; break;
1877 case 7:
1878 mask = 128; break;
1879 default:
1880 return ValueObjectSP();
1881 }
1882 bool bit_set = ((byte & mask) != 0);
1883 Target& target(process_sp->GetTarget());
1884 ValueObjectSP retval_sp;
1885 if (bit_set)
1886 target.EvaluateExpression("(bool)true", NULL, retval_sp);
1887 else
1888 target.EvaluateExpression("(bool)false", NULL, retval_sp);
1889 StreamString name; name.Printf("[%zu]",idx);
1890 if (retval_sp)
1891 retval_sp->SetName(ConstString(name.GetData()));
1892 return retval_sp;
1893}
1894
1895/*(std::__1::vector<std::__1::allocator<bool> >) vBool = {
1896 __begin_ = 0x00000001001000e0
1897 __size_ = 56
1898 __cap_alloc_ = {
1899 std::__1::__libcpp_compressed_pair_imp<unsigned long, std::__1::allocator<unsigned long> > = {
1900 __first_ = 1
1901 }
1902 }
1903}*/
1904
1905bool
1906lldb_private::formatters::LibcxxVectorBoolSyntheticFrontEnd::Update()
1907{
1908 ValueObjectSP valobj_sp = m_backend.GetSP();
1909 if (!valobj_sp)
1910 return false;
1911 if (valobj_sp->IsDynamic())
1912 valobj_sp = valobj_sp->GetStaticValue();
1913 if (!valobj_sp)
1914 return false;
1915 m_exe_ctx_ref = valobj_sp->GetExecutionContextRef();
1916 ValueObjectSP size_sp(valobj_sp->GetChildMemberWithName(ConstString("__size_"), true));
1917 if (!size_sp)
1918 return false;
1919 m_count = size_sp->GetValueAsUnsigned(0);
1920 if (!m_count)
1921 return true;
1922 ValueObjectSP begin_sp(valobj_sp->GetChildMemberWithName(ConstString("__begin_"), true));
1923 if (!begin_sp)
1924 {
1925 m_count = 0;
1926 return false;
1927 }
1928 m_base_data_address = begin_sp->GetValueAsUnsigned(0);
1929 if (!m_base_data_address)
1930 {
1931 m_count = 0;
1932 return false;
1933 }
1934 return true;
1935}
1936
1937bool
1938lldb_private::formatters::LibcxxVectorBoolSyntheticFrontEnd::MightHaveChildren ()
1939{
1940 return true;
1941}
1942
1943size_t
1944lldb_private::formatters::LibcxxVectorBoolSyntheticFrontEnd::GetIndexOfChildWithName (const ConstString &name)
1945{
1946 if (!m_count || !m_base_data_address)
1947 return UINT32_MAX;
1948 const char* item_name = name.GetCString();
1949 uint32_t idx = ExtractIndexFromString(item_name);
1950 if (idx < UINT32_MAX && idx >= CalculateNumChildren())
1951 return UINT32_MAX;
1952 return idx;
1953}
1954
1955lldb_private::formatters::LibcxxVectorBoolSyntheticFrontEnd::~LibcxxVectorBoolSyntheticFrontEnd ()
1956{}
1957
1958SyntheticChildrenFrontEnd*
1959lldb_private::formatters::LibcxxVectorBoolSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP valobj_sp)
1960{
1961 if (!valobj_sp)
1962 return NULL;
1963 return (new LibcxxVectorBoolSyntheticFrontEnd(valobj_sp));
1964}
1965
1966lldb_private::formatters::LibstdcppVectorBoolSyntheticFrontEnd::LibstdcppVectorBoolSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp) :
1967SyntheticChildrenFrontEnd(*valobj_sp.get()),
1968m_exe_ctx_ref(),
1969m_count(0),
1970m_base_data_address(0),
1971m_options()
1972{
1973 if (valobj_sp)
1974 Update();
1975 m_options.SetCoerceToId(false)
1976 .SetUnwindOnError(true)
1977 .SetKeepInMemory(true)
1978 .SetUseDynamic(lldb::eDynamicCanRunTarget);
1979}
1980
1981size_t
1982lldb_private::formatters::LibstdcppVectorBoolSyntheticFrontEnd::CalculateNumChildren ()
1983{
1984 return m_count;
1985}
1986
1987lldb::ValueObjectSP
1988lldb_private::formatters::LibstdcppVectorBoolSyntheticFrontEnd::GetChildAtIndex (size_t idx)
1989{
1990 if (idx >= m_count)
1991 return ValueObjectSP();
1992 if (m_base_data_address == 0 || m_count == 0)
1993 return ValueObjectSP();
1994 size_t byte_idx = (idx >> 3); // divide by 8 to get byte index
1995 size_t bit_index = (idx & 7); // efficient idx % 8 for bit index
1996 lldb::addr_t byte_location = m_base_data_address + byte_idx;
1997 ProcessSP process_sp(m_exe_ctx_ref.GetProcessSP());
1998 if (!process_sp)
1999 return ValueObjectSP();
2000 uint8_t byte = 0;
2001 uint8_t mask = 0;
2002 Error err;
2003 size_t bytes_read = process_sp->ReadMemory(byte_location, &byte, 1, err);
2004 if (err.Fail() || bytes_read == 0)
2005 return ValueObjectSP();
2006 switch (bit_index)
2007 {
2008 case 0:
2009 mask = 1; break;
2010 case 1:
2011 mask = 2; break;
2012 case 2:
2013 mask = 4; break;
2014 case 3:
2015 mask = 8; break;
2016 case 4:
2017 mask = 16; break;
2018 case 5:
2019 mask = 32; break;
2020 case 6:
2021 mask = 64; break;
2022 case 7:
2023 mask = 128; break;
2024 default:
2025 return ValueObjectSP();
2026 }
2027 bool bit_set = ((byte & mask) != 0);
2028 Target& target(process_sp->GetTarget());
2029 ValueObjectSP retval_sp;
2030 if (bit_set)
2031 target.EvaluateExpression("(bool)true", NULL, retval_sp);
2032 else
2033 target.EvaluateExpression("(bool)false", NULL, retval_sp);
2034 StreamString name; name.Printf("[%zu]",idx);
2035 if (retval_sp)
2036 retval_sp->SetName(ConstString(name.GetData()));
2037 return retval_sp;
2038}
2039
2040/*((std::vector<std::allocator<bool> >) vBool = {
2041 (std::_Bvector_base<std::allocator<bool> >) std::_Bvector_base<std::allocator<bool> > = {
2042 (std::_Bvector_base<std::allocator<bool> >::_Bvector_impl) _M_impl = {
2043 (std::_Bit_iterator) _M_start = {
2044 (std::_Bit_iterator_base) std::_Bit_iterator_base = {
2045 (_Bit_type *) _M_p = 0x0016b160
2046 (unsigned int) _M_offset = 0
2047 }
2048 }
2049 (std::_Bit_iterator) _M_finish = {
2050 (std::_Bit_iterator_base) std::_Bit_iterator_base = {
2051 (_Bit_type *) _M_p = 0x0016b16c
2052 (unsigned int) _M_offset = 16
2053 }
2054 }
2055 (_Bit_type *) _M_end_of_storage = 0x0016b170
2056 }
2057 }
2058 }
2059*/
2060
2061bool
2062lldb_private::formatters::LibstdcppVectorBoolSyntheticFrontEnd::Update()
2063{
2064 ValueObjectSP valobj_sp = m_backend.GetSP();
2065 if (!valobj_sp)
2066 return false;
2067 if (valobj_sp->IsDynamic())
2068 valobj_sp = valobj_sp->GetStaticValue();
2069 if (!valobj_sp)
2070 return false;
2071 m_exe_ctx_ref = valobj_sp->GetExecutionContextRef();
2072
2073 ValueObjectSP m_impl_sp(valobj_sp->GetChildMemberWithName(ConstString("_M_impl"), true));
2074 if (!m_impl_sp)
2075 return false;
2076
2077 ValueObjectSP m_start_sp(m_impl_sp->GetChildMemberWithName(ConstString("_M_start"), true));
2078 ValueObjectSP m_finish_sp(m_impl_sp->GetChildMemberWithName(ConstString("_M_finish"), true));
2079
2080 ValueObjectSP start_p_sp, finish_p_sp, finish_offset_sp;
2081
2082 if (!m_start_sp || !m_finish_sp)
2083 return false;
2084
2085 start_p_sp = m_start_sp->GetChildMemberWithName(ConstString("_M_p"), true);
2086 finish_p_sp = m_finish_sp->GetChildMemberWithName(ConstString("_M_p"), true);
2087 finish_offset_sp = m_finish_sp->GetChildMemberWithName(ConstString("_M_offset"), true);
2088
2089 if (!start_p_sp || !finish_offset_sp || !finish_p_sp)
2090 return false;
2091
2092 m_base_data_address = start_p_sp->GetValueAsUnsigned(0);
2093 if (!m_base_data_address)
2094 return false;
2095
2096 lldb::addr_t end_data_address(finish_p_sp->GetValueAsUnsigned(0));
2097 if (!end_data_address)
2098 return false;
2099
2100 if (end_data_address < m_base_data_address)
2101 return false;
2102 else
2103 m_count = finish_offset_sp->GetValueAsUnsigned(0) + (end_data_address-m_base_data_address)*8;
2104
2105 return true;
2106}
2107
2108bool
2109lldb_private::formatters::LibstdcppVectorBoolSyntheticFrontEnd::MightHaveChildren ()
2110{
2111 return true;
2112}
2113
2114size_t
2115lldb_private::formatters::LibstdcppVectorBoolSyntheticFrontEnd::GetIndexOfChildWithName (const ConstString &name)
2116{
2117 if (!m_count || !m_base_data_address)
2118 return UINT32_MAX;
2119 const char* item_name = name.GetCString();
2120 uint32_t idx = ExtractIndexFromString(item_name);
2121 if (idx < UINT32_MAX && idx >= CalculateNumChildren())
2122 return UINT32_MAX;
2123 return idx;
2124}
2125
2126lldb_private::formatters::LibstdcppVectorBoolSyntheticFrontEnd::~LibstdcppVectorBoolSyntheticFrontEnd ()
2127{}
2128
2129SyntheticChildrenFrontEnd*
2130lldb_private::formatters::LibstdcppVectorBoolSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP valobj_sp)
2131{
2132 if (!valobj_sp)
2133 return NULL;
2134 return (new LibstdcppVectorBoolSyntheticFrontEnd(valobj_sp));
2135}
2136
Enrico Granatacaaf0102012-09-04 18:48:21 +00002137template bool
Enrico Granataf91e78f2012-09-13 18:27:09 +00002138lldb_private::formatters::NSDictionarySummaryProvider<true> (ValueObject&, Stream&) ;
Enrico Granatacaaf0102012-09-04 18:48:21 +00002139
2140template bool
Enrico Granataf91e78f2012-09-13 18:27:09 +00002141lldb_private::formatters::NSDictionarySummaryProvider<false> (ValueObject&, Stream&) ;
Enrico Granatacaaf0102012-09-04 18:48:21 +00002142
2143template bool
Enrico Granataf91e78f2012-09-13 18:27:09 +00002144lldb_private::formatters::NSDataSummaryProvider<true> (ValueObject&, Stream&) ;
2145
2146template bool
2147lldb_private::formatters::NSDataSummaryProvider<false> (ValueObject&, Stream&) ;
Enrico Granatadb054912012-10-29 21:18:03 +00002148
2149template bool
2150lldb_private::formatters::ObjCSELSummaryProvider<true> (ValueObject&, Stream&) ;
2151
2152template bool
2153lldb_private::formatters::ObjCSELSummaryProvider<false> (ValueObject&, Stream&) ;