blob: 68605862ddddef11de0ada19017a3c7df2559b28 [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
1016lldb_private::formatters::RuntimeSpecificDescriptionSummaryProvider (ValueObject& valobj, Stream& stream)
1017{
1018 stream.Printf("%s",valobj.GetObjectDescription());
1019 return true;
1020}
1021
Enrico Granatadb054912012-10-29 21:18:03 +00001022bool
1023lldb_private::formatters::ObjCBOOLSummaryProvider (ValueObject& valobj, Stream& stream)
1024{
1025 const uint32_t type_info = ClangASTContext::GetTypeInfo(valobj.GetClangType(),
1026 valobj.GetClangAST(),
1027 NULL);
1028
1029 ValueObjectSP real_guy_sp = valobj.GetSP();
1030
1031 if (type_info & ClangASTContext::eTypeIsPointer)
1032 {
1033 Error err;
1034 real_guy_sp = valobj.Dereference(err);
1035 if (err.Fail() || !real_guy_sp)
1036 return false;
1037 }
1038 else if (type_info & ClangASTContext::eTypeIsReference)
1039 {
1040 real_guy_sp = valobj.GetChildAtIndex(0, true);
1041 if (!real_guy_sp)
1042 return false;
1043 }
1044 uint64_t value = real_guy_sp->GetValueAsUnsigned(0);
1045 if (value == 0)
1046 {
1047 stream.Printf("NO");
1048 return true;
1049 }
1050 stream.Printf("YES");
1051 return true;
1052}
1053
1054template <bool is_sel_ptr>
1055bool
1056lldb_private::formatters::ObjCSELSummaryProvider (ValueObject& valobj, Stream& stream)
1057{
1058 lldb::addr_t data_address = LLDB_INVALID_ADDRESS;
1059
1060 if (is_sel_ptr)
1061 data_address = valobj.GetValueAsUnsigned(LLDB_INVALID_ADDRESS);
1062 else
1063 data_address = valobj.GetAddressOf();
1064
1065 if (data_address == LLDB_INVALID_ADDRESS)
1066 return false;
1067
1068 ExecutionContext exe_ctx(valobj.GetExecutionContextRef());
1069
1070 void* char_opaque_type = valobj.GetClangAST()->CharTy.getAsOpaquePtr();
1071 ClangASTType charstar(valobj.GetClangAST(),ClangASTType::GetPointerType(valobj.GetClangAST(), char_opaque_type));
1072
1073 ValueObjectSP valobj_sp(ValueObject::CreateValueObjectFromAddress("text", data_address, exe_ctx, charstar));
1074
1075 stream.Printf("%s",valobj_sp->GetSummaryAsCString());
1076 return true;
1077}
1078
Enrico Granataf91e78f2012-09-13 18:27:09 +00001079lldb_private::formatters::NSArrayMSyntheticFrontEnd::NSArrayMSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp) :
1080SyntheticChildrenFrontEnd(*valobj_sp.get()),
1081m_exe_ctx_ref(),
1082m_ptr_size(8),
1083m_data_32(NULL),
1084m_data_64(NULL)
1085{
Enrico Granata247da332012-10-04 21:04:46 +00001086 if (valobj_sp)
Enrico Granataf91e78f2012-09-13 18:27:09 +00001087 {
Enrico Granata247da332012-10-04 21:04:46 +00001088 m_id_type = ClangASTType(valobj_sp->GetClangAST(),valobj_sp->GetClangAST()->ObjCBuiltinIdTy.getAsOpaquePtr());
1089 Update();
Enrico Granataf91e78f2012-09-13 18:27:09 +00001090 }
Enrico Granataf91e78f2012-09-13 18:27:09 +00001091}
1092
Greg Clayton36da2aa2013-01-25 18:06:21 +00001093size_t
Enrico Granataf91e78f2012-09-13 18:27:09 +00001094lldb_private::formatters::NSArrayMSyntheticFrontEnd::CalculateNumChildren ()
1095{
1096 if (m_data_32)
1097 return m_data_32->_used;
1098 if (m_data_64)
1099 return m_data_64->_used;
1100 return 0;
1101}
1102
1103lldb::ValueObjectSP
Greg Clayton36da2aa2013-01-25 18:06:21 +00001104lldb_private::formatters::NSArrayMSyntheticFrontEnd::GetChildAtIndex (size_t idx)
Enrico Granataf91e78f2012-09-13 18:27:09 +00001105{
1106 if (!m_data_32 && !m_data_64)
1107 return lldb::ValueObjectSP();
1108 if (idx >= CalculateNumChildren())
1109 return lldb::ValueObjectSP();
1110 lldb::addr_t object_at_idx = (m_data_32 ? m_data_32->_data : m_data_64->_data);
1111 object_at_idx += (idx * m_ptr_size);
1112 StreamString idx_name;
Greg Clayton36da2aa2013-01-25 18:06:21 +00001113 idx_name.Printf("[%zu]",idx);
Enrico Granataf91e78f2012-09-13 18:27:09 +00001114 lldb::ValueObjectSP retval_sp = ValueObject::CreateValueObjectFromAddress(idx_name.GetData(),
1115 object_at_idx,
1116 m_exe_ctx_ref,
1117 m_id_type);
1118 m_children.push_back(retval_sp);
1119 return retval_sp;
1120}
1121
1122bool
1123lldb_private::formatters::NSArrayMSyntheticFrontEnd::Update()
1124{
1125 m_children.clear();
Enrico Granata247da332012-10-04 21:04:46 +00001126 ValueObjectSP valobj_sp = m_backend.GetSP();
1127 m_ptr_size = 0;
1128 delete m_data_32;
1129 m_data_32 = NULL;
1130 delete m_data_64;
1131 m_data_64 = NULL;
1132 if (valobj_sp->IsDynamic())
1133 valobj_sp = valobj_sp->GetStaticValue();
1134 if (!valobj_sp)
1135 return false;
1136 m_exe_ctx_ref = valobj_sp->GetExecutionContextRef();
1137 Error error;
1138 if (valobj_sp->IsPointerType())
1139 {
1140 valobj_sp = valobj_sp->Dereference(error);
1141 if (error.Fail() || !valobj_sp)
1142 return false;
1143 }
1144 error.Clear();
1145 lldb::ProcessSP process_sp(valobj_sp->GetProcessSP());
1146 if (!process_sp)
1147 return false;
1148 m_ptr_size = process_sp->GetAddressByteSize();
1149 uint64_t data_location = valobj_sp->GetAddressOf() + m_ptr_size;
1150 if (m_ptr_size == 4)
1151 {
1152 m_data_32 = new DataDescriptor_32();
1153 process_sp->ReadMemory (data_location, m_data_32, sizeof(DataDescriptor_32), error);
1154 }
1155 else
1156 {
1157 m_data_64 = new DataDescriptor_64();
1158 process_sp->ReadMemory (data_location, m_data_64, sizeof(DataDescriptor_64), error);
1159 }
1160 if (error.Fail())
1161 return false;
Enrico Granataf91e78f2012-09-13 18:27:09 +00001162 return false;
1163}
1164
Enrico Granata800332c2012-10-23 19:54:09 +00001165bool
1166lldb_private::formatters::NSArrayMSyntheticFrontEnd::MightHaveChildren ()
1167{
Enrico Granataf3c10482012-12-10 19:55:53 +00001168 return true;
Enrico Granata800332c2012-10-23 19:54:09 +00001169}
1170
Enrico Granataf91e78f2012-09-13 18:27:09 +00001171static uint32_t
1172ExtractIndexFromString (const char* item_name)
1173{
1174 if (!item_name || !*item_name)
1175 return UINT32_MAX;
1176 if (*item_name != '[')
1177 return UINT32_MAX;
1178 item_name++;
1179 uint32_t idx = 0;
1180 while(*item_name)
1181 {
1182 char x = *item_name;
1183 if (x == ']')
1184 break;
1185 if (x < '0' || x > '9')
1186 return UINT32_MAX;
1187 idx = 10*idx + (x-'0');
1188 item_name++;
1189 }
1190 return idx;
1191}
1192
Enrico Granataf509c5e2013-01-28 23:47:25 +00001193size_t
Enrico Granataf91e78f2012-09-13 18:27:09 +00001194lldb_private::formatters::NSArrayMSyntheticFrontEnd::GetIndexOfChildWithName (const ConstString &name)
1195{
1196 if (!m_data_32 && !m_data_64)
1197 return UINT32_MAX;
1198 const char* item_name = name.GetCString();
1199 uint32_t idx = ExtractIndexFromString(item_name);
1200 if (idx < UINT32_MAX && idx >= CalculateNumChildren())
1201 return UINT32_MAX;
1202 return idx;
1203}
1204
1205lldb_private::formatters::NSArrayMSyntheticFrontEnd::~NSArrayMSyntheticFrontEnd ()
1206{
1207 delete m_data_32;
1208 m_data_32 = NULL;
1209 delete m_data_64;
1210 m_data_64 = NULL;
1211}
1212
1213lldb_private::formatters::NSArrayISyntheticFrontEnd::NSArrayISyntheticFrontEnd (lldb::ValueObjectSP valobj_sp) :
1214SyntheticChildrenFrontEnd(*valobj_sp.get()),
1215m_exe_ctx_ref(),
1216m_ptr_size(8),
1217m_items(0),
1218m_data_ptr(0)
1219{
Enrico Granata247da332012-10-04 21:04:46 +00001220 if (valobj_sp)
Enrico Granataf91e78f2012-09-13 18:27:09 +00001221 {
Enrico Granata247da332012-10-04 21:04:46 +00001222 m_id_type = ClangASTType(valobj_sp->GetClangAST(),valobj_sp->GetClangAST()->ObjCBuiltinIdTy.getAsOpaquePtr());
1223 Update();
Enrico Granataf91e78f2012-09-13 18:27:09 +00001224 }
Enrico Granataf91e78f2012-09-13 18:27:09 +00001225}
1226
1227lldb_private::formatters::NSArrayISyntheticFrontEnd::~NSArrayISyntheticFrontEnd ()
1228{
1229}
1230
Enrico Granataf509c5e2013-01-28 23:47:25 +00001231size_t
Enrico Granataf91e78f2012-09-13 18:27:09 +00001232lldb_private::formatters::NSArrayISyntheticFrontEnd::GetIndexOfChildWithName (const ConstString &name)
1233{
1234 const char* item_name = name.GetCString();
1235 uint32_t idx = ExtractIndexFromString(item_name);
1236 if (idx < UINT32_MAX && idx >= CalculateNumChildren())
1237 return UINT32_MAX;
1238 return idx;
1239}
1240
Greg Clayton36da2aa2013-01-25 18:06:21 +00001241size_t
Enrico Granataf91e78f2012-09-13 18:27:09 +00001242lldb_private::formatters::NSArrayISyntheticFrontEnd::CalculateNumChildren ()
1243{
1244 return m_items;
1245}
1246
1247bool
1248lldb_private::formatters::NSArrayISyntheticFrontEnd::Update()
1249{
Enrico Granata247da332012-10-04 21:04:46 +00001250 m_ptr_size = 0;
1251 m_items = 0;
1252 m_data_ptr = 0;
Enrico Granataf91e78f2012-09-13 18:27:09 +00001253 m_children.clear();
Enrico Granata247da332012-10-04 21:04:46 +00001254 ValueObjectSP valobj_sp = m_backend.GetSP();
1255 if (valobj_sp->IsDynamic())
1256 valobj_sp = valobj_sp->GetStaticValue();
1257 if (!valobj_sp)
1258 return false;
1259 m_exe_ctx_ref = valobj_sp->GetExecutionContextRef();
1260 Error error;
1261 if (valobj_sp->IsPointerType())
1262 {
1263 valobj_sp = valobj_sp->Dereference(error);
1264 if (error.Fail() || !valobj_sp)
1265 return false;
1266 }
1267 error.Clear();
1268 lldb::ProcessSP process_sp(valobj_sp->GetProcessSP());
1269 if (!process_sp)
1270 return false;
1271 m_ptr_size = process_sp->GetAddressByteSize();
1272 uint64_t data_location = valobj_sp->GetAddressOf() + m_ptr_size;
1273 m_items = process_sp->ReadPointerFromMemory(data_location, error);
1274 if (error.Fail())
1275 return false;
1276 m_data_ptr = data_location+m_ptr_size;
Enrico Granataf91e78f2012-09-13 18:27:09 +00001277 return false;
1278}
1279
Enrico Granata800332c2012-10-23 19:54:09 +00001280bool
1281lldb_private::formatters::NSArrayISyntheticFrontEnd::MightHaveChildren ()
1282{
Enrico Granataf3c10482012-12-10 19:55:53 +00001283 return true;
Enrico Granata800332c2012-10-23 19:54:09 +00001284}
1285
Enrico Granataf91e78f2012-09-13 18:27:09 +00001286lldb::ValueObjectSP
Greg Clayton36da2aa2013-01-25 18:06:21 +00001287lldb_private::formatters::NSArrayISyntheticFrontEnd::GetChildAtIndex (size_t idx)
Enrico Granataf91e78f2012-09-13 18:27:09 +00001288{
1289 if (idx >= CalculateNumChildren())
1290 return lldb::ValueObjectSP();
1291 lldb::addr_t object_at_idx = m_data_ptr;
1292 object_at_idx += (idx * m_ptr_size);
1293 ProcessSP process_sp = m_exe_ctx_ref.GetProcessSP();
1294 if (!process_sp)
1295 return lldb::ValueObjectSP();
1296 Error error;
1297 object_at_idx = process_sp->ReadPointerFromMemory(object_at_idx, error);
1298 if (error.Fail())
1299 return lldb::ValueObjectSP();
1300 StreamString expr;
Daniel Malea5f35a4b2012-11-29 21:49:15 +00001301 expr.Printf("(id)%" PRIu64,object_at_idx);
Enrico Granataf91e78f2012-09-13 18:27:09 +00001302 StreamString idx_name;
Greg Clayton36da2aa2013-01-25 18:06:21 +00001303 idx_name.Printf("[%zu]",idx);
Enrico Granataf91e78f2012-09-13 18:27:09 +00001304 lldb::ValueObjectSP retval_sp = ValueObject::CreateValueObjectFromExpression(idx_name.GetData(), expr.GetData(), m_exe_ctx_ref);
1305 m_children.push_back(retval_sp);
1306 return retval_sp;
1307}
1308
1309SyntheticChildrenFrontEnd* lldb_private::formatters::NSArraySyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP valobj_sp)
1310{
1311 lldb::ProcessSP process_sp (valobj_sp->GetProcessSP());
1312 if (!process_sp)
1313 return NULL;
1314 ObjCLanguageRuntime *runtime = (ObjCLanguageRuntime*)process_sp->GetLanguageRuntime(lldb::eLanguageTypeObjC);
1315 if (!runtime)
1316 return NULL;
1317
1318 if (!valobj_sp->IsPointerType())
1319 {
1320 Error error;
1321 valobj_sp = valobj_sp->AddressOf(error);
1322 if (error.Fail() || !valobj_sp)
1323 return NULL;
1324 }
1325
1326 ObjCLanguageRuntime::ClassDescriptorSP descriptor(runtime->GetClassDescriptor(*valobj_sp.get()));
1327
1328 if (!descriptor.get() || !descriptor->IsValid())
1329 return NULL;
1330
1331 const char* class_name = descriptor->GetClassName().GetCString();
Enrico Granata7685a562012-09-29 00:47:43 +00001332
1333 if (!class_name || !*class_name)
1334 return NULL;
1335
Enrico Granataf91e78f2012-09-13 18:27:09 +00001336 if (!strcmp(class_name,"__NSArrayI"))
1337 {
1338 return (new NSArrayISyntheticFrontEnd(valobj_sp));
1339 }
1340 else if (!strcmp(class_name,"__NSArrayM"))
1341 {
1342 return (new NSArrayMSyntheticFrontEnd(valobj_sp));
1343 }
1344 else
1345 {
1346 return (new NSArrayCodeRunningSyntheticFrontEnd(valobj_sp));
1347 }
1348}
1349
1350lldb_private::formatters::NSArrayCodeRunningSyntheticFrontEnd::NSArrayCodeRunningSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp) :
1351SyntheticChildrenFrontEnd(*valobj_sp.get())
1352{}
1353
Greg Clayton36da2aa2013-01-25 18:06:21 +00001354size_t
Enrico Granataf91e78f2012-09-13 18:27:09 +00001355lldb_private::formatters::NSArrayCodeRunningSyntheticFrontEnd::CalculateNumChildren ()
1356{
Enrico Granataf91e78f2012-09-13 18:27:09 +00001357 uint64_t count = 0;
1358 if (ExtractValueFromObjCExpression(m_backend, "int", "count", count))
1359 return count;
1360 return 0;
1361}
1362
1363lldb::ValueObjectSP
Greg Clayton36da2aa2013-01-25 18:06:21 +00001364lldb_private::formatters::NSArrayCodeRunningSyntheticFrontEnd::GetChildAtIndex (size_t idx)
Enrico Granataf91e78f2012-09-13 18:27:09 +00001365{
1366 StreamString idx_name;
Greg Clayton36da2aa2013-01-25 18:06:21 +00001367 idx_name.Printf("[%zu]",idx);
Enrico Granataf91e78f2012-09-13 18:27:09 +00001368 lldb::ValueObjectSP valobj_sp = CallSelectorOnObject(m_backend,"id","objectAtIndex:",idx);
1369 if (valobj_sp)
1370 valobj_sp->SetName(ConstString(idx_name.GetData()));
1371 return valobj_sp;
1372}
1373
1374bool
1375lldb_private::formatters::NSArrayCodeRunningSyntheticFrontEnd::Update()
1376{
1377 return false;
1378}
1379
Enrico Granata800332c2012-10-23 19:54:09 +00001380bool
1381lldb_private::formatters::NSArrayCodeRunningSyntheticFrontEnd::MightHaveChildren ()
1382{
Enrico Granataf3c10482012-12-10 19:55:53 +00001383 return true;
Enrico Granata800332c2012-10-23 19:54:09 +00001384}
1385
Enrico Granataf509c5e2013-01-28 23:47:25 +00001386size_t
Enrico Granataf91e78f2012-09-13 18:27:09 +00001387lldb_private::formatters::NSArrayCodeRunningSyntheticFrontEnd::GetIndexOfChildWithName (const ConstString &name)
1388{
1389 return 0;
1390}
1391
1392lldb_private::formatters::NSArrayCodeRunningSyntheticFrontEnd::~NSArrayCodeRunningSyntheticFrontEnd ()
1393{}
1394
Enrico Granata3a08fd12012-09-18 17:43:16 +00001395SyntheticChildrenFrontEnd* lldb_private::formatters::NSDictionarySyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP valobj_sp)
1396{
1397
1398 lldb::ProcessSP process_sp (valobj_sp->GetProcessSP());
1399 if (!process_sp)
1400 return NULL;
1401 ObjCLanguageRuntime *runtime = (ObjCLanguageRuntime*)process_sp->GetLanguageRuntime(lldb::eLanguageTypeObjC);
1402 if (!runtime)
1403 return NULL;
1404
1405 if (!valobj_sp->IsPointerType())
1406 {
1407 Error error;
1408 valobj_sp = valobj_sp->AddressOf(error);
1409 if (error.Fail() || !valobj_sp)
1410 return NULL;
1411 }
1412
1413 ObjCLanguageRuntime::ClassDescriptorSP descriptor(runtime->GetClassDescriptor(*valobj_sp.get()));
1414
1415 if (!descriptor.get() || !descriptor->IsValid())
1416 return NULL;
1417
1418 const char* class_name = descriptor->GetClassName().GetCString();
Enrico Granata7685a562012-09-29 00:47:43 +00001419
1420 if (!class_name || !*class_name)
1421 return NULL;
1422
Enrico Granata3a08fd12012-09-18 17:43:16 +00001423 if (!strcmp(class_name,"__NSDictionaryI"))
1424 {
1425 return (new NSDictionaryISyntheticFrontEnd(valobj_sp));
1426 }
1427 else if (!strcmp(class_name,"__NSDictionaryM"))
1428 {
1429 return (new NSDictionaryMSyntheticFrontEnd(valobj_sp));
1430 }
1431 else
1432 {
1433 return (new NSDictionaryCodeRunningSyntheticFrontEnd(valobj_sp));
1434 }
1435}
1436
1437lldb_private::formatters::NSDictionaryCodeRunningSyntheticFrontEnd::NSDictionaryCodeRunningSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp) :
1438SyntheticChildrenFrontEnd(*valobj_sp.get())
1439{}
1440
Greg Clayton36da2aa2013-01-25 18:06:21 +00001441size_t
Enrico Granata3a08fd12012-09-18 17:43:16 +00001442lldb_private::formatters::NSDictionaryCodeRunningSyntheticFrontEnd::CalculateNumChildren ()
1443{
1444 uint64_t count = 0;
1445 if (ExtractValueFromObjCExpression(m_backend, "int", "count", count))
1446 return count;
1447 return 0;
1448}
1449
1450lldb::ValueObjectSP
Greg Clayton36da2aa2013-01-25 18:06:21 +00001451lldb_private::formatters::NSDictionaryCodeRunningSyntheticFrontEnd::GetChildAtIndex (size_t idx)
Enrico Granata3a08fd12012-09-18 17:43:16 +00001452{
1453 StreamString idx_name;
Greg Clayton36da2aa2013-01-25 18:06:21 +00001454 idx_name.Printf("[%zu]",idx);
Enrico Granata3a08fd12012-09-18 17:43:16 +00001455 StreamString valobj_expr_path;
1456 m_backend.GetExpressionPath(valobj_expr_path, false);
1457 StreamString key_fetcher_expr;
Greg Clayton36da2aa2013-01-25 18:06:21 +00001458 key_fetcher_expr.Printf("(id)[(NSArray*)[%s allKeys] objectAtIndex:%zu]",valobj_expr_path.GetData(),idx);
Enrico Granata3a08fd12012-09-18 17:43:16 +00001459 StreamString value_fetcher_expr;
1460 value_fetcher_expr.Printf("(id)[%s objectForKey:%s]",valobj_expr_path.GetData(),key_fetcher_expr.GetData());
1461 StreamString object_fetcher_expr;
Enrico Granatafd3d28d2012-10-01 21:49:10 +00001462 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 +00001463 lldb::ValueObjectSP child_sp;
1464 m_backend.GetTargetSP()->EvaluateExpression(object_fetcher_expr.GetData(), m_backend.GetFrameSP().get(), child_sp,
Jim Ingham47beabb2012-10-16 21:41:58 +00001465 EvaluateExpressionOptions().SetKeepInMemory(true));
Enrico Granata3a08fd12012-09-18 17:43:16 +00001466 if (child_sp)
1467 child_sp->SetName(ConstString(idx_name.GetData()));
1468 return child_sp;
1469}
1470
1471bool
1472lldb_private::formatters::NSDictionaryCodeRunningSyntheticFrontEnd::Update()
1473{
1474 return false;
1475}
1476
Enrico Granata800332c2012-10-23 19:54:09 +00001477bool
1478lldb_private::formatters::NSDictionaryCodeRunningSyntheticFrontEnd::MightHaveChildren ()
1479{
Enrico Granataf3c10482012-12-10 19:55:53 +00001480 return true;
Enrico Granata800332c2012-10-23 19:54:09 +00001481}
1482
Enrico Granataf509c5e2013-01-28 23:47:25 +00001483size_t
Enrico Granata3a08fd12012-09-18 17:43:16 +00001484lldb_private::formatters::NSDictionaryCodeRunningSyntheticFrontEnd::GetIndexOfChildWithName (const ConstString &name)
1485{
1486 return 0;
1487}
1488
1489lldb_private::formatters::NSDictionaryCodeRunningSyntheticFrontEnd::~NSDictionaryCodeRunningSyntheticFrontEnd ()
1490{}
1491
1492lldb_private::formatters::NSDictionaryISyntheticFrontEnd::NSDictionaryISyntheticFrontEnd (lldb::ValueObjectSP valobj_sp) :
1493 SyntheticChildrenFrontEnd(*valobj_sp.get()),
1494 m_exe_ctx_ref(),
1495 m_ptr_size(8),
1496 m_data_32(NULL),
1497 m_data_64(NULL)
1498{
Enrico Granataa787c1a2012-10-04 21:46:06 +00001499 if (valobj_sp)
1500 Update();
Enrico Granata3a08fd12012-09-18 17:43:16 +00001501}
1502
1503lldb_private::formatters::NSDictionaryISyntheticFrontEnd::~NSDictionaryISyntheticFrontEnd ()
1504{
1505 delete m_data_32;
1506 m_data_32 = NULL;
1507 delete m_data_64;
1508 m_data_64 = NULL;
1509}
1510
Enrico Granataf509c5e2013-01-28 23:47:25 +00001511size_t
Enrico Granata3a08fd12012-09-18 17:43:16 +00001512lldb_private::formatters::NSDictionaryISyntheticFrontEnd::GetIndexOfChildWithName (const ConstString &name)
1513{
1514 const char* item_name = name.GetCString();
1515 uint32_t idx = ExtractIndexFromString(item_name);
1516 if (idx < UINT32_MAX && idx >= CalculateNumChildren())
1517 return UINT32_MAX;
1518 return idx;
1519}
1520
Greg Clayton36da2aa2013-01-25 18:06:21 +00001521size_t
Enrico Granata3a08fd12012-09-18 17:43:16 +00001522lldb_private::formatters::NSDictionaryISyntheticFrontEnd::CalculateNumChildren ()
1523{
1524 if (!m_data_32 && !m_data_64)
1525 return 0;
1526 return (m_data_32 ? m_data_32->_used : m_data_64->_used);
1527}
1528
1529bool
1530lldb_private::formatters::NSDictionaryISyntheticFrontEnd::Update()
1531{
1532 m_children.clear();
Enrico Granataa787c1a2012-10-04 21:46:06 +00001533 delete m_data_32;
1534 m_data_32 = NULL;
1535 delete m_data_64;
1536 m_data_64 = NULL;
1537 m_ptr_size = 0;
1538 ValueObjectSP valobj_sp = m_backend.GetSP();
1539 if (!valobj_sp)
1540 return false;
1541 if (valobj_sp->IsDynamic())
1542 valobj_sp = valobj_sp->GetStaticValue();
1543 if (!valobj_sp)
1544 return false;
1545 m_exe_ctx_ref = valobj_sp->GetExecutionContextRef();
1546 Error error;
1547 if (valobj_sp->IsPointerType())
1548 {
1549 valobj_sp = valobj_sp->Dereference(error);
1550 if (error.Fail() || !valobj_sp)
1551 return false;
1552 }
1553 error.Clear();
1554 lldb::ProcessSP process_sp(valobj_sp->GetProcessSP());
1555 if (!process_sp)
1556 return false;
1557 m_ptr_size = process_sp->GetAddressByteSize();
1558 uint64_t data_location = valobj_sp->GetAddressOf() + m_ptr_size;
1559 if (m_ptr_size == 4)
1560 {
1561 m_data_32 = new DataDescriptor_32();
1562 process_sp->ReadMemory (data_location, m_data_32, sizeof(DataDescriptor_32), error);
1563 }
1564 else
1565 {
1566 m_data_64 = new DataDescriptor_64();
1567 process_sp->ReadMemory (data_location, m_data_64, sizeof(DataDescriptor_64), error);
1568 }
1569 if (error.Fail())
1570 return false;
1571 m_data_ptr = data_location + m_ptr_size;
Enrico Granata3a08fd12012-09-18 17:43:16 +00001572 return false;
1573}
1574
Enrico Granata800332c2012-10-23 19:54:09 +00001575bool
1576lldb_private::formatters::NSDictionaryISyntheticFrontEnd::MightHaveChildren ()
1577{
Enrico Granataf3c10482012-12-10 19:55:53 +00001578 return true;
Enrico Granata800332c2012-10-23 19:54:09 +00001579}
1580
Enrico Granata3a08fd12012-09-18 17:43:16 +00001581lldb::ValueObjectSP
Greg Clayton36da2aa2013-01-25 18:06:21 +00001582lldb_private::formatters::NSDictionaryISyntheticFrontEnd::GetChildAtIndex (size_t idx)
Enrico Granata3a08fd12012-09-18 17:43:16 +00001583{
1584 uint32_t num_children = CalculateNumChildren();
1585
1586 if (idx >= num_children)
1587 return lldb::ValueObjectSP();
1588
1589 if (m_children.empty())
1590 {
1591 // do the scan phase
1592 lldb::addr_t key_at_idx = 0, val_at_idx = 0;
1593
1594 uint32_t tries = 0;
1595 uint32_t test_idx = 0;
1596
1597 while(tries < num_children)
1598 {
1599 key_at_idx = m_data_ptr + (2*test_idx * m_ptr_size);
1600 val_at_idx = key_at_idx + m_ptr_size;
1601 ProcessSP process_sp = m_exe_ctx_ref.GetProcessSP();
1602 if (!process_sp)
1603 return lldb::ValueObjectSP();
1604 Error error;
1605 key_at_idx = process_sp->ReadPointerFromMemory(key_at_idx, error);
1606 if (error.Fail())
1607 return lldb::ValueObjectSP();
1608 val_at_idx = process_sp->ReadPointerFromMemory(val_at_idx, error);
1609 if (error.Fail())
1610 return lldb::ValueObjectSP();
1611
1612 test_idx++;
1613
1614 if (!key_at_idx || !val_at_idx)
1615 continue;
1616 tries++;
1617
1618 DictionaryItemDescriptor descriptor = {key_at_idx,val_at_idx,lldb::ValueObjectSP()};
1619
1620 m_children.push_back(descriptor);
1621 }
1622 }
1623
1624 if (idx >= m_children.size()) // should never happen
1625 return lldb::ValueObjectSP();
1626
1627 DictionaryItemDescriptor &dict_item = m_children[idx];
1628 if (!dict_item.valobj_sp)
1629 {
1630 // make the new ValueObject
1631 StreamString expr;
Daniel Malea5f35a4b2012-11-29 21:49:15 +00001632 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 +00001633 StreamString idx_name;
Greg Clayton36da2aa2013-01-25 18:06:21 +00001634 idx_name.Printf("[%zu]",idx);
Enrico Granata3a08fd12012-09-18 17:43:16 +00001635 dict_item.valobj_sp = ValueObject::CreateValueObjectFromExpression(idx_name.GetData(), expr.GetData(), m_exe_ctx_ref);
1636 }
1637 return dict_item.valobj_sp;
1638}
1639
1640lldb_private::formatters::NSDictionaryMSyntheticFrontEnd::NSDictionaryMSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp) :
1641 SyntheticChildrenFrontEnd(*valobj_sp.get()),
1642 m_exe_ctx_ref(),
1643 m_ptr_size(8),
1644 m_data_32(NULL),
1645 m_data_64(NULL)
1646{
Enrico Granataa787c1a2012-10-04 21:46:06 +00001647 if (valobj_sp)
1648 Update ();
Enrico Granata3a08fd12012-09-18 17:43:16 +00001649}
1650
1651lldb_private::formatters::NSDictionaryMSyntheticFrontEnd::~NSDictionaryMSyntheticFrontEnd ()
1652{
1653 delete m_data_32;
1654 m_data_32 = NULL;
1655 delete m_data_64;
1656 m_data_64 = NULL;
1657}
1658
Enrico Granataf509c5e2013-01-28 23:47:25 +00001659size_t
Enrico Granata3a08fd12012-09-18 17:43:16 +00001660lldb_private::formatters::NSDictionaryMSyntheticFrontEnd::GetIndexOfChildWithName (const ConstString &name)
1661{
1662 const char* item_name = name.GetCString();
1663 uint32_t idx = ExtractIndexFromString(item_name);
1664 if (idx < UINT32_MAX && idx >= CalculateNumChildren())
1665 return UINT32_MAX;
1666 return idx;
1667}
1668
Greg Clayton36da2aa2013-01-25 18:06:21 +00001669size_t
Enrico Granata3a08fd12012-09-18 17:43:16 +00001670lldb_private::formatters::NSDictionaryMSyntheticFrontEnd::CalculateNumChildren ()
1671{
1672 if (!m_data_32 && !m_data_64)
1673 return 0;
1674 return (m_data_32 ? m_data_32->_used : m_data_64->_used);
1675}
1676
1677bool
1678lldb_private::formatters::NSDictionaryMSyntheticFrontEnd::Update()
1679{
1680 m_children.clear();
Enrico Granataa787c1a2012-10-04 21:46:06 +00001681 ValueObjectSP valobj_sp = m_backend.GetSP();
1682 m_ptr_size = 0;
1683 delete m_data_32;
1684 m_data_32 = NULL;
1685 delete m_data_64;
1686 m_data_64 = NULL;
1687 if (!valobj_sp)
1688 return false;
1689 if (valobj_sp->IsDynamic())
1690 valobj_sp = valobj_sp->GetStaticValue();
1691 if (!valobj_sp)
1692 return false;
1693 m_exe_ctx_ref = valobj_sp->GetExecutionContextRef();
1694 Error error;
1695 if (valobj_sp->IsPointerType())
1696 {
1697 valobj_sp = valobj_sp->Dereference(error);
1698 if (error.Fail() || !valobj_sp)
1699 return false;
1700 }
1701 error.Clear();
1702 lldb::ProcessSP process_sp(valobj_sp->GetProcessSP());
1703 if (!process_sp)
1704 return false;
1705 m_ptr_size = process_sp->GetAddressByteSize();
1706 uint64_t data_location = valobj_sp->GetAddressOf() + m_ptr_size;
1707 if (m_ptr_size == 4)
1708 {
1709 m_data_32 = new DataDescriptor_32();
1710 process_sp->ReadMemory (data_location, m_data_32, sizeof(DataDescriptor_32), error);
1711 }
1712 else
1713 {
1714 m_data_64 = new DataDescriptor_64();
1715 process_sp->ReadMemory (data_location, m_data_64, sizeof(DataDescriptor_64), error);
1716 }
1717 if (error.Fail())
1718 return false;
Enrico Granata3a08fd12012-09-18 17:43:16 +00001719 return false;
1720}
1721
Enrico Granata800332c2012-10-23 19:54:09 +00001722bool
1723lldb_private::formatters::NSDictionaryMSyntheticFrontEnd::MightHaveChildren ()
1724{
Enrico Granataf3c10482012-12-10 19:55:53 +00001725 return true;
Enrico Granata800332c2012-10-23 19:54:09 +00001726}
1727
Enrico Granata3a08fd12012-09-18 17:43:16 +00001728lldb::ValueObjectSP
Greg Clayton36da2aa2013-01-25 18:06:21 +00001729lldb_private::formatters::NSDictionaryMSyntheticFrontEnd::GetChildAtIndex (size_t idx)
Enrico Granata3a08fd12012-09-18 17:43:16 +00001730{
1731 lldb::addr_t m_keys_ptr = (m_data_32 ? m_data_32->_keys_addr : m_data_64->_keys_addr);
1732 lldb::addr_t m_values_ptr = (m_data_32 ? m_data_32->_objs_addr : m_data_64->_objs_addr);
1733
1734 uint32_t num_children = CalculateNumChildren();
1735
1736 if (idx >= num_children)
1737 return lldb::ValueObjectSP();
1738
1739 if (m_children.empty())
1740 {
1741 // do the scan phase
1742 lldb::addr_t key_at_idx = 0, val_at_idx = 0;
1743
1744 uint32_t tries = 0;
1745 uint32_t test_idx = 0;
1746
1747 while(tries < num_children)
1748 {
1749 key_at_idx = m_keys_ptr + (test_idx * m_ptr_size);
1750 val_at_idx = m_values_ptr + (test_idx * m_ptr_size);;
1751 ProcessSP process_sp = m_exe_ctx_ref.GetProcessSP();
1752 if (!process_sp)
1753 return lldb::ValueObjectSP();
1754 Error error;
1755 key_at_idx = process_sp->ReadPointerFromMemory(key_at_idx, error);
1756 if (error.Fail())
1757 return lldb::ValueObjectSP();
1758 val_at_idx = process_sp->ReadPointerFromMemory(val_at_idx, error);
1759 if (error.Fail())
1760 return lldb::ValueObjectSP();
1761
1762 test_idx++;
1763
1764 if (!key_at_idx || !val_at_idx)
1765 continue;
1766 tries++;
1767
1768 DictionaryItemDescriptor descriptor = {key_at_idx,val_at_idx,lldb::ValueObjectSP()};
1769
1770 m_children.push_back(descriptor);
1771 }
1772 }
1773
1774 if (idx >= m_children.size()) // should never happen
1775 return lldb::ValueObjectSP();
1776
1777 DictionaryItemDescriptor &dict_item = m_children[idx];
1778 if (!dict_item.valobj_sp)
1779 {
1780 // make the new ValueObject
1781 StreamString expr;
Daniel Malea5f35a4b2012-11-29 21:49:15 +00001782 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 +00001783 StreamString idx_name;
Greg Clayton36da2aa2013-01-25 18:06:21 +00001784 idx_name.Printf("[%zu]",idx);
Enrico Granata3a08fd12012-09-18 17:43:16 +00001785 dict_item.valobj_sp = ValueObject::CreateValueObjectFromExpression(idx_name.GetData(), expr.GetData(), m_exe_ctx_ref);
1786 }
1787 return dict_item.valobj_sp;
1788}
Enrico Granatacaaf0102012-09-04 18:48:21 +00001789
Enrico Granata689696c2013-02-04 22:54:42 +00001790lldb_private::formatters::LibcxxVectorBoolSyntheticFrontEnd::LibcxxVectorBoolSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp) :
1791 SyntheticChildrenFrontEnd(*valobj_sp.get()),
1792 m_exe_ctx_ref(),
1793 m_count(0),
1794 m_base_data_address(0),
1795 m_options()
1796 {
1797 if (valobj_sp)
1798 Update();
1799 m_options.SetCoerceToId(false)
1800 .SetUnwindOnError(true)
1801 .SetKeepInMemory(true)
1802 .SetUseDynamic(lldb::eDynamicCanRunTarget);
1803 }
1804
1805size_t
1806lldb_private::formatters::LibcxxVectorBoolSyntheticFrontEnd::CalculateNumChildren ()
1807{
1808 return m_count;
1809}
1810
1811lldb::ValueObjectSP
1812lldb_private::formatters::LibcxxVectorBoolSyntheticFrontEnd::GetChildAtIndex (size_t idx)
1813{
1814 if (idx >= m_count)
1815 return ValueObjectSP();
1816 if (m_base_data_address == 0 || m_count == 0)
1817 return ValueObjectSP();
1818 size_t byte_idx = (idx >> 3); // divide by 8 to get byte index
1819 size_t bit_index = (idx & 7); // efficient idx % 8 for bit index
1820 lldb::addr_t byte_location = m_base_data_address + byte_idx;
1821 ProcessSP process_sp(m_exe_ctx_ref.GetProcessSP());
1822 if (!process_sp)
1823 return ValueObjectSP();
1824 uint8_t byte = 0;
1825 uint8_t mask = 0;
1826 Error err;
1827 size_t bytes_read = process_sp->ReadMemory(byte_location, &byte, 1, err);
1828 if (err.Fail() || bytes_read == 0)
1829 return ValueObjectSP();
1830 switch (bit_index)
1831 {
1832 case 0:
1833 mask = 1; break;
1834 case 1:
1835 mask = 2; break;
1836 case 2:
1837 mask = 4; break;
1838 case 3:
1839 mask = 8; break;
1840 case 4:
1841 mask = 16; break;
1842 case 5:
1843 mask = 32; break;
1844 case 6:
1845 mask = 64; break;
1846 case 7:
1847 mask = 128; break;
1848 default:
1849 return ValueObjectSP();
1850 }
1851 bool bit_set = ((byte & mask) != 0);
1852 Target& target(process_sp->GetTarget());
1853 ValueObjectSP retval_sp;
1854 if (bit_set)
1855 target.EvaluateExpression("(bool)true", NULL, retval_sp);
1856 else
1857 target.EvaluateExpression("(bool)false", NULL, retval_sp);
1858 StreamString name; name.Printf("[%zu]",idx);
1859 if (retval_sp)
1860 retval_sp->SetName(ConstString(name.GetData()));
1861 return retval_sp;
1862}
1863
1864/*(std::__1::vector<std::__1::allocator<bool> >) vBool = {
1865 __begin_ = 0x00000001001000e0
1866 __size_ = 56
1867 __cap_alloc_ = {
1868 std::__1::__libcpp_compressed_pair_imp<unsigned long, std::__1::allocator<unsigned long> > = {
1869 __first_ = 1
1870 }
1871 }
1872}*/
1873
1874bool
1875lldb_private::formatters::LibcxxVectorBoolSyntheticFrontEnd::Update()
1876{
1877 ValueObjectSP valobj_sp = m_backend.GetSP();
1878 if (!valobj_sp)
1879 return false;
1880 if (valobj_sp->IsDynamic())
1881 valobj_sp = valobj_sp->GetStaticValue();
1882 if (!valobj_sp)
1883 return false;
1884 m_exe_ctx_ref = valobj_sp->GetExecutionContextRef();
1885 ValueObjectSP size_sp(valobj_sp->GetChildMemberWithName(ConstString("__size_"), true));
1886 if (!size_sp)
1887 return false;
1888 m_count = size_sp->GetValueAsUnsigned(0);
1889 if (!m_count)
1890 return true;
1891 ValueObjectSP begin_sp(valobj_sp->GetChildMemberWithName(ConstString("__begin_"), true));
1892 if (!begin_sp)
1893 {
1894 m_count = 0;
1895 return false;
1896 }
1897 m_base_data_address = begin_sp->GetValueAsUnsigned(0);
1898 if (!m_base_data_address)
1899 {
1900 m_count = 0;
1901 return false;
1902 }
1903 return true;
1904}
1905
1906bool
1907lldb_private::formatters::LibcxxVectorBoolSyntheticFrontEnd::MightHaveChildren ()
1908{
1909 return true;
1910}
1911
1912size_t
1913lldb_private::formatters::LibcxxVectorBoolSyntheticFrontEnd::GetIndexOfChildWithName (const ConstString &name)
1914{
1915 if (!m_count || !m_base_data_address)
1916 return UINT32_MAX;
1917 const char* item_name = name.GetCString();
1918 uint32_t idx = ExtractIndexFromString(item_name);
1919 if (idx < UINT32_MAX && idx >= CalculateNumChildren())
1920 return UINT32_MAX;
1921 return idx;
1922}
1923
1924lldb_private::formatters::LibcxxVectorBoolSyntheticFrontEnd::~LibcxxVectorBoolSyntheticFrontEnd ()
1925{}
1926
1927SyntheticChildrenFrontEnd*
1928lldb_private::formatters::LibcxxVectorBoolSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP valobj_sp)
1929{
1930 if (!valobj_sp)
1931 return NULL;
1932 return (new LibcxxVectorBoolSyntheticFrontEnd(valobj_sp));
1933}
1934
1935lldb_private::formatters::LibstdcppVectorBoolSyntheticFrontEnd::LibstdcppVectorBoolSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp) :
1936SyntheticChildrenFrontEnd(*valobj_sp.get()),
1937m_exe_ctx_ref(),
1938m_count(0),
1939m_base_data_address(0),
1940m_options()
1941{
1942 if (valobj_sp)
1943 Update();
1944 m_options.SetCoerceToId(false)
1945 .SetUnwindOnError(true)
1946 .SetKeepInMemory(true)
1947 .SetUseDynamic(lldb::eDynamicCanRunTarget);
1948}
1949
1950size_t
1951lldb_private::formatters::LibstdcppVectorBoolSyntheticFrontEnd::CalculateNumChildren ()
1952{
1953 return m_count;
1954}
1955
1956lldb::ValueObjectSP
1957lldb_private::formatters::LibstdcppVectorBoolSyntheticFrontEnd::GetChildAtIndex (size_t idx)
1958{
1959 if (idx >= m_count)
1960 return ValueObjectSP();
1961 if (m_base_data_address == 0 || m_count == 0)
1962 return ValueObjectSP();
1963 size_t byte_idx = (idx >> 3); // divide by 8 to get byte index
1964 size_t bit_index = (idx & 7); // efficient idx % 8 for bit index
1965 lldb::addr_t byte_location = m_base_data_address + byte_idx;
1966 ProcessSP process_sp(m_exe_ctx_ref.GetProcessSP());
1967 if (!process_sp)
1968 return ValueObjectSP();
1969 uint8_t byte = 0;
1970 uint8_t mask = 0;
1971 Error err;
1972 size_t bytes_read = process_sp->ReadMemory(byte_location, &byte, 1, err);
1973 if (err.Fail() || bytes_read == 0)
1974 return ValueObjectSP();
1975 switch (bit_index)
1976 {
1977 case 0:
1978 mask = 1; break;
1979 case 1:
1980 mask = 2; break;
1981 case 2:
1982 mask = 4; break;
1983 case 3:
1984 mask = 8; break;
1985 case 4:
1986 mask = 16; break;
1987 case 5:
1988 mask = 32; break;
1989 case 6:
1990 mask = 64; break;
1991 case 7:
1992 mask = 128; break;
1993 default:
1994 return ValueObjectSP();
1995 }
1996 bool bit_set = ((byte & mask) != 0);
1997 Target& target(process_sp->GetTarget());
1998 ValueObjectSP retval_sp;
1999 if (bit_set)
2000 target.EvaluateExpression("(bool)true", NULL, retval_sp);
2001 else
2002 target.EvaluateExpression("(bool)false", NULL, retval_sp);
2003 StreamString name; name.Printf("[%zu]",idx);
2004 if (retval_sp)
2005 retval_sp->SetName(ConstString(name.GetData()));
2006 return retval_sp;
2007}
2008
2009/*((std::vector<std::allocator<bool> >) vBool = {
2010 (std::_Bvector_base<std::allocator<bool> >) std::_Bvector_base<std::allocator<bool> > = {
2011 (std::_Bvector_base<std::allocator<bool> >::_Bvector_impl) _M_impl = {
2012 (std::_Bit_iterator) _M_start = {
2013 (std::_Bit_iterator_base) std::_Bit_iterator_base = {
2014 (_Bit_type *) _M_p = 0x0016b160
2015 (unsigned int) _M_offset = 0
2016 }
2017 }
2018 (std::_Bit_iterator) _M_finish = {
2019 (std::_Bit_iterator_base) std::_Bit_iterator_base = {
2020 (_Bit_type *) _M_p = 0x0016b16c
2021 (unsigned int) _M_offset = 16
2022 }
2023 }
2024 (_Bit_type *) _M_end_of_storage = 0x0016b170
2025 }
2026 }
2027 }
2028*/
2029
2030bool
2031lldb_private::formatters::LibstdcppVectorBoolSyntheticFrontEnd::Update()
2032{
2033 ValueObjectSP valobj_sp = m_backend.GetSP();
2034 if (!valobj_sp)
2035 return false;
2036 if (valobj_sp->IsDynamic())
2037 valobj_sp = valobj_sp->GetStaticValue();
2038 if (!valobj_sp)
2039 return false;
2040 m_exe_ctx_ref = valobj_sp->GetExecutionContextRef();
2041
2042 ValueObjectSP m_impl_sp(valobj_sp->GetChildMemberWithName(ConstString("_M_impl"), true));
2043 if (!m_impl_sp)
2044 return false;
2045
2046 ValueObjectSP m_start_sp(m_impl_sp->GetChildMemberWithName(ConstString("_M_start"), true));
2047 ValueObjectSP m_finish_sp(m_impl_sp->GetChildMemberWithName(ConstString("_M_finish"), true));
2048
2049 ValueObjectSP start_p_sp, finish_p_sp, finish_offset_sp;
2050
2051 if (!m_start_sp || !m_finish_sp)
2052 return false;
2053
2054 start_p_sp = m_start_sp->GetChildMemberWithName(ConstString("_M_p"), true);
2055 finish_p_sp = m_finish_sp->GetChildMemberWithName(ConstString("_M_p"), true);
2056 finish_offset_sp = m_finish_sp->GetChildMemberWithName(ConstString("_M_offset"), true);
2057
2058 if (!start_p_sp || !finish_offset_sp || !finish_p_sp)
2059 return false;
2060
2061 m_base_data_address = start_p_sp->GetValueAsUnsigned(0);
2062 if (!m_base_data_address)
2063 return false;
2064
2065 lldb::addr_t end_data_address(finish_p_sp->GetValueAsUnsigned(0));
2066 if (!end_data_address)
2067 return false;
2068
2069 if (end_data_address < m_base_data_address)
2070 return false;
2071 else
2072 m_count = finish_offset_sp->GetValueAsUnsigned(0) + (end_data_address-m_base_data_address)*8;
2073
2074 return true;
2075}
2076
2077bool
2078lldb_private::formatters::LibstdcppVectorBoolSyntheticFrontEnd::MightHaveChildren ()
2079{
2080 return true;
2081}
2082
2083size_t
2084lldb_private::formatters::LibstdcppVectorBoolSyntheticFrontEnd::GetIndexOfChildWithName (const ConstString &name)
2085{
2086 if (!m_count || !m_base_data_address)
2087 return UINT32_MAX;
2088 const char* item_name = name.GetCString();
2089 uint32_t idx = ExtractIndexFromString(item_name);
2090 if (idx < UINT32_MAX && idx >= CalculateNumChildren())
2091 return UINT32_MAX;
2092 return idx;
2093}
2094
2095lldb_private::formatters::LibstdcppVectorBoolSyntheticFrontEnd::~LibstdcppVectorBoolSyntheticFrontEnd ()
2096{}
2097
2098SyntheticChildrenFrontEnd*
2099lldb_private::formatters::LibstdcppVectorBoolSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP valobj_sp)
2100{
2101 if (!valobj_sp)
2102 return NULL;
2103 return (new LibstdcppVectorBoolSyntheticFrontEnd(valobj_sp));
2104}
2105
Enrico Granatacaaf0102012-09-04 18:48:21 +00002106template bool
Enrico Granataf91e78f2012-09-13 18:27:09 +00002107lldb_private::formatters::NSDictionarySummaryProvider<true> (ValueObject&, Stream&) ;
Enrico Granatacaaf0102012-09-04 18:48:21 +00002108
2109template bool
Enrico Granataf91e78f2012-09-13 18:27:09 +00002110lldb_private::formatters::NSDictionarySummaryProvider<false> (ValueObject&, Stream&) ;
Enrico Granatacaaf0102012-09-04 18:48:21 +00002111
2112template bool
Enrico Granataf91e78f2012-09-13 18:27:09 +00002113lldb_private::formatters::NSDataSummaryProvider<true> (ValueObject&, Stream&) ;
2114
2115template bool
2116lldb_private::formatters::NSDataSummaryProvider<false> (ValueObject&, Stream&) ;
Enrico Granatadb054912012-10-29 21:18:03 +00002117
2118template bool
2119lldb_private::formatters::ObjCSELSummaryProvider<true> (ValueObject&, Stream&) ;
2120
2121template bool
2122lldb_private::formatters::ObjCSELSummaryProvider<false> (ValueObject&, Stream&) ;