1254721Semaste//===-- CXXFormatterFunctions.cpp---------------------------------*- C++ -*-===//
2254721Semaste//
3254721Semaste//                     The LLVM Compiler Infrastructure
4254721Semaste//
5254721Semaste// This file is distributed under the University of Illinois Open Source
6254721Semaste// License. See LICENSE.TXT for details.
7254721Semaste//
8254721Semaste//===----------------------------------------------------------------------===//
9254721Semaste
10254721Semaste#include "lldb/lldb-python.h"
11254721Semaste
12254721Semaste#include "lldb/DataFormatters/CXXFormatterFunctions.h"
13254721Semaste
14254721Semaste#include "llvm/Support/ConvertUTF.h"
15254721Semaste
16254721Semaste#include "lldb/Core/DataBufferHeap.h"
17254721Semaste#include "lldb/Core/Error.h"
18254721Semaste#include "lldb/Core/Stream.h"
19254721Semaste#include "lldb/Core/ValueObject.h"
20254721Semaste#include "lldb/Core/ValueObjectConstResult.h"
21254721Semaste#include "lldb/Host/Endian.h"
22254721Semaste#include "lldb/Symbol/ClangASTContext.h"
23254721Semaste#include "lldb/Target/ObjCLanguageRuntime.h"
24254721Semaste#include "lldb/Target/Target.h"
25254721Semaste
26254721Semaste#include <algorithm>
27254721Semaste
28254721Semasteusing namespace lldb;
29254721Semasteusing namespace lldb_private;
30254721Semasteusing namespace lldb_private::formatters;
31254721Semaste
32254721Semastebool
33254721Semastelldb_private::formatters::ExtractValueFromObjCExpression (ValueObject &valobj,
34254721Semaste                                                          const char* target_type,
35254721Semaste                                                          const char* selector,
36254721Semaste                                                          uint64_t &value)
37254721Semaste{
38254721Semaste    if (!target_type || !*target_type)
39254721Semaste        return false;
40254721Semaste    if (!selector || !*selector)
41254721Semaste        return false;
42254721Semaste    StreamString expr;
43254721Semaste    expr.Printf("(%s)[(id)0x%" PRIx64 " %s]",target_type,valobj.GetPointerValue(),selector);
44254721Semaste    ExecutionContext exe_ctx (valobj.GetExecutionContextRef());
45254721Semaste    lldb::ValueObjectSP result_sp;
46254721Semaste    Target* target = exe_ctx.GetTargetPtr();
47254721Semaste    StackFrame* stack_frame = exe_ctx.GetFramePtr();
48254721Semaste    if (!target || !stack_frame)
49254721Semaste        return false;
50254721Semaste
51254721Semaste    EvaluateExpressionOptions options;
52263367Semaste    options.SetCoerceToId(false);
53263367Semaste    options.SetUnwindOnError(true);
54263367Semaste    options.SetKeepInMemory(true);
55254721Semaste
56254721Semaste    target->EvaluateExpression(expr.GetData(),
57254721Semaste                               stack_frame,
58254721Semaste                               result_sp,
59254721Semaste                               options);
60254721Semaste    if (!result_sp)
61254721Semaste        return false;
62254721Semaste    value = result_sp->GetValueAsUnsigned(0);
63254721Semaste    return true;
64254721Semaste}
65254721Semaste
66254721Semastebool
67254721Semastelldb_private::formatters::ExtractSummaryFromObjCExpression (ValueObject &valobj,
68254721Semaste                                                            const char* target_type,
69254721Semaste                                                            const char* selector,
70254721Semaste                                                            Stream &stream)
71254721Semaste{
72254721Semaste    if (!target_type || !*target_type)
73254721Semaste        return false;
74254721Semaste    if (!selector || !*selector)
75254721Semaste        return false;
76254721Semaste    StreamString expr;
77254721Semaste    expr.Printf("(%s)[(id)0x%" PRIx64 " %s]",target_type,valobj.GetPointerValue(),selector);
78254721Semaste    ExecutionContext exe_ctx (valobj.GetExecutionContextRef());
79254721Semaste    lldb::ValueObjectSP result_sp;
80254721Semaste    Target* target = exe_ctx.GetTargetPtr();
81254721Semaste    StackFrame* stack_frame = exe_ctx.GetFramePtr();
82254721Semaste    if (!target || !stack_frame)
83254721Semaste        return false;
84254721Semaste
85254721Semaste    EvaluateExpressionOptions options;
86263367Semaste    options.SetCoerceToId(false);
87263367Semaste    options.SetUnwindOnError(true);
88263367Semaste    options.SetKeepInMemory(true);
89263367Semaste    options.SetUseDynamic(lldb::eDynamicCanRunTarget);
90254721Semaste
91254721Semaste    target->EvaluateExpression(expr.GetData(),
92254721Semaste                               stack_frame,
93254721Semaste                               result_sp,
94254721Semaste                               options);
95254721Semaste    if (!result_sp)
96254721Semaste        return false;
97254721Semaste    stream.Printf("%s",result_sp->GetSummaryAsCString());
98254721Semaste    return true;
99254721Semaste}
100254721Semaste
101254721Semastelldb::ValueObjectSP
102254721Semastelldb_private::formatters::CallSelectorOnObject (ValueObject &valobj,
103254721Semaste                                                const char* return_type,
104254721Semaste                                                const char* selector,
105254721Semaste                                                uint64_t index)
106254721Semaste{
107254721Semaste    lldb::ValueObjectSP valobj_sp;
108254721Semaste    if (!return_type || !*return_type)
109254721Semaste        return valobj_sp;
110254721Semaste    if (!selector || !*selector)
111254721Semaste        return valobj_sp;
112254721Semaste    StreamString expr_path_stream;
113254721Semaste    valobj.GetExpressionPath(expr_path_stream, false);
114254721Semaste    StreamString expr;
115254721Semaste    expr.Printf("(%s)[%s %s:%" PRId64 "]",return_type,expr_path_stream.GetData(),selector,index);
116254721Semaste    ExecutionContext exe_ctx (valobj.GetExecutionContextRef());
117254721Semaste    lldb::ValueObjectSP result_sp;
118254721Semaste    Target* target = exe_ctx.GetTargetPtr();
119254721Semaste    StackFrame* stack_frame = exe_ctx.GetFramePtr();
120254721Semaste    if (!target || !stack_frame)
121254721Semaste        return valobj_sp;
122254721Semaste
123254721Semaste    EvaluateExpressionOptions options;
124263367Semaste    options.SetCoerceToId(false);
125263367Semaste    options.SetUnwindOnError(true);
126263367Semaste    options.SetKeepInMemory(true);
127263367Semaste    options.SetUseDynamic(lldb::eDynamicCanRunTarget);
128254721Semaste
129254721Semaste    target->EvaluateExpression(expr.GetData(),
130254721Semaste                               stack_frame,
131254721Semaste                               valobj_sp,
132254721Semaste                               options);
133254721Semaste    return valobj_sp;
134254721Semaste}
135254721Semaste
136254721Semastelldb::ValueObjectSP
137254721Semastelldb_private::formatters::CallSelectorOnObject (ValueObject &valobj,
138254721Semaste                                                const char* return_type,
139254721Semaste                                                const char* selector,
140254721Semaste                                                const char* key)
141254721Semaste{
142254721Semaste    lldb::ValueObjectSP valobj_sp;
143254721Semaste    if (!return_type || !*return_type)
144254721Semaste        return valobj_sp;
145254721Semaste    if (!selector || !*selector)
146254721Semaste        return valobj_sp;
147254721Semaste    if (!key || !*key)
148254721Semaste        return valobj_sp;
149254721Semaste    StreamString expr_path_stream;
150254721Semaste    valobj.GetExpressionPath(expr_path_stream, false);
151254721Semaste    StreamString expr;
152254721Semaste    expr.Printf("(%s)[%s %s:%s]",return_type,expr_path_stream.GetData(),selector,key);
153254721Semaste    ExecutionContext exe_ctx (valobj.GetExecutionContextRef());
154254721Semaste    lldb::ValueObjectSP result_sp;
155254721Semaste    Target* target = exe_ctx.GetTargetPtr();
156254721Semaste    StackFrame* stack_frame = exe_ctx.GetFramePtr();
157254721Semaste    if (!target || !stack_frame)
158254721Semaste        return valobj_sp;
159254721Semaste
160254721Semaste    EvaluateExpressionOptions options;
161263367Semaste    options.SetCoerceToId(false);
162263367Semaste    options.SetUnwindOnError(true);
163263367Semaste    options.SetKeepInMemory(true);
164263367Semaste    options.SetUseDynamic(lldb::eDynamicCanRunTarget);
165254721Semaste
166254721Semaste    target->EvaluateExpression(expr.GetData(),
167254721Semaste                               stack_frame,
168254721Semaste                               valobj_sp,
169254721Semaste                               options);
170254721Semaste    return valobj_sp;
171254721Semaste}
172254721Semaste
173254721Semaste// use this call if you already have an LLDB-side buffer for the data
174254721Semastetemplate<typename SourceDataType>
175254721Semastestatic bool
176254721SemasteDumpUTFBufferToStream (ConversionResult (*ConvertFunction) (const SourceDataType**,
177254721Semaste                                                            const SourceDataType*,
178254721Semaste                                                            UTF8**,
179254721Semaste                                                            UTF8*,
180254721Semaste                                                            ConversionFlags),
181254721Semaste                       DataExtractor& data,
182254721Semaste                       Stream& stream,
183254721Semaste                       char prefix_token = '@',
184254721Semaste                       char quote = '"',
185254721Semaste                       uint32_t sourceSize = 0)
186254721Semaste{
187254721Semaste    if (prefix_token != 0)
188254721Semaste        stream.Printf("%c",prefix_token);
189254721Semaste    if (quote != 0)
190254721Semaste        stream.Printf("%c",quote);
191254721Semaste    if (data.GetByteSize() && data.GetDataStart() && data.GetDataEnd())
192254721Semaste    {
193254721Semaste        const int bufferSPSize = data.GetByteSize();
194254721Semaste        if (sourceSize == 0)
195254721Semaste        {
196254721Semaste            const int origin_encoding = 8*sizeof(SourceDataType);
197254721Semaste            sourceSize = bufferSPSize/(origin_encoding / 4);
198254721Semaste        }
199254721Semaste
200254721Semaste        SourceDataType *data_ptr = (SourceDataType*)data.GetDataStart();
201254721Semaste        SourceDataType *data_end_ptr = data_ptr + sourceSize;
202254721Semaste
203254721Semaste        while (data_ptr < data_end_ptr)
204254721Semaste        {
205254721Semaste            if (!*data_ptr)
206254721Semaste            {
207254721Semaste                data_end_ptr = data_ptr;
208254721Semaste                break;
209254721Semaste            }
210254721Semaste            data_ptr++;
211254721Semaste        }
212254721Semaste
213254721Semaste        data_ptr = (SourceDataType*)data.GetDataStart();
214254721Semaste
215254721Semaste        lldb::DataBufferSP utf8_data_buffer_sp;
216254721Semaste        UTF8* utf8_data_ptr = nullptr;
217254721Semaste        UTF8* utf8_data_end_ptr = nullptr;
218254721Semaste
219254721Semaste        if (ConvertFunction)
220254721Semaste        {
221254721Semaste            utf8_data_buffer_sp.reset(new DataBufferHeap(4*bufferSPSize,0));
222254721Semaste            utf8_data_ptr = (UTF8*)utf8_data_buffer_sp->GetBytes();
223254721Semaste            utf8_data_end_ptr = utf8_data_ptr + utf8_data_buffer_sp->GetByteSize();
224254721Semaste            ConvertFunction ( (const SourceDataType**)&data_ptr, data_end_ptr, &utf8_data_ptr, utf8_data_end_ptr, lenientConversion );
225254721Semaste            utf8_data_ptr = (UTF8*)utf8_data_buffer_sp->GetBytes(); // needed because the ConvertFunction will change the value of the data_ptr
226254721Semaste        }
227254721Semaste        else
228254721Semaste        {
229254721Semaste            // just copy the pointers - the cast is necessary to make the compiler happy
230254721Semaste            // but this should only happen if we are reading UTF8 data
231254721Semaste            utf8_data_ptr = (UTF8*)data_ptr;
232254721Semaste            utf8_data_end_ptr = (UTF8*)data_end_ptr;
233254721Semaste        }
234254721Semaste
235254721Semaste        // since we tend to accept partial data (and even partially malformed data)
236254721Semaste        // we might end up with no NULL terminator before the end_ptr
237254721Semaste        // hence we need to take a slower route and ensure we stay within boundaries
238254721Semaste        for (;utf8_data_ptr != utf8_data_end_ptr; utf8_data_ptr++)
239254721Semaste        {
240254721Semaste            if (!*utf8_data_ptr)
241254721Semaste                break;
242254721Semaste            stream.Printf("%c",*utf8_data_ptr);
243254721Semaste        }
244254721Semaste    }
245254721Semaste    if (quote != 0)
246254721Semaste        stream.Printf("%c",quote);
247254721Semaste    return true;
248254721Semaste}
249254721Semaste
250254721Semastetemplate<typename SourceDataType>
251254721Semasteclass ReadUTFBufferAndDumpToStreamOptions
252254721Semaste{
253254721Semastepublic:
254254721Semaste    typedef ConversionResult (*ConvertFunctionType) (const SourceDataType**,
255254721Semaste                                                     const SourceDataType*,
256254721Semaste                                                     UTF8**,
257254721Semaste                                                     UTF8*,
258254721Semaste                                                     ConversionFlags);
259254721Semaste
260254721Semaste    ReadUTFBufferAndDumpToStreamOptions () :
261254721Semaste    m_conversion_function(NULL),
262254721Semaste    m_location(0),
263254721Semaste    m_process_sp(),
264254721Semaste    m_stream(NULL),
265254721Semaste    m_prefix_token('@'),
266254721Semaste    m_quote('"'),
267254721Semaste    m_source_size(0),
268254721Semaste    m_needs_zero_termination(true)
269254721Semaste    {
270254721Semaste    }
271254721Semaste
272254721Semaste    ReadUTFBufferAndDumpToStreamOptions&
273254721Semaste    SetConversionFunction (ConvertFunctionType f)
274254721Semaste    {
275254721Semaste        m_conversion_function = f;
276254721Semaste        return *this;
277254721Semaste    }
278254721Semaste
279254721Semaste    ConvertFunctionType
280254721Semaste    GetConversionFunction () const
281254721Semaste    {
282254721Semaste        return m_conversion_function;
283254721Semaste    }
284254721Semaste
285254721Semaste    ReadUTFBufferAndDumpToStreamOptions&
286254721Semaste    SetLocation (uint64_t l)
287254721Semaste    {
288254721Semaste        m_location = l;
289254721Semaste        return *this;
290254721Semaste    }
291254721Semaste
292254721Semaste    uint64_t
293254721Semaste    GetLocation () const
294254721Semaste    {
295254721Semaste        return m_location;
296254721Semaste    }
297254721Semaste
298254721Semaste    ReadUTFBufferAndDumpToStreamOptions&
299254721Semaste    SetProcessSP (ProcessSP p)
300254721Semaste    {
301254721Semaste        m_process_sp = p;
302254721Semaste        return *this;
303254721Semaste    }
304254721Semaste
305254721Semaste    ProcessSP
306254721Semaste    GetProcessSP () const
307254721Semaste    {
308254721Semaste        return m_process_sp;
309254721Semaste    }
310254721Semaste
311254721Semaste    ReadUTFBufferAndDumpToStreamOptions&
312254721Semaste    SetStream (Stream* s)
313254721Semaste    {
314254721Semaste        m_stream = s;
315254721Semaste        return *this;
316254721Semaste    }
317254721Semaste
318254721Semaste    Stream*
319254721Semaste    GetStream () const
320254721Semaste    {
321254721Semaste        return m_stream;
322254721Semaste    }
323254721Semaste
324254721Semaste    ReadUTFBufferAndDumpToStreamOptions&
325254721Semaste    SetPrefixToken (char p)
326254721Semaste    {
327254721Semaste        m_prefix_token = p;
328254721Semaste        return *this;
329254721Semaste    }
330254721Semaste
331254721Semaste    char
332254721Semaste    GetPrefixToken () const
333254721Semaste    {
334254721Semaste        return m_prefix_token;
335254721Semaste    }
336254721Semaste
337254721Semaste    ReadUTFBufferAndDumpToStreamOptions&
338254721Semaste    SetQuote (char q)
339254721Semaste    {
340254721Semaste        m_quote = q;
341254721Semaste        return *this;
342254721Semaste    }
343254721Semaste
344254721Semaste    char
345254721Semaste    GetQuote () const
346254721Semaste    {
347254721Semaste        return m_quote;
348254721Semaste    }
349254721Semaste
350254721Semaste    ReadUTFBufferAndDumpToStreamOptions&
351254721Semaste    SetSourceSize (uint32_t s)
352254721Semaste    {
353254721Semaste        m_source_size = s;
354254721Semaste        return *this;
355254721Semaste    }
356254721Semaste
357254721Semaste    uint32_t
358254721Semaste    GetSourceSize () const
359254721Semaste    {
360254721Semaste        return m_source_size;
361254721Semaste    }
362254721Semaste
363254721Semaste    ReadUTFBufferAndDumpToStreamOptions&
364254721Semaste    SetNeedsZeroTermination (bool z)
365254721Semaste    {
366254721Semaste        m_needs_zero_termination = z;
367254721Semaste        return *this;
368254721Semaste    }
369254721Semaste
370254721Semaste    bool
371254721Semaste    GetNeedsZeroTermination () const
372254721Semaste    {
373254721Semaste        return m_needs_zero_termination;
374254721Semaste    }
375254721Semaste
376254721Semasteprivate:
377254721Semaste    ConvertFunctionType m_conversion_function;
378254721Semaste    uint64_t m_location;
379254721Semaste    ProcessSP m_process_sp;
380254721Semaste    Stream* m_stream;
381254721Semaste    char m_prefix_token;
382254721Semaste    char m_quote;
383254721Semaste    uint32_t m_source_size;
384254721Semaste    bool m_needs_zero_termination;
385254721Semaste};
386254721Semaste
387254721Semastetemplate<typename SourceDataType>
388254721Semastestatic bool
389254721SemasteReadUTFBufferAndDumpToStream (const ReadUTFBufferAndDumpToStreamOptions<SourceDataType>& options)
390254721Semaste{
391254721Semaste    if (options.GetLocation() == 0 || options.GetLocation() == LLDB_INVALID_ADDRESS)
392254721Semaste        return false;
393254721Semaste
394254721Semaste    ProcessSP process_sp(options.GetProcessSP());
395254721Semaste
396254721Semaste    if (!process_sp)
397254721Semaste        return false;
398254721Semaste
399254721Semaste    const int type_width = sizeof(SourceDataType);
400254721Semaste    const int origin_encoding = 8 * type_width ;
401254721Semaste    if (origin_encoding != 8 && origin_encoding != 16 && origin_encoding != 32)
402254721Semaste        return false;
403254721Semaste    // if not UTF8, I need a conversion function to return proper UTF8
404254721Semaste    if (origin_encoding != 8 && !options.GetConversionFunction())
405254721Semaste        return false;
406254721Semaste
407254721Semaste    if (!options.GetStream())
408254721Semaste        return false;
409254721Semaste
410254721Semaste    uint32_t sourceSize = options.GetSourceSize();
411254721Semaste    bool needs_zero_terminator = options.GetNeedsZeroTermination();
412254721Semaste
413254721Semaste    if (!sourceSize)
414254721Semaste    {
415254721Semaste        sourceSize = process_sp->GetTarget().GetMaximumSizeOfStringSummary();
416254721Semaste        needs_zero_terminator = true;
417254721Semaste    }
418254721Semaste    else
419254721Semaste        sourceSize = std::min(sourceSize,process_sp->GetTarget().GetMaximumSizeOfStringSummary());
420254721Semaste
421254721Semaste    const int bufferSPSize = sourceSize * type_width;
422254721Semaste
423254721Semaste    lldb::DataBufferSP buffer_sp(new DataBufferHeap(bufferSPSize,0));
424254721Semaste
425254721Semaste    if (!buffer_sp->GetBytes())
426254721Semaste        return false;
427254721Semaste
428254721Semaste    Error error;
429254721Semaste    char *buffer = reinterpret_cast<char *>(buffer_sp->GetBytes());
430254721Semaste
431254721Semaste    size_t data_read = 0;
432254721Semaste    if (needs_zero_terminator)
433254721Semaste        data_read = process_sp->ReadStringFromMemory(options.GetLocation(), buffer, bufferSPSize, error, type_width);
434254721Semaste    else
435254721Semaste        data_read = process_sp->ReadMemoryFromInferior(options.GetLocation(), (char*)buffer_sp->GetBytes(), bufferSPSize, error);
436254721Semaste
437254721Semaste    if (error.Fail() || data_read == 0)
438254721Semaste    {
439254721Semaste        options.GetStream()->Printf("unable to read data");
440254721Semaste        return true;
441254721Semaste    }
442254721Semaste
443254721Semaste    DataExtractor data(buffer_sp, process_sp->GetByteOrder(), process_sp->GetAddressByteSize());
444254721Semaste
445254721Semaste    return DumpUTFBufferToStream(options.GetConversionFunction(), data, *options.GetStream(), options.GetPrefixToken(), options.GetQuote(), sourceSize);
446254721Semaste}
447254721Semaste
448254721Semastebool
449254721Semastelldb_private::formatters::Char16StringSummaryProvider (ValueObject& valobj, Stream& stream)
450254721Semaste{
451254721Semaste    ProcessSP process_sp = valobj.GetProcessSP();
452254721Semaste    if (!process_sp)
453254721Semaste        return false;
454254721Semaste
455254721Semaste    lldb::addr_t valobj_addr = valobj.GetValueAsUnsigned(0);
456254721Semaste
457254721Semaste    if (!valobj_addr)
458254721Semaste        return false;
459254721Semaste
460254721Semaste    ReadUTFBufferAndDumpToStreamOptions<UTF16> options;
461254721Semaste    options.SetLocation(valobj_addr);
462254721Semaste    options.SetConversionFunction(ConvertUTF16toUTF8);
463254721Semaste    options.SetProcessSP(process_sp);
464254721Semaste    options.SetStream(&stream);
465254721Semaste    options.SetPrefixToken('u');
466254721Semaste
467254721Semaste    if (!ReadUTFBufferAndDumpToStream(options))
468254721Semaste    {
469254721Semaste        stream.Printf("Summary Unavailable");
470254721Semaste        return true;
471254721Semaste    }
472254721Semaste
473254721Semaste    return true;
474254721Semaste}
475254721Semaste
476254721Semastebool
477254721Semastelldb_private::formatters::Char32StringSummaryProvider (ValueObject& valobj, Stream& stream)
478254721Semaste{
479254721Semaste    ProcessSP process_sp = valobj.GetProcessSP();
480254721Semaste    if (!process_sp)
481254721Semaste        return false;
482254721Semaste
483254721Semaste    lldb::addr_t valobj_addr = valobj.GetValueAsUnsigned(0);
484254721Semaste
485254721Semaste    if (!valobj_addr)
486254721Semaste        return false;
487254721Semaste
488254721Semaste    ReadUTFBufferAndDumpToStreamOptions<UTF32> options;
489254721Semaste    options.SetLocation(valobj_addr);
490254721Semaste    options.SetConversionFunction(ConvertUTF32toUTF8);
491254721Semaste    options.SetProcessSP(process_sp);
492254721Semaste    options.SetStream(&stream);
493254721Semaste    options.SetPrefixToken('U');
494254721Semaste
495254721Semaste    if (!ReadUTFBufferAndDumpToStream(options))
496254721Semaste    {
497254721Semaste        stream.Printf("Summary Unavailable");
498254721Semaste        return true;
499254721Semaste    }
500254721Semaste
501254721Semaste    return true;
502254721Semaste}
503254721Semaste
504254721Semastebool
505254721Semastelldb_private::formatters::WCharStringSummaryProvider (ValueObject& valobj, Stream& stream)
506254721Semaste{
507254721Semaste    ProcessSP process_sp = valobj.GetProcessSP();
508254721Semaste    if (!process_sp)
509254721Semaste        return false;
510254721Semaste
511254721Semaste    lldb::addr_t data_addr = 0;
512254721Semaste
513254721Semaste    if (valobj.IsPointerType())
514254721Semaste        data_addr = valobj.GetValueAsUnsigned(0);
515254721Semaste    else if (valobj.IsArrayType())
516254721Semaste        data_addr = valobj.GetAddressOf();
517254721Semaste
518254721Semaste    if (data_addr == 0 || data_addr == LLDB_INVALID_ADDRESS)
519254721Semaste        return false;
520254721Semaste
521254721Semaste    clang::ASTContext* ast = valobj.GetClangType().GetASTContext();
522254721Semaste
523254721Semaste    if (!ast)
524254721Semaste        return false;
525254721Semaste
526254721Semaste    ClangASTType wchar_clang_type = ClangASTContext::GetBasicType(ast, lldb::eBasicTypeWChar);
527254721Semaste    const uint32_t wchar_size = wchar_clang_type.GetBitSize();
528254721Semaste
529254721Semaste    switch (wchar_size)
530254721Semaste    {
531254721Semaste        case 8:
532254721Semaste        {
533254721Semaste            // utf 8
534254721Semaste
535254721Semaste            ReadUTFBufferAndDumpToStreamOptions<UTF8> options;
536254721Semaste            options.SetLocation(data_addr);
537254721Semaste            options.SetConversionFunction(nullptr);
538254721Semaste            options.SetProcessSP(process_sp);
539254721Semaste            options.SetStream(&stream);
540254721Semaste            options.SetPrefixToken('L');
541254721Semaste
542254721Semaste            return ReadUTFBufferAndDumpToStream(options);
543254721Semaste        }
544254721Semaste        case 16:
545254721Semaste        {
546254721Semaste            // utf 16
547254721Semaste            ReadUTFBufferAndDumpToStreamOptions<UTF16> options;
548254721Semaste            options.SetLocation(data_addr);
549254721Semaste            options.SetConversionFunction(ConvertUTF16toUTF8);
550254721Semaste            options.SetProcessSP(process_sp);
551254721Semaste            options.SetStream(&stream);
552254721Semaste            options.SetPrefixToken('L');
553254721Semaste
554254721Semaste            return ReadUTFBufferAndDumpToStream(options);
555254721Semaste        }
556254721Semaste        case 32:
557254721Semaste        {
558254721Semaste            // utf 32
559254721Semaste            ReadUTFBufferAndDumpToStreamOptions<UTF32> options;
560254721Semaste            options.SetLocation(data_addr);
561254721Semaste            options.SetConversionFunction(ConvertUTF32toUTF8);
562254721Semaste            options.SetProcessSP(process_sp);
563254721Semaste            options.SetStream(&stream);
564254721Semaste            options.SetPrefixToken('L');
565254721Semaste
566254721Semaste            return ReadUTFBufferAndDumpToStream(options);
567254721Semaste        }
568254721Semaste        default:
569254721Semaste            stream.Printf("size for wchar_t is not valid");
570254721Semaste            return true;
571254721Semaste    }
572254721Semaste    return true;
573254721Semaste}
574254721Semaste
575254721Semastebool
576254721Semastelldb_private::formatters::Char16SummaryProvider (ValueObject& valobj, Stream& stream)
577254721Semaste{
578254721Semaste    DataExtractor data;
579254721Semaste    valobj.GetData(data);
580254721Semaste
581254721Semaste    std::string value;
582254721Semaste    valobj.GetValueAsCString(lldb::eFormatUnicode16, value);
583254721Semaste    if (!value.empty())
584254721Semaste        stream.Printf("%s ", value.c_str());
585254721Semaste
586254721Semaste    return DumpUTFBufferToStream<UTF16>(ConvertUTF16toUTF8,data,stream, 'u','\'',1);
587254721Semaste}
588254721Semaste
589254721Semastebool
590254721Semastelldb_private::formatters::Char32SummaryProvider (ValueObject& valobj, Stream& stream)
591254721Semaste{
592254721Semaste    DataExtractor data;
593254721Semaste    valobj.GetData(data);
594254721Semaste
595254721Semaste    std::string value;
596254721Semaste    valobj.GetValueAsCString(lldb::eFormatUnicode32, value);
597254721Semaste    if (!value.empty())
598254721Semaste        stream.Printf("%s ", value.c_str());
599254721Semaste
600254721Semaste    return DumpUTFBufferToStream<UTF32>(ConvertUTF32toUTF8,data,stream, 'U','\'',1);
601254721Semaste}
602254721Semaste
603254721Semastebool
604254721Semastelldb_private::formatters::WCharSummaryProvider (ValueObject& valobj, Stream& stream)
605254721Semaste{
606254721Semaste    DataExtractor data;
607254721Semaste    valobj.GetData(data);
608254721Semaste
609254721Semaste    clang::ASTContext* ast = valobj.GetClangType().GetASTContext();
610254721Semaste
611254721Semaste    if (!ast)
612254721Semaste        return false;
613254721Semaste
614254721Semaste    ClangASTType wchar_clang_type = ClangASTContext::GetBasicType(ast, lldb::eBasicTypeWChar);
615254721Semaste    const uint32_t wchar_size = wchar_clang_type.GetBitSize();
616254721Semaste    std::string value;
617254721Semaste
618254721Semaste    switch (wchar_size)
619254721Semaste    {
620254721Semaste        case 8:
621254721Semaste            // utf 8
622254721Semaste            valobj.GetValueAsCString(lldb::eFormatChar, value);
623254721Semaste            if (!value.empty())
624254721Semaste                stream.Printf("%s ", value.c_str());
625254721Semaste            return DumpUTFBufferToStream<UTF8>(nullptr,
626254721Semaste                                               data,
627254721Semaste                                               stream,
628254721Semaste                                               'L',
629254721Semaste                                               '\'',
630254721Semaste                                               1);
631254721Semaste        case 16:
632254721Semaste            // utf 16
633254721Semaste            valobj.GetValueAsCString(lldb::eFormatUnicode16, value);
634254721Semaste            if (!value.empty())
635254721Semaste                stream.Printf("%s ", value.c_str());
636254721Semaste            return DumpUTFBufferToStream<UTF16>(ConvertUTF16toUTF8,
637254721Semaste                                                data,
638254721Semaste                                                stream,
639254721Semaste                                                'L',
640254721Semaste                                                '\'',
641254721Semaste                                                1);
642254721Semaste        case 32:
643254721Semaste            // utf 32
644254721Semaste            valobj.GetValueAsCString(lldb::eFormatUnicode32, value);
645254721Semaste            if (!value.empty())
646254721Semaste                stream.Printf("%s ", value.c_str());
647254721Semaste            return DumpUTFBufferToStream<UTF32>(ConvertUTF32toUTF8,
648254721Semaste                                                data,
649254721Semaste                                                stream,
650254721Semaste                                                'L',
651254721Semaste                                                '\'',
652254721Semaste                                                1);
653254721Semaste        default:
654254721Semaste            stream.Printf("size for wchar_t is not valid");
655254721Semaste            return true;
656254721Semaste    }
657254721Semaste    return true;
658254721Semaste}
659254721Semaste
660254721Semaste// the field layout in a libc++ string (cap, side, data or data, size, cap)
661254721Semasteenum LibcxxStringLayoutMode
662254721Semaste{
663254721Semaste    eLibcxxStringLayoutModeCSD = 0,
664254721Semaste    eLibcxxStringLayoutModeDSC = 1,
665254721Semaste    eLibcxxStringLayoutModeInvalid = 0xffff
666254721Semaste};
667254721Semaste
668254721Semaste// this function abstracts away the layout and mode details of a libc++ string
669254721Semaste// and returns the address of the data and the size ready for callers to consume
670254721Semastestatic bool
671254721SemasteExtractLibcxxStringInfo (ValueObject& valobj,
672254721Semaste                         ValueObjectSP &location_sp,
673254721Semaste                         uint64_t& size)
674254721Semaste{
675254721Semaste    ValueObjectSP D(valobj.GetChildAtIndexPath({0,0,0,0}));
676254721Semaste    if (!D)
677254721Semaste        return false;
678254721Semaste
679254721Semaste    ValueObjectSP layout_decider(D->GetChildAtIndexPath({0,0}));
680254721Semaste
681254721Semaste    // this child should exist
682254721Semaste    if (!layout_decider)
683254721Semaste        return false;
684254721Semaste
685254721Semaste    ConstString g_data_name("__data_");
686254721Semaste    ConstString g_size_name("__size_");
687254721Semaste    bool short_mode = false; // this means the string is in short-mode and the data is stored inline
688254721Semaste    LibcxxStringLayoutMode layout = (layout_decider->GetName() == g_data_name) ? eLibcxxStringLayoutModeDSC : eLibcxxStringLayoutModeCSD;
689254721Semaste    uint64_t size_mode_value = 0;
690254721Semaste
691254721Semaste    if (layout == eLibcxxStringLayoutModeDSC)
692254721Semaste    {
693254721Semaste        ValueObjectSP size_mode(D->GetChildAtIndexPath({1,1,0}));
694254721Semaste        if (!size_mode)
695254721Semaste            return false;
696254721Semaste
697254721Semaste        if (size_mode->GetName() != g_size_name)
698254721Semaste        {
699254721Semaste            // we are hitting the padding structure, move along
700254721Semaste            size_mode = D->GetChildAtIndexPath({1,1,1});
701254721Semaste            if (!size_mode)
702254721Semaste                return false;
703254721Semaste        }
704254721Semaste
705254721Semaste        size_mode_value = (size_mode->GetValueAsUnsigned(0));
706254721Semaste        short_mode = ((size_mode_value & 0x80) == 0);
707254721Semaste    }
708254721Semaste    else
709254721Semaste    {
710254721Semaste        ValueObjectSP size_mode(D->GetChildAtIndexPath({1,0,0}));
711254721Semaste        if (!size_mode)
712254721Semaste            return false;
713254721Semaste
714254721Semaste        size_mode_value = (size_mode->GetValueAsUnsigned(0));
715254721Semaste        short_mode = ((size_mode_value & 1) == 0);
716254721Semaste    }
717254721Semaste
718254721Semaste    if (short_mode)
719254721Semaste    {
720254721Semaste        ValueObjectSP s(D->GetChildAtIndex(1, true));
721254721Semaste        if (!s)
722254721Semaste            return false;
723254721Semaste        location_sp = s->GetChildAtIndex((layout == eLibcxxStringLayoutModeDSC) ? 0 : 1, true);
724254721Semaste        size = (layout == eLibcxxStringLayoutModeDSC) ? size_mode_value : ((size_mode_value >> 1) % 256);
725254721Semaste        return (location_sp.get() != nullptr);
726254721Semaste    }
727254721Semaste    else
728254721Semaste    {
729254721Semaste        ValueObjectSP l(D->GetChildAtIndex(0, true));
730254721Semaste        if (!l)
731254721Semaste            return false;
732254721Semaste        // we can use the layout_decider object as the data pointer
733254721Semaste        location_sp = (layout == eLibcxxStringLayoutModeDSC) ? layout_decider : l->GetChildAtIndex(2, true);
734254721Semaste        ValueObjectSP size_vo(l->GetChildAtIndex(1, true));
735254721Semaste        if (!size_vo || !location_sp)
736254721Semaste            return false;
737254721Semaste        size = size_vo->GetValueAsUnsigned(0);
738254721Semaste        return true;
739254721Semaste    }
740254721Semaste}
741254721Semaste
742254721Semastebool
743254721Semastelldb_private::formatters::LibcxxWStringSummaryProvider (ValueObject& valobj, Stream& stream)
744254721Semaste{
745254721Semaste    uint64_t size = 0;
746254721Semaste    ValueObjectSP location_sp((ValueObject*)nullptr);
747254721Semaste    if (!ExtractLibcxxStringInfo(valobj, location_sp, size))
748254721Semaste        return false;
749254721Semaste    if (size == 0)
750254721Semaste    {
751254721Semaste        stream.Printf("L\"\"");
752254721Semaste        return true;
753254721Semaste    }
754254721Semaste    if (!location_sp)
755254721Semaste        return false;
756254721Semaste    return WCharStringSummaryProvider(*location_sp.get(), stream);
757254721Semaste}
758254721Semaste
759254721Semastebool
760254721Semastelldb_private::formatters::LibcxxStringSummaryProvider (ValueObject& valobj, Stream& stream)
761254721Semaste{
762254721Semaste    uint64_t size = 0;
763254721Semaste    ValueObjectSP location_sp((ValueObject*)nullptr);
764254721Semaste    if (!ExtractLibcxxStringInfo(valobj, location_sp, size))
765254721Semaste        return false;
766254721Semaste    if (size == 0)
767254721Semaste    {
768254721Semaste        stream.Printf("\"\"");
769254721Semaste        return true;
770254721Semaste    }
771254721Semaste    if (!location_sp)
772254721Semaste        return false;
773254721Semaste    Error error;
774254721Semaste    if (location_sp->ReadPointedString(stream,
775254721Semaste                                       error,
776254721Semaste                                       0, // max length is decided by the settings
777254721Semaste                                       false) == 0) // do not honor array (terminates on first 0 byte even for a char[])
778254721Semaste        stream.Printf("\"\""); // if nothing was read, print an empty string
779254721Semaste    return error.Success();
780254721Semaste}
781254721Semaste
782254721Semastebool
783254721Semastelldb_private::formatters::ObjCClassSummaryProvider (ValueObject& valobj, Stream& stream)
784254721Semaste{
785254721Semaste    ProcessSP process_sp = valobj.GetProcessSP();
786254721Semaste    if (!process_sp)
787254721Semaste        return false;
788254721Semaste
789254721Semaste    ObjCLanguageRuntime* runtime = (ObjCLanguageRuntime*)process_sp->GetLanguageRuntime(lldb::eLanguageTypeObjC);
790254721Semaste
791254721Semaste    if (!runtime)
792254721Semaste        return false;
793254721Semaste
794254721Semaste    ObjCLanguageRuntime::ClassDescriptorSP descriptor(runtime->GetClassDescriptorFromISA(valobj.GetValueAsUnsigned(0)));
795254721Semaste
796254721Semaste    if (!descriptor.get() || !descriptor->IsValid())
797254721Semaste        return false;
798254721Semaste
799254721Semaste    const char* class_name = descriptor->GetClassName().GetCString();
800254721Semaste
801254721Semaste    if (!class_name || !*class_name)
802254721Semaste        return false;
803254721Semaste
804254721Semaste    stream.Printf("%s",class_name);
805254721Semaste    return true;
806254721Semaste}
807254721Semaste
808254721Semasteclass ObjCClassSyntheticChildrenFrontEnd : public SyntheticChildrenFrontEnd
809254721Semaste{
810254721Semastepublic:
811254721Semaste    ObjCClassSyntheticChildrenFrontEnd (lldb::ValueObjectSP valobj_sp) :
812254721Semaste    SyntheticChildrenFrontEnd(*valobj_sp.get())
813254721Semaste    {
814254721Semaste    }
815254721Semaste
816254721Semaste    virtual size_t
817254721Semaste    CalculateNumChildren ()
818254721Semaste    {
819254721Semaste        return 0;
820254721Semaste    }
821254721Semaste
822254721Semaste    virtual lldb::ValueObjectSP
823254721Semaste    GetChildAtIndex (size_t idx)
824254721Semaste    {
825254721Semaste        return lldb::ValueObjectSP();
826254721Semaste    }
827254721Semaste
828254721Semaste    virtual bool
829254721Semaste    Update()
830254721Semaste    {
831254721Semaste        return false;
832254721Semaste    }
833254721Semaste
834254721Semaste    virtual bool
835254721Semaste    MightHaveChildren ()
836254721Semaste    {
837254721Semaste        return false;
838254721Semaste    }
839254721Semaste
840254721Semaste    virtual size_t
841254721Semaste    GetIndexOfChildWithName (const ConstString &name)
842254721Semaste    {
843254721Semaste        return UINT32_MAX;
844254721Semaste    }
845254721Semaste
846254721Semaste    virtual
847254721Semaste    ~ObjCClassSyntheticChildrenFrontEnd ()
848254721Semaste    {
849254721Semaste    }
850254721Semaste};
851254721Semaste
852254721SemasteSyntheticChildrenFrontEnd*
853254721Semastelldb_private::formatters::ObjCClassSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP valobj_sp)
854254721Semaste{
855254721Semaste    return new ObjCClassSyntheticChildrenFrontEnd(valobj_sp);
856254721Semaste}
857254721Semaste
858254721Semastetemplate<bool needs_at>
859254721Semastebool
860254721Semastelldb_private::formatters::NSDataSummaryProvider (ValueObject& valobj, Stream& stream)
861254721Semaste{
862254721Semaste    ProcessSP process_sp = valobj.GetProcessSP();
863254721Semaste    if (!process_sp)
864254721Semaste        return false;
865254721Semaste
866254721Semaste    ObjCLanguageRuntime* runtime = (ObjCLanguageRuntime*)process_sp->GetLanguageRuntime(lldb::eLanguageTypeObjC);
867254721Semaste
868254721Semaste    if (!runtime)
869254721Semaste        return false;
870254721Semaste
871254721Semaste    ObjCLanguageRuntime::ClassDescriptorSP descriptor(runtime->GetClassDescriptor(valobj));
872254721Semaste
873254721Semaste    if (!descriptor.get() || !descriptor->IsValid())
874254721Semaste        return false;
875254721Semaste
876254721Semaste    bool is_64bit = (process_sp->GetAddressByteSize() == 8);
877254721Semaste    lldb::addr_t valobj_addr = valobj.GetValueAsUnsigned(0);
878254721Semaste
879254721Semaste    if (!valobj_addr)
880254721Semaste        return false;
881254721Semaste
882254721Semaste    uint64_t value = 0;
883254721Semaste
884254721Semaste    const char* class_name = descriptor->GetClassName().GetCString();
885254721Semaste
886254721Semaste    if (!class_name || !*class_name)
887254721Semaste        return false;
888254721Semaste
889254721Semaste    if (!strcmp(class_name,"NSConcreteData") ||
890254721Semaste        !strcmp(class_name,"NSConcreteMutableData") ||
891254721Semaste        !strcmp(class_name,"__NSCFData"))
892254721Semaste    {
893254721Semaste        uint32_t offset = (is_64bit ? 16 : 8);
894254721Semaste        Error error;
895254721Semaste        value = process_sp->ReadUnsignedIntegerFromMemory(valobj_addr + offset, is_64bit ? 8 : 4, 0, error);
896254721Semaste        if (error.Fail())
897254721Semaste            return false;
898254721Semaste    }
899254721Semaste    else
900254721Semaste    {
901254721Semaste        if (!ExtractValueFromObjCExpression(valobj, "int", "length", value))
902254721Semaste            return false;
903254721Semaste    }
904254721Semaste
905254721Semaste    stream.Printf("%s%" PRIu64 " byte%s%s",
906254721Semaste                  (needs_at ? "@\"" : ""),
907254721Semaste                  value,
908254721Semaste                  (value != 1 ? "s" : ""),
909254721Semaste                  (needs_at ? "\"" : ""));
910254721Semaste
911254721Semaste    return true;
912254721Semaste}
913254721Semaste
914254721Semastestatic bool
915254721SemasteReadAsciiBufferAndDumpToStream (lldb::addr_t location,
916254721Semaste                                lldb::ProcessSP& process_sp,
917254721Semaste                                Stream& dest,
918254721Semaste                                uint32_t size = 0,
919254721Semaste                                Error* error = NULL,
920254721Semaste                                size_t *data_read = NULL,
921254721Semaste                                char prefix_token = '@',
922254721Semaste                                char quote = '"')
923254721Semaste{
924254721Semaste    Error my_error;
925254721Semaste    size_t my_data_read;
926254721Semaste    if (!process_sp || location == 0)
927254721Semaste        return false;
928254721Semaste
929254721Semaste    if (!size)
930254721Semaste        size = process_sp->GetTarget().GetMaximumSizeOfStringSummary();
931254721Semaste    else
932254721Semaste        size = std::min(size,process_sp->GetTarget().GetMaximumSizeOfStringSummary());
933254721Semaste
934254721Semaste    lldb::DataBufferSP buffer_sp(new DataBufferHeap(size,0));
935254721Semaste
936254721Semaste    my_data_read = process_sp->ReadCStringFromMemory(location, (char*)buffer_sp->GetBytes(), size, my_error);
937254721Semaste
938254721Semaste    if (error)
939254721Semaste        *error = my_error;
940254721Semaste    if (data_read)
941254721Semaste        *data_read = my_data_read;
942254721Semaste
943254721Semaste    if (my_error.Fail())
944254721Semaste        return false;
945254721Semaste
946254721Semaste    dest.Printf("%c%c",prefix_token,quote);
947254721Semaste
948254721Semaste    if (my_data_read)
949254721Semaste        dest.Printf("%s",(char*)buffer_sp->GetBytes());
950254721Semaste
951254721Semaste    dest.Printf("%c",quote);
952254721Semaste
953254721Semaste    return true;
954254721Semaste}
955254721Semaste
956254721Semastebool
957254721Semastelldb_private::formatters::NSStringSummaryProvider (ValueObject& valobj, Stream& stream)
958254721Semaste{
959254721Semaste    ProcessSP process_sp = valobj.GetProcessSP();
960254721Semaste    if (!process_sp)
961254721Semaste        return false;
962254721Semaste
963254721Semaste    ObjCLanguageRuntime* runtime = (ObjCLanguageRuntime*)process_sp->GetLanguageRuntime(lldb::eLanguageTypeObjC);
964254721Semaste
965254721Semaste    if (!runtime)
966254721Semaste        return false;
967254721Semaste
968254721Semaste    ObjCLanguageRuntime::ClassDescriptorSP descriptor(runtime->GetClassDescriptor(valobj));
969254721Semaste
970254721Semaste    if (!descriptor.get() || !descriptor->IsValid())
971254721Semaste        return false;
972254721Semaste
973254721Semaste    uint32_t ptr_size = process_sp->GetAddressByteSize();
974254721Semaste
975254721Semaste    lldb::addr_t valobj_addr = valobj.GetValueAsUnsigned(0);
976254721Semaste
977254721Semaste    if (!valobj_addr)
978254721Semaste        return false;
979254721Semaste
980254721Semaste    const char* class_name = descriptor->GetClassName().GetCString();
981254721Semaste
982254721Semaste    if (!class_name || !*class_name)
983254721Semaste        return false;
984254721Semaste
985254721Semaste    uint64_t info_bits_location = valobj_addr + ptr_size;
986254721Semaste    if (process_sp->GetByteOrder() != lldb::eByteOrderLittle)
987254721Semaste        info_bits_location += 3;
988254721Semaste
989254721Semaste    Error error;
990254721Semaste
991254721Semaste    uint8_t info_bits = process_sp->ReadUnsignedIntegerFromMemory(info_bits_location, 1, 0, error);
992254721Semaste    if (error.Fail())
993254721Semaste        return false;
994254721Semaste
995254721Semaste    bool is_mutable = (info_bits & 1) == 1;
996254721Semaste    bool is_inline = (info_bits & 0x60) == 0;
997254721Semaste    bool has_explicit_length = (info_bits & (1 | 4)) != 4;
998254721Semaste    bool is_unicode = (info_bits & 0x10) == 0x10;
999254721Semaste    bool is_special = strcmp(class_name,"NSPathStore2") == 0;
1000254721Semaste    bool has_null = (info_bits & 8) == 8;
1001254721Semaste
1002254721Semaste    size_t explicit_length = 0;
1003254721Semaste    if (!has_null && has_explicit_length && !is_special)
1004254721Semaste    {
1005254721Semaste        lldb::addr_t explicit_length_offset = 2*ptr_size;
1006263363Semaste        if (is_mutable && !is_inline)
1007254721Semaste            explicit_length_offset = explicit_length_offset + ptr_size; //  notInlineMutable.length;
1008254721Semaste        else if (is_inline)
1009254721Semaste            explicit_length = explicit_length + 0; // inline1.length;
1010263363Semaste        else if (!is_inline && !is_mutable)
1011254721Semaste            explicit_length_offset = explicit_length_offset + ptr_size; // notInlineImmutable1.length;
1012254721Semaste        else
1013254721Semaste            explicit_length_offset = 0;
1014254721Semaste
1015254721Semaste        if (explicit_length_offset)
1016254721Semaste        {
1017254721Semaste            explicit_length_offset = valobj_addr + explicit_length_offset;
1018254721Semaste            explicit_length = process_sp->ReadUnsignedIntegerFromMemory(explicit_length_offset, 4, 0, error);
1019254721Semaste        }
1020254721Semaste    }
1021254721Semaste
1022254721Semaste    if (strcmp(class_name,"NSString") &&
1023254721Semaste        strcmp(class_name,"CFStringRef") &&
1024254721Semaste        strcmp(class_name,"CFMutableStringRef") &&
1025254721Semaste        strcmp(class_name,"__NSCFConstantString") &&
1026254721Semaste        strcmp(class_name,"__NSCFString") &&
1027254721Semaste        strcmp(class_name,"NSCFConstantString") &&
1028254721Semaste        strcmp(class_name,"NSCFString") &&
1029254721Semaste        strcmp(class_name,"NSPathStore2"))
1030254721Semaste    {
1031254721Semaste        // not one of us - but tell me class name
1032254721Semaste        stream.Printf("class name = %s",class_name);
1033254721Semaste        return true;
1034254721Semaste    }
1035254721Semaste
1036254721Semaste    if (is_mutable)
1037254721Semaste    {
1038254721Semaste        uint64_t location = 2 * ptr_size + valobj_addr;
1039254721Semaste        location = process_sp->ReadPointerFromMemory(location, error);
1040254721Semaste        if (error.Fail())
1041254721Semaste            return false;
1042263363Semaste        if (has_explicit_length && is_unicode)
1043254721Semaste        {
1044254721Semaste            ReadUTFBufferAndDumpToStreamOptions<UTF16> options;
1045254721Semaste            options.SetConversionFunction(ConvertUTF16toUTF8);
1046254721Semaste            options.SetLocation(location);
1047254721Semaste            options.SetProcessSP(process_sp);
1048254721Semaste            options.SetStream(&stream);
1049254721Semaste            options.SetPrefixToken('@');
1050254721Semaste            options.SetQuote('"');
1051254721Semaste            options.SetSourceSize(explicit_length);
1052254721Semaste            options.SetNeedsZeroTermination(false);
1053254721Semaste            return ReadUTFBufferAndDumpToStream (options);
1054254721Semaste        }
1055254721Semaste        else
1056254721Semaste            return ReadAsciiBufferAndDumpToStream(location+1,process_sp,stream, explicit_length);
1057254721Semaste    }
1058254721Semaste    else if (is_inline && has_explicit_length && !is_unicode && !is_special && !is_mutable)
1059254721Semaste    {
1060254721Semaste        uint64_t location = 3 * ptr_size + valobj_addr;
1061254721Semaste        return ReadAsciiBufferAndDumpToStream(location,process_sp,stream,explicit_length);
1062254721Semaste    }
1063254721Semaste    else if (is_unicode)
1064254721Semaste    {
1065254721Semaste        uint64_t location = valobj_addr + 2*ptr_size;
1066254721Semaste        if (is_inline)
1067254721Semaste        {
1068254721Semaste            if (!has_explicit_length)
1069254721Semaste            {
1070254721Semaste                stream.Printf("found new combo");
1071254721Semaste                return true;
1072254721Semaste            }
1073254721Semaste            else
1074254721Semaste                location += ptr_size;
1075254721Semaste        }
1076254721Semaste        else
1077254721Semaste        {
1078254721Semaste            location = process_sp->ReadPointerFromMemory(location, error);
1079254721Semaste            if (error.Fail())
1080254721Semaste                return false;
1081254721Semaste        }
1082254721Semaste        ReadUTFBufferAndDumpToStreamOptions<UTF16> options;
1083254721Semaste        options.SetConversionFunction(ConvertUTF16toUTF8);
1084254721Semaste        options.SetLocation(location);
1085254721Semaste        options.SetProcessSP(process_sp);
1086254721Semaste        options.SetStream(&stream);
1087254721Semaste        options.SetPrefixToken('@');
1088254721Semaste        options.SetQuote('"');
1089254721Semaste        options.SetSourceSize(explicit_length);
1090254721Semaste        options.SetNeedsZeroTermination(has_explicit_length == false);
1091254721Semaste        return ReadUTFBufferAndDumpToStream (options);
1092254721Semaste    }
1093254721Semaste    else if (is_special)
1094254721Semaste    {
1095254721Semaste        uint64_t location = valobj_addr + (ptr_size == 8 ? 12 : 8);
1096254721Semaste        ReadUTFBufferAndDumpToStreamOptions<UTF16> options;
1097254721Semaste        options.SetConversionFunction(ConvertUTF16toUTF8);
1098254721Semaste        options.SetLocation(location);
1099254721Semaste        options.SetProcessSP(process_sp);
1100254721Semaste        options.SetStream(&stream);
1101254721Semaste        options.SetPrefixToken('@');
1102254721Semaste        options.SetQuote('"');
1103254721Semaste        options.SetSourceSize(explicit_length);
1104254721Semaste        options.SetNeedsZeroTermination(has_explicit_length == false);
1105254721Semaste        return ReadUTFBufferAndDumpToStream (options);
1106254721Semaste    }
1107254721Semaste    else if (is_inline)
1108254721Semaste    {
1109254721Semaste        uint64_t location = valobj_addr + 2*ptr_size;
1110254721Semaste        if (!has_explicit_length)
1111254721Semaste            location++;
1112254721Semaste        return ReadAsciiBufferAndDumpToStream(location,process_sp,stream,explicit_length);
1113254721Semaste    }
1114254721Semaste    else
1115254721Semaste    {
1116254721Semaste        uint64_t location = valobj_addr + 2*ptr_size;
1117254721Semaste        location = process_sp->ReadPointerFromMemory(location, error);
1118254721Semaste        if (error.Fail())
1119254721Semaste            return false;
1120254721Semaste        if (has_explicit_length && !has_null)
1121254721Semaste            explicit_length++; // account for the fact that there is no NULL and we need to have one added
1122254721Semaste        return ReadAsciiBufferAndDumpToStream(location,process_sp,stream,explicit_length);
1123254721Semaste    }
1124254721Semaste
1125254721Semaste    stream.Printf("class name = %s",class_name);
1126254721Semaste    return true;
1127254721Semaste
1128254721Semaste}
1129254721Semaste
1130254721Semastebool
1131254721Semastelldb_private::formatters::NSAttributedStringSummaryProvider (ValueObject& valobj, Stream& stream)
1132254721Semaste{
1133254721Semaste    TargetSP target_sp(valobj.GetTargetSP());
1134254721Semaste    if (!target_sp)
1135254721Semaste        return false;
1136254721Semaste    uint32_t addr_size = target_sp->GetArchitecture().GetAddressByteSize();
1137254721Semaste    uint64_t pointer_value = valobj.GetValueAsUnsigned(0);
1138254721Semaste    if (!pointer_value)
1139254721Semaste        return false;
1140254721Semaste    pointer_value += addr_size;
1141254721Semaste    ClangASTType type(valobj.GetClangType());
1142254721Semaste    ExecutionContext exe_ctx(target_sp,false);
1143254721Semaste    ValueObjectSP child_ptr_sp(valobj.CreateValueObjectFromAddress("string_ptr", pointer_value, exe_ctx, type));
1144254721Semaste    if (!child_ptr_sp)
1145254721Semaste        return false;
1146254721Semaste    DataExtractor data;
1147254721Semaste    child_ptr_sp->GetData(data);
1148254721Semaste    ValueObjectSP child_sp(child_ptr_sp->CreateValueObjectFromData("string_data", data, exe_ctx, type));
1149254721Semaste    child_sp->GetValueAsUnsigned(0);
1150254721Semaste    if (child_sp)
1151254721Semaste        return NSStringSummaryProvider(*child_sp, stream);
1152254721Semaste    return false;
1153254721Semaste}
1154254721Semaste
1155254721Semastebool
1156254721Semastelldb_private::formatters::NSMutableAttributedStringSummaryProvider (ValueObject& valobj, Stream& stream)
1157254721Semaste{
1158254721Semaste    return NSAttributedStringSummaryProvider(valobj, stream);
1159254721Semaste}
1160254721Semaste
1161254721Semastebool
1162254721Semastelldb_private::formatters::RuntimeSpecificDescriptionSummaryProvider (ValueObject& valobj, Stream& stream)
1163254721Semaste{
1164254721Semaste    stream.Printf("%s",valobj.GetObjectDescription());
1165254721Semaste    return true;
1166254721Semaste}
1167254721Semaste
1168254721Semastebool
1169254721Semastelldb_private::formatters::ObjCBOOLSummaryProvider (ValueObject& valobj, Stream& stream)
1170254721Semaste{
1171254721Semaste    const uint32_t type_info = valobj.GetClangType().GetTypeInfo();
1172254721Semaste
1173254721Semaste    ValueObjectSP real_guy_sp = valobj.GetSP();
1174254721Semaste
1175254721Semaste    if (type_info & ClangASTType::eTypeIsPointer)
1176254721Semaste    {
1177254721Semaste        Error err;
1178254721Semaste        real_guy_sp = valobj.Dereference(err);
1179254721Semaste        if (err.Fail() || !real_guy_sp)
1180254721Semaste            return false;
1181254721Semaste    }
1182254721Semaste    else if (type_info & ClangASTType::eTypeIsReference)
1183254721Semaste    {
1184254721Semaste        real_guy_sp =  valobj.GetChildAtIndex(0, true);
1185254721Semaste        if (!real_guy_sp)
1186254721Semaste            return false;
1187254721Semaste    }
1188254721Semaste    uint64_t value = real_guy_sp->GetValueAsUnsigned(0);
1189254721Semaste    if (value == 0)
1190254721Semaste    {
1191254721Semaste        stream.Printf("NO");
1192254721Semaste        return true;
1193254721Semaste    }
1194254721Semaste    stream.Printf("YES");
1195254721Semaste    return true;
1196254721Semaste}
1197254721Semaste
1198254721Semastetemplate <bool is_sel_ptr>
1199254721Semastebool
1200254721Semastelldb_private::formatters::ObjCSELSummaryProvider (ValueObject& valobj, Stream& stream)
1201254721Semaste{
1202254721Semaste    lldb::ValueObjectSP valobj_sp;
1203254721Semaste
1204254721Semaste    ClangASTType charstar (valobj.GetClangType().GetBasicTypeFromAST(eBasicTypeChar).GetPointerType());
1205254721Semaste
1206254721Semaste    if (!charstar)
1207254721Semaste        return false;
1208254721Semaste
1209254721Semaste    ExecutionContext exe_ctx(valobj.GetExecutionContextRef());
1210254721Semaste
1211254721Semaste    if (is_sel_ptr)
1212254721Semaste    {
1213254721Semaste        lldb::addr_t data_address = valobj.GetValueAsUnsigned(LLDB_INVALID_ADDRESS);
1214254721Semaste        if (data_address == LLDB_INVALID_ADDRESS)
1215254721Semaste            return false;
1216254721Semaste        valobj_sp = ValueObject::CreateValueObjectFromAddress("text", data_address, exe_ctx, charstar);
1217254721Semaste    }
1218254721Semaste    else
1219254721Semaste    {
1220254721Semaste        DataExtractor data;
1221254721Semaste        valobj.GetData(data);
1222254721Semaste        valobj_sp = ValueObject::CreateValueObjectFromData("text", data, exe_ctx, charstar);
1223254721Semaste    }
1224254721Semaste
1225254721Semaste    if (!valobj_sp)
1226254721Semaste        return false;
1227254721Semaste
1228254721Semaste    stream.Printf("%s",valobj_sp->GetSummaryAsCString());
1229254721Semaste    return true;
1230254721Semaste}
1231254721Semaste
1232254721Semaste// POSIX has an epoch on Jan-1-1970, but Cocoa prefers Jan-1-2001
1233254721Semaste// this call gives the POSIX equivalent of the Cocoa epoch
1234254721Semastetime_t
1235254721Semastelldb_private::formatters::GetOSXEpoch ()
1236254721Semaste{
1237254721Semaste    static time_t epoch = 0;
1238254721Semaste    if (!epoch)
1239254721Semaste    {
1240263363Semaste#ifndef _WIN32
1241254721Semaste        tzset();
1242254721Semaste        tm tm_epoch;
1243254721Semaste        tm_epoch.tm_sec = 0;
1244254721Semaste        tm_epoch.tm_hour = 0;
1245254721Semaste        tm_epoch.tm_min = 0;
1246254721Semaste        tm_epoch.tm_mon = 0;
1247254721Semaste        tm_epoch.tm_mday = 1;
1248254721Semaste        tm_epoch.tm_year = 2001-1900; // for some reason, we need to subtract 1900 from this field. not sure why.
1249254721Semaste        tm_epoch.tm_isdst = -1;
1250254721Semaste        tm_epoch.tm_gmtoff = 0;
1251254721Semaste        tm_epoch.tm_zone = NULL;
1252254721Semaste        epoch = timegm(&tm_epoch);
1253263363Semaste#endif
1254254721Semaste    }
1255254721Semaste    return epoch;
1256254721Semaste}
1257254721Semaste
1258254721Semastesize_t
1259254721Semastelldb_private::formatters::ExtractIndexFromString (const char* item_name)
1260254721Semaste{
1261254721Semaste    if (!item_name || !*item_name)
1262254721Semaste        return UINT32_MAX;
1263254721Semaste    if (*item_name != '[')
1264254721Semaste        return UINT32_MAX;
1265254721Semaste    item_name++;
1266254721Semaste    char* endptr = NULL;
1267254721Semaste    unsigned long int idx = ::strtoul(item_name, &endptr, 0);
1268254721Semaste    if (idx == 0 && endptr == item_name)
1269254721Semaste        return UINT32_MAX;
1270254721Semaste    if (idx == ULONG_MAX)
1271254721Semaste        return UINT32_MAX;
1272254721Semaste    return idx;
1273254721Semaste}
1274254721Semaste
1275254721Semastelldb_private::formatters::VectorIteratorSyntheticFrontEnd::VectorIteratorSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp,
1276254721Semaste                                                                                            ConstString item_name) :
1277254721SemasteSyntheticChildrenFrontEnd(*valobj_sp.get()),
1278254721Semastem_exe_ctx_ref(),
1279254721Semastem_item_name(item_name),
1280254721Semastem_item_sp()
1281254721Semaste{
1282254721Semaste    if (valobj_sp)
1283254721Semaste        Update();
1284254721Semaste}
1285254721Semaste
1286254721Semastebool
1287254721Semastelldb_private::formatters::VectorIteratorSyntheticFrontEnd::Update()
1288254721Semaste{
1289254721Semaste    m_item_sp.reset();
1290254721Semaste
1291254721Semaste    ValueObjectSP valobj_sp = m_backend.GetSP();
1292254721Semaste    if (!valobj_sp)
1293254721Semaste        return false;
1294254721Semaste
1295254721Semaste    if (!valobj_sp)
1296254721Semaste        return false;
1297254721Semaste
1298254721Semaste    ValueObjectSP item_ptr(valobj_sp->GetChildMemberWithName(m_item_name,true));
1299254721Semaste    if (!item_ptr)
1300254721Semaste        return false;
1301254721Semaste    if (item_ptr->GetValueAsUnsigned(0) == 0)
1302254721Semaste        return false;
1303254721Semaste    Error err;
1304254721Semaste    m_exe_ctx_ref = valobj_sp->GetExecutionContextRef();
1305254721Semaste    m_item_sp = ValueObject::CreateValueObjectFromAddress("item", item_ptr->GetValueAsUnsigned(0), m_exe_ctx_ref, item_ptr->GetClangType().GetPointeeType());
1306254721Semaste    if (err.Fail())
1307254721Semaste        m_item_sp.reset();
1308254721Semaste    return false;
1309254721Semaste}
1310254721Semaste
1311254721Semastesize_t
1312254721Semastelldb_private::formatters::VectorIteratorSyntheticFrontEnd::CalculateNumChildren ()
1313254721Semaste{
1314254721Semaste    return 1;
1315254721Semaste}
1316254721Semaste
1317254721Semastelldb::ValueObjectSP
1318254721Semastelldb_private::formatters::VectorIteratorSyntheticFrontEnd::GetChildAtIndex (size_t idx)
1319254721Semaste{
1320254721Semaste    if (idx == 0)
1321254721Semaste        return m_item_sp;
1322254721Semaste    return lldb::ValueObjectSP();
1323254721Semaste}
1324254721Semaste
1325254721Semastebool
1326254721Semastelldb_private::formatters::VectorIteratorSyntheticFrontEnd::MightHaveChildren ()
1327254721Semaste{
1328254721Semaste    return true;
1329254721Semaste}
1330254721Semaste
1331254721Semastesize_t
1332254721Semastelldb_private::formatters::VectorIteratorSyntheticFrontEnd::GetIndexOfChildWithName (const ConstString &name)
1333254721Semaste{
1334254721Semaste    if (name == ConstString("item"))
1335254721Semaste        return 0;
1336254721Semaste    return UINT32_MAX;
1337254721Semaste}
1338254721Semaste
1339254721Semastelldb_private::formatters::VectorIteratorSyntheticFrontEnd::~VectorIteratorSyntheticFrontEnd ()
1340254721Semaste{
1341254721Semaste}
1342254721Semaste
1343254721Semastetemplate bool
1344254721Semastelldb_private::formatters::NSDataSummaryProvider<true> (ValueObject&, Stream&) ;
1345254721Semaste
1346254721Semastetemplate bool
1347254721Semastelldb_private::formatters::NSDataSummaryProvider<false> (ValueObject&, Stream&) ;
1348254721Semaste
1349254721Semastetemplate bool
1350254721Semastelldb_private::formatters::ObjCSELSummaryProvider<true> (ValueObject&, Stream&) ;
1351254721Semaste
1352254721Semastetemplate bool
1353254721Semastelldb_private::formatters::ObjCSELSummaryProvider<false> (ValueObject&, Stream&) ;
1354