summaryrefslogtreecommitdiff
path: root/source/DataFormatters
diff options
context:
space:
mode:
authorEd Maste <emaste@FreeBSD.org>2015-02-06 21:38:51 +0000
committerEd Maste <emaste@FreeBSD.org>2015-02-06 21:38:51 +0000
commit205afe679855a4ce8149cdaa94d3f0868ce796dc (patch)
tree09bc83f73246ee3c7a779605cd0122093d2a8a19 /source/DataFormatters
parent0cac4ca3916ac24ab6139d03cbfd18db9e715bfe (diff)
Notes
Diffstat (limited to 'source/DataFormatters')
-rw-r--r--source/DataFormatters/CF.cpp8
-rw-r--r--source/DataFormatters/CXXFormatterFunctions.cpp580
-rw-r--r--source/DataFormatters/Cocoa.cpp28
-rw-r--r--source/DataFormatters/DataVisualization.cpp24
-rw-r--r--source/DataFormatters/FormatCache.cpp76
-rw-r--r--source/DataFormatters/FormatManager.cpp205
-rw-r--r--source/DataFormatters/LibCxx.cpp113
-rw-r--r--source/DataFormatters/LibCxxInitializerList.cpp145
-rw-r--r--source/DataFormatters/LibCxxList.cpp61
-rw-r--r--source/DataFormatters/LibCxxMap.cpp215
-rw-r--r--source/DataFormatters/LibCxxUnorderedMap.cpp35
-rw-r--r--source/DataFormatters/LibCxxVector.cpp157
-rw-r--r--source/DataFormatters/LibStdcpp.cpp2
-rw-r--r--source/DataFormatters/NSArray.cpp17
-rw-r--r--source/DataFormatters/NSDictionary.cpp197
-rw-r--r--source/DataFormatters/NSIndexPath.cpp309
-rw-r--r--source/DataFormatters/NSSet.cpp178
-rw-r--r--source/DataFormatters/StringPrinter.cpp650
-rw-r--r--source/DataFormatters/TypeCategory.cpp97
-rw-r--r--source/DataFormatters/TypeCategoryMap.cpp68
-rw-r--r--source/DataFormatters/TypeFormat.cpp12
-rw-r--r--source/DataFormatters/TypeSummary.cpp56
-rw-r--r--source/DataFormatters/TypeSynthetic.cpp138
-rw-r--r--source/DataFormatters/TypeValidator.cpp75
-rw-r--r--source/DataFormatters/ValueObjectPrinter.cpp108
25 files changed, 2790 insertions, 764 deletions
diff --git a/source/DataFormatters/CF.cpp b/source/DataFormatters/CF.cpp
index e131b68096fd4..483419e5ac3fb 100644
--- a/source/DataFormatters/CF.cpp
+++ b/source/DataFormatters/CF.cpp
@@ -26,7 +26,7 @@ using namespace lldb_private;
using namespace lldb_private::formatters;
bool
-lldb_private::formatters::CFAbsoluteTimeSummaryProvider (ValueObject& valobj, Stream& stream)
+lldb_private::formatters::CFAbsoluteTimeSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options)
{
time_t epoch = GetOSXEpoch();
epoch = epoch + (time_t)valobj.GetValueAsUnsigned(0);
@@ -41,7 +41,7 @@ lldb_private::formatters::CFAbsoluteTimeSummaryProvider (ValueObject& valobj, St
}
bool
-lldb_private::formatters::CFBagSummaryProvider (ValueObject& valobj, Stream& stream)
+lldb_private::formatters::CFBagSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options)
{
ProcessSP process_sp = valobj.GetProcessSP();
if (!process_sp)
@@ -105,7 +105,7 @@ lldb_private::formatters::CFBagSummaryProvider (ValueObject& valobj, Stream& str
}
bool
-lldb_private::formatters::CFBitVectorSummaryProvider (ValueObject& valobj, Stream& stream)
+lldb_private::formatters::CFBitVectorSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options)
{
ProcessSP process_sp = valobj.GetProcessSP();
if (!process_sp)
@@ -235,7 +235,7 @@ lldb_private::formatters::CFBitVectorSummaryProvider (ValueObject& valobj, Strea
}
bool
-lldb_private::formatters::CFBinaryHeapSummaryProvider (ValueObject& valobj, Stream& stream)
+lldb_private::formatters::CFBinaryHeapSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options)
{
ProcessSP process_sp = valobj.GetProcessSP();
if (!process_sp)
diff --git a/source/DataFormatters/CXXFormatterFunctions.cpp b/source/DataFormatters/CXXFormatterFunctions.cpp
index ae5b35fd2b1cb..04cdadf5a98fe 100644
--- a/source/DataFormatters/CXXFormatterFunctions.cpp
+++ b/source/DataFormatters/CXXFormatterFunctions.cpp
@@ -10,6 +10,8 @@
#include "lldb/lldb-python.h"
#include "lldb/DataFormatters/CXXFormatterFunctions.h"
+#include "lldb/DataFormatters/StringPrinter.h"
+#include "lldb/DataFormatters/TypeSummary.h"
#include "llvm/Support/ConvertUTF.h"
@@ -20,10 +22,16 @@
#include "lldb/Core/ValueObjectConstResult.h"
#include "lldb/Host/Endian.h"
#include "lldb/Symbol/ClangASTContext.h"
+#include "lldb/Target/SectionLoadList.h"
#include "lldb/Target/Target.h"
#include "lldb/Target/Thread.h"
+#include "lldb/Utility/ProcessStructReader.h"
+
#include <algorithm>
+#if __ANDROID_NDK__
+#include <sys/types.h>
+#endif
using namespace lldb;
using namespace lldb_private;
@@ -187,283 +195,53 @@ lldb_private::formatters::CallSelectorOnObject (ValueObject &valobj,
return valobj_sp;
}
-// use this call if you already have an LLDB-side buffer for the data
-template<typename SourceDataType>
-static bool
-DumpUTFBufferToStream (ConversionResult (*ConvertFunction) (const SourceDataType**,
- const SourceDataType*,
- UTF8**,
- UTF8*,
- ConversionFlags),
- DataExtractor& data,
- Stream& stream,
- char prefix_token = '@',
- char quote = '"',
- uint32_t sourceSize = 0)
+bool
+lldb_private::formatters::FunctionPointerSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options)
{
- if (prefix_token != 0)
- stream.Printf("%c",prefix_token);
- if (quote != 0)
- stream.Printf("%c",quote);
- if (data.GetByteSize() && data.GetDataStart() && data.GetDataEnd())
+ std::string destination;
+ StreamString sstr;
+ AddressType func_ptr_address_type = eAddressTypeInvalid;
+ addr_t func_ptr_address = valobj.GetPointerValue (&func_ptr_address_type);
+ if (func_ptr_address != 0 && func_ptr_address != LLDB_INVALID_ADDRESS)
{
- const int bufferSPSize = data.GetByteSize();
- if (sourceSize == 0)
- {
- const int origin_encoding = 8*sizeof(SourceDataType);
- sourceSize = bufferSPSize/(origin_encoding / 4);
- }
-
- SourceDataType *data_ptr = (SourceDataType*)data.GetDataStart();
- SourceDataType *data_end_ptr = data_ptr + sourceSize;
-
- while (data_ptr < data_end_ptr)
+ switch (func_ptr_address_type)
{
- if (!*data_ptr)
- {
- data_end_ptr = data_ptr;
+ case eAddressTypeInvalid:
+ case eAddressTypeFile:
+ case eAddressTypeHost:
break;
+
+ case eAddressTypeLoad:
+ {
+ ExecutionContext exe_ctx (valobj.GetExecutionContextRef());
+
+ Address so_addr;
+ Target *target = exe_ctx.GetTargetPtr();
+ if (target && target->GetSectionLoadList().IsEmpty() == false)
+ {
+ if (target->GetSectionLoadList().ResolveLoadAddress(func_ptr_address, so_addr))
+ {
+ so_addr.Dump (&sstr,
+ exe_ctx.GetBestExecutionContextScope(),
+ Address::DumpStyleResolvedDescription,
+ Address::DumpStyleSectionNameOffset);
+ }
+ }
}
- data_ptr++;
- }
-
- data_ptr = (SourceDataType*)data.GetDataStart();
-
- lldb::DataBufferSP utf8_data_buffer_sp;
- UTF8* utf8_data_ptr = nullptr;
- UTF8* utf8_data_end_ptr = nullptr;
-
- if (ConvertFunction)
- {
- utf8_data_buffer_sp.reset(new DataBufferHeap(4*bufferSPSize,0));
- utf8_data_ptr = (UTF8*)utf8_data_buffer_sp->GetBytes();
- utf8_data_end_ptr = utf8_data_ptr + utf8_data_buffer_sp->GetByteSize();
- ConvertFunction ( (const SourceDataType**)&data_ptr, data_end_ptr, &utf8_data_ptr, utf8_data_end_ptr, lenientConversion );
- utf8_data_ptr = (UTF8*)utf8_data_buffer_sp->GetBytes(); // needed because the ConvertFunction will change the value of the data_ptr
- }
- else
- {
- // just copy the pointers - the cast is necessary to make the compiler happy
- // but this should only happen if we are reading UTF8 data
- utf8_data_ptr = (UTF8*)data_ptr;
- utf8_data_end_ptr = (UTF8*)data_end_ptr;
- }
-
- // since we tend to accept partial data (and even partially malformed data)
- // we might end up with no NULL terminator before the end_ptr
- // hence we need to take a slower route and ensure we stay within boundaries
- for (;utf8_data_ptr != utf8_data_end_ptr; utf8_data_ptr++)
- {
- if (!*utf8_data_ptr)
break;
- stream.Printf("%c",*utf8_data_ptr);
}
}
- if (quote != 0)
- stream.Printf("%c",quote);
- return true;
-}
-
-template<typename SourceDataType>
-class ReadUTFBufferAndDumpToStreamOptions
-{
-public:
- typedef ConversionResult (*ConvertFunctionType) (const SourceDataType**,
- const SourceDataType*,
- UTF8**,
- UTF8*,
- ConversionFlags);
-
- ReadUTFBufferAndDumpToStreamOptions () :
- m_conversion_function(NULL),
- m_location(0),
- m_process_sp(),
- m_stream(NULL),
- m_prefix_token('@'),
- m_quote('"'),
- m_source_size(0),
- m_needs_zero_termination(true)
- {
- }
-
- ReadUTFBufferAndDumpToStreamOptions&
- SetConversionFunction (ConvertFunctionType f)
- {
- m_conversion_function = f;
- return *this;
- }
-
- ConvertFunctionType
- GetConversionFunction () const
- {
- return m_conversion_function;
- }
-
- ReadUTFBufferAndDumpToStreamOptions&
- SetLocation (uint64_t l)
- {
- m_location = l;
- return *this;
- }
-
- uint64_t
- GetLocation () const
- {
- return m_location;
- }
-
- ReadUTFBufferAndDumpToStreamOptions&
- SetProcessSP (ProcessSP p)
- {
- m_process_sp = p;
- return *this;
- }
-
- ProcessSP
- GetProcessSP () const
- {
- return m_process_sp;
- }
-
- ReadUTFBufferAndDumpToStreamOptions&
- SetStream (Stream* s)
- {
- m_stream = s;
- return *this;
- }
-
- Stream*
- GetStream () const
- {
- return m_stream;
- }
-
- ReadUTFBufferAndDumpToStreamOptions&
- SetPrefixToken (char p)
- {
- m_prefix_token = p;
- return *this;
- }
-
- char
- GetPrefixToken () const
- {
- return m_prefix_token;
- }
-
- ReadUTFBufferAndDumpToStreamOptions&
- SetQuote (char q)
- {
- m_quote = q;
- return *this;
- }
-
- char
- GetQuote () const
- {
- return m_quote;
- }
-
- ReadUTFBufferAndDumpToStreamOptions&
- SetSourceSize (uint32_t s)
- {
- m_source_size = s;
- return *this;
- }
-
- uint32_t
- GetSourceSize () const
- {
- return m_source_size;
- }
-
- ReadUTFBufferAndDumpToStreamOptions&
- SetNeedsZeroTermination (bool z)
+ if (sstr.GetSize() > 0)
{
- m_needs_zero_termination = z;
- return *this;
- }
-
- bool
- GetNeedsZeroTermination () const
- {
- return m_needs_zero_termination;
- }
-
-private:
- ConvertFunctionType m_conversion_function;
- uint64_t m_location;
- ProcessSP m_process_sp;
- Stream* m_stream;
- char m_prefix_token;
- char m_quote;
- uint32_t m_source_size;
- bool m_needs_zero_termination;
-};
-
-template<typename SourceDataType>
-static bool
-ReadUTFBufferAndDumpToStream (const ReadUTFBufferAndDumpToStreamOptions<SourceDataType>& options)
-{
- if (options.GetLocation() == 0 || options.GetLocation() == LLDB_INVALID_ADDRESS)
- return false;
-
- ProcessSP process_sp(options.GetProcessSP());
-
- if (!process_sp)
- return false;
-
- const int type_width = sizeof(SourceDataType);
- const int origin_encoding = 8 * type_width ;
- if (origin_encoding != 8 && origin_encoding != 16 && origin_encoding != 32)
- return false;
- // if not UTF8, I need a conversion function to return proper UTF8
- if (origin_encoding != 8 && !options.GetConversionFunction())
- return false;
-
- if (!options.GetStream())
- return false;
-
- uint32_t sourceSize = options.GetSourceSize();
- bool needs_zero_terminator = options.GetNeedsZeroTermination();
-
- if (!sourceSize)
- {
- sourceSize = process_sp->GetTarget().GetMaximumSizeOfStringSummary();
- needs_zero_terminator = true;
+ stream.Printf("(%s)", sstr.GetData());
+ return true;
}
else
- sourceSize = std::min(sourceSize,process_sp->GetTarget().GetMaximumSizeOfStringSummary());
-
- const int bufferSPSize = sourceSize * type_width;
-
- lldb::DataBufferSP buffer_sp(new DataBufferHeap(bufferSPSize,0));
-
- if (!buffer_sp->GetBytes())
return false;
-
- Error error;
- char *buffer = reinterpret_cast<char *>(buffer_sp->GetBytes());
-
- size_t data_read = 0;
- if (needs_zero_terminator)
- data_read = process_sp->ReadStringFromMemory(options.GetLocation(), buffer, bufferSPSize, error, type_width);
- else
- data_read = process_sp->ReadMemoryFromInferior(options.GetLocation(), (char*)buffer_sp->GetBytes(), bufferSPSize, error);
-
- if (error.Fail() || data_read == 0)
- {
- options.GetStream()->Printf("unable to read data");
- return true;
- }
-
- DataExtractor data(buffer_sp, process_sp->GetByteOrder(), process_sp->GetAddressByteSize());
-
- return DumpUTFBufferToStream(options.GetConversionFunction(), data, *options.GetStream(), options.GetPrefixToken(), options.GetQuote(), sourceSize);
}
bool
-lldb_private::formatters::Char16StringSummaryProvider (ValueObject& valobj, Stream& stream)
+lldb_private::formatters::Char16StringSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions&)
{
ProcessSP process_sp = valobj.GetProcessSP();
if (!process_sp)
@@ -474,14 +252,13 @@ lldb_private::formatters::Char16StringSummaryProvider (ValueObject& valobj, Stre
if (!valobj_addr)
return false;
- ReadUTFBufferAndDumpToStreamOptions<UTF16> options;
+ ReadStringAndDumpToStreamOptions options(valobj);
options.SetLocation(valobj_addr);
- options.SetConversionFunction(ConvertUTF16toUTF8);
options.SetProcessSP(process_sp);
options.SetStream(&stream);
options.SetPrefixToken('u');
- if (!ReadUTFBufferAndDumpToStream(options))
+ if (!ReadStringAndDumpToStream<StringElementType::UTF16>(options))
{
stream.Printf("Summary Unavailable");
return true;
@@ -491,7 +268,7 @@ lldb_private::formatters::Char16StringSummaryProvider (ValueObject& valobj, Stre
}
bool
-lldb_private::formatters::Char32StringSummaryProvider (ValueObject& valobj, Stream& stream)
+lldb_private::formatters::Char32StringSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions&)
{
ProcessSP process_sp = valobj.GetProcessSP();
if (!process_sp)
@@ -502,14 +279,13 @@ lldb_private::formatters::Char32StringSummaryProvider (ValueObject& valobj, Stre
if (!valobj_addr)
return false;
- ReadUTFBufferAndDumpToStreamOptions<UTF32> options;
+ ReadStringAndDumpToStreamOptions options(valobj);
options.SetLocation(valobj_addr);
- options.SetConversionFunction(ConvertUTF32toUTF8);
options.SetProcessSP(process_sp);
options.SetStream(&stream);
options.SetPrefixToken('U');
- if (!ReadUTFBufferAndDumpToStream(options))
+ if (!ReadStringAndDumpToStream<StringElementType::UTF32>(options))
{
stream.Printf("Summary Unavailable");
return true;
@@ -519,7 +295,7 @@ lldb_private::formatters::Char32StringSummaryProvider (ValueObject& valobj, Stre
}
bool
-lldb_private::formatters::WCharStringSummaryProvider (ValueObject& valobj, Stream& stream)
+lldb_private::formatters::WCharStringSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions&)
{
ProcessSP process_sp = valobj.GetProcessSP();
if (!process_sp)
@@ -543,45 +319,20 @@ lldb_private::formatters::WCharStringSummaryProvider (ValueObject& valobj, Strea
ClangASTType wchar_clang_type = ClangASTContext::GetBasicType(ast, lldb::eBasicTypeWChar);
const uint32_t wchar_size = wchar_clang_type.GetBitSize();
+ ReadStringAndDumpToStreamOptions options(valobj);
+ options.SetLocation(data_addr);
+ options.SetProcessSP(process_sp);
+ options.SetStream(&stream);
+ options.SetPrefixToken('L');
+
switch (wchar_size)
{
case 8:
- {
- // utf 8
-
- ReadUTFBufferAndDumpToStreamOptions<UTF8> options;
- options.SetLocation(data_addr);
- options.SetConversionFunction(nullptr);
- options.SetProcessSP(process_sp);
- options.SetStream(&stream);
- options.SetPrefixToken('L');
-
- return ReadUTFBufferAndDumpToStream(options);
- }
+ return ReadStringAndDumpToStream<StringElementType::UTF8>(options);
case 16:
- {
- // utf 16
- ReadUTFBufferAndDumpToStreamOptions<UTF16> options;
- options.SetLocation(data_addr);
- options.SetConversionFunction(ConvertUTF16toUTF8);
- options.SetProcessSP(process_sp);
- options.SetStream(&stream);
- options.SetPrefixToken('L');
-
- return ReadUTFBufferAndDumpToStream(options);
- }
+ return ReadStringAndDumpToStream<StringElementType::UTF16>(options);
case 32:
- {
- // utf 32
- ReadUTFBufferAndDumpToStreamOptions<UTF32> options;
- options.SetLocation(data_addr);
- options.SetConversionFunction(ConvertUTF32toUTF8);
- options.SetProcessSP(process_sp);
- options.SetStream(&stream);
- options.SetPrefixToken('L');
-
- return ReadUTFBufferAndDumpToStream(options);
- }
+ return ReadStringAndDumpToStream<StringElementType::UTF32>(options);
default:
stream.Printf("size for wchar_t is not valid");
return true;
@@ -590,7 +341,7 @@ lldb_private::formatters::WCharStringSummaryProvider (ValueObject& valobj, Strea
}
bool
-lldb_private::formatters::Char16SummaryProvider (ValueObject& valobj, Stream& stream)
+lldb_private::formatters::Char16SummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions&)
{
DataExtractor data;
Error error;
@@ -604,11 +355,18 @@ lldb_private::formatters::Char16SummaryProvider (ValueObject& valobj, Stream& st
if (!value.empty())
stream.Printf("%s ", value.c_str());
- return DumpUTFBufferToStream<UTF16>(ConvertUTF16toUTF8,data,stream, 'u','\'',1);
+ ReadBufferAndDumpToStreamOptions options(valobj);
+ options.SetData(data);
+ options.SetStream(&stream);
+ options.SetPrefixToken('u');
+ options.SetQuote('\'');
+ options.SetSourceSize(1);
+
+ return ReadBufferAndDumpToStream<StringElementType::UTF16>(options);
}
bool
-lldb_private::formatters::Char32SummaryProvider (ValueObject& valobj, Stream& stream)
+lldb_private::formatters::Char32SummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions&)
{
DataExtractor data;
Error error;
@@ -622,11 +380,18 @@ lldb_private::formatters::Char32SummaryProvider (ValueObject& valobj, Stream& st
if (!value.empty())
stream.Printf("%s ", value.c_str());
- return DumpUTFBufferToStream<UTF32>(ConvertUTF32toUTF8,data,stream, 'U','\'',1);
+ ReadBufferAndDumpToStreamOptions options(valobj);
+ options.SetData(data);
+ options.SetStream(&stream);
+ options.SetPrefixToken('U');
+ options.SetQuote('\'');
+ options.SetSourceSize(1);
+
+ return ReadBufferAndDumpToStream<StringElementType::UTF32>(options);
}
bool
-lldb_private::formatters::WCharSummaryProvider (ValueObject& valobj, Stream& stream)
+lldb_private::formatters::WCharSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions&)
{
DataExtractor data;
Error error;
@@ -635,55 +400,14 @@ lldb_private::formatters::WCharSummaryProvider (ValueObject& valobj, Stream& str
if (error.Fail())
return false;
- clang::ASTContext* ast = valobj.GetClangType().GetASTContext();
-
- if (!ast)
- return false;
-
- ClangASTType wchar_clang_type = ClangASTContext::GetBasicType(ast, lldb::eBasicTypeWChar);
- const uint32_t wchar_size = wchar_clang_type.GetBitSize();
- std::string value;
+ ReadBufferAndDumpToStreamOptions options(valobj);
+ options.SetData(data);
+ options.SetStream(&stream);
+ options.SetPrefixToken('L');
+ options.SetQuote('\'');
+ options.SetSourceSize(1);
- switch (wchar_size)
- {
- case 8:
- // utf 8
- valobj.GetValueAsCString(lldb::eFormatChar, value);
- if (!value.empty())
- stream.Printf("%s ", value.c_str());
- return DumpUTFBufferToStream<UTF8>(nullptr,
- data,
- stream,
- 'L',
- '\'',
- 1);
- case 16:
- // utf 16
- valobj.GetValueAsCString(lldb::eFormatUnicode16, value);
- if (!value.empty())
- stream.Printf("%s ", value.c_str());
- return DumpUTFBufferToStream<UTF16>(ConvertUTF16toUTF8,
- data,
- stream,
- 'L',
- '\'',
- 1);
- case 32:
- // utf 32
- valobj.GetValueAsCString(lldb::eFormatUnicode32, value);
- if (!value.empty())
- stream.Printf("%s ", value.c_str());
- return DumpUTFBufferToStream<UTF32>(ConvertUTF32toUTF8,
- data,
- stream,
- 'L',
- '\'',
- 1);
- default:
- stream.Printf("size for wchar_t is not valid");
- return true;
- }
- return true;
+ return ReadBufferAndDumpToStream<StringElementType::UTF16>(options);
}
// the field layout in a libc++ string (cap, side, data or data, size, cap)
@@ -769,7 +493,7 @@ ExtractLibcxxStringInfo (ValueObject& valobj,
}
bool
-lldb_private::formatters::LibcxxWStringSummaryProvider (ValueObject& valobj, Stream& stream)
+lldb_private::formatters::LibcxxWStringSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options)
{
uint64_t size = 0;
ValueObjectSP location_sp((ValueObject*)nullptr);
@@ -782,34 +506,45 @@ lldb_private::formatters::LibcxxWStringSummaryProvider (ValueObject& valobj, Str
}
if (!location_sp)
return false;
- return WCharStringSummaryProvider(*location_sp.get(), stream);
+ return WCharStringSummaryProvider(*location_sp.get(), stream, options);
}
bool
-lldb_private::formatters::LibcxxStringSummaryProvider (ValueObject& valobj, Stream& stream)
+lldb_private::formatters::LibcxxStringSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& summary_options)
{
uint64_t size = 0;
ValueObjectSP location_sp((ValueObject*)nullptr);
+
if (!ExtractLibcxxStringInfo(valobj, location_sp, size))
return false;
+
if (size == 0)
{
stream.Printf("\"\"");
return true;
}
+
if (!location_sp)
return false;
- Error error;
- if (location_sp->ReadPointedString(stream,
- error,
- 0, // max length is decided by the settings
- false) == 0) // do not honor array (terminates on first 0 byte even for a char[])
- stream.Printf("\"\""); // if nothing was read, print an empty string
- return error.Success();
+
+ DataExtractor extractor;
+ if (summary_options.GetCapping() == TypeSummaryCapping::eTypeSummaryCapped)
+ size = std::min<decltype(size)>(size, valobj.GetTargetSP()->GetMaximumSizeOfStringSummary());
+ location_sp->GetPointeeData(extractor, 0, size);
+
+ ReadBufferAndDumpToStreamOptions options(valobj);
+ options.SetData(extractor); // none of this matters for a string - pass some defaults
+ options.SetStream(&stream);
+ options.SetPrefixToken(0);
+ options.SetQuote('"');
+ options.SetSourceSize(size);
+ lldb_private::formatters::ReadBufferAndDumpToStream<lldb_private::formatters::StringElementType::ASCII>(options);
+
+ return true;
}
bool
-lldb_private::formatters::ObjCClassSummaryProvider (ValueObject& valobj, Stream& stream)
+lldb_private::formatters::ObjCClassSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options)
{
ProcessSP process_sp = valobj.GetProcessSP();
if (!process_sp)
@@ -886,7 +621,7 @@ lldb_private::formatters::ObjCClassSyntheticFrontEndCreator (CXXSyntheticChildre
template<bool needs_at>
bool
-lldb_private::formatters::NSDataSummaryProvider (ValueObject& valobj, Stream& stream)
+lldb_private::formatters::NSDataSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options)
{
ProcessSP process_sp = valobj.GetProcessSP();
if (!process_sp)
@@ -1037,8 +772,28 @@ lldb_private::formatters::NSTaggedString_SummaryProvider (ObjCLanguageRuntime::C
return true;
}
+static ClangASTType
+GetNSPathStore2Type (Target &target)
+{
+ static ConstString g_type_name("__lldb_autogen_nspathstore2");
+
+ ClangASTContext *ast_ctx = target.GetScratchClangASTContext();
+
+ if (!ast_ctx)
+ return ClangASTType();
+
+ ClangASTType voidstar = ast_ctx->GetBasicType(lldb::eBasicTypeVoid).GetPointerType();
+ ClangASTType uint32 = ast_ctx->GetIntTypeFromBitSize(32, false);
+
+ return ast_ctx->GetOrCreateStructForIdentifier(g_type_name, {
+ {"isa",voidstar},
+ {"lengthAndRef",uint32},
+ {"buffer",voidstar}
+ });
+}
+
bool
-lldb_private::formatters::NSStringSummaryProvider (ValueObject& valobj, Stream& stream)
+lldb_private::formatters::NSStringSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& summary_options)
{
ProcessSP process_sp = valobj.GetProcessSP();
if (!process_sp)
@@ -1131,8 +886,7 @@ lldb_private::formatters::NSStringSummaryProvider (ValueObject& valobj, Stream&
return false;
if (has_explicit_length && is_unicode)
{
- ReadUTFBufferAndDumpToStreamOptions<UTF16> options;
- options.SetConversionFunction(ConvertUTF16toUTF8);
+ ReadStringAndDumpToStreamOptions options(valobj);
options.SetLocation(location);
options.SetProcessSP(process_sp);
options.SetStream(&stream);
@@ -1140,10 +894,21 @@ lldb_private::formatters::NSStringSummaryProvider (ValueObject& valobj, Stream&
options.SetQuote('"');
options.SetSourceSize(explicit_length);
options.SetNeedsZeroTermination(false);
- return ReadUTFBufferAndDumpToStream (options);
+ options.SetIgnoreMaxLength(summary_options.GetCapping() == TypeSummaryCapping::eTypeSummaryUncapped);
+ return ReadStringAndDumpToStream<StringElementType::UTF16>(options);
}
else
- return ReadAsciiBufferAndDumpToStream(location+1,process_sp,stream, explicit_length);
+ {
+ ReadStringAndDumpToStreamOptions options(valobj);
+ options.SetLocation(location+1);
+ options.SetProcessSP(process_sp);
+ options.SetStream(&stream);
+ options.SetPrefixToken('@');
+ options.SetSourceSize(explicit_length);
+ options.SetNeedsZeroTermination(false);
+ options.SetIgnoreMaxLength(summary_options.GetCapping() == TypeSummaryCapping::eTypeSummaryUncapped);
+ return ReadStringAndDumpToStream<StringElementType::ASCII>(options);
+ }
}
else if (is_inline && has_explicit_length && !is_unicode && !is_special && !is_mutable)
{
@@ -1169,8 +934,7 @@ lldb_private::formatters::NSStringSummaryProvider (ValueObject& valobj, Stream&
if (error.Fail())
return false;
}
- ReadUTFBufferAndDumpToStreamOptions<UTF16> options;
- options.SetConversionFunction(ConvertUTF16toUTF8);
+ ReadStringAndDumpToStreamOptions options(valobj);
options.SetLocation(location);
options.SetProcessSP(process_sp);
options.SetStream(&stream);
@@ -1178,13 +942,16 @@ lldb_private::formatters::NSStringSummaryProvider (ValueObject& valobj, Stream&
options.SetQuote('"');
options.SetSourceSize(explicit_length);
options.SetNeedsZeroTermination(has_explicit_length == false);
- return ReadUTFBufferAndDumpToStream (options);
+ options.SetIgnoreMaxLength(summary_options.GetCapping() == TypeSummaryCapping::eTypeSummaryUncapped);
+ return ReadStringAndDumpToStream<StringElementType::UTF16> (options);
}
else if (is_special)
{
- uint64_t location = valobj_addr + (ptr_size == 8 ? 12 : 8);
- ReadUTFBufferAndDumpToStreamOptions<UTF16> options;
- options.SetConversionFunction(ConvertUTF16toUTF8);
+ ProcessStructReader reader(valobj.GetProcessSP().get(), valobj.GetValueAsUnsigned(0), GetNSPathStore2Type(*valobj.GetTargetSP()));
+ explicit_length = reader.GetField<uint32_t>(ConstString("lengthAndRef")) >> 20;
+ lldb::addr_t location = valobj.GetValueAsUnsigned(0) + ptr_size + 4;
+
+ ReadStringAndDumpToStreamOptions options(valobj);
options.SetLocation(location);
options.SetProcessSP(process_sp);
options.SetStream(&stream);
@@ -1192,14 +959,22 @@ lldb_private::formatters::NSStringSummaryProvider (ValueObject& valobj, Stream&
options.SetQuote('"');
options.SetSourceSize(explicit_length);
options.SetNeedsZeroTermination(has_explicit_length == false);
- return ReadUTFBufferAndDumpToStream (options);
+ options.SetIgnoreMaxLength(summary_options.GetCapping() == TypeSummaryCapping::eTypeSummaryUncapped);
+ return ReadStringAndDumpToStream<StringElementType::UTF16> (options);
}
else if (is_inline)
{
uint64_t location = valobj_addr + 2*ptr_size;
if (!has_explicit_length)
location++;
- return ReadAsciiBufferAndDumpToStream(location,process_sp,stream,explicit_length);
+ ReadStringAndDumpToStreamOptions options(valobj);
+ options.SetLocation(location);
+ options.SetProcessSP(process_sp);
+ options.SetStream(&stream);
+ options.SetPrefixToken('@');
+ options.SetSourceSize(explicit_length);
+ options.SetIgnoreMaxLength(summary_options.GetCapping() == TypeSummaryCapping::eTypeSummaryUncapped);
+ return ReadStringAndDumpToStream<StringElementType::ASCII>(options);
}
else
{
@@ -1209,16 +984,19 @@ lldb_private::formatters::NSStringSummaryProvider (ValueObject& valobj, Stream&
return false;
if (has_explicit_length && !has_null)
explicit_length++; // account for the fact that there is no NULL and we need to have one added
- return ReadAsciiBufferAndDumpToStream(location,process_sp,stream,explicit_length);
+ ReadStringAndDumpToStreamOptions options(valobj);
+ options.SetLocation(location);
+ options.SetProcessSP(process_sp);
+ options.SetPrefixToken('@');
+ options.SetStream(&stream);
+ options.SetSourceSize(explicit_length);
+ options.SetIgnoreMaxLength(summary_options.GetCapping() == TypeSummaryCapping::eTypeSummaryUncapped);
+ return ReadStringAndDumpToStream<StringElementType::ASCII>(options);
}
-
- stream.Printf("class name = %s",class_name);
- return true;
-
}
bool
-lldb_private::formatters::NSAttributedStringSummaryProvider (ValueObject& valobj, Stream& stream)
+lldb_private::formatters::NSAttributedStringSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options)
{
TargetSP target_sp(valobj.GetTargetSP());
if (!target_sp)
@@ -1241,38 +1019,38 @@ lldb_private::formatters::NSAttributedStringSummaryProvider (ValueObject& valobj
ValueObjectSP child_sp(child_ptr_sp->CreateValueObjectFromData("string_data", data, exe_ctx, type));
child_sp->GetValueAsUnsigned(0);
if (child_sp)
- return NSStringSummaryProvider(*child_sp, stream);
+ return NSStringSummaryProvider(*child_sp, stream, options);
return false;
}
bool
-lldb_private::formatters::NSMutableAttributedStringSummaryProvider (ValueObject& valobj, Stream& stream)
+lldb_private::formatters::NSMutableAttributedStringSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options)
{
- return NSAttributedStringSummaryProvider(valobj, stream);
+ return NSAttributedStringSummaryProvider(valobj, stream, options);
}
bool
-lldb_private::formatters::RuntimeSpecificDescriptionSummaryProvider (ValueObject& valobj, Stream& stream)
+lldb_private::formatters::RuntimeSpecificDescriptionSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options)
{
stream.Printf("%s",valobj.GetObjectDescription());
return true;
}
bool
-lldb_private::formatters::ObjCBOOLSummaryProvider (ValueObject& valobj, Stream& stream)
+lldb_private::formatters::ObjCBOOLSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options)
{
const uint32_t type_info = valobj.GetClangType().GetTypeInfo();
ValueObjectSP real_guy_sp = valobj.GetSP();
- if (type_info & ClangASTType::eTypeIsPointer)
+ if (type_info & eTypeIsPointer)
{
Error err;
real_guy_sp = valobj.Dereference(err);
if (err.Fail() || !real_guy_sp)
return false;
}
- else if (type_info & ClangASTType::eTypeIsReference)
+ else if (type_info & eTypeIsReference)
{
real_guy_sp = valobj.GetChildAtIndex(0, true);
if (!real_guy_sp)
@@ -1290,7 +1068,7 @@ lldb_private::formatters::ObjCBOOLSummaryProvider (ValueObject& valobj, Stream&
template <bool is_sel_ptr>
bool
-lldb_private::formatters::ObjCSELSummaryProvider (ValueObject& valobj, Stream& stream)
+lldb_private::formatters::ObjCSELSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options)
{
lldb::ValueObjectSP valobj_sp;
@@ -1398,7 +1176,7 @@ lldb_private::formatters::VectorIteratorSyntheticFrontEnd::Update()
return false;
Error err;
m_exe_ctx_ref = valobj_sp->GetExecutionContextRef();
- m_item_sp = ValueObject::CreateValueObjectFromAddress("item", item_ptr->GetValueAsUnsigned(0), m_exe_ctx_ref, item_ptr->GetClangType().GetPointeeType());
+ m_item_sp = CreateValueObjectFromAddress("item", item_ptr->GetValueAsUnsigned(0), m_exe_ctx_ref, item_ptr->GetClangType().GetPointeeType());
if (err.Fail())
m_item_sp.reset();
return false;
@@ -1437,13 +1215,13 @@ lldb_private::formatters::VectorIteratorSyntheticFrontEnd::~VectorIteratorSynthe
}
template bool
-lldb_private::formatters::NSDataSummaryProvider<true> (ValueObject&, Stream&) ;
+lldb_private::formatters::NSDataSummaryProvider<true> (ValueObject&, Stream&, const TypeSummaryOptions&) ;
template bool
-lldb_private::formatters::NSDataSummaryProvider<false> (ValueObject&, Stream&) ;
+lldb_private::formatters::NSDataSummaryProvider<false> (ValueObject&, Stream&, const TypeSummaryOptions&) ;
template bool
-lldb_private::formatters::ObjCSELSummaryProvider<true> (ValueObject&, Stream&) ;
+lldb_private::formatters::ObjCSELSummaryProvider<true> (ValueObject&, Stream&, const TypeSummaryOptions&) ;
template bool
-lldb_private::formatters::ObjCSELSummaryProvider<false> (ValueObject&, Stream&) ;
+lldb_private::formatters::ObjCSELSummaryProvider<false> (ValueObject&, Stream&, const TypeSummaryOptions&) ;
diff --git a/source/DataFormatters/Cocoa.cpp b/source/DataFormatters/Cocoa.cpp
index 8e92de4ddaa45..137fd4f483ccc 100644
--- a/source/DataFormatters/Cocoa.cpp
+++ b/source/DataFormatters/Cocoa.cpp
@@ -26,7 +26,7 @@ using namespace lldb_private;
using namespace lldb_private::formatters;
bool
-lldb_private::formatters::NSBundleSummaryProvider (ValueObject& valobj, Stream& stream)
+lldb_private::formatters::NSBundleSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options)
{
ProcessSP process_sp = valobj.GetProcessSP();
if (!process_sp)
@@ -60,7 +60,7 @@ lldb_private::formatters::NSBundleSummaryProvider (ValueObject& valobj, Stream&
ValueObjectSP text(valobj.GetSyntheticChildAtOffset(offset, valobj.GetClangType().GetBasicTypeFromAST(lldb::eBasicTypeObjCID), true));
StreamString summary_stream;
- bool was_nsstring_ok = NSStringSummaryProvider(*text.get(), summary_stream);
+ bool was_nsstring_ok = NSStringSummaryProvider(*text.get(), summary_stream, options);
if (was_nsstring_ok && summary_stream.GetSize() > 0)
{
stream.Printf("%s",summary_stream.GetData());
@@ -73,7 +73,7 @@ lldb_private::formatters::NSBundleSummaryProvider (ValueObject& valobj, Stream&
}
bool
-lldb_private::formatters::NSTimeZoneSummaryProvider (ValueObject& valobj, Stream& stream)
+lldb_private::formatters::NSTimeZoneSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options)
{
ProcessSP process_sp = valobj.GetProcessSP();
if (!process_sp)
@@ -106,7 +106,7 @@ lldb_private::formatters::NSTimeZoneSummaryProvider (ValueObject& valobj, Stream
uint64_t offset = ptr_size;
ValueObjectSP text(valobj.GetSyntheticChildAtOffset(offset, valobj.GetClangType(), true));
StreamString summary_stream;
- bool was_nsstring_ok = NSStringSummaryProvider(*text.get(), summary_stream);
+ bool was_nsstring_ok = NSStringSummaryProvider(*text.get(), summary_stream, options);
if (was_nsstring_ok && summary_stream.GetSize() > 0)
{
stream.Printf("%s",summary_stream.GetData());
@@ -117,7 +117,7 @@ lldb_private::formatters::NSTimeZoneSummaryProvider (ValueObject& valobj, Stream
}
bool
-lldb_private::formatters::NSNotificationSummaryProvider (ValueObject& valobj, Stream& stream)
+lldb_private::formatters::NSNotificationSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options)
{
ProcessSP process_sp = valobj.GetProcessSP();
if (!process_sp)
@@ -150,7 +150,7 @@ lldb_private::formatters::NSNotificationSummaryProvider (ValueObject& valobj, St
uint64_t offset = ptr_size;
ValueObjectSP text(valobj.GetSyntheticChildAtOffset(offset, valobj.GetClangType(), true));
StreamString summary_stream;
- bool was_nsstring_ok = NSStringSummaryProvider(*text.get(), summary_stream);
+ bool was_nsstring_ok = NSStringSummaryProvider(*text.get(), summary_stream, options);
if (was_nsstring_ok && summary_stream.GetSize() > 0)
{
stream.Printf("%s",summary_stream.GetData());
@@ -163,7 +163,7 @@ lldb_private::formatters::NSNotificationSummaryProvider (ValueObject& valobj, St
}
bool
-lldb_private::formatters::NSMachPortSummaryProvider (ValueObject& valobj, Stream& stream)
+lldb_private::formatters::NSMachPortSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options)
{
ProcessSP process_sp = valobj.GetProcessSP();
if (!process_sp)
@@ -212,7 +212,7 @@ lldb_private::formatters::NSMachPortSummaryProvider (ValueObject& valobj, Stream
}
bool
-lldb_private::formatters::NSIndexSetSummaryProvider (ValueObject& valobj, Stream& stream)
+lldb_private::formatters::NSIndexSetSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options)
{
ProcessSP process_sp = valobj.GetProcessSP();
if (!process_sp)
@@ -290,7 +290,7 @@ lldb_private::formatters::NSIndexSetSummaryProvider (ValueObject& valobj, Stream
}
bool
-lldb_private::formatters::NSNumberSummaryProvider (ValueObject& valobj, Stream& stream)
+lldb_private::formatters::NSNumberSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options)
{
ProcessSP process_sp = valobj.GetProcessSP();
if (!process_sp)
@@ -413,7 +413,7 @@ lldb_private::formatters::NSNumberSummaryProvider (ValueObject& valobj, Stream&
}
bool
-lldb_private::formatters::NSURLSummaryProvider (ValueObject& valobj, Stream& stream)
+lldb_private::formatters::NSURLSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options)
{
ProcessSP process_sp = valobj.GetProcessSP();
if (!process_sp)
@@ -453,7 +453,7 @@ lldb_private::formatters::NSURLSummaryProvider (ValueObject& valobj, Stream& str
if (text->GetValueAsUnsigned(0) == 0)
return false;
StreamString summary;
- if (!NSStringSummaryProvider(*text, summary))
+ if (!NSStringSummaryProvider(*text, summary, options))
return false;
if (base && base->GetValueAsUnsigned(0))
{
@@ -461,7 +461,7 @@ lldb_private::formatters::NSURLSummaryProvider (ValueObject& valobj, Stream& str
summary.GetString().resize(summary.GetSize()-1);
summary.Printf(" -- ");
StreamString base_summary;
- if (NSURLSummaryProvider(*base, base_summary) && base_summary.GetSize() > 0)
+ if (NSURLSummaryProvider(*base, base_summary, options) && base_summary.GetSize() > 0)
summary.Printf("%s",base_summary.GetSize() > 2 ? base_summary.GetData() + 2 : base_summary.GetData());
}
if (summary.GetSize())
@@ -478,7 +478,7 @@ lldb_private::formatters::NSURLSummaryProvider (ValueObject& valobj, Stream& str
}
bool
-lldb_private::formatters::NSDateSummaryProvider (ValueObject& valobj, Stream& stream)
+lldb_private::formatters::NSDateSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options)
{
ProcessSP process_sp = valobj.GetProcessSP();
if (!process_sp)
@@ -552,7 +552,7 @@ lldb_private::formatters::NSDateSummaryProvider (ValueObject& valobj, Stream& st
// vendor decides to get creative
time_t epoch = GetOSXEpoch();
epoch = epoch + (time_t)date_value;
- tm *tm_date = localtime(&epoch);
+ tm *tm_date = gmtime(&epoch);
if (!tm_date)
return false;
std::string buffer(1024,0);
diff --git a/source/DataFormatters/DataVisualization.cpp b/source/DataFormatters/DataVisualization.cpp
index c2c2206f34492..7ef0be50efe08 100644
--- a/source/DataFormatters/DataVisualization.cpp
+++ b/source/DataFormatters/DataVisualization.cpp
@@ -101,6 +101,18 @@ DataVisualization::GetSyntheticForType (lldb::TypeNameSpecifierImplSP type_sp)
}
#endif
+lldb::TypeValidatorImplSP
+DataVisualization::GetValidator (ValueObject& valobj, lldb::DynamicValueType use_dynamic)
+{
+ return GetFormatManager().GetValidator(valobj, use_dynamic);
+}
+
+lldb::TypeValidatorImplSP
+DataVisualization::GetValidatorForType (lldb::TypeNameSpecifierImplSP type_sp)
+{
+ return GetFormatManager().GetValidatorForType(type_sp);
+}
+
bool
DataVisualization::AnyMatches (ConstString type_name,
TypeCategoryImpl::FormatCategoryItems items,
@@ -184,6 +196,18 @@ DataVisualization::Categories::Disable (const lldb::TypeCategoryImplSP& category
}
void
+DataVisualization::Categories::EnableStar ()
+{
+ GetFormatManager().EnableAllCategories ();
+}
+
+void
+DataVisualization::Categories::DisableStar ()
+{
+ GetFormatManager().DisableAllCategories();
+}
+
+void
DataVisualization::Categories::LoopThrough (FormatManager::CategoryCallback callback, void* callback_baton)
{
GetFormatManager().LoopThroughCategories(callback, callback_baton);
diff --git a/source/DataFormatters/FormatCache.cpp b/source/DataFormatters/FormatCache.cpp
index 3721f182f91e7..aaa4bc1f958ab 100644
--- a/source/DataFormatters/FormatCache.cpp
+++ b/source/DataFormatters/FormatCache.cpp
@@ -25,16 +25,20 @@ FormatCache::Entry::Entry () :
m_format_cached(false),
m_summary_cached(false),
m_synthetic_cached(false),
+m_validator_cached(false),
m_format_sp(),
m_summary_sp(),
-m_synthetic_sp()
+m_synthetic_sp(),
+m_validator_sp()
{}
FormatCache::Entry::Entry (lldb::TypeFormatImplSP format_sp) :
m_summary_cached(false),
m_synthetic_cached(false),
+m_validator_cached(false),
m_summary_sp(),
-m_synthetic_sp()
+m_synthetic_sp(),
+m_validator_sp()
{
SetFormat (format_sp);
}
@@ -42,8 +46,10 @@ m_synthetic_sp()
FormatCache::Entry::Entry (lldb::TypeSummaryImplSP summary_sp) :
m_format_cached(false),
m_synthetic_cached(false),
+m_validator_cached(false),
m_format_sp(),
-m_synthetic_sp()
+m_synthetic_sp(),
+m_validator_sp()
{
SetSummary (summary_sp);
}
@@ -51,17 +57,31 @@ m_synthetic_sp()
FormatCache::Entry::Entry (lldb::SyntheticChildrenSP synthetic_sp) :
m_format_cached(false),
m_summary_cached(false),
+m_validator_cached(false),
m_format_sp(),
-m_summary_sp()
+m_summary_sp(),
+m_validator_sp()
{
SetSynthetic (synthetic_sp);
}
-FormatCache::Entry::Entry (lldb::TypeFormatImplSP format_sp, lldb::TypeSummaryImplSP summary_sp, lldb::SyntheticChildrenSP synthetic_sp)
+FormatCache::Entry::Entry (lldb::TypeValidatorImplSP validator_sp) :
+m_format_cached(false),
+m_summary_cached(false),
+m_synthetic_cached(false),
+m_format_sp(),
+m_summary_sp(),
+m_synthetic_sp()
+{
+ SetValidator (validator_sp);
+}
+
+FormatCache::Entry::Entry (lldb::TypeFormatImplSP format_sp, lldb::TypeSummaryImplSP summary_sp, lldb::SyntheticChildrenSP synthetic_sp, lldb::TypeValidatorImplSP validator_sp)
{
SetFormat (format_sp);
SetSummary (summary_sp);
SetSynthetic (synthetic_sp);
+ SetValidator (validator_sp);
}
bool
@@ -82,6 +102,12 @@ FormatCache::Entry::IsSyntheticCached ()
return m_synthetic_cached;
}
+bool
+FormatCache::Entry::IsValidatorCached ()
+{
+ return m_validator_cached;
+}
+
lldb::TypeFormatImplSP
FormatCache::Entry::GetFormat ()
{
@@ -100,6 +126,12 @@ FormatCache::Entry::GetSynthetic ()
return m_synthetic_sp;
}
+lldb::TypeValidatorImplSP
+FormatCache::Entry::GetValidator ()
+{
+ return m_validator_sp;
+}
+
void
FormatCache::Entry::SetFormat (lldb::TypeFormatImplSP format_sp)
{
@@ -121,6 +153,13 @@ FormatCache::Entry::SetSynthetic (lldb::SyntheticChildrenSP synthetic_sp)
m_synthetic_sp = synthetic_sp;
}
+void
+FormatCache::Entry::SetValidator (lldb::TypeValidatorImplSP validator_sp)
+{
+ m_validator_cached = true;
+ m_validator_sp = validator_sp;
+}
+
FormatCache::FormatCache () :
m_map(),
m_mutex (Mutex::eMutexTypeRecursive)
@@ -201,6 +240,26 @@ FormatCache::GetSynthetic (const ConstString& type,lldb::SyntheticChildrenSP& sy
return false;
}
+bool
+FormatCache::GetValidator (const ConstString& type,lldb::TypeValidatorImplSP& validator_sp)
+{
+ Mutex::Locker lock(m_mutex);
+ auto entry = GetEntry(type);
+ if (entry.IsValidatorCached())
+ {
+#ifdef LLDB_CONFIGURATION_DEBUG
+ m_cache_hits++;
+#endif
+ validator_sp = entry.GetValidator();
+ return true;
+ }
+#ifdef LLDB_CONFIGURATION_DEBUG
+ m_cache_misses++;
+#endif
+ validator_sp.reset();
+ return false;
+}
+
void
FormatCache::SetFormat (const ConstString& type,lldb::TypeFormatImplSP& format_sp)
{
@@ -223,6 +282,13 @@ FormatCache::SetSynthetic (const ConstString& type,lldb::SyntheticChildrenSP& sy
}
void
+FormatCache::SetValidator (const ConstString& type,lldb::TypeValidatorImplSP& validator_sp)
+{
+ Mutex::Locker lock(m_mutex);
+ GetEntry(type).SetValidator(validator_sp);
+}
+
+void
FormatCache::Clear ()
{
Mutex::Locker lock(m_mutex);
diff --git a/source/DataFormatters/FormatManager.cpp b/source/DataFormatters/FormatManager.cpp
index 28d108f2410a3..01799cef5e4ee 100644
--- a/source/DataFormatters/FormatManager.cpp
+++ b/source/DataFormatters/FormatManager.cpp
@@ -447,6 +447,32 @@ FormatManager::GetSyntheticChildrenForType (lldb::TypeNameSpecifierImplSP type_s
}
#endif
+lldb::TypeValidatorImplSP
+FormatManager::GetValidatorForType (lldb::TypeNameSpecifierImplSP type_sp)
+{
+ if (!type_sp)
+ return lldb::TypeValidatorImplSP();
+ lldb::TypeValidatorImplSP validator_chosen_sp;
+ uint32_t num_categories = m_categories_map.GetCount();
+ lldb::TypeCategoryImplSP category_sp;
+ uint32_t prio_category = UINT32_MAX;
+ for (uint32_t category_id = 0;
+ category_id < num_categories;
+ category_id++)
+ {
+ category_sp = GetCategoryAtIndex(category_id);
+ if (category_sp->IsEnabled() == false)
+ continue;
+ lldb::TypeValidatorImplSP validator_current_sp(category_sp->GetValidatorForType(type_sp).get());
+ if (validator_current_sp && (validator_chosen_sp.get() == NULL || (prio_category > category_sp->GetEnabledPosition())))
+ {
+ prio_category = category_sp->GetEnabledPosition();
+ validator_chosen_sp = validator_current_sp;
+ }
+ }
+ return validator_chosen_sp;
+}
+
lldb::TypeCategoryImplSP
FormatManager::GetCategory (const ConstString& category_name,
bool can_create)
@@ -501,10 +527,9 @@ FormatManager::ShouldPrintAsOneLiner (ValueObject& valobj)
if (valobj.GetTargetSP().get() && valobj.GetTargetSP()->GetDebugger().GetAutoOneLineSummaries() == false)
return false; // then don't oneline
- // if this object has a summary, don't try to do anything special to it
- // if the user wants one-liner, they can ask for it in summary :)
+ // if this object has a summary, then ask the summary
if (valobj.GetSummaryFormat().get() != nullptr)
- return false;
+ return valobj.GetSummaryFormat()->IsOneLiner();
// no children, no party
if (valobj.GetNumChildren() == 0)
@@ -516,6 +541,7 @@ FormatManager::ShouldPrintAsOneLiner (ValueObject& valobj)
idx < valobj.GetNumChildren();
idx++)
{
+ bool is_synth_val = false;
ValueObjectSP child_sp(valobj.GetChildAtIndex(idx, true));
// something is wrong here - bail out
if (!child_sp)
@@ -523,7 +549,17 @@ FormatManager::ShouldPrintAsOneLiner (ValueObject& valobj)
// if we decided to define synthetic children for a type, we probably care enough
// to show them, but avoid nesting children in children
if (child_sp->GetSyntheticChildren().get() != nullptr)
- return false;
+ {
+ ValueObjectSP synth_sp(child_sp->GetSyntheticValue());
+ // wait.. wat? just get out of here..
+ if (!synth_sp)
+ return false;
+ // but if we only have them to provide a value, keep going
+ if (synth_sp->MightHaveChildren() == false && synth_sp->DoesProvideSyntheticValue())
+ is_synth_val = true;
+ else
+ return false;
+ }
total_children_name_len += child_sp->GetName().GetLength();
@@ -547,7 +583,7 @@ FormatManager::ShouldPrintAsOneLiner (ValueObject& valobj)
// ...and no summary...
// (if it had a summary and the summary wanted children, we would have bailed out anyway
// so this only makes us bail out if this has no summary and we would then print children)
- if (!child_sp->GetSummaryFormat())
+ if (!child_sp->GetSummaryFormat() && !is_synth_val) // but again only do that if not a synthetic valued child
return false; // then bail out
}
}
@@ -756,6 +792,63 @@ FormatManager::GetSyntheticChildren (ValueObject& valobj,
}
#endif
+lldb::TypeValidatorImplSP
+FormatManager::GetValidator (ValueObject& valobj,
+ lldb::DynamicValueType use_dynamic)
+{
+ TypeValidatorImplSP retval;
+ Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_TYPES));
+ ConstString valobj_type(GetTypeForCache(valobj, use_dynamic));
+ if (valobj_type)
+ {
+ if (log)
+ log->Printf("\n\n[FormatManager::GetValidator] Looking into cache for type %s", valobj_type.AsCString("<invalid>"));
+ if (m_format_cache.GetValidator(valobj_type,retval))
+ {
+ if (log)
+ {
+ log->Printf("[FormatManager::GetValidator] Cache search success. Returning.");
+ if (log->GetDebug())
+ log->Printf("[FormatManager::GetValidator] Cache hits: %" PRIu64 " - Cache Misses: %" PRIu64, m_format_cache.GetCacheHits(), m_format_cache.GetCacheMisses());
+ }
+ return retval;
+ }
+ if (log)
+ log->Printf("[FormatManager::GetValidator] Cache search failed. Going normal route");
+ }
+ retval = m_categories_map.GetValidator(valobj, use_dynamic);
+ if (!retval)
+ {
+ if (log)
+ log->Printf("[FormatManager::GetValidator] Search failed. Giving hardcoded a chance.");
+ retval = GetHardcodedValidator(valobj, use_dynamic);
+ }
+ else if (valobj_type)
+ {
+ if (log)
+ log->Printf("[FormatManager::GetValidator] Caching %p for type %s",
+ static_cast<void*>(retval.get()),
+ valobj_type.AsCString("<invalid>"));
+ m_format_cache.SetValidator(valobj_type,retval);
+ }
+ if (log && log->GetDebug())
+ log->Printf("[FormatManager::GetValidator] Cache hits: %" PRIu64 " - Cache Misses: %" PRIu64, m_format_cache.GetCacheHits(), m_format_cache.GetCacheMisses());
+ return retval;
+}
+
+lldb::TypeValidatorImplSP
+FormatManager::GetHardcodedValidator (ValueObject& valobj,
+ lldb::DynamicValueType use_dynamic)
+{
+ for (const auto& candidate: m_hardcoded_validators)
+ {
+ auto result = candidate(valobj,use_dynamic,*this);
+ if (result)
+ return result;
+ }
+ return nullptr;
+}
+
FormatManager::FormatManager() :
m_format_cache(),
m_named_summaries_map(this),
@@ -773,7 +866,8 @@ FormatManager::FormatManager() :
m_appkit_category_name(ConstString("AppKit")),
m_hardcoded_formats(),
m_hardcoded_summaries(),
- m_hardcoded_synthetics()
+ m_hardcoded_synthetics(),
+ m_hardcoded_validators()
{
LoadSystemFormatters();
@@ -825,6 +919,21 @@ AddStringSummary(TypeCategoryImpl::SharedPointer category_sp,
category_sp->GetTypeSummariesContainer()->Add(type_name, summary_sp);
}
+static void
+AddOneLineSummary (TypeCategoryImpl::SharedPointer category_sp,
+ ConstString type_name,
+ TypeSummaryImpl::Flags flags,
+ bool regex = false)
+{
+ flags.SetShowMembersOneLiner(true);
+ lldb::TypeSummaryImplSP summary_sp(new StringSummaryFormat(flags, ""));
+
+ if (regex)
+ category_sp->GetRegexTypeSummariesContainer()->Add(RegularExpressionSP(new RegularExpression(type_name.AsCString())),summary_sp);
+ else
+ category_sp->GetTypeSummariesContainer()->Add(type_name, summary_sp);
+}
+
#ifndef LLDB_DISABLE_PYTHON
static void
AddCXXSummary (TypeCategoryImpl::SharedPointer category_sp,
@@ -945,13 +1054,6 @@ FormatManager::LoadLibStdcppFormatters()
AddCXXSynthetic(gnu_category_sp, lldb_private::formatters::LibStdcppVectorIteratorSyntheticFrontEndCreator, "std::vector iterator synthetic children", ConstString("^__gnu_cxx::__normal_iterator<.+>$"), stl_synth_flags, true);
AddCXXSynthetic(gnu_category_sp, lldb_private::formatters::LibstdcppMapIteratorSyntheticFrontEndCreator, "std::map iterator synthetic children", ConstString("^std::_Rb_tree_iterator<.+>$"), stl_synth_flags, true);
-
- gnu_category_sp->GetTypeSummariesContainer()->Add(ConstString("std::vector<std::allocator<bool> >"),
- TypeSummaryImplSP(new StringSummaryFormat(stl_summary_flags, "size=${svar%#}")));
-
- gnu_category_sp->GetTypeSyntheticsContainer()->Add(ConstString("std::vector<std::allocator<bool> >"),
- SyntheticChildrenSP(new CXXSyntheticChildren(stl_synth_flags,"libc++ std::vector<bool> synthetic children",lldb_private::formatters::LibstdcppVectorBoolSyntheticFrontEndCreator)));
-
#endif
}
@@ -998,6 +1100,7 @@ FormatManager::LoadLibcxxFormatters()
AddCXXSynthetic(libcxx_category_sp, lldb_private::formatters::LibcxxStdMapSyntheticFrontEndCreator, "libc++ std::multiset synthetic children", ConstString("^std::__1::multiset<.+> >(( )?&)?$"), stl_synth_flags, true);
AddCXXSynthetic(libcxx_category_sp, lldb_private::formatters::LibcxxStdMapSyntheticFrontEndCreator, "libc++ std::multimap synthetic children", ConstString("^std::__1::multimap<.+> >(( )?&)?$"), stl_synth_flags, true);
AddCXXSynthetic(libcxx_category_sp, lldb_private::formatters::LibcxxStdUnorderedMapSyntheticFrontEndCreator, "libc++ std::unordered containers synthetic children", ConstString("^(std::__1::)unordered_(multi)?(map|set)<.+> >$"), stl_synth_flags, true);
+ AddCXXSynthetic(libcxx_category_sp, lldb_private::formatters::LibcxxInitializerListSyntheticFrontEndCreator, "libc++ std::initializer_list synthetic children", ConstString("^std::initializer_list<.+>(( )?&)?$"), stl_synth_flags, true);
libcxx_category_sp->GetRegexTypeSyntheticsContainer()->Add(RegularExpressionSP(new RegularExpression("^(std::__1::)deque<.+>(( )?&)?$")),
SyntheticChildrenSP(new ScriptedSyntheticChildren(stl_synth_flags,
@@ -1124,6 +1227,10 @@ FormatManager::LoadObjCFormatters()
.SetHideItemNames(false);
TypeCategoryImpl::SharedPointer objc_category_sp = GetCategory(m_objc_category_name);
+ TypeCategoryImpl::SharedPointer appkit_category_sp = GetCategory(m_appkit_category_name);
+ TypeCategoryImpl::SharedPointer corefoundation_category_sp = GetCategory(m_corefoundation_category_name);
+ TypeCategoryImpl::SharedPointer coregraphics_category_sp = GetCategory(m_coregraphics_category_name);
+ TypeCategoryImpl::SharedPointer coreservices_category_sp = GetCategory(m_coreservices_category_name);
lldb::TypeSummaryImplSP ObjC_BOOL_summary(new CXXFunctionSummaryFormat(objc_flags, lldb_private::formatters::ObjCBOOLSummaryProvider,""));
objc_category_sp->GetTypeSummariesContainer()->Add(ConstString("BOOL"),
@@ -1159,8 +1266,6 @@ FormatManager::LoadObjCFormatters()
ConstString("__block_literal_generic"),
objc_flags);
- TypeCategoryImpl::SharedPointer corefoundation_category_sp = GetCategory(m_corefoundation_category_name);
-
AddStringSummary(corefoundation_category_sp,
"${var.years} years, ${var.months} months, ${var.days} days, ${var.hours} hours, ${var.minutes} minutes ${var.seconds} seconds",
ConstString("CFGregorianUnits"),
@@ -1169,43 +1274,35 @@ FormatManager::LoadObjCFormatters()
"location=${var.location} length=${var.length}",
ConstString("CFRange"),
objc_flags);
- AddStringSummary(corefoundation_category_sp,
- "(x=${var.x}, y=${var.y})",
- ConstString("NSPoint"),
- objc_flags);
- AddStringSummary(corefoundation_category_sp,
+
+ AddStringSummary(appkit_category_sp,
"location=${var.location}, length=${var.length}",
ConstString("NSRange"),
objc_flags);
- AddStringSummary(corefoundation_category_sp,
- "${var.origin}, ${var.size}",
- ConstString("NSRect"),
- objc_flags);
- AddStringSummary(corefoundation_category_sp,
+ AddStringSummary(appkit_category_sp,
"(${var.origin}, ${var.size}), ...",
ConstString("NSRectArray"),
objc_flags);
- AddStringSummary(objc_category_sp,
- "(width=${var.width}, height=${var.height})",
- ConstString("NSSize"),
- objc_flags);
-
- TypeCategoryImpl::SharedPointer coregraphics_category_sp = GetCategory(m_coregraphics_category_name);
-
- AddStringSummary(coregraphics_category_sp,
- "(width=${var.width}, height=${var.height})",
- ConstString("CGSize"),
- objc_flags);
- AddStringSummary(coregraphics_category_sp,
- "(x=${var.x}, y=${var.y})",
- ConstString("CGPoint"),
- objc_flags);
- AddStringSummary(coregraphics_category_sp,
- "origin=${var.origin} size=${var.size}",
- ConstString("CGRect"),
- objc_flags);
- TypeCategoryImpl::SharedPointer coreservices_category_sp = GetCategory(m_coreservices_category_name);
+ AddOneLineSummary (appkit_category_sp,
+ ConstString("NSPoint"),
+ objc_flags);
+ AddOneLineSummary (appkit_category_sp,
+ ConstString("NSSize"),
+ objc_flags);
+ AddOneLineSummary (appkit_category_sp,
+ ConstString("NSRect"),
+ objc_flags);
+
+ AddOneLineSummary (coregraphics_category_sp,
+ ConstString("CGSize"),
+ objc_flags);
+ AddOneLineSummary (coregraphics_category_sp,
+ ConstString("CGPoint"),
+ objc_flags);
+ AddOneLineSummary (coregraphics_category_sp,
+ ConstString("CGRect"),
+ objc_flags);
AddStringSummary(coreservices_category_sp,
"red=${var.red} green=${var.green} blue=${var.blue}",
@@ -1236,8 +1333,6 @@ FormatManager::LoadObjCFormatters()
ConstString("HIRect"),
objc_flags);
- TypeCategoryImpl::SharedPointer appkit_category_sp = GetCategory(m_appkit_category_name);
-
TypeSummaryImpl::Flags appkit_flags;
appkit_flags.SetCascades(true)
.SetSkipPointers(false)
@@ -1307,6 +1402,8 @@ FormatManager::LoadObjCFormatters()
AddCXXSynthetic(appkit_category_sp, lldb_private::formatters::NSSetSyntheticFrontEndCreator, "NSOrderedSet synthetic children", ConstString("NSOrderedSet"), ScriptedSyntheticChildren::Flags());
AddCXXSynthetic(appkit_category_sp, lldb_private::formatters::NSSetSyntheticFrontEndCreator, "__NSOrderedSetI synthetic children", ConstString("__NSOrderedSetI"), ScriptedSyntheticChildren::Flags());
AddCXXSynthetic(appkit_category_sp, lldb_private::formatters::NSSetSyntheticFrontEndCreator, "__NSOrderedSetM synthetic children", ConstString("__NSOrderedSetM"), ScriptedSyntheticChildren::Flags());
+
+ AddCXXSynthetic(appkit_category_sp, lldb_private::formatters::NSIndexPathSyntheticFrontEndCreator, "NSIndexPath synthetic children", ConstString("NSIndexPath"), ScriptedSyntheticChildren::Flags());
AddCXXSummary(corefoundation_category_sp,lldb_private::formatters::CFBagSummaryProvider, "CFBag summary provider", ConstString("CFBagRef"), appkit_flags);
AddCXXSummary(corefoundation_category_sp,lldb_private::formatters::CFBagSummaryProvider, "CFBag summary provider", ConstString("__CFBag"), appkit_flags);
@@ -1471,8 +1568,22 @@ FormatManager::LoadHardcodedFormatters()
}
{
// insert code to load summaries here
+ m_hardcoded_summaries.push_back(
+ [](lldb_private::ValueObject& valobj,
+ lldb::DynamicValueType,
+ FormatManager&) -> TypeSummaryImpl::SharedPointer {
+ static CXXFunctionSummaryFormat::SharedPointer formatter_sp(new CXXFunctionSummaryFormat(TypeSummaryImpl::Flags(), lldb_private::formatters::FunctionPointerSummaryProvider, "Function pointer summary provider"));
+ if (valobj.GetClangType().IsFunctionPointerType())
+ {
+ return formatter_sp;
+ }
+ return nullptr;
+ });
}
{
// insert code to load synthetics here
}
+ {
+ // insert code to load validators here
+ }
}
diff --git a/source/DataFormatters/LibCxx.cpp b/source/DataFormatters/LibCxx.cpp
index 174202661f039..26bbcf91242f1 100644
--- a/source/DataFormatters/LibCxx.cpp
+++ b/source/DataFormatters/LibCxx.cpp
@@ -27,7 +27,7 @@ using namespace lldb_private;
using namespace lldb_private::formatters;
bool
-lldb_private::formatters::LibcxxSmartPointerSummaryProvider (ValueObject& valobj, Stream& stream)
+lldb_private::formatters::LibcxxSmartPointerSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options)
{
ValueObjectSP valobj_sp(valobj.GetNonSyntheticValue());
if (!valobj_sp)
@@ -143,7 +143,7 @@ lldb_private::formatters::LibcxxVectorBoolSyntheticFrontEnd::GetChildAtIndex (si
if (bit_set && buffer_sp && buffer_sp->GetBytes())
*(buffer_sp->GetBytes()) = 1; // regardless of endianness, anything non-zero is true
StreamString name; name.Printf("[%" PRIu64 "]", (uint64_t)idx);
- ValueObjectSP retval_sp(ValueObject::CreateValueObjectFromData(name.GetData(), DataExtractor(buffer_sp, process_sp->GetByteOrder(), process_sp->GetAddressByteSize()), m_exe_ctx_ref, m_bool_type));
+ ValueObjectSP retval_sp(CreateValueObjectFromData(name.GetData(), DataExtractor(buffer_sp, process_sp->GetByteOrder(), process_sp->GetAddressByteSize()), m_exe_ctx_ref, m_bool_type));
if (retval_sp)
m_children[idx] = retval_sp;
return retval_sp;
@@ -378,7 +378,7 @@ lldb_private::formatters::LibcxxSharedPtrSyntheticFrontEnd::GetChildAtIndex (siz
return lldb::ValueObjectSP();
uint64_t count = 1 + shared_owners_sp->GetValueAsUnsigned(0);
DataExtractor data(&count, 8, m_byte_order, m_ptr_size);
- m_count_sp = ValueObject::CreateValueObjectFromData("count", data, valobj_sp->GetExecutionContextRef(), shared_owners_sp->GetClangType());
+ m_count_sp = CreateValueObjectFromData("count", data, valobj_sp->GetExecutionContextRef(), shared_owners_sp->GetClangType());
}
return m_count_sp;
}
@@ -391,7 +391,7 @@ lldb_private::formatters::LibcxxSharedPtrSyntheticFrontEnd::GetChildAtIndex (siz
return lldb::ValueObjectSP();
uint64_t count = 1 + shared_weak_owners_sp->GetValueAsUnsigned(0);
DataExtractor data(&count, 8, m_byte_order, m_ptr_size);
- m_weak_count_sp = ValueObject::CreateValueObjectFromData("count", data, valobj_sp->GetExecutionContextRef(), shared_weak_owners_sp->GetClangType());
+ m_weak_count_sp = CreateValueObjectFromData("count", data, valobj_sp->GetExecutionContextRef(), shared_weak_owners_sp->GetClangType());
}
return m_weak_count_sp;
}
@@ -450,111 +450,8 @@ lldb_private::formatters::LibcxxSharedPtrSyntheticFrontEndCreator (CXXSyntheticC
return (new LibcxxSharedPtrSyntheticFrontEnd(valobj_sp));
}
-lldb_private::formatters::LibcxxStdVectorSyntheticFrontEnd::LibcxxStdVectorSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp) :
- SyntheticChildrenFrontEnd(*valobj_sp.get()),
- m_start(NULL),
- m_finish(NULL),
- m_element_type(),
- m_element_size(0),
- m_children()
-{
- if (valobj_sp)
- Update();
-}
-
-size_t
-lldb_private::formatters::LibcxxStdVectorSyntheticFrontEnd::CalculateNumChildren ()
-{
- if (!m_start || !m_finish)
- return 0;
- uint64_t start_val = m_start->GetValueAsUnsigned(0);
- uint64_t finish_val = m_finish->GetValueAsUnsigned(0);
-
- if (start_val == 0 || finish_val == 0)
- return 0;
-
- if (start_val >= finish_val)
- return 0;
-
- size_t num_children = (finish_val - start_val);
- if (num_children % m_element_size)
- return 0;
- return num_children/m_element_size;
-}
-
-lldb::ValueObjectSP
-lldb_private::formatters::LibcxxStdVectorSyntheticFrontEnd::GetChildAtIndex (size_t idx)
-{
- if (!m_start || !m_finish)
- return lldb::ValueObjectSP();
-
- auto cached = m_children.find(idx);
- if (cached != m_children.end())
- return cached->second;
-
- uint64_t offset = idx * m_element_size;
- offset = offset + m_start->GetValueAsUnsigned(0);
- StreamString name;
- name.Printf("[%" PRIu64 "]", (uint64_t)idx);
- ValueObjectSP child_sp = ValueObject::CreateValueObjectFromAddress(name.GetData(), offset, m_backend.GetExecutionContextRef(), m_element_type);
- m_children[idx] = child_sp;
- return child_sp;
-}
-
-bool
-lldb_private::formatters::LibcxxStdVectorSyntheticFrontEnd::Update()
-{
- m_start = m_finish = NULL;
- m_children.clear();
- ValueObjectSP data_type_finder_sp(m_backend.GetChildMemberWithName(ConstString("__end_cap_"),true));
- if (!data_type_finder_sp)
- return false;
- data_type_finder_sp = data_type_finder_sp->GetChildMemberWithName(ConstString("__first_"),true);
- if (!data_type_finder_sp)
- return false;
- m_element_type = data_type_finder_sp->GetClangType().GetPointeeType();
- m_element_size = m_element_type.GetByteSize();
-
- if (m_element_size > 0)
- {
- // store raw pointers or end up with a circular dependency
- m_start = m_backend.GetChildMemberWithName(ConstString("__begin_"),true).get();
- m_finish = m_backend.GetChildMemberWithName(ConstString("__end_"),true).get();
- }
- return false;
-}
-
-bool
-lldb_private::formatters::LibcxxStdVectorSyntheticFrontEnd::MightHaveChildren ()
-{
- return true;
-}
-
-size_t
-lldb_private::formatters::LibcxxStdVectorSyntheticFrontEnd::GetIndexOfChildWithName (const ConstString &name)
-{
- if (!m_start || !m_finish)
- return UINT32_MAX;
- return ExtractIndexFromString(name.GetCString());
-}
-
-lldb_private::formatters::LibcxxStdVectorSyntheticFrontEnd::~LibcxxStdVectorSyntheticFrontEnd ()
-{
- // these need to stay around because they are child objects who will follow their parent's life cycle
- // delete m_start;
- // delete m_finish;
-}
-
-SyntheticChildrenFrontEnd*
-lldb_private::formatters::LibcxxStdVectorSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP valobj_sp)
-{
- if (!valobj_sp)
- return NULL;
- return (new LibcxxStdVectorSyntheticFrontEnd(valobj_sp));
-}
-
bool
-lldb_private::formatters::LibcxxContainerSummaryProvider (ValueObject& valobj, Stream& stream)
+lldb_private::formatters::LibcxxContainerSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options)
{
if (valobj.IsPointerType())
{
diff --git a/source/DataFormatters/LibCxxInitializerList.cpp b/source/DataFormatters/LibCxxInitializerList.cpp
new file mode 100644
index 0000000000000..e76b0bec95ce2
--- /dev/null
+++ b/source/DataFormatters/LibCxxInitializerList.cpp
@@ -0,0 +1,145 @@
+//===-- LibCxxInitializerList.cpp ----------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "lldb/lldb-python.h"
+
+#include "lldb/DataFormatters/CXXFormatterFunctions.h"
+
+#include "lldb/Core/ConstString.h"
+#include "lldb/Core/ValueObject.h"
+
+using namespace lldb;
+using namespace lldb_private;
+using namespace lldb_private::formatters;
+
+namespace lldb_private {
+ namespace formatters {
+ class LibcxxInitializerListSyntheticFrontEnd : public SyntheticChildrenFrontEnd
+ {
+ public:
+ LibcxxInitializerListSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp);
+
+ virtual size_t
+ CalculateNumChildren ();
+
+ virtual lldb::ValueObjectSP
+ GetChildAtIndex (size_t idx);
+
+ virtual bool
+ Update();
+
+ virtual bool
+ MightHaveChildren ();
+
+ virtual size_t
+ GetIndexOfChildWithName (const ConstString &name);
+
+ virtual
+ ~LibcxxInitializerListSyntheticFrontEnd ();
+ private:
+ ValueObject* m_start;
+ ClangASTType m_element_type;
+ uint32_t m_element_size;
+ size_t m_num_elements;
+ std::map<size_t,lldb::ValueObjectSP> m_children;
+ };
+ }
+}
+
+lldb_private::formatters::LibcxxInitializerListSyntheticFrontEnd::LibcxxInitializerListSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp) :
+SyntheticChildrenFrontEnd(*valobj_sp.get()),
+m_start(NULL),
+m_element_type(),
+m_element_size(0),
+m_num_elements(0),
+m_children()
+{
+ if (valobj_sp)
+ Update();
+}
+
+size_t
+lldb_private::formatters::LibcxxInitializerListSyntheticFrontEnd::CalculateNumChildren ()
+{
+ static ConstString g___size_("__size_");
+ m_num_elements = 0;
+ ValueObjectSP size_sp(m_backend.GetChildMemberWithName(g___size_, true));
+ if (size_sp)
+ m_num_elements = size_sp->GetValueAsUnsigned(0);
+ return m_num_elements;
+}
+
+lldb::ValueObjectSP
+lldb_private::formatters::LibcxxInitializerListSyntheticFrontEnd::GetChildAtIndex (size_t idx)
+{
+ if (!m_start)
+ return lldb::ValueObjectSP();
+
+ auto cached = m_children.find(idx);
+ if (cached != m_children.end())
+ return cached->second;
+
+ uint64_t offset = idx * m_element_size;
+ offset = offset + m_start->GetValueAsUnsigned(0);
+ StreamString name;
+ name.Printf("[%" PRIu64 "]", (uint64_t)idx);
+ ValueObjectSP child_sp = CreateValueObjectFromAddress(name.GetData(), offset, m_backend.GetExecutionContextRef(), m_element_type);
+ m_children[idx] = child_sp;
+ return child_sp;
+}
+
+bool
+lldb_private::formatters::LibcxxInitializerListSyntheticFrontEnd::Update()
+{
+ static ConstString g___begin_("__begin_");
+
+ m_start = nullptr;
+ m_num_elements = 0;
+ m_children.clear();
+ lldb::TemplateArgumentKind kind;
+ m_element_type = m_backend.GetClangType().GetTemplateArgument(0, kind);
+ if (kind != lldb::eTemplateArgumentKindType || false == m_element_type.IsValid())
+ return false;
+
+ m_element_size = m_element_type.GetByteSize();
+
+ if (m_element_size > 0)
+ m_start = m_backend.GetChildMemberWithName(g___begin_,true).get(); // store raw pointers or end up with a circular dependency
+
+ return false;
+}
+
+bool
+lldb_private::formatters::LibcxxInitializerListSyntheticFrontEnd::MightHaveChildren ()
+{
+ return true;
+}
+
+size_t
+lldb_private::formatters::LibcxxInitializerListSyntheticFrontEnd::GetIndexOfChildWithName (const ConstString &name)
+{
+ if (!m_start)
+ return UINT32_MAX;
+ return ExtractIndexFromString(name.GetCString());
+}
+
+lldb_private::formatters::LibcxxInitializerListSyntheticFrontEnd::~LibcxxInitializerListSyntheticFrontEnd ()
+{
+ // this needs to stay around because it's a child object who will follow its parent's life cycle
+ // delete m_start;
+}
+
+lldb_private::SyntheticChildrenFrontEnd*
+lldb_private::formatters::LibcxxInitializerListSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP valobj_sp)
+{
+ if (!valobj_sp)
+ return NULL;
+ return (new LibcxxInitializerListSyntheticFrontEnd(valobj_sp));
+}
+
diff --git a/source/DataFormatters/LibCxxList.cpp b/source/DataFormatters/LibCxxList.cpp
index 7d6db1a0ccd44..5bb6ce07480f5 100644
--- a/source/DataFormatters/LibCxxList.cpp
+++ b/source/DataFormatters/LibCxxList.cpp
@@ -25,6 +25,47 @@ using namespace lldb;
using namespace lldb_private;
using namespace lldb_private::formatters;
+namespace lldb_private {
+ namespace formatters {
+ class LibcxxStdListSyntheticFrontEnd : public SyntheticChildrenFrontEnd
+ {
+ public:
+ LibcxxStdListSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp);
+
+ virtual size_t
+ CalculateNumChildren ();
+
+ virtual lldb::ValueObjectSP
+ GetChildAtIndex (size_t idx);
+
+ virtual bool
+ Update();
+
+ virtual bool
+ MightHaveChildren ();
+
+ virtual size_t
+ GetIndexOfChildWithName (const ConstString &name);
+
+ virtual
+ ~LibcxxStdListSyntheticFrontEnd ();
+ private:
+ bool
+ HasLoop(size_t);
+
+ size_t m_list_capping_size;
+ static const bool g_use_loop_detect = true;
+ size_t m_loop_detected;
+ lldb::addr_t m_node_address;
+ ValueObject* m_head;
+ ValueObject* m_tail;
+ ClangASTType m_element_type;
+ size_t m_count;
+ std::map<size_t,lldb::ValueObjectSP> m_children;
+ };
+ }
+}
+
class ListEntry
{
public:
@@ -150,6 +191,7 @@ private:
lldb_private::formatters::LibcxxStdListSyntheticFrontEnd::LibcxxStdListSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp) :
SyntheticChildrenFrontEnd(*valobj_sp.get()),
m_list_capping_size(0),
+m_loop_detected(0),
m_node_address(),
m_head(NULL),
m_tail(NULL),
@@ -162,14 +204,15 @@ m_children()
}
bool
-lldb_private::formatters::LibcxxStdListSyntheticFrontEnd::HasLoop()
+lldb_private::formatters::LibcxxStdListSyntheticFrontEnd::HasLoop(size_t count)
{
if (g_use_loop_detect == false)
return false;
// don't bother checking for a loop if we won't actually need to jump nodes
if (m_count < 2)
return false;
- auto steps_left = m_count;
+ auto steps_left = std::min(count,m_count);
+ auto steps_left_save = steps_left;
ListEntry slow(m_head);
ListEntry fast(m_head);
while (steps_left-- > 0)
@@ -185,6 +228,7 @@ lldb_private::formatters::LibcxxStdListSyntheticFrontEnd::HasLoop()
if (slow == fast)
return true;
}
+ m_loop_detected = steps_left_save;
return false;
}
@@ -206,9 +250,7 @@ lldb_private::formatters::LibcxxStdListSyntheticFrontEnd::CalculateNumChildren (
}
if (m_count != UINT32_MAX)
{
- if (!HasLoop())
- return m_count;
- return m_count = 0;
+ return m_count;
}
else
{
@@ -220,8 +262,6 @@ lldb_private::formatters::LibcxxStdListSyntheticFrontEnd::CalculateNumChildren (
return 0;
if (next_val == prev_val)
return 1;
- if (HasLoop())
- return 0;
uint64_t size = 2;
ListEntry current(m_head);
while (current.next() && current.next().value() != m_node_address)
@@ -248,6 +288,10 @@ lldb_private::formatters::LibcxxStdListSyntheticFrontEnd::GetChildAtIndex (size_
if (cached != m_children.end())
return cached->second;
+ if (m_loop_detected <= idx)
+ if (HasLoop(idx))
+ return lldb::ValueObjectSP();
+
ListIterator current(m_head);
ValueObjectSP current_sp(current.advance(idx));
if (!current_sp)
@@ -264,7 +308,7 @@ lldb_private::formatters::LibcxxStdListSyntheticFrontEnd::GetChildAtIndex (size_
StreamString name;
name.Printf("[%" PRIu64 "]", (uint64_t)idx);
- return (m_children[idx] = ValueObject::CreateValueObjectFromData(name.GetData(), data, m_backend.GetExecutionContextRef(), m_element_type));
+ return (m_children[idx] = CreateValueObjectFromData(name.GetData(), data, m_backend.GetExecutionContextRef(), m_element_type));
}
bool
@@ -273,6 +317,7 @@ lldb_private::formatters::LibcxxStdListSyntheticFrontEnd::Update()
m_head = m_tail = NULL;
m_node_address = 0;
m_count = UINT32_MAX;
+ m_loop_detected = false;
Error err;
ValueObjectSP backend_addr(m_backend.AddressOf(err));
m_list_capping_size = 0;
diff --git a/source/DataFormatters/LibCxxMap.cpp b/source/DataFormatters/LibCxxMap.cpp
index e665f29622d81..82e747e2db088 100644
--- a/source/DataFormatters/LibCxxMap.cpp
+++ b/source/DataFormatters/LibCxxMap.cpp
@@ -25,40 +25,84 @@ using namespace lldb;
using namespace lldb_private;
using namespace lldb_private::formatters;
+namespace lldb_private {
+ namespace formatters {
+ class LibcxxStdMapSyntheticFrontEnd : public SyntheticChildrenFrontEnd
+ {
+ public:
+ LibcxxStdMapSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp);
+
+ virtual size_t
+ CalculateNumChildren ();
+
+ virtual lldb::ValueObjectSP
+ GetChildAtIndex (size_t idx);
+
+ virtual bool
+ Update();
+
+ virtual bool
+ MightHaveChildren ();
+
+ virtual size_t
+ GetIndexOfChildWithName (const ConstString &name);
+
+ virtual
+ ~LibcxxStdMapSyntheticFrontEnd ();
+ private:
+ bool
+ GetDataType();
+
+ void
+ GetValueOffset (const lldb::ValueObjectSP& node);
+
+ ValueObject* m_tree;
+ ValueObject* m_root_node;
+ ClangASTType m_element_type;
+ uint32_t m_skip_size;
+ size_t m_count;
+ std::map<size_t,lldb::ValueObjectSP> m_children;
+ };
+ }
+}
+
class MapEntry
{
public:
MapEntry () {}
- MapEntry (ValueObjectSP entry_sp) : m_entry_sp(entry_sp) {}
+ explicit MapEntry (ValueObjectSP entry_sp) : m_entry_sp(entry_sp) {}
MapEntry (const MapEntry& rhs) : m_entry_sp(rhs.m_entry_sp) {}
- MapEntry (ValueObject* entry) : m_entry_sp(entry ? entry->GetSP() : ValueObjectSP()) {}
+ explicit MapEntry (ValueObject* entry) : m_entry_sp(entry ? entry->GetSP() : ValueObjectSP()) {}
ValueObjectSP
- left ()
+ left () const
{
+ static ConstString g_left("__left_");
if (!m_entry_sp)
return m_entry_sp;
- return m_entry_sp->GetChildMemberWithName(ConstString("__left_"), true);
+ return m_entry_sp->GetChildMemberWithName(g_left, true);
}
ValueObjectSP
- right ()
+ right () const
{
+ static ConstString g_right("__right_");
if (!m_entry_sp)
return m_entry_sp;
- return m_entry_sp->GetChildMemberWithName(ConstString("__right_"), true);
+ return m_entry_sp->GetChildMemberWithName(g_right, true);
}
ValueObjectSP
- parent ()
+ parent () const
{
+ static ConstString g_parent("__parent_");
if (!m_entry_sp)
return m_entry_sp;
- return m_entry_sp->GetChildMemberWithName(ConstString("__parent_"), true);
+ return m_entry_sp->GetChildMemberWithName(g_parent, true);
}
uint64_t
- value ()
+ value () const
{
if (!m_entry_sp)
return 0;
@@ -66,7 +110,7 @@ public:
}
bool
- error ()
+ error () const
{
if (!m_entry_sp)
return true;
@@ -74,13 +118,13 @@ public:
}
bool
- null()
+ null() const
{
return (value() == 0);
}
ValueObjectSP
- GetEntry ()
+ GetEntry () const
{
return m_entry_sp;
}
@@ -119,27 +163,18 @@ public:
ValueObjectSP
advance (size_t count)
{
+ ValueObjectSP fail(nullptr);
if (m_error)
- return lldb::ValueObjectSP();
- if (count == 0)
- return m_entry.GetEntry();
- if (count == 1)
- {
- next ();
- return m_entry.GetEntry();
- }
+ return fail;
size_t steps = 0;
while (count > 0)
{
- if (m_error)
- return lldb::ValueObjectSP();
- next ();
- count--;
- if (m_entry.null())
- return lldb::ValueObjectSP();
- steps++;
- if (steps > m_max_depth)
- return lldb::ValueObjectSP();
+ next();
+ count--, steps++;
+ if (m_error ||
+ m_entry.null() ||
+ (steps > m_max_depth))
+ return fail;
}
return m_entry.GetEntry();
}
@@ -147,16 +182,39 @@ protected:
void
next ()
{
- m_entry.SetEntry(increment(m_entry.GetEntry()));
+ if (m_entry.null())
+ return;
+ MapEntry right(m_entry.right());
+ if (right.null() == false)
+ {
+ m_entry = tree_min(std::move(right));
+ return;
+ }
+ size_t steps = 0;
+ while (!is_left_child(m_entry))
+ {
+ if (m_entry.error())
+ {
+ m_error = true;
+ return;
+ }
+ m_entry.SetEntry(m_entry.parent());
+ steps++;
+ if (steps > m_max_depth)
+ {
+ m_entry = MapEntry();
+ return;
+ }
+ }
+ m_entry = MapEntry(m_entry.parent());
}
private:
- ValueObjectSP
- tree_min (ValueObjectSP x_sp)
+ MapEntry
+ tree_min (MapEntry&& x)
{
- MapEntry x(x_sp);
if (x.null())
- return ValueObjectSP();
+ return MapEntry();
MapEntry left(x.left());
size_t steps = 0;
while (left.null() == false)
@@ -164,42 +222,20 @@ private:
if (left.error())
{
m_error = true;
- return lldb::ValueObjectSP();
+ return MapEntry();
}
- x.SetEntry(left.GetEntry());
+ x = left;
left.SetEntry(x.left());
steps++;
if (steps > m_max_depth)
- return lldb::ValueObjectSP();
- }
- return x.GetEntry();
- }
-
- ValueObjectSP
- tree_max (ValueObjectSP x_sp)
- {
- MapEntry x(x_sp);
- if (x.null())
- return ValueObjectSP();
- MapEntry right(x.right());
- size_t steps = 0;
- while (right.null() == false)
- {
- if (right.error())
- return lldb::ValueObjectSP();
- x.SetEntry(right.GetEntry());
- right.SetEntry(x.right());
- steps++;
- if (steps > m_max_depth)
- return lldb::ValueObjectSP();
+ return MapEntry();
}
- return x.GetEntry();
+ return x;
}
-
+
bool
- is_left_child (ValueObjectSP x_sp)
+ is_left_child (const MapEntry& x)
{
- MapEntry x(x_sp);
if (x.null())
return false;
MapEntry rhs(x.parent());
@@ -207,31 +243,6 @@ private:
return x.value() == rhs.value();
}
- ValueObjectSP
- increment (ValueObjectSP x_sp)
- {
- MapEntry node(x_sp);
- if (node.null())
- return ValueObjectSP();
- MapEntry right(node.right());
- if (right.null() == false)
- return tree_min(right.GetEntry());
- size_t steps = 0;
- while (!is_left_child(node.GetEntry()))
- {
- if (node.error())
- {
- m_error = true;
- return lldb::ValueObjectSP();
- }
- node.SetEntry(node.parent());
- steps++;
- if (steps > m_max_depth)
- return lldb::ValueObjectSP();
- }
- return node.parent();
- }
-
MapEntry m_entry;
size_t m_max_depth;
bool m_error;
@@ -302,6 +313,10 @@ lldb_private::formatters::LibcxxStdMapSyntheticFrontEnd::GetValueOffset (const l
lldb::ValueObjectSP
lldb_private::formatters::LibcxxStdMapSyntheticFrontEnd::GetChildAtIndex (size_t idx)
{
+ static ConstString g___cc("__cc");
+ static ConstString g___nc("__nc");
+
+
if (idx >= CalculateNumChildren())
return lldb::ValueObjectSP();
if (m_tree == NULL || m_root_node == NULL)
@@ -375,7 +390,31 @@ lldb_private::formatters::LibcxxStdMapSyntheticFrontEnd::GetChildAtIndex (size_t
}
StreamString name;
name.Printf("[%" PRIu64 "]", (uint64_t)idx);
- return (m_children[idx] = ValueObject::CreateValueObjectFromData(name.GetData(), data, m_backend.GetExecutionContextRef(), m_element_type));
+ auto potential_child_sp = CreateValueObjectFromData(name.GetData(), data, m_backend.GetExecutionContextRef(), m_element_type);
+ if (potential_child_sp)
+ {
+ switch (potential_child_sp->GetNumChildren())
+ {
+ case 1:
+ {
+ auto child0_sp = potential_child_sp->GetChildAtIndex(0, true);
+ if (child0_sp && child0_sp->GetName() == g___cc)
+ potential_child_sp = child0_sp;
+ break;
+ }
+ case 2:
+ {
+ auto child0_sp = potential_child_sp->GetChildAtIndex(0, true);
+ auto child1_sp = potential_child_sp->GetChildAtIndex(1, true);
+ if (child0_sp && child0_sp->GetName() == g___cc &&
+ child1_sp && child1_sp->GetName() == g___nc)
+ potential_child_sp = child0_sp;
+ break;
+ }
+ }
+ potential_child_sp->SetName(ConstString(name.GetData()));
+ }
+ return (m_children[idx] = potential_child_sp);
}
bool
diff --git a/source/DataFormatters/LibCxxUnorderedMap.cpp b/source/DataFormatters/LibCxxUnorderedMap.cpp
index bf68f20955b54..da2a88966f5ed 100644
--- a/source/DataFormatters/LibCxxUnorderedMap.cpp
+++ b/source/DataFormatters/LibCxxUnorderedMap.cpp
@@ -25,6 +25,41 @@ using namespace lldb;
using namespace lldb_private;
using namespace lldb_private::formatters;
+namespace lldb_private {
+ namespace formatters {
+ class LibcxxStdUnorderedMapSyntheticFrontEnd : public SyntheticChildrenFrontEnd
+ {
+ public:
+ LibcxxStdUnorderedMapSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp);
+
+ virtual size_t
+ CalculateNumChildren ();
+
+ virtual lldb::ValueObjectSP
+ GetChildAtIndex (size_t idx);
+
+ virtual bool
+ Update();
+
+ virtual bool
+ MightHaveChildren ();
+
+ virtual size_t
+ GetIndexOfChildWithName (const ConstString &name);
+
+ virtual
+ ~LibcxxStdUnorderedMapSyntheticFrontEnd ();
+ private:
+
+ ValueObject* m_tree;
+ size_t m_num_elements;
+ ValueObject* m_next_element;
+ std::map<size_t,lldb::ValueObjectSP> m_children;
+ std::vector<std::pair<ValueObject*, uint64_t> > m_elements_cache;
+ };
+ }
+}
+
lldb_private::formatters::LibcxxStdUnorderedMapSyntheticFrontEnd::LibcxxStdUnorderedMapSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp) :
SyntheticChildrenFrontEnd(*valobj_sp.get()),
m_tree(NULL),
diff --git a/source/DataFormatters/LibCxxVector.cpp b/source/DataFormatters/LibCxxVector.cpp
new file mode 100644
index 0000000000000..26c62afbed2b9
--- /dev/null
+++ b/source/DataFormatters/LibCxxVector.cpp
@@ -0,0 +1,157 @@
+//===-- LibCxxVector.cpp -----------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "lldb/lldb-python.h"
+
+#include "lldb/DataFormatters/CXXFormatterFunctions.h"
+
+#include "lldb/Core/ConstString.h"
+#include "lldb/Core/ValueObject.h"
+
+using namespace lldb;
+using namespace lldb_private;
+using namespace lldb_private::formatters;
+
+namespace lldb_private {
+ namespace formatters {
+ class LibcxxStdVectorSyntheticFrontEnd : public SyntheticChildrenFrontEnd
+ {
+ public:
+ LibcxxStdVectorSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp);
+
+ virtual size_t
+ CalculateNumChildren ();
+
+ virtual lldb::ValueObjectSP
+ GetChildAtIndex (size_t idx);
+
+ virtual bool
+ Update();
+
+ virtual bool
+ MightHaveChildren ();
+
+ virtual size_t
+ GetIndexOfChildWithName (const ConstString &name);
+
+ virtual
+ ~LibcxxStdVectorSyntheticFrontEnd ();
+ private:
+ ValueObject* m_start;
+ ValueObject* m_finish;
+ ClangASTType m_element_type;
+ uint32_t m_element_size;
+ std::map<size_t,lldb::ValueObjectSP> m_children;
+ };
+ }
+}
+
+lldb_private::formatters::LibcxxStdVectorSyntheticFrontEnd::LibcxxStdVectorSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp) :
+SyntheticChildrenFrontEnd(*valobj_sp.get()),
+m_start(NULL),
+m_finish(NULL),
+m_element_type(),
+m_element_size(0),
+m_children()
+{
+ if (valobj_sp)
+ Update();
+}
+
+size_t
+lldb_private::formatters::LibcxxStdVectorSyntheticFrontEnd::CalculateNumChildren ()
+{
+ if (!m_start || !m_finish)
+ return 0;
+ uint64_t start_val = m_start->GetValueAsUnsigned(0);
+ uint64_t finish_val = m_finish->GetValueAsUnsigned(0);
+
+ if (start_val == 0 || finish_val == 0)
+ return 0;
+
+ if (start_val >= finish_val)
+ return 0;
+
+ size_t num_children = (finish_val - start_val);
+ if (num_children % m_element_size)
+ return 0;
+ return num_children/m_element_size;
+}
+
+lldb::ValueObjectSP
+lldb_private::formatters::LibcxxStdVectorSyntheticFrontEnd::GetChildAtIndex (size_t idx)
+{
+ if (!m_start || !m_finish)
+ return lldb::ValueObjectSP();
+
+ auto cached = m_children.find(idx);
+ if (cached != m_children.end())
+ return cached->second;
+
+ uint64_t offset = idx * m_element_size;
+ offset = offset + m_start->GetValueAsUnsigned(0);
+ StreamString name;
+ name.Printf("[%" PRIu64 "]", (uint64_t)idx);
+ ValueObjectSP child_sp = CreateValueObjectFromAddress(name.GetData(), offset, m_backend.GetExecutionContextRef(), m_element_type);
+ m_children[idx] = child_sp;
+ return child_sp;
+}
+
+bool
+lldb_private::formatters::LibcxxStdVectorSyntheticFrontEnd::Update()
+{
+ m_start = m_finish = NULL;
+ m_children.clear();
+ ValueObjectSP data_type_finder_sp(m_backend.GetChildMemberWithName(ConstString("__end_cap_"),true));
+ if (!data_type_finder_sp)
+ return false;
+ data_type_finder_sp = data_type_finder_sp->GetChildMemberWithName(ConstString("__first_"),true);
+ if (!data_type_finder_sp)
+ return false;
+ m_element_type = data_type_finder_sp->GetClangType().GetPointeeType();
+ m_element_size = m_element_type.GetByteSize();
+
+ if (m_element_size > 0)
+ {
+ // store raw pointers or end up with a circular dependency
+ m_start = m_backend.GetChildMemberWithName(ConstString("__begin_"),true).get();
+ m_finish = m_backend.GetChildMemberWithName(ConstString("__end_"),true).get();
+ }
+ return false;
+}
+
+bool
+lldb_private::formatters::LibcxxStdVectorSyntheticFrontEnd::MightHaveChildren ()
+{
+ return true;
+}
+
+size_t
+lldb_private::formatters::LibcxxStdVectorSyntheticFrontEnd::GetIndexOfChildWithName (const ConstString &name)
+{
+ if (!m_start || !m_finish)
+ return UINT32_MAX;
+ return ExtractIndexFromString(name.GetCString());
+}
+
+lldb_private::formatters::LibcxxStdVectorSyntheticFrontEnd::~LibcxxStdVectorSyntheticFrontEnd ()
+{
+ // these need to stay around because they are child objects who will follow their parent's life cycle
+ // delete m_start;
+ // delete m_finish;
+}
+
+lldb_private::SyntheticChildrenFrontEnd*
+lldb_private::formatters::LibcxxStdVectorSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP valobj_sp)
+{
+ if (!valobj_sp)
+ return NULL;
+ return (new LibcxxStdVectorSyntheticFrontEnd(valobj_sp));
+}
+
diff --git a/source/DataFormatters/LibStdcpp.cpp b/source/DataFormatters/LibStdcpp.cpp
index f2d617323cca5..b8f031ceeb2fd 100644
--- a/source/DataFormatters/LibStdcpp.cpp
+++ b/source/DataFormatters/LibStdcpp.cpp
@@ -276,7 +276,7 @@ lldb_private::formatters::LibstdcppMapIteratorSyntheticFrontEnd::GetChildAtIndex
if (m_pair_address != 0 && m_pair_type)
{
if (!m_pair_sp)
- m_pair_sp = ValueObject::CreateValueObjectFromAddress("pair", m_pair_address, m_exe_ctx_ref, m_pair_type);
+ m_pair_sp = CreateValueObjectFromAddress("pair", m_pair_address, m_exe_ctx_ref, m_pair_type);
if (m_pair_sp)
return m_pair_sp->GetChildAtIndex(idx, true);
}
diff --git a/source/DataFormatters/NSArray.cpp b/source/DataFormatters/NSArray.cpp
index 16635381f94fd..e242155f4fef9 100644
--- a/source/DataFormatters/NSArray.cpp
+++ b/source/DataFormatters/NSArray.cpp
@@ -228,7 +228,7 @@ namespace lldb_private {
}
bool
-lldb_private::formatters::NSArraySummaryProvider (ValueObject& valobj, Stream& stream)
+lldb_private::formatters::NSArraySummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options)
{
ProcessSP process_sp = valobj.GetProcessSP();
if (!process_sp)
@@ -341,10 +341,10 @@ lldb_private::formatters::NSArrayMSyntheticFrontEnd::GetChildAtIndex (size_t idx
object_at_idx += (pyhs_idx * m_ptr_size);
StreamString idx_name;
idx_name.Printf("[%" PRIu64 "]", (uint64_t)idx);
- lldb::ValueObjectSP retval_sp = ValueObject::CreateValueObjectFromAddress(idx_name.GetData(),
- object_at_idx,
- m_exe_ctx_ref,
- m_id_type);
+ lldb::ValueObjectSP retval_sp = CreateValueObjectFromAddress(idx_name.GetData(),
+ object_at_idx,
+ m_exe_ctx_ref,
+ m_id_type);
m_children.push_back(retval_sp);
return retval_sp;
}
@@ -604,7 +604,10 @@ lldb_private::formatters::NSArrayISyntheticFrontEnd::GetChildAtIndex (size_t idx
return lldb::ValueObjectSP();
StreamString idx_name;
idx_name.Printf("[%" PRIu64 "]", (uint64_t)idx);
- lldb::ValueObjectSP retval_sp = ValueObject::CreateValueObjectFromAddress(idx_name.GetData(), object_at_idx, m_exe_ctx_ref, m_id_type);
+ lldb::ValueObjectSP retval_sp = CreateValueObjectFromAddress(idx_name.GetData(),
+ object_at_idx,
+ m_exe_ctx_ref,
+ m_id_type);
m_children.push_back(retval_sp);
return retval_sp;
}
@@ -624,7 +627,7 @@ SyntheticChildrenFrontEnd* lldb_private::formatters::NSArraySyntheticFrontEndCre
ClangASTType valobj_type(valobj_sp->GetClangType());
Flags flags(valobj_type.GetTypeInfo());
- if (flags.IsClear(ClangASTType::eTypeIsPointer))
+ if (flags.IsClear(eTypeIsPointer))
{
Error error;
valobj_sp = valobj_sp->AddressOf(error);
diff --git a/source/DataFormatters/NSDictionary.cpp b/source/DataFormatters/NSDictionary.cpp
index ddd1e2e7ca90c..fdac05192c467 100644
--- a/source/DataFormatters/NSDictionary.cpp
+++ b/source/DataFormatters/NSDictionary.cpp
@@ -36,52 +36,167 @@ GetLLDBNSPairType (TargetSP target_sp)
if (target_ast_context)
{
- clang::ASTContext *ast = target_ast_context->getASTContext();
+ ConstString g___lldb_autogen_nspair("__lldb_autogen_nspair");
- if (ast)
+ clang_type = target_ast_context->GetTypeForIdentifier<clang::CXXRecordDecl>(g___lldb_autogen_nspair);
+
+ if (!clang_type)
{
- const char* type_name = "__lldb_autogen_nspair";
+ clang_type = target_ast_context->CreateRecordType(NULL, lldb::eAccessPublic, g___lldb_autogen_nspair.GetCString(), clang::TTK_Struct, lldb::eLanguageTypeC);
- clang::IdentifierInfo &myIdent = ast->Idents.get(type_name);
- clang::DeclarationName myName = ast->DeclarationNames.getIdentifier(&myIdent);
-
- clang::DeclContext::lookup_const_result result = ast->getTranslationUnitDecl()->lookup(myName);
-
- for (clang::NamedDecl *named_decl : result)
- {
- if (const clang::CXXRecordDecl *record_decl = llvm::dyn_cast<clang::CXXRecordDecl>(named_decl))
- {
- clang_type.SetClangType(ast, clang::QualType(record_decl->getTypeForDecl(), 0));
- break;
- }
- else
- {
- // somebody else (the user?) has defined a type with the magic name already - fail!!!
- return clang_type;
- }
- }
-
- if (!clang_type)
+ if (clang_type)
{
- clang_type = target_ast_context->CreateRecordType(NULL, lldb::eAccessPublic, type_name, clang::TTK_Struct, lldb::eLanguageTypeC);
-
- if (clang_type)
- {
- clang_type.StartTagDeclarationDefinition();
- ClangASTType id_clang_type = target_ast_context->GetBasicType (eBasicTypeObjCID);
- clang_type.AddFieldToRecordType("key", id_clang_type, lldb::eAccessPublic, 0);
- clang_type.AddFieldToRecordType("value", id_clang_type, lldb::eAccessPublic, 0);
- clang_type.CompleteTagDeclarationDefinition();
- }
+ clang_type.StartTagDeclarationDefinition();
+ ClangASTType id_clang_type = target_ast_context->GetBasicType (eBasicTypeObjCID);
+ clang_type.AddFieldToRecordType("key", id_clang_type, lldb::eAccessPublic, 0);
+ clang_type.AddFieldToRecordType("value", id_clang_type, lldb::eAccessPublic, 0);
+ clang_type.CompleteTagDeclarationDefinition();
}
}
}
return clang_type;
}
+namespace lldb_private {
+ namespace formatters {
+ class NSDictionaryISyntheticFrontEnd : public SyntheticChildrenFrontEnd
+ {
+ private:
+ struct DataDescriptor_32
+ {
+ uint32_t _used : 26;
+ uint32_t _szidx : 6;
+ };
+ struct DataDescriptor_64
+ {
+ uint64_t _used : 58;
+ uint32_t _szidx : 6;
+ };
+
+ struct DictionaryItemDescriptor
+ {
+ lldb::addr_t key_ptr;
+ lldb::addr_t val_ptr;
+ lldb::ValueObjectSP valobj_sp;
+ };
+
+ public:
+ NSDictionaryISyntheticFrontEnd (lldb::ValueObjectSP valobj_sp);
+
+ virtual size_t
+ CalculateNumChildren ();
+
+ virtual lldb::ValueObjectSP
+ GetChildAtIndex (size_t idx);
+
+ virtual bool
+ Update();
+
+ virtual bool
+ MightHaveChildren ();
+
+ virtual size_t
+ GetIndexOfChildWithName (const ConstString &name);
+
+ virtual
+ ~NSDictionaryISyntheticFrontEnd ();
+ private:
+ ExecutionContextRef m_exe_ctx_ref;
+ uint8_t m_ptr_size;
+ lldb::ByteOrder m_order;
+ DataDescriptor_32 *m_data_32;
+ DataDescriptor_64 *m_data_64;
+ lldb::addr_t m_data_ptr;
+ ClangASTType m_pair_type;
+ std::vector<DictionaryItemDescriptor> m_children;
+ };
+
+ class NSDictionaryMSyntheticFrontEnd : public SyntheticChildrenFrontEnd
+ {
+ private:
+ struct DataDescriptor_32
+ {
+ uint32_t _used : 26;
+ uint32_t _kvo : 1;
+ uint32_t _size;
+ uint32_t _mutations;
+ uint32_t _objs_addr;
+ uint32_t _keys_addr;
+ };
+ struct DataDescriptor_64
+ {
+ uint64_t _used : 58;
+ uint32_t _kvo : 1;
+ uint64_t _size;
+ uint64_t _mutations;
+ uint64_t _objs_addr;
+ uint64_t _keys_addr;
+ };
+ struct DictionaryItemDescriptor
+ {
+ lldb::addr_t key_ptr;
+ lldb::addr_t val_ptr;
+ lldb::ValueObjectSP valobj_sp;
+ };
+ public:
+ NSDictionaryMSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp);
+
+ virtual size_t
+ CalculateNumChildren ();
+
+ virtual lldb::ValueObjectSP
+ GetChildAtIndex (size_t idx);
+
+ virtual bool
+ Update();
+
+ virtual bool
+ MightHaveChildren ();
+
+ virtual size_t
+ GetIndexOfChildWithName (const ConstString &name);
+
+ virtual
+ ~NSDictionaryMSyntheticFrontEnd ();
+ private:
+ ExecutionContextRef m_exe_ctx_ref;
+ uint8_t m_ptr_size;
+ lldb::ByteOrder m_order;
+ DataDescriptor_32 *m_data_32;
+ DataDescriptor_64 *m_data_64;
+ ClangASTType m_pair_type;
+ std::vector<DictionaryItemDescriptor> m_children;
+ };
+
+ class NSDictionaryCodeRunningSyntheticFrontEnd : public SyntheticChildrenFrontEnd
+ {
+ public:
+ NSDictionaryCodeRunningSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp);
+
+ virtual size_t
+ CalculateNumChildren ();
+
+ virtual lldb::ValueObjectSP
+ GetChildAtIndex (size_t idx);
+
+ virtual bool
+ Update();
+
+ virtual bool
+ MightHaveChildren ();
+
+ virtual size_t
+ GetIndexOfChildWithName (const ConstString &name);
+
+ virtual
+ ~NSDictionaryCodeRunningSyntheticFrontEnd ();
+ };
+ }
+}
+
template<bool name_entries>
bool
-lldb_private::formatters::NSDictionarySummaryProvider (ValueObject& valobj, Stream& stream)
+lldb_private::formatters::NSDictionarySummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options)
{
ProcessSP process_sp = valobj.GetProcessSP();
if (!process_sp)
@@ -407,7 +522,10 @@ lldb_private::formatters::NSDictionaryISyntheticFrontEnd::GetChildAtIndex (size_
StreamString idx_name;
idx_name.Printf("[%" PRIu64 "]", (uint64_t)idx);
DataExtractor data(buffer_sp, m_order, m_ptr_size);
- dict_item.valobj_sp = ValueObject::CreateValueObjectFromData(idx_name.GetData(), data, m_exe_ctx_ref, m_pair_type);
+ dict_item.valobj_sp = CreateValueObjectFromData(idx_name.GetData(),
+ data,
+ m_exe_ctx_ref,
+ m_pair_type);
}
return dict_item.valobj_sp;
}
@@ -571,13 +689,16 @@ lldb_private::formatters::NSDictionaryMSyntheticFrontEnd::GetChildAtIndex (size_
StreamString idx_name;
idx_name.Printf("[%" PRIu64 "]", (uint64_t)idx);
DataExtractor data(buffer_sp, m_order, m_ptr_size);
- dict_item.valobj_sp = ValueObject::CreateValueObjectFromData(idx_name.GetData(), data, m_exe_ctx_ref, m_pair_type);
+ dict_item.valobj_sp = CreateValueObjectFromData(idx_name.GetData(),
+ data,
+ m_exe_ctx_ref,
+ m_pair_type);
}
return dict_item.valobj_sp;
}
template bool
-lldb_private::formatters::NSDictionarySummaryProvider<true> (ValueObject&, Stream&) ;
+lldb_private::formatters::NSDictionarySummaryProvider<true> (ValueObject&, Stream&, const TypeSummaryOptions&) ;
template bool
-lldb_private::formatters::NSDictionarySummaryProvider<false> (ValueObject&, Stream&) ;
+lldb_private::formatters::NSDictionarySummaryProvider<false> (ValueObject&, Stream&, const TypeSummaryOptions&) ;
diff --git a/source/DataFormatters/NSIndexPath.cpp b/source/DataFormatters/NSIndexPath.cpp
new file mode 100644
index 0000000000000..ee9583ef4cc1a
--- /dev/null
+++ b/source/DataFormatters/NSIndexPath.cpp
@@ -0,0 +1,309 @@
+//===-- NSIndexPath.cpp ------------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "lldb/DataFormatters/CXXFormatterFunctions.h"
+
+#include "lldb/Core/ValueObject.h"
+#include "lldb/Core/ValueObjectConstResult.h"
+#include "lldb/DataFormatters/TypeSynthetic.h"
+#include "lldb/Target/ObjCLanguageRuntime.h"
+#include "lldb/Target/Process.h"
+#include "lldb/Symbol/ClangASTContext.h"
+
+using namespace lldb;
+using namespace lldb_private;
+using namespace lldb_private::formatters;
+
+class NSIndexPathSyntheticFrontEnd : public SyntheticChildrenFrontEnd
+{
+public:
+ NSIndexPathSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp) :
+ SyntheticChildrenFrontEnd (*valobj_sp.get()),
+ m_ptr_size(0),
+ m_ast_ctx(nullptr),
+ m_uint_star_type()
+ {
+ m_ptr_size = m_backend.GetTargetSP()->GetArchitecture().GetAddressByteSize();
+ }
+
+ virtual size_t
+ CalculateNumChildren ()
+ {
+ return m_impl.GetNumIndexes();
+ }
+
+ virtual lldb::ValueObjectSP
+ GetChildAtIndex (size_t idx)
+ {
+ return m_impl.GetIndexAtIndex(idx, m_uint_star_type);
+ }
+
+ virtual bool
+ Update()
+ {
+ m_impl.m_mode = Mode::Invalid;
+
+ m_ast_ctx = ClangASTContext::GetASTContext(m_backend.GetClangType().GetASTContext());
+ if (!m_ast_ctx)
+ return false;
+
+ m_uint_star_type = m_ast_ctx->GetPointerSizedIntType(false);
+
+ static ConstString g__indexes("_indexes");
+ static ConstString g__length("_length");
+
+ ProcessSP process_sp = m_backend.GetProcessSP();
+ if (!process_sp)
+ return false;
+
+ ObjCLanguageRuntime* runtime = (ObjCLanguageRuntime*)process_sp->GetLanguageRuntime(lldb::eLanguageTypeObjC);
+
+ if (!runtime)
+ return false;
+
+ ObjCLanguageRuntime::ClassDescriptorSP descriptor(runtime->GetClassDescriptor(m_backend));
+
+ if (!descriptor.get() || !descriptor->IsValid())
+ return false;
+
+ uint64_t info_bits(0),value_bits(0),payload(0);
+
+ if (descriptor->GetTaggedPointerInfo(&info_bits, &value_bits, &payload))
+ {
+ m_impl.m_mode = Mode::Inlined;
+ m_impl.m_inlined.SetIndexes(payload, *process_sp);
+ }
+ else
+ {
+ ObjCLanguageRuntime::ClassDescriptor::iVarDescriptor _indexes_id;
+ ObjCLanguageRuntime::ClassDescriptor::iVarDescriptor _length_id;
+
+ bool has_indexes(false),has_length(false);
+
+ for (size_t x = 0;
+ x < descriptor->GetNumIVars();
+ x++)
+ {
+ const auto& ivar = descriptor->GetIVarAtIndex(x);
+ if (ivar.m_name == g__indexes)
+ {
+ _indexes_id = ivar;
+ has_indexes = true;
+ }
+ else if (ivar.m_name == g__length)
+ {
+ _length_id = ivar;
+ has_length = true;
+ }
+
+ if (has_length && has_indexes)
+ break;
+ }
+
+ if (has_length && has_indexes)
+ {
+ m_impl.m_outsourced.m_indexes = m_backend.GetSyntheticChildAtOffset(_indexes_id.m_offset,
+ m_uint_star_type.GetPointerType(),
+ true).get();
+ ValueObjectSP length_sp(m_backend.GetSyntheticChildAtOffset(_length_id.m_offset,
+ m_uint_star_type,
+ true));
+ if (length_sp)
+ {
+ m_impl.m_outsourced.m_count = length_sp->GetValueAsUnsigned(0);
+ if (m_impl.m_outsourced.m_indexes)
+ m_impl.m_mode = Mode::Outsourced;
+ }
+ }
+ }
+ return false;
+ }
+
+ virtual bool
+ MightHaveChildren ()
+ {
+ if (m_impl.m_mode == Mode::Invalid)
+ return false;
+ return true;
+ }
+
+ virtual size_t
+ GetIndexOfChildWithName (const ConstString &name)
+ {
+ const char* item_name = name.GetCString();
+ uint32_t idx = ExtractIndexFromString(item_name);
+ if (idx < UINT32_MAX && idx >= CalculateNumChildren())
+ return UINT32_MAX;
+ return idx;
+ }
+
+ virtual lldb::ValueObjectSP
+ GetSyntheticValue () { return nullptr; }
+
+ virtual
+ ~NSIndexPathSyntheticFrontEnd () {}
+
+protected:
+ ObjCLanguageRuntime::ClassDescriptorSP m_descriptor_sp;
+
+ enum class Mode {
+ Inlined,
+ Outsourced,
+ Invalid
+ };
+
+ struct Impl {
+ Mode m_mode;
+
+ size_t
+ GetNumIndexes ()
+ {
+ switch (m_mode)
+ {
+ case Mode::Inlined:
+ return m_inlined.GetNumIndexes();
+ case Mode::Outsourced:
+ return m_outsourced.m_count;
+ default:
+ return 0;
+ }
+ }
+
+ lldb::ValueObjectSP
+ GetIndexAtIndex (size_t idx, const ClangASTType& desired_type)
+ {
+ if (idx >= GetNumIndexes())
+ return nullptr;
+ switch (m_mode)
+ {
+ default: return nullptr;
+ case Mode::Inlined:
+ return m_inlined.GetIndexAtIndex (idx, desired_type);
+ case Mode::Outsourced:
+ return m_outsourced.GetIndexAtIndex (idx);
+ }
+ }
+
+ struct InlinedIndexes {
+ public:
+ void SetIndexes(uint64_t value, Process& p)
+ {
+ m_indexes = value;
+ _lengthForInlinePayload(p.GetAddressByteSize());
+ m_process = &p;
+ }
+
+ size_t
+ GetNumIndexes ()
+ {
+ return m_count;
+ }
+
+ lldb::ValueObjectSP
+ GetIndexAtIndex (size_t idx, const ClangASTType& desired_type)
+ {
+ std::pair<uint64_t, bool> value(_indexAtPositionForInlinePayload(idx));
+ if (!value.second)
+ return nullptr;
+ Value v;
+ if (m_ptr_size == 8)
+ {
+ Scalar scalar( (unsigned long long)value.first );
+ v = Value(scalar);
+ }
+ else
+ {
+ Scalar scalar( (unsigned int)value.first );
+ v = Value(scalar);
+ }
+ v.SetClangType(desired_type);
+ StreamString idx_name;
+ idx_name.Printf("[%" PRIu64 "]", (uint64_t)idx);
+ return ValueObjectConstResult::Create(m_process, v, ConstString(idx_name.GetData()));
+ }
+
+ private:
+ uint64_t m_indexes;
+ size_t m_count;
+ uint32_t m_ptr_size;
+ Process *m_process;
+
+ // cfr. Foundation for the details of this code
+ size_t _lengthForInlinePayload(uint32_t ptr_size) {
+ m_ptr_size = ptr_size;
+ if (m_ptr_size == 8)
+ m_count = ((m_indexes >> 3) & 0x7);
+ else
+ m_count = ((m_indexes >> 3) & 0x3);
+ return m_count;
+ }
+
+ std::pair<uint64_t, bool>
+ _indexAtPositionForInlinePayload(size_t pos) {
+ if (m_ptr_size == 8)
+ {
+ switch (pos) {
+ case 5: return {((m_indexes >> 51) & 0x1ff),true};
+ case 4: return {((m_indexes >> 42) & 0x1ff),true};
+ case 3: return {((m_indexes >> 33) & 0x1ff),true};
+ case 2: return {((m_indexes >> 24) & 0x1ff),true};
+ case 1: return {((m_indexes >> 15) & 0x1ff),true};
+ case 0: return {((m_indexes >> 6) & 0x1ff),true};
+ }
+ }
+ else
+ {
+ switch (pos) {
+ case 2: return {((m_indexes >> 23) & 0x1ff),true};
+ case 1: return {((m_indexes >> 14) & 0x1ff),true};
+ case 0: return {((m_indexes >> 5) & 0x1ff),true};
+ }
+ }
+ return {0,false};
+ }
+
+ };
+ struct OutsourcedIndexes {
+ ValueObject *m_indexes;
+ size_t m_count;
+
+ lldb::ValueObjectSP
+ GetIndexAtIndex (size_t idx)
+ {
+ if (m_indexes)
+ {
+ ValueObjectSP index_sp(m_indexes->GetSyntheticArrayMemberFromPointer(idx, true));
+ return index_sp;
+ }
+ return nullptr;
+ }
+ };
+
+ union {
+ struct InlinedIndexes m_inlined;
+ struct OutsourcedIndexes m_outsourced;
+ };
+ } m_impl;
+
+ uint32_t m_ptr_size;
+ ClangASTContext* m_ast_ctx;
+ ClangASTType m_uint_star_type;
+};
+
+namespace lldb_private {
+ namespace formatters {
+
+ SyntheticChildrenFrontEnd* NSIndexPathSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP valobj_sp)
+ {
+ if (valobj_sp)
+ return new NSIndexPathSyntheticFrontEnd(valobj_sp);
+ return nullptr;
+ }
+ }
+}
diff --git a/source/DataFormatters/NSSet.cpp b/source/DataFormatters/NSSet.cpp
index 3c7c003ed95ac..194d1bd29ea13 100644
--- a/source/DataFormatters/NSSet.cpp
+++ b/source/DataFormatters/NSSet.cpp
@@ -25,9 +25,165 @@ using namespace lldb;
using namespace lldb_private;
using namespace lldb_private::formatters;
+namespace lldb_private {
+ namespace formatters {
+ class NSSetISyntheticFrontEnd : public SyntheticChildrenFrontEnd
+ {
+ private:
+ struct DataDescriptor_32
+ {
+ uint32_t _used : 26;
+ uint32_t _szidx : 6;
+ };
+ struct DataDescriptor_64
+ {
+ uint64_t _used : 58;
+ uint32_t _szidx : 6;
+ };
+
+ struct SetItemDescriptor
+ {
+ lldb::addr_t item_ptr;
+ lldb::ValueObjectSP valobj_sp;
+ };
+
+ public:
+ NSSetISyntheticFrontEnd (lldb::ValueObjectSP valobj_sp);
+
+ virtual size_t
+ CalculateNumChildren ();
+
+ virtual lldb::ValueObjectSP
+ GetChildAtIndex (size_t idx);
+
+ virtual bool
+ Update();
+
+ virtual bool
+ MightHaveChildren ();
+
+ virtual size_t
+ GetIndexOfChildWithName (const ConstString &name);
+
+ virtual
+ ~NSSetISyntheticFrontEnd ();
+ private:
+ ExecutionContextRef m_exe_ctx_ref;
+ uint8_t m_ptr_size;
+ DataDescriptor_32 *m_data_32;
+ DataDescriptor_64 *m_data_64;
+ lldb::addr_t m_data_ptr;
+ std::vector<SetItemDescriptor> m_children;
+ };
+
+ class NSOrderedSetSyntheticFrontEnd : public SyntheticChildrenFrontEnd
+ {
+ private:
+
+ public:
+ NSOrderedSetSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp);
+
+ virtual size_t
+ CalculateNumChildren ();
+
+ virtual lldb::ValueObjectSP
+ GetChildAtIndex (size_t idx);
+
+ virtual bool
+ Update();
+
+ virtual bool
+ MightHaveChildren ();
+
+ virtual size_t
+ GetIndexOfChildWithName (const ConstString &name);
+
+ virtual
+ ~NSOrderedSetSyntheticFrontEnd ();
+ private:
+ uint32_t m_count;
+ std::map<uint32_t,lldb::ValueObjectSP> m_children;
+ };
+
+ class NSSetMSyntheticFrontEnd : public SyntheticChildrenFrontEnd
+ {
+ private:
+ struct DataDescriptor_32
+ {
+ uint32_t _used : 26;
+ uint32_t _size;
+ uint32_t _mutations;
+ uint32_t _objs_addr;
+ };
+ struct DataDescriptor_64
+ {
+ uint64_t _used : 58;
+ uint64_t _size;
+ uint64_t _mutations;
+ uint64_t _objs_addr;
+ };
+ struct SetItemDescriptor
+ {
+ lldb::addr_t item_ptr;
+ lldb::ValueObjectSP valobj_sp;
+ };
+ public:
+ NSSetMSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp);
+
+ virtual size_t
+ CalculateNumChildren ();
+
+ virtual lldb::ValueObjectSP
+ GetChildAtIndex (size_t idx);
+
+ virtual bool
+ Update();
+
+ virtual bool
+ MightHaveChildren ();
+
+ virtual size_t
+ GetIndexOfChildWithName (const ConstString &name);
+
+ virtual
+ ~NSSetMSyntheticFrontEnd ();
+ private:
+ ExecutionContextRef m_exe_ctx_ref;
+ uint8_t m_ptr_size;
+ DataDescriptor_32 *m_data_32;
+ DataDescriptor_64 *m_data_64;
+ std::vector<SetItemDescriptor> m_children;
+ };
+
+ class NSSetCodeRunningSyntheticFrontEnd : public SyntheticChildrenFrontEnd
+ {
+ public:
+ NSSetCodeRunningSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp);
+
+ virtual size_t
+ CalculateNumChildren ();
+
+ virtual lldb::ValueObjectSP
+ GetChildAtIndex (size_t idx);
+
+ virtual bool
+ Update();
+
+ virtual bool
+ MightHaveChildren ();
+
+ virtual size_t
+ GetIndexOfChildWithName (const ConstString &name);
+
+ virtual
+ ~NSSetCodeRunningSyntheticFrontEnd ();
+ };
+ }
+}
+
template<bool cf_style>
bool
-lldb_private::formatters::NSSetSummaryProvider (ValueObject& valobj, Stream& stream)
+lldb_private::formatters::NSSetSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options)
{
ProcessSP process_sp = valobj.GetProcessSP();
if (!process_sp)
@@ -313,10 +469,10 @@ lldb_private::formatters::NSSetISyntheticFrontEnd::GetChildAtIndex (size_t idx)
process_sp->GetAddressByteSize());
set_item.valobj_sp =
- ValueObject::CreateValueObjectFromData(idx_name.GetData(),
- data,
- m_exe_ctx_ref,
- m_backend.GetClangType().GetBasicTypeFromAST(lldb::eBasicTypeObjCID));
+ CreateValueObjectFromData(idx_name.GetData(),
+ data,
+ m_exe_ctx_ref,
+ m_backend.GetClangType().GetBasicTypeFromAST(lldb::eBasicTypeObjCID));
}
return set_item.valobj_sp;
}
@@ -481,10 +637,10 @@ lldb_private::formatters::NSSetMSyntheticFrontEnd::GetChildAtIndex (size_t idx)
process_sp->GetAddressByteSize());
set_item.valobj_sp =
- ValueObject::CreateValueObjectFromData(idx_name.GetData(),
- data,
- m_exe_ctx_ref,
- m_backend.GetClangType().GetBasicTypeFromAST(lldb::eBasicTypeObjCID));
+ CreateValueObjectFromData(idx_name.GetData(),
+ data,
+ m_exe_ctx_ref,
+ m_backend.GetClangType().GetBasicTypeFromAST(lldb::eBasicTypeObjCID));
}
return set_item.valobj_sp;
}
@@ -557,7 +713,7 @@ lldb_private::formatters::NSOrderedSetSyntheticFrontEnd::~NSOrderedSetSyntheticF
}
template bool
-lldb_private::formatters::NSSetSummaryProvider<true> (ValueObject& valobj, Stream& stream);
+lldb_private::formatters::NSSetSummaryProvider<true> (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options);
template bool
-lldb_private::formatters::NSSetSummaryProvider<false> (ValueObject& valobj, Stream& stream);
+lldb_private::formatters::NSSetSummaryProvider<false> (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options);
diff --git a/source/DataFormatters/StringPrinter.cpp b/source/DataFormatters/StringPrinter.cpp
new file mode 100644
index 0000000000000..3af5931ad716f
--- /dev/null
+++ b/source/DataFormatters/StringPrinter.cpp
@@ -0,0 +1,650 @@
+//===-- StringPrinter.cpp ----------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "lldb/DataFormatters/StringPrinter.h"
+
+#include "lldb/Core/DataExtractor.h"
+#include "lldb/Core/Debugger.h"
+#include "lldb/Core/Error.h"
+#include "lldb/Core/ValueObject.h"
+#include "lldb/Target/Process.h"
+#include "lldb/Target/Target.h"
+
+#include "llvm/Support/ConvertUTF.h"
+
+#include <ctype.h>
+#include <functional>
+#include <locale>
+
+using namespace lldb;
+using namespace lldb_private;
+using namespace lldb_private::formatters;
+
+// I can't use a std::unique_ptr for this because the Deleter is a template argument there
+// and I want the same type to represent both pointers I want to free and pointers I don't need
+// to free - which is what this class essentially is
+// It's very specialized to the needs of this file, and not suggested for general use
+template <typename T = uint8_t, typename U = char, typename S = size_t>
+struct StringPrinterBufferPointer
+{
+public:
+
+ typedef std::function<void(const T*)> Deleter;
+
+ StringPrinterBufferPointer (std::nullptr_t ptr) :
+ m_data(nullptr),
+ m_size(0),
+ m_deleter()
+ {}
+
+ StringPrinterBufferPointer(const T* bytes, S size, Deleter deleter = nullptr) :
+ m_data(bytes),
+ m_size(size),
+ m_deleter(deleter)
+ {}
+
+ StringPrinterBufferPointer(const U* bytes, S size, Deleter deleter = nullptr) :
+ m_data((T*)bytes),
+ m_size(size),
+ m_deleter(deleter)
+ {}
+
+ StringPrinterBufferPointer(StringPrinterBufferPointer&& rhs) :
+ m_data(rhs.m_data),
+ m_size(rhs.m_size),
+ m_deleter(rhs.m_deleter)
+ {
+ rhs.m_data = nullptr;
+ }
+
+ StringPrinterBufferPointer(const StringPrinterBufferPointer& rhs) :
+ m_data(rhs.m_data),
+ m_size(rhs.m_size),
+ m_deleter(rhs.m_deleter)
+ {
+ rhs.m_data = nullptr; // this is why m_data has to be mutable
+ }
+
+ const T*
+ GetBytes () const
+ {
+ return m_data;
+ }
+
+ const S
+ GetSize () const
+ {
+ return m_size;
+ }
+
+ ~StringPrinterBufferPointer ()
+ {
+ if (m_data && m_deleter)
+ m_deleter(m_data);
+ m_data = nullptr;
+ }
+
+ StringPrinterBufferPointer&
+ operator = (const StringPrinterBufferPointer& rhs)
+ {
+ if (m_data && m_deleter)
+ m_deleter(m_data);
+ m_data = rhs.m_data;
+ m_size = rhs.m_size;
+ m_deleter = rhs.m_deleter;
+ rhs.m_data = nullptr;
+ return *this;
+ }
+
+private:
+ mutable const T* m_data;
+ size_t m_size;
+ Deleter m_deleter;
+};
+
+// we define this for all values of type but only implement it for those we care about
+// that's good because we get linker errors for any unsupported type
+template <StringElementType type>
+static StringPrinterBufferPointer<>
+GetPrintableImpl(uint8_t* buffer, uint8_t* buffer_end, uint8_t*& next);
+
+// mimic isprint() for Unicode codepoints
+static bool
+isprint(char32_t codepoint)
+{
+ if (codepoint <= 0x1F || codepoint == 0x7F) // C0
+ {
+ return false;
+ }
+ if (codepoint >= 0x80 && codepoint <= 0x9F) // C1
+ {
+ return false;
+ }
+ if (codepoint == 0x2028 || codepoint == 0x2029) // line/paragraph separators
+ {
+ return false;
+ }
+ if (codepoint == 0x200E || codepoint == 0x200F || (codepoint >= 0x202A && codepoint <= 0x202E)) // bidirectional text control
+ {
+ return false;
+ }
+ if (codepoint >= 0xFFF9 && codepoint <= 0xFFFF) // interlinears and generally specials
+ {
+ return false;
+ }
+ return true;
+}
+
+template <>
+StringPrinterBufferPointer<>
+GetPrintableImpl<StringElementType::ASCII> (uint8_t* buffer, uint8_t* buffer_end, uint8_t*& next)
+{
+ StringPrinterBufferPointer<> retval = {nullptr};
+
+ switch (*buffer)
+ {
+ case 0:
+ retval = {"\\0",2};
+ break;
+ case '\a':
+ retval = {"\\a",2};
+ break;
+ case '\b':
+ retval = {"\\b",2};
+ break;
+ case '\f':
+ retval = {"\\f",2};
+ break;
+ case '\n':
+ retval = {"\\n",2};
+ break;
+ case '\r':
+ retval = {"\\r",2};
+ break;
+ case '\t':
+ retval = {"\\t",2};
+ break;
+ case '\v':
+ retval = {"\\v",2};
+ break;
+ case '\"':
+ retval = {"\\\"",2};
+ break;
+ case '\\':
+ retval = {"\\\\",2};
+ break;
+ default:
+ if (isprint(*buffer))
+ retval = {buffer,1};
+ else
+ {
+ retval = { new uint8_t[5],4,[] (const uint8_t* c) {delete[] c;} };
+ sprintf((char*)retval.GetBytes(),"\\x%02x",*buffer);
+ break;
+ }
+ }
+
+ next = buffer + 1;
+ return retval;
+}
+
+static char32_t
+ConvertUTF8ToCodePoint (unsigned char c0, unsigned char c1)
+{
+ return (c0-192)*64+(c1-128);
+}
+static char32_t
+ConvertUTF8ToCodePoint (unsigned char c0, unsigned char c1, unsigned char c2)
+{
+ return (c0-224)*4096+(c1-128)*64+(c2-128);
+}
+static char32_t
+ConvertUTF8ToCodePoint (unsigned char c0, unsigned char c1, unsigned char c2, unsigned char c3)
+{
+ return (c0-240)*262144+(c2-128)*4096+(c2-128)*64+(c3-128);
+}
+
+template <>
+StringPrinterBufferPointer<>
+GetPrintableImpl<StringElementType::UTF8> (uint8_t* buffer, uint8_t* buffer_end, uint8_t*& next)
+{
+ StringPrinterBufferPointer<> retval {nullptr};
+
+ unsigned utf8_encoded_len = getNumBytesForUTF8(*buffer);
+
+ if (1+buffer_end-buffer < utf8_encoded_len)
+ {
+ // I don't have enough bytes - print whatever I have left
+ retval = {buffer,static_cast<size_t>(1+buffer_end-buffer)};
+ next = buffer_end+1;
+ return retval;
+ }
+
+ char32_t codepoint = 0;
+ switch (utf8_encoded_len)
+ {
+ case 1:
+ // this is just an ASCII byte - ask ASCII
+ return GetPrintableImpl<StringElementType::ASCII>(buffer, buffer_end, next);
+ case 2:
+ codepoint = ConvertUTF8ToCodePoint((unsigned char)*buffer, (unsigned char)*(buffer+1));
+ break;
+ case 3:
+ codepoint = ConvertUTF8ToCodePoint((unsigned char)*buffer, (unsigned char)*(buffer+1), (unsigned char)*(buffer+2));
+ break;
+ case 4:
+ codepoint = ConvertUTF8ToCodePoint((unsigned char)*buffer, (unsigned char)*(buffer+1), (unsigned char)*(buffer+2), (unsigned char)*(buffer+3));
+ break;
+ default:
+ // this is probably some bogus non-character thing
+ // just print it as-is and hope to sync up again soon
+ retval = {buffer,1};
+ next = buffer+1;
+ return retval;
+ }
+
+ if (codepoint)
+ {
+ switch (codepoint)
+ {
+ case 0:
+ retval = {"\\0",2};
+ break;
+ case '\a':
+ retval = {"\\a",2};
+ break;
+ case '\b':
+ retval = {"\\b",2};
+ break;
+ case '\f':
+ retval = {"\\f",2};
+ break;
+ case '\n':
+ retval = {"\\n",2};
+ break;
+ case '\r':
+ retval = {"\\r",2};
+ break;
+ case '\t':
+ retval = {"\\t",2};
+ break;
+ case '\v':
+ retval = {"\\v",2};
+ break;
+ case '\"':
+ retval = {"\\\"",2};
+ break;
+ case '\\':
+ retval = {"\\\\",2};
+ break;
+ default:
+ if (isprint(codepoint))
+ retval = {buffer,utf8_encoded_len};
+ else
+ {
+ retval = { new uint8_t[11],10,[] (const uint8_t* c) {delete[] c;} };
+ sprintf((char*)retval.GetBytes(),"\\U%08x",codepoint);
+ break;
+ }
+ }
+
+ next = buffer + utf8_encoded_len;
+ return retval;
+ }
+
+ // this should not happen - but just in case.. try to resync at some point
+ retval = {buffer,1};
+ next = buffer+1;
+ return retval;
+}
+
+// Given a sequence of bytes, this function returns:
+// a sequence of bytes to actually print out + a length
+// the following unscanned position of the buffer is in next
+static StringPrinterBufferPointer<>
+GetPrintable(StringElementType type, uint8_t* buffer, uint8_t* buffer_end, uint8_t*& next)
+{
+ if (!buffer)
+ return {nullptr};
+
+ switch (type)
+ {
+ case StringElementType::ASCII:
+ return GetPrintableImpl<StringElementType::ASCII>(buffer, buffer_end, next);
+ case StringElementType::UTF8:
+ return GetPrintableImpl<StringElementType::UTF8>(buffer, buffer_end, next);
+ default:
+ return {nullptr};
+ }
+}
+
+// use this call if you already have an LLDB-side buffer for the data
+template<typename SourceDataType>
+static bool
+DumpUTFBufferToStream (ConversionResult (*ConvertFunction) (const SourceDataType**,
+ const SourceDataType*,
+ UTF8**,
+ UTF8*,
+ ConversionFlags),
+ const DataExtractor& data,
+ Stream& stream,
+ char prefix_token,
+ char quote,
+ uint32_t sourceSize,
+ bool escapeNonPrintables)
+{
+ if (prefix_token != 0)
+ stream.Printf("%c",prefix_token);
+ if (quote != 0)
+ stream.Printf("%c",quote);
+ if (data.GetByteSize() && data.GetDataStart() && data.GetDataEnd())
+ {
+ const int bufferSPSize = data.GetByteSize();
+ if (sourceSize == 0)
+ {
+ const int origin_encoding = 8*sizeof(SourceDataType);
+ sourceSize = bufferSPSize/(origin_encoding / 4);
+ }
+
+ SourceDataType *data_ptr = (SourceDataType*)data.GetDataStart();
+ SourceDataType *data_end_ptr = data_ptr + sourceSize;
+
+ while (data_ptr < data_end_ptr)
+ {
+ if (!*data_ptr)
+ {
+ data_end_ptr = data_ptr;
+ break;
+ }
+ data_ptr++;
+ }
+
+ data_ptr = (SourceDataType*)data.GetDataStart();
+
+ lldb::DataBufferSP utf8_data_buffer_sp;
+ UTF8* utf8_data_ptr = nullptr;
+ UTF8* utf8_data_end_ptr = nullptr;
+
+ if (ConvertFunction)
+ {
+ utf8_data_buffer_sp.reset(new DataBufferHeap(4*bufferSPSize,0));
+ utf8_data_ptr = (UTF8*)utf8_data_buffer_sp->GetBytes();
+ utf8_data_end_ptr = utf8_data_ptr + utf8_data_buffer_sp->GetByteSize();
+ ConvertFunction ( (const SourceDataType**)&data_ptr, data_end_ptr, &utf8_data_ptr, utf8_data_end_ptr, lenientConversion );
+ utf8_data_ptr = (UTF8*)utf8_data_buffer_sp->GetBytes(); // needed because the ConvertFunction will change the value of the data_ptr
+ }
+ else
+ {
+ // just copy the pointers - the cast is necessary to make the compiler happy
+ // but this should only happen if we are reading UTF8 data
+ utf8_data_ptr = (UTF8*)data_ptr;
+ utf8_data_end_ptr = (UTF8*)data_end_ptr;
+ }
+
+ // since we tend to accept partial data (and even partially malformed data)
+ // we might end up with no NULL terminator before the end_ptr
+ // hence we need to take a slower route and ensure we stay within boundaries
+ for (;utf8_data_ptr < utf8_data_end_ptr;)
+ {
+ if (!*utf8_data_ptr)
+ break;
+
+ if (escapeNonPrintables)
+ {
+ uint8_t* next_data = nullptr;
+ auto printable = GetPrintable(StringElementType::UTF8, utf8_data_ptr, utf8_data_end_ptr, next_data);
+ auto printable_bytes = printable.GetBytes();
+ auto printable_size = printable.GetSize();
+ if (!printable_bytes || !next_data)
+ {
+ // GetPrintable() failed on us - print one byte in a desperate resync attempt
+ printable_bytes = utf8_data_ptr;
+ printable_size = 1;
+ next_data = utf8_data_ptr+1;
+ }
+ for (unsigned c = 0; c < printable_size; c++)
+ stream.Printf("%c", *(printable_bytes+c));
+ utf8_data_ptr = (uint8_t*)next_data;
+ }
+ else
+ {
+ stream.Printf("%c",*utf8_data_ptr);
+ utf8_data_ptr++;
+ }
+ }
+ }
+ if (quote != 0)
+ stream.Printf("%c",quote);
+ return true;
+}
+
+lldb_private::formatters::ReadStringAndDumpToStreamOptions::ReadStringAndDumpToStreamOptions (ValueObject& valobj) :
+ ReadStringAndDumpToStreamOptions()
+{
+ SetEscapeNonPrintables(valobj.GetTargetSP()->GetDebugger().GetEscapeNonPrintables());
+}
+
+lldb_private::formatters::ReadBufferAndDumpToStreamOptions::ReadBufferAndDumpToStreamOptions (ValueObject& valobj) :
+ ReadBufferAndDumpToStreamOptions()
+{
+ SetEscapeNonPrintables(valobj.GetTargetSP()->GetDebugger().GetEscapeNonPrintables());
+}
+
+
+namespace lldb_private
+{
+
+namespace formatters
+{
+
+template <>
+bool
+ReadStringAndDumpToStream<StringElementType::ASCII> (ReadStringAndDumpToStreamOptions options)
+{
+ assert(options.GetStream() && "need a Stream to print the string to");
+ Error my_error;
+ size_t my_data_read;
+
+ ProcessSP process_sp(options.GetProcessSP());
+
+ if (process_sp.get() == nullptr || options.GetLocation() == 0)
+ return false;
+
+ size_t size;
+
+ if (options.GetSourceSize() == 0)
+ size = process_sp->GetTarget().GetMaximumSizeOfStringSummary();
+ else if (!options.GetIgnoreMaxLength())
+ size = std::min(options.GetSourceSize(),process_sp->GetTarget().GetMaximumSizeOfStringSummary());
+ else
+ size = options.GetSourceSize();
+
+ lldb::DataBufferSP buffer_sp(new DataBufferHeap(size,0));
+
+ my_data_read = process_sp->ReadCStringFromMemory(options.GetLocation(), (char*)buffer_sp->GetBytes(), size, my_error);
+
+ if (my_error.Fail())
+ return false;
+
+ char prefix_token = options.GetPrefixToken();
+ char quote = options.GetQuote();
+
+ if (prefix_token != 0)
+ options.GetStream()->Printf("%c%c",prefix_token,quote);
+ else if (quote != 0)
+ options.GetStream()->Printf("%c",quote);
+
+ uint8_t* data_end = buffer_sp->GetBytes()+buffer_sp->GetByteSize();
+
+ // since we tend to accept partial data (and even partially malformed data)
+ // we might end up with no NULL terminator before the end_ptr
+ // hence we need to take a slower route and ensure we stay within boundaries
+ for (uint8_t* data = buffer_sp->GetBytes(); *data && (data < data_end);)
+ {
+ if (options.GetEscapeNonPrintables())
+ {
+ uint8_t* next_data = nullptr;
+ auto printable = GetPrintable(StringElementType::ASCII, data, data_end, next_data);
+ auto printable_bytes = printable.GetBytes();
+ auto printable_size = printable.GetSize();
+ if (!printable_bytes || !next_data)
+ {
+ // GetPrintable() failed on us - print one byte in a desperate resync attempt
+ printable_bytes = data;
+ printable_size = 1;
+ next_data = data+1;
+ }
+ for (unsigned c = 0; c < printable_size; c++)
+ options.GetStream()->Printf("%c", *(printable_bytes+c));
+ data = (uint8_t*)next_data;
+ }
+ else
+ {
+ options.GetStream()->Printf("%c",*data);
+ data++;
+ }
+ }
+
+ if (quote != 0)
+ options.GetStream()->Printf("%c",quote);
+
+ return true;
+}
+
+template<typename SourceDataType>
+static bool
+ReadUTFBufferAndDumpToStream (const ReadStringAndDumpToStreamOptions& options,
+ ConversionResult (*ConvertFunction) (const SourceDataType**,
+ const SourceDataType*,
+ UTF8**,
+ UTF8*,
+ ConversionFlags))
+{
+ assert(options.GetStream() && "need a Stream to print the string to");
+
+ if (options.GetLocation() == 0 || options.GetLocation() == LLDB_INVALID_ADDRESS)
+ return false;
+
+ lldb::ProcessSP process_sp(options.GetProcessSP());
+
+ if (!process_sp)
+ return false;
+
+ const int type_width = sizeof(SourceDataType);
+ const int origin_encoding = 8 * type_width ;
+ if (origin_encoding != 8 && origin_encoding != 16 && origin_encoding != 32)
+ return false;
+ // if not UTF8, I need a conversion function to return proper UTF8
+ if (origin_encoding != 8 && !ConvertFunction)
+ return false;
+
+ if (!options.GetStream())
+ return false;
+
+ uint32_t sourceSize = options.GetSourceSize();
+ bool needs_zero_terminator = options.GetNeedsZeroTermination();
+
+ if (!sourceSize)
+ {
+ sourceSize = process_sp->GetTarget().GetMaximumSizeOfStringSummary();
+ needs_zero_terminator = true;
+ }
+ else
+ sourceSize = std::min(sourceSize,process_sp->GetTarget().GetMaximumSizeOfStringSummary());
+
+ const int bufferSPSize = sourceSize * type_width;
+
+ lldb::DataBufferSP buffer_sp(new DataBufferHeap(bufferSPSize,0));
+
+ if (!buffer_sp->GetBytes())
+ return false;
+
+ Error error;
+ char *buffer = reinterpret_cast<char *>(buffer_sp->GetBytes());
+
+ size_t data_read = 0;
+ if (needs_zero_terminator)
+ data_read = process_sp->ReadStringFromMemory(options.GetLocation(), buffer, bufferSPSize, error, type_width);
+ else
+ data_read = process_sp->ReadMemoryFromInferior(options.GetLocation(), (char*)buffer_sp->GetBytes(), bufferSPSize, error);
+
+ if (error.Fail())
+ {
+ options.GetStream()->Printf("unable to read data");
+ return true;
+ }
+
+ DataExtractor data(buffer_sp, process_sp->GetByteOrder(), process_sp->GetAddressByteSize());
+
+ return DumpUTFBufferToStream(ConvertFunction, data, *options.GetStream(), options.GetPrefixToken(), options.GetQuote(), sourceSize, options.GetEscapeNonPrintables());
+}
+
+template <>
+bool
+ReadStringAndDumpToStream<StringElementType::UTF8> (ReadStringAndDumpToStreamOptions options)
+{
+ return ReadUTFBufferAndDumpToStream<UTF8>(options,
+ nullptr);
+}
+
+template <>
+bool
+ReadStringAndDumpToStream<StringElementType::UTF16> (ReadStringAndDumpToStreamOptions options)
+{
+ return ReadUTFBufferAndDumpToStream<UTF16>(options,
+ ConvertUTF16toUTF8);
+}
+
+template <>
+bool
+ReadStringAndDumpToStream<StringElementType::UTF32> (ReadStringAndDumpToStreamOptions options)
+{
+ return ReadUTFBufferAndDumpToStream<UTF32>(options,
+ ConvertUTF32toUTF8);
+}
+
+template <>
+bool
+ReadBufferAndDumpToStream<StringElementType::UTF8> (ReadBufferAndDumpToStreamOptions options)
+{
+ assert(options.GetStream() && "need a Stream to print the string to");
+
+ return DumpUTFBufferToStream<UTF8>(nullptr, options.GetData(), *options.GetStream(), options.GetPrefixToken(), options.GetQuote(), options.GetSourceSize(), options.GetEscapeNonPrintables());
+}
+
+template <>
+bool
+ReadBufferAndDumpToStream<StringElementType::ASCII> (ReadBufferAndDumpToStreamOptions options)
+{
+ // treat ASCII the same as UTF8
+ // FIXME: can we optimize ASCII some more?
+ return ReadBufferAndDumpToStream<StringElementType::UTF8>(options);
+}
+
+template <>
+bool
+ReadBufferAndDumpToStream<StringElementType::UTF16> (ReadBufferAndDumpToStreamOptions options)
+{
+ assert(options.GetStream() && "need a Stream to print the string to");
+
+ return DumpUTFBufferToStream(ConvertUTF16toUTF8, options.GetData(), *options.GetStream(), options.GetPrefixToken(), options.GetQuote(), options.GetSourceSize(), options.GetEscapeNonPrintables());
+}
+
+template <>
+bool
+ReadBufferAndDumpToStream<StringElementType::UTF32> (ReadBufferAndDumpToStreamOptions options)
+{
+ assert(options.GetStream() && "need a Stream to print the string to");
+
+ return DumpUTFBufferToStream(ConvertUTF32toUTF8, options.GetData(), *options.GetStream(), options.GetPrefixToken(), options.GetQuote(), options.GetSourceSize(), options.GetEscapeNonPrintables());
+}
+
+} // namespace formatters
+
+} // namespace lldb_private
diff --git a/source/DataFormatters/TypeCategory.cpp b/source/DataFormatters/TypeCategory.cpp
index 322d1cf55437e..3df6884fe679e 100644
--- a/source/DataFormatters/TypeCategory.cpp
+++ b/source/DataFormatters/TypeCategory.cpp
@@ -27,6 +27,7 @@ m_filter_cont("filter","regex-filter",clist),
#ifndef LLDB_DISABLE_PYTHON
m_synth_cont("synth","regex-synth",clist),
#endif
+m_validator_cont("validator","regex-validator",clist),
m_enabled(false),
m_change_listener(clist),
m_mutex(Mutex::eMutexTypeRecursive),
@@ -129,6 +130,22 @@ TypeCategoryImpl::Get (ValueObject& valobj,
return false;
}
+bool
+TypeCategoryImpl::Get (ValueObject& valobj,
+ const FormattersMatchVector& candidates,
+ lldb::TypeValidatorImplSP& entry,
+ uint32_t* reason)
+{
+ if (!IsEnabled())
+ return false;
+ if (GetTypeValidatorsContainer()->Get(candidates, entry, reason))
+ return true;
+ bool regex = GetRegexTypeValidatorsContainer()->Get(candidates, entry, reason);
+ if (regex && reason)
+ *reason |= lldb_private::eFormatterChoiceCriterionRegularExpressionSummary;
+ return regex;
+}
+
void
TypeCategoryImpl::Clear (FormatCategoryItems items)
{
@@ -153,6 +170,11 @@ TypeCategoryImpl::Clear (FormatCategoryItems items)
if ( (items & eFormatCategoryItemRegexSynth) == eFormatCategoryItemRegexSynth )
GetRegexTypeSyntheticsContainer()->Clear();
#endif
+
+ if ( (items & eFormatCategoryItemValidator) == eFormatCategoryItemValidator )
+ GetTypeValidatorsContainer()->Clear();
+ if ( (items & eFormatCategoryItemRegexValidator) == eFormatCategoryItemRegexValidator )
+ GetRegexTypeValidatorsContainer()->Clear();
}
bool
@@ -182,6 +204,12 @@ TypeCategoryImpl::Delete (ConstString name,
if ( (items & eFormatCategoryItemRegexSynth) == eFormatCategoryItemRegexSynth )
success = GetRegexTypeSyntheticsContainer()->Delete(name) || success;
#endif
+
+ if ( (items & eFormatCategoryItemValidator) == eFormatCategoryItemValidator )
+ success = GetTypeValidatorsContainer()->Delete(name) || success;
+ if ( (items & eFormatCategoryItemRegexValidator) == eFormatCategoryItemRegexValidator )
+ success = GetRegexTypeValidatorsContainer()->Delete(name) || success;
+
return success;
}
@@ -211,6 +239,12 @@ TypeCategoryImpl::GetCount (FormatCategoryItems items)
if ( (items & eFormatCategoryItemRegexSynth) == eFormatCategoryItemRegexSynth )
count += GetRegexTypeSyntheticsContainer()->GetCount();
#endif
+
+ if ( (items & eFormatCategoryItemValidator) == eFormatCategoryItemValidator )
+ count += GetTypeValidatorsContainer()->GetCount();
+ if ( (items & eFormatCategoryItemRegexValidator) == eFormatCategoryItemRegexValidator )
+ count += GetRegexTypeValidatorsContainer()->GetCount();
+
return count;
}
@@ -230,6 +264,7 @@ TypeCategoryImpl::AnyMatches(ConstString type_name,
#ifndef LLDB_DISABLE_PYTHON
ScriptedSyntheticChildren::SharedPointer synth_sp;
#endif
+ TypeValidatorImpl::SharedPointer validator_sp;
if ( (items & eFormatCategoryItemValue) == eFormatCategoryItemValue )
{
@@ -324,6 +359,30 @@ TypeCategoryImpl::AnyMatches(ConstString type_name,
}
}
#endif
+
+ if ( (items & eFormatCategoryItemValidator) == eFormatCategoryItemValidator )
+ {
+ if (GetTypeValidatorsContainer()->Get(type_name, validator_sp))
+ {
+ if (matching_category)
+ *matching_category = m_name.GetCString();
+ if (matching_type)
+ *matching_type = eFormatCategoryItemValidator;
+ return true;
+ }
+ }
+ if ( (items & eFormatCategoryItemRegexValidator) == eFormatCategoryItemRegexValidator )
+ {
+ if (GetRegexTypeValidatorsContainer()->Get(type_name, validator_sp))
+ {
+ if (matching_category)
+ *matching_category = m_name.GetCString();
+ if (matching_type)
+ *matching_type = eFormatCategoryItemRegexValidator;
+ return true;
+ }
+ }
+
return false;
}
@@ -393,6 +452,22 @@ TypeCategoryImpl::GetSyntheticForType (lldb::TypeNameSpecifierImplSP type_sp)
}
#endif
+TypeCategoryImpl::ValidatorContainer::MapValueType
+TypeCategoryImpl::GetValidatorForType (lldb::TypeNameSpecifierImplSP type_sp)
+{
+ ValidatorContainer::MapValueType retval;
+
+ if (type_sp)
+ {
+ if (type_sp->IsRegex())
+ GetRegexTypeValidatorsContainer()->GetExact(ConstString(type_sp->GetName()),retval);
+ else
+ GetTypeValidatorsContainer()->GetExact(ConstString(type_sp->GetName()),retval);
+ }
+
+ return retval;
+}
+
lldb::TypeNameSpecifierImplSP
TypeCategoryImpl::GetTypeNameSpecifierForSummaryAtIndex (size_t index)
{
@@ -467,12 +542,30 @@ TypeCategoryImpl::GetTypeNameSpecifierForSyntheticAtIndex (size_t index)
}
#endif
+TypeCategoryImpl::ValidatorContainer::MapValueType
+TypeCategoryImpl::GetValidatorAtIndex (size_t index)
+{
+ if (index < GetTypeValidatorsContainer()->GetCount())
+ return GetTypeValidatorsContainer()->GetAtIndex(index);
+ else
+ return GetRegexTypeValidatorsContainer()->GetAtIndex(index-GetTypeValidatorsContainer()->GetCount());
+}
+
+lldb::TypeNameSpecifierImplSP
+TypeCategoryImpl::GetTypeNameSpecifierForValidatorAtIndex (size_t index)
+{
+ if (index < GetTypeValidatorsContainer()->GetCount())
+ return GetTypeValidatorsContainer()->GetTypeNameSpecifierAtIndex(index);
+ else
+ return GetRegexTypeValidatorsContainer()->GetTypeNameSpecifierAtIndex(index - GetTypeValidatorsContainer()->GetCount());
+}
+
void
TypeCategoryImpl::Enable (bool value, uint32_t position)
{
Mutex::Locker locker(m_mutex);
- m_enabled = value;
- m_enabled_position = position;
+ if ( (m_enabled = value) )
+ m_enabled_position = position;
if (m_change_listener)
m_change_listener->Changed();
}
diff --git a/source/DataFormatters/TypeCategoryMap.cpp b/source/DataFormatters/TypeCategoryMap.cpp
index c6dba1b9f4bd0..ae34d0339011d 100644
--- a/source/DataFormatters/TypeCategoryMap.cpp
+++ b/source/DataFormatters/TypeCategoryMap.cpp
@@ -120,6 +120,46 @@ TypeCategoryMap::Disable (ValueSP category)
}
void
+TypeCategoryMap::EnableAllCategories ()
+{
+ Mutex::Locker locker(m_map_mutex);
+ std::vector<ValueSP> sorted_categories(m_map.size(), ValueSP());
+ MapType::iterator iter = m_map.begin(), end = m_map.end();
+ for (; iter != end; ++iter)
+ {
+ if (iter->second->IsEnabled())
+ continue;
+ auto pos = iter->second->GetLastEnabledPosition();
+ if (pos >= sorted_categories.size())
+ {
+ auto iter = std::find_if(sorted_categories.begin(),
+ sorted_categories.end(),
+ [] (const ValueSP& sp) -> bool {
+ return sp.get() == nullptr;
+ });
+ pos = std::distance(sorted_categories.begin(), iter);
+ }
+ sorted_categories.at(pos) = iter->second;
+ }
+ decltype(sorted_categories)::iterator viter = sorted_categories.begin(), vend = sorted_categories.end();
+ for (; viter != vend; viter++)
+ if (viter->get())
+ Enable(*viter, Last);
+}
+
+void
+TypeCategoryMap::DisableAllCategories ()
+{
+ Mutex::Locker locker(m_map_mutex);
+ Position p = First;
+ for (; false == m_active_categories.empty(); p++)
+ {
+ m_active_categories.front()->SetEnabledPosition(p);
+ Disable(m_active_categories.front());
+ }
+}
+
+void
TypeCategoryMap::Clear ()
{
Mutex::Locker locker(m_map_mutex);
@@ -266,6 +306,34 @@ TypeCategoryMap::GetSyntheticChildren (ValueObject& valobj,
}
#endif
+lldb::TypeValidatorImplSP
+TypeCategoryMap::GetValidator (ValueObject& valobj,
+ lldb::DynamicValueType use_dynamic)
+{
+ Mutex::Locker locker(m_map_mutex);
+
+ uint32_t reason_why;
+ ActiveCategoriesIterator begin, end = m_active_categories.end();
+
+ Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_TYPES));
+
+ FormattersMatchVector matches = FormatManager::GetPossibleMatches(valobj, use_dynamic);
+
+ for (begin = m_active_categories.begin(); begin != end; begin++)
+ {
+ lldb::TypeCategoryImplSP category_sp = *begin;
+ lldb::TypeValidatorImplSP current_format;
+ if (log)
+ log->Printf("\n[CategoryMap::GetValidator] Trying to use category %s", category_sp->GetName());
+ if (!category_sp->Get(valobj, matches, current_format, &reason_why))
+ continue;
+ return current_format;
+ }
+ if (log)
+ log->Printf("[CategoryMap::GetValidator] nothing found - returning empty SP");
+ return lldb::TypeValidatorImplSP();
+}
+
void
TypeCategoryMap::LoopThrough(CallbackType callback, void* param)
{
diff --git a/source/DataFormatters/TypeFormat.cpp b/source/DataFormatters/TypeFormat.cpp
index 0c62daf87bbcd..f07d8127d2b9e 100644
--- a/source/DataFormatters/TypeFormat.cpp
+++ b/source/DataFormatters/TypeFormat.cpp
@@ -59,9 +59,9 @@ TypeFormatImpl_Format::FormatObject (ValueObject *valobj,
{
if (!valobj)
return false;
- if (valobj->GetClangType().IsAggregateType () == false)
+ if (valobj->CanProvideValue())
{
- const Value& value(valobj->GetValue());
+ Value& value(valobj->GetValue());
const Value::ContextType context_type = value.GetContextType();
ExecutionContext exe_ctx (valobj->GetExecutionContextRef());
DataExtractor data;
@@ -92,14 +92,14 @@ TypeFormatImpl_Format::FormatObject (ValueObject *valobj,
}
else
{
- ClangASTType clang_type = valobj->GetClangType ();
+ ClangASTType clang_type = value.GetClangType ();
if (clang_type)
{
// put custom bytes to display in the DataExtractor to override the default value logic
if (GetFormat() == eFormatCString)
{
lldb_private::Flags type_flags(clang_type.GetTypeInfo(NULL)); // disambiguate w.r.t. TypeFormatImpl::Flags
- if (type_flags.Test(ClangASTType::eTypeIsPointer) && !type_flags.Test(ClangASTType::eTypeIsObjC))
+ if (type_flags.Test(eTypeIsPointer) && !type_flags.Test(eTypeIsObjC))
{
// if we are dumping a pointer as a c-string, get the pointee data as a string
TargetSP target_sp(valobj->GetTargetSP());
@@ -180,7 +180,7 @@ TypeFormatImpl_EnumType::FormatObject (ValueObject *valobj,
dest.clear();
if (!valobj)
return false;
- if (valobj->GetClangType().IsAggregateType ())
+ if (!valobj->CanProvideValue())
return false;
ProcessSP process_sp;
TargetSP target_sp;
@@ -209,7 +209,7 @@ TypeFormatImpl_EnumType::FormatObject (ValueObject *valobj,
{
if (!type_sp)
continue;
- if ( (type_sp->GetClangForwardType().GetTypeInfo() & ClangASTType::eTypeIsEnumeration) == ClangASTType::eTypeIsEnumeration)
+ if ( (type_sp->GetClangForwardType().GetTypeInfo() & eTypeIsEnumeration) == eTypeIsEnumeration)
{
valobj_enum_type = type_sp->GetClangFullType();
m_types.emplace(valobj_key,valobj_enum_type);
diff --git a/source/DataFormatters/TypeSummary.cpp b/source/DataFormatters/TypeSummary.cpp
index e5d80174c3ccc..ff089af58cb70 100644
--- a/source/DataFormatters/TypeSummary.cpp
+++ b/source/DataFormatters/TypeSummary.cpp
@@ -34,6 +34,50 @@
using namespace lldb;
using namespace lldb_private;
+TypeSummaryOptions::TypeSummaryOptions () :
+ m_lang(eLanguageTypeUnknown),
+ m_capping(eTypeSummaryCapped)
+{}
+
+TypeSummaryOptions::TypeSummaryOptions (const TypeSummaryOptions& rhs) :
+ m_lang(rhs.m_lang),
+ m_capping(rhs.m_capping)
+{}
+
+TypeSummaryOptions&
+TypeSummaryOptions::operator = (const TypeSummaryOptions& rhs)
+{
+ m_lang = rhs.m_lang;
+ m_capping = rhs.m_capping;
+ return *this;
+}
+
+lldb::LanguageType
+TypeSummaryOptions::GetLanguage () const
+{
+ return m_lang;
+}
+
+lldb::TypeSummaryCapping
+TypeSummaryOptions::GetCapping () const
+{
+ return m_capping;
+}
+
+TypeSummaryOptions&
+TypeSummaryOptions::SetLanguage (lldb::LanguageType lang)
+{
+ m_lang = lang;
+ return *this;
+}
+
+TypeSummaryOptions&
+TypeSummaryOptions::SetCapping (lldb::TypeSummaryCapping cap)
+{
+ m_capping = cap;
+ return *this;
+}
+
TypeSummaryImpl::TypeSummaryImpl (const TypeSummaryImpl::Flags& flags) :
m_flags(flags)
{
@@ -51,7 +95,8 @@ m_format()
bool
StringSummaryFormat::FormatObject (ValueObject *valobj,
- std::string& retval)
+ std::string& retval,
+ const TypeSummaryOptions& options)
{
if (!valobj)
{
@@ -115,11 +160,12 @@ m_description(description ? description : "")
bool
CXXFunctionSummaryFormat::FormatObject (ValueObject *valobj,
- std::string& dest)
+ std::string& dest,
+ const TypeSummaryOptions& options)
{
dest.clear();
StreamString stream;
- if (!m_impl || m_impl(*valobj,stream) == false)
+ if (!m_impl || m_impl(*valobj,stream,options) == false)
return false;
dest.assign(stream.GetData());
return true;
@@ -160,7 +206,8 @@ m_script_function_sp()
bool
ScriptSummaryFormat::FormatObject (ValueObject *valobj,
- std::string& retval)
+ std::string& retval,
+ const TypeSummaryOptions& options)
{
Timer scoped_timer (__PRETTY_FUNCTION__, __PRETTY_FUNCTION__);
@@ -190,6 +237,7 @@ ScriptSummaryFormat::FormatObject (ValueObject *valobj,
return script_interpreter->GetScriptedSummary(m_function_name.c_str(),
valobj->GetSP(),
m_script_function_sp,
+ options,
retval);
}
diff --git a/source/DataFormatters/TypeSynthetic.cpp b/source/DataFormatters/TypeSynthetic.cpp
index 3949673a4be89..13c1c7508b683 100644
--- a/source/DataFormatters/TypeSynthetic.cpp
+++ b/source/DataFormatters/TypeSynthetic.cpp
@@ -23,6 +23,7 @@
#include "lldb/Core/StreamString.h"
#include "lldb/DataFormatters/TypeSynthetic.h"
#include "lldb/Interpreter/CommandInterpreter.h"
+#include "lldb/Interpreter/ScriptInterpreterPython.h"
#include "lldb/Symbol/ClangASTType.h"
#include "lldb/Target/StackFrame.h"
#include "lldb/Target/Target.h"
@@ -30,6 +31,59 @@
using namespace lldb;
using namespace lldb_private;
+void
+TypeFilterImpl::AddExpressionPath (const std::string& path)
+{
+ bool need_add_dot = true;
+ if (path[0] == '.' ||
+ (path[0] == '-' && path[1] == '>') ||
+ path[0] == '[')
+ need_add_dot = false;
+ // add a '.' symbol to help forgetful users
+ if(!need_add_dot)
+ m_expression_paths.push_back(path);
+ else
+ m_expression_paths.push_back(std::string(".") + path);
+}
+
+bool
+TypeFilterImpl::SetExpressionPathAtIndex (size_t i, const std::string& path)
+{
+ if (i >= GetCount())
+ return false;
+ bool need_add_dot = true;
+ if (path[0] == '.' ||
+ (path[0] == '-' && path[1] == '>') ||
+ path[0] == '[')
+ need_add_dot = false;
+ // add a '.' symbol to help forgetful users
+ if(!need_add_dot)
+ m_expression_paths[i] = path;
+ else
+ m_expression_paths[i] = std::string(".") + path;
+ return true;
+}
+
+size_t
+TypeFilterImpl::FrontEnd::GetIndexOfChildWithName (const ConstString &name)
+{
+ const char* name_cstr = name.GetCString();
+ for (size_t i = 0; i < filter->GetCount(); i++)
+ {
+ const char* expr_cstr = filter->GetExpressionPathAtIndex(i);
+ if (expr_cstr)
+ {
+ if (*expr_cstr == '.')
+ expr_cstr++;
+ else if (*expr_cstr == '-' && *(expr_cstr+1) == '>')
+ expr_cstr += 2;
+ }
+ if (!::strcmp(name_cstr, expr_cstr))
+ return i;
+ }
+ return UINT32_MAX;
+}
+
std::string
TypeFilterImpl::GetDescription()
{
@@ -63,6 +117,41 @@ CXXSyntheticChildren::GetDescription()
return sstr.GetString();
}
+lldb::ValueObjectSP
+SyntheticChildrenFrontEnd::CreateValueObjectFromExpression (const char* name,
+ const char* expression,
+ const ExecutionContext& exe_ctx)
+{
+ ValueObjectSP valobj_sp(ValueObject::CreateValueObjectFromExpression(name, expression, exe_ctx));
+ if (valobj_sp)
+ valobj_sp->SetSyntheticChildrenGenerated(true);
+ return valobj_sp;
+}
+
+lldb::ValueObjectSP
+SyntheticChildrenFrontEnd::CreateValueObjectFromAddress (const char* name,
+ uint64_t address,
+ const ExecutionContext& exe_ctx,
+ ClangASTType type)
+{
+ ValueObjectSP valobj_sp(ValueObject::CreateValueObjectFromAddress(name, address, exe_ctx, type));
+ if (valobj_sp)
+ valobj_sp->SetSyntheticChildrenGenerated(true);
+ return valobj_sp;
+}
+
+lldb::ValueObjectSP
+SyntheticChildrenFrontEnd::CreateValueObjectFromData (const char* name,
+ const DataExtractor& data,
+ const ExecutionContext& exe_ctx,
+ ClangASTType type)
+{
+ ValueObjectSP valobj_sp(ValueObject::CreateValueObjectFromData(name, data, exe_ctx, type));
+ if (valobj_sp)
+ valobj_sp->SetSyntheticChildrenGenerated(true);
+ return valobj_sp;
+}
+
#ifndef LLDB_DISABLE_PYTHON
ScriptedSyntheticChildren::FrontEnd::FrontEnd(std::string pclass, ValueObject &backend) :
@@ -98,6 +187,55 @@ ScriptedSyntheticChildren::FrontEnd::GetChildAtIndex (size_t idx)
return m_interpreter->GetChildAtIndex(m_wrapper_sp, idx);
}
+bool
+ScriptedSyntheticChildren::FrontEnd::IsValid ()
+{
+ return m_wrapper_sp.get() != nullptr && m_wrapper_sp->operator bool() && m_interpreter != nullptr;
+}
+
+size_t
+ScriptedSyntheticChildren::FrontEnd::CalculateNumChildren ()
+{
+ if (!m_wrapper_sp || m_interpreter == NULL)
+ return 0;
+ return m_interpreter->CalculateNumChildren(m_wrapper_sp);
+}
+
+bool
+ScriptedSyntheticChildren::FrontEnd::Update ()
+{
+ if (!m_wrapper_sp || m_interpreter == NULL)
+ return false;
+
+ return m_interpreter->UpdateSynthProviderInstance(m_wrapper_sp);
+}
+
+bool
+ScriptedSyntheticChildren::FrontEnd::MightHaveChildren ()
+{
+ if (!m_wrapper_sp || m_interpreter == NULL)
+ return false;
+
+ return m_interpreter->MightHaveChildrenSynthProviderInstance(m_wrapper_sp);
+}
+
+size_t
+ScriptedSyntheticChildren::FrontEnd::GetIndexOfChildWithName (const ConstString &name)
+{
+ if (!m_wrapper_sp || m_interpreter == NULL)
+ return UINT32_MAX;
+ return m_interpreter->GetIndexOfChildWithName(m_wrapper_sp, name.GetCString());
+}
+
+lldb::ValueObjectSP
+ScriptedSyntheticChildren::FrontEnd::GetSyntheticValue ()
+{
+ if (!m_wrapper_sp || m_interpreter == NULL)
+ return nullptr;
+
+ return m_interpreter->GetSyntheticValue(m_wrapper_sp);
+}
+
std::string
ScriptedSyntheticChildren::GetDescription()
{
diff --git a/source/DataFormatters/TypeValidator.cpp b/source/DataFormatters/TypeValidator.cpp
new file mode 100644
index 0000000000000..b5efac8f586a0
--- /dev/null
+++ b/source/DataFormatters/TypeValidator.cpp
@@ -0,0 +1,75 @@
+//===-- TypeValidator.cpp ---------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// C Includes
+
+// C++ Includes
+
+// Other libraries and framework includes
+
+// Project includes
+#include "lldb/DataFormatters/TypeValidator.h"
+#include "lldb/Core/StreamString.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+TypeValidatorImpl::TypeValidatorImpl(const Flags &flags) :
+ m_flags(flags),
+ m_my_revision(0)
+{
+}
+
+TypeValidatorImpl::~TypeValidatorImpl()
+{
+}
+
+TypeValidatorImpl::ValidationResult
+TypeValidatorImpl::Success ()
+{
+ return ValidationResult { TypeValidatorResult::Success, "" };
+}
+
+TypeValidatorImpl::ValidationResult
+TypeValidatorImpl::Failure (std::string message)
+{
+ return ValidationResult { TypeValidatorResult::Failure, message };
+}
+
+TypeValidatorImpl_CXX::TypeValidatorImpl_CXX (ValidatorFunction f, std::string d, const TypeValidatorImpl::Flags& flags) :
+ TypeValidatorImpl(flags),
+ m_description(d),
+ m_validator_function(f)
+{
+}
+
+TypeValidatorImpl_CXX::~TypeValidatorImpl_CXX()
+{
+}
+
+TypeValidatorImpl::ValidationResult
+TypeValidatorImpl_CXX::FormatObject (ValueObject *valobj) const
+{
+ if (!valobj)
+ return Success(); // I guess there's nothing wrong with a null valueobject..
+
+ return m_validator_function(valobj);
+}
+
+std::string
+TypeValidatorImpl_CXX::GetDescription()
+{
+ StreamString sstr;
+ sstr.Printf ("%s%s%s%s",
+ m_description.c_str(),
+ Cascades() ? "" : " (not cascading)",
+ SkipsPointers() ? " (skip pointers)" : "",
+ SkipsReferences() ? " (skip references)" : "");
+ return sstr.GetString();
+}
diff --git a/source/DataFormatters/ValueObjectPrinter.cpp b/source/DataFormatters/ValueObjectPrinter.cpp
index 65e5e3f458238..5560ce2971e7f 100644
--- a/source/DataFormatters/ValueObjectPrinter.cpp
+++ b/source/DataFormatters/ValueObjectPrinter.cpp
@@ -66,11 +66,13 @@ ValueObjectPrinter::Init (ValueObject* valobj,
bool
ValueObjectPrinter::PrintValueObject ()
{
- if (!GetDynamicValueIfNeeded () || m_valobj == nullptr)
+ if (!GetMostSpecializedValue () || m_valobj == nullptr)
return false;
if (ShouldPrintValueObject())
{
+ PrintValidationMarkerIfNeeded();
+
PrintLocationIfNeeded();
m_stream->Indent();
@@ -89,11 +91,13 @@ ValueObjectPrinter::PrintValueObject ()
else
m_stream->EOL();
+ PrintValidationErrorIfNeeded();
+
return true;
}
bool
-ValueObjectPrinter::GetDynamicValueIfNeeded ()
+ValueObjectPrinter::GetMostSpecializedValue ()
{
if (m_valobj)
return true;
@@ -130,6 +134,25 @@ ValueObjectPrinter::GetDynamicValueIfNeeded ()
else
m_valobj = m_orig_valobj;
}
+
+ if (m_valobj->IsSynthetic())
+ {
+ if (options.m_use_synthetic == false)
+ {
+ ValueObject *non_synthetic = m_valobj->GetNonSyntheticValue().get();
+ if (non_synthetic)
+ m_valobj = non_synthetic;
+ }
+ }
+ else
+ {
+ if (options.m_use_synthetic == true)
+ {
+ ValueObject *synthetic = m_valobj->GetSyntheticValue().get();
+ if (synthetic)
+ m_valobj = synthetic;
+ }
+ }
}
m_clang_type = m_valobj->GetClangType();
m_type_flags = m_clang_type.GetTypeInfo ();
@@ -160,7 +183,7 @@ bool
ValueObjectPrinter::ShouldPrintValueObject ()
{
if (m_should_print == eLazyBoolCalculate)
- m_should_print = (options.m_flat_output == false || m_type_flags.Test (ClangASTType::eTypeHasValue)) ? eLazyBoolYes : eLazyBoolNo;
+ m_should_print = (options.m_flat_output == false || m_type_flags.Test (eTypeHasValue)) ? eLazyBoolYes : eLazyBoolNo;
return m_should_print == eLazyBoolYes;
}
@@ -176,7 +199,7 @@ bool
ValueObjectPrinter::IsPtr ()
{
if (m_is_ptr == eLazyBoolCalculate)
- m_is_ptr = m_type_flags.Test (ClangASTType::eTypeIsPointer) ? eLazyBoolYes : eLazyBoolNo;
+ m_is_ptr = m_type_flags.Test (eTypeIsPointer) ? eLazyBoolYes : eLazyBoolNo;
return m_is_ptr == eLazyBoolYes;
}
@@ -184,7 +207,7 @@ bool
ValueObjectPrinter::IsRef ()
{
if (m_is_ref == eLazyBoolCalculate)
- m_is_ref = m_type_flags.Test (ClangASTType::eTypeIsReference) ? eLazyBoolYes : eLazyBoolNo;
+ m_is_ref = m_type_flags.Test (eTypeIsReference) ? eLazyBoolYes : eLazyBoolNo;
return m_is_ref == eLazyBoolYes;
}
@@ -192,7 +215,7 @@ bool
ValueObjectPrinter::IsAggregate ()
{
if (m_is_aggregate == eLazyBoolCalculate)
- m_is_aggregate = m_type_flags.Test (ClangASTType::eTypeHasChildren) ? eLazyBoolYes : eLazyBoolNo;
+ m_is_aggregate = m_type_flags.Test (eTypeHasChildren) ? eLazyBoolYes : eLazyBoolNo;
return m_is_aggregate == eLazyBoolYes;
}
@@ -222,13 +245,13 @@ ValueObjectPrinter::PrintTypeIfNeeded ()
{
// Some ValueObjects don't have types (like registers sets). Only print
// the type if there is one to print
- ConstString qualified_type_name;
- if (options.m_be_raw)
- qualified_type_name = m_valobj->GetQualifiedTypeName();
+ ConstString type_name;
+ if (options.m_use_type_display_name)
+ type_name = m_valobj->GetDisplayTypeName();
else
- qualified_type_name = m_valobj->GetDisplayTypeName();
- if (qualified_type_name)
- m_stream->Printf("(%s) ", qualified_type_name.GetCString());
+ type_name = m_valobj->GetQualifiedTypeName();
+ if (type_name)
+ m_stream->Printf("(%s) ", type_name.GetCString());
else
show_type = false;
}
@@ -438,8 +461,7 @@ ValueObjectPrinter::ShouldPrintChildren (bool is_failed_description,
ValueObject*
ValueObjectPrinter::GetValueObjectForChildrenGeneration ()
{
- ValueObjectSP synth_valobj_sp = m_valobj->GetSyntheticValue (options.m_use_synthetic);
- return (synth_valobj_sp ? synth_valobj_sp.get() : m_valobj);
+ return m_valobj;
}
void
@@ -536,7 +558,13 @@ ValueObjectPrinter::PrintChildren (uint32_t curr_ptr_depth)
{
// Aggregate, no children...
if (ShouldPrintValueObject())
- m_stream->PutCString(" {}\n");
+ {
+ // if it has a synthetic value, then don't print {}, the synthetic children are probably only being used to vend a value
+ if (m_valobj->DoesProvideSyntheticValue())
+ m_stream->PutCString( "\n");
+ else
+ m_stream->PutCString(" {}\n");
+ }
}
else
{
@@ -548,7 +576,7 @@ ValueObjectPrinter::PrintChildren (uint32_t curr_ptr_depth)
bool
ValueObjectPrinter::PrintChildrenOneLiner (bool hide_names)
{
- if (!GetDynamicValueIfNeeded () || m_valobj == nullptr)
+ if (!GetMostSpecializedValue () || m_valobj == nullptr)
return false;
ValueObject* synth_m_valobj = GetValueObjectForChildrenGeneration();
@@ -563,9 +591,8 @@ ValueObjectPrinter::PrintChildrenOneLiner (bool hide_names)
for (uint32_t idx=0; idx<num_children; ++idx)
{
lldb::ValueObjectSP child_sp(synth_m_valobj->GetChildAtIndex(idx, true));
- lldb::ValueObjectSP child_dyn_sp = child_sp.get() ? child_sp->GetDynamicValue(options.m_use_dynamic) : child_sp;
- if (child_dyn_sp)
- child_sp = child_dyn_sp;
+ if (child_sp)
+ child_sp = child_sp->GetQualifiedRepresentationIfAvailable(options.m_use_dynamic, options.m_use_synthetic);
if (child_sp)
{
if (idx)
@@ -604,7 +631,7 @@ ValueObjectPrinter::PrintChildrenIfNeeded (bool value_printed,
uint32_t curr_ptr_depth = m_ptr_depth;
bool print_children = ShouldPrintChildren (is_failed_description,curr_ptr_depth);
- bool print_oneline = (curr_ptr_depth > 0 || options.m_show_types || options.m_be_raw) ? false : DataVisualization::ShouldPrintAsOneLiner(*m_valobj);
+ bool print_oneline = (curr_ptr_depth > 0 || options.m_show_types || !options.m_allow_oneliner_mode) ? false : DataVisualization::ShouldPrintAsOneLiner(*m_valobj);
if (print_children)
{
@@ -624,3 +651,44 @@ ValueObjectPrinter::PrintChildrenIfNeeded (bool value_printed,
else
m_stream->EOL();
}
+
+bool
+ValueObjectPrinter::ShouldPrintValidation ()
+{
+ return options.m_run_validator;
+}
+
+bool
+ValueObjectPrinter::PrintValidationMarkerIfNeeded ()
+{
+ if (!ShouldPrintValidation())
+ return false;
+
+ m_validation = m_valobj->GetValidationStatus();
+
+ if (TypeValidatorResult::Failure == m_validation.first)
+ {
+ m_stream->Printf("! ");
+ return true;
+ }
+
+ return false;
+}
+
+bool
+ValueObjectPrinter::PrintValidationErrorIfNeeded ()
+{
+ if (!ShouldPrintValidation())
+ return false;
+
+ if (TypeValidatorResult::Success == m_validation.first)
+ return false;
+
+ if (m_validation.second.empty())
+ m_validation.second.assign("unknown error");
+
+ m_stream->Printf(" ! validation error: %s", m_validation.second.c_str());
+ m_stream->EOL();
+
+ return true;
+}