1 //===-- CxxStringTypes.cpp --------------------------------------*- C++ -*-===// 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 "lldb/Core/ValueObject.h" 14 #include "lldb/Core/ValueObjectConstResult.h" 15 #include "lldb/DataFormatters/FormattersHelpers.h" 16 #include "lldb/DataFormatters/StringPrinter.h" 17 #include "lldb/DataFormatters/TypeSummary.h" 18 #include "lldb/Host/Time.h" 19 #include "lldb/Symbol/ClangASTContext.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 bool lldb_private::formatters::Char8StringSummaryProvider( 36 ValueObject &valobj, Stream &stream, const TypeSummaryOptions &) { 37 ProcessSP process_sp = valobj.GetProcessSP(); 38 if (!process_sp) 39 return false; 40 41 lldb::addr_t valobj_addr = GetArrayAddressOrPointerValue(valobj); 42 if (valobj_addr == 0 || valobj_addr == LLDB_INVALID_ADDRESS) 43 return false; 44 45 StringPrinter::ReadStringAndDumpToStreamOptions options(valobj); 46 options.SetLocation(valobj_addr); 47 options.SetProcessSP(process_sp); 48 options.SetStream(&stream); 49 options.SetPrefixToken("u8"); 50 51 if (!StringPrinter::ReadStringAndDumpToStream< 52 StringPrinter::StringElementType::UTF8>(options)) { 53 stream.Printf("Summary Unavailable"); 54 return true; 55 } 56 57 return true; 58 } 59 60 bool lldb_private::formatters::Char16StringSummaryProvider( 61 ValueObject &valobj, Stream &stream, const TypeSummaryOptions &) { 62 ProcessSP process_sp = valobj.GetProcessSP(); 63 if (!process_sp) 64 return false; 65 66 lldb::addr_t valobj_addr = GetArrayAddressOrPointerValue(valobj); 67 if (valobj_addr == 0 || valobj_addr == LLDB_INVALID_ADDRESS) 68 return false; 69 70 StringPrinter::ReadStringAndDumpToStreamOptions options(valobj); 71 options.SetLocation(valobj_addr); 72 options.SetProcessSP(process_sp); 73 options.SetStream(&stream); 74 options.SetPrefixToken("u"); 75 76 if (!StringPrinter::ReadStringAndDumpToStream< 77 StringPrinter::StringElementType::UTF16>(options)) { 78 stream.Printf("Summary Unavailable"); 79 return true; 80 } 81 82 return true; 83 } 84 85 bool lldb_private::formatters::Char32StringSummaryProvider( 86 ValueObject &valobj, Stream &stream, const TypeSummaryOptions &) { 87 ProcessSP process_sp = valobj.GetProcessSP(); 88 if (!process_sp) 89 return false; 90 91 lldb::addr_t valobj_addr = GetArrayAddressOrPointerValue(valobj); 92 if (valobj_addr == 0 || valobj_addr == LLDB_INVALID_ADDRESS) 93 return false; 94 95 StringPrinter::ReadStringAndDumpToStreamOptions options(valobj); 96 options.SetLocation(valobj_addr); 97 options.SetProcessSP(process_sp); 98 options.SetStream(&stream); 99 options.SetPrefixToken("U"); 100 101 if (!StringPrinter::ReadStringAndDumpToStream< 102 StringPrinter::StringElementType::UTF32>(options)) { 103 stream.Printf("Summary Unavailable"); 104 return true; 105 } 106 107 return true; 108 } 109 110 bool lldb_private::formatters::WCharStringSummaryProvider( 111 ValueObject &valobj, Stream &stream, const TypeSummaryOptions &) { 112 ProcessSP process_sp = valobj.GetProcessSP(); 113 if (!process_sp) 114 return false; 115 116 lldb::addr_t valobj_addr = GetArrayAddressOrPointerValue(valobj); 117 if (valobj_addr == 0 || valobj_addr == LLDB_INVALID_ADDRESS) 118 return false; 119 120 // Get a wchar_t basic type from the current type system 121 CompilerType wchar_compiler_type = 122 valobj.GetCompilerType().GetBasicTypeFromAST(lldb::eBasicTypeWChar); 123 124 if (!wchar_compiler_type) 125 return false; 126 127 // Safe to pass nullptr for exe_scope here. 128 llvm::Optional<uint64_t> size = wchar_compiler_type.GetBitSize(nullptr); 129 if (!size) 130 return false; 131 const uint32_t wchar_size = *size; 132 133 StringPrinter::ReadStringAndDumpToStreamOptions options(valobj); 134 options.SetLocation(valobj_addr); 135 options.SetProcessSP(process_sp); 136 options.SetStream(&stream); 137 options.SetPrefixToken("L"); 138 139 switch (wchar_size) { 140 case 8: 141 return StringPrinter::ReadStringAndDumpToStream< 142 StringPrinter::StringElementType::UTF8>(options); 143 case 16: 144 return StringPrinter::ReadStringAndDumpToStream< 145 StringPrinter::StringElementType::UTF16>(options); 146 case 32: 147 return StringPrinter::ReadStringAndDumpToStream< 148 StringPrinter::StringElementType::UTF32>(options); 149 default: 150 stream.Printf("size for wchar_t is not valid"); 151 return true; 152 } 153 return true; 154 } 155 156 bool lldb_private::formatters::Char8SummaryProvider( 157 ValueObject &valobj, Stream &stream, const TypeSummaryOptions &) { 158 DataExtractor data; 159 Status error; 160 valobj.GetData(data, error); 161 162 if (error.Fail()) 163 return false; 164 165 std::string value; 166 valobj.GetValueAsCString(lldb::eFormatUnicode8, value); 167 if (!value.empty()) 168 stream.Printf("%s ", value.c_str()); 169 170 StringPrinter::ReadBufferAndDumpToStreamOptions options(valobj); 171 options.SetData(data); 172 options.SetStream(&stream); 173 options.SetPrefixToken("u8"); 174 options.SetQuote('\''); 175 options.SetSourceSize(1); 176 options.SetBinaryZeroIsTerminator(false); 177 178 return StringPrinter::ReadBufferAndDumpToStream< 179 StringPrinter::StringElementType::UTF8>(options); 180 } 181 182 bool lldb_private::formatters::Char16SummaryProvider( 183 ValueObject &valobj, Stream &stream, const TypeSummaryOptions &) { 184 DataExtractor data; 185 Status error; 186 valobj.GetData(data, error); 187 188 if (error.Fail()) 189 return false; 190 191 std::string value; 192 valobj.GetValueAsCString(lldb::eFormatUnicode16, value); 193 if (!value.empty()) 194 stream.Printf("%s ", value.c_str()); 195 196 StringPrinter::ReadBufferAndDumpToStreamOptions options(valobj); 197 options.SetData(data); 198 options.SetStream(&stream); 199 options.SetPrefixToken("u"); 200 options.SetQuote('\''); 201 options.SetSourceSize(1); 202 options.SetBinaryZeroIsTerminator(false); 203 204 return StringPrinter::ReadBufferAndDumpToStream< 205 StringPrinter::StringElementType::UTF16>(options); 206 } 207 208 bool lldb_private::formatters::Char32SummaryProvider( 209 ValueObject &valobj, Stream &stream, const TypeSummaryOptions &) { 210 DataExtractor data; 211 Status error; 212 valobj.GetData(data, error); 213 214 if (error.Fail()) 215 return false; 216 217 std::string value; 218 valobj.GetValueAsCString(lldb::eFormatUnicode32, value); 219 if (!value.empty()) 220 stream.Printf("%s ", value.c_str()); 221 222 StringPrinter::ReadBufferAndDumpToStreamOptions options(valobj); 223 options.SetData(data); 224 options.SetStream(&stream); 225 options.SetPrefixToken("U"); 226 options.SetQuote('\''); 227 options.SetSourceSize(1); 228 options.SetBinaryZeroIsTerminator(false); 229 230 return StringPrinter::ReadBufferAndDumpToStream< 231 StringPrinter::StringElementType::UTF32>(options); 232 } 233 234 bool lldb_private::formatters::WCharSummaryProvider( 235 ValueObject &valobj, Stream &stream, const TypeSummaryOptions &) { 236 DataExtractor data; 237 Status error; 238 valobj.GetData(data, error); 239 240 if (error.Fail()) 241 return false; 242 243 // Get a wchar_t basic type from the current type system 244 CompilerType wchar_compiler_type = 245 valobj.GetCompilerType().GetBasicTypeFromAST(lldb::eBasicTypeWChar); 246 247 if (!wchar_compiler_type) 248 return false; 249 250 // Safe to pass nullptr for exe_scope here. 251 llvm::Optional<uint64_t> size = wchar_compiler_type.GetBitSize(nullptr); 252 if (!size) 253 return false; 254 const uint32_t wchar_size = *size; 255 256 StringPrinter::ReadBufferAndDumpToStreamOptions options(valobj); 257 options.SetData(data); 258 options.SetStream(&stream); 259 options.SetPrefixToken("L"); 260 options.SetQuote('\''); 261 options.SetSourceSize(1); 262 options.SetBinaryZeroIsTerminator(false); 263 264 switch (wchar_size) { 265 case 8: 266 return StringPrinter::ReadBufferAndDumpToStream< 267 StringPrinter::StringElementType::UTF8>(options); 268 case 16: 269 return StringPrinter::ReadBufferAndDumpToStream< 270 StringPrinter::StringElementType::UTF16>(options); 271 case 32: 272 return StringPrinter::ReadBufferAndDumpToStream< 273 StringPrinter::StringElementType::UTF32>(options); 274 default: 275 stream.Printf("size for wchar_t is not valid"); 276 return true; 277 } 278 return true; 279 } 280