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