Home | History | Annotate | Download | only in DataFormatters
      1 //===-- 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 
     10 #include "lldb/lldb-python.h"
     11 
     12 #include "lldb/DataFormatters/CXXFormatterFunctions.h"
     13 
     14 #include "llvm/Support/ConvertUTF.h"
     15 
     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"
     25 
     26 #include <algorithm>
     27 
     28 using namespace lldb;
     29 using namespace lldb_private;
     30 using namespace lldb_private::formatters;
     31 
     32 bool
     33 lldb_private::formatters::ExtractValueFromObjCExpression (ValueObject &valobj,
     34                                                           const char* target_type,
     35                                                           const char* selector,
     36                                                           uint64_t &value)
     37 {
     38     if (!target_type || !*target_type)
     39         return false;
     40     if (!selector || !*selector)
     41         return false;
     42     StreamString expr;
     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)
     49         return false;
     50 
     51     EvaluateExpressionOptions options;
     52     options.SetCoerceToId(false)
     53     .SetUnwindOnError(true)
     54     .SetKeepInMemory(true);
     55 
     56     target->EvaluateExpression(expr.GetData(),
     57                                stack_frame,
     58                                result_sp,
     59                                options);
     60     if (!result_sp)
     61         return false;
     62     value = result_sp->GetValueAsUnsigned(0);
     63     return true;
     64 }
     65 
     66 bool
     67 lldb_private::formatters::ExtractSummaryFromObjCExpression (ValueObject &valobj,
     68                                                             const char* target_type,
     69                                                             const char* selector,
     70                                                             Stream &stream)
     71 {
     72     if (!target_type || !*target_type)
     73         return false;
     74     if (!selector || !*selector)
     75         return false;
     76     StreamString expr;
     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)
     83         return false;
     84 
     85     EvaluateExpressionOptions options;
     86     options.SetCoerceToId(false)
     87     .SetUnwindOnError(true)
     88     .SetKeepInMemory(true)
     89     .SetUseDynamic(lldb::eDynamicCanRunTarget);
     90 
     91     target->EvaluateExpression(expr.GetData(),
     92                                stack_frame,
     93                                result_sp,
     94                                options);
     95     if (!result_sp)
     96         return false;
     97     stream.Printf("%s",result_sp->GetSummaryAsCString());
     98     return true;
     99 }
    100 
    101 lldb::ValueObjectSP
    102 lldb_private::formatters::CallSelectorOnObject (ValueObject &valobj,
    103                                                 const char* return_type,
    104                                                 const char* selector,
    105                                                 uint64_t index)
    106 {
    107     lldb::ValueObjectSP valobj_sp;
    108     if (!return_type || !*return_type)
    109         return valobj_sp;
    110     if (!selector || !*selector)
    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:%" 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)
    121         return valobj_sp;
    122 
    123     EvaluateExpressionOptions options;
    124     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 
    136 lldb::ValueObjectSP
    137 lldb_private::formatters::CallSelectorOnObject (ValueObject &valobj,
    138                                                 const char* return_type,
    139                                                 const char* selector,
    140                                                 const char* key)
    141 {
    142     lldb::ValueObjectSP valobj_sp;
    143     if (!return_type || !*return_type)
    144         return valobj_sp;
    145     if (!selector || !*selector)
    146         return valobj_sp;
    147     if (!key || !*key)
    148         return valobj_sp;
    149     StreamString expr_path_stream;
    150     valobj.GetExpressionPath(expr_path_stream, false);
    151     StreamString expr;
    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)
    158         return valobj_sp;
    159 
    160     EvaluateExpressionOptions options;
    161     options.SetCoerceToId(false)
    162     .SetUnwindOnError(true)
    163     .SetKeepInMemory(true)
    164     .SetUseDynamic(lldb::eDynamicCanRunTarget);
    165 
    166     target->EvaluateExpression(expr.GetData(),
    167                                stack_frame,
    168                                valobj_sp,
    169                                options);
    170     return valobj_sp;
    171 }
    172 
    173 // use this call if you already have an LLDB-side buffer for the data
    174 template<typename SourceDataType>
    175 static bool
    176 DumpUTFBufferToStream (ConversionResult (*ConvertFunction) (const SourceDataType**,
    177                                                             const SourceDataType*,
    178                                                             UTF8**,
    179                                                             UTF8*,
    180                                                             ConversionFlags),
    181                        DataExtractor& data,
    182                        Stream& stream,
    183                        char prefix_token = '@',
    184                        char quote = '"',
    185                        uint32_t sourceSize = 0)
    186 {
    187     if (prefix_token != 0)
    188         stream.Printf("%c",prefix_token);
    189     if (quote != 0)
    190         stream.Printf("%c",quote);
    191     if (data.GetByteSize() && data.GetDataStart() && data.GetDataEnd())
    192     {
    193         const int bufferSPSize = data.GetByteSize();
    194         if (sourceSize == 0)
    195         {
    196             const int origin_encoding = 8*sizeof(SourceDataType);
    197             sourceSize = bufferSPSize/(origin_encoding / 4);
    198         }
    199 
    200         SourceDataType *data_ptr = (SourceDataType*)data.GetDataStart();
    201         SourceDataType *data_end_ptr = data_ptr + sourceSize;
    202 
    203         while (data_ptr < data_end_ptr)
    204         {
    205             if (!*data_ptr)
    206             {
    207                 data_end_ptr = data_ptr;
    208                 break;
    209             }
    210             data_ptr++;
    211         }
    212 
    213         data_ptr = (SourceDataType*)data.GetDataStart();
    214 
    215         lldb::DataBufferSP utf8_data_buffer_sp;
    216         UTF8* utf8_data_ptr = nullptr;
    217         UTF8* utf8_data_end_ptr = nullptr;
    218 
    219         if (ConvertFunction)
    220         {
    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
    226         }
    227         else
    228         {
    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;
    233         }
    234 
    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++)
    239         {
    240             if (!*utf8_data_ptr)
    241                 break;
    242             stream.Printf("%c",*utf8_data_ptr);
    243         }
    244     }
    245     if (quote != 0)
    246         stream.Printf("%c",quote);
    247     return true;
    248 }
    249 
    250 template<typename SourceDataType>
    251 class ReadUTFBufferAndDumpToStreamOptions
    252 {
    253 public:
    254     typedef ConversionResult (*ConvertFunctionType) (const SourceDataType**,
    255                                                      const SourceDataType*,
    256                                                      UTF8**,
    257                                                      UTF8*,
    258                                                      ConversionFlags);
    259 
    260     ReadUTFBufferAndDumpToStreamOptions () :
    261     m_conversion_function(NULL),
    262     m_location(0),
    263     m_process_sp(),
    264     m_stream(NULL),
    265     m_prefix_token('@'),
    266     m_quote('"'),
    267     m_source_size(0),
    268     m_needs_zero_termination(true)
    269     {
    270     }
    271 
    272     ReadUTFBufferAndDumpToStreamOptions&
    273     SetConversionFunction (ConvertFunctionType f)
    274     {
    275         m_conversion_function = f;
    276         return *this;
    277     }
    278 
    279     ConvertFunctionType
    280     GetConversionFunction () const
    281     {
    282         return m_conversion_function;
    283     }
    284 
    285     ReadUTFBufferAndDumpToStreamOptions&
    286     SetLocation (uint64_t l)
    287     {
    288         m_location = l;
    289         return *this;
    290     }
    291 
    292     uint64_t
    293     GetLocation () const
    294     {
    295         return m_location;
    296     }
    297 
    298     ReadUTFBufferAndDumpToStreamOptions&
    299     SetProcessSP (ProcessSP p)
    300     {
    301         m_process_sp = p;
    302         return *this;
    303     }
    304 
    305     ProcessSP
    306     GetProcessSP () const
    307     {
    308         return m_process_sp;
    309     }
    310 
    311     ReadUTFBufferAndDumpToStreamOptions&
    312     SetStream (Stream* s)
    313     {
    314         m_stream = s;
    315         return *this;
    316     }
    317 
    318     Stream*
    319     GetStream () const
    320     {
    321         return m_stream;
    322     }
    323 
    324     ReadUTFBufferAndDumpToStreamOptions&
    325     SetPrefixToken (char p)
    326     {
    327         m_prefix_token = p;
    328         return *this;
    329     }
    330 
    331     char
    332     GetPrefixToken () const
    333     {
    334         return m_prefix_token;
    335     }
    336 
    337     ReadUTFBufferAndDumpToStreamOptions&
    338     SetQuote (char q)
    339     {
    340         m_quote = q;
    341         return *this;
    342     }
    343 
    344     char
    345     GetQuote () const
    346     {
    347         return m_quote;
    348     }
    349 
    350     ReadUTFBufferAndDumpToStreamOptions&
    351     SetSourceSize (uint32_t s)
    352     {
    353         m_source_size = s;
    354         return *this;
    355     }
    356 
    357     uint32_t
    358     GetSourceSize () const
    359     {
    360         return m_source_size;
    361     }
    362 
    363     ReadUTFBufferAndDumpToStreamOptions&
    364     SetNeedsZeroTermination (bool z)
    365     {
    366         m_needs_zero_termination = z;
    367         return *this;
    368     }
    369 
    370     bool
    371     GetNeedsZeroTermination () const
    372     {
    373         return m_needs_zero_termination;
    374     }
    375 
    376 private:
    377     ConvertFunctionType m_conversion_function;
    378     uint64_t m_location;
    379     ProcessSP m_process_sp;
    380     Stream* m_stream;
    381     char m_prefix_token;
    382     char m_quote;
    383     uint32_t m_source_size;
    384     bool m_needs_zero_termination;
    385 };
    386 
    387 template<typename SourceDataType>
    388 static bool
    389 ReadUTFBufferAndDumpToStream (const ReadUTFBufferAndDumpToStreamOptions<SourceDataType>& options)
    390 {
    391     if (options.GetLocation() == 0 || options.GetLocation() == LLDB_INVALID_ADDRESS)
    392         return false;
    393 
    394     ProcessSP process_sp(options.GetProcessSP());
    395 
    396     if (!process_sp)
    397         return false;
    398 
    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)
    402         return false;
    403     // if not UTF8, I need a conversion function to return proper UTF8
    404     if (origin_encoding != 8 && !options.GetConversionFunction())
    405         return false;
    406 
    407     if (!options.GetStream())
    408         return false;
    409 
    410     uint32_t sourceSize = options.GetSourceSize();
    411     bool needs_zero_terminator = options.GetNeedsZeroTermination();
    412 
    413     if (!sourceSize)
    414     {
    415         sourceSize = process_sp->GetTarget().GetMaximumSizeOfStringSummary();
    416         needs_zero_terminator = true;
    417     }
    418     else
    419         sourceSize = std::min(sourceSize,process_sp->GetTarget().GetMaximumSizeOfStringSummary());
    420 
    421     const int bufferSPSize = sourceSize * type_width;
    422 
    423     lldb::DataBufferSP buffer_sp(new DataBufferHeap(bufferSPSize,0));
    424 
    425     if (!buffer_sp->GetBytes())
    426         return false;
    427 
    428     Error error;
    429     char *buffer = reinterpret_cast<char *>(buffer_sp->GetBytes());
    430 
    431     size_t data_read = 0;
    432     if (needs_zero_terminator)
    433         data_read = process_sp->ReadStringFromMemory(options.GetLocation(), buffer, bufferSPSize, error, type_width);
    434     else
    435         data_read = process_sp->ReadMemoryFromInferior(options.GetLocation(), (char*)buffer_sp->GetBytes(), bufferSPSize, error);
    436 
    437     if (error.Fail() || data_read == 0)
    438     {
    439         options.GetStream()->Printf("unable to read data");
    440         return true;
    441     }
    442 
    443     DataExtractor data(buffer_sp, process_sp->GetByteOrder(), process_sp->GetAddressByteSize());
    444 
    445     return DumpUTFBufferToStream(options.GetConversionFunction(), data, *options.GetStream(), options.GetPrefixToken(), options.GetQuote(), sourceSize);
    446 }
    447 
    448 bool
    449 lldb_private::formatters::Char16StringSummaryProvider (ValueObject& valobj, Stream& stream)
    450 {
    451     ProcessSP process_sp = valobj.GetProcessSP();
    452     if (!process_sp)
    453         return false;
    454 
    455     lldb::addr_t valobj_addr = valobj.GetValueAsUnsigned(0);
    456 
    457     if (!valobj_addr)
    458         return false;
    459 
    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');
    466 
    467     if (!ReadUTFBufferAndDumpToStream(options))
    468     {
    469         stream.Printf("Summary Unavailable");
    470         return true;
    471     }
    472 
    473     return true;
    474 }
    475 
    476 bool
    477 lldb_private::formatters::Char32StringSummaryProvider (ValueObject& valobj, Stream& stream)
    478 {
    479     ProcessSP process_sp = valobj.GetProcessSP();
    480     if (!process_sp)
    481         return false;
    482 
    483     lldb::addr_t valobj_addr = valobj.GetValueAsUnsigned(0);
    484 
    485     if (!valobj_addr)
    486         return false;
    487 
    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');
    494 
    495     if (!ReadUTFBufferAndDumpToStream(options))
    496     {
    497         stream.Printf("Summary Unavailable");
    498         return true;
    499     }
    500 
    501     return true;
    502 }
    503 
    504 bool
    505 lldb_private::formatters::WCharStringSummaryProvider (ValueObject& valobj, Stream& stream)
    506 {
    507     ProcessSP process_sp = valobj.GetProcessSP();
    508     if (!process_sp)
    509         return false;
    510 
    511     lldb::addr_t data_addr = 0;
    512 
    513     if (valobj.IsPointerType())
    514         data_addr = valobj.GetValueAsUnsigned(0);
    515     else if (valobj.IsArrayType())
    516         data_addr = valobj.GetAddressOf();
    517 
    518     if (data_addr == 0 || data_addr == LLDB_INVALID_ADDRESS)
    519         return false;
    520 
    521     clang::ASTContext* ast = valobj.GetClangType().GetASTContext();
    522 
    523     if (!ast)
    524         return false;
    525 
    526     ClangASTType wchar_clang_type = ClangASTContext::GetBasicType(ast, lldb::eBasicTypeWChar);
    527     const uint32_t wchar_size = wchar_clang_type.GetBitSize();
    528 
    529     switch (wchar_size)
    530     {
    531         case 8:
    532         {
    533             // utf 8
    534 
    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');
    541 
    542             return ReadUTFBufferAndDumpToStream(options);
    543         }
    544         case 16:
    545         {
    546             // utf 16
    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');
    553 
    554             return ReadUTFBufferAndDumpToStream(options);
    555         }
    556         case 32:
    557         {
    558             // utf 32
    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');
    565 
    566             return ReadUTFBufferAndDumpToStream(options);
    567         }
    568         default:
    569             stream.Printf("size for wchar_t is not valid");
    570             return true;
    571     }
    572     return true;
    573 }
    574 
    575 bool
    576 lldb_private::formatters::Char16SummaryProvider (ValueObject& valobj, Stream& stream)
    577 {
    578     DataExtractor data;
    579     valobj.GetData(data);
    580 
    581     std::string value;
    582     valobj.GetValueAsCString(lldb::eFormatUnicode16, value);
    583     if (!value.empty())
    584         stream.Printf("%s ", value.c_str());
    585 
    586     return DumpUTFBufferToStream<UTF16>(ConvertUTF16toUTF8,data,stream, 'u','\'',1);
    587 }
    588 
    589 bool
    590 lldb_private::formatters::Char32SummaryProvider (ValueObject& valobj, Stream& stream)
    591 {
    592     DataExtractor data;
    593     valobj.GetData(data);
    594 
    595     std::string value;
    596     valobj.GetValueAsCString(lldb::eFormatUnicode32, value);
    597     if (!value.empty())
    598         stream.Printf("%s ", value.c_str());
    599 
    600     return DumpUTFBufferToStream<UTF32>(ConvertUTF32toUTF8,data,stream, 'U','\'',1);
    601 }
    602 
    603 bool
    604 lldb_private::formatters::WCharSummaryProvider (ValueObject& valobj, Stream& stream)
    605 {
    606     DataExtractor data;
    607     valobj.GetData(data);
    608 
    609     clang::ASTContext* ast = valobj.GetClangType().GetASTContext();
    610 
    611     if (!ast)
    612         return false;
    613 
    614     ClangASTType wchar_clang_type = ClangASTContext::GetBasicType(ast, lldb::eBasicTypeWChar);
    615     const uint32_t wchar_size = wchar_clang_type.GetBitSize();
    616     std::string value;
    617 
    618     switch (wchar_size)
    619     {
    620         case 8:
    621             // utf 8
    622             valobj.GetValueAsCString(lldb::eFormatChar, value);
    623             if (!value.empty())
    624                 stream.Printf("%s ", value.c_str());
    625             return DumpUTFBufferToStream<UTF8>(nullptr,
    626                                                data,
    627                                                stream,
    628                                                'L',
    629                                                '\'',
    630                                                1);
    631         case 16:
    632             // utf 16
    633             valobj.GetValueAsCString(lldb::eFormatUnicode16, value);
    634             if (!value.empty())
    635                 stream.Printf("%s ", value.c_str());
    636             return DumpUTFBufferToStream<UTF16>(ConvertUTF16toUTF8,
    637                                                 data,
    638                                                 stream,
    639                                                 'L',
    640                                                 '\'',
    641                                                 1);
    642         case 32:
    643             // utf 32
    644             valobj.GetValueAsCString(lldb::eFormatUnicode32, value);
    645             if (!value.empty())
    646                 stream.Printf("%s ", value.c_str());
    647             return DumpUTFBufferToStream<UTF32>(ConvertUTF32toUTF8,
    648                                                 data,
    649                                                 stream,
    650                                                 'L',
    651                                                 '\'',
    652                                                 1);
    653         default:
    654             stream.Printf("size for wchar_t is not valid");
    655             return true;
    656     }
    657     return true;
    658 }
    659 
    660 // the field layout in a libc++ string (cap, side, data or data, size, cap)
    661 enum LibcxxStringLayoutMode
    662 {
    663     eLibcxxStringLayoutModeCSD = 0,
    664     eLibcxxStringLayoutModeDSC = 1,
    665     eLibcxxStringLayoutModeInvalid = 0xffff
    666 };
    667 
    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
    670 static bool
    671 ExtractLibcxxStringInfo (ValueObject& valobj,
    672                          ValueObjectSP &location_sp,
    673                          uint64_t& size)
    674 {
    675     ValueObjectSP D(valobj.GetChildAtIndexPath({0,0,0,0}));
    676     if (!D)
    677         return false;
    678 
    679     ValueObjectSP layout_decider(D->GetChildAtIndexPath({0,0}));
    680 
    681     // this child should exist
    682     if (!layout_decider)
    683         return false;
    684 
    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;
    690 
    691     if (layout == eLibcxxStringLayoutModeDSC)
    692     {
    693         ValueObjectSP size_mode(D->GetChildAtIndexPath({1,1,0}));
    694         if (!size_mode)
    695             return false;
    696 
    697         if (size_mode->GetName() != g_size_name)
    698         {
    699             // we are hitting the padding structure, move along
    700             size_mode = D->GetChildAtIndexPath({1,1,1});
    701             if (!size_mode)
    702                 return false;
    703         }
    704 
    705         size_mode_value = (size_mode->GetValueAsUnsigned(0));
    706         short_mode = ((size_mode_value & 0x80) == 0);
    707     }
    708     else
    709     {
    710         ValueObjectSP size_mode(D->GetChildAtIndexPath({1,0,0}));
    711         if (!size_mode)
    712             return false;
    713 
    714         size_mode_value = (size_mode->GetValueAsUnsigned(0));
    715         short_mode = ((size_mode_value & 1) == 0);
    716     }
    717 
    718     if (short_mode)
    719     {
    720         ValueObjectSP s(D->GetChildAtIndex(1, true));
    721         if (!s)
    722             return false;
    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);
    726     }
    727     else
    728     {
    729         ValueObjectSP l(D->GetChildAtIndex(0, true));
    730         if (!l)
    731             return false;
    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)
    736             return false;
    737         size = size_vo->GetValueAsUnsigned(0);
    738         return true;
    739     }
    740 }
    741 
    742 bool
    743 lldb_private::formatters::LibcxxWStringSummaryProvider (ValueObject& valobj, Stream& stream)
    744 {
    745     uint64_t size = 0;
    746     ValueObjectSP location_sp((ValueObject*)nullptr);
    747     if (!ExtractLibcxxStringInfo(valobj, location_sp, size))
    748         return false;
    749     if (size == 0)
    750     {
    751         stream.Printf("L\"\"");
    752         return true;
    753     }
    754     if (!location_sp)
    755         return false;
    756     return WCharStringSummaryProvider(*location_sp.get(), stream);
    757 }
    758 
    759 bool
    760 lldb_private::formatters::LibcxxStringSummaryProvider (ValueObject& valobj, Stream& stream)
    761 {
    762     uint64_t size = 0;
    763     ValueObjectSP location_sp((ValueObject*)nullptr);
    764     if (!ExtractLibcxxStringInfo(valobj, location_sp, size))
    765         return false;
    766     if (size == 0)
    767     {
    768         stream.Printf("\"\"");
    769         return true;
    770     }
    771     if (!location_sp)
    772         return false;
    773     Error error;
    774     if (location_sp->ReadPointedString(stream,
    775                                        error,
    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();
    780 }
    781 
    782 bool
    783 lldb_private::formatters::ObjCClassSummaryProvider (ValueObject& valobj, Stream& stream)
    784 {
    785     ProcessSP process_sp = valobj.GetProcessSP();
    786     if (!process_sp)
    787         return false;
    788 
    789     ObjCLanguageRuntime* runtime = (ObjCLanguageRuntime*)process_sp->GetLanguageRuntime(lldb::eLanguageTypeObjC);
    790 
    791     if (!runtime)
    792         return false;
    793 
    794     ObjCLanguageRuntime::ClassDescriptorSP descriptor(runtime->GetClassDescriptorFromISA(valobj.GetValueAsUnsigned(0)));
    795 
    796     if (!descriptor.get() || !descriptor->IsValid())
    797         return false;
    798 
    799     const char* class_name = descriptor->GetClassName().GetCString();
    800 
    801     if (!class_name || !*class_name)
    802         return false;
    803 
    804     stream.Printf("%s",class_name);
    805     return true;
    806 }
    807 
    808 class ObjCClassSyntheticChildrenFrontEnd : public SyntheticChildrenFrontEnd
    809 {
    810 public:
    811     ObjCClassSyntheticChildrenFrontEnd (lldb::ValueObjectSP valobj_sp) :
    812     SyntheticChildrenFrontEnd(*valobj_sp.get())
    813     {
    814     }
    815 
    816     virtual size_t
    817     CalculateNumChildren ()
    818     {
    819         return 0;
    820     }
    821 
    822     virtual lldb::ValueObjectSP
    823     GetChildAtIndex (size_t idx)
    824     {
    825         return lldb::ValueObjectSP();
    826     }
    827 
    828     virtual bool
    829     Update()
    830     {
    831         return false;
    832     }
    833 
    834     virtual bool
    835     MightHaveChildren ()
    836     {
    837         return false;
    838     }
    839 
    840     virtual size_t
    841     GetIndexOfChildWithName (const ConstString &name)
    842     {
    843         return UINT32_MAX;
    844     }
    845 
    846     virtual
    847     ~ObjCClassSyntheticChildrenFrontEnd ()
    848     {
    849     }
    850 };
    851 
    852 SyntheticChildrenFrontEnd*
    853 lldb_private::formatters::ObjCClassSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP valobj_sp)
    854 {
    855     return new ObjCClassSyntheticChildrenFrontEnd(valobj_sp);
    856 }
    857 
    858 template<bool needs_at>
    859 bool
    860 lldb_private::formatters::NSDataSummaryProvider (ValueObject& valobj, Stream& stream)
    861 {
    862     ProcessSP process_sp = valobj.GetProcessSP();
    863     if (!process_sp)
    864         return false;
    865 
    866     ObjCLanguageRuntime* runtime = (ObjCLanguageRuntime*)process_sp->GetLanguageRuntime(lldb::eLanguageTypeObjC);
    867 
    868     if (!runtime)
    869         return false;
    870 
    871     ObjCLanguageRuntime::ClassDescriptorSP descriptor(runtime->GetClassDescriptor(valobj));
    872 
    873     if (!descriptor.get() || !descriptor->IsValid())
    874         return false;
    875 
    876     bool is_64bit = (process_sp->GetAddressByteSize() == 8);
    877     lldb::addr_t valobj_addr = valobj.GetValueAsUnsigned(0);
    878 
    879     if (!valobj_addr)
    880         return false;
    881 
    882     uint64_t value = 0;
    883 
    884     const char* class_name = descriptor->GetClassName().GetCString();
    885 
    886     if (!class_name || !*class_name)
    887         return false;
    888 
    889     if (!strcmp(class_name,"NSConcreteData") ||
    890         !strcmp(class_name,"NSConcreteMutableData") ||
    891         !strcmp(class_name,"__NSCFData"))
    892     {
    893         uint32_t offset = (is_64bit ? 16 : 8);
    894         Error error;
    895         value = process_sp->ReadUnsignedIntegerFromMemory(valobj_addr + offset, is_64bit ? 8 : 4, 0, error);
    896         if (error.Fail())
    897             return false;
    898     }
    899     else
    900     {
    901         if (!ExtractValueFromObjCExpression(valobj, "int", "length", value))
    902             return false;
    903     }
    904 
    905     stream.Printf("%s%" PRIu64 " byte%s%s",
    906                   (needs_at ? "@\"" : ""),
    907                   value,
    908                   (value != 1 ? "s" : ""),
    909                   (needs_at ? "\"" : ""));
    910 
    911     return true;
    912 }
    913 
    914 static bool
    915 ReadAsciiBufferAndDumpToStream (lldb::addr_t location,
    916                                 lldb::ProcessSP& process_sp,
    917                                 Stream& dest,
    918                                 uint32_t size = 0,
    919                                 Error* error = NULL,
    920                                 size_t *data_read = NULL,
    921                                 char prefix_token = '@',
    922                                 char quote = '"')
    923 {
    924     Error my_error;
    925     size_t my_data_read;
    926     if (!process_sp || location == 0)
    927         return false;
    928 
    929     if (!size)
    930         size = process_sp->GetTarget().GetMaximumSizeOfStringSummary();
    931     else
    932         size = std::min(size,process_sp->GetTarget().GetMaximumSizeOfStringSummary());
    933 
    934     lldb::DataBufferSP buffer_sp(new DataBufferHeap(size,0));
    935 
    936     my_data_read = process_sp->ReadCStringFromMemory(location, (char*)buffer_sp->GetBytes(), size, my_error);
    937 
    938     if (error)
    939         *error = my_error;
    940     if (data_read)
    941         *data_read = my_data_read;
    942 
    943     if (my_error.Fail())
    944         return false;
    945 
    946     dest.Printf("%c%c",prefix_token,quote);
    947 
    948     if (my_data_read)
    949         dest.Printf("%s",(char*)buffer_sp->GetBytes());
    950 
    951     dest.Printf("%c",quote);
    952 
    953     return true;
    954 }
    955 
    956 bool
    957 lldb_private::formatters::NSStringSummaryProvider (ValueObject& valobj, Stream& stream)
    958 {
    959     ProcessSP process_sp = valobj.GetProcessSP();
    960     if (!process_sp)
    961         return false;
    962 
    963     ObjCLanguageRuntime* runtime = (ObjCLanguageRuntime*)process_sp->GetLanguageRuntime(lldb::eLanguageTypeObjC);
    964 
    965     if (!runtime)
    966         return false;
    967 
    968     ObjCLanguageRuntime::ClassDescriptorSP descriptor(runtime->GetClassDescriptor(valobj));
    969 
    970     if (!descriptor.get() || !descriptor->IsValid())
    971         return false;
    972 
    973     uint32_t ptr_size = process_sp->GetAddressByteSize();
    974 
    975     lldb::addr_t valobj_addr = valobj.GetValueAsUnsigned(0);
    976 
    977     if (!valobj_addr)
    978         return false;
    979 
    980     const char* class_name = descriptor->GetClassName().GetCString();
    981 
    982     if (!class_name || !*class_name)
    983         return false;
    984 
    985     uint64_t info_bits_location = valobj_addr + ptr_size;
    986     if (process_sp->GetByteOrder() != lldb::eByteOrderLittle)
    987         info_bits_location += 3;
    988 
    989     Error error;
    990 
    991     uint8_t info_bits = process_sp->ReadUnsignedIntegerFromMemory(info_bits_location, 1, 0, error);
    992     if (error.Fail())
    993         return false;
    994 
    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;
   1001 
   1002     size_t explicit_length = 0;
   1003     if (!has_null && has_explicit_length && !is_special)
   1004     {
   1005         lldb::addr_t explicit_length_offset = 2*ptr_size;
   1006         if (is_mutable and not is_inline)
   1007             explicit_length_offset = explicit_length_offset + ptr_size; //  notInlineMutable.length;
   1008         else if (is_inline)
   1009             explicit_length = explicit_length + 0; // inline1.length;
   1010         else if (not is_inline and not is_mutable)
   1011             explicit_length_offset = explicit_length_offset + ptr_size; // notInlineImmutable1.length;
   1012         else
   1013             explicit_length_offset = 0;
   1014 
   1015         if (explicit_length_offset)
   1016         {
   1017             explicit_length_offset = valobj_addr + explicit_length_offset;
   1018             explicit_length = process_sp->ReadUnsignedIntegerFromMemory(explicit_length_offset, 4, 0, error);
   1019         }
   1020     }
   1021 
   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"))
   1030     {
   1031         // not one of us - but tell me class name
   1032         stream.Printf("class name = %s",class_name);
   1033         return true;
   1034     }
   1035 
   1036     if (is_mutable)
   1037     {
   1038         uint64_t location = 2 * ptr_size + valobj_addr;
   1039         location = process_sp->ReadPointerFromMemory(location, error);
   1040         if (error.Fail())
   1041             return false;
   1042         if (has_explicit_length and is_unicode)
   1043         {
   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);
   1054         }
   1055         else
   1056             return ReadAsciiBufferAndDumpToStream(location+1,process_sp,stream, explicit_length);
   1057     }
   1058     else if (is_inline && has_explicit_length && !is_unicode && !is_special && !is_mutable)
   1059     {
   1060         uint64_t location = 3 * ptr_size + valobj_addr;
   1061         return ReadAsciiBufferAndDumpToStream(location,process_sp,stream,explicit_length);
   1062     }
   1063     else if (is_unicode)
   1064     {
   1065         uint64_t location = valobj_addr + 2*ptr_size;
   1066         if (is_inline)
   1067         {
   1068             if (!has_explicit_length)
   1069             {
   1070                 stream.Printf("found new combo");
   1071                 return true;
   1072             }
   1073             else
   1074                 location += ptr_size;
   1075         }
   1076         else
   1077         {
   1078             location = process_sp->ReadPointerFromMemory(location, error);
   1079             if (error.Fail())
   1080                 return false;
   1081         }
   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);
   1092     }
   1093     else if (is_special)
   1094     {
   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);
   1106     }
   1107     else if (is_inline)
   1108     {
   1109         uint64_t location = valobj_addr + 2*ptr_size;
   1110         if (!has_explicit_length)
   1111             location++;
   1112         return ReadAsciiBufferAndDumpToStream(location,process_sp,stream,explicit_length);
   1113     }
   1114     else
   1115     {
   1116         uint64_t location = valobj_addr + 2*ptr_size;
   1117         location = process_sp->ReadPointerFromMemory(location, error);
   1118         if (error.Fail())
   1119             return false;
   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);
   1123     }
   1124 
   1125     stream.Printf("class name = %s",class_name);
   1126     return true;
   1127 
   1128 }
   1129 
   1130 bool
   1131 lldb_private::formatters::NSAttributedStringSummaryProvider (ValueObject& valobj, Stream& stream)
   1132 {
   1133     TargetSP target_sp(valobj.GetTargetSP());
   1134     if (!target_sp)
   1135         return false;
   1136     uint32_t addr_size = target_sp->GetArchitecture().GetAddressByteSize();
   1137     uint64_t pointer_value = valobj.GetValueAsUnsigned(0);
   1138     if (!pointer_value)
   1139         return false;
   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));
   1144     if (!child_ptr_sp)
   1145         return false;
   1146     DataExtractor data;
   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);
   1150     if (child_sp)
   1151         return NSStringSummaryProvider(*child_sp, stream);
   1152     return false;
   1153 }
   1154 
   1155 bool
   1156 lldb_private::formatters::NSMutableAttributedStringSummaryProvider (ValueObject& valobj, Stream& stream)
   1157 {
   1158     return NSAttributedStringSummaryProvider(valobj, stream);
   1159 }
   1160 
   1161 bool
   1162 lldb_private::formatters::RuntimeSpecificDescriptionSummaryProvider (ValueObject& valobj, Stream& stream)
   1163 {
   1164     stream.Printf("%s",valobj.GetObjectDescription());
   1165     return true;
   1166 }
   1167 
   1168 bool
   1169 lldb_private::formatters::ObjCBOOLSummaryProvider (ValueObject& valobj, Stream& stream)
   1170 {
   1171     const uint32_t type_info = valobj.GetClangType().GetTypeInfo();
   1172 
   1173     ValueObjectSP real_guy_sp = valobj.GetSP();
   1174 
   1175     if (type_info & ClangASTType::eTypeIsPointer)
   1176     {
   1177         Error err;
   1178         real_guy_sp = valobj.Dereference(err);
   1179         if (err.Fail() || !real_guy_sp)
   1180             return false;
   1181     }
   1182     else if (type_info & ClangASTType::eTypeIsReference)
   1183     {
   1184         real_guy_sp =  valobj.GetChildAtIndex(0, true);
   1185         if (!real_guy_sp)
   1186             return false;
   1187     }
   1188     uint64_t value = real_guy_sp->GetValueAsUnsigned(0);
   1189     if (value == 0)
   1190     {
   1191         stream.Printf("NO");
   1192         return true;
   1193     }
   1194     stream.Printf("YES");
   1195     return true;
   1196 }
   1197 
   1198 template <bool is_sel_ptr>
   1199 bool
   1200 lldb_private::formatters::ObjCSELSummaryProvider (ValueObject& valobj, Stream& stream)
   1201 {
   1202     lldb::ValueObjectSP valobj_sp;
   1203 
   1204     ClangASTType charstar (valobj.GetClangType().GetBasicTypeFromAST(eBasicTypeChar).GetPointerType());
   1205 
   1206     if (!charstar)
   1207         return false;
   1208 
   1209     ExecutionContext exe_ctx(valobj.GetExecutionContextRef());
   1210 
   1211     if (is_sel_ptr)
   1212     {
   1213         lldb::addr_t data_address = valobj.GetValueAsUnsigned(LLDB_INVALID_ADDRESS);
   1214         if (data_address == LLDB_INVALID_ADDRESS)
   1215             return false;
   1216         valobj_sp = ValueObject::CreateValueObjectFromAddress("text", data_address, exe_ctx, charstar);
   1217     }
   1218     else
   1219     {
   1220         DataExtractor data;
   1221         valobj.GetData(data);
   1222         valobj_sp = ValueObject::CreateValueObjectFromData("text", data, exe_ctx, charstar);
   1223     }
   1224 
   1225     if (!valobj_sp)
   1226         return false;
   1227 
   1228     stream.Printf("%s",valobj_sp->GetSummaryAsCString());
   1229     return true;
   1230 }
   1231 
   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
   1234 time_t
   1235 lldb_private::formatters::GetOSXEpoch ()
   1236 {
   1237     static time_t epoch = 0;
   1238     if (!epoch)
   1239     {
   1240         tzset();
   1241         tm tm_epoch;
   1242         tm_epoch.tm_sec = 0;
   1243         tm_epoch.tm_hour = 0;
   1244         tm_epoch.tm_min = 0;
   1245         tm_epoch.tm_mon = 0;
   1246         tm_epoch.tm_mday = 1;
   1247         tm_epoch.tm_year = 2001-1900; // for some reason, we need to subtract 1900 from this field. not sure why.
   1248         tm_epoch.tm_isdst = -1;
   1249         tm_epoch.tm_gmtoff = 0;
   1250         tm_epoch.tm_zone = NULL;
   1251         epoch = timegm(&tm_epoch);
   1252     }
   1253     return epoch;
   1254 }
   1255 
   1256 size_t
   1257 lldb_private::formatters::ExtractIndexFromString (const char* item_name)
   1258 {
   1259     if (!item_name || !*item_name)
   1260         return UINT32_MAX;
   1261     if (*item_name != '[')
   1262         return UINT32_MAX;
   1263     item_name++;
   1264     char* endptr = NULL;
   1265     unsigned long int idx = ::strtoul(item_name, &endptr, 0);
   1266     if (idx == 0 && endptr == item_name)
   1267         return UINT32_MAX;
   1268     if (idx == ULONG_MAX)
   1269         return UINT32_MAX;
   1270     return idx;
   1271 }
   1272 
   1273 lldb_private::formatters::VectorIteratorSyntheticFrontEnd::VectorIteratorSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp,
   1274                                                                                             ConstString item_name) :
   1275 SyntheticChildrenFrontEnd(*valobj_sp.get()),
   1276 m_exe_ctx_ref(),
   1277 m_item_name(item_name),
   1278 m_item_sp()
   1279 {
   1280     if (valobj_sp)
   1281         Update();
   1282 }
   1283 
   1284 bool
   1285 lldb_private::formatters::VectorIteratorSyntheticFrontEnd::Update()
   1286 {
   1287     m_item_sp.reset();
   1288 
   1289     ValueObjectSP valobj_sp = m_backend.GetSP();
   1290     if (!valobj_sp)
   1291         return false;
   1292 
   1293     if (!valobj_sp)
   1294         return false;
   1295 
   1296     ValueObjectSP item_ptr(valobj_sp->GetChildMemberWithName(m_item_name,true));
   1297     if (!item_ptr)
   1298         return false;
   1299     if (item_ptr->GetValueAsUnsigned(0) == 0)
   1300         return false;
   1301     Error err;
   1302     m_exe_ctx_ref = valobj_sp->GetExecutionContextRef();
   1303     m_item_sp = ValueObject::CreateValueObjectFromAddress("item", item_ptr->GetValueAsUnsigned(0), m_exe_ctx_ref, item_ptr->GetClangType().GetPointeeType());
   1304     if (err.Fail())
   1305         m_item_sp.reset();
   1306     return false;
   1307 }
   1308 
   1309 size_t
   1310 lldb_private::formatters::VectorIteratorSyntheticFrontEnd::CalculateNumChildren ()
   1311 {
   1312     return 1;
   1313 }
   1314 
   1315 lldb::ValueObjectSP
   1316 lldb_private::formatters::VectorIteratorSyntheticFrontEnd::GetChildAtIndex (size_t idx)
   1317 {
   1318     if (idx == 0)
   1319         return m_item_sp;
   1320     return lldb::ValueObjectSP();
   1321 }
   1322 
   1323 bool
   1324 lldb_private::formatters::VectorIteratorSyntheticFrontEnd::MightHaveChildren ()
   1325 {
   1326     return true;
   1327 }
   1328 
   1329 size_t
   1330 lldb_private::formatters::VectorIteratorSyntheticFrontEnd::GetIndexOfChildWithName (const ConstString &name)
   1331 {
   1332     if (name == ConstString("item"))
   1333         return 0;
   1334     return UINT32_MAX;
   1335 }
   1336 
   1337 lldb_private::formatters::VectorIteratorSyntheticFrontEnd::~VectorIteratorSyntheticFrontEnd ()
   1338 {
   1339 }
   1340 
   1341 template bool
   1342 lldb_private::formatters::NSDataSummaryProvider<true> (ValueObject&, Stream&) ;
   1343 
   1344 template bool
   1345 lldb_private::formatters::NSDataSummaryProvider<false> (ValueObject&, Stream&) ;
   1346 
   1347 template bool
   1348 lldb_private::formatters::ObjCSELSummaryProvider<true> (ValueObject&, Stream&) ;
   1349 
   1350 template bool
   1351 lldb_private::formatters::ObjCSELSummaryProvider<false> (ValueObject&, Stream&) ;
   1352