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/Target.h"
24 #include "lldb/Target/Thread.h"
29 using namespace lldb_private;
30 using namespace lldb_private::formatters;
33 lldb_private::formatters::GetViableFrame (ExecutionContext exe_ctx)
35 StackFrame* frame = exe_ctx.GetFramePtr();
39 Process* process = exe_ctx.GetProcessPtr();
43 ThreadSP thread_sp(process->GetThreadList().GetSelectedThread());
45 return thread_sp->GetSelectedFrame().get();
50 lldb_private::formatters::ExtractValueFromObjCExpression (ValueObject &valobj,
51 const char* target_type,
55 if (!target_type || !*target_type)
57 if (!selector || !*selector)
60 expr.Printf("(%s)[(id)0x%" PRIx64 " %s]",target_type,valobj.GetPointerValue(),selector);
61 ExecutionContext exe_ctx (valobj.GetExecutionContextRef());
62 lldb::ValueObjectSP result_sp;
63 Target* target = exe_ctx.GetTargetPtr();
64 StackFrame* stack_frame = GetViableFrame(exe_ctx);
65 if (!target || !stack_frame)
68 EvaluateExpressionOptions options;
69 options.SetCoerceToId(false);
70 options.SetUnwindOnError(true);
71 options.SetKeepInMemory(true);
73 target->EvaluateExpression(expr.GetData(),
79 value = result_sp->GetValueAsUnsigned(0);
84 lldb_private::formatters::ExtractSummaryFromObjCExpression (ValueObject &valobj,
85 const char* target_type,
89 if (!target_type || !*target_type)
91 if (!selector || !*selector)
94 expr.Printf("(%s)[(id)0x%" PRIx64 " %s]",target_type,valobj.GetPointerValue(),selector);
95 ExecutionContext exe_ctx (valobj.GetExecutionContextRef());
96 lldb::ValueObjectSP result_sp;
97 Target* target = exe_ctx.GetTargetPtr();
98 StackFrame* stack_frame = GetViableFrame(exe_ctx);
99 if (!target || !stack_frame)
102 EvaluateExpressionOptions options;
103 options.SetCoerceToId(false);
104 options.SetUnwindOnError(true);
105 options.SetKeepInMemory(true);
106 options.SetUseDynamic(lldb::eDynamicCanRunTarget);
108 target->EvaluateExpression(expr.GetData(),
114 stream.Printf("%s",result_sp->GetSummaryAsCString());
119 lldb_private::formatters::CallSelectorOnObject (ValueObject &valobj,
120 const char* return_type,
121 const char* selector,
124 lldb::ValueObjectSP valobj_sp;
125 if (!return_type || !*return_type)
127 if (!selector || !*selector)
129 StreamString expr_path_stream;
130 valobj.GetExpressionPath(expr_path_stream, false);
132 expr.Printf("(%s)[%s %s:%" PRId64 "]",return_type,expr_path_stream.GetData(),selector,index);
133 ExecutionContext exe_ctx (valobj.GetExecutionContextRef());
134 lldb::ValueObjectSP result_sp;
135 Target* target = exe_ctx.GetTargetPtr();
136 StackFrame* stack_frame = GetViableFrame(exe_ctx);
137 if (!target || !stack_frame)
140 EvaluateExpressionOptions options;
141 options.SetCoerceToId(false);
142 options.SetUnwindOnError(true);
143 options.SetKeepInMemory(true);
144 options.SetUseDynamic(lldb::eDynamicCanRunTarget);
146 target->EvaluateExpression(expr.GetData(),
154 lldb_private::formatters::CallSelectorOnObject (ValueObject &valobj,
155 const char* return_type,
156 const char* selector,
159 lldb::ValueObjectSP valobj_sp;
160 if (!return_type || !*return_type)
162 if (!selector || !*selector)
166 StreamString expr_path_stream;
167 valobj.GetExpressionPath(expr_path_stream, false);
169 expr.Printf("(%s)[%s %s:%s]",return_type,expr_path_stream.GetData(),selector,key);
170 ExecutionContext exe_ctx (valobj.GetExecutionContextRef());
171 lldb::ValueObjectSP result_sp;
172 Target* target = exe_ctx.GetTargetPtr();
173 StackFrame* stack_frame = GetViableFrame(exe_ctx);
174 if (!target || !stack_frame)
177 EvaluateExpressionOptions options;
178 options.SetCoerceToId(false);
179 options.SetUnwindOnError(true);
180 options.SetKeepInMemory(true);
181 options.SetUseDynamic(lldb::eDynamicCanRunTarget);
183 target->EvaluateExpression(expr.GetData(),
190 // use this call if you already have an LLDB-side buffer for the data
191 template<typename SourceDataType>
193 DumpUTFBufferToStream (ConversionResult (*ConvertFunction) (const SourceDataType**,
194 const SourceDataType*,
200 char prefix_token = '@',
202 uint32_t sourceSize = 0)
204 if (prefix_token != 0)
205 stream.Printf("%c",prefix_token);
207 stream.Printf("%c",quote);
208 if (data.GetByteSize() && data.GetDataStart() && data.GetDataEnd())
210 const int bufferSPSize = data.GetByteSize();
213 const int origin_encoding = 8*sizeof(SourceDataType);
214 sourceSize = bufferSPSize/(origin_encoding / 4);
217 SourceDataType *data_ptr = (SourceDataType*)data.GetDataStart();
218 SourceDataType *data_end_ptr = data_ptr + sourceSize;
220 while (data_ptr < data_end_ptr)
224 data_end_ptr = data_ptr;
230 data_ptr = (SourceDataType*)data.GetDataStart();
232 lldb::DataBufferSP utf8_data_buffer_sp;
233 UTF8* utf8_data_ptr = nullptr;
234 UTF8* utf8_data_end_ptr = nullptr;
238 utf8_data_buffer_sp.reset(new DataBufferHeap(4*bufferSPSize,0));
239 utf8_data_ptr = (UTF8*)utf8_data_buffer_sp->GetBytes();
240 utf8_data_end_ptr = utf8_data_ptr + utf8_data_buffer_sp->GetByteSize();
241 ConvertFunction ( (const SourceDataType**)&data_ptr, data_end_ptr, &utf8_data_ptr, utf8_data_end_ptr, lenientConversion );
242 utf8_data_ptr = (UTF8*)utf8_data_buffer_sp->GetBytes(); // needed because the ConvertFunction will change the value of the data_ptr
246 // just copy the pointers - the cast is necessary to make the compiler happy
247 // but this should only happen if we are reading UTF8 data
248 utf8_data_ptr = (UTF8*)data_ptr;
249 utf8_data_end_ptr = (UTF8*)data_end_ptr;
252 // since we tend to accept partial data (and even partially malformed data)
253 // we might end up with no NULL terminator before the end_ptr
254 // hence we need to take a slower route and ensure we stay within boundaries
255 for (;utf8_data_ptr != utf8_data_end_ptr; utf8_data_ptr++)
259 stream.Printf("%c",*utf8_data_ptr);
263 stream.Printf("%c",quote);
267 template<typename SourceDataType>
268 class ReadUTFBufferAndDumpToStreamOptions
271 typedef ConversionResult (*ConvertFunctionType) (const SourceDataType**,
272 const SourceDataType*,
277 ReadUTFBufferAndDumpToStreamOptions () :
278 m_conversion_function(NULL),
285 m_needs_zero_termination(true)
289 ReadUTFBufferAndDumpToStreamOptions&
290 SetConversionFunction (ConvertFunctionType f)
292 m_conversion_function = f;
297 GetConversionFunction () const
299 return m_conversion_function;
302 ReadUTFBufferAndDumpToStreamOptions&
303 SetLocation (uint64_t l)
315 ReadUTFBufferAndDumpToStreamOptions&
316 SetProcessSP (ProcessSP p)
323 GetProcessSP () const
328 ReadUTFBufferAndDumpToStreamOptions&
329 SetStream (Stream* s)
341 ReadUTFBufferAndDumpToStreamOptions&
342 SetPrefixToken (char p)
349 GetPrefixToken () const
351 return m_prefix_token;
354 ReadUTFBufferAndDumpToStreamOptions&
367 ReadUTFBufferAndDumpToStreamOptions&
368 SetSourceSize (uint32_t s)
375 GetSourceSize () const
377 return m_source_size;
380 ReadUTFBufferAndDumpToStreamOptions&
381 SetNeedsZeroTermination (bool z)
383 m_needs_zero_termination = z;
388 GetNeedsZeroTermination () const
390 return m_needs_zero_termination;
394 ConvertFunctionType m_conversion_function;
396 ProcessSP m_process_sp;
400 uint32_t m_source_size;
401 bool m_needs_zero_termination;
404 template<typename SourceDataType>
406 ReadUTFBufferAndDumpToStream (const ReadUTFBufferAndDumpToStreamOptions<SourceDataType>& options)
408 if (options.GetLocation() == 0 || options.GetLocation() == LLDB_INVALID_ADDRESS)
411 ProcessSP process_sp(options.GetProcessSP());
416 const int type_width = sizeof(SourceDataType);
417 const int origin_encoding = 8 * type_width ;
418 if (origin_encoding != 8 && origin_encoding != 16 && origin_encoding != 32)
420 // if not UTF8, I need a conversion function to return proper UTF8
421 if (origin_encoding != 8 && !options.GetConversionFunction())
424 if (!options.GetStream())
427 uint32_t sourceSize = options.GetSourceSize();
428 bool needs_zero_terminator = options.GetNeedsZeroTermination();
432 sourceSize = process_sp->GetTarget().GetMaximumSizeOfStringSummary();
433 needs_zero_terminator = true;
436 sourceSize = std::min(sourceSize,process_sp->GetTarget().GetMaximumSizeOfStringSummary());
438 const int bufferSPSize = sourceSize * type_width;
440 lldb::DataBufferSP buffer_sp(new DataBufferHeap(bufferSPSize,0));
442 if (!buffer_sp->GetBytes())
446 char *buffer = reinterpret_cast<char *>(buffer_sp->GetBytes());
448 size_t data_read = 0;
449 if (needs_zero_terminator)
450 data_read = process_sp->ReadStringFromMemory(options.GetLocation(), buffer, bufferSPSize, error, type_width);
452 data_read = process_sp->ReadMemoryFromInferior(options.GetLocation(), (char*)buffer_sp->GetBytes(), bufferSPSize, error);
454 if (error.Fail() || data_read == 0)
456 options.GetStream()->Printf("unable to read data");
460 DataExtractor data(buffer_sp, process_sp->GetByteOrder(), process_sp->GetAddressByteSize());
462 return DumpUTFBufferToStream(options.GetConversionFunction(), data, *options.GetStream(), options.GetPrefixToken(), options.GetQuote(), sourceSize);
466 lldb_private::formatters::Char16StringSummaryProvider (ValueObject& valobj, Stream& stream)
468 ProcessSP process_sp = valobj.GetProcessSP();
472 lldb::addr_t valobj_addr = valobj.GetValueAsUnsigned(0);
477 ReadUTFBufferAndDumpToStreamOptions<UTF16> options;
478 options.SetLocation(valobj_addr);
479 options.SetConversionFunction(ConvertUTF16toUTF8);
480 options.SetProcessSP(process_sp);
481 options.SetStream(&stream);
482 options.SetPrefixToken('u');
484 if (!ReadUTFBufferAndDumpToStream(options))
486 stream.Printf("Summary Unavailable");
494 lldb_private::formatters::Char32StringSummaryProvider (ValueObject& valobj, Stream& stream)
496 ProcessSP process_sp = valobj.GetProcessSP();
500 lldb::addr_t valobj_addr = valobj.GetValueAsUnsigned(0);
505 ReadUTFBufferAndDumpToStreamOptions<UTF32> options;
506 options.SetLocation(valobj_addr);
507 options.SetConversionFunction(ConvertUTF32toUTF8);
508 options.SetProcessSP(process_sp);
509 options.SetStream(&stream);
510 options.SetPrefixToken('U');
512 if (!ReadUTFBufferAndDumpToStream(options))
514 stream.Printf("Summary Unavailable");
522 lldb_private::formatters::WCharStringSummaryProvider (ValueObject& valobj, Stream& stream)
524 ProcessSP process_sp = valobj.GetProcessSP();
528 lldb::addr_t data_addr = 0;
530 if (valobj.IsPointerType())
531 data_addr = valobj.GetValueAsUnsigned(0);
532 else if (valobj.IsArrayType())
533 data_addr = valobj.GetAddressOf();
535 if (data_addr == 0 || data_addr == LLDB_INVALID_ADDRESS)
538 clang::ASTContext* ast = valobj.GetClangType().GetASTContext();
543 ClangASTType wchar_clang_type = ClangASTContext::GetBasicType(ast, lldb::eBasicTypeWChar);
544 const uint32_t wchar_size = wchar_clang_type.GetBitSize();
552 ReadUTFBufferAndDumpToStreamOptions<UTF8> options;
553 options.SetLocation(data_addr);
554 options.SetConversionFunction(nullptr);
555 options.SetProcessSP(process_sp);
556 options.SetStream(&stream);
557 options.SetPrefixToken('L');
559 return ReadUTFBufferAndDumpToStream(options);
564 ReadUTFBufferAndDumpToStreamOptions<UTF16> options;
565 options.SetLocation(data_addr);
566 options.SetConversionFunction(ConvertUTF16toUTF8);
567 options.SetProcessSP(process_sp);
568 options.SetStream(&stream);
569 options.SetPrefixToken('L');
571 return ReadUTFBufferAndDumpToStream(options);
576 ReadUTFBufferAndDumpToStreamOptions<UTF32> options;
577 options.SetLocation(data_addr);
578 options.SetConversionFunction(ConvertUTF32toUTF8);
579 options.SetProcessSP(process_sp);
580 options.SetStream(&stream);
581 options.SetPrefixToken('L');
583 return ReadUTFBufferAndDumpToStream(options);
586 stream.Printf("size for wchar_t is not valid");
593 lldb_private::formatters::Char16SummaryProvider (ValueObject& valobj, Stream& stream)
597 valobj.GetData(data, error);
603 valobj.GetValueAsCString(lldb::eFormatUnicode16, value);
605 stream.Printf("%s ", value.c_str());
607 return DumpUTFBufferToStream<UTF16>(ConvertUTF16toUTF8,data,stream, 'u','\'',1);
611 lldb_private::formatters::Char32SummaryProvider (ValueObject& valobj, Stream& stream)
615 valobj.GetData(data, error);
621 valobj.GetValueAsCString(lldb::eFormatUnicode32, value);
623 stream.Printf("%s ", value.c_str());
625 return DumpUTFBufferToStream<UTF32>(ConvertUTF32toUTF8,data,stream, 'U','\'',1);
629 lldb_private::formatters::WCharSummaryProvider (ValueObject& valobj, Stream& stream)
633 valobj.GetData(data, error);
638 clang::ASTContext* ast = valobj.GetClangType().GetASTContext();
643 ClangASTType wchar_clang_type = ClangASTContext::GetBasicType(ast, lldb::eBasicTypeWChar);
644 const uint32_t wchar_size = wchar_clang_type.GetBitSize();
651 valobj.GetValueAsCString(lldb::eFormatChar, value);
653 stream.Printf("%s ", value.c_str());
654 return DumpUTFBufferToStream<UTF8>(nullptr,
662 valobj.GetValueAsCString(lldb::eFormatUnicode16, value);
664 stream.Printf("%s ", value.c_str());
665 return DumpUTFBufferToStream<UTF16>(ConvertUTF16toUTF8,
673 valobj.GetValueAsCString(lldb::eFormatUnicode32, value);
675 stream.Printf("%s ", value.c_str());
676 return DumpUTFBufferToStream<UTF32>(ConvertUTF32toUTF8,
683 stream.Printf("size for wchar_t is not valid");
689 // the field layout in a libc++ string (cap, side, data or data, size, cap)
690 enum LibcxxStringLayoutMode
692 eLibcxxStringLayoutModeCSD = 0,
693 eLibcxxStringLayoutModeDSC = 1,
694 eLibcxxStringLayoutModeInvalid = 0xffff
697 // this function abstracts away the layout and mode details of a libc++ string
698 // and returns the address of the data and the size ready for callers to consume
700 ExtractLibcxxStringInfo (ValueObject& valobj,
701 ValueObjectSP &location_sp,
704 ValueObjectSP D(valobj.GetChildAtIndexPath({0,0,0,0}));
708 ValueObjectSP layout_decider(D->GetChildAtIndexPath({0,0}));
710 // this child should exist
714 ConstString g_data_name("__data_");
715 ConstString g_size_name("__size_");
716 bool short_mode = false; // this means the string is in short-mode and the data is stored inline
717 LibcxxStringLayoutMode layout = (layout_decider->GetName() == g_data_name) ? eLibcxxStringLayoutModeDSC : eLibcxxStringLayoutModeCSD;
718 uint64_t size_mode_value = 0;
720 if (layout == eLibcxxStringLayoutModeDSC)
722 ValueObjectSP size_mode(D->GetChildAtIndexPath({1,1,0}));
726 if (size_mode->GetName() != g_size_name)
728 // we are hitting the padding structure, move along
729 size_mode = D->GetChildAtIndexPath({1,1,1});
734 size_mode_value = (size_mode->GetValueAsUnsigned(0));
735 short_mode = ((size_mode_value & 0x80) == 0);
739 ValueObjectSP size_mode(D->GetChildAtIndexPath({1,0,0}));
743 size_mode_value = (size_mode->GetValueAsUnsigned(0));
744 short_mode = ((size_mode_value & 1) == 0);
749 ValueObjectSP s(D->GetChildAtIndex(1, true));
752 location_sp = s->GetChildAtIndex((layout == eLibcxxStringLayoutModeDSC) ? 0 : 1, true);
753 size = (layout == eLibcxxStringLayoutModeDSC) ? size_mode_value : ((size_mode_value >> 1) % 256);
754 return (location_sp.get() != nullptr);
758 ValueObjectSP l(D->GetChildAtIndex(0, true));
761 // we can use the layout_decider object as the data pointer
762 location_sp = (layout == eLibcxxStringLayoutModeDSC) ? layout_decider : l->GetChildAtIndex(2, true);
763 ValueObjectSP size_vo(l->GetChildAtIndex(1, true));
764 if (!size_vo || !location_sp)
766 size = size_vo->GetValueAsUnsigned(0);
772 lldb_private::formatters::LibcxxWStringSummaryProvider (ValueObject& valobj, Stream& stream)
775 ValueObjectSP location_sp((ValueObject*)nullptr);
776 if (!ExtractLibcxxStringInfo(valobj, location_sp, size))
780 stream.Printf("L\"\"");
785 return WCharStringSummaryProvider(*location_sp.get(), stream);
789 lldb_private::formatters::LibcxxStringSummaryProvider (ValueObject& valobj, Stream& stream)
792 ValueObjectSP location_sp((ValueObject*)nullptr);
793 if (!ExtractLibcxxStringInfo(valobj, location_sp, size))
797 stream.Printf("\"\"");
803 if (location_sp->ReadPointedString(stream,
805 0, // max length is decided by the settings
806 false) == 0) // do not honor array (terminates on first 0 byte even for a char[])
807 stream.Printf("\"\""); // if nothing was read, print an empty string
808 return error.Success();
812 lldb_private::formatters::ObjCClassSummaryProvider (ValueObject& valobj, Stream& stream)
814 ProcessSP process_sp = valobj.GetProcessSP();
818 ObjCLanguageRuntime* runtime = (ObjCLanguageRuntime*)process_sp->GetLanguageRuntime(lldb::eLanguageTypeObjC);
823 ObjCLanguageRuntime::ClassDescriptorSP descriptor(runtime->GetClassDescriptorFromISA(valobj.GetValueAsUnsigned(0)));
825 if (!descriptor.get() || !descriptor->IsValid())
828 const char* class_name = descriptor->GetClassName().GetCString();
830 if (!class_name || !*class_name)
833 stream.Printf("%s",class_name);
837 class ObjCClassSyntheticChildrenFrontEnd : public SyntheticChildrenFrontEnd
840 ObjCClassSyntheticChildrenFrontEnd (lldb::ValueObjectSP valobj_sp) :
841 SyntheticChildrenFrontEnd(*valobj_sp.get())
846 CalculateNumChildren ()
851 virtual lldb::ValueObjectSP
852 GetChildAtIndex (size_t idx)
854 return lldb::ValueObjectSP();
870 GetIndexOfChildWithName (const ConstString &name)
876 ~ObjCClassSyntheticChildrenFrontEnd ()
881 SyntheticChildrenFrontEnd*
882 lldb_private::formatters::ObjCClassSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP valobj_sp)
884 return new ObjCClassSyntheticChildrenFrontEnd(valobj_sp);
887 template<bool needs_at>
889 lldb_private::formatters::NSDataSummaryProvider (ValueObject& valobj, Stream& stream)
891 ProcessSP process_sp = valobj.GetProcessSP();
895 ObjCLanguageRuntime* runtime = (ObjCLanguageRuntime*)process_sp->GetLanguageRuntime(lldb::eLanguageTypeObjC);
900 ObjCLanguageRuntime::ClassDescriptorSP descriptor(runtime->GetClassDescriptor(valobj));
902 if (!descriptor.get() || !descriptor->IsValid())
905 bool is_64bit = (process_sp->GetAddressByteSize() == 8);
906 lldb::addr_t valobj_addr = valobj.GetValueAsUnsigned(0);
913 const char* class_name = descriptor->GetClassName().GetCString();
915 if (!class_name || !*class_name)
918 if (!strcmp(class_name,"NSConcreteData") ||
919 !strcmp(class_name,"NSConcreteMutableData") ||
920 !strcmp(class_name,"__NSCFData"))
922 uint32_t offset = (is_64bit ? 16 : 8);
924 value = process_sp->ReadUnsignedIntegerFromMemory(valobj_addr + offset, is_64bit ? 8 : 4, 0, error);
930 if (!ExtractValueFromObjCExpression(valobj, "int", "length", value))
934 stream.Printf("%s%" PRIu64 " byte%s%s",
935 (needs_at ? "@\"" : ""),
937 (value != 1 ? "s" : ""),
938 (needs_at ? "\"" : ""));
944 ReadAsciiBufferAndDumpToStream (lldb::addr_t location,
945 lldb::ProcessSP& process_sp,
949 size_t *data_read = NULL,
950 char prefix_token = '@',
955 if (!process_sp || location == 0)
959 size = process_sp->GetTarget().GetMaximumSizeOfStringSummary();
961 size = std::min(size,process_sp->GetTarget().GetMaximumSizeOfStringSummary());
963 lldb::DataBufferSP buffer_sp(new DataBufferHeap(size,0));
965 my_data_read = process_sp->ReadCStringFromMemory(location, (char*)buffer_sp->GetBytes(), size, my_error);
970 *data_read = my_data_read;
975 dest.Printf("%c%c",prefix_token,quote);
978 dest.Printf("%s",(char*)buffer_sp->GetBytes());
980 dest.Printf("%c",quote);
986 lldb_private::formatters::NSTaggedString_SummaryProvider (ObjCLanguageRuntime::ClassDescriptorSP descriptor, Stream& stream)
990 uint64_t len_bits = 0, data_bits = 0;
991 if (!descriptor->GetTaggedPointerInfo(&len_bits,&data_bits,nullptr))
994 static const int g_MaxNonBitmaskedLen = 7; //TAGGED_STRING_UNPACKED_MAXLEN
995 static const int g_SixbitMaxLen = 9;
996 static const int g_fiveBitMaxLen = 11;
998 static const char *sixBitToCharLookup = "eilotrm.apdnsIc ufkMShjTRxgC4013" "bDNvwyUL2O856P-B79AFKEWV_zGJ/HYX";
1000 if (len_bits > g_fiveBitMaxLen)
1003 // this is a fairly ugly trick - pretend that the numeric value is actually a char*
1004 // this works under a few assumptions:
1005 // little endian architecture
1006 // sizeof(uint64_t) > g_MaxNonBitmaskedLen
1007 if (len_bits <= g_MaxNonBitmaskedLen)
1009 stream.Printf("@\"%s\"",(const char*)&data_bits);
1013 // if the data is bitmasked, we need to actually process the bytes
1014 uint8_t bitmask = 0;
1015 uint8_t shift_offset = 0;
1017 if (len_bits <= g_SixbitMaxLen)
1028 std::vector<uint8_t> bytes;
1029 bytes.resize(len_bits);
1030 for (; len_bits > 0; data_bits >>= shift_offset, --len_bits)
1032 uint8_t packed = data_bits & bitmask;
1033 bytes.insert(bytes.begin(), sixBitToCharLookup[packed]);
1036 stream.Printf("@\"%s\"",&bytes[0]);
1041 lldb_private::formatters::NSStringSummaryProvider (ValueObject& valobj, Stream& stream)
1043 ProcessSP process_sp = valobj.GetProcessSP();
1047 ObjCLanguageRuntime* runtime = (ObjCLanguageRuntime*)process_sp->GetLanguageRuntime(lldb::eLanguageTypeObjC);
1052 ObjCLanguageRuntime::ClassDescriptorSP descriptor(runtime->GetClassDescriptor(valobj));
1054 if (!descriptor.get() || !descriptor->IsValid())
1057 uint32_t ptr_size = process_sp->GetAddressByteSize();
1059 lldb::addr_t valobj_addr = valobj.GetValueAsUnsigned(0);
1064 const char* class_name = descriptor->GetClassName().GetCString();
1066 if (!class_name || !*class_name)
1069 bool is_tagged_ptr = (0 == strcmp(class_name,"NSTaggedPointerString")) && descriptor->GetTaggedPointerInfo();
1070 // for a tagged pointer, the descriptor has everything we need
1072 return NSTaggedString_SummaryProvider(descriptor, stream);
1074 // if not a tagged pointer that we know about, try the normal route
1075 uint64_t info_bits_location = valobj_addr + ptr_size;
1076 if (process_sp->GetByteOrder() != lldb::eByteOrderLittle)
1077 info_bits_location += 3;
1081 uint8_t info_bits = process_sp->ReadUnsignedIntegerFromMemory(info_bits_location, 1, 0, error);
1085 bool is_mutable = (info_bits & 1) == 1;
1086 bool is_inline = (info_bits & 0x60) == 0;
1087 bool has_explicit_length = (info_bits & (1 | 4)) != 4;
1088 bool is_unicode = (info_bits & 0x10) == 0x10;
1089 bool is_special = strcmp(class_name,"NSPathStore2") == 0;
1090 bool has_null = (info_bits & 8) == 8;
1092 size_t explicit_length = 0;
1093 if (!has_null && has_explicit_length && !is_special)
1095 lldb::addr_t explicit_length_offset = 2*ptr_size;
1096 if (is_mutable && !is_inline)
1097 explicit_length_offset = explicit_length_offset + ptr_size; // notInlineMutable.length;
1099 explicit_length = explicit_length + 0; // inline1.length;
1100 else if (!is_inline && !is_mutable)
1101 explicit_length_offset = explicit_length_offset + ptr_size; // notInlineImmutable1.length;
1103 explicit_length_offset = 0;
1105 if (explicit_length_offset)
1107 explicit_length_offset = valobj_addr + explicit_length_offset;
1108 explicit_length = process_sp->ReadUnsignedIntegerFromMemory(explicit_length_offset, 4, 0, error);
1112 if (strcmp(class_name,"NSString") &&
1113 strcmp(class_name,"CFStringRef") &&
1114 strcmp(class_name,"CFMutableStringRef") &&
1115 strcmp(class_name,"__NSCFConstantString") &&
1116 strcmp(class_name,"__NSCFString") &&
1117 strcmp(class_name,"NSCFConstantString") &&
1118 strcmp(class_name,"NSCFString") &&
1119 strcmp(class_name,"NSPathStore2"))
1121 // not one of us - but tell me class name
1122 stream.Printf("class name = %s",class_name);
1128 uint64_t location = 2 * ptr_size + valobj_addr;
1129 location = process_sp->ReadPointerFromMemory(location, error);
1132 if (has_explicit_length && is_unicode)
1134 ReadUTFBufferAndDumpToStreamOptions<UTF16> options;
1135 options.SetConversionFunction(ConvertUTF16toUTF8);
1136 options.SetLocation(location);
1137 options.SetProcessSP(process_sp);
1138 options.SetStream(&stream);
1139 options.SetPrefixToken('@');
1140 options.SetQuote('"');
1141 options.SetSourceSize(explicit_length);
1142 options.SetNeedsZeroTermination(false);
1143 return ReadUTFBufferAndDumpToStream (options);
1146 return ReadAsciiBufferAndDumpToStream(location+1,process_sp,stream, explicit_length);
1148 else if (is_inline && has_explicit_length && !is_unicode && !is_special && !is_mutable)
1150 uint64_t location = 3 * ptr_size + valobj_addr;
1151 return ReadAsciiBufferAndDumpToStream(location,process_sp,stream,explicit_length);
1153 else if (is_unicode)
1155 uint64_t location = valobj_addr + 2*ptr_size;
1158 if (!has_explicit_length)
1160 stream.Printf("found new combo");
1164 location += ptr_size;
1168 location = process_sp->ReadPointerFromMemory(location, error);
1172 ReadUTFBufferAndDumpToStreamOptions<UTF16> options;
1173 options.SetConversionFunction(ConvertUTF16toUTF8);
1174 options.SetLocation(location);
1175 options.SetProcessSP(process_sp);
1176 options.SetStream(&stream);
1177 options.SetPrefixToken('@');
1178 options.SetQuote('"');
1179 options.SetSourceSize(explicit_length);
1180 options.SetNeedsZeroTermination(has_explicit_length == false);
1181 return ReadUTFBufferAndDumpToStream (options);
1183 else if (is_special)
1185 uint64_t location = valobj_addr + (ptr_size == 8 ? 12 : 8);
1186 ReadUTFBufferAndDumpToStreamOptions<UTF16> options;
1187 options.SetConversionFunction(ConvertUTF16toUTF8);
1188 options.SetLocation(location);
1189 options.SetProcessSP(process_sp);
1190 options.SetStream(&stream);
1191 options.SetPrefixToken('@');
1192 options.SetQuote('"');
1193 options.SetSourceSize(explicit_length);
1194 options.SetNeedsZeroTermination(has_explicit_length == false);
1195 return ReadUTFBufferAndDumpToStream (options);
1199 uint64_t location = valobj_addr + 2*ptr_size;
1200 if (!has_explicit_length)
1202 return ReadAsciiBufferAndDumpToStream(location,process_sp,stream,explicit_length);
1206 uint64_t location = valobj_addr + 2*ptr_size;
1207 location = process_sp->ReadPointerFromMemory(location, error);
1210 if (has_explicit_length && !has_null)
1211 explicit_length++; // account for the fact that there is no NULL and we need to have one added
1212 return ReadAsciiBufferAndDumpToStream(location,process_sp,stream,explicit_length);
1215 stream.Printf("class name = %s",class_name);
1221 lldb_private::formatters::NSAttributedStringSummaryProvider (ValueObject& valobj, Stream& stream)
1223 TargetSP target_sp(valobj.GetTargetSP());
1226 uint32_t addr_size = target_sp->GetArchitecture().GetAddressByteSize();
1227 uint64_t pointer_value = valobj.GetValueAsUnsigned(0);
1230 pointer_value += addr_size;
1231 ClangASTType type(valobj.GetClangType());
1232 ExecutionContext exe_ctx(target_sp,false);
1233 ValueObjectSP child_ptr_sp(valobj.CreateValueObjectFromAddress("string_ptr", pointer_value, exe_ctx, type));
1238 child_ptr_sp->GetData(data, error);
1241 ValueObjectSP child_sp(child_ptr_sp->CreateValueObjectFromData("string_data", data, exe_ctx, type));
1242 child_sp->GetValueAsUnsigned(0);
1244 return NSStringSummaryProvider(*child_sp, stream);
1249 lldb_private::formatters::NSMutableAttributedStringSummaryProvider (ValueObject& valobj, Stream& stream)
1251 return NSAttributedStringSummaryProvider(valobj, stream);
1255 lldb_private::formatters::RuntimeSpecificDescriptionSummaryProvider (ValueObject& valobj, Stream& stream)
1257 stream.Printf("%s",valobj.GetObjectDescription());
1262 lldb_private::formatters::ObjCBOOLSummaryProvider (ValueObject& valobj, Stream& stream)
1264 const uint32_t type_info = valobj.GetClangType().GetTypeInfo();
1266 ValueObjectSP real_guy_sp = valobj.GetSP();
1268 if (type_info & ClangASTType::eTypeIsPointer)
1271 real_guy_sp = valobj.Dereference(err);
1272 if (err.Fail() || !real_guy_sp)
1275 else if (type_info & ClangASTType::eTypeIsReference)
1277 real_guy_sp = valobj.GetChildAtIndex(0, true);
1281 uint64_t value = real_guy_sp->GetValueAsUnsigned(0);
1284 stream.Printf("NO");
1287 stream.Printf("YES");
1291 template <bool is_sel_ptr>
1293 lldb_private::formatters::ObjCSELSummaryProvider (ValueObject& valobj, Stream& stream)
1295 lldb::ValueObjectSP valobj_sp;
1297 ClangASTType charstar (valobj.GetClangType().GetBasicTypeFromAST(eBasicTypeChar).GetPointerType());
1302 ExecutionContext exe_ctx(valobj.GetExecutionContextRef());
1306 lldb::addr_t data_address = valobj.GetValueAsUnsigned(LLDB_INVALID_ADDRESS);
1307 if (data_address == LLDB_INVALID_ADDRESS)
1309 valobj_sp = ValueObject::CreateValueObjectFromAddress("text", data_address, exe_ctx, charstar);
1315 valobj.GetData(data, error);
1318 valobj_sp = ValueObject::CreateValueObjectFromData("text", data, exe_ctx, charstar);
1324 stream.Printf("%s",valobj_sp->GetSummaryAsCString());
1328 // POSIX has an epoch on Jan-1-1970, but Cocoa prefers Jan-1-2001
1329 // this call gives the POSIX equivalent of the Cocoa epoch
1331 lldb_private::formatters::GetOSXEpoch ()
1333 static time_t epoch = 0;
1339 tm_epoch.tm_sec = 0;
1340 tm_epoch.tm_hour = 0;
1341 tm_epoch.tm_min = 0;
1342 tm_epoch.tm_mon = 0;
1343 tm_epoch.tm_mday = 1;
1344 tm_epoch.tm_year = 2001-1900; // for some reason, we need to subtract 1900 from this field. not sure why.
1345 tm_epoch.tm_isdst = -1;
1346 tm_epoch.tm_gmtoff = 0;
1347 tm_epoch.tm_zone = NULL;
1348 epoch = timegm(&tm_epoch);
1355 lldb_private::formatters::ExtractIndexFromString (const char* item_name)
1357 if (!item_name || !*item_name)
1359 if (*item_name != '[')
1362 char* endptr = NULL;
1363 unsigned long int idx = ::strtoul(item_name, &endptr, 0);
1364 if (idx == 0 && endptr == item_name)
1366 if (idx == ULONG_MAX)
1371 lldb_private::formatters::VectorIteratorSyntheticFrontEnd::VectorIteratorSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp,
1372 ConstString item_name) :
1373 SyntheticChildrenFrontEnd(*valobj_sp.get()),
1375 m_item_name(item_name),
1383 lldb_private::formatters::VectorIteratorSyntheticFrontEnd::Update()
1387 ValueObjectSP valobj_sp = m_backend.GetSP();
1394 ValueObjectSP item_ptr(valobj_sp->GetChildMemberWithName(m_item_name,true));
1397 if (item_ptr->GetValueAsUnsigned(0) == 0)
1400 m_exe_ctx_ref = valobj_sp->GetExecutionContextRef();
1401 m_item_sp = ValueObject::CreateValueObjectFromAddress("item", item_ptr->GetValueAsUnsigned(0), m_exe_ctx_ref, item_ptr->GetClangType().GetPointeeType());
1408 lldb_private::formatters::VectorIteratorSyntheticFrontEnd::CalculateNumChildren ()
1414 lldb_private::formatters::VectorIteratorSyntheticFrontEnd::GetChildAtIndex (size_t idx)
1418 return lldb::ValueObjectSP();
1422 lldb_private::formatters::VectorIteratorSyntheticFrontEnd::MightHaveChildren ()
1428 lldb_private::formatters::VectorIteratorSyntheticFrontEnd::GetIndexOfChildWithName (const ConstString &name)
1430 if (name == ConstString("item"))
1435 lldb_private::formatters::VectorIteratorSyntheticFrontEnd::~VectorIteratorSyntheticFrontEnd ()
1440 lldb_private::formatters::NSDataSummaryProvider<true> (ValueObject&, Stream&) ;
1443 lldb_private::formatters::NSDataSummaryProvider<false> (ValueObject&, Stream&) ;
1446 lldb_private::formatters::ObjCSELSummaryProvider<true> (ValueObject&, Stream&) ;
1449 lldb_private::formatters::ObjCSELSummaryProvider<false> (ValueObject&, Stream&) ;