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