]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm/tools/lldb/source/DataFormatters/CXXFormatterFunctions.cpp
Update LLDB snapshot to upstream r225923 (git 2b588ecd)
[FreeBSD/FreeBSD.git] / contrib / llvm / tools / lldb / source / DataFormatters / CXXFormatterFunctions.cpp
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 #include "lldb/DataFormatters/StringPrinter.h"
14 #include "lldb/DataFormatters/TypeSummary.h"
15
16 #include "llvm/Support/ConvertUTF.h"
17
18 #include "lldb/Core/DataBufferHeap.h"
19 #include "lldb/Core/Error.h"
20 #include "lldb/Core/Stream.h"
21 #include "lldb/Core/ValueObject.h"
22 #include "lldb/Core/ValueObjectConstResult.h"
23 #include "lldb/Host/Endian.h"
24 #include "lldb/Symbol/ClangASTContext.h"
25 #include "lldb/Target/SectionLoadList.h"
26 #include "lldb/Target/Target.h"
27 #include "lldb/Target/Thread.h"
28
29 #include "lldb/Utility/ProcessStructReader.h"
30
31 #include <algorithm>
32 #if __ANDROID_NDK__
33 #include <sys/types.h>
34 #endif
35
36 using namespace lldb;
37 using namespace lldb_private;
38 using namespace lldb_private::formatters;
39
40 StackFrame*
41 lldb_private::formatters::GetViableFrame (ExecutionContext exe_ctx)
42 {
43     StackFrame* frame = exe_ctx.GetFramePtr();
44     if (frame)
45         return frame;
46     
47     Process* process = exe_ctx.GetProcessPtr();
48     if (!process)
49         return nullptr;
50     
51     ThreadSP thread_sp(process->GetThreadList().GetSelectedThread());
52     if (thread_sp)
53         return thread_sp->GetSelectedFrame().get();
54     return nullptr;
55 }
56
57 bool
58 lldb_private::formatters::ExtractValueFromObjCExpression (ValueObject &valobj,
59                                                           const char* target_type,
60                                                           const char* selector,
61                                                           uint64_t &value)
62 {
63     if (!target_type || !*target_type)
64         return false;
65     if (!selector || !*selector)
66         return false;
67     StreamString expr;
68     expr.Printf("(%s)[(id)0x%" PRIx64 " %s]",target_type,valobj.GetPointerValue(),selector);
69     ExecutionContext exe_ctx (valobj.GetExecutionContextRef());
70     lldb::ValueObjectSP result_sp;
71     Target* target = exe_ctx.GetTargetPtr();
72     StackFrame* stack_frame = GetViableFrame(exe_ctx);
73     if (!target || !stack_frame)
74         return false;
75     
76     EvaluateExpressionOptions options;
77     options.SetCoerceToId(false);
78     options.SetUnwindOnError(true);
79     options.SetKeepInMemory(true);
80     
81     target->EvaluateExpression(expr.GetData(),
82                                stack_frame,
83                                result_sp,
84                                options);
85     if (!result_sp)
86         return false;
87     value = result_sp->GetValueAsUnsigned(0);
88     return true;
89 }
90
91 bool
92 lldb_private::formatters::ExtractSummaryFromObjCExpression (ValueObject &valobj,
93                                                             const char* target_type,
94                                                             const char* selector,
95                                                             Stream &stream)
96 {
97     if (!target_type || !*target_type)
98         return false;
99     if (!selector || !*selector)
100         return false;
101     StreamString expr;
102     expr.Printf("(%s)[(id)0x%" PRIx64 " %s]",target_type,valobj.GetPointerValue(),selector);
103     ExecutionContext exe_ctx (valobj.GetExecutionContextRef());
104     lldb::ValueObjectSP result_sp;
105     Target* target = exe_ctx.GetTargetPtr();
106     StackFrame* stack_frame = GetViableFrame(exe_ctx);
107     if (!target || !stack_frame)
108         return false;
109     
110     EvaluateExpressionOptions options;
111     options.SetCoerceToId(false);
112     options.SetUnwindOnError(true);
113     options.SetKeepInMemory(true);
114     options.SetUseDynamic(lldb::eDynamicCanRunTarget);
115     
116     target->EvaluateExpression(expr.GetData(),
117                                stack_frame,
118                                result_sp,
119                                options);
120     if (!result_sp)
121         return false;
122     stream.Printf("%s",result_sp->GetSummaryAsCString());
123     return true;
124 }
125
126 lldb::ValueObjectSP
127 lldb_private::formatters::CallSelectorOnObject (ValueObject &valobj,
128                                                 const char* return_type,
129                                                 const char* selector,
130                                                 uint64_t index)
131 {
132     lldb::ValueObjectSP valobj_sp;
133     if (!return_type || !*return_type)
134         return valobj_sp;
135     if (!selector || !*selector)
136         return valobj_sp;
137     StreamString expr_path_stream;
138     valobj.GetExpressionPath(expr_path_stream, false);
139     StreamString expr;
140     expr.Printf("(%s)[%s %s:%" PRId64 "]",return_type,expr_path_stream.GetData(),selector,index);
141     ExecutionContext exe_ctx (valobj.GetExecutionContextRef());
142     lldb::ValueObjectSP result_sp;
143     Target* target = exe_ctx.GetTargetPtr();
144     StackFrame* stack_frame = GetViableFrame(exe_ctx);
145     if (!target || !stack_frame)
146         return valobj_sp;
147     
148     EvaluateExpressionOptions options;
149     options.SetCoerceToId(false);
150     options.SetUnwindOnError(true);
151     options.SetKeepInMemory(true);
152     options.SetUseDynamic(lldb::eDynamicCanRunTarget);
153     
154     target->EvaluateExpression(expr.GetData(),
155                                stack_frame,
156                                valobj_sp,
157                                options);
158     return valobj_sp;
159 }
160
161 lldb::ValueObjectSP
162 lldb_private::formatters::CallSelectorOnObject (ValueObject &valobj,
163                                                 const char* return_type,
164                                                 const char* selector,
165                                                 const char* key)
166 {
167     lldb::ValueObjectSP valobj_sp;
168     if (!return_type || !*return_type)
169         return valobj_sp;
170     if (!selector || !*selector)
171         return valobj_sp;
172     if (!key || !*key)
173         return valobj_sp;
174     StreamString expr_path_stream;
175     valobj.GetExpressionPath(expr_path_stream, false);
176     StreamString expr;
177     expr.Printf("(%s)[%s %s:%s]",return_type,expr_path_stream.GetData(),selector,key);
178     ExecutionContext exe_ctx (valobj.GetExecutionContextRef());
179     lldb::ValueObjectSP result_sp;
180     Target* target = exe_ctx.GetTargetPtr();
181     StackFrame* stack_frame = GetViableFrame(exe_ctx);
182     if (!target || !stack_frame)
183         return valobj_sp;
184     
185     EvaluateExpressionOptions options;
186     options.SetCoerceToId(false);
187     options.SetUnwindOnError(true);
188     options.SetKeepInMemory(true);
189     options.SetUseDynamic(lldb::eDynamicCanRunTarget);
190     
191     target->EvaluateExpression(expr.GetData(),
192                                stack_frame,
193                                valobj_sp,
194                                options);
195     return valobj_sp;
196 }
197
198 bool
199 lldb_private::formatters::FunctionPointerSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options)
200 {
201     std::string destination;
202     StreamString sstr;
203     AddressType func_ptr_address_type = eAddressTypeInvalid;
204     addr_t func_ptr_address = valobj.GetPointerValue (&func_ptr_address_type);
205     if (func_ptr_address != 0 && func_ptr_address != LLDB_INVALID_ADDRESS)
206     {
207         switch (func_ptr_address_type)
208         {
209             case eAddressTypeInvalid:
210             case eAddressTypeFile:
211             case eAddressTypeHost:
212                 break;
213                 
214             case eAddressTypeLoad:
215             {
216                 ExecutionContext exe_ctx (valobj.GetExecutionContextRef());
217                 
218                 Address so_addr;
219                 Target *target = exe_ctx.GetTargetPtr();
220                 if (target && target->GetSectionLoadList().IsEmpty() == false)
221                 {
222                     if (target->GetSectionLoadList().ResolveLoadAddress(func_ptr_address, so_addr))
223                     {
224                         so_addr.Dump (&sstr,
225                                       exe_ctx.GetBestExecutionContextScope(),
226                                       Address::DumpStyleResolvedDescription,
227                                       Address::DumpStyleSectionNameOffset);
228                     }
229                 }
230             }
231                 break;
232         }
233     }
234     if (sstr.GetSize() > 0)
235     {
236         stream.Printf("(%s)", sstr.GetData());
237         return true;
238     }
239     else
240         return false;
241 }
242
243 bool
244 lldb_private::formatters::Char16StringSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions&)
245 {
246     ProcessSP process_sp = valobj.GetProcessSP();
247     if (!process_sp)
248         return false;
249     
250     lldb::addr_t valobj_addr = valobj.GetValueAsUnsigned(0);
251     
252     if (!valobj_addr)
253         return false;
254     
255     ReadStringAndDumpToStreamOptions options(valobj);
256     options.SetLocation(valobj_addr);
257     options.SetProcessSP(process_sp);
258     options.SetStream(&stream);
259     options.SetPrefixToken('u');
260     
261     if (!ReadStringAndDumpToStream<StringElementType::UTF16>(options))
262     {
263         stream.Printf("Summary Unavailable");
264         return true;
265     }
266
267     return true;
268 }
269
270 bool
271 lldb_private::formatters::Char32StringSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions&)
272 {
273     ProcessSP process_sp = valobj.GetProcessSP();
274     if (!process_sp)
275         return false;
276     
277     lldb::addr_t valobj_addr = valobj.GetValueAsUnsigned(0);
278     
279     if (!valobj_addr)
280         return false;
281     
282     ReadStringAndDumpToStreamOptions options(valobj);
283     options.SetLocation(valobj_addr);
284     options.SetProcessSP(process_sp);
285     options.SetStream(&stream);
286     options.SetPrefixToken('U');
287     
288     if (!ReadStringAndDumpToStream<StringElementType::UTF32>(options))
289     {
290         stream.Printf("Summary Unavailable");
291         return true;
292     }
293     
294     return true;
295 }
296
297 bool
298 lldb_private::formatters::WCharStringSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions&)
299 {
300     ProcessSP process_sp = valobj.GetProcessSP();
301     if (!process_sp)
302         return false;
303
304     lldb::addr_t data_addr = 0;
305     
306     if (valobj.IsPointerType())
307         data_addr = valobj.GetValueAsUnsigned(0);
308     else if (valobj.IsArrayType())
309         data_addr = valobj.GetAddressOf();
310
311     if (data_addr == 0 || data_addr == LLDB_INVALID_ADDRESS)
312         return false;
313
314     clang::ASTContext* ast = valobj.GetClangType().GetASTContext();
315     
316     if (!ast)
317         return false;
318
319     ClangASTType wchar_clang_type = ClangASTContext::GetBasicType(ast, lldb::eBasicTypeWChar);
320     const uint32_t wchar_size = wchar_clang_type.GetBitSize();
321
322     ReadStringAndDumpToStreamOptions options(valobj);
323     options.SetLocation(data_addr);
324     options.SetProcessSP(process_sp);
325     options.SetStream(&stream);
326     options.SetPrefixToken('L');
327     
328     switch (wchar_size)
329     {
330         case 8:
331             return ReadStringAndDumpToStream<StringElementType::UTF8>(options);
332         case 16:
333             return ReadStringAndDumpToStream<StringElementType::UTF16>(options);
334         case 32:
335             return ReadStringAndDumpToStream<StringElementType::UTF32>(options);
336         default:
337             stream.Printf("size for wchar_t is not valid");
338             return true;
339     }
340     return true;
341 }
342
343 bool
344 lldb_private::formatters::Char16SummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions&)
345 {
346     DataExtractor data;
347     Error error;
348     valobj.GetData(data, error);
349     
350     if (error.Fail())
351         return false;
352     
353     std::string value;
354     valobj.GetValueAsCString(lldb::eFormatUnicode16, value);
355     if (!value.empty())
356         stream.Printf("%s ", value.c_str());
357
358     ReadBufferAndDumpToStreamOptions options(valobj);
359     options.SetData(data);
360     options.SetStream(&stream);
361     options.SetPrefixToken('u');
362     options.SetQuote('\'');
363     options.SetSourceSize(1);
364     
365     return ReadBufferAndDumpToStream<StringElementType::UTF16>(options);
366 }
367
368 bool
369 lldb_private::formatters::Char32SummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions&)
370 {
371     DataExtractor data;
372     Error error;
373     valobj.GetData(data, error);
374     
375     if (error.Fail())
376         return false;
377     
378     std::string value;
379     valobj.GetValueAsCString(lldb::eFormatUnicode32, value);
380     if (!value.empty())
381         stream.Printf("%s ", value.c_str());
382     
383     ReadBufferAndDumpToStreamOptions options(valobj);
384     options.SetData(data);
385     options.SetStream(&stream);
386     options.SetPrefixToken('U');
387     options.SetQuote('\'');
388     options.SetSourceSize(1);
389     
390     return ReadBufferAndDumpToStream<StringElementType::UTF32>(options);
391 }
392
393 bool
394 lldb_private::formatters::WCharSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions&)
395 {
396     DataExtractor data;
397     Error error;
398     valobj.GetData(data, error);
399     
400     if (error.Fail())
401         return false;
402     
403     ReadBufferAndDumpToStreamOptions options(valobj);
404     options.SetData(data);
405     options.SetStream(&stream);
406     options.SetPrefixToken('L');
407     options.SetQuote('\'');
408     options.SetSourceSize(1);
409     
410     return ReadBufferAndDumpToStream<StringElementType::UTF16>(options);
411 }
412
413 // the field layout in a libc++ string (cap, side, data or data, size, cap)
414 enum LibcxxStringLayoutMode
415 {
416     eLibcxxStringLayoutModeCSD = 0,
417     eLibcxxStringLayoutModeDSC = 1,
418     eLibcxxStringLayoutModeInvalid = 0xffff
419 };
420
421 // this function abstracts away the layout and mode details of a libc++ string
422 // and returns the address of the data and the size ready for callers to consume
423 static bool
424 ExtractLibcxxStringInfo (ValueObject& valobj,
425                          ValueObjectSP &location_sp,
426                          uint64_t& size)
427 {
428     ValueObjectSP D(valobj.GetChildAtIndexPath({0,0,0,0}));
429     if (!D)
430         return false;
431     
432     ValueObjectSP layout_decider(D->GetChildAtIndexPath({0,0}));
433     
434     // this child should exist
435     if (!layout_decider)
436         return false;
437     
438     ConstString g_data_name("__data_");
439     ConstString g_size_name("__size_");
440     bool short_mode = false; // this means the string is in short-mode and the data is stored inline
441     LibcxxStringLayoutMode layout = (layout_decider->GetName() == g_data_name) ? eLibcxxStringLayoutModeDSC : eLibcxxStringLayoutModeCSD;
442     uint64_t size_mode_value = 0;
443     
444     if (layout == eLibcxxStringLayoutModeDSC)
445     {
446         ValueObjectSP size_mode(D->GetChildAtIndexPath({1,1,0}));
447         if (!size_mode)
448             return false;
449         
450         if (size_mode->GetName() != g_size_name)
451         {
452             // we are hitting the padding structure, move along
453             size_mode = D->GetChildAtIndexPath({1,1,1});
454             if (!size_mode)
455                 return false;
456         }
457         
458         size_mode_value = (size_mode->GetValueAsUnsigned(0));
459         short_mode = ((size_mode_value & 0x80) == 0);
460     }
461     else
462     {
463         ValueObjectSP size_mode(D->GetChildAtIndexPath({1,0,0}));
464         if (!size_mode)
465             return false;
466         
467         size_mode_value = (size_mode->GetValueAsUnsigned(0));
468         short_mode = ((size_mode_value & 1) == 0);
469     }
470     
471     if (short_mode)
472     {
473         ValueObjectSP s(D->GetChildAtIndex(1, true));
474         if (!s)
475             return false;
476         location_sp = s->GetChildAtIndex((layout == eLibcxxStringLayoutModeDSC) ? 0 : 1, true);
477         size = (layout == eLibcxxStringLayoutModeDSC) ? size_mode_value : ((size_mode_value >> 1) % 256);
478         return (location_sp.get() != nullptr);
479     }
480     else
481     {
482         ValueObjectSP l(D->GetChildAtIndex(0, true));
483         if (!l)
484             return false;
485         // we can use the layout_decider object as the data pointer
486         location_sp = (layout == eLibcxxStringLayoutModeDSC) ? layout_decider : l->GetChildAtIndex(2, true);
487         ValueObjectSP size_vo(l->GetChildAtIndex(1, true));
488         if (!size_vo || !location_sp)
489             return false;
490         size = size_vo->GetValueAsUnsigned(0);
491         return true;
492     }
493 }
494
495 bool
496 lldb_private::formatters::LibcxxWStringSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options)
497 {
498     uint64_t size = 0;
499     ValueObjectSP location_sp((ValueObject*)nullptr);
500     if (!ExtractLibcxxStringInfo(valobj, location_sp, size))
501         return false;
502     if (size == 0)
503     {
504         stream.Printf("L\"\"");
505         return true;
506     }   
507     if (!location_sp)
508         return false;
509     return WCharStringSummaryProvider(*location_sp.get(), stream, options);
510 }
511
512 bool
513 lldb_private::formatters::LibcxxStringSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& summary_options)
514 {
515     uint64_t size = 0;
516     ValueObjectSP location_sp((ValueObject*)nullptr);
517     
518     if (!ExtractLibcxxStringInfo(valobj, location_sp, size))
519         return false;
520     
521     if (size == 0)
522     {
523         stream.Printf("\"\"");
524         return true;
525     }
526     
527     if (!location_sp)
528         return false;
529     
530     DataExtractor extractor;
531     if (summary_options.GetCapping() == TypeSummaryCapping::eTypeSummaryCapped)
532         size = std::min<decltype(size)>(size, valobj.GetTargetSP()->GetMaximumSizeOfStringSummary());
533     location_sp->GetPointeeData(extractor, 0, size);
534     
535     ReadBufferAndDumpToStreamOptions options(valobj);
536     options.SetData(extractor); // none of this matters for a string - pass some defaults
537     options.SetStream(&stream);
538     options.SetPrefixToken(0);
539     options.SetQuote('"');
540     options.SetSourceSize(size);
541     lldb_private::formatters::ReadBufferAndDumpToStream<lldb_private::formatters::StringElementType::ASCII>(options);
542     
543     return true;
544 }
545
546 bool
547 lldb_private::formatters::ObjCClassSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options)
548 {
549     ProcessSP process_sp = valobj.GetProcessSP();
550     if (!process_sp)
551         return false;
552     
553     ObjCLanguageRuntime* runtime = (ObjCLanguageRuntime*)process_sp->GetLanguageRuntime(lldb::eLanguageTypeObjC);
554     
555     if (!runtime)
556         return false;
557     
558     ObjCLanguageRuntime::ClassDescriptorSP descriptor(runtime->GetClassDescriptorFromISA(valobj.GetValueAsUnsigned(0)));
559     
560     if (!descriptor.get() || !descriptor->IsValid())
561         return false;
562
563     const char* class_name = descriptor->GetClassName().GetCString();
564     
565     if (!class_name || !*class_name)
566         return false;
567     
568     stream.Printf("%s",class_name);
569     return true;
570 }
571
572 class ObjCClassSyntheticChildrenFrontEnd : public SyntheticChildrenFrontEnd
573 {
574 public:
575     ObjCClassSyntheticChildrenFrontEnd (lldb::ValueObjectSP valobj_sp) :
576     SyntheticChildrenFrontEnd(*valobj_sp.get())
577     {
578     }
579     
580     virtual size_t
581     CalculateNumChildren ()
582     {
583         return 0;
584     }
585     
586     virtual lldb::ValueObjectSP
587     GetChildAtIndex (size_t idx)
588     {
589         return lldb::ValueObjectSP();
590     }
591     
592     virtual bool
593     Update()
594     {
595         return false;
596     }
597     
598     virtual bool
599     MightHaveChildren ()
600     {
601         return false;
602     }
603     
604     virtual size_t
605     GetIndexOfChildWithName (const ConstString &name)
606     {
607         return UINT32_MAX;
608     }
609     
610     virtual
611     ~ObjCClassSyntheticChildrenFrontEnd ()
612     {
613     }
614 };
615
616 SyntheticChildrenFrontEnd*
617 lldb_private::formatters::ObjCClassSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP valobj_sp)
618 {
619     return new ObjCClassSyntheticChildrenFrontEnd(valobj_sp);
620 }
621
622 template<bool needs_at>
623 bool
624 lldb_private::formatters::NSDataSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options)
625 {
626     ProcessSP process_sp = valobj.GetProcessSP();
627     if (!process_sp)
628         return false;
629     
630     ObjCLanguageRuntime* runtime = (ObjCLanguageRuntime*)process_sp->GetLanguageRuntime(lldb::eLanguageTypeObjC);
631     
632     if (!runtime)
633         return false;
634     
635     ObjCLanguageRuntime::ClassDescriptorSP descriptor(runtime->GetClassDescriptor(valobj));
636     
637     if (!descriptor.get() || !descriptor->IsValid())
638         return false;
639     
640     bool is_64bit = (process_sp->GetAddressByteSize() == 8);
641     lldb::addr_t valobj_addr = valobj.GetValueAsUnsigned(0);
642     
643     if (!valobj_addr)
644         return false;
645     
646     uint64_t value = 0;
647     
648     const char* class_name = descriptor->GetClassName().GetCString();
649     
650     if (!class_name || !*class_name)
651         return false;
652     
653     if (!strcmp(class_name,"NSConcreteData") ||
654         !strcmp(class_name,"NSConcreteMutableData") ||
655         !strcmp(class_name,"__NSCFData"))
656     {
657         uint32_t offset = (is_64bit ? 16 : 8);
658         Error error;
659         value = process_sp->ReadUnsignedIntegerFromMemory(valobj_addr + offset, is_64bit ? 8 : 4, 0, error);
660         if (error.Fail())
661             return false;
662     }
663     else
664     {
665         if (!ExtractValueFromObjCExpression(valobj, "int", "length", value))
666             return false;
667     }
668     
669     stream.Printf("%s%" PRIu64 " byte%s%s",
670                   (needs_at ? "@\"" : ""),
671                   value,
672                   (value != 1 ? "s" : ""),
673                   (needs_at ? "\"" : ""));
674     
675     return true;
676 }
677
678 static bool
679 ReadAsciiBufferAndDumpToStream (lldb::addr_t location,
680                                 lldb::ProcessSP& process_sp,
681                                 Stream& dest,
682                                 uint32_t size = 0,
683                                 Error* error = NULL,
684                                 size_t *data_read = NULL,
685                                 char prefix_token = '@',
686                                 char quote = '"')
687 {
688     Error my_error;
689     size_t my_data_read;
690     if (!process_sp || location == 0)
691         return false;
692     
693     if (!size)
694         size = process_sp->GetTarget().GetMaximumSizeOfStringSummary();
695     else
696         size = std::min(size,process_sp->GetTarget().GetMaximumSizeOfStringSummary());
697     
698     lldb::DataBufferSP buffer_sp(new DataBufferHeap(size,0));
699     
700     my_data_read = process_sp->ReadCStringFromMemory(location, (char*)buffer_sp->GetBytes(), size, my_error);
701
702     if (error)
703         *error = my_error;
704     if (data_read)
705         *data_read = my_data_read;
706     
707     if (my_error.Fail())
708         return false;
709     
710     dest.Printf("%c%c",prefix_token,quote);
711     
712     if (my_data_read)
713         dest.Printf("%s",(char*)buffer_sp->GetBytes());
714     
715     dest.Printf("%c",quote);
716     
717     return true;
718 }
719
720 bool
721 lldb_private::formatters::NSTaggedString_SummaryProvider (ObjCLanguageRuntime::ClassDescriptorSP descriptor, Stream& stream)
722 {
723     if (!descriptor)
724         return false;
725     uint64_t len_bits = 0, data_bits = 0;
726     if (!descriptor->GetTaggedPointerInfo(&len_bits,&data_bits,nullptr))
727         return false;
728     
729     static const int g_MaxNonBitmaskedLen = 7; //TAGGED_STRING_UNPACKED_MAXLEN
730     static const int g_SixbitMaxLen = 9;
731     static const int g_fiveBitMaxLen = 11;
732     
733     static const char *sixBitToCharLookup = "eilotrm.apdnsIc ufkMShjTRxgC4013" "bDNvwyUL2O856P-B79AFKEWV_zGJ/HYX";
734     
735     if (len_bits > g_fiveBitMaxLen)
736         return false;
737     
738     // this is a fairly ugly trick - pretend that the numeric value is actually a char*
739     // this works under a few assumptions:
740     // little endian architecture
741     // sizeof(uint64_t) > g_MaxNonBitmaskedLen
742     if (len_bits <= g_MaxNonBitmaskedLen)
743     {
744         stream.Printf("@\"%s\"",(const char*)&data_bits);
745         return true;
746     }
747     
748     // if the data is bitmasked, we need to actually process the bytes
749     uint8_t bitmask = 0;
750     uint8_t shift_offset = 0;
751     
752     if (len_bits <= g_SixbitMaxLen)
753     {
754         bitmask = 0x03f;
755         shift_offset = 6;
756     }
757     else
758     {
759         bitmask = 0x01f;
760         shift_offset = 5;
761     }
762     
763     std::vector<uint8_t> bytes;
764     bytes.resize(len_bits);
765     for (; len_bits > 0; data_bits >>= shift_offset, --len_bits)
766     {
767         uint8_t packed = data_bits & bitmask;
768         bytes.insert(bytes.begin(), sixBitToCharLookup[packed]);
769     }
770     
771     stream.Printf("@\"%s\"",&bytes[0]);
772     return true;
773 }
774
775 static ClangASTType
776 GetNSPathStore2Type (Target &target)
777 {
778     static ConstString g_type_name("__lldb_autogen_nspathstore2");
779
780     ClangASTContext *ast_ctx = target.GetScratchClangASTContext();
781     
782     if (!ast_ctx)
783         return ClangASTType();
784     
785     ClangASTType voidstar = ast_ctx->GetBasicType(lldb::eBasicTypeVoid).GetPointerType();
786     ClangASTType uint32 = ast_ctx->GetIntTypeFromBitSize(32, false);
787     
788     return ast_ctx->GetOrCreateStructForIdentifier(g_type_name, {
789         {"isa",voidstar},
790         {"lengthAndRef",uint32},
791         {"buffer",voidstar}
792     });
793 }
794
795 bool
796 lldb_private::formatters::NSStringSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& summary_options)
797 {
798     ProcessSP process_sp = valobj.GetProcessSP();
799     if (!process_sp)
800         return false;
801     
802     ObjCLanguageRuntime* runtime = (ObjCLanguageRuntime*)process_sp->GetLanguageRuntime(lldb::eLanguageTypeObjC);
803     
804     if (!runtime)
805         return false;
806     
807     ObjCLanguageRuntime::ClassDescriptorSP descriptor(runtime->GetClassDescriptor(valobj));
808     
809     if (!descriptor.get() || !descriptor->IsValid())
810         return false;
811     
812     uint32_t ptr_size = process_sp->GetAddressByteSize();
813     
814     lldb::addr_t valobj_addr = valobj.GetValueAsUnsigned(0);
815     
816     if (!valobj_addr)
817         return false;
818     
819     const char* class_name = descriptor->GetClassName().GetCString();
820     
821     if (!class_name || !*class_name)
822         return false;
823     
824     bool is_tagged_ptr = (0 == strcmp(class_name,"NSTaggedPointerString")) && descriptor->GetTaggedPointerInfo();
825     // for a tagged pointer, the descriptor has everything we need
826     if (is_tagged_ptr)
827         return NSTaggedString_SummaryProvider(descriptor, stream);
828     
829     // if not a tagged pointer that we know about, try the normal route
830     uint64_t info_bits_location = valobj_addr + ptr_size;
831     if (process_sp->GetByteOrder() != lldb::eByteOrderLittle)
832         info_bits_location += 3;
833         
834     Error error;
835     
836     uint8_t info_bits = process_sp->ReadUnsignedIntegerFromMemory(info_bits_location, 1, 0, error);
837     if (error.Fail())
838         return false;
839     
840     bool is_mutable = (info_bits & 1) == 1;
841     bool is_inline = (info_bits & 0x60) == 0;
842     bool has_explicit_length = (info_bits & (1 | 4)) != 4;
843     bool is_unicode = (info_bits & 0x10) == 0x10;
844     bool is_special = strcmp(class_name,"NSPathStore2") == 0;
845     bool has_null = (info_bits & 8) == 8;
846     
847     size_t explicit_length = 0;
848     if (!has_null && has_explicit_length && !is_special)
849     {
850         lldb::addr_t explicit_length_offset = 2*ptr_size;
851         if (is_mutable && !is_inline)
852             explicit_length_offset = explicit_length_offset + ptr_size; //  notInlineMutable.length;
853         else if (is_inline)
854             explicit_length = explicit_length + 0; // inline1.length;
855         else if (!is_inline && !is_mutable)
856             explicit_length_offset = explicit_length_offset + ptr_size; // notInlineImmutable1.length;
857         else
858             explicit_length_offset = 0;
859
860         if (explicit_length_offset)
861         {
862             explicit_length_offset = valobj_addr + explicit_length_offset;
863             explicit_length = process_sp->ReadUnsignedIntegerFromMemory(explicit_length_offset, 4, 0, error);
864         }
865     }
866     
867     if (strcmp(class_name,"NSString") &&
868         strcmp(class_name,"CFStringRef") &&
869         strcmp(class_name,"CFMutableStringRef") &&
870         strcmp(class_name,"__NSCFConstantString") &&
871         strcmp(class_name,"__NSCFString") &&
872         strcmp(class_name,"NSCFConstantString") &&
873         strcmp(class_name,"NSCFString") &&
874         strcmp(class_name,"NSPathStore2"))
875     {
876         // not one of us - but tell me class name
877         stream.Printf("class name = %s",class_name);
878         return true;
879     }
880     
881     if (is_mutable)
882     {
883         uint64_t location = 2 * ptr_size + valobj_addr;
884         location = process_sp->ReadPointerFromMemory(location, error);
885         if (error.Fail())
886             return false;
887         if (has_explicit_length && is_unicode)
888         {
889             ReadStringAndDumpToStreamOptions options(valobj);
890             options.SetLocation(location);
891             options.SetProcessSP(process_sp);
892             options.SetStream(&stream);
893             options.SetPrefixToken('@');
894             options.SetQuote('"');
895             options.SetSourceSize(explicit_length);
896             options.SetNeedsZeroTermination(false);
897             options.SetIgnoreMaxLength(summary_options.GetCapping() == TypeSummaryCapping::eTypeSummaryUncapped);
898             return ReadStringAndDumpToStream<StringElementType::UTF16>(options);
899         }
900         else
901         {
902             ReadStringAndDumpToStreamOptions options(valobj);
903             options.SetLocation(location+1);
904             options.SetProcessSP(process_sp);
905             options.SetStream(&stream);
906             options.SetPrefixToken('@');
907             options.SetSourceSize(explicit_length);
908             options.SetNeedsZeroTermination(false);
909             options.SetIgnoreMaxLength(summary_options.GetCapping() == TypeSummaryCapping::eTypeSummaryUncapped);
910             return ReadStringAndDumpToStream<StringElementType::ASCII>(options);
911         }
912     }
913     else if (is_inline && has_explicit_length && !is_unicode && !is_special && !is_mutable)
914     {
915         uint64_t location = 3 * ptr_size + valobj_addr;
916         return ReadAsciiBufferAndDumpToStream(location,process_sp,stream,explicit_length);
917     }
918     else if (is_unicode)
919     {
920         uint64_t location = valobj_addr + 2*ptr_size;
921         if (is_inline)
922         {
923             if (!has_explicit_length)
924             {
925                 stream.Printf("found new combo");
926                 return true;
927             }
928             else
929                 location += ptr_size;
930         }
931         else
932         {
933             location = process_sp->ReadPointerFromMemory(location, error);
934             if (error.Fail())
935                 return false;
936         }
937         ReadStringAndDumpToStreamOptions options(valobj);
938         options.SetLocation(location);
939         options.SetProcessSP(process_sp);
940         options.SetStream(&stream);
941         options.SetPrefixToken('@');
942         options.SetQuote('"');
943         options.SetSourceSize(explicit_length);
944         options.SetNeedsZeroTermination(has_explicit_length == false);
945         options.SetIgnoreMaxLength(summary_options.GetCapping() == TypeSummaryCapping::eTypeSummaryUncapped);
946         return ReadStringAndDumpToStream<StringElementType::UTF16> (options);
947     }
948     else if (is_special)
949     {
950         ProcessStructReader reader(valobj.GetProcessSP().get(), valobj.GetValueAsUnsigned(0), GetNSPathStore2Type(*valobj.GetTargetSP()));
951         explicit_length = reader.GetField<uint32_t>(ConstString("lengthAndRef")) >> 20;
952         lldb::addr_t location = valobj.GetValueAsUnsigned(0) + ptr_size + 4;
953         
954         ReadStringAndDumpToStreamOptions options(valobj);
955         options.SetLocation(location);
956         options.SetProcessSP(process_sp);
957         options.SetStream(&stream);
958         options.SetPrefixToken('@');
959         options.SetQuote('"');
960         options.SetSourceSize(explicit_length);
961         options.SetNeedsZeroTermination(has_explicit_length == false);
962         options.SetIgnoreMaxLength(summary_options.GetCapping() == TypeSummaryCapping::eTypeSummaryUncapped);
963         return ReadStringAndDumpToStream<StringElementType::UTF16> (options);
964     }
965     else if (is_inline)
966     {
967         uint64_t location = valobj_addr + 2*ptr_size;
968         if (!has_explicit_length)
969             location++;
970         ReadStringAndDumpToStreamOptions options(valobj);
971         options.SetLocation(location);
972         options.SetProcessSP(process_sp);
973         options.SetStream(&stream);
974         options.SetPrefixToken('@');
975         options.SetSourceSize(explicit_length);
976         options.SetIgnoreMaxLength(summary_options.GetCapping() == TypeSummaryCapping::eTypeSummaryUncapped);
977         return ReadStringAndDumpToStream<StringElementType::ASCII>(options);
978     }
979     else
980     {
981         uint64_t location = valobj_addr + 2*ptr_size;
982         location = process_sp->ReadPointerFromMemory(location, error);
983         if (error.Fail())
984             return false;
985         if (has_explicit_length && !has_null)
986             explicit_length++; // account for the fact that there is no NULL and we need to have one added
987         ReadStringAndDumpToStreamOptions options(valobj);
988         options.SetLocation(location);
989         options.SetProcessSP(process_sp);
990         options.SetPrefixToken('@');
991         options.SetStream(&stream);
992         options.SetSourceSize(explicit_length);
993         options.SetIgnoreMaxLength(summary_options.GetCapping() == TypeSummaryCapping::eTypeSummaryUncapped);
994         return ReadStringAndDumpToStream<StringElementType::ASCII>(options);
995     }
996 }
997
998 bool
999 lldb_private::formatters::NSAttributedStringSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options)
1000 {
1001     TargetSP target_sp(valobj.GetTargetSP());
1002     if (!target_sp)
1003         return false;
1004     uint32_t addr_size = target_sp->GetArchitecture().GetAddressByteSize();
1005     uint64_t pointer_value = valobj.GetValueAsUnsigned(0);
1006     if (!pointer_value)
1007         return false;
1008     pointer_value += addr_size;
1009     ClangASTType type(valobj.GetClangType());
1010     ExecutionContext exe_ctx(target_sp,false);
1011     ValueObjectSP child_ptr_sp(valobj.CreateValueObjectFromAddress("string_ptr", pointer_value, exe_ctx, type));
1012     if (!child_ptr_sp)
1013         return false;
1014     DataExtractor data;
1015     Error error;
1016     child_ptr_sp->GetData(data, error);
1017     if (error.Fail())
1018         return false;
1019     ValueObjectSP child_sp(child_ptr_sp->CreateValueObjectFromData("string_data", data, exe_ctx, type));
1020     child_sp->GetValueAsUnsigned(0);
1021     if (child_sp)
1022         return NSStringSummaryProvider(*child_sp, stream, options);
1023     return false;
1024 }
1025
1026 bool
1027 lldb_private::formatters::NSMutableAttributedStringSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options)
1028 {
1029     return NSAttributedStringSummaryProvider(valobj, stream, options);
1030 }
1031
1032 bool
1033 lldb_private::formatters::RuntimeSpecificDescriptionSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options)
1034 {
1035     stream.Printf("%s",valobj.GetObjectDescription());
1036     return true;
1037 }
1038
1039 bool
1040 lldb_private::formatters::ObjCBOOLSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options)
1041 {
1042     const uint32_t type_info = valobj.GetClangType().GetTypeInfo();
1043     
1044     ValueObjectSP real_guy_sp = valobj.GetSP();
1045     
1046     if (type_info & eTypeIsPointer)
1047     {
1048         Error err;
1049         real_guy_sp = valobj.Dereference(err);
1050         if (err.Fail() || !real_guy_sp)
1051             return false;
1052     }
1053     else if (type_info & eTypeIsReference)
1054     {
1055         real_guy_sp =  valobj.GetChildAtIndex(0, true);
1056         if (!real_guy_sp)
1057             return false;
1058     }
1059     uint64_t value = real_guy_sp->GetValueAsUnsigned(0);
1060     if (value == 0)
1061     {
1062         stream.Printf("NO");
1063         return true;
1064     }
1065     stream.Printf("YES");
1066     return true;
1067 }
1068
1069 template <bool is_sel_ptr>
1070 bool
1071 lldb_private::formatters::ObjCSELSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options)
1072 {
1073     lldb::ValueObjectSP valobj_sp;
1074
1075     ClangASTType charstar (valobj.GetClangType().GetBasicTypeFromAST(eBasicTypeChar).GetPointerType());
1076     
1077     if (!charstar)
1078         return false;
1079
1080     ExecutionContext exe_ctx(valobj.GetExecutionContextRef());
1081     
1082     if (is_sel_ptr)
1083     {
1084         lldb::addr_t data_address = valobj.GetValueAsUnsigned(LLDB_INVALID_ADDRESS);
1085         if (data_address == LLDB_INVALID_ADDRESS)
1086             return false;
1087         valobj_sp = ValueObject::CreateValueObjectFromAddress("text", data_address, exe_ctx, charstar);
1088     }
1089     else
1090     {
1091         DataExtractor data;
1092         Error error;
1093         valobj.GetData(data, error);
1094         if (error.Fail())
1095             return false;
1096         valobj_sp = ValueObject::CreateValueObjectFromData("text", data, exe_ctx, charstar);
1097     }
1098     
1099     if (!valobj_sp)
1100         return false;
1101     
1102     stream.Printf("%s",valobj_sp->GetSummaryAsCString());
1103     return true;
1104 }
1105
1106 // POSIX has an epoch on Jan-1-1970, but Cocoa prefers Jan-1-2001
1107 // this call gives the POSIX equivalent of the Cocoa epoch
1108 time_t
1109 lldb_private::formatters::GetOSXEpoch ()
1110 {
1111     static time_t epoch = 0;
1112     if (!epoch)
1113     {
1114 #ifndef _WIN32
1115         tzset();
1116         tm tm_epoch;
1117         tm_epoch.tm_sec = 0;
1118         tm_epoch.tm_hour = 0;
1119         tm_epoch.tm_min = 0;
1120         tm_epoch.tm_mon = 0;
1121         tm_epoch.tm_mday = 1;
1122         tm_epoch.tm_year = 2001-1900; // for some reason, we need to subtract 1900 from this field. not sure why.
1123         tm_epoch.tm_isdst = -1;
1124         tm_epoch.tm_gmtoff = 0;
1125         tm_epoch.tm_zone = NULL;
1126         epoch = timegm(&tm_epoch);
1127 #endif
1128     }
1129     return epoch;
1130 }
1131
1132 size_t
1133 lldb_private::formatters::ExtractIndexFromString (const char* item_name)
1134 {
1135     if (!item_name || !*item_name)
1136         return UINT32_MAX;
1137     if (*item_name != '[')
1138         return UINT32_MAX;
1139     item_name++;
1140     char* endptr = NULL;
1141     unsigned long int idx = ::strtoul(item_name, &endptr, 0);
1142     if (idx == 0 && endptr == item_name)
1143         return UINT32_MAX;
1144     if (idx == ULONG_MAX)
1145         return UINT32_MAX;
1146     return idx;
1147 }
1148
1149 lldb_private::formatters::VectorIteratorSyntheticFrontEnd::VectorIteratorSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp,
1150                                                                                             ConstString item_name) :
1151 SyntheticChildrenFrontEnd(*valobj_sp.get()),
1152 m_exe_ctx_ref(),
1153 m_item_name(item_name),
1154 m_item_sp()
1155 {
1156     if (valobj_sp)
1157         Update();
1158 }
1159
1160 bool
1161 lldb_private::formatters::VectorIteratorSyntheticFrontEnd::Update()
1162 {
1163     m_item_sp.reset();
1164
1165     ValueObjectSP valobj_sp = m_backend.GetSP();
1166     if (!valobj_sp)
1167         return false;
1168     
1169     if (!valobj_sp)
1170         return false;
1171     
1172     ValueObjectSP item_ptr(valobj_sp->GetChildMemberWithName(m_item_name,true));
1173     if (!item_ptr)
1174         return false;
1175     if (item_ptr->GetValueAsUnsigned(0) == 0)
1176         return false;
1177     Error err;
1178     m_exe_ctx_ref = valobj_sp->GetExecutionContextRef();
1179     m_item_sp = CreateValueObjectFromAddress("item", item_ptr->GetValueAsUnsigned(0), m_exe_ctx_ref, item_ptr->GetClangType().GetPointeeType());
1180     if (err.Fail())
1181         m_item_sp.reset();
1182     return false;
1183 }
1184
1185 size_t
1186 lldb_private::formatters::VectorIteratorSyntheticFrontEnd::CalculateNumChildren ()
1187 {
1188     return 1;
1189 }
1190
1191 lldb::ValueObjectSP
1192 lldb_private::formatters::VectorIteratorSyntheticFrontEnd::GetChildAtIndex (size_t idx)
1193 {
1194     if (idx == 0)
1195         return m_item_sp;
1196     return lldb::ValueObjectSP();
1197 }
1198
1199 bool
1200 lldb_private::formatters::VectorIteratorSyntheticFrontEnd::MightHaveChildren ()
1201 {
1202     return true;
1203 }
1204
1205 size_t
1206 lldb_private::formatters::VectorIteratorSyntheticFrontEnd::GetIndexOfChildWithName (const ConstString &name)
1207 {
1208     if (name == ConstString("item"))
1209         return 0;
1210     return UINT32_MAX;
1211 }
1212
1213 lldb_private::formatters::VectorIteratorSyntheticFrontEnd::~VectorIteratorSyntheticFrontEnd ()
1214 {
1215 }
1216
1217 template bool
1218 lldb_private::formatters::NSDataSummaryProvider<true> (ValueObject&, Stream&, const TypeSummaryOptions&) ;
1219
1220 template bool
1221 lldb_private::formatters::NSDataSummaryProvider<false> (ValueObject&, Stream&, const TypeSummaryOptions&) ;
1222
1223 template bool
1224 lldb_private::formatters::ObjCSELSummaryProvider<true> (ValueObject&, Stream&, const TypeSummaryOptions&) ;
1225
1226 template bool
1227 lldb_private::formatters::ObjCSELSummaryProvider<false> (ValueObject&, Stream&, const TypeSummaryOptions&) ;