| //===-- CxxStringTypes.cpp ------------------------------------------------===// |
| // |
| // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
| // See https://llvm.org/LICENSE.txt for license information. |
| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
| // |
| //===----------------------------------------------------------------------===// |
| |
| #include "CxxStringTypes.h" |
| |
| #include "llvm/Support/ConvertUTF.h" |
| |
| #include "Plugins/TypeSystem/Clang/TypeSystemClang.h" |
| #include "lldb/Core/ValueObject.h" |
| #include "lldb/Core/ValueObjectConstResult.h" |
| #include "lldb/DataFormatters/FormattersHelpers.h" |
| #include "lldb/DataFormatters/StringPrinter.h" |
| #include "lldb/DataFormatters/TypeSummary.h" |
| #include "lldb/Host/Time.h" |
| #include "lldb/Target/ProcessStructReader.h" |
| #include "lldb/Target/SectionLoadList.h" |
| #include "lldb/Target/Target.h" |
| #include "lldb/Target/Thread.h" |
| #include "lldb/Utility/DataBufferHeap.h" |
| #include "lldb/Utility/Endian.h" |
| #include "lldb/Utility/Status.h" |
| #include "lldb/Utility/Stream.h" |
| |
| #include <algorithm> |
| |
| using namespace lldb; |
| using namespace lldb_private; |
| using namespace lldb_private::formatters; |
| |
| using StringElementType = StringPrinter::StringElementType; |
| |
| static constexpr std::pair<const char *, Format> |
| getElementTraits(StringElementType ElemType) { |
| switch (ElemType) { |
| case StringElementType::UTF8: |
| return std::make_pair("u8", lldb::eFormatUnicode8); |
| case StringElementType::UTF16: |
| return std::make_pair("u", lldb::eFormatUnicode16); |
| case StringElementType::UTF32: |
| return std::make_pair("U", lldb::eFormatUnicode32); |
| default: |
| return std::make_pair(nullptr, lldb::eFormatInvalid); |
| } |
| } |
| |
| template <StringElementType ElemType> |
| static bool CharStringSummaryProvider(ValueObject &valobj, Stream &stream) { |
| Address valobj_addr = GetArrayAddressOrPointerValue(valobj); |
| if (!valobj_addr.IsValid()) |
| return false; |
| |
| StringPrinter::ReadStringAndDumpToStreamOptions options(valobj); |
| options.SetLocation(valobj_addr); |
| options.SetTargetSP(valobj.GetTargetSP()); |
| options.SetStream(&stream); |
| options.SetPrefixToken(getElementTraits(ElemType).first); |
| |
| if (!StringPrinter::ReadStringAndDumpToStream<ElemType>(options)) |
| stream.Printf("Summary Unavailable"); |
| |
| return true; |
| } |
| |
| template <StringElementType ElemType> |
| static bool CharSummaryProvider(ValueObject &valobj, Stream &stream) { |
| DataExtractor data; |
| Status error; |
| valobj.GetData(data, error); |
| |
| if (error.Fail()) |
| return false; |
| |
| std::string value; |
| StringPrinter::ReadBufferAndDumpToStreamOptions options(valobj); |
| |
| constexpr auto ElemTraits = getElementTraits(ElemType); |
| valobj.GetValueAsCString(ElemTraits.second, value); |
| |
| if (!value.empty()) |
| stream.Printf("%s ", value.c_str()); |
| |
| options.SetData(std::move(data)); |
| options.SetStream(&stream); |
| options.SetPrefixToken(ElemTraits.first); |
| options.SetQuote('\''); |
| options.SetSourceSize(1); |
| options.SetBinaryZeroIsTerminator(false); |
| |
| return StringPrinter::ReadBufferAndDumpToStream<ElemType>(options); |
| } |
| |
| bool lldb_private::formatters::Char8StringSummaryProvider( |
| ValueObject &valobj, Stream &stream, const TypeSummaryOptions &) { |
| return CharStringSummaryProvider<StringElementType::UTF8>(valobj, stream); |
| } |
| |
| bool lldb_private::formatters::Char16StringSummaryProvider( |
| ValueObject &valobj, Stream &stream, const TypeSummaryOptions &) { |
| return CharStringSummaryProvider<StringElementType::UTF16>(valobj, stream); |
| } |
| |
| bool lldb_private::formatters::Char32StringSummaryProvider( |
| ValueObject &valobj, Stream &stream, const TypeSummaryOptions &) { |
| return CharStringSummaryProvider<StringElementType::UTF32>(valobj, stream); |
| } |
| |
| bool lldb_private::formatters::WCharStringSummaryProvider( |
| ValueObject &valobj, Stream &stream, const TypeSummaryOptions &) { |
| Address valobj_addr = GetArrayAddressOrPointerValue(valobj); |
| if (!valobj_addr.IsValid()) |
| return false; |
| |
| // Get a wchar_t basic type from the current type system |
| CompilerType wchar_compiler_type = |
| valobj.GetCompilerType().GetBasicTypeFromAST(lldb::eBasicTypeWChar); |
| |
| if (!wchar_compiler_type) |
| return false; |
| |
| // Safe to pass nullptr for exe_scope here. |
| llvm::Optional<uint64_t> size = wchar_compiler_type.GetBitSize(nullptr); |
| if (!size) |
| return false; |
| const uint32_t wchar_size = *size; |
| |
| StringPrinter::ReadStringAndDumpToStreamOptions options(valobj); |
| options.SetLocation(valobj_addr); |
| options.SetTargetSP(valobj.GetTargetSP()); |
| options.SetStream(&stream); |
| options.SetPrefixToken("L"); |
| |
| switch (wchar_size) { |
| case 8: |
| return StringPrinter::ReadStringAndDumpToStream<StringElementType::UTF8>( |
| options); |
| case 16: |
| return StringPrinter::ReadStringAndDumpToStream<StringElementType::UTF16>( |
| options); |
| case 32: |
| return StringPrinter::ReadStringAndDumpToStream<StringElementType::UTF32>( |
| options); |
| default: |
| stream.Printf("size for wchar_t is not valid"); |
| return true; |
| } |
| return true; |
| } |
| |
| bool lldb_private::formatters::Char8SummaryProvider( |
| ValueObject &valobj, Stream &stream, const TypeSummaryOptions &) { |
| return CharSummaryProvider<StringElementType::UTF8>(valobj, stream); |
| } |
| |
| bool lldb_private::formatters::Char16SummaryProvider( |
| ValueObject &valobj, Stream &stream, const TypeSummaryOptions &) { |
| return CharSummaryProvider<StringElementType::UTF16>(valobj, stream); |
| } |
| |
| bool lldb_private::formatters::Char32SummaryProvider( |
| ValueObject &valobj, Stream &stream, const TypeSummaryOptions &) { |
| return CharSummaryProvider<StringElementType::UTF32>(valobj, stream); |
| } |
| |
| bool lldb_private::formatters::WCharSummaryProvider( |
| ValueObject &valobj, Stream &stream, const TypeSummaryOptions &) { |
| DataExtractor data; |
| Status error; |
| valobj.GetData(data, error); |
| |
| if (error.Fail()) |
| return false; |
| |
| // Get a wchar_t basic type from the current type system |
| CompilerType wchar_compiler_type = |
| valobj.GetCompilerType().GetBasicTypeFromAST(lldb::eBasicTypeWChar); |
| |
| if (!wchar_compiler_type) |
| return false; |
| |
| // Safe to pass nullptr for exe_scope here. |
| llvm::Optional<uint64_t> size = wchar_compiler_type.GetBitSize(nullptr); |
| if (!size) |
| return false; |
| const uint32_t wchar_size = *size; |
| |
| StringPrinter::ReadBufferAndDumpToStreamOptions options(valobj); |
| options.SetData(std::move(data)); |
| options.SetStream(&stream); |
| options.SetPrefixToken("L"); |
| options.SetQuote('\''); |
| options.SetSourceSize(1); |
| options.SetBinaryZeroIsTerminator(false); |
| |
| switch (wchar_size) { |
| case 8: |
| return StringPrinter::ReadBufferAndDumpToStream<StringElementType::UTF8>( |
| options); |
| case 16: |
| return StringPrinter::ReadBufferAndDumpToStream<StringElementType::UTF16>( |
| options); |
| case 32: |
| return StringPrinter::ReadBufferAndDumpToStream<StringElementType::UTF32>( |
| options); |
| default: |
| stream.Printf("size for wchar_t is not valid"); |
| return true; |
| } |
| return true; |
| } |