1 //===-- CXXFormatterFunctions.cpp---------------------------------*- C++ -*-===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 #include "lldb/lldb-python.h"
12 #include "lldb/DataFormatters/CXXFormatterFunctions.h"
14 #include "llvm/Support/ConvertUTF.h"
16 #include "lldb/Core/DataBufferHeap.h"
17 #include "lldb/Core/Error.h"
18 #include "lldb/Core/Stream.h"
19 #include "lldb/Core/ValueObject.h"
20 #include "lldb/Core/ValueObjectConstResult.h"
21 #include "lldb/Host/Endian.h"
22 #include "lldb/Symbol/ClangASTContext.h"
23 #include "lldb/Target/ObjCLanguageRuntime.h"
24 #include "lldb/Target/Target.h"
29 using namespace lldb_private;
30 using namespace lldb_private::formatters;
33 lldb_private::formatters::ExtractValueFromObjCExpression (ValueObject &valobj,
34 const char* target_type,
38 if (!target_type || !*target_type)
40 if (!selector || !*selector)
43 expr.Printf("(%s)[(id)0x%" PRIx64 " %s]",target_type,valobj.GetPointerValue(),selector);
44 ExecutionContext exe_ctx (valobj.GetExecutionContextRef());
45 lldb::ValueObjectSP result_sp;
46 Target* target = exe_ctx.GetTargetPtr();
47 StackFrame* stack_frame = exe_ctx.GetFramePtr();
48 if (!target || !stack_frame)
51 EvaluateExpressionOptions options;
52 options.SetCoerceToId(false);
53 options.SetUnwindOnError(true);
54 options.SetKeepInMemory(true);
56 target->EvaluateExpression(expr.GetData(),
62 value = result_sp->GetValueAsUnsigned(0);
67 lldb_private::formatters::ExtractSummaryFromObjCExpression (ValueObject &valobj,
68 const char* target_type,
72 if (!target_type || !*target_type)
74 if (!selector || !*selector)
77 expr.Printf("(%s)[(id)0x%" PRIx64 " %s]",target_type,valobj.GetPointerValue(),selector);
78 ExecutionContext exe_ctx (valobj.GetExecutionContextRef());
79 lldb::ValueObjectSP result_sp;
80 Target* target = exe_ctx.GetTargetPtr();
81 StackFrame* stack_frame = exe_ctx.GetFramePtr();
82 if (!target || !stack_frame)
85 EvaluateExpressionOptions options;
86 options.SetCoerceToId(false);
87 options.SetUnwindOnError(true);
88 options.SetKeepInMemory(true);
89 options.SetUseDynamic(lldb::eDynamicCanRunTarget);
91 target->EvaluateExpression(expr.GetData(),
97 stream.Printf("%s",result_sp->GetSummaryAsCString());
102 lldb_private::formatters::CallSelectorOnObject (ValueObject &valobj,
103 const char* return_type,
104 const char* selector,
107 lldb::ValueObjectSP valobj_sp;
108 if (!return_type || !*return_type)
110 if (!selector || !*selector)
112 StreamString expr_path_stream;
113 valobj.GetExpressionPath(expr_path_stream, false);
115 expr.Printf("(%s)[%s %s:%" PRId64 "]",return_type,expr_path_stream.GetData(),selector,index);
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)
123 EvaluateExpressionOptions options;
124 options.SetCoerceToId(false);
125 options.SetUnwindOnError(true);
126 options.SetKeepInMemory(true);
127 options.SetUseDynamic(lldb::eDynamicCanRunTarget);
129 target->EvaluateExpression(expr.GetData(),
137 lldb_private::formatters::CallSelectorOnObject (ValueObject &valobj,
138 const char* return_type,
139 const char* selector,
142 lldb::ValueObjectSP valobj_sp;
143 if (!return_type || !*return_type)
145 if (!selector || !*selector)
149 StreamString expr_path_stream;
150 valobj.GetExpressionPath(expr_path_stream, false);
152 expr.Printf("(%s)[%s %s:%s]",return_type,expr_path_stream.GetData(),selector,key);
153 ExecutionContext exe_ctx (valobj.GetExecutionContextRef());
154 lldb::ValueObjectSP result_sp;
155 Target* target = exe_ctx.GetTargetPtr();
156 StackFrame* stack_frame = exe_ctx.GetFramePtr();
157 if (!target || !stack_frame)
160 EvaluateExpressionOptions options;
161 options.SetCoerceToId(false);
162 options.SetUnwindOnError(true);
163 options.SetKeepInMemory(true);
164 options.SetUseDynamic(lldb::eDynamicCanRunTarget);
166 target->EvaluateExpression(expr.GetData(),
173 // use this call if you already have an LLDB-side buffer for the data
174 template<typename SourceDataType>
176 DumpUTFBufferToStream (ConversionResult (*ConvertFunction) (const SourceDataType**,
177 const SourceDataType*,
183 char prefix_token = '@',
185 uint32_t sourceSize = 0)
187 if (prefix_token != 0)
188 stream.Printf("%c",prefix_token);
190 stream.Printf("%c",quote);
191 if (data.GetByteSize() && data.GetDataStart() && data.GetDataEnd())
193 const int bufferSPSize = data.GetByteSize();
196 const int origin_encoding = 8*sizeof(SourceDataType);
197 sourceSize = bufferSPSize/(origin_encoding / 4);
200 SourceDataType *data_ptr = (SourceDataType*)data.GetDataStart();
201 SourceDataType *data_end_ptr = data_ptr + sourceSize;
203 while (data_ptr < data_end_ptr)
207 data_end_ptr = data_ptr;
213 data_ptr = (SourceDataType*)data.GetDataStart();
215 lldb::DataBufferSP utf8_data_buffer_sp;
216 UTF8* utf8_data_ptr = nullptr;
217 UTF8* utf8_data_end_ptr = nullptr;
221 utf8_data_buffer_sp.reset(new DataBufferHeap(4*bufferSPSize,0));
222 utf8_data_ptr = (UTF8*)utf8_data_buffer_sp->GetBytes();
223 utf8_data_end_ptr = utf8_data_ptr + utf8_data_buffer_sp->GetByteSize();
224 ConvertFunction ( (const SourceDataType**)&data_ptr, data_end_ptr, &utf8_data_ptr, utf8_data_end_ptr, lenientConversion );
225 utf8_data_ptr = (UTF8*)utf8_data_buffer_sp->GetBytes(); // needed because the ConvertFunction will change the value of the data_ptr
229 // just copy the pointers - the cast is necessary to make the compiler happy
230 // but this should only happen if we are reading UTF8 data
231 utf8_data_ptr = (UTF8*)data_ptr;
232 utf8_data_end_ptr = (UTF8*)data_end_ptr;
235 // since we tend to accept partial data (and even partially malformed data)
236 // we might end up with no NULL terminator before the end_ptr
237 // hence we need to take a slower route and ensure we stay within boundaries
238 for (;utf8_data_ptr != utf8_data_end_ptr; utf8_data_ptr++)
242 stream.Printf("%c",*utf8_data_ptr);
246 stream.Printf("%c",quote);
250 template<typename SourceDataType>
251 class ReadUTFBufferAndDumpToStreamOptions
254 typedef ConversionResult (*ConvertFunctionType) (const SourceDataType**,
255 const SourceDataType*,
260 ReadUTFBufferAndDumpToStreamOptions () :
261 m_conversion_function(NULL),
268 m_needs_zero_termination(true)
272 ReadUTFBufferAndDumpToStreamOptions&
273 SetConversionFunction (ConvertFunctionType f)
275 m_conversion_function = f;
280 GetConversionFunction () const
282 return m_conversion_function;
285 ReadUTFBufferAndDumpToStreamOptions&
286 SetLocation (uint64_t l)
298 ReadUTFBufferAndDumpToStreamOptions&
299 SetProcessSP (ProcessSP p)
306 GetProcessSP () const
311 ReadUTFBufferAndDumpToStreamOptions&
312 SetStream (Stream* s)
324 ReadUTFBufferAndDumpToStreamOptions&
325 SetPrefixToken (char p)
332 GetPrefixToken () const
334 return m_prefix_token;
337 ReadUTFBufferAndDumpToStreamOptions&
350 ReadUTFBufferAndDumpToStreamOptions&
351 SetSourceSize (uint32_t s)
358 GetSourceSize () const
360 return m_source_size;
363 ReadUTFBufferAndDumpToStreamOptions&
364 SetNeedsZeroTermination (bool z)
366 m_needs_zero_termination = z;
371 GetNeedsZeroTermination () const
373 return m_needs_zero_termination;
377 ConvertFunctionType m_conversion_function;
379 ProcessSP m_process_sp;
383 uint32_t m_source_size;
384 bool m_needs_zero_termination;
387 template<typename SourceDataType>
389 ReadUTFBufferAndDumpToStream (const ReadUTFBufferAndDumpToStreamOptions<SourceDataType>& options)
391 if (options.GetLocation() == 0 || options.GetLocation() == LLDB_INVALID_ADDRESS)
394 ProcessSP process_sp(options.GetProcessSP());
399 const int type_width = sizeof(SourceDataType);
400 const int origin_encoding = 8 * type_width ;
401 if (origin_encoding != 8 && origin_encoding != 16 && origin_encoding != 32)
403 // if not UTF8, I need a conversion function to return proper UTF8
404 if (origin_encoding != 8 && !options.GetConversionFunction())
407 if (!options.GetStream())
410 uint32_t sourceSize = options.GetSourceSize();
411 bool needs_zero_terminator = options.GetNeedsZeroTermination();
415 sourceSize = process_sp->GetTarget().GetMaximumSizeOfStringSummary();
416 needs_zero_terminator = true;
419 sourceSize = std::min(sourceSize,process_sp->GetTarget().GetMaximumSizeOfStringSummary());
421 const int bufferSPSize = sourceSize * type_width;
423 lldb::DataBufferSP buffer_sp(new DataBufferHeap(bufferSPSize,0));
425 if (!buffer_sp->GetBytes())
429 char *buffer = reinterpret_cast<char *>(buffer_sp->GetBytes());
431 size_t data_read = 0;
432 if (needs_zero_terminator)
433 data_read = process_sp->ReadStringFromMemory(options.GetLocation(), buffer, bufferSPSize, error, type_width);
435 data_read = process_sp->ReadMemoryFromInferior(options.GetLocation(), (char*)buffer_sp->GetBytes(), bufferSPSize, error);
437 if (error.Fail() || data_read == 0)
439 options.GetStream()->Printf("unable to read data");
443 DataExtractor data(buffer_sp, process_sp->GetByteOrder(), process_sp->GetAddressByteSize());
445 return DumpUTFBufferToStream(options.GetConversionFunction(), data, *options.GetStream(), options.GetPrefixToken(), options.GetQuote(), sourceSize);
449 lldb_private::formatters::Char16StringSummaryProvider (ValueObject& valobj, Stream& stream)
451 ProcessSP process_sp = valobj.GetProcessSP();
455 lldb::addr_t valobj_addr = valobj.GetValueAsUnsigned(0);
460 ReadUTFBufferAndDumpToStreamOptions<UTF16> options;
461 options.SetLocation(valobj_addr);
462 options.SetConversionFunction(ConvertUTF16toUTF8);
463 options.SetProcessSP(process_sp);
464 options.SetStream(&stream);
465 options.SetPrefixToken('u');
467 if (!ReadUTFBufferAndDumpToStream(options))
469 stream.Printf("Summary Unavailable");
477 lldb_private::formatters::Char32StringSummaryProvider (ValueObject& valobj, Stream& stream)
479 ProcessSP process_sp = valobj.GetProcessSP();
483 lldb::addr_t valobj_addr = valobj.GetValueAsUnsigned(0);
488 ReadUTFBufferAndDumpToStreamOptions<UTF32> options;
489 options.SetLocation(valobj_addr);
490 options.SetConversionFunction(ConvertUTF32toUTF8);
491 options.SetProcessSP(process_sp);
492 options.SetStream(&stream);
493 options.SetPrefixToken('U');
495 if (!ReadUTFBufferAndDumpToStream(options))
497 stream.Printf("Summary Unavailable");
505 lldb_private::formatters::WCharStringSummaryProvider (ValueObject& valobj, Stream& stream)
507 ProcessSP process_sp = valobj.GetProcessSP();
511 lldb::addr_t data_addr = 0;
513 if (valobj.IsPointerType())
514 data_addr = valobj.GetValueAsUnsigned(0);
515 else if (valobj.IsArrayType())
516 data_addr = valobj.GetAddressOf();
518 if (data_addr == 0 || data_addr == LLDB_INVALID_ADDRESS)
521 clang::ASTContext* ast = valobj.GetClangType().GetASTContext();
526 ClangASTType wchar_clang_type = ClangASTContext::GetBasicType(ast, lldb::eBasicTypeWChar);
527 const uint32_t wchar_size = wchar_clang_type.GetBitSize();
535 ReadUTFBufferAndDumpToStreamOptions<UTF8> options;
536 options.SetLocation(data_addr);
537 options.SetConversionFunction(nullptr);
538 options.SetProcessSP(process_sp);
539 options.SetStream(&stream);
540 options.SetPrefixToken('L');
542 return ReadUTFBufferAndDumpToStream(options);
547 ReadUTFBufferAndDumpToStreamOptions<UTF16> options;
548 options.SetLocation(data_addr);
549 options.SetConversionFunction(ConvertUTF16toUTF8);
550 options.SetProcessSP(process_sp);
551 options.SetStream(&stream);
552 options.SetPrefixToken('L');
554 return ReadUTFBufferAndDumpToStream(options);
559 ReadUTFBufferAndDumpToStreamOptions<UTF32> options;
560 options.SetLocation(data_addr);
561 options.SetConversionFunction(ConvertUTF32toUTF8);
562 options.SetProcessSP(process_sp);
563 options.SetStream(&stream);
564 options.SetPrefixToken('L');
566 return ReadUTFBufferAndDumpToStream(options);
569 stream.Printf("size for wchar_t is not valid");
576 lldb_private::formatters::Char16SummaryProvider (ValueObject& valobj, Stream& stream)
579 valobj.GetData(data);
582 valobj.GetValueAsCString(lldb::eFormatUnicode16, value);
584 stream.Printf("%s ", value.c_str());
586 return DumpUTFBufferToStream<UTF16>(ConvertUTF16toUTF8,data,stream, 'u','\'',1);
590 lldb_private::formatters::Char32SummaryProvider (ValueObject& valobj, Stream& stream)
593 valobj.GetData(data);
596 valobj.GetValueAsCString(lldb::eFormatUnicode32, value);
598 stream.Printf("%s ", value.c_str());
600 return DumpUTFBufferToStream<UTF32>(ConvertUTF32toUTF8,data,stream, 'U','\'',1);
604 lldb_private::formatters::WCharSummaryProvider (ValueObject& valobj, Stream& stream)
607 valobj.GetData(data);
609 clang::ASTContext* ast = valobj.GetClangType().GetASTContext();
614 ClangASTType wchar_clang_type = ClangASTContext::GetBasicType(ast, lldb::eBasicTypeWChar);
615 const uint32_t wchar_size = wchar_clang_type.GetBitSize();
622 valobj.GetValueAsCString(lldb::eFormatChar, value);
624 stream.Printf("%s ", value.c_str());
625 return DumpUTFBufferToStream<UTF8>(nullptr,
633 valobj.GetValueAsCString(lldb::eFormatUnicode16, value);
635 stream.Printf("%s ", value.c_str());
636 return DumpUTFBufferToStream<UTF16>(ConvertUTF16toUTF8,
644 valobj.GetValueAsCString(lldb::eFormatUnicode32, value);
646 stream.Printf("%s ", value.c_str());
647 return DumpUTFBufferToStream<UTF32>(ConvertUTF32toUTF8,
654 stream.Printf("size for wchar_t is not valid");
660 // the field layout in a libc++ string (cap, side, data or data, size, cap)
661 enum LibcxxStringLayoutMode
663 eLibcxxStringLayoutModeCSD = 0,
664 eLibcxxStringLayoutModeDSC = 1,
665 eLibcxxStringLayoutModeInvalid = 0xffff
668 // this function abstracts away the layout and mode details of a libc++ string
669 // and returns the address of the data and the size ready for callers to consume
671 ExtractLibcxxStringInfo (ValueObject& valobj,
672 ValueObjectSP &location_sp,
675 ValueObjectSP D(valobj.GetChildAtIndexPath({0,0,0,0}));
679 ValueObjectSP layout_decider(D->GetChildAtIndexPath({0,0}));
681 // this child should exist
685 ConstString g_data_name("__data_");
686 ConstString g_size_name("__size_");
687 bool short_mode = false; // this means the string is in short-mode and the data is stored inline
688 LibcxxStringLayoutMode layout = (layout_decider->GetName() == g_data_name) ? eLibcxxStringLayoutModeDSC : eLibcxxStringLayoutModeCSD;
689 uint64_t size_mode_value = 0;
691 if (layout == eLibcxxStringLayoutModeDSC)
693 ValueObjectSP size_mode(D->GetChildAtIndexPath({1,1,0}));
697 if (size_mode->GetName() != g_size_name)
699 // we are hitting the padding structure, move along
700 size_mode = D->GetChildAtIndexPath({1,1,1});
705 size_mode_value = (size_mode->GetValueAsUnsigned(0));
706 short_mode = ((size_mode_value & 0x80) == 0);
710 ValueObjectSP size_mode(D->GetChildAtIndexPath({1,0,0}));
714 size_mode_value = (size_mode->GetValueAsUnsigned(0));
715 short_mode = ((size_mode_value & 1) == 0);
720 ValueObjectSP s(D->GetChildAtIndex(1, true));
723 location_sp = s->GetChildAtIndex((layout == eLibcxxStringLayoutModeDSC) ? 0 : 1, true);
724 size = (layout == eLibcxxStringLayoutModeDSC) ? size_mode_value : ((size_mode_value >> 1) % 256);
725 return (location_sp.get() != nullptr);
729 ValueObjectSP l(D->GetChildAtIndex(0, true));
732 // we can use the layout_decider object as the data pointer
733 location_sp = (layout == eLibcxxStringLayoutModeDSC) ? layout_decider : l->GetChildAtIndex(2, true);
734 ValueObjectSP size_vo(l->GetChildAtIndex(1, true));
735 if (!size_vo || !location_sp)
737 size = size_vo->GetValueAsUnsigned(0);
743 lldb_private::formatters::LibcxxWStringSummaryProvider (ValueObject& valobj, Stream& stream)
746 ValueObjectSP location_sp((ValueObject*)nullptr);
747 if (!ExtractLibcxxStringInfo(valobj, location_sp, size))
751 stream.Printf("L\"\"");
756 return WCharStringSummaryProvider(*location_sp.get(), stream);
760 lldb_private::formatters::LibcxxStringSummaryProvider (ValueObject& valobj, Stream& stream)
763 ValueObjectSP location_sp((ValueObject*)nullptr);
764 if (!ExtractLibcxxStringInfo(valobj, location_sp, size))
768 stream.Printf("\"\"");
774 if (location_sp->ReadPointedString(stream,
776 0, // max length is decided by the settings
777 false) == 0) // do not honor array (terminates on first 0 byte even for a char[])
778 stream.Printf("\"\""); // if nothing was read, print an empty string
779 return error.Success();
783 lldb_private::formatters::ObjCClassSummaryProvider (ValueObject& valobj, Stream& stream)
785 ProcessSP process_sp = valobj.GetProcessSP();
789 ObjCLanguageRuntime* runtime = (ObjCLanguageRuntime*)process_sp->GetLanguageRuntime(lldb::eLanguageTypeObjC);
794 ObjCLanguageRuntime::ClassDescriptorSP descriptor(runtime->GetClassDescriptorFromISA(valobj.GetValueAsUnsigned(0)));
796 if (!descriptor.get() || !descriptor->IsValid())
799 const char* class_name = descriptor->GetClassName().GetCString();
801 if (!class_name || !*class_name)
804 stream.Printf("%s",class_name);
808 class ObjCClassSyntheticChildrenFrontEnd : public SyntheticChildrenFrontEnd
811 ObjCClassSyntheticChildrenFrontEnd (lldb::ValueObjectSP valobj_sp) :
812 SyntheticChildrenFrontEnd(*valobj_sp.get())
817 CalculateNumChildren ()
822 virtual lldb::ValueObjectSP
823 GetChildAtIndex (size_t idx)
825 return lldb::ValueObjectSP();
841 GetIndexOfChildWithName (const ConstString &name)
847 ~ObjCClassSyntheticChildrenFrontEnd ()
852 SyntheticChildrenFrontEnd*
853 lldb_private::formatters::ObjCClassSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP valobj_sp)
855 return new ObjCClassSyntheticChildrenFrontEnd(valobj_sp);
858 template<bool needs_at>
860 lldb_private::formatters::NSDataSummaryProvider (ValueObject& valobj, Stream& stream)
862 ProcessSP process_sp = valobj.GetProcessSP();
866 ObjCLanguageRuntime* runtime = (ObjCLanguageRuntime*)process_sp->GetLanguageRuntime(lldb::eLanguageTypeObjC);
871 ObjCLanguageRuntime::ClassDescriptorSP descriptor(runtime->GetClassDescriptor(valobj));
873 if (!descriptor.get() || !descriptor->IsValid())
876 bool is_64bit = (process_sp->GetAddressByteSize() == 8);
877 lldb::addr_t valobj_addr = valobj.GetValueAsUnsigned(0);
884 const char* class_name = descriptor->GetClassName().GetCString();
886 if (!class_name || !*class_name)
889 if (!strcmp(class_name,"NSConcreteData") ||
890 !strcmp(class_name,"NSConcreteMutableData") ||
891 !strcmp(class_name,"__NSCFData"))
893 uint32_t offset = (is_64bit ? 16 : 8);
895 value = process_sp->ReadUnsignedIntegerFromMemory(valobj_addr + offset, is_64bit ? 8 : 4, 0, error);
901 if (!ExtractValueFromObjCExpression(valobj, "int", "length", value))
905 stream.Printf("%s%" PRIu64 " byte%s%s",
906 (needs_at ? "@\"" : ""),
908 (value != 1 ? "s" : ""),
909 (needs_at ? "\"" : ""));
915 ReadAsciiBufferAndDumpToStream (lldb::addr_t location,
916 lldb::ProcessSP& process_sp,
920 size_t *data_read = NULL,
921 char prefix_token = '@',
926 if (!process_sp || location == 0)
930 size = process_sp->GetTarget().GetMaximumSizeOfStringSummary();
932 size = std::min(size,process_sp->GetTarget().GetMaximumSizeOfStringSummary());
934 lldb::DataBufferSP buffer_sp(new DataBufferHeap(size,0));
936 my_data_read = process_sp->ReadCStringFromMemory(location, (char*)buffer_sp->GetBytes(), size, my_error);
941 *data_read = my_data_read;
946 dest.Printf("%c%c",prefix_token,quote);
949 dest.Printf("%s",(char*)buffer_sp->GetBytes());
951 dest.Printf("%c",quote);
957 lldb_private::formatters::NSStringSummaryProvider (ValueObject& valobj, Stream& stream)
959 ProcessSP process_sp = valobj.GetProcessSP();
963 ObjCLanguageRuntime* runtime = (ObjCLanguageRuntime*)process_sp->GetLanguageRuntime(lldb::eLanguageTypeObjC);
968 ObjCLanguageRuntime::ClassDescriptorSP descriptor(runtime->GetClassDescriptor(valobj));
970 if (!descriptor.get() || !descriptor->IsValid())
973 uint32_t ptr_size = process_sp->GetAddressByteSize();
975 lldb::addr_t valobj_addr = valobj.GetValueAsUnsigned(0);
980 const char* class_name = descriptor->GetClassName().GetCString();
982 if (!class_name || !*class_name)
985 uint64_t info_bits_location = valobj_addr + ptr_size;
986 if (process_sp->GetByteOrder() != lldb::eByteOrderLittle)
987 info_bits_location += 3;
991 uint8_t info_bits = process_sp->ReadUnsignedIntegerFromMemory(info_bits_location, 1, 0, error);
995 bool is_mutable = (info_bits & 1) == 1;
996 bool is_inline = (info_bits & 0x60) == 0;
997 bool has_explicit_length = (info_bits & (1 | 4)) != 4;
998 bool is_unicode = (info_bits & 0x10) == 0x10;
999 bool is_special = strcmp(class_name,"NSPathStore2") == 0;
1000 bool has_null = (info_bits & 8) == 8;
1002 size_t explicit_length = 0;
1003 if (!has_null && has_explicit_length && !is_special)
1005 lldb::addr_t explicit_length_offset = 2*ptr_size;
1006 if (is_mutable && !is_inline)
1007 explicit_length_offset = explicit_length_offset + ptr_size; // notInlineMutable.length;
1009 explicit_length = explicit_length + 0; // inline1.length;
1010 else if (!is_inline && !is_mutable)
1011 explicit_length_offset = explicit_length_offset + ptr_size; // notInlineImmutable1.length;
1013 explicit_length_offset = 0;
1015 if (explicit_length_offset)
1017 explicit_length_offset = valobj_addr + explicit_length_offset;
1018 explicit_length = process_sp->ReadUnsignedIntegerFromMemory(explicit_length_offset, 4, 0, error);
1022 if (strcmp(class_name,"NSString") &&
1023 strcmp(class_name,"CFStringRef") &&
1024 strcmp(class_name,"CFMutableStringRef") &&
1025 strcmp(class_name,"__NSCFConstantString") &&
1026 strcmp(class_name,"__NSCFString") &&
1027 strcmp(class_name,"NSCFConstantString") &&
1028 strcmp(class_name,"NSCFString") &&
1029 strcmp(class_name,"NSPathStore2"))
1031 // not one of us - but tell me class name
1032 stream.Printf("class name = %s",class_name);
1038 uint64_t location = 2 * ptr_size + valobj_addr;
1039 location = process_sp->ReadPointerFromMemory(location, error);
1042 if (has_explicit_length && is_unicode)
1044 ReadUTFBufferAndDumpToStreamOptions<UTF16> options;
1045 options.SetConversionFunction(ConvertUTF16toUTF8);
1046 options.SetLocation(location);
1047 options.SetProcessSP(process_sp);
1048 options.SetStream(&stream);
1049 options.SetPrefixToken('@');
1050 options.SetQuote('"');
1051 options.SetSourceSize(explicit_length);
1052 options.SetNeedsZeroTermination(false);
1053 return ReadUTFBufferAndDumpToStream (options);
1056 return ReadAsciiBufferAndDumpToStream(location+1,process_sp,stream, explicit_length);
1058 else if (is_inline && has_explicit_length && !is_unicode && !is_special && !is_mutable)
1060 uint64_t location = 3 * ptr_size + valobj_addr;
1061 return ReadAsciiBufferAndDumpToStream(location,process_sp,stream,explicit_length);
1063 else if (is_unicode)
1065 uint64_t location = valobj_addr + 2*ptr_size;
1068 if (!has_explicit_length)
1070 stream.Printf("found new combo");
1074 location += ptr_size;
1078 location = process_sp->ReadPointerFromMemory(location, error);
1082 ReadUTFBufferAndDumpToStreamOptions<UTF16> options;
1083 options.SetConversionFunction(ConvertUTF16toUTF8);
1084 options.SetLocation(location);
1085 options.SetProcessSP(process_sp);
1086 options.SetStream(&stream);
1087 options.SetPrefixToken('@');
1088 options.SetQuote('"');
1089 options.SetSourceSize(explicit_length);
1090 options.SetNeedsZeroTermination(has_explicit_length == false);
1091 return ReadUTFBufferAndDumpToStream (options);
1093 else if (is_special)
1095 uint64_t location = valobj_addr + (ptr_size == 8 ? 12 : 8);
1096 ReadUTFBufferAndDumpToStreamOptions<UTF16> options;
1097 options.SetConversionFunction(ConvertUTF16toUTF8);
1098 options.SetLocation(location);
1099 options.SetProcessSP(process_sp);
1100 options.SetStream(&stream);
1101 options.SetPrefixToken('@');
1102 options.SetQuote('"');
1103 options.SetSourceSize(explicit_length);
1104 options.SetNeedsZeroTermination(has_explicit_length == false);
1105 return ReadUTFBufferAndDumpToStream (options);
1109 uint64_t location = valobj_addr + 2*ptr_size;
1110 if (!has_explicit_length)
1112 return ReadAsciiBufferAndDumpToStream(location,process_sp,stream,explicit_length);
1116 uint64_t location = valobj_addr + 2*ptr_size;
1117 location = process_sp->ReadPointerFromMemory(location, error);
1120 if (has_explicit_length && !has_null)
1121 explicit_length++; // account for the fact that there is no NULL and we need to have one added
1122 return ReadAsciiBufferAndDumpToStream(location,process_sp,stream,explicit_length);
1125 stream.Printf("class name = %s",class_name);
1131 lldb_private::formatters::NSAttributedStringSummaryProvider (ValueObject& valobj, Stream& stream)
1133 TargetSP target_sp(valobj.GetTargetSP());
1136 uint32_t addr_size = target_sp->GetArchitecture().GetAddressByteSize();
1137 uint64_t pointer_value = valobj.GetValueAsUnsigned(0);
1140 pointer_value += addr_size;
1141 ClangASTType type(valobj.GetClangType());
1142 ExecutionContext exe_ctx(target_sp,false);
1143 ValueObjectSP child_ptr_sp(valobj.CreateValueObjectFromAddress("string_ptr", pointer_value, exe_ctx, type));
1147 child_ptr_sp->GetData(data);
1148 ValueObjectSP child_sp(child_ptr_sp->CreateValueObjectFromData("string_data", data, exe_ctx, type));
1149 child_sp->GetValueAsUnsigned(0);
1151 return NSStringSummaryProvider(*child_sp, stream);
1156 lldb_private::formatters::NSMutableAttributedStringSummaryProvider (ValueObject& valobj, Stream& stream)
1158 return NSAttributedStringSummaryProvider(valobj, stream);
1162 lldb_private::formatters::RuntimeSpecificDescriptionSummaryProvider (ValueObject& valobj, Stream& stream)
1164 stream.Printf("%s",valobj.GetObjectDescription());
1169 lldb_private::formatters::ObjCBOOLSummaryProvider (ValueObject& valobj, Stream& stream)
1171 const uint32_t type_info = valobj.GetClangType().GetTypeInfo();
1173 ValueObjectSP real_guy_sp = valobj.GetSP();
1175 if (type_info & ClangASTType::eTypeIsPointer)
1178 real_guy_sp = valobj.Dereference(err);
1179 if (err.Fail() || !real_guy_sp)
1182 else if (type_info & ClangASTType::eTypeIsReference)
1184 real_guy_sp = valobj.GetChildAtIndex(0, true);
1188 uint64_t value = real_guy_sp->GetValueAsUnsigned(0);
1191 stream.Printf("NO");
1194 stream.Printf("YES");
1198 template <bool is_sel_ptr>
1200 lldb_private::formatters::ObjCSELSummaryProvider (ValueObject& valobj, Stream& stream)
1202 lldb::ValueObjectSP valobj_sp;
1204 ClangASTType charstar (valobj.GetClangType().GetBasicTypeFromAST(eBasicTypeChar).GetPointerType());
1209 ExecutionContext exe_ctx(valobj.GetExecutionContextRef());
1213 lldb::addr_t data_address = valobj.GetValueAsUnsigned(LLDB_INVALID_ADDRESS);
1214 if (data_address == LLDB_INVALID_ADDRESS)
1216 valobj_sp = ValueObject::CreateValueObjectFromAddress("text", data_address, exe_ctx, charstar);
1221 valobj.GetData(data);
1222 valobj_sp = ValueObject::CreateValueObjectFromData("text", data, exe_ctx, charstar);
1228 stream.Printf("%s",valobj_sp->GetSummaryAsCString());
1232 // POSIX has an epoch on Jan-1-1970, but Cocoa prefers Jan-1-2001
1233 // this call gives the POSIX equivalent of the Cocoa epoch
1235 lldb_private::formatters::GetOSXEpoch ()
1237 static time_t epoch = 0;
1243 tm_epoch.tm_sec = 0;
1244 tm_epoch.tm_hour = 0;
1245 tm_epoch.tm_min = 0;
1246 tm_epoch.tm_mon = 0;
1247 tm_epoch.tm_mday = 1;
1248 tm_epoch.tm_year = 2001-1900; // for some reason, we need to subtract 1900 from this field. not sure why.
1249 tm_epoch.tm_isdst = -1;
1250 tm_epoch.tm_gmtoff = 0;
1251 tm_epoch.tm_zone = NULL;
1252 epoch = timegm(&tm_epoch);
1259 lldb_private::formatters::ExtractIndexFromString (const char* item_name)
1261 if (!item_name || !*item_name)
1263 if (*item_name != '[')
1266 char* endptr = NULL;
1267 unsigned long int idx = ::strtoul(item_name, &endptr, 0);
1268 if (idx == 0 && endptr == item_name)
1270 if (idx == ULONG_MAX)
1275 lldb_private::formatters::VectorIteratorSyntheticFrontEnd::VectorIteratorSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp,
1276 ConstString item_name) :
1277 SyntheticChildrenFrontEnd(*valobj_sp.get()),
1279 m_item_name(item_name),
1287 lldb_private::formatters::VectorIteratorSyntheticFrontEnd::Update()
1291 ValueObjectSP valobj_sp = m_backend.GetSP();
1298 ValueObjectSP item_ptr(valobj_sp->GetChildMemberWithName(m_item_name,true));
1301 if (item_ptr->GetValueAsUnsigned(0) == 0)
1304 m_exe_ctx_ref = valobj_sp->GetExecutionContextRef();
1305 m_item_sp = ValueObject::CreateValueObjectFromAddress("item", item_ptr->GetValueAsUnsigned(0), m_exe_ctx_ref, item_ptr->GetClangType().GetPointeeType());
1312 lldb_private::formatters::VectorIteratorSyntheticFrontEnd::CalculateNumChildren ()
1318 lldb_private::formatters::VectorIteratorSyntheticFrontEnd::GetChildAtIndex (size_t idx)
1322 return lldb::ValueObjectSP();
1326 lldb_private::formatters::VectorIteratorSyntheticFrontEnd::MightHaveChildren ()
1332 lldb_private::formatters::VectorIteratorSyntheticFrontEnd::GetIndexOfChildWithName (const ConstString &name)
1334 if (name == ConstString("item"))
1339 lldb_private::formatters::VectorIteratorSyntheticFrontEnd::~VectorIteratorSyntheticFrontEnd ()
1344 lldb_private::formatters::NSDataSummaryProvider<true> (ValueObject&, Stream&) ;
1347 lldb_private::formatters::NSDataSummaryProvider<false> (ValueObject&, Stream&) ;
1350 lldb_private::formatters::ObjCSELSummaryProvider<true> (ValueObject&, Stream&) ;
1353 lldb_private::formatters::ObjCSELSummaryProvider<false> (ValueObject&, Stream&) ;