1 //===-- CxxStringTypes.cpp ------------------------------------------------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #include "CxxStringTypes.h" 10 11 #include "llvm/Support/ConvertUTF.h" 12 13 #include "Plugins/TypeSystem/Clang/TypeSystemClang.h" 14 #include "lldb/Core/ValueObject.h" 15 #include "lldb/Core/ValueObjectConstResult.h" 16 #include "lldb/DataFormatters/FormattersHelpers.h" 17 #include "lldb/DataFormatters/StringPrinter.h" 18 #include "lldb/DataFormatters/TypeSummary.h" 19 #include "lldb/Host/Time.h" 20 #include "lldb/Target/ProcessStructReader.h" 21 #include "lldb/Target/SectionLoadList.h" 22 #include "lldb/Target/Target.h" 23 #include "lldb/Target/Thread.h" 24 #include "lldb/Utility/DataBufferHeap.h" 25 #include "lldb/Utility/Endian.h" 26 #include "lldb/Utility/Status.h" 27 #include "lldb/Utility/Stream.h" 28 29 #include <algorithm> 30 31 using namespace lldb; 32 using namespace lldb_private; 33 using namespace lldb_private::formatters; 34 35 using StringElementType = StringPrinter::StringElementType; 36 37 static constexpr std::pair<const char *, Format> 38 getElementTraits(StringElementType ElemType) { 39 switch (ElemType) { 40 case StringElementType::UTF8: 41 return std::make_pair("u8", lldb::eFormatUnicode8); 42 case StringElementType::UTF16: 43 return std::make_pair("u", lldb::eFormatUnicode16); 44 case StringElementType::UTF32: 45 return std::make_pair("U", lldb::eFormatUnicode32); 46 default: 47 return std::make_pair(nullptr, lldb::eFormatInvalid); 48 } 49 } 50 51 template <StringElementType ElemType> 52 static bool CharStringSummaryProvider(ValueObject &valobj, Stream &stream) { 53 Address valobj_addr = GetArrayAddressOrPointerValue(valobj); 54 if (!valobj_addr.IsValid()) 55 return false; 56 57 StringPrinter::ReadStringAndDumpToStreamOptions options(valobj); 58 options.SetLocation(valobj_addr); 59 options.SetTargetSP(valobj.GetTargetSP()); 60 options.SetStream(&stream); 61 options.SetPrefixToken(getElementTraits(ElemType).first); 62 63 if (!StringPrinter::ReadStringAndDumpToStream<ElemType>(options)) 64 stream.Printf("Summary Unavailable"); 65 66 return true; 67 } 68 69 template <StringElementType ElemType> 70 static bool CharSummaryProvider(ValueObject &valobj, Stream &stream) { 71 DataExtractor data; 72 Status error; 73 valobj.GetData(data, error); 74 75 if (error.Fail()) 76 return false; 77 78 std::string value; 79 StringPrinter::ReadBufferAndDumpToStreamOptions options(valobj); 80 81 constexpr auto ElemTraits = getElementTraits(ElemType); 82 valobj.GetValueAsCString(ElemTraits.second, value); 83 84 if (!value.empty()) 85 stream.Printf("%s ", value.c_str()); 86 87 options.SetData(std::move(data)); 88 options.SetStream(&stream); 89 options.SetPrefixToken(ElemTraits.first); 90 options.SetQuote('\''); 91 options.SetSourceSize(1); 92 options.SetBinaryZeroIsTerminator(false); 93 94 return StringPrinter::ReadBufferAndDumpToStream<ElemType>(options); 95 } 96 97 bool lldb_private::formatters::Char8StringSummaryProvider( 98 ValueObject &valobj, Stream &stream, const TypeSummaryOptions &) { 99 return CharStringSummaryProvider<StringElementType::UTF8>(valobj, stream); 100 } 101 102 bool lldb_private::formatters::Char16StringSummaryProvider( 103 ValueObject &valobj, Stream &stream, const TypeSummaryOptions &) { 104 return CharStringSummaryProvider<StringElementType::UTF16>(valobj, stream); 105 } 106 107 bool lldb_private::formatters::Char32StringSummaryProvider( 108 ValueObject &valobj, Stream &stream, const TypeSummaryOptions &) { 109 return CharStringSummaryProvider<StringElementType::UTF32>(valobj, stream); 110 } 111 112 bool lldb_private::formatters::WCharStringSummaryProvider( 113 ValueObject &valobj, Stream &stream, const TypeSummaryOptions &) { 114 Address valobj_addr = GetArrayAddressOrPointerValue(valobj); 115 if (!valobj_addr.IsValid()) 116 return false; 117 118 // Get a wchar_t basic type from the current type system 119 CompilerType wchar_compiler_type = 120 valobj.GetCompilerType().GetBasicTypeFromAST(lldb::eBasicTypeWChar); 121 122 if (!wchar_compiler_type) 123 return false; 124 125 // Safe to pass nullptr for exe_scope here. 126 llvm::Optional<uint64_t> size = wchar_compiler_type.GetBitSize(nullptr); 127 if (!size) 128 return false; 129 const uint32_t wchar_size = *size; 130 131 StringPrinter::ReadStringAndDumpToStreamOptions options(valobj); 132 options.SetLocation(valobj_addr); 133 options.SetTargetSP(valobj.GetTargetSP()); 134 options.SetStream(&stream); 135 options.SetPrefixToken("L"); 136 137 switch (wchar_size) { 138 case 8: 139 return StringPrinter::ReadStringAndDumpToStream<StringElementType::UTF8>( 140 options); 141 case 16: 142 return StringPrinter::ReadStringAndDumpToStream<StringElementType::UTF16>( 143 options); 144 case 32: 145 return StringPrinter::ReadStringAndDumpToStream<StringElementType::UTF32>( 146 options); 147 default: 148 stream.Printf("size for wchar_t is not valid"); 149 return true; 150 } 151 return true; 152 } 153 154 bool lldb_private::formatters::Char8SummaryProvider( 155 ValueObject &valobj, Stream &stream, const TypeSummaryOptions &) { 156 return CharSummaryProvider<StringElementType::UTF8>(valobj, stream); 157 } 158 159 bool lldb_private::formatters::Char16SummaryProvider( 160 ValueObject &valobj, Stream &stream, const TypeSummaryOptions &) { 161 return CharSummaryProvider<StringElementType::UTF16>(valobj, stream); 162 } 163 164 bool lldb_private::formatters::Char32SummaryProvider( 165 ValueObject &valobj, Stream &stream, const TypeSummaryOptions &) { 166 return CharSummaryProvider<StringElementType::UTF32>(valobj, stream); 167 } 168 169 bool lldb_private::formatters::WCharSummaryProvider( 170 ValueObject &valobj, Stream &stream, const TypeSummaryOptions &) { 171 DataExtractor data; 172 Status error; 173 valobj.GetData(data, error); 174 175 if (error.Fail()) 176 return false; 177 178 // Get a wchar_t basic type from the current type system 179 CompilerType wchar_compiler_type = 180 valobj.GetCompilerType().GetBasicTypeFromAST(lldb::eBasicTypeWChar); 181 182 if (!wchar_compiler_type) 183 return false; 184 185 // Safe to pass nullptr for exe_scope here. 186 llvm::Optional<uint64_t> size = wchar_compiler_type.GetBitSize(nullptr); 187 if (!size) 188 return false; 189 const uint32_t wchar_size = *size; 190 191 StringPrinter::ReadBufferAndDumpToStreamOptions options(valobj); 192 options.SetData(std::move(data)); 193 options.SetStream(&stream); 194 options.SetPrefixToken("L"); 195 options.SetQuote('\''); 196 options.SetSourceSize(1); 197 options.SetBinaryZeroIsTerminator(false); 198 199 switch (wchar_size) { 200 case 8: 201 return StringPrinter::ReadBufferAndDumpToStream<StringElementType::UTF8>( 202 options); 203 case 16: 204 return StringPrinter::ReadBufferAndDumpToStream<StringElementType::UTF16>( 205 options); 206 case 32: 207 return StringPrinter::ReadBufferAndDumpToStream<StringElementType::UTF32>( 208 options); 209 default: 210 stream.Printf("size for wchar_t is not valid"); 211 return true; 212 } 213 return true; 214 } 215